Types.hs (10751B)
1 {-# OPTIONS_HADDOCK hide #-} 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 -- * HTLC output type 22 , HTLCOutputType(..) 23 , htlc_output_type 24 , htlc_output_type_weight 25 26 -- * Spending transactions 27 , SpendingTx(..) 28 29 -- * Revoked outputs 30 , RevokedOutput(..) 31 , RevokedOutputType(..) 32 , revoked_output_weight 33 34 -- * Weight constants (Appendix A) 35 , to_local_penalty_witness_weight 36 , offered_htlc_penalty_witness_weight 37 , accepted_htlc_penalty_witness_weight 38 , offered_htlc_penalty_witness_weight_anchors 39 , accepted_htlc_penalty_witness_weight_anchors 40 , to_local_penalty_input_weight 41 , offered_htlc_penalty_input_weight 42 , accepted_htlc_penalty_input_weight 43 , offered_htlc_penalty_input_weight_anchors 44 , accepted_htlc_penalty_input_weight_anchors 45 , to_remote_input_weight 46 , penalty_tx_base_weight 47 , max_standard_weight 48 49 -- * Fee calculation 50 , spending_fee 51 ) where 52 53 import Bitcoin.Prim.Tx (OutPoint, Tx) 54 import Bitcoin.Prim.Tx.Sighash (SighashType) 55 import Control.DeepSeq (NFData(..)) 56 import Data.Word (Word64) 57 import GHC.Generics (Generic) 58 import Lightning.Protocol.BOLT1 (Satoshi) 59 import qualified Lightning.Protocol.BOLT1 as BOLT1 60 import Lightning.Protocol.BOLT3 61 62 -- close identification ----------------------------------------------- 63 64 -- | What kind of close was detected on chain. 65 -- 66 -- @identify_close@ produces only 'LocalCommitClose' and 67 -- 'RemoteCommitClose'; recognising mutual and revoked closes is 68 -- left to the caller. 69 data CloseType 70 = MutualClose 71 -- ^ Cooperative closure agreed by both parties. 72 | LocalCommitClose 73 -- ^ Our commitment transaction was broadcast. 74 | RemoteCommitClose 75 -- ^ The remote party's commitment transaction was broadcast. 76 | RevokedCommitClose 77 -- ^ A revoked (outdated) commitment transaction was broadcast. 78 deriving (Eq, Show, Generic) 79 80 instance NFData CloseType 81 82 -- output classification ---------------------------------------------- 83 84 -- | An unresolved commitment transaction output. 85 data UnresolvedOutput = UnresolvedOutput 86 { uo_outpoint :: !OutPoint 87 , uo_value :: {-# UNPACK #-} !Satoshi 88 , uo_type :: !OutputResolution 89 } deriving (Eq, Show, Generic) 90 91 instance NFData UnresolvedOutput 92 93 -- | How to resolve an output, per BOLT #5 rules. 94 data OutputResolution 95 = Resolved 96 -- ^ Nothing to do (e.g. to_remote on our local commitment). 97 | SpendToLocal 98 !ToSelfDelay !RevocationPubkey !LocalDelayedPubkey 99 -- ^ Spend to_local after the CSV delay. 100 | SpendHTLCTimeout 101 !HTLC !CommitmentKeys !CommitmentFormat 102 -- ^ Spend via an HTLC-timeout transaction (our commitment, an 103 -- HTLC we offered). 104 | SpendHTLCSuccess 105 !HTLC !CommitmentKeys !CommitmentFormat 106 -- ^ Spend via an HTLC-success transaction (our commitment, an 107 -- HTLC we received). 108 | SpendHTLCTimeoutDirect !HTLC 109 -- ^ Spend the HTLC directly after it times out (the remote 110 -- commitment, an HTLC we offered). 111 | SpendHTLCPreimageDirect !HTLC 112 -- ^ Spend the HTLC directly with the preimage (the remote 113 -- commitment, an HTLC we received). 114 | Revoke !RevocationPubkey 115 -- ^ Spend a revoked to_local output with the revocation key. 116 | RevokeHTLC !RevocationPubkey !HTLCOutputType 117 -- ^ Spend a revoked HTLC output with the revocation key. 118 | AnchorSpend !FundingPubkey 119 -- ^ Spend our anchor output. 120 deriving (Eq, Show, Generic) 121 122 instance NFData OutputResolution 123 124 -- HTLC output type ------------------------------------------------- 125 126 -- | The kind of an HTLC output, from the commitment owner's point of 127 -- view. 128 -- 129 -- Unlike bolt3's 'OutputType', this can't describe a to_local, 130 -- to_remote or anchor output. 131 data HTLCOutputType 132 = HTLCOfferedOutput {-# UNPACK #-} !CltvExpiry 133 -- ^ Offered HTLC output with CLTV expiry. 134 | HTLCReceivedOutput {-# UNPACK #-} !CltvExpiry 135 -- ^ Received HTLC output with CLTV expiry. 136 deriving (Eq, Show, Generic) 137 138 instance NFData HTLCOutputType 139 140 -- | The 'HTLCOutputType' of a bolt3 'OutputType', or 'Nothing' if 141 -- it isn't an HTLC output. 142 -- 143 -- >>> htlc_output_type OutputToLocal 144 -- Nothing 145 htlc_output_type :: OutputType -> Maybe HTLCOutputType 146 htlc_output_type t = case t of 147 OutputHTLC h -> Just $ case htlc_direction h of 148 HTLCOffered -> HTLCOfferedOutput (htlc_cltv_expiry h) 149 HTLCReceived -> HTLCReceivedOutput (htlc_cltv_expiry h) 150 OutputToLocal -> Nothing 151 OutputToRemote -> Nothing 152 OutputLocalAnchor -> Nothing 153 OutputRemoteAnchor -> Nothing 154 {-# INLINE htlc_output_type #-} 155 156 -- | Penalty input weight for an HTLC output. 157 -- 158 -- >>> htlc_output_type_weight Anchors (HTLCOfferedOutput (CltvExpiry 500)) 159 -- 410 160 htlc_output_type_weight :: CommitmentFormat -> HTLCOutputType -> Word64 161 htlc_output_type_weight !fmt !t = case (fmt, t) of 162 (StaticRemotekey, HTLCOfferedOutput _) -> 163 offered_htlc_penalty_input_weight 164 (StaticRemotekey, HTLCReceivedOutput _) -> 165 accepted_htlc_penalty_input_weight 166 (Anchors, HTLCOfferedOutput _) -> 167 offered_htlc_penalty_input_weight_anchors 168 (Anchors, HTLCReceivedOutput _) -> 169 accepted_htlc_penalty_input_weight_anchors 170 {-# INLINE htlc_output_type_weight #-} 171 172 -- spending transactions ---------------------------------------------- 173 174 -- | An unsigned spending transaction, with what the caller needs to 175 -- sign its (single) input. 176 -- 177 -- The caller signs the input's BIP143 sighash (ppad-tx's 178 -- @sighash_segwit@ over 'stx_tx', input 0, 'stx_input_script', 179 -- 'stx_input_value' and 'stx_sighash_type') and assembles the 180 -- witness with bolt3's witness functions. 181 data SpendingTx = SpendingTx 182 { stx_tx :: !Tx 183 -- ^ The unsigned transaction. 184 , stx_input_script :: !Script 185 -- ^ Witness script of the output being spent. 186 , stx_input_value :: {-# UNPACK #-} !Satoshi 187 -- ^ Value of the output being spent. 188 , stx_sighash_type :: !SighashType 189 -- ^ Sighash type of the local signature. 190 } deriving (Eq, Show, Generic) 191 192 instance NFData SpendingTx where 193 rnf (SpendingTx tx s v h) = rnf tx `seq` rnf s `seq` rnf v `seq` h `seq` () 194 195 -- revoked outputs ---------------------------------------------------- 196 197 -- | A revoked output that can be swept with a revocation key. 198 data RevokedOutput = RevokedOutput 199 { ro_outpoint :: !OutPoint 200 , ro_value :: {-# UNPACK #-} !Satoshi 201 , ro_type :: !RevokedOutputType 202 } deriving (Eq, Show, Generic) 203 204 instance NFData RevokedOutput 205 206 -- | What kind of revoked output is being swept. 207 data RevokedOutputType 208 = RevokedToLocal 209 -- ^ Revoked to_local output. 210 | RevokedHTLC !HTLCOutputType 211 -- ^ Revoked HTLC output. 212 deriving (Eq, Show, Generic) 213 214 instance NFData RevokedOutputType 215 216 -- | Penalty input weight for a revoked output. 217 revoked_output_weight :: CommitmentFormat -> RevokedOutput -> Word64 218 revoked_output_weight !fmt !ro = case ro_type ro of 219 RevokedToLocal -> 220 to_local_penalty_input_weight 221 RevokedHTLC !htype -> 222 htlc_output_type_weight fmt htype 223 {-# INLINE revoked_output_weight #-} 224 225 -- weight constants (BOLT #5 Appendix A) ------------------------------ 226 227 -- | Expected weight of the to_local penalty transaction witness 228 -- (160 weight units). 229 to_local_penalty_witness_weight :: Word64 230 to_local_penalty_witness_weight = 160 231 232 -- | Expected weight of the offered_htlc penalty transaction 233 -- witness (243 weight units), for a 133-byte witness script 234 -- (no option_anchors). 235 offered_htlc_penalty_witness_weight :: Word64 236 offered_htlc_penalty_witness_weight = 243 237 238 -- | Expected weight of the accepted_htlc penalty transaction 239 -- witness (249 weight units), for a 139-byte witness script 240 -- (no option_anchors). 241 accepted_htlc_penalty_witness_weight :: Word64 242 accepted_htlc_penalty_witness_weight = 249 243 244 -- | Expected weight of the offered_htlc penalty transaction 245 -- witness with option_anchors (246 weight units), whose witness 246 -- script is 136 bytes. 247 offered_htlc_penalty_witness_weight_anchors :: Word64 248 offered_htlc_penalty_witness_weight_anchors = 246 249 250 -- | Expected weight of the accepted_htlc penalty transaction 251 -- witness with option_anchors (252 weight units), whose witness 252 -- script is 142 bytes. 253 accepted_htlc_penalty_witness_weight_anchors :: Word64 254 accepted_htlc_penalty_witness_weight_anchors = 252 255 256 -- | Weight of a to_local penalty input (164 + 160 = 324). 257 to_local_penalty_input_weight :: Word64 258 to_local_penalty_input_weight = 324 259 260 -- | Weight of an offered_htlc penalty input (164 + 243 = 407). 261 offered_htlc_penalty_input_weight :: Word64 262 offered_htlc_penalty_input_weight = 407 263 264 -- | Weight of an accepted_htlc penalty input (164 + 249 = 413). 265 accepted_htlc_penalty_input_weight :: Word64 266 accepted_htlc_penalty_input_weight = 413 267 268 -- | Weight of an offered_htlc penalty input with option_anchors 269 -- (164 + 246 = 410). 270 offered_htlc_penalty_input_weight_anchors :: Word64 271 offered_htlc_penalty_input_weight_anchors = 410 272 273 -- | Weight of an accepted_htlc penalty input with option_anchors 274 -- (164 + 252 = 416). 275 accepted_htlc_penalty_input_weight_anchors :: Word64 276 accepted_htlc_penalty_input_weight_anchors = 416 277 278 -- | Weight of a to_remote P2WPKH input (108 + 164 = 272). 279 to_remote_input_weight :: Word64 280 to_remote_input_weight = 272 281 282 -- | Base weight of a penalty transaction (4 * 53 + 2 = 214). 283 -- 284 -- Non-witness: version (4) + input count (1) + output count (1) + 285 -- value (8) + script length (1) + P2WSH script (34) + locktime (4) 286 -- = 53 bytes. Witness header: 2 bytes. 287 -- 288 -- The spending transactions here use it as their base weight 289 -- whatever their destination script. 290 penalty_tx_base_weight :: Word64 291 penalty_tx_base_weight = 214 292 293 -- | Maximum standard transaction weight (400,000). 294 max_standard_weight :: Word64 295 max_standard_weight = 400000 296 297 -- fee calculation ---------------------------------------------------- 298 299 -- | The fee for a transaction of the given weight: 300 -- 301 -- @fee = feerate_per_kw * weight / 1000@ 302 -- 303 -- rounded down, and saturating at 21 million BTC. 304 -- 305 -- >>> spending_fee (FeeratePerKw 253) 324 306 -- Satoshi 81 307 spending_fee :: FeeratePerKw -> Word64 -> Satoshi 308 spending_fee (FeeratePerKw !rate) !weight = 309 let !f = toInteger rate * toInteger weight `quot` 1000 310 !m = BOLT1.un_satoshi BOLT1.max_satoshi 311 in case BOLT1.satoshi (fromInteger (min f (toInteger m))) of 312 Just s -> s 313 Nothing -> BOLT1.max_satoshi 314 {-# INLINE spending_fee #-}