bolt3

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

commit 5c8e6411ce97624b46951a5c74d0383f67152b30
parent d8dbc23a79dc8ce18a3ad1eb78d69b53d935b7b0
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun, 25 Jan 2026 11:11:19 +0400

Fix Keys module to use correct ppad-secp256k1 API

- parse_seckey -> parse_int256 (parse bytes as scalar)
- derive_pubkey -> derive_pub (scalar * G)
- add_point -> add (point addition, non-Maybe return)
- mul_point -> mul (point * scalar)
- Remove unused imports and variables to eliminate warnings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Diffstat:
Mflake.lock | 299++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mlib/Lightning/Protocol/BOLT3/Keys.hs | 37++++++++++++++++++-------------------
2 files changed, 314 insertions(+), 22 deletions(-)

diff --git a/flake.lock b/flake.lock @@ -54,6 +54,24 @@ "type": "github" } }, + "flake-utils_4": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1766840161, @@ -102,6 +120,22 @@ "type": "github" } }, + "nixpkgs_4": { + "locked": { + "lastModified": 1766840161, + "narHash": "sha256-Ss/LHpJJsng8vz1Pe33RSGIWUOcqM1fjrehjUkdrWio=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3edc4a30ed3903fdf6f90c837f961fa6b49582d1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "ppad-base16": { "inputs": { "flake-utils": [ @@ -139,6 +173,40 @@ "ppad-base16_2": { "inputs": { "flake-utils": [ + "ppad-secp256k1", + "ppad-base16", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-base16", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1766934151, + "narHash": "sha256-BUFpuLfrGXE2xi3Wa9TYCEhhRhFp175Ghxnr0JRbG2I=", + "ref": "master", + "rev": "58dfb7922401a60d5de76825fcd5f6ecbcd7afe0", + "revCount": 26, + "type": "git", + "url": "git://git.ppad.tech/base16.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/base16.git" + } + }, + "ppad-base16_3": { + "inputs": { + "flake-utils": [ "ppad-sha256", "ppad-base16", "ppad-nixpkgs", @@ -170,6 +238,85 @@ "url": "git://git.ppad.tech/base16.git" } }, + "ppad-fixed": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-fixed", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-fixed", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1767278248, + "narHash": "sha256-ynF6Tyew83dDr3dFWdTdgK3N5WEkLSCQ/uHHTxb5J1s=", + "ref": "master", + "rev": "ae6f5d732d69e6e2bb70ea9da18e2a8060ca9aeb", + "revCount": 290, + "type": "git", + "url": "git://git.ppad.tech/fixed.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/fixed.git" + } + }, + "ppad-hmac-drbg": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-hmac-drbg", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-hmac-drbg", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": [ + "ppad-secp256k1", + "ppad-base16" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ], + "ppad-sha256": [ + "ppad-secp256k1", + "ppad-sha256" + ], + "ppad-sha512": [ + "ppad-secp256k1", + "ppad-sha512" + ] + }, + "locked": { + "lastModified": 1768057958, + "narHash": "sha256-Csrv+J0WnGankFhvEMQsHnLd3h8zVpmTKV5WaHD5LoM=", + "owner": "ppad-tech", + "repo": "hmac-drbg", + "rev": "c6487458ef620c4f83bdbc7494f5f48c989133b6", + "type": "github" + }, + "original": { + "owner": "ppad-tech", + "repo": "hmac-drbg", + "type": "github" + } + }, "ppad-nixpkgs": { "inputs": { "flake-utils": "flake-utils", @@ -230,6 +377,26 @@ "url": "git://git.ppad.tech/nixpkgs.git" } }, + "ppad-nixpkgs_4": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1766932084, + "narHash": "sha256-GvVsbTfW+B7IQ9K/QP2xcXJAm1lhBin1jYZWNjOzT+o=", + "ref": "master", + "rev": "353e61763b959b960a55321a85423501e3e9ed7a", + "revCount": 2, + "type": "git", + "url": "git://git.ppad.tech/nixpkgs.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/nixpkgs.git" + } + }, "ppad-ripemd160": { "inputs": { "flake-utils": [ @@ -260,20 +427,92 @@ "url": "git://git.ppad.tech/ripemd160.git" } }, + "ppad-secp256k1": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": "ppad-base16_2", + "ppad-fixed": "ppad-fixed", + "ppad-hmac-drbg": "ppad-hmac-drbg", + "ppad-nixpkgs": "ppad-nixpkgs_3", + "ppad-sha256": "ppad-sha256", + "ppad-sha512": "ppad-sha512" + }, + "locked": { + "lastModified": 1768069596, + "narHash": "sha256-S98vYYeuLkLLfUozc/YraIEBX4uWrIS5V14hkN2xyk0=", + "ref": "master", + "rev": "ee40b39f69f79e77ce50ca9be31e0e4679839b8a", + "revCount": 243, + "type": "git", + "url": "git://git.ppad.tech/secp256k1.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/secp256k1.git" + } + }, "ppad-sha256": { "inputs": { "flake-utils": [ + "ppad-secp256k1", "ppad-sha256", "ppad-nixpkgs", "flake-utils" ], "nixpkgs": [ + "ppad-secp256k1", "ppad-sha256", "ppad-nixpkgs", "nixpkgs" ], - "ppad-base16": "ppad-base16_2", - "ppad-nixpkgs": "ppad-nixpkgs_3" + "ppad-base16": [ + "ppad-secp256k1", + "ppad-base16" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1768045644, + "narHash": "sha256-8+jLaYRN8iX6NmyotE7DvjfjUIT8I0KOchgcP7uq7Vo=", + "ref": "master", + "rev": "4716cd5b4e673e9cb66e4e5e427e5464a7c10977", + "revCount": 116, + "type": "git", + "url": "git://git.ppad.tech/sha256.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/sha256.git" + } + }, + "ppad-sha256_2": { + "inputs": { + "flake-utils": [ + "ppad-sha256", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-sha256", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": "ppad-base16_3", + "ppad-nixpkgs": "ppad-nixpkgs_4" }, "locked": { "lastModified": 1768121850, @@ -290,6 +529,44 @@ "url": "git://git.ppad.tech/sha256.git" } }, + "ppad-sha512": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-sha512", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-sha512", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": [ + "ppad-secp256k1", + "ppad-base16" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1768045869, + "narHash": "sha256-ySqv5fQRz+/9X54yXCuck2QnGyuIqRLpRzanh+Ehl88=", + "ref": "master", + "rev": "0fbaba3c091692622744d30016e36ca6b726a819", + "revCount": 42, + "type": "git", + "url": "git://git.ppad.tech/sha512.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/sha512.git" + } + }, "root": { "inputs": { "flake-utils": [ @@ -302,7 +579,8 @@ ], "ppad-nixpkgs": "ppad-nixpkgs", "ppad-ripemd160": "ppad-ripemd160", - "ppad-sha256": "ppad-sha256" + "ppad-secp256k1": "ppad-secp256k1", + "ppad-sha256": "ppad-sha256_2" } }, "systems": { @@ -349,6 +627,21 @@ "repo": "default", "type": "github" } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/lib/Lightning/Protocol/BOLT3/Keys.hs b/lib/Lightning/Protocol/BOLT3/Keys.hs @@ -49,7 +49,7 @@ module Lightning.Protocol.BOLT3.Keys ( , obscured_commitment_number ) where -import Data.Bits ((.&.), xor, shiftL, shiftR, testBit, complementBit) +import Data.Bits ((.&.), xor, shiftL, testBit, complementBit) import qualified Data.ByteString as BS import Data.Word (Word64) import GHC.Generics (Generic) @@ -70,9 +70,9 @@ derive_per_commitment_point :: PerCommitmentSecret -> Maybe PerCommitmentPoint derive_per_commitment_point (PerCommitmentSecret sec) = do - sk <- S.parse_seckey sec - let !pk = S.derive_pubkey sk - !bs = S.serialize_point pk + sk <- S.parse_int256 sec + pk <- S.derive_pub sk + let !bs = S.serialize_point pk pure $! PerCommitmentPoint (Point bs) {-# INLINE derive_per_commitment_point #-} @@ -94,15 +94,14 @@ derive_pubkey -> Maybe Pubkey derive_pubkey (Point basepointBs) (PerCommitmentPoint (Point pcpBs)) = do basepoint <- S.parse_point basepointBs - pcp <- S.parse_point pcpBs -- SHA256(per_commitment_point || basepoint) let !h = SHA256.hash (pcpBs <> basepointBs) -- Treat hash as scalar and multiply by G - tweak <- S.parse_seckey h - let !tweakPoint = S.derive_pubkey tweak + tweak <- S.parse_int256 h + tweakPoint <- S.derive_pub tweak -- Add basepoint + tweak*G - result <- S.add_point basepoint tweakPoint - let !bs = S.serialize_point result + let !result = S.add basepoint tweakPoint + !bs = S.serialize_point result pure $! Pubkey bs {-# INLINE derive_pubkey #-} @@ -196,13 +195,13 @@ derive_revocationpubkey -- SHA256(per_commitment_point || revocation_basepoint) let !h2 = SHA256.hash (pcpBs <> rbpBs) -- Multiply points by their respective scalars - s1 <- S.parse_seckey h1 - s2 <- S.parse_seckey h2 - let !p1 = S.mul_point rbp s1 -- revocation_basepoint * h1 - !p2 = S.mul_point pcp s2 -- per_commitment_point * h2 + s1 <- S.parse_int256 h1 + s2 <- S.parse_int256 h2 + p1 <- S.mul rbp s1 -- revocation_basepoint * h1 + p2 <- S.mul pcp s2 -- per_commitment_point * h2 -- Add the two points - result <- S.add_point p1 p2 - let !bs = S.serialize_point result + let !result = S.add p1 p2 + !bs = S.serialize_point result pure $! RevocationPubkey (Pubkey bs) {-# INLINE derive_revocationpubkey #-} @@ -348,7 +347,7 @@ insert_secret secret idx (SecretStore known) = do where validateBuckets :: Int -> [SecretEntry] -> Maybe Bool validateBuckets b entries = go 0 entries where - go !currentB [] = Just True + go !_ [] = Just True go !currentB (SecretEntry knownIdx knownSecret : rest) | currentB >= b = Just True | otherwise = @@ -359,8 +358,8 @@ insert_secret secret idx (SecretStore known) = do else Nothing insertAt :: Int -> SecretEntry -> [SecretEntry] -> [SecretEntry] - insertAt b entry [] = [entry] - insertAt b entry entries@(e:es) + insertAt _ entry [] = [entry] + insertAt b entry entries@(_:_) | length entries <= b = entries ++ [entry] | otherwise = take b entries ++ [entry] {-# INLINE insert_secret #-} @@ -378,7 +377,7 @@ derive_old_secret -> Maybe BS.ByteString derive_old_secret targetIdx (SecretStore known) = go 0 known where go :: Int -> [SecretEntry] -> Maybe BS.ByteString - go !b [] = Nothing + go !_ [] = Nothing go !b (SecretEntry knownIdx knownSecret : rest) = -- Mask off the non-zero prefix of the index let !mask = complement ((1 `shiftL` b) - 1)