Tx.hs (21374B)
1 {-# OPTIONS_HADDOCK hide #-} 2 {-# LANGUAGE BangPatterns #-} 3 {-# LANGUAGE DeriveGeneric #-} 4 5 -- | 6 -- Module: Lightning.Protocol.BOLT3.Tx 7 -- Copyright: (c) 2025 Jared Tobin 8 -- License: MIT 9 -- Maintainer: Jared Tobin <jared@ppad.tech> 10 -- 11 -- Commitment, HTLC and closing transactions, per BOLT #3. 12 13 module Lightning.Protocol.BOLT3.Tx ( 14 -- * Commitment transactions 15 CommitmentContext(..) 16 , CommitmentTx(..) 17 , CommitmentOutput(..) 18 , OutputType(..) 19 , build_commitment_tx 20 21 -- * HTLC transactions 22 , HTLCContext(..) 23 , HTLCTx(..) 24 , build_htlc_tx 25 26 -- * Closing transactions 27 , ClosingTx(..) 28 , ClosingOutput(..) 29 , ClosingContext(..) 30 , ClosingOutputs(..) 31 , build_closing_tx 32 , LegacyClosingContext(..) 33 , build_legacy_closing_tx 34 35 -- * Fees 36 , commitment_fee 37 , htlc_timeout_fee 38 , htlc_success_fee 39 40 -- * Trimming 41 , htlc_trim_threshold 42 , is_trimmed 43 44 -- * Serialization 45 , commitment_to_tx 46 , htlc_to_tx 47 , closing_to_tx 48 , encode_commitment_tx 49 , encode_htlc_tx 50 , encode_closing_tx 51 ) where 52 53 import Bitcoin.Prim.Tx (OutPoint(..), TxId) 54 import qualified Bitcoin.Prim.Tx as BT 55 import Control.DeepSeq (NFData) 56 import Data.Bits ((.&.), (.|.), shiftR) 57 import qualified Data.ByteString as BS 58 import Data.List (sortBy) 59 import Data.List.NonEmpty (NonEmpty(..)) 60 import qualified Data.List.NonEmpty as NE 61 import Data.Maybe (fromMaybe) 62 import Data.Word (Word32, Word64) 63 import GHC.Generics (Generic) 64 import Lightning.Protocol.BOLT1 (Satoshi, MilliSatoshi) 65 import qualified Lightning.Protocol.BOLT1 as BOLT1 66 import Lightning.Protocol.BOLT3.Keys 67 import Lightning.Protocol.BOLT3.Scripts 68 import Lightning.Protocol.BOLT3.Types 69 70 -- commitment transactions ---------------------------------------------------- 71 72 -- | What a commitment transaction output pays. 73 data OutputType 74 = OutputToLocal 75 | OutputToRemote 76 | OutputLocalAnchor 77 | OutputRemoteAnchor 78 | OutputHTLC !HTLC 79 -- ^ an offered or received HTLC (per its 'htlc_direction') 80 deriving (Eq, Show, Generic) 81 82 instance NFData OutputType 83 84 -- | A commitment transaction output. 85 data CommitmentOutput = CommitmentOutput 86 { co_value :: {-# UNPACK #-} !Satoshi 87 , co_script :: !Script -- ^ scriptPubKey 88 , co_type :: !OutputType 89 } deriving (Eq, Show, Generic) 90 91 instance NFData CommitmentOutput 92 93 -- | The parameters of a commitment transaction, from the point of view 94 -- of its owner (the "local" party, whose outputs are delayed). 95 data CommitmentContext = CommitmentContext 96 { cc_funding_outpoint :: {-# UNPACK #-} !OutPoint 97 , cc_commitment_number :: {-# UNPACK #-} !CommitmentNumber 98 , cc_local_payment_bp :: !PaymentBasepoint 99 -- ^ the owner's @payment_basepoint@ 100 , cc_remote_payment_bp :: !PaymentBasepoint 101 -- ^ the other party's @payment_basepoint@ 102 , cc_to_self_delay :: {-# UNPACK #-} !ToSelfDelay 103 -- ^ the delay on the owner's outputs (set by the other party) 104 , cc_dust_limit :: {-# UNPACK #-} !DustLimit 105 -- ^ the owner's @dust_limit_satoshis@ 106 , cc_feerate :: {-# UNPACK #-} !FeeratePerKw 107 , cc_format :: !CommitmentFormat 108 , cc_is_funder :: !Bool 109 -- ^ whether the owner opened the channel, and so pays the fee 110 , cc_to_local_msat :: {-# UNPACK #-} !MilliSatoshi 111 , cc_to_remote_msat :: {-# UNPACK #-} !MilliSatoshi 112 , cc_htlcs :: ![HTLC] 113 , cc_keys :: !CommitmentKeys 114 } deriving (Eq, Show, Generic) 115 116 instance NFData CommitmentContext 117 118 -- | An unsigned commitment transaction. 119 data CommitmentTx = CommitmentTx 120 { ctx_version :: {-# UNPACK #-} !Word32 121 , ctx_locktime :: {-# UNPACK #-} !Locktime 122 , ctx_input_outpoint :: {-# UNPACK #-} !OutPoint 123 , ctx_input_sequence :: {-# UNPACK #-} !Sequence 124 , ctx_outputs :: !(NonEmpty CommitmentOutput) 125 -- ^ in BIP69+CLTV order 126 , ctx_funding_script :: !Script 127 -- ^ the funding output's witness script, which signatures commit 128 -- to 129 } deriving (Eq, Show, Generic) 130 131 instance NFData CommitmentTx 132 133 -- | Build a commitment transaction, per BOLT #3's "Commitment 134 -- Transaction Construction": 135 -- 136 -- * the locktime and input sequence encode the obscured commitment 137 -- number (the payment basepoints are ordered by 'cc_is_funder'); 138 -- * HTLCs whose amount, less the HTLC transaction fee, is below the 139 -- dust limit are trimmed; 140 -- * the base fee (and under 'Anchors', both anchors) are taken from 141 -- the funder's output, which is left at zero if it can't cover 142 -- them; 143 -- * @to_local@ and @to_remote@ outputs below the dust limit are 144 -- omitted, and under 'Anchors' each party's anchor is added if its 145 -- output, or any HTLC output, exists; 146 -- * outputs are sorted by value, scriptPubKey and CLTV expiry. 147 -- 148 -- Fails if the transaction would have no outputs. 149 build_commitment_tx :: CommitmentContext -> Maybe CommitmentTx 150 build_commitment_tx ctx = do 151 outputs <- NE.nonEmpty . sort_outputs $ 152 to_local <> to_remote <> local_anchor <> remote_anchor <> htlcs 153 pure CommitmentTx 154 { ctx_version = 2 155 , ctx_locktime = 156 Locktime (0x20000000 .|. (fromIntegral obscured .&. 0xFFFFFF)) 157 , ctx_input_outpoint = cc_funding_outpoint ctx 158 , ctx_input_sequence = 159 Sequence 160 (0x80000000 .|. (fromIntegral (obscured `shiftR` 24) .&. 0xFFFFFF)) 161 , ctx_outputs = outputs 162 , ctx_funding_script = 163 funding_script (ck_local_funding keys) (ck_remote_funding keys) 164 } 165 where 166 !keys = cc_keys ctx 167 !fmt = cc_format ctx 168 !rate = cc_feerate ctx 169 !dust = cc_dust_limit ctx 170 DustLimit dust_sat = dust 171 172 (!opener, !accepter) 173 | cc_is_funder ctx = (cc_local_payment_bp ctx, cc_remote_payment_bp ctx) 174 | otherwise = (cc_remote_payment_bp ctx, cc_local_payment_bp ctx) 175 !obscured = 176 obscured_commitment_number opener accepter (cc_commitment_number ctx) 177 178 untrimmed = filter (not . is_trimmed dust rate fmt) (cc_htlcs ctx) 179 180 !fee = commitment_fee rate fmt (fromIntegral (length untrimmed)) 181 !deduction = case fmt of 182 StaticRemotekey -> fee 183 Anchors -> 184 fromMaybe BOLT1.max_satoshi (BOLT1.add_sat fee (sat 660)) 185 deduct s = fromMaybe (sat 0) (BOLT1.sub_sat s deduction) 186 187 !local_sat = BOLT1.msat_to_sat (cc_to_local_msat ctx) 188 !remote_sat = BOLT1.msat_to_sat (cc_to_remote_msat ctx) 189 (!to_local_sat, !to_remote_sat) 190 | cc_is_funder ctx = (deduct local_sat, remote_sat) 191 | otherwise = (local_sat, deduct remote_sat) 192 193 to_local = 194 [ CommitmentOutput to_local_sat 195 (to_p2wsh (to_local_script (ck_revocation_pubkey keys) 196 (cc_to_self_delay ctx) (ck_local_delayed keys))) 197 OutputToLocal 198 | to_local_sat >= dust_sat ] 199 200 to_remote = 201 [ CommitmentOutput to_remote_sat 202 (to_remote_script_pubkey (ck_remote_payment keys) fmt) 203 OutputToRemote 204 | to_remote_sat >= dust_sat ] 205 206 has_htlcs = not (null untrimmed) 207 anchor pk ty = CommitmentOutput anchor_output_value 208 (to_p2wsh (anchor_script pk)) ty 209 210 local_anchor = case fmt of 211 Anchors | not (null to_local) || has_htlcs -> 212 [anchor (ck_local_funding keys) OutputLocalAnchor] 213 _ -> [] 214 215 remote_anchor = case fmt of 216 Anchors | not (null to_remote) || has_htlcs -> 217 [anchor (ck_remote_funding keys) OutputRemoteAnchor] 218 _ -> [] 219 220 htlcs = fmap htlc_output untrimmed 221 222 htlc_output h = 223 let !script = case htlc_direction h of 224 HTLCOffered -> offered_htlc_script 225 (ck_revocation_pubkey keys) (ck_remote_htlc keys) 226 (ck_local_htlc keys) (htlc_payment_hash h) fmt 227 HTLCReceived -> received_htlc_script 228 (ck_revocation_pubkey keys) (ck_remote_htlc keys) 229 (ck_local_htlc keys) (htlc_payment_hash h) 230 (htlc_cltv_expiry h) fmt 231 in CommitmentOutput (BOLT1.msat_to_sat (htlc_amount_msat h)) 232 (to_p2wsh script) (OutputHTLC h) 233 234 -- BIP69+CLTV order: value, then scriptPubKey, then (for HTLCs) CLTV 235 -- expiry. 236 sort_outputs :: [CommitmentOutput] -> [CommitmentOutput] 237 sort_outputs = sortBy cmp where 238 cmp a b = compare (co_value a) (co_value b) 239 <> compare (co_script a) (co_script b) 240 <> compare (cltv (co_type a)) (cltv (co_type b)) 241 cltv t = case t of 242 OutputHTLC h -> Just (htlc_cltv_expiry h) 243 _ -> Nothing 244 245 -- HTLC transactions ---------------------------------------------------------- 246 247 -- | The parameters of an HTLC-success or HTLC-timeout transaction, 248 -- spending an HTLC output of the owner's commitment transaction. 249 data HTLCContext = HTLCContext 250 { hc_commitment_txid :: !TxId 251 , hc_output_index :: {-# UNPACK #-} !Word32 252 , hc_htlc :: !HTLC 253 , hc_to_self_delay :: {-# UNPACK #-} !ToSelfDelay 254 , hc_feerate :: {-# UNPACK #-} !FeeratePerKw 255 , hc_format :: !CommitmentFormat 256 , hc_revocation_pubkey :: !RevocationPubkey 257 , hc_local_delayed :: !LocalDelayedPubkey 258 } deriving (Eq, Show, Generic) 259 260 instance NFData HTLCContext 261 262 -- | An unsigned HTLC-success or HTLC-timeout transaction. 263 data HTLCTx = HTLCTx 264 { htx_version :: {-# UNPACK #-} !Word32 265 , htx_locktime :: {-# UNPACK #-} !Locktime 266 , htx_input_outpoint :: {-# UNPACK #-} !OutPoint 267 , htx_input_sequence :: {-# UNPACK #-} !Sequence 268 , htx_output_value :: {-# UNPACK #-} !Satoshi 269 , htx_output_script :: !Script 270 } deriving (Eq, Show, Generic) 271 272 instance NFData HTLCTx 273 274 -- | Build the second-stage transaction for an HTLC output of the 275 -- owner's commitment transaction: HTLC-timeout (locktime 276 -- @cltv_expiry@) for an offered HTLC, and HTLC-success (locktime 0) 277 -- for a received one. 278 -- 279 -- The output pays the HTLC amount, less the HTLC transaction fee 280 -- (zero under 'Anchors'), to the 'to_local_script' of the owner's 281 -- keys. Fails if the fee exceeds the amount (such an HTLC is always 282 -- trimmed). 283 build_htlc_tx :: HTLCContext -> Maybe HTLCTx 284 build_htlc_tx ctx = do 285 value <- BOLT1.sub_sat (BOLT1.msat_to_sat (htlc_amount_msat h)) fee 286 pure HTLCTx 287 { htx_version = 2 288 , htx_locktime = locktime 289 , htx_input_outpoint = 290 OutPoint (hc_commitment_txid ctx) (hc_output_index ctx) 291 , htx_input_sequence = case fmt of 292 StaticRemotekey -> Sequence 0 293 Anchors -> Sequence 1 294 , htx_output_value = value 295 , htx_output_script = to_p2wsh $ to_local_script 296 (hc_revocation_pubkey ctx) (hc_to_self_delay ctx) 297 (hc_local_delayed ctx) 298 } 299 where 300 !h = hc_htlc ctx 301 !fmt = hc_format ctx 302 (!fee, !locktime) = case htlc_direction h of 303 HTLCOffered -> 304 let CltvExpiry e = htlc_cltv_expiry h 305 in (htlc_timeout_fee (hc_feerate ctx) fmt, Locktime e) 306 HTLCReceived -> 307 (htlc_success_fee (hc_feerate ctx) fmt, Locktime 0) 308 309 -- closing transactions ------------------------------------------------------- 310 311 -- | A closing transaction output. 312 data ClosingOutput = ClosingOutput 313 { clo_value :: {-# UNPACK #-} !Satoshi 314 , clo_script :: !Script -- ^ scriptPubKey 315 } deriving (Eq, Show, Generic) 316 317 instance NFData ClosingOutput 318 319 -- | An unsigned closing transaction. 320 data ClosingTx = ClosingTx 321 { cltx_version :: {-# UNPACK #-} !Word32 322 , cltx_locktime :: {-# UNPACK #-} !Locktime 323 , cltx_input_outpoint :: {-# UNPACK #-} !OutPoint 324 , cltx_input_sequence :: {-# UNPACK #-} !Sequence 325 , cltx_outputs :: !(NonEmpty ClosingOutput) 326 -- ^ in BIP69 order 327 } deriving (Eq, Show, Generic) 328 329 instance NFData ClosingTx 330 331 -- | Which outputs an @option_simple_close@ closing transaction has, 332 -- matching the signature fields of @closing_complete@. 333 data ClosingOutputs 334 = CloserOutputOnly 335 | CloseeOutputOnly 336 | CloserAndCloseeOutputs 337 deriving (Eq, Show, Generic) 338 339 instance NFData ClosingOutputs 340 341 -- | The parameters of an @option_simple_close@ closing transaction, 342 -- as given by a @closing_complete@ message. 343 data ClosingContext = ClosingContext 344 { clc_funding_outpoint :: {-# UNPACK #-} !OutPoint 345 , clc_closer_msat :: {-# UNPACK #-} !MilliSatoshi 346 -- ^ the closer's final balance 347 , clc_closee_msat :: {-# UNPACK #-} !MilliSatoshi 348 -- ^ the closee's final balance 349 , clc_closer_script :: !Script 350 , clc_closee_script :: !Script 351 , clc_fee :: {-# UNPACK #-} !Satoshi 352 , clc_locktime :: {-# UNPACK #-} !Locktime 353 , clc_outputs :: !ClosingOutputs 354 } deriving (Eq, Show, Generic) 355 356 instance NFData ClosingContext 357 358 -- | Build an @option_simple_close@ closing transaction (BOLT #3's 359 -- "Closing Transaction"), for @closing_complete@ and @closing_sig@. 360 -- 361 -- The closer pays the fee: its output is its balance, rounded down 362 -- to whole satoshis, less the fee. An output whose scriptPubKey 363 -- starts with @OP_RETURN@ has amount 0. Only the chosen outputs are 364 -- included, and none is trimmed. Fails if the fee exceeds the 365 -- closer's balance. 366 build_closing_tx :: ClosingContext -> Maybe ClosingTx 367 build_closing_tx ctx = do 368 closer_sat <- 369 BOLT1.sub_sat (BOLT1.msat_to_sat (clc_closer_msat ctx)) (clc_fee ctx) 370 let !closer = output closer_sat (clc_closer_script ctx) 371 !closee = output (BOLT1.msat_to_sat (clc_closee_msat ctx)) 372 (clc_closee_script ctx) 373 pure ClosingTx 374 { cltx_version = 2 375 , cltx_locktime = clc_locktime ctx 376 , cltx_input_outpoint = clc_funding_outpoint ctx 377 , cltx_input_sequence = Sequence 0xFFFFFFFD 378 , cltx_outputs = case clc_outputs ctx of 379 CloserOutputOnly -> closer :| [] 380 CloseeOutputOnly -> closee :| [] 381 CloserAndCloseeOutputs -> sort_closing (closer :| [closee]) 382 } 383 where 384 output amt spk@(Script s) = case BS.uncons s of 385 Just (0x6a, _) -> ClosingOutput (sat 0) spk 386 _ -> ClosingOutput amt spk 387 388 -- | The parameters of a legacy closing transaction (for 389 -- @closing_signed@), from the point of view of the node producing 390 -- the signature (the "local" party). 391 data LegacyClosingContext = LegacyClosingContext 392 { lcc_funding_outpoint :: {-# UNPACK #-} !OutPoint 393 , lcc_local_msat :: {-# UNPACK #-} !MilliSatoshi 394 , lcc_remote_msat :: {-# UNPACK #-} !MilliSatoshi 395 , lcc_local_script :: !Script 396 , lcc_remote_script :: !Script 397 , lcc_dust_limit :: {-# UNPACK #-} !DustLimit 398 -- ^ the signer's @dust_limit_satoshis@ 399 , lcc_fee :: {-# UNPACK #-} !Satoshi 400 , lcc_is_funder :: !Bool 401 -- ^ whether the signer funded the channel, and so pays the fee 402 , lcc_omit_local :: !Bool 403 -- ^ whether the signer eliminates its own output 404 } deriving (Eq, Show, Generic) 405 406 instance NFData LegacyClosingContext 407 408 -- | Build a legacy closing transaction (BOLT #3's "Legacy Closing 409 -- Transaction"), for @closing_signed@. 410 -- 411 -- Balances are rounded down to whole satoshis and the fee is taken 412 -- from the funder's output. Outputs below the signer's dust limit 413 -- are removed, as is the signer's own output if 'lcc_omit_local' is 414 -- set. Fails if the fee exceeds the funder's balance, or if no 415 -- output remains. 416 build_legacy_closing_tx :: LegacyClosingContext -> Maybe ClosingTx 417 build_legacy_closing_tx ctx = do 418 let !local_sat = BOLT1.msat_to_sat (lcc_local_msat ctx) 419 !remote_sat = BOLT1.msat_to_sat (lcc_remote_msat ctx) 420 DustLimit dust = lcc_dust_limit ctx 421 (l, r) <- 422 if lcc_is_funder ctx 423 then fmap (\x -> (x, remote_sat)) (BOLT1.sub_sat local_sat fee) 424 else fmap (\x -> (local_sat, x)) (BOLT1.sub_sat remote_sat fee) 425 outputs <- NE.nonEmpty $ 426 [ ClosingOutput l (lcc_local_script ctx) 427 | not (lcc_omit_local ctx), l >= dust ] 428 <> [ ClosingOutput r (lcc_remote_script ctx) | r >= dust ] 429 pure ClosingTx 430 { cltx_version = 2 431 , cltx_locktime = Locktime 0 432 , cltx_input_outpoint = lcc_funding_outpoint ctx 433 , cltx_input_sequence = Sequence 0xFFFFFFFF 434 , cltx_outputs = sort_closing outputs 435 } 436 where 437 !fee = lcc_fee ctx 438 439 -- BIP69 order: value, then scriptPubKey. 440 sort_closing :: NonEmpty ClosingOutput -> NonEmpty ClosingOutput 441 sort_closing = NE.sortBy $ \a b -> 442 compare (clo_value a) (clo_value b) <> compare (clo_script a) (clo_script b) 443 444 -- fees ----------------------------------------------------------------------- 445 446 -- feerate * weight / 1000, saturating at 21 million BTC. 447 weight_fee :: FeeratePerKw -> Integer -> Satoshi 448 weight_fee (FeeratePerKw rate) weight = 449 let !f = toInteger rate * weight `quot` 1000 450 in if f > toInteger (BOLT1.un_satoshi BOLT1.max_satoshi) 451 then BOLT1.max_satoshi 452 else sat (fromInteger f) 453 454 -- | The base fee of a commitment transaction with a given number of 455 -- untrimmed HTLC outputs: 456 -- 457 -- @feerate_per_kw * (724 + 172 * num_htlcs) / 1000@ 458 -- 459 -- with a base weight of 1124 rather than 724 under 'Anchors'. 460 -- 461 -- >>> commitment_fee (FeeratePerKw 5000) StaticRemotekey 2 462 -- Satoshi 5340 463 commitment_fee :: FeeratePerKw -> CommitmentFormat -> Word64 -> Satoshi 464 commitment_fee rate fmt n = weight_fee rate (base + 172 * toInteger n) where 465 base = case fmt of 466 StaticRemotekey -> 724 467 Anchors -> 1124 468 469 -- | The fee of an HTLC-timeout transaction: @feerate_per_kw * 663 / 470 -- 1000@, or zero under 'Anchors'. 471 -- 472 -- >>> htlc_timeout_fee (FeeratePerKw 5000) StaticRemotekey 473 -- Satoshi 3315 474 htlc_timeout_fee :: FeeratePerKw -> CommitmentFormat -> Satoshi 475 htlc_timeout_fee rate fmt = case fmt of 476 StaticRemotekey -> weight_fee rate 663 477 Anchors -> sat 0 478 479 -- | The fee of an HTLC-success transaction: @feerate_per_kw * 703 / 480 -- 1000@, or zero under 'Anchors'. 481 -- 482 -- >>> htlc_success_fee (FeeratePerKw 5000) StaticRemotekey 483 -- Satoshi 3515 484 htlc_success_fee :: FeeratePerKw -> CommitmentFormat -> Satoshi 485 htlc_success_fee rate fmt = case fmt of 486 StaticRemotekey -> weight_fee rate 703 487 Anchors -> sat 0 488 489 -- trimming ------------------------------------------------------------------- 490 491 -- | The amount below which an HTLC in a given direction is trimmed: 492 -- the dust limit plus the fee of its HTLC transaction. 493 -- 494 -- >>> let Just d = fmap DustLimit (BOLT1.satoshi 546) 495 -- >>> htlc_trim_threshold d (FeeratePerKw 5000) StaticRemotekey HTLCOffered 496 -- Satoshi 3861 497 htlc_trim_threshold 498 :: DustLimit 499 -> FeeratePerKw 500 -> CommitmentFormat 501 -> HTLCDirection 502 -> Satoshi 503 htlc_trim_threshold (DustLimit dust) rate fmt dir = 504 let !fee = case dir of 505 HTLCOffered -> htlc_timeout_fee rate fmt 506 HTLCReceived -> htlc_success_fee rate fmt 507 in fromMaybe BOLT1.max_satoshi (BOLT1.add_sat dust fee) 508 509 -- | Whether an HTLC is trimmed from a commitment transaction: whether 510 -- its amount, rounded down to whole satoshis, is below 511 -- 'htlc_trim_threshold'. 512 is_trimmed :: DustLimit -> FeeratePerKw -> CommitmentFormat -> HTLC -> Bool 513 is_trimmed dust rate fmt h = 514 BOLT1.msat_to_sat (htlc_amount_msat h) 515 < htlc_trim_threshold dust rate fmt (htlc_direction h) 516 517 -- serialization -------------------------------------------------------------- 518 519 unsigned_tx 520 :: Word32 -> Locktime -> OutPoint -> Sequence -> NonEmpty BT.TxOut 521 -> BT.Tx 522 unsigned_tx version (Locktime lt) prevout (Sequence sq) outs = BT.Tx 523 { BT.tx_version = version 524 , BT.tx_inputs = BT.TxIn prevout BS.empty sq (BT.Witness []) :| [] 525 , BT.tx_outputs = outs 526 , BT.tx_locktime = lt 527 } 528 529 txout :: Satoshi -> Script -> BT.TxOut 530 txout v (Script s) = BT.TxOut (BOLT1.un_satoshi v) s 531 {-# INLINE txout #-} 532 533 -- | The unsigned commitment transaction as a ppad-tx 'BT.Tx' (with no 534 -- witnesses), e.g. for computing its txid or sighashes. 535 commitment_to_tx :: CommitmentTx -> BT.Tx 536 commitment_to_tx c = unsigned_tx (ctx_version c) (ctx_locktime c) 537 (ctx_input_outpoint c) (ctx_input_sequence c) 538 (fmap (\o -> txout (co_value o) (co_script o)) (ctx_outputs c)) 539 540 -- | The unsigned HTLC transaction as a ppad-tx 'BT.Tx'. 541 htlc_to_tx :: HTLCTx -> BT.Tx 542 htlc_to_tx h = unsigned_tx (htx_version h) (htx_locktime h) 543 (htx_input_outpoint h) (htx_input_sequence h) 544 (txout (htx_output_value h) (htx_output_script h) :| []) 545 546 -- | The unsigned closing transaction as a ppad-tx 'BT.Tx'. 547 closing_to_tx :: ClosingTx -> BT.Tx 548 closing_to_tx c = unsigned_tx (cltx_version c) (cltx_locktime c) 549 (cltx_input_outpoint c) (cltx_input_sequence c) 550 (fmap (\o -> txout (clo_value o) (clo_script o)) (cltx_outputs c)) 551 552 -- | Serialize an unsigned commitment transaction, without witness 553 -- data. This is the form whose double-SHA256 is the txid; it is not 554 -- what segwit signatures commit to (see ppad-tx's 555 -- @Bitcoin.Prim.Tx.Sighash@). To broadcast, attach the witness to 556 -- 'commitment_to_tx' and serialize with ppad-tx. 557 encode_commitment_tx :: CommitmentTx -> BS.ByteString 558 encode_commitment_tx = BT.to_bytes_legacy . commitment_to_tx 559 560 -- | Serialize an unsigned HTLC transaction, without witness data (cf. 561 -- 'encode_commitment_tx'). 562 encode_htlc_tx :: HTLCTx -> BS.ByteString 563 encode_htlc_tx = BT.to_bytes_legacy . htlc_to_tx 564 565 -- | Serialize an unsigned closing transaction, without witness data 566 -- (cf. 'encode_commitment_tx'). 567 encode_closing_tx :: ClosingTx -> BS.ByteString 568 encode_closing_tx = BT.to_bytes_legacy . closing_to_tx