bolt5

On-chain transaction handling for Lightning (docs.ppad.tech/bolt5).
git clone git://git.ppad.tech/bolt5.git
Log | Files | Refs | README | LICENSE

Types.hs (6261B)


      1 {-# OPTIONS_HADDOCK prune #-}
      2 {-# LANGUAGE BangPatterns #-}
      3 {-# LANGUAGE DeriveGeneric #-}
      4 
      5 -- |
      6 -- Module: Lightning.Protocol.BOLT5.Types
      7 -- Copyright: (c) 2025 Jared Tobin
      8 -- License: MIT
      9 -- Maintainer: Jared Tobin <jared@ppad.tech>
     10 --
     11 -- Types for BOLT #5 on-chain transaction handling.
     12 
     13 module Lightning.Protocol.BOLT5.Types (
     14     -- * Close identification
     15     CloseType(..)
     16 
     17     -- * Output classification
     18   , UnresolvedOutput(..)
     19   , OutputResolution(..)
     20 
     21     -- * Spending transactions
     22   , SpendingTx(..)
     23 
     24     -- * Penalty batching
     25   , PenaltyContext(..)
     26 
     27     -- * Weight constants (Appendix A)
     28   , to_local_penalty_witness_weight
     29   , offered_htlc_penalty_witness_weight
     30   , accepted_htlc_penalty_witness_weight
     31   , to_local_penalty_input_weight
     32   , offered_htlc_penalty_input_weight
     33   , accepted_htlc_penalty_input_weight
     34   , to_remote_input_weight
     35   , penalty_tx_base_weight
     36   , max_standard_weight
     37 
     38     -- * Fee calculation
     39   , spending_fee
     40   ) where
     41 
     42 import Bitcoin.Prim.Tx (Tx(..))
     43 import Bitcoin.Prim.Tx.Sighash (SighashType(..))
     44 import Data.List.NonEmpty (NonEmpty)
     45 import Data.Word (Word64)
     46 import GHC.Generics (Generic)
     47 import Lightning.Protocol.BOLT3.Types
     48 import Lightning.Protocol.BOLT3.Tx (
     49     CommitmentKeys(..)
     50   , OutputType(..)
     51   )
     52 
     53 -- close identification -----------------------------------------------
     54 
     55 -- | What kind of close was detected on chain.
     56 data CloseType
     57   = MutualClose
     58     -- ^ Cooperative closure agreed by both parties.
     59   | LocalCommitClose
     60     -- ^ Our commitment transaction was broadcast.
     61   | RemoteCommitClose
     62     -- ^ The remote party's commitment transaction was broadcast.
     63   | RevokedCommitClose
     64     -- ^ A revoked (outdated) commitment transaction was broadcast.
     65   deriving (Eq, Show, Generic)
     66 
     67 -- output classification ----------------------------------------------
     68 
     69 -- | An unresolved commitment transaction output.
     70 data UnresolvedOutput = UnresolvedOutput
     71   { uo_outpoint :: !OutPoint
     72   , uo_value    :: {-# UNPACK #-} !Satoshi
     73   , uo_type     :: !OutputResolution
     74   } deriving (Eq, Show, Generic)
     75 
     76 -- | How to resolve an output, per BOLT #5 rules.
     77 data OutputResolution
     78   = Resolved
     79     -- ^ Already resolved (e.g. to_remote on local commit).
     80   | SpendToLocal
     81       !ToSelfDelay !RevocationPubkey !LocalDelayedPubkey
     82     -- ^ Spend to_local after CSV delay.
     83   | SpendHTLCTimeout
     84       !HTLC !CommitmentKeys !ChannelFeatures
     85     -- ^ Spend via HTLC-timeout second-stage tx (local commit,
     86     --   local offer).
     87   | SpendHTLCSuccess
     88       !HTLC !CommitmentKeys !ChannelFeatures
     89     -- ^ Spend via HTLC-success second-stage tx (local commit,
     90     --   remote offer).
     91   | SpendHTLCTimeoutDirect !HTLC
     92     -- ^ Spend HTLC directly after timeout (remote commit,
     93     --   local offer).
     94   | SpendHTLCPreimageDirect !HTLC
     95     -- ^ Spend HTLC directly with preimage (remote commit,
     96     --   remote offer).
     97   | Revoke !RevocationPubkey
     98     -- ^ Spend revoked to_local with revocation key.
     99   | RevokeHTLC !RevocationPubkey !OutputType
    100     -- ^ Spend revoked HTLC output with revocation key.
    101   | AnchorSpend !FundingPubkey
    102     -- ^ Spend anchor output.
    103   deriving (Eq, Show, Generic)
    104 
    105 -- spending transactions ----------------------------------------------
    106 
    107 -- | Unsigned spending transaction, ready for caller to sign.
    108 --
    109 -- The caller uses bolt3 witness constructors to assemble the
    110 -- final witness after signing.
    111 data SpendingTx = SpendingTx
    112   { stx_tx           :: !Tx
    113     -- ^ The unsigned transaction.
    114   , stx_input_script :: !Script
    115     -- ^ Witness script for the input being spent.
    116   , stx_input_value  :: {-# UNPACK #-} !Satoshi
    117     -- ^ Value of the input being spent (for sighash).
    118   , stx_sighash_type :: !SighashType
    119     -- ^ Sighash type to use when signing.
    120   } deriving (Eq, Show, Generic)
    121 
    122 -- penalty batching ---------------------------------------------------
    123 
    124 -- | Context for constructing batched penalty transactions.
    125 data PenaltyContext = PenaltyContext
    126   { pc_outputs        :: !(NonEmpty UnresolvedOutput)
    127     -- ^ Revoked outputs to sweep (must be non-empty).
    128   , pc_revocation_key :: !RevocationPubkey
    129     -- ^ Revocation pubkey for all outputs.
    130   , pc_destination    :: !Script
    131     -- ^ Destination scriptPubKey.
    132   , pc_feerate        :: !FeeratePerKw
    133     -- ^ Fee rate for the penalty transaction.
    134   } deriving (Eq, Show, Generic)
    135 
    136 -- weight constants (BOLT #5 Appendix A) ------------------------------
    137 
    138 -- | Expected weight of the to_local penalty transaction witness
    139 --   (160 bytes).
    140 to_local_penalty_witness_weight :: Word64
    141 to_local_penalty_witness_weight = 160
    142 
    143 -- | Expected weight of the offered_htlc penalty transaction
    144 --   witness (243 bytes).
    145 offered_htlc_penalty_witness_weight :: Word64
    146 offered_htlc_penalty_witness_weight = 243
    147 
    148 -- | Expected weight of the accepted_htlc penalty transaction
    149 --   witness (249 bytes).
    150 accepted_htlc_penalty_witness_weight :: Word64
    151 accepted_htlc_penalty_witness_weight = 249
    152 
    153 -- | Weight of a to_local penalty input (164 + 160 = 324 bytes).
    154 to_local_penalty_input_weight :: Word64
    155 to_local_penalty_input_weight = 324
    156 
    157 -- | Weight of an offered_htlc penalty input
    158 --   (164 + 243 = 407 bytes).
    159 offered_htlc_penalty_input_weight :: Word64
    160 offered_htlc_penalty_input_weight = 407
    161 
    162 -- | Weight of an accepted_htlc penalty input
    163 --   (164 + 249 = 413 bytes).
    164 accepted_htlc_penalty_input_weight :: Word64
    165 accepted_htlc_penalty_input_weight = 413
    166 
    167 -- | Weight of a to_remote P2WPKH input
    168 --   (108 + 164 = 272 bytes).
    169 to_remote_input_weight :: Word64
    170 to_remote_input_weight = 272
    171 
    172 -- | Base weight of a penalty transaction (4*53 + 2 = 214 bytes).
    173 --
    174 -- Non-witness: version(4) + input_count(1) + output_count(1) +
    175 -- value(8) + script_len(1) + p2wsh_script(34) + locktime(4) = 53
    176 -- Witness header: 2 bytes.
    177 penalty_tx_base_weight :: Word64
    178 penalty_tx_base_weight = 214
    179 
    180 -- | Maximum standard transaction weight (400,000 bytes).
    181 max_standard_weight :: Word64
    182 max_standard_weight = 400000
    183 
    184 -- fee calculation ----------------------------------------------------
    185 
    186 -- | Calculate the fee for a spending transaction given its weight.
    187 --
    188 -- @fee = feerate_per_kw * weight / 1000@
    189 spending_fee :: FeeratePerKw -> Word64 -> Satoshi
    190 spending_fee (FeeratePerKw !rate) !weight =
    191   Satoshi ((fromIntegral rate * weight) `div` 1000)
    192 {-# INLINE spending_fee #-}