ppad-bolt3-0.0.1: Bitcoin transaction formats per BOLT #3
Copyright(c) 2025 Jared Tobin
LicenseMIT
MaintainerJared Tobin <jared@ppad.tech>
Safe HaskellNone
LanguageHaskell2010

Lightning.Protocol.BOLT3.Validate

Description

Stateless validation for BOLT #3 transactions.

Provides validation for:

  • Commitment transaction structure and outputs
  • HTLC transaction structure
  • Closing transaction structure
  • Output ordering per BIP69+CLTV
  • Dust limit compliance
Synopsis

Validation errors

data ValidationError Source #

Errors that can occur during validation.

Constructors

InvalidVersion !Word32 !Word32

Expected version, actual version

InvalidLocktime !Word32

Invalid locktime format

InvalidSequence !Word32

Invalid sequence format

InvalidOutputOrdering

Outputs not in BIP69+CLTV order

DustLimitViolation !Int !Satoshi !Satoshi

Output index, actual value, dust limit

MissingAnchorOutput

Expected anchor output not present

InvalidAnchorValue !Satoshi

Anchor value not 330 satoshis

InvalidFee !Satoshi !Satoshi

Expected fee, actual fee

InvalidHTLCLocktime !Word32 !Word32

Expected locktime, actual locktime

InvalidHTLCSequence !Word32 !Word32

Expected sequence, actual sequence

NoOutputs

Transaction has no outputs

TooManyOutputs !Int

More outputs than expected

Instances

Instances details
Generic ValidationError Source # 
Instance details

Defined in Lightning.Protocol.BOLT3.Validate

Associated Types

type Rep ValidationError 
Instance details

Defined in Lightning.Protocol.BOLT3.Validate

type Rep ValidationError = D1 ('MetaData "ValidationError" "Lightning.Protocol.BOLT3.Validate" "ppad-bolt3-0.0.1-BTVAwWY46FT4MsZtX0EtFp" 'False) (((C1 ('MetaCons "InvalidVersion" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)) :+: (C1 ('MetaCons "InvalidLocktime" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)) :+: C1 ('MetaCons "InvalidSequence" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))) :+: (C1 ('MetaCons "InvalidOutputOrdering" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "DustLimitViolation" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Satoshi) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Satoshi))) :+: C1 ('MetaCons "MissingAnchorOutput" 'PrefixI 'False) (U1 :: Type -> Type)))) :+: ((C1 ('MetaCons "InvalidAnchorValue" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Satoshi)) :+: (C1 ('MetaCons "InvalidFee" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Satoshi) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Satoshi)) :+: C1 ('MetaCons "InvalidHTLCLocktime" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))) :+: (C1 ('MetaCons "InvalidHTLCSequence" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)) :+: (C1 ('MetaCons "NoOutputs" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "TooManyOutputs" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Int))))))
Show ValidationError Source # 
Instance details

Defined in Lightning.Protocol.BOLT3.Validate

Eq ValidationError Source # 
Instance details

Defined in Lightning.Protocol.BOLT3.Validate

type Rep ValidationError Source # 
Instance details

Defined in Lightning.Protocol.BOLT3.Validate

type Rep ValidationError = D1 ('MetaData "ValidationError" "Lightning.Protocol.BOLT3.Validate" "ppad-bolt3-0.0.1-BTVAwWY46FT4MsZtX0EtFp" 'False) (((C1 ('MetaCons "InvalidVersion" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)) :+: (C1 ('MetaCons "InvalidLocktime" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)) :+: C1 ('MetaCons "InvalidSequence" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))) :+: (C1 ('MetaCons "InvalidOutputOrdering" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "DustLimitViolation" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Satoshi) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Satoshi))) :+: C1 ('MetaCons "MissingAnchorOutput" 'PrefixI 'False) (U1 :: Type -> Type)))) :+: ((C1 ('MetaCons "InvalidAnchorValue" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Satoshi)) :+: (C1 ('MetaCons "InvalidFee" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Satoshi) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Satoshi)) :+: C1 ('MetaCons "InvalidHTLCLocktime" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))) :+: (C1 ('MetaCons "InvalidHTLCSequence" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)) :+: (C1 ('MetaCons "NoOutputs" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "TooManyOutputs" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Int))))))

Commitment transaction validation

validate_commitment_tx :: DustLimit -> ChannelFeatures -> CommitmentTx -> Either ValidationError () Source #

Validate a commitment transaction.

Checks:

  • Version is 2
  • Locktime format (upper 8 bits = 0x20)
  • Sequence format (upper 8 bits = 0x80)
  • Output ordering per BIP69+CLTV
  • Dust limit compliance
  • Anchor outputs if option_anchors

validate_commitment_locktime :: Locktime -> Either ValidationError () Source #

Validate commitment transaction locktime format.

Upper 8 bits must be 0x20.

validate_commitment_sequence :: Sequence -> Either ValidationError () Source #

Validate commitment transaction sequence format.

Upper 8 bits must be 0x80.

HTLC transaction validation

validate_htlc_tx :: HTLCTx -> Either ValidationError () Source #

Validate an HTLC transaction (timeout or success).

Checks:

  • Version is 2
  • Single output

validate_htlc_timeout_tx :: ChannelFeatures -> CltvExpiry -> HTLCTx -> Either ValidationError () Source #

Validate an HTLC-timeout transaction.

Checks:

  • Base HTLC validation
  • Locktime equals HTLC cltv_expiry
  • Sequence is 0 (or 1 with option_anchors)

validate_htlc_success_tx :: ChannelFeatures -> HTLCTx -> Either ValidationError () Source #

Validate an HTLC-success transaction.

Checks:

  • Base HTLC validation
  • Locktime is 0
  • Sequence is 0 (or 1 with option_anchors)

Closing transaction validation

validate_closing_tx :: ClosingTx -> Either ValidationError () Source #

Validate a closing transaction (option_simple_close).

Checks:

  • Version is 2
  • Sequence is 0xFFFFFFFD
  • At least one output
  • Output ordering per BIP69

validate_legacy_closing_tx :: ClosingTx -> Either ValidationError () Source #

Validate a legacy closing transaction (closing_signed).

Checks:

  • Version is 2
  • Locktime is 0
  • Sequence is 0xFFFFFFFF
  • At least one output
  • Output ordering per BIP69

Output validation

validate_output_ordering :: [TxOutput] -> Either ValidationError () Source #

Validate output ordering per BIP69+CLTV.

Outputs must be sorted by: 1. Value (smallest first) 2. ScriptPubKey (lexicographic) 3. CLTV expiry (for HTLC outputs)

validate_dust_limits :: DustLimit -> [TxOutput] -> Either ValidationError () Source #

Validate that no output violates dust limits.

validate_anchor_outputs :: [TxOutput] -> Either ValidationError () Source #

Validate anchor outputs are present and correctly valued.

Fee validation

validate_commitment_fee Source #

Arguments

:: FeeratePerKw 
-> ChannelFeatures 
-> Word64

Number of untrimmed HTLCs

-> Satoshi

Actual fee

-> Either ValidationError () 

Validate commitment transaction fee.

Checks that the fee matches the expected calculation.

validate_htlc_fee Source #

Arguments

:: FeeratePerKw 
-> ChannelFeatures 
-> HTLCDirection 
-> Satoshi

Actual fee

-> Either ValidationError () 

Validate HTLC transaction fee.