bolt3

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

commit 8af91e37d272af25626b1f02b2cdf55456d4db36
parent 98e8f9cc3d5c4883e91eedeae380654d6a53b8f3
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun, 25 Jan 2026 10:52:43 +0400

Milestone 0: Add module stubs and core Types

Create project structure with module stubs:
- Lightning.Protocol.BOLT3.Types: core newtypes and ADTs
- Lightning.Protocol.BOLT3.Keys: key derivation (stub)
- Lightning.Protocol.BOLT3.Scripts: script templates (stub)
- Lightning.Protocol.BOLT3.Tx: transaction assembly (stub)
- Lightning.Protocol.BOLT3.Encode: serialization (stub)
- Lightning.Protocol.BOLT3.Decode: parsing (stub)
- Lightning.Protocol.BOLT3.Validate: validation (stub)

Types module includes:
- Monetary types (Satoshi, MilliSatoshi)
- Key types (Pubkey, Seckey, Point, various basepoints)
- Transaction primitives (TxId, Outpoint, Sequence, Locktime)
- Channel parameters (CommitmentNumber, ToSelfDelay, etc.)
- HTLC types with BOLT #3 ordering
- Script/Witness newtypes
- Weight and dust constants from spec

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

Diffstat:
Aflake.lock | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/Lightning/Protocol/BOLT3.hs | 14+++++++++++++-
Alib/Lightning/Protocol/BOLT3/Decode.hs | 26++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT3/Encode.hs | 27+++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT3/Keys.hs | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT3/Scripts.hs | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT3/Tx.hs | 48++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT3/Types.hs | 363+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT3/Validate.hs | 30++++++++++++++++++++++++++++++
Mppad-bolt3.cabal | 7+++++++
10 files changed, 714 insertions(+), 1 deletion(-)

diff --git a/flake.lock b/flake.lock @@ -0,0 +1,88 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "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, + "narHash": "sha256-Ss/LHpJJsng8vz1Pe33RSGIWUOcqM1fjrehjUkdrWio=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3edc4a30ed3903fdf6f90c837f961fa6b49582d1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "ppad-nixpkgs": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "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" + } + }, + "root": { + "inputs": { + "flake-utils": [ + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": "ppad-nixpkgs" + } + }, + "systems": { + "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", + "version": 7 +} diff --git a/lib/Lightning/Protocol/BOLT3.hs b/lib/Lightning/Protocol/BOLT3.hs @@ -1,5 +1,4 @@ {-# OPTIONS_HADDOCK prune #-} -{-# LANGUAGE BangPatterns #-} -- | -- Module: Lightning.Protocol.BOLT3 @@ -9,7 +8,20 @@ -- -- Bitcoin transaction formats for the Lightning Network, per -- [BOLT #3](https://github.com/lightning/bolts/blob/master/03-transactions.md). +-- +-- This module re-exports the public API from submodules: +-- +-- * "Lightning.Protocol.BOLT3.Types" - Core types +-- * "Lightning.Protocol.BOLT3.Keys" - Key derivation +-- * "Lightning.Protocol.BOLT3.Scripts" - Script templates +-- * "Lightning.Protocol.BOLT3.Tx" - Transaction assembly +-- * "Lightning.Protocol.BOLT3.Encode" - Serialization +-- * "Lightning.Protocol.BOLT3.Decode" - Parsing +-- * "Lightning.Protocol.BOLT3.Validate" - Validation module Lightning.Protocol.BOLT3 ( + -- * Re-exports + module Lightning.Protocol.BOLT3.Types ) where +import Lightning.Protocol.BOLT3.Types diff --git a/lib/Lightning/Protocol/BOLT3/Decode.hs b/lib/Lightning/Protocol/BOLT3/Decode.hs @@ -0,0 +1,26 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Decode +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Parsing for BOLT #3 transactions and scripts. + +module Lightning.Protocol.BOLT3.Decode ( + -- * Transaction parsing + -- decode_tx + + -- * Script parsing + -- , decode_script + -- , decode_witness + + -- * Primitive decoding + -- , decode_varint + -- , decode_le32 + -- , decode_le64 + ) where + +import Lightning.Protocol.BOLT3.Types diff --git a/lib/Lightning/Protocol/BOLT3/Encode.hs b/lib/Lightning/Protocol/BOLT3/Encode.hs @@ -0,0 +1,27 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Encode +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Serialization for BOLT #3 transactions and scripts. + +module Lightning.Protocol.BOLT3.Encode ( + -- * Transaction serialization + -- encode_tx + -- , encode_tx_for_signing + + -- * Script serialization + -- , encode_script + -- , encode_witness + + -- * Primitive encoding + -- , encode_varint + -- , encode_le32 + -- , encode_le64 + ) where + +import Lightning.Protocol.BOLT3.Types diff --git a/lib/Lightning/Protocol/BOLT3/Keys.hs b/lib/Lightning/Protocol/BOLT3/Keys.hs @@ -0,0 +1,51 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Keys +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Per-commitment key derivation per BOLT #3. +-- +-- Implements key derivation formulas: +-- +-- @ +-- pubkey = basepoint + SHA256(per_commitment_point || basepoint) * G +-- revocationpubkey = revocation_basepoint * SHA256(revocation_basepoint || per_commitment_point) +-- + per_commitment_point * SHA256(per_commitment_point || revocation_basepoint) +-- @ + +module Lightning.Protocol.BOLT3.Keys ( + -- * Per-commitment point derivation + -- derive_per_commitment_point + + -- * Key derivation + -- , derive_pubkey + -- , derive_localpubkey + -- , derive_local_htlcpubkey + -- , derive_remote_htlcpubkey + -- , derive_local_delayedpubkey + -- , derive_remote_delayedpubkey + + -- * Revocation key derivation + -- , derive_revocationpubkey + -- , derive_revocationprivkey + + -- * Per-commitment secret generation + -- , generate_from_seed + -- , derive_secret + + -- * Per-commitment secret storage + -- , SecretStore + -- , empty_store + -- , insert_secret + -- , derive_old_secret + + -- * Commitment number obscuring + -- , obscured_commitment_number + -- , commitment_number_from_locktime_sequence + ) where + +import Lightning.Protocol.BOLT3.Types diff --git a/lib/Lightning/Protocol/BOLT3/Scripts.hs b/lib/Lightning/Protocol/BOLT3/Scripts.hs @@ -0,0 +1,61 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Scripts +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Script templates for BOLT #3 transaction outputs. +-- +-- Includes witness scripts for: +-- +-- * Funding output (2-of-2 multisig) +-- * to_local output (revocable with CSV delay) +-- * to_remote output (P2WPKH or anchored) +-- * Anchor outputs +-- * Offered HTLC outputs +-- * Received HTLC outputs +-- * HTLC-timeout/success output (revocable with delay) + +module Lightning.Protocol.BOLT3.Scripts ( + -- * Funding output + -- funding_script + -- , funding_witness + + -- * to_local output + -- , to_local_script + -- , to_local_witness_spend + -- , to_local_witness_revoke + + -- * to_remote output + -- , to_remote_script + -- , to_remote_witness + + -- * Anchor outputs + -- , anchor_script + -- , anchor_witness_owner + -- , anchor_witness_anyone + + -- * Offered HTLC output + -- , offered_htlc_script + -- , offered_htlc_witness_preimage + -- , offered_htlc_witness_revoke + + -- * Received HTLC output + -- , received_htlc_script + -- , received_htlc_witness_timeout + -- , received_htlc_witness_revoke + + -- * HTLC-timeout/success output (same as to_local) + -- , htlc_output_script + -- , htlc_output_witness_spend + -- , htlc_output_witness_revoke + + -- * P2WSH helpers + -- , to_p2wsh + -- , witness_script_hash + ) where + +import Lightning.Protocol.BOLT3.Types diff --git a/lib/Lightning/Protocol/BOLT3/Tx.hs b/lib/Lightning/Protocol/BOLT3/Tx.hs @@ -0,0 +1,48 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Tx +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Transaction assembly for BOLT #3. +-- +-- Constructs: +-- +-- * Commitment transactions +-- * HTLC-timeout transactions +-- * HTLC-success transactions +-- * Closing transactions + +module Lightning.Protocol.BOLT3.Tx ( + -- * Commitment transaction + -- CommitmentTx(..) + -- , build_commitment_tx + + -- * HTLC transactions + -- , HTLCTx(..) + -- , build_htlc_timeout_tx + -- , build_htlc_success_tx + + -- * Closing transaction + -- , ClosingTx(..) + -- , build_closing_tx + -- , build_legacy_closing_tx + + -- * Fee calculation + -- , commitment_fee + -- , htlc_timeout_fee + -- , htlc_success_fee + + -- * Trimming + -- , is_trimmed + -- , trimmed_htlcs + -- , untrimmed_htlcs + + -- * Output ordering + -- , sort_outputs + ) where + +import Lightning.Protocol.BOLT3.Types diff --git a/lib/Lightning/Protocol/BOLT3/Types.hs b/lib/Lightning/Protocol/BOLT3/Types.hs @@ -0,0 +1,363 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Types +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Core types for BOLT #3 transaction and script formats. + +module Lightning.Protocol.BOLT3.Types ( + -- * Monetary amounts + Satoshi(..) + , MilliSatoshi(..) + , msat_to_sat + , sat_to_msat + + -- * Keys and points + , Pubkey(..) + , Seckey(..) + , Point(..) + + -- * Hashes + , PaymentHash(..) + , PaymentPreimage(..) + + -- * Transaction primitives + , TxId(..) + , Outpoint(..) + , Sequence(..) + , Locktime(..) + + -- * Channel parameters + , CommitmentNumber(..) + , ToSelfDelay(..) + , CltvExpiry(..) + , DustLimit(..) + , FeeratePerKw(..) + + -- * HTLC types + , HTLC(..) + , HTLCDirection(..) + + -- * Basepoints + , Basepoints(..) + , PerCommitmentPoint(..) + , PerCommitmentSecret(..) + , RevocationBasepoint(..) + , PaymentBasepoint(..) + , DelayedPaymentBasepoint(..) + , HtlcBasepoint(..) + + -- * Derived keys + , LocalPubkey(..) + , RemotePubkey(..) + , LocalDelayedPubkey(..) + , RemoteDelayedPubkey(..) + , LocalHtlcPubkey(..) + , RemoteHtlcPubkey(..) + , RevocationPubkey(..) + , FundingPubkey(..) + + -- * Script and witness + , Script(..) + , Witness(..) + + -- * Channel options + , ChannelFeatures(..) + , has_anchors + + -- * Transaction weights (constants) + , commitment_weight_no_anchors + , commitment_weight_anchors + , htlc_timeout_weight_no_anchors + , htlc_timeout_weight_anchors + , htlc_success_weight_no_anchors + , htlc_success_weight_anchors + , htlc_output_weight + + -- * Dust thresholds (constants) + , dust_p2pkh + , dust_p2sh + , dust_p2wpkh + , dust_p2wsh + , anchor_output_value + ) where + +import Data.Bits ((.&.)) +import Data.Word (Word16, Word32, Word64) +import qualified Data.ByteString as BS +import GHC.Generics (Generic) + +-- monetary amounts ------------------------------------------------------------ + +-- | Amount in satoshis. +newtype Satoshi = Satoshi { unSatoshi :: Word64 } + deriving (Eq, Ord, Show, Generic, Num) + +-- | Amount in millisatoshis. +newtype MilliSatoshi = MilliSatoshi { unMilliSatoshi :: Word64 } + deriving (Eq, Ord, Show, Generic, Num) + +-- | Convert millisatoshis to satoshis (rounds down). +msat_to_sat :: MilliSatoshi -> Satoshi +msat_to_sat (MilliSatoshi m) = Satoshi (m `div` 1000) +{-# INLINE msat_to_sat #-} + +-- | Convert satoshis to millisatoshis. +sat_to_msat :: Satoshi -> MilliSatoshi +sat_to_msat (Satoshi s) = MilliSatoshi (s * 1000) +{-# INLINE sat_to_msat #-} + +-- keys and points ------------------------------------------------------------- + +-- | Compressed public key (33 bytes). +newtype Pubkey = Pubkey { unPubkey :: BS.ByteString } + deriving (Eq, Ord, Show, Generic) + +-- | Secret key (32 bytes). +newtype Seckey = Seckey { unSeckey :: BS.ByteString } + deriving (Eq, Generic) + +-- Don't show secret keys +instance Show Seckey where + show _ = "Seckey <redacted>" + +-- | Elliptic curve point (33-byte compressed form). +newtype Point = Point { unPoint :: BS.ByteString } + deriving (Eq, Ord, Show, Generic) + +-- hashes ---------------------------------------------------------------------- + +-- | Payment hash (32 bytes, SHA256 of preimage). +newtype PaymentHash = PaymentHash { unPaymentHash :: BS.ByteString } + deriving (Eq, Ord, Show, Generic) + +-- | Payment preimage (32 bytes). +newtype PaymentPreimage = PaymentPreimage { unPaymentPreimage :: BS.ByteString } + deriving (Eq, Generic) + +instance Show PaymentPreimage where + show _ = "PaymentPreimage <redacted>" + +-- transaction primitives ------------------------------------------------------ + +-- | Transaction ID (32 bytes, little-endian hash). +newtype TxId = TxId { unTxId :: BS.ByteString } + deriving (Eq, Ord, Show, Generic) + +-- | Transaction outpoint (txid + output index). +data Outpoint = Outpoint + { outpoint_txid :: {-# UNPACK #-} !TxId + , outpoint_index :: {-# UNPACK #-} !Word32 + } deriving (Eq, Ord, Show, Generic) + +-- | Transaction input sequence number. +newtype Sequence = Sequence { unSequence :: Word32 } + deriving (Eq, Ord, Show, Generic, Num) + +-- | Transaction locktime. +newtype Locktime = Locktime { unLocktime :: Word32 } + deriving (Eq, Ord, Show, Generic, Num) + +-- channel parameters ---------------------------------------------------------- + +-- | 48-bit commitment number. +newtype CommitmentNumber = CommitmentNumber { unCommitmentNumber :: Word64 } + deriving (Eq, Ord, Show, Generic, Num) + +-- | CSV delay for to_local outputs. +newtype ToSelfDelay = ToSelfDelay { unToSelfDelay :: Word16 } + deriving (Eq, Ord, Show, Generic, Num) + +-- | CLTV expiry for HTLCs. +newtype CltvExpiry = CltvExpiry { unCltvExpiry :: Word32 } + deriving (Eq, Ord, Show, Generic, Num) + +-- | Dust limit threshold. +newtype DustLimit = DustLimit { unDustLimit :: Satoshi } + deriving (Eq, Ord, Show, Generic) + +-- | Fee rate in satoshis per 1000 weight units. +newtype FeeratePerKw = FeeratePerKw { unFeeratePerKw :: Word32 } + deriving (Eq, Ord, Show, Generic, Num) + +-- HTLC types ------------------------------------------------------------------ + +-- | Direction of an HTLC from the commitment tx owner's perspective. +data HTLCDirection + = HTLCOffered -- ^ We offered this HTLC (outgoing) + | HTLCReceived -- ^ We received this HTLC (incoming) + deriving (Eq, Ord, Show, Generic) + +-- | HTLC output details. +data HTLC = HTLC + { htlc_direction :: !HTLCDirection + , htlc_amount_msat :: {-# UNPACK #-} !MilliSatoshi + , htlc_payment_hash :: {-# UNPACK #-} !PaymentHash + , htlc_cltv_expiry :: {-# UNPACK #-} !CltvExpiry + } deriving (Eq, Show, Generic) + +-- Define ordering per BOLT #3: by amount (sat), then scriptpubkey, then expiry +instance Ord HTLC where + compare h1 h2 = + let sat1 = msat_to_sat (htlc_amount_msat h1) + sat2 = msat_to_sat (htlc_amount_msat h2) + in case compare sat1 sat2 of + EQ -> compare (htlc_cltv_expiry h1) (htlc_cltv_expiry h2) + other -> other + +-- basepoints ------------------------------------------------------------------ + +-- | Per-commitment point (used to derive keys). +newtype PerCommitmentPoint = PerCommitmentPoint { unPerCommitmentPoint :: Point } + deriving (Eq, Ord, Show, Generic) + +-- | Per-commitment secret (32 bytes). +newtype PerCommitmentSecret = PerCommitmentSecret + { unPerCommitmentSecret :: BS.ByteString } + deriving (Eq, Generic) + +instance Show PerCommitmentSecret where + show _ = "PerCommitmentSecret <redacted>" + +-- | Revocation basepoint. +newtype RevocationBasepoint = RevocationBasepoint + { unRevocationBasepoint :: Point } + deriving (Eq, Ord, Show, Generic) + +-- | Payment basepoint. +newtype PaymentBasepoint = PaymentBasepoint + { unPaymentBasepoint :: Point } + deriving (Eq, Ord, Show, Generic) + +-- | Delayed payment basepoint. +newtype DelayedPaymentBasepoint = DelayedPaymentBasepoint + { unDelayedPaymentBasepoint :: Point } + deriving (Eq, Ord, Show, Generic) + +-- | HTLC basepoint. +newtype HtlcBasepoint = HtlcBasepoint { unHtlcBasepoint :: Point } + deriving (Eq, Ord, Show, Generic) + +-- | Collection of all basepoints for one party. +data Basepoints = Basepoints + { bp_revocation :: !RevocationBasepoint + , bp_payment :: !PaymentBasepoint + , bp_delayed_payment :: !DelayedPaymentBasepoint + , bp_htlc :: !HtlcBasepoint + } deriving (Eq, Show, Generic) + +-- derived keys ---------------------------------------------------------------- + +-- | Local pubkey (derived from payment_basepoint + per_commitment_point). +newtype LocalPubkey = LocalPubkey { unLocalPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Remote pubkey (simply the remote's payment_basepoint). +newtype RemotePubkey = RemotePubkey { unRemotePubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Local delayed pubkey. +newtype LocalDelayedPubkey = LocalDelayedPubkey + { unLocalDelayedPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Remote delayed pubkey. +newtype RemoteDelayedPubkey = RemoteDelayedPubkey + { unRemoteDelayedPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Local HTLC pubkey. +newtype LocalHtlcPubkey = LocalHtlcPubkey { unLocalHtlcPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Remote HTLC pubkey. +newtype RemoteHtlcPubkey = RemoteHtlcPubkey { unRemoteHtlcPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Revocation pubkey (derived from revocation_basepoint + per_commitment). +newtype RevocationPubkey = RevocationPubkey { unRevocationPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- | Funding pubkey (used in 2-of-2 multisig). +newtype FundingPubkey = FundingPubkey { unFundingPubkey :: Pubkey } + deriving (Eq, Ord, Show, Generic) + +-- script and witness ---------------------------------------------------------- + +-- | Bitcoin script (serialized). +newtype Script = Script { unScript :: BS.ByteString } + deriving (Eq, Ord, Show, Generic) + +-- | Transaction witness stack. +newtype Witness = Witness { unWitness :: [BS.ByteString] } + deriving (Eq, Ord, Show, Generic) + +-- channel options ------------------------------------------------------------- + +-- | Channel feature flags relevant to BOLT #3. +data ChannelFeatures = ChannelFeatures + { cf_option_anchors :: !Bool + } deriving (Eq, Show, Generic) + +-- | Check if option_anchors is enabled. +has_anchors :: ChannelFeatures -> Bool +has_anchors = cf_option_anchors +{-# INLINE has_anchors #-} + +-- transaction weights (constants from spec) ----------------------------------- + +-- | Base commitment tx weight without option_anchors. +commitment_weight_no_anchors :: Word64 +commitment_weight_no_anchors = 724 + +-- | Base commitment tx weight with option_anchors. +commitment_weight_anchors :: Word64 +commitment_weight_anchors = 1124 + +-- | HTLC-timeout tx weight without option_anchors. +htlc_timeout_weight_no_anchors :: Word64 +htlc_timeout_weight_no_anchors = 663 + +-- | HTLC-timeout tx weight with option_anchors. +htlc_timeout_weight_anchors :: Word64 +htlc_timeout_weight_anchors = 666 + +-- | HTLC-success tx weight without option_anchors. +htlc_success_weight_no_anchors :: Word64 +htlc_success_weight_no_anchors = 703 + +-- | HTLC-success tx weight with option_anchors. +htlc_success_weight_anchors :: Word64 +htlc_success_weight_anchors = 706 + +-- | Weight added per HTLC output in commitment tx. +htlc_output_weight :: Word64 +htlc_output_weight = 172 + +-- dust thresholds (constants from Bitcoin Core) ------------------------------- + +-- | P2PKH dust threshold (546 satoshis). +dust_p2pkh :: Satoshi +dust_p2pkh = Satoshi 546 + +-- | P2SH dust threshold (540 satoshis). +dust_p2sh :: Satoshi +dust_p2sh = Satoshi 540 + +-- | P2WPKH dust threshold (294 satoshis). +dust_p2wpkh :: Satoshi +dust_p2wpkh = Satoshi 294 + +-- | P2WSH dust threshold (330 satoshis). +dust_p2wsh :: Satoshi +dust_p2wsh = Satoshi 330 + +-- | Fixed anchor output value (330 satoshis). +anchor_output_value :: Satoshi +anchor_output_value = Satoshi 330 diff --git a/lib/Lightning/Protocol/BOLT3/Validate.hs b/lib/Lightning/Protocol/BOLT3/Validate.hs @@ -0,0 +1,30 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} + +-- | +-- Module: Lightning.Protocol.BOLT3.Validate +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Stateless validation for BOLT #3 transactions. + +module Lightning.Protocol.BOLT3.Validate ( + -- * Validation errors + -- ValidationError(..) + + -- * Commitment transaction validation + -- , validate_commitment_tx + + -- * HTLC transaction validation + -- , validate_htlc_tx + + -- * Closing transaction validation + -- , validate_closing_tx + + -- * Output validation + -- , validate_output_ordering + -- , validate_dust_limits + ) where + +import Lightning.Protocol.BOLT3.Types diff --git a/ppad-bolt3.cabal b/ppad-bolt3.cabal @@ -25,6 +25,13 @@ library -Wall exposed-modules: Lightning.Protocol.BOLT3 + Lightning.Protocol.BOLT3.Decode + Lightning.Protocol.BOLT3.Encode + Lightning.Protocol.BOLT3.Keys + Lightning.Protocol.BOLT3.Scripts + Lightning.Protocol.BOLT3.Tx + Lightning.Protocol.BOLT3.Types + Lightning.Protocol.BOLT3.Validate build-depends: base >= 4.9 && < 5 , bytestring >= 0.9 && < 0.13