bolt3

Lightning transaction and script formats, per BOLT #3 (docs.ppad.tech/bolt3).
git clone git://git.ppad.tech/bolt3.git
Log | Files | Refs | README | LICENSE

commit e66edc606bc7553d01e20b847195527142024ecf
parent 523aa8b203c356019e543a4e01bba28450d35020
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat, 10 Oct 2026 13:10:43 +0400

test: use ppad-base16 for hex decoding

Replaces the base16-bytestring test dependency with ppad-base16 and
makes the hex helper total: it now runs in IO and fails the test via
assertFailure on an invalid literal, instead of calling error.

Diffstat:
Mppad-bolt3.cabal | 2+-
Mtest/Main.hs | 143+++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 72 insertions(+), 73 deletions(-)

diff --git a/ppad-bolt3.cabal b/ppad-bolt3.cabal @@ -53,8 +53,8 @@ test-suite bolt3-tests build-depends: base - , base16-bytestring , bytestring + , ppad-base16 , ppad-bolt3 , ppad-secp256k1 >= 0.5.4 && < 0.6 , QuickCheck diff --git a/test/Main.hs b/test/Main.hs @@ -49,45 +49,45 @@ main = defaultMain $ testGroup "ppad-bolt3" [ ] ] --- hex decoding helper -hex :: BS.ByteString -> BS.ByteString +-- | Decode a hex literal, failing the enclosing test on bad input. +hex :: BS.ByteString -> IO BS.ByteString hex h = case B16.decode h of - Right bs -> bs - Left _ -> error "invalid hex" + Just bs -> pure bs + Nothing -> assertFailure ("invalid hex literal: " ++ show h) -- Key derivation test vectors from Appendix E --------------------------------- keyDerivationTests :: TestTree keyDerivationTests = testGroup "BOLT #3 Appendix E" [ testCase "derive_pubkey" $ do - let basepoint = Point $ hex - "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" - perCommitmentPoint = PerCommitmentPoint $ Point $ hex - "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" - expected = hex - "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" + basepoint <- Point <$> hex + "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" + perCommitmentPoint <- PerCommitmentPoint . Point <$> hex + "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" + expected <- hex + "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" case derive_pubkey basepoint perCommitmentPoint of Nothing -> assertFailure "derive_pubkey returned Nothing" Just (Pubkey pk) -> pk @?= expected , testCase "derive_pubkey' matches vector" $ do - let basepoint = Point $ hex - "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" - perCommitmentPoint = PerCommitmentPoint $ Point $ hex - "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" - expected = hex - "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" + basepoint <- Point <$> hex + "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" + perCommitmentPoint <- PerCommitmentPoint . Point <$> hex + "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" + expected <- hex + "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" case derive_pubkey' tex basepoint perCommitmentPoint of Nothing -> assertFailure "derive_pubkey' returned Nothing" Just (Pubkey pk) -> pk @?= expected , testCase "derive_revocationpubkey" $ do - let revocationBasepoint = RevocationBasepoint $ Point $ hex - "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" - perCommitmentPoint = PerCommitmentPoint $ Point $ hex - "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" - expected = hex - "02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0" + revocationBasepoint <- RevocationBasepoint . Point <$> hex + "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" + perCommitmentPoint <- PerCommitmentPoint . Point <$> hex + "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" + expected <- hex + "02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0" case derive_revocationpubkey revocationBasepoint perCommitmentPoint of Nothing -> assertFailure "derive_revocationpubkey returned Nothing" Just (RevocationPubkey (Pubkey pk)) -> pk @?= expected @@ -98,43 +98,43 @@ keyDerivationTests = testGroup "BOLT #3 Appendix E" [ secretGenerationTests :: TestTree secretGenerationTests = testGroup "BOLT #3 Appendix D - Generation" [ testCase "generate_from_seed 0 final node" $ do - let seed = hex - "0000000000000000000000000000000000000000000000000000000000000000" - i = 281474976710655 - expected = hex - "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148" + seed <- hex + "0000000000000000000000000000000000000000000000000000000000000000" + expected <- hex + "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148" + let i = 281474976710655 generate_from_seed seed i @?= expected , testCase "generate_from_seed FF final node" $ do - let seed = hex - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - i = 281474976710655 - expected = hex - "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc" + seed <- hex + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + expected <- hex + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc" + let i = 281474976710655 generate_from_seed seed i @?= expected , testCase "generate_from_seed FF alternate bits 1" $ do - let seed = hex - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - i = 0xaaaaaaaaaaa - expected = hex - "56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528" + seed <- hex + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + expected <- hex + "56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528" + let i = 0xaaaaaaaaaaa generate_from_seed seed i @?= expected , testCase "generate_from_seed FF alternate bits 2" $ do - let seed = hex - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - i = 0x555555555555 - expected = hex - "9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31" + seed <- hex + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + expected <- hex + "9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31" + let i = 0x555555555555 generate_from_seed seed i @?= expected , testCase "generate_from_seed 01 last nontrivial node" $ do - let seed = hex - "0101010101010101010101010101010101010101010101010101010101010101" - i = 1 - expected = hex - "915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c" + seed <- hex + "0101010101010101010101010101010101010101010101010101010101010101" + expected <- hex + "915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c" + let i = 1 generate_from_seed seed i @?= expected ] @@ -143,24 +143,24 @@ secretGenerationTests = testGroup "BOLT #3 Appendix D - Generation" [ secretStorageTests :: TestTree secretStorageTests = testGroup "BOLT #3 Appendix D - Storage" [ testCase "insert_secret correct sequence" $ do - let secrets = [ - (281474976710655, hex - "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc") - , (281474976710654, hex - "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964") - , (281474976710653, hex - "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8") - , (281474976710652, hex - "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116") - , (281474976710651, hex - "c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd") - , (281474976710650, hex - "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2") - , (281474976710649, hex - "a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32") - , (281474976710648, hex - "05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17") - ] + secrets <- traverse (\(i, s) -> (,) i <$> hex s) [ + (281474976710655, + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc") + , (281474976710654, + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964") + , (281474976710653, + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8") + , (281474976710652, + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116") + , (281474976710651, + "c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd") + , (281474976710650, + "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2") + , (281474976710649, + "a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32") + , (281474976710648, + "05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17") + ] let insertAll store [] = Just store insertAll store ((idx, secret):rest) = case insert_secret secret idx store of @@ -172,15 +172,14 @@ secretStorageTests = testGroup "BOLT #3 Appendix D - Storage" [ , testCase "insert_secret #1 incorrect" $ do -- First secret is from wrong seed, second should fail - let store0 = empty_store - case insert_secret (hex - "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148") - 281474976710655 store0 of + s0 <- hex + "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148" + s1 <- hex + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964" + case insert_secret s0 281474976710655 empty_store of Nothing -> assertFailure "First insert should succeed" Just store1 -> - case insert_secret (hex - "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964") - 281474976710654 store1 of + case insert_secret s1 281474976710654 store1 of Nothing -> return () -- Expected to fail Just _ -> assertFailure "Second insert should fail" ]