From 0ea4378ce98ba3f780a00d1979f361957a5e6fe9 Mon Sep 17 00:00:00 2001 From: t-bast Date: Wed, 15 Jul 2020 15:38:46 +0200 Subject: [PATCH] Implement anchor outputs HTLC transactions Add support for HTLC transactions with a 1-block relative delay. Add missing anchor outputs spec tests. Add missing tests for some revoked paths. --- .../fr/acinq/eclair/channel/Commitments.scala | 2 +- .../fr/acinq/eclair/channel/Helpers.scala | 4 +- .../acinq/eclair/transactions/Scripts.scala | 15 +- .../eclair/transactions/Transactions.scala | 39 ++-- ...-tx-test-vectors-anchor-outputs-format.txt | 176 ++++++++++++++++- .../channel/states/h/ClosingStateSpec.scala | 2 +- .../eclair/integration/IntegrationSpec.scala | 6 +- .../eclair/transactions/TestVectorsSpec.scala | 187 ++++++++---------- .../transactions/TransactionsSpec.scala | 142 ++++++++++++- 9 files changed, 432 insertions(+), 141 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala index fe432e0afe..12fb953819 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala @@ -540,7 +540,7 @@ object Commitments { // combine the sigs to make signed txes val htlcTxsAndSigs = (sortedHtlcTxs, htlcSigs, commit.htlcSignatures).zipped.toList.collect { case (htlcTx: HtlcTimeoutTx, localSig, remoteSig) => - if (Transactions.checkSpendable(Transactions.addSigs(htlcTx, localSig, remoteSig)).isFailure) { + if (Transactions.checkSpendable(Transactions.addSigs(htlcTx, localSig, remoteSig, commitmentFormat)).isFailure) { throw InvalidHtlcSignature(commitments.channelId, htlcTx.tx) } HtlcTxAndSigs(htlcTx, localSig, remoteSig) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala index 9095df96a4..1c964c9d8b 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala @@ -545,7 +545,7 @@ object Helpers { case HtlcTxAndSigs(txinfo@HtlcSuccessTx(_, _, paymentHash), localSig, remoteSig) if preimages.exists(r => sha256(r) == paymentHash) => generateTx("htlc-success") { val preimage = preimages.find(r => sha256(r) == paymentHash).get - Right(Transactions.addSigs(txinfo, localSig, remoteSig, preimage)) + Right(Transactions.addSigs(txinfo, localSig, remoteSig, preimage, commitmentFormat)) } // (incoming htlc for which we don't have the preimage: nothing to do, it will timeout eventually and they will get their funds back) @@ -553,7 +553,7 @@ object Helpers { // outgoing htlc: they may or may not have the preimage, the only thing to do is try to get back our funds after timeout case HtlcTxAndSigs(txinfo: HtlcTimeoutTx, localSig, remoteSig) => generateTx("htlc-timeout") { - Right(Transactions.addSigs(txinfo, localSig, remoteSig)) + Right(Transactions.addSigs(txinfo, localSig, remoteSig, commitmentFormat)) } }.flatten diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala index b46d68df6e..e27280890a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala @@ -34,7 +34,12 @@ object Scripts { * @param sig raw ECDSA signature (r,s) * @param sighash sighash flags */ - def der(sig: ByteVector64, sighash: Byte = SIGHASH_ALL.toByte): ByteVector = Crypto.compact2der(sig) :+ sighash + def der(sig: ByteVector64, sighash: Int = SIGHASH_ALL): ByteVector = Crypto.compact2der(sig) :+ sighash.toByte + + def htlcRemoteSighash(commitmentFormat: CommitmentFormat): Int = commitmentFormat match { + case DefaultCommitmentFormat => SIGHASH_ALL + case AnchorOutputsCommitmentFormat => SIGHASH_SINGLE | SIGHASH_ANYONECANPAY + } def multiSig2of2(pubkey1: PublicKey, pubkey2: PublicKey): Seq[ScriptElt] = if (LexicographicalOrdering.isLessThan(pubkey1.value, pubkey2.value)) { @@ -200,8 +205,8 @@ object Scripts { /** * This is the witness script of the 2nd-stage HTLC Success transaction (consumes htlcOffered script from commit tx) */ - def witnessHtlcSuccess(localSig: ByteVector64, remoteSig: ByteVector64, paymentPreimage: ByteVector32, htlcOfferedScript: ByteVector) = - ScriptWitness(ByteVector.empty :: der(remoteSig) :: der(localSig) :: paymentPreimage.bytes :: htlcOfferedScript :: Nil) + def witnessHtlcSuccess(localSig: ByteVector64, remoteSig: ByteVector64, paymentPreimage: ByteVector32, htlcOfferedScript: ByteVector, commitmentFormat: CommitmentFormat) = + ScriptWitness(ByteVector.empty :: der(remoteSig, htlcRemoteSighash(commitmentFormat)) :: der(localSig) :: paymentPreimage.bytes :: htlcOfferedScript :: Nil) /** Extract the payment preimage from a 2nd-stage HTLC Success transaction's witness script */ def extractPreimageFromHtlcSuccess: PartialFunction[ScriptWitness, ByteVector32] = { @@ -253,8 +258,8 @@ object Scripts { /** * This is the witness script of the 2nd-stage HTLC Timeout transaction (consumes htlcOffered script from commit tx) */ - def witnessHtlcTimeout(localSig: ByteVector64, remoteSig: ByteVector64, htlcOfferedScript: ByteVector) = - ScriptWitness(ByteVector.empty :: der(remoteSig) :: der(localSig) :: ByteVector.empty :: htlcOfferedScript :: Nil) + def witnessHtlcTimeout(localSig: ByteVector64, remoteSig: ByteVector64, htlcOfferedScript: ByteVector, commitmentFormat: CommitmentFormat) = + ScriptWitness(ByteVector.empty :: der(remoteSig, htlcRemoteSighash(commitmentFormat)) :: der(localSig) :: ByteVector.empty :: htlcOfferedScript :: Nil) /** Extract the payment hash from a 2nd-stage HTLC Timeout transaction's witness script */ def extractPaymentHashFromHtlcTimeout: PartialFunction[ScriptWitness, ByteVector] = { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala index 0a03ff21e5..f086c518e9 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala @@ -235,6 +235,11 @@ object Transactions { def decodeTxNumber(sequence: Long, locktime: Long): Long = ((sequence & 0xffffffL) << 24) + (locktime & 0xffffffL) + def getHtlcTxInputSequence(commitmentFormat: CommitmentFormat): Long = commitmentFormat match { + case DefaultCommitmentFormat => 0 // htlc txs immediately spend the commit tx + case AnchorOutputsCommitmentFormat => 1 // htlc txs have a 1-block delay to allow CPFP carve-out on anchors + } + /** * Represent a link between a commitment spec item (to-local, to-remote, anchors, htlc) and the actual output in the commit tx * @@ -374,7 +379,7 @@ object Transactions { val input = InputInfo(OutPoint(commitTx, outputIndex), commitTx.txOut(outputIndex), write(redeemScript)) Right(HtlcTimeoutTx(input, Transaction( version = 2, - txIn = TxIn(input.outPoint, ByteVector.empty, 0x00000000L) :: Nil, + txIn = TxIn(input.outPoint, ByteVector.empty, getHtlcTxInputSequence(commitmentFormat)) :: Nil, txOut = TxOut(amount, pay2wsh(toLocalDelayed(localRevocationPubkey, toLocalDelay, localDelayedPaymentPubkey))) :: Nil, lockTime = htlc.cltvExpiry.toLong))) } @@ -399,7 +404,7 @@ object Transactions { val input = InputInfo(OutPoint(commitTx, outputIndex), commitTx.txOut(outputIndex), write(redeemScript)) Right(HtlcSuccessTx(input, Transaction( version = 2, - txIn = TxIn(input.outPoint, ByteVector.empty, 0x00000000L) :: Nil, + txIn = TxIn(input.outPoint, ByteVector.empty, getHtlcTxInputSequence(commitmentFormat)) :: Nil, txOut = TxOut(amount, pay2wsh(toLocalDelayed(localRevocationPubkey, toLocalDelay, localDelayedPaymentPubkey))) :: Nil, lockTime = 0), htlc.paymentHash)) } @@ -442,9 +447,13 @@ object Transactions { } match { case Some(outputIndex) => val input = InputInfo(OutPoint(commitTx, outputIndex), commitTx.txOut(outputIndex), write(redeemScript)) + val sequence = commitmentFormat match { + case DefaultCommitmentFormat => 0xffffffffL // RBF disabled + case AnchorOutputsCommitmentFormat => 1 // txs have a 1-block delay to allow CPFP carve-out on anchors + } val tx = Transaction( version = 2, - txIn = TxIn(input.outPoint, ByteVector.empty, 0xffffffffL) :: Nil, + txIn = TxIn(input.outPoint, ByteVector.empty, sequence) :: Nil, txOut = TxOut(Satoshi(0), localFinalScriptPubKey) :: Nil, lockTime = 0) val weight = addSigs(ClaimHtlcSuccessTx(input, tx), PlaceHolderSig, ByteVector32.Zeroes).tx.weight() @@ -479,7 +488,7 @@ object Transactions { // unsigned tx val tx = Transaction( version = 2, - txIn = TxIn(input.outPoint, ByteVector.empty, 0x00000000L) :: Nil, + txIn = TxIn(input.outPoint, ByteVector.empty, getHtlcTxInputSequence(commitmentFormat)) :: Nil, txOut = TxOut(Satoshi(0), localFinalScriptPubKey) :: Nil, lockTime = htlc.cltvExpiry.toLong) val weight = addSigs(ClaimHtlcTimeoutTx(input, tx), PlaceHolderSig).tx.weight() @@ -590,13 +599,13 @@ object Transactions { } } - def makeClaimDelayedOutputPenaltyTx(commitTx: Transaction, localDustLimit: Satoshi, localRevocationPubkey: PublicKey, toLocalDelay: CltvExpiryDelta, localDelayedPaymentPubkey: PublicKey, localFinalScriptPubKey: ByteVector, feeratePerKw: Long): Either[TxGenerationSkipped, ClaimDelayedOutputPenaltyTx] = { + def makeClaimDelayedOutputPenaltyTx(htlcTx: Transaction, localDustLimit: Satoshi, localRevocationPubkey: PublicKey, toLocalDelay: CltvExpiryDelta, localDelayedPaymentPubkey: PublicKey, localFinalScriptPubKey: ByteVector, feeratePerKw: Long): Either[TxGenerationSkipped, ClaimDelayedOutputPenaltyTx] = { val redeemScript = toLocalDelayed(localRevocationPubkey, toLocalDelay, localDelayedPaymentPubkey) val pubkeyScript = write(pay2wsh(redeemScript)) - findPubKeyScriptIndex(commitTx, pubkeyScript, amount_opt = None) match { + findPubKeyScriptIndex(htlcTx, pubkeyScript, amount_opt = None) match { case Left(skip) => Left(skip) case Right(outputIndex) => - val input = InputInfo(OutPoint(commitTx, outputIndex), commitTx.txOut(outputIndex), write(redeemScript)) + val input = InputInfo(OutPoint(htlcTx, outputIndex), htlcTx.txOut(outputIndex), write(redeemScript)) // unsigned transaction val tx = Transaction( version = 2, @@ -708,15 +717,15 @@ object Transactions { val PlaceHolderSig = ByteVector64(ByteVector.fill(64)(0xaa)) assert(der(PlaceHolderSig).size == 72) - def sign(tx: Transaction, inputIndex: Int, redeemScript: ByteVector, amount: Satoshi, key: PrivateKey): ByteVector64 = { - val sigDER = Transaction.signInput(tx, inputIndex, redeemScript, SIGHASH_ALL, amount, SIGVERSION_WITNESS_V0, key) + private def sign(tx: Transaction, redeemScript: ByteVector, amount: Satoshi, key: PrivateKey, sighashType: Int): ByteVector64 = { + val sigDER = Transaction.signInput(tx, inputIndex = 0, redeemScript, sighashType, amount, SIGVERSION_WITNESS_V0, key) val sig64 = Crypto.der2compact(sigDER) sig64 } - def sign(txinfo: TransactionWithInputInfo, key: PrivateKey): ByteVector64 = { + def sign(txinfo: TransactionWithInputInfo, key: PrivateKey, sighashType: Int = SIGHASH_ALL): ByteVector64 = { require(txinfo.tx.txIn.lengthCompare(1) == 0, "only one input allowed") - sign(txinfo.tx, inputIndex = 0, txinfo.input.redeemScript, txinfo.input.txOut.amount, key) + sign(txinfo.tx, txinfo.input.redeemScript, txinfo.input.txOut.amount, key, sighashType) } def addSigs(commitTx: CommitTx, localFundingPubkey: PublicKey, remoteFundingPubkey: PublicKey, localSig: ByteVector64, remoteSig: ByteVector64): CommitTx = { @@ -734,13 +743,13 @@ object Transactions { htlcPenaltyTx.copy(tx = htlcPenaltyTx.tx.updateWitness(0, witness)) } - def addSigs(htlcSuccessTx: HtlcSuccessTx, localSig: ByteVector64, remoteSig: ByteVector64, paymentPreimage: ByteVector32): HtlcSuccessTx = { - val witness = witnessHtlcSuccess(localSig, remoteSig, paymentPreimage, htlcSuccessTx.input.redeemScript) + def addSigs(htlcSuccessTx: HtlcSuccessTx, localSig: ByteVector64, remoteSig: ByteVector64, paymentPreimage: ByteVector32, commitmentFormat: CommitmentFormat): HtlcSuccessTx = { + val witness = witnessHtlcSuccess(localSig, remoteSig, paymentPreimage, htlcSuccessTx.input.redeemScript, commitmentFormat) htlcSuccessTx.copy(tx = htlcSuccessTx.tx.updateWitness(0, witness)) } - def addSigs(htlcTimeoutTx: HtlcTimeoutTx, localSig: ByteVector64, remoteSig: ByteVector64): HtlcTimeoutTx = { - val witness = witnessHtlcTimeout(localSig, remoteSig, htlcTimeoutTx.input.redeemScript) + def addSigs(htlcTimeoutTx: HtlcTimeoutTx, localSig: ByteVector64, remoteSig: ByteVector64, commitmentFormat: CommitmentFormat): HtlcTimeoutTx = { + val witness = witnessHtlcTimeout(localSig, remoteSig, htlcTimeoutTx.input.redeemScript, commitmentFormat) htlcTimeoutTx.copy(tx = htlcTimeoutTx.tx.updateWitness(0, witness)) } diff --git a/eclair-core/src/test/resources/bolt3-tx-test-vectors-anchor-outputs-format.txt b/eclair-core/src/test/resources/bolt3-tx-test-vectors-anchor-outputs-format.txt index d4a869b19e..39fb4fed9e 100644 --- a/eclair-core/src/test/resources/bolt3-tx-test-vectors-anchor-outputs-format.txt +++ b/eclair-core/src/test/resources/bolt3-tx-test-vectors-anchor-outputs-format.txt @@ -6,10 +6,184 @@ output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80044a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a508b6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004830450221008266ac6db5ea71aac3c95d97b0e172ff596844851a3216eb88382a8dddfd33d2022050e240974cfd5d708708b4365574517c18e7ae535ef732a3484d43d0d82be9f701483045022100f89034eba16b2be0e5581f750a0a6309192b75cce0f202f0ee2b4ec0cc394850022076c65dc507fe42276152b7a3d90e961e678adbe966e916ecfe85e64d430e75f301475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 num_htlcs: 0 + name: commitment tx with all five HTLCs untrimmed (minimum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 0 + remote_signature = 3044022076a51aed1bd085487a7023f2ca8a87544a60a5b7277805b614b6ff7d36f1a44c02207ffac246b6572f3b4c9a7867ffa97c203500eebbf14659df78cfa0fadea22a64 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80094a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994e80300000000000022002010f88bf09e56f14fb4543fd26e47b0db50ea5de9cf3fc46434792471082621aed0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a4c9e6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100cf8f902751006923e4062f5dbf55f8475bef08f4b5ac060d219bbff6c1a4431b02206006c515754ffc1f4f263004f61082e1fe4241449629da9096b0679e7e30972201473044022076a51aed1bd085487a7023f2ca8a87544a60a5b7277805b614b6ff7d36f1a44c02207ffac246b6572f3b4c9a7867ffa97c203500eebbf14659df78cfa0fadea22a6401475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 5 + remote_htlc_signature = 30440220627339df18b9a37bc829385f6f0267b33e94c07fdf0fce3f1697ad1c67eefc6e022012edb8c003bb4977b083d30ccda0101bf669a25846a3a7e5a0cdd8bfb5ad8234 + remote_htlc_signature = 304402206b238b1841ac5cd26a908da773bd4a000bd5ab3ef2d7bb266887043f0b9e42e0022029a9573aa23c82123e5a6d475462e2e0e8e2ea034a0bf6563cb3853068645519 + remote_htlc_signature = 30440220349215b20045e7ecb1ffc52a34e9d8fb4eed2efbd0bdafd710bfee84f03fa9630220386c0c7b103891a849f019d11e8a26397bc204e4b90998a849a6c956b0160ca0 + remote_htlc_signature = 3045022100e1720474cf9542f10355e7c7e036f6c9679bae9689816fb1db4fefabc8ad0a3d02201815d326838754cbc088d65191f28cd22052d6957a71d9ed9ca5701fcee76e3f + remote_htlc_signature = 3045022100a2a5fd584d6af9e99d06b9d707e1a349abe7022187eb9d913fa6f55f51ea452102201bbb856d4ed73801014d7bec50e3b66547f4db46e9d29609828b42e1975552d6 + output htlc_success_tx 0: 020000000001017fcd67e09cd17d77b0a6015221bc45cee4281a42844581cc1df60415e7f2675c02000000000100000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220627339df18b9a37bc829385f6f0267b33e94c07fdf0fce3f1697ad1c67eefc6e022012edb8c003bb4977b083d30ccda0101bf669a25846a3a7e5a0cdd8bfb5ad8234834830450221008b46dbb4df7f0e386d2ab2a1c5251bc502c8e9e4a35cd9e2be7134e4af9c82920220606a8a147419e98f4c9b074150283734e73a1920f91621eefb2ceabf5e903f2b012000000000000000000000000000000000000000000000000000000000000000008d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac6851b2756800000000 + output htlc_timeout_tx 2: 020000000001017fcd67e09cd17d77b0a6015221bc45cee4281a42844581cc1df60415e7f2675c03000000000100000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206b238b1841ac5cd26a908da773bd4a000bd5ab3ef2d7bb266887043f0b9e42e0022029a9573aa23c82123e5a6d475462e2e0e8e2ea034a0bf6563cb385306864551983483045022100d594933496f92fe7d48c850d0cd7a8093dade88ea0bda055c7750c6474c5c5ef0220363024530f2312c8951b6aa6a27f0d7993db2f1a4d44dc23a5174b800454d72b01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000 + output htlc_success_tx 1: 020000000001017fcd67e09cd17d77b0a6015221bc45cee4281a42844581cc1df60415e7f2675c04000000000100000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220349215b20045e7ecb1ffc52a34e9d8fb4eed2efbd0bdafd710bfee84f03fa9630220386c0c7b103891a849f019d11e8a26397bc204e4b90998a849a6c956b0160ca08347304402203904ca53c086253377bd0154084c8d959eff373bb88bb45f15951e24dc4d30910220722d813636890223a7d682b13166d8ce55216caefea07ff67307475ef9a6ccf2012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000 + output htlc_timeout_tx 3: 020000000001017fcd67e09cd17d77b0a6015221bc45cee4281a42844581cc1df60415e7f2675c05000000000100000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e1720474cf9542f10355e7c7e036f6c9679bae9689816fb1db4fefabc8ad0a3d02201815d326838754cbc088d65191f28cd22052d6957a71d9ed9ca5701fcee76e3f8346304302207b24b990da8b2a872199fa0633cc7af06d924db79e18b3451b497cc1b32db44f021f363aeaa5345e0768e40535811e5fe360cbdbb077963d1e506255ee798c323401008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 020000000001017fcd67e09cd17d77b0a6015221bc45cee4281a42844581cc1df60415e7f2675c06000000000100000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100a2a5fd584d6af9e99d06b9d707e1a349abe7022187eb9d913fa6f55f51ea452102201bbb856d4ed73801014d7bec50e3b66547f4db46e9d29609828b42e1975552d68348304502210086a2bc2a62fd5c2ab1823d9e66a0cb57fb4ff363ddae9792c8fe323656b6bf1a022044a543323209ca8c52b7d842e101358f4afde218c7809630f6dbeb0b99933633012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with seven outputs untrimmed (maximum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 644 + remote_signature = 3045022100e0106830467a558c07544a3de7715610c1147062e7d091deeebe8b5c661cda9402202ad049c1a6d04834317a78483f723c205c9f638d17222aafc620800cc1b6ae35 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80094a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994e80300000000000022002010f88bf09e56f14fb4543fd26e47b0db50ea5de9cf3fc46434792471082621aed0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a4f996a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100ef82a405364bfc4007e63a7cc82925a513d79065bdbc216d60b6a4223a323f8a02200716730b8561f3c6d362eaf47f202e99fb30d0557b61b92b5f9134f8e2de368101483045022100e0106830467a558c07544a3de7715610c1147062e7d091deeebe8b5c661cda9402202ad049c1a6d04834317a78483f723c205c9f638d17222aafc620800cc1b6ae3501475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 5 + remote_htlc_signature = 304402205912d91c58016f593d9e46fefcdb6f4125055c41a17b03101eaaa034b9028ab60220520d4d239c85c66e4c75c5b413620b62736e227659d7821b308e2b8ced3e728e + remote_htlc_signature = 3045022100c6b4113678039ee1e43a6cba5e3224ed2355ffc05e365a393afe8843dc9a76860220566d01fd52d65a89ba8595023884f9e8f2e9a310a6b9b85281c0bce06863430c + remote_htlc_signature = 304402203c3a699fb80a38112aafd73d6e3a9b7d40bc2c3ed8b7fbc182a20f43b215172202204e71821b984d1af52c4b8e2cd4c572578c12a965866130c2345f61e4c2d3fef4 + remote_htlc_signature = 304402200f089bcd20f25475216307d32aa5b6c857419624bfba1da07335f51f6ba4645b02206ce0f7153edfba23b0d4b2afc26bb3157d404368cb8ea0ca7cf78590dcdd28cf + remote_htlc_signature = 3045022100aa72cfaf0965020c73a12c77276c6411ca68c4de36ac1998adf86c917a899a43022060da0a159fecfe0bed37c3962d767f12f90e30fed8a8f34b1301775c21a2bd3a + output htlc_success_tx 0: 02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a0200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402205912d91c58016f593d9e46fefcdb6f4125055c41a17b03101eaaa034b9028ab60220520d4d239c85c66e4c75c5b413620b62736e227659d7821b308e2b8ced3e728e834730440220473166a5adcca68550bab80403f410a726b5bd855030527e3fefa8c1e4b4fd7b02203b1dc91d8d69039473036cb5c34398b99e8eb90ae500c22130a557b62294b188012000000000000000000000000000000000000000000000000000000000000000008d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac6851b2756800000000 + output htlc_timeout_tx 2: 02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a0300000000010000000124060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100c6b4113678039ee1e43a6cba5e3224ed2355ffc05e365a393afe8843dc9a76860220566d01fd52d65a89ba8595023884f9e8f2e9a310a6b9b85281c0bce06863430c83483045022100d0d86307ea55d5daa80f453ad6d64b78fe8a6504aac25407c73e8502c0702c1602206a0809a02aa00c8dc4a53d976bb05d4605d8bb0b7b26b973a5c4e2734d8afbb401008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000 + output htlc_success_tx 1: 02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a040000000001000000010a060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402203c3a699fb80a38112aafd73d6e3a9b7d40bc2c3ed8b7fbc182a20f43b215172202204e71821b984d1af52c4b8e2cd4c572578c12a965866130c2345f61e4c2d3fef48347304402205bcfa92f83c69289a412b0b6dd4f2a0fe0b0fc2d45bd74706e963257a09ea24902203783e47883e60b86240e877fcbf33d50b1742f65bc93b3162d1be26583b367ee012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000 + output htlc_timeout_tx 3: 02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a050000000001000000010c0a0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402200f089bcd20f25475216307d32aa5b6c857419624bfba1da07335f51f6ba4645b02206ce0f7153edfba23b0d4b2afc26bb3157d404368cb8ea0ca7cf78590dcdd28cf83483045022100e4516da08f72c7a4f7b2f37aa84a0feb54ae2cc5b73f0da378e81ae0ca8119bf02207751b2628d8e2f62b4b9abccda4866246c1bfcc82e3d416ad562fd212102c28f01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a06000000000100000001da0d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100aa72cfaf0965020c73a12c77276c6411ca68c4de36ac1998adf86c917a899a43022060da0a159fecfe0bed37c3962d767f12f90e30fed8a8f34b1301775c21a2bd3a8347304402203cd12065c2a42963c762e6b1a981e17695616ecb6f9fb33d8b0717cdd7ca0ee4022065500005c491c1dcf2fe9c4024f74b1c90785d572527055a491278f901143904012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with six outputs untrimmed (minimum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 645 + remote_signature = 3044022025d97466c8049e955a5afce28e322f4b34d2561118e52332fb400f9b908cc0a402205dc6fba3a0d67ee142c428c535580cd1f2ff42e2f89b47e0c8a01847caffc312 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80084a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994abc996a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100d57697c707b6f6d053febf24b98e8989f186eea42e37e9e91663ec2c70bb8f70022079b0715a472118f262f43016a674f59c015d9cafccec885968e76d9d9c5d005101473044022025d97466c8049e955a5afce28e322f4b34d2561118e52332fb400f9b908cc0a402205dc6fba3a0d67ee142c428c535580cd1f2ff42e2f89b47e0c8a01847caffc31201475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 4 + remote_htlc_signature = 30440220446f9e5c375db6a61d6eeee8b59219a30a4a37372afc2670a1a2889c78e9b943022061895f6088fb48b490ab2140a4842c277b64bf25ff591625dd0356e0c96ab7a8 + remote_htlc_signature = 3044022027a3ffcb8a007e3349d75382efbd4b3fb99fcbd479a18555e58697bd1278d5c402205c8303d46211c3ae8975fe84a0df08b4623119fecd03bc93b49d7f7a0c64c710 + remote_htlc_signature = 30440220013975ae356e6daf22a86a29f21c4f35aca82ed8f731a1103c60c74f5ed1c5aa02200350d4e5455cdbcacb7ccf174db5bed8286019e509a113f6b4c5e606ee12c9d7 + remote_htlc_signature = 304402205257017423644c7e831f30bc0c334eecfe66e9a6d2e92d157c5bece576b2be4f022047b21cf8e955e22b7471940563922d1a5852fb95459ca32905c7d46a19141664 + output htlc_timeout_tx 2: 02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b28534856132000200000000010000000123060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220446f9e5c375db6a61d6eeee8b59219a30a4a37372afc2670a1a2889c78e9b943022061895f6088fb48b490ab2140a4842c277b64bf25ff591625dd0356e0c96ab7a883483045022100c1621ba26a99c263fd885feff5fda5ca2cc73df080b3a49ecf15164ee244d2a5022037f4cc7fd4441af39a83a0e44c3b1db7d64a4c8080e8697f9e952f85421a34d801008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000 + output htlc_success_tx 1: 02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b28534856132000300000000010000000109060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022027a3ffcb8a007e3349d75382efbd4b3fb99fcbd479a18555e58697bd1278d5c402205c8303d46211c3ae8975fe84a0df08b4623119fecd03bc93b49d7f7a0c64c71083483045022100b697aca55c6fb15e5348bb7387b584815fd15e8dd306afe0c477cb550d0c2d40022050b0f7e370f7604d2fec781fefe86715dbe95dff4dab88d628f509d62f854de1012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000 + output htlc_timeout_tx 3: 02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b2853485613200040000000001000000010b0a0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220013975ae356e6daf22a86a29f21c4f35aca82ed8f731a1103c60c74f5ed1c5aa02200350d4e5455cdbcacb7ccf174db5bed8286019e509a113f6b4c5e606ee12c9d783483045022100e69a29f78779577830e73f327073c93168896f1b89432124b7846f5def9cd9cb02204433db3697e6ed7ac89574ca066a749640e0c9e114ac2e0ee4545741fcf7b7e901008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b285348561320005000000000100000001d90d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402205257017423644c7e831f30bc0c334eecfe66e9a6d2e92d157c5bece576b2be4f022047b21cf8e955e22b7471940563922d1a5852fb95459ca32905c7d46a191416648347304402204f5de65a624e3f757adffb678bd887eb4e656538c5ea7044922f6ee3eed8a06202206ff6f7bfe73b565343cae76131ac658f1a9c60d3ca2343358cda60b9e35f94c8012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with six outputs untrimmed (maximum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 2060 + remote_signature = 304402206208aeb34e404bd052ce3f298dfa832891c9d42caec99fe2a0d2832e9690b94302201b034bfcc6fa9faec667a9b7cbfe0b8d85e954aa239b66277887b5088aff08c3 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80084a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994ab88f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402201ce37a44b95213358c20f44404d6db7a6083bea6f58de6c46547ae41a47c9f8202206db1d45be41373e92f90d346381febbea8c78671b28c153e30ad1db3441a94970147304402206208aeb34e404bd052ce3f298dfa832891c9d42caec99fe2a0d2832e9690b94302201b034bfcc6fa9faec667a9b7cbfe0b8d85e954aa239b66277887b5088aff08c301475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 4 + remote_htlc_signature = 30440220011f999016570bbab9f3125377d0f35096b4dbe155f97c20f71829ead2817d1602201f23f7e17f6928734601c5d8613431eed5c90aa41c3106e8c1cb02ce32aacb5d + remote_htlc_signature = 304402202d2d9681409b0a0987bd4a268ffeb112df85c4c988ac2a3a2475cb00a61912c302206aa4f4d1388b7d3282bc847871af3cca30766cc8f1064e3a41ec7e82221e10f7 + remote_htlc_signature = 3045022100f51cdaa525b7d4304548c642bb7945215eb5ae7d32874517cde67ca23ab0a12202206286d59e4b19926c6ac844be6f3ab8149a1ddb9c70f5026b7e83e40a6c08e6e1 + remote_htlc_signature = 304402202f058d99cb5a54f90773d43ba4e7a0089efd9f8269ef2da1b85d48a3e230555402205acc4bd6561830867d45cd7b84bba9fa35ad2b345016471c1737142bc99782c4 + output htlc_timeout_tx 2: 02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d0200000000010000000175020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220011f999016570bbab9f3125377d0f35096b4dbe155f97c20f71829ead2817d1602201f23f7e17f6928734601c5d8613431eed5c90aa41c3106e8c1cb02ce32aacb5d83473044022017da96dfb0eb4061fa0162dc6fa6b2e07ecc5040ab5e6cb07be59838460b3e58022079371ffc95002cc1dc2891ec38198c9c25aca8164304fe114f1b55e2ffd1ddd501008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000 + output htlc_success_tx 1: 02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d0300000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202d2d9681409b0a0987bd4a268ffeb112df85c4c988ac2a3a2475cb00a61912c302206aa4f4d1388b7d3282bc847871af3cca30766cc8f1064e3a41ec7e82221e10f78347304402206426d67911aa6ff9b1cb147b093f3f65a37831a86d7c741d999afc0666e1773d022000bb71821650c70ea58d9bcdd03af736c41a5a8159d436c3ee0408a07394dcce012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000 + output htlc_timeout_tx 3: 02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d040000000001000000015d060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100f51cdaa525b7d4304548c642bb7945215eb5ae7d32874517cde67ca23ab0a12202206286d59e4b19926c6ac844be6f3ab8149a1ddb9c70f5026b7e83e40a6c08e6e18348304502210091b16b1ac63b867e7a5ca0344f7b2aa1cdd49d4b72eac86a31e7ec6f069e20640220402bfb571ba3a9c49e3b0061c89303453803d0241059d899222aaac4799b507601008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d05000000000100000001f2090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202f058d99cb5a54f90773d43ba4e7a0089efd9f8269ef2da1b85d48a3e230555402205acc4bd6561830867d45cd7b84bba9fa35ad2b345016471c1737142bc99782c48347304402202913f9cacea54efd2316cffa91219def9e0e111977216c1e76e9da80befab14f022000a9a69e8f37ebe4a39107ab50fab0dde537334588f8f412bbaca57b179b87a6012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with five outputs untrimmed (minimum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 2061 + remote_signature = 3045022100a2faf2ad7e323b2a82e07dc40b6847207ca6ad7b089f2c21dea9a4d37e52d59d02204c9480ce0358eb51d92a4342355a97e272e3cc45f86c612a76a3fe32fc3c4cb4 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837eab80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a18916a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402204ab07c659412dd2cd6043b1ad811ab215e901b6b5653e08cb3d2fe63d3e3dc57022031c7b3d130f9380ef09581f4f5a15cb6f359a2e0a597146b96c3533a26d6f4cd01483045022100a2faf2ad7e323b2a82e07dc40b6847207ca6ad7b089f2c21dea9a4d37e52d59d02204c9480ce0358eb51d92a4342355a97e272e3cc45f86c612a76a3fe32fc3c4cb401475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 3 + remote_htlc_signature = 3045022100e10744f572a2cd1d787c969e894b792afaed21217ee0480df0112d2fa3ef96ea02202af4f66eb6beebc36d8e98719ed6b4be1b181659fcb561fc491d8cfebff3aa85 + remote_htlc_signature = 3045022100e1f51fb72fec604b029b348a3bb6363454e1869f5b1e24fd736f860c8039f8070220030a2c90186437d8c9b47d4897798c024521b1274991c4cdc125970b346094b1 + remote_htlc_signature = 304402203479f81a1d83c516957679dc98bf91d35deada967739a8e3869e3e8db08246130220053c8e154b97e3019048dcec3d51bfaf396f36861fbda6d33f0e2a57155c8b9f + output htlc_timeout_tx 2: 02000000000101cf32732fe2d1387ed4e2335f69ddd3c0f337dabc03269e742531f89d35e161d10200000000010000000174020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e10744f572a2cd1d787c969e894b792afaed21217ee0480df0112d2fa3ef96ea02202af4f66eb6beebc36d8e98719ed6b4be1b181659fcb561fc491d8cfebff3aa8583483045022100c3dc3ea50a0ca20e350f97b50c52c5514717cfa36cb9600918caac5cb556842b022049af018d676dde0c8e28ecf325f3ff5c1594261c4f7511d501f9d62d0594d2a201008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000 + output htlc_timeout_tx 3: 02000000000101cf32732fe2d1387ed4e2335f69ddd3c0f337dabc03269e742531f89d35e161d1030000000001000000015c060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e1f51fb72fec604b029b348a3bb6363454e1869f5b1e24fd736f860c8039f8070220030a2c90186437d8c9b47d4897798c024521b1274991c4cdc125970b346094b183483045022100ec7ade6037e531629f24390ca9713782a04d648065d17fbe6b015981cdb296c202202d61049a6ecba2fb5314f3edcda2361cad187a89bea6e5d15185354d80c0c08501008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 02000000000101cf32732fe2d1387ed4e2335f69ddd3c0f337dabc03269e742531f89d35e161d104000000000100000001f1090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402203479f81a1d83c516957679dc98bf91d35deada967739a8e3869e3e8db08246130220053c8e154b97e3019048dcec3d51bfaf396f36861fbda6d33f0e2a57155c8b9f83483045022100a558eb5caa04e35a4417c1f0123ac12eec5f6badee28f5764dc6b69486e594f802201589b12784e242f205832d2d032149bd4e79433ec304c05394241fc7dcba5a71012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with five outputs untrimmed (maximum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 2184 + remote_signature = 3044022013d326f80ff7607cf366c823fcbbcb7a2b10322484825f151e6c4c756af24b8f02201ba05b9d8beb7cea2947f9f4d9e03f90435e93db2dd48b32eb9ca3f3dd042c79 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837eab80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a4f906a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220555c05261f72c5b4702d5c83a608630822b473048724b08640d6e75e345094250220448950b74a96a56963928ba5db8b457661a742c855e69d239b3b6ab73de307a301473044022013d326f80ff7607cf366c823fcbbcb7a2b10322484825f151e6c4c756af24b8f02201ba05b9d8beb7cea2947f9f4d9e03f90435e93db2dd48b32eb9ca3f3dd042c7901475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 3 + remote_htlc_signature = 304402202e03ba1390998b3487e9a7fefcb66814c09abea0ef1bcc915dbaefbcf310569a02206bd10493a105ac69048e9bcedcb8e3301ef81b55018d911a4afd297297f98d30 + remote_htlc_signature = 304402201f8a6adda2403bc400c919ea69d72d315337291e00d02cde085ea32953dbc50002202d65230da98df7af8ebefd2b60b457d0945232988ee2d7460a94a77d414a9acc + remote_htlc_signature = 3045022100ea6e4c9b8f56dd9cf5799492a201cdd65b8bc9bc089c3cff34107896ae313f90022034760f7760975cc68e8917a7f62894e25583da7be11af557c4fc402661d0cbf8 + output htlc_timeout_tx 2: 020000000001015b03043e20eb467029305a22af4c3b915e793743f192c5d225cf1d3c6e8c03010200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202e03ba1390998b3487e9a7fefcb66814c09abea0ef1bcc915dbaefbcf310569a02206bd10493a105ac69048e9bcedcb8e3301ef81b55018d911a4afd297297f98d308347304402200c3952ca04be0c60dcc0b7873a0829f560607524943554ae4a27d8d967166199022021a68657b88e22f9bf9ac6065be412685aff643d17049f04f2e99e86197dabb101008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000 + output htlc_timeout_tx 3: 020000000001015b03043e20eb467029305a22af4c3b915e793743f192c5d225cf1d3c6e8c0301030000000001000000010a060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402201f8a6adda2403bc400c919ea69d72d315337291e00d02cde085ea32953dbc50002202d65230da98df7af8ebefd2b60b457d0945232988ee2d7460a94a77d414a9acc83483045022100ea69c9273b8914ac62b5b7082d6ac1da2b7b065ebf2ef3cd6403f5305ce3f26802203d98736ea97638895a898dfcc5ee0d0c55eb496b3964df0bb25d223688ea8b8701008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 020000000001015b03043e20eb467029305a22af4c3b915e793743f192c5d225cf1d3c6e8c0301040000000001000000019b090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100ea6e4c9b8f56dd9cf5799492a201cdd65b8bc9bc089c3cff34107896ae313f90022034760f7760975cc68e8917a7f62894e25583da7be11af557c4fc402661d0cbf8834730440220717012f2f7ef6cac590aaf66c2109132c93ffba245959ac62d82e394ba80191302203f00fd9cb37c92c6b0ad4b33e62c3e55b04e5c2cfa0adcca5a9bc49774eeca8a012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with four outputs untrimmed (minimum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 2185 + remote_signature = 3044022040f63a16148cf35c8d3d41827f5ae7f7c3746885bb64d4d1b895892a83812b3e02202fcf95c2bf02c466163b3fa3ced6a24926fbb4035095a96842ef516e86ba54c0 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80064a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994b80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994ac5916a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100cd8479cfe1edb1e5a1d487391e0451a469c7171e51e680183f19eb4321f20e9b02204eab7d5a6384b1b08e03baa6e4d9748dfd2b5ab2bae7e39604a0d0055bbffdd501473044022040f63a16148cf35c8d3d41827f5ae7f7c3746885bb64d4d1b895892a83812b3e02202fcf95c2bf02c466163b3fa3ced6a24926fbb4035095a96842ef516e86ba54c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 2 + remote_htlc_signature = 304502210094480e38afb41d10fae299224872f19c53abe23c7033a1c0642c48713e7863a10220726dd9456407682667dc4bd9c66975acb3744961770b5002f7eb9c0df9ef2f3e + remote_htlc_signature = 304402200dbde868dbc20c6a2433fe8979ba5e3f966b1c2d1aeb615f1c42e9c938b3495402202eec5f663c8b601c2061c1453d35de22597c137d1907a2feaf714d551035cb6e + output htlc_timeout_tx 3: 02000000000101ac13a7715f80b8e52dda43c6929cade5521bdced3a405da02b443f1ffb1e33cc0200000000010000000109060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050048304502210094480e38afb41d10fae299224872f19c53abe23c7033a1c0642c48713e7863a10220726dd9456407682667dc4bd9c66975acb3744961770b5002f7eb9c0df9ef2f3e8347304402203148dac61513dc0361738cba30cb341a1e580f8acd5ab0149bf65bd670688cf002207e5d9a0fcbbea2c263bc714fa9e9c44d7f582ea447f366119fc614a23de32f1f01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 02000000000101ac13a7715f80b8e52dda43c6929cade5521bdced3a405da02b443f1ffb1e33cc030000000001000000019a090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402200dbde868dbc20c6a2433fe8979ba5e3f966b1c2d1aeb615f1c42e9c938b3495402202eec5f663c8b601c2061c1453d35de22597c137d1907a2feaf714d551035cb6e83483045022100b896bded41d7feac7af25c19e35c53037c53b50e73cfd01eb4ba139c7fdf231602203a3be049d3d89396c4dc766d82ce31e237da8bc3a93e2c7d35992d1932d9cfeb012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with four outputs untrimmed (maximum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 3686 + remote_signature = 30440220784485cf7a0ad7979daf2c858ffdaf5298d0020cea7aea466843e7948223bd9902206031b81d25e02a178c64e62f843577fdcdfc7a1decbbfb54cd895de692df85ca + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80064a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994b80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a29896a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100c268496aad5c3f97f25cf41c1ba5483a12982de29b222051b6de3daa2229413b02207f3c82d77a2c14f0096ed9bb4c34649483bb20fa71f819f71af44de6593e8bb2014730440220784485cf7a0ad7979daf2c858ffdaf5298d0020cea7aea466843e7948223bd9902206031b81d25e02a178c64e62f843577fdcdfc7a1decbbfb54cd895de692df85ca01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 2 + remote_htlc_signature = 304402202cfe6618926ca9f1574f8c4659b425e9790b4677ba2248d77901290806130ffe02204ab37bb0287abcdb8b750b018d41a09effe37cb65ff801fa70d3f1a416599841 + remote_htlc_signature = 30440220687af8544d335376620a6f4b5412bfd0da48de047c1785674f26e669d4a3ff82022058591c1e3a6c50017427d38a8f756eb685bdab88ec73838eed3530048861f9d5 + output htlc_timeout_tx 3: 020000000001012c32e55722e4b96324d8e5b398d583a20780b25202816adc32dc3157dee731c90200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202cfe6618926ca9f1574f8c4659b425e9790b4677ba2248d77901290806130ffe02204ab37bb0287abcdb8b750b018d41a09effe37cb65ff801fa70d3f1a41659984183473044022030b318139715e3b34f19be852cc01c1c0e1599e8b926a73df2bfb70dd186ddee022062a2b7398aed9f563b4014da04a1a99debd0ff663ceece68a547df5982dc2d7201008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000 + output htlc_success_tx 4: 020000000001012c32e55722e4b96324d8e5b398d583a20780b25202816adc32dc3157dee731c90300000000010000000176050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220687af8544d335376620a6f4b5412bfd0da48de047c1785674f26e669d4a3ff82022058591c1e3a6c50017427d38a8f756eb685bdab88ec73838eed3530048861f9d5834730440220109f1a62b5a13d28d5b7634dd7693b1d5994eb404c4bb4a9a80aa540d3984d170220307251107ff8499a23e99abce7dda4f1c707c98abddb9405a83de0081cde8ace012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with three outputs untrimmed (minimum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 3687 + remote_signature = 3045022100ad6c71569856b2d7ff42e838b4abe74a713426b37f22fa667a195a4c88908c6902202b37272b02a42dc6d9f4f82cab3eaf84ac882d9ed762859e1e75455c2c228377 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80054a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994aa28b6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100c970799bcb33f43179eb43b3378a0a61991cf2923f69b36ef12548c3df0e6d500220413dc27d2e39ee583093adfcb7799be680141738babb31cc7b0669a777a31f5d01483045022100ad6c71569856b2d7ff42e838b4abe74a713426b37f22fa667a195a4c88908c6902202b37272b02a42dc6d9f4f82cab3eaf84ac882d9ed762859e1e75455c2c22837701475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 1 + remote_htlc_signature = 3045022100b287bb8e079a62dcb3aaa8b6c67c0f434a87ebf64ab0bcfb2fc14b55576b859f02206d37c2eb5fd04cfc9eb0534c76a28a98da251b84a931377cce307af39dfaed74 + output htlc_success_tx 4: 02000000000101542562b326c08e3a076d9cfca2be175041366591da334d8d513ff1686fd95a600200000000010000000175050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100b287bb8e079a62dcb3aaa8b6c67c0f434a87ebf64ab0bcfb2fc14b55576b859f02206d37c2eb5fd04cfc9eb0534c76a28a98da251b84a931377cce307af39dfaed7483483045022100a497c64faea286ec4221f48628086dc6403fd7b60a23c4176e8ebbca15ae70dc0220754e20e968e96cf6421fd2a672c8c26d3bc6e19218cfc8fc2aa51fce026c14b1012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + + name: commitment tx with three outputs untrimmed (maximum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 4893 + remote_signature = 3045022100a8771147109e4d3f44a5976c3c3de98732bbb77308d21444dbe0d76faf06480e02200b4e916e850c3d1f918de87bbbbb07843ffea1d4658dfe060b6f9ccd96d34be8 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80054a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a87856a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220086288faceab47461eb2d808e9e9b0cb3ffc24a03c2f18db7198247d38f10e58022031d1c2782a58c8c6ce187d0019eb47a83babdf3040e2caff299ab48f7e12b1fa01483045022100a8771147109e4d3f44a5976c3c3de98732bbb77308d21444dbe0d76faf06480e02200b4e916e850c3d1f918de87bbbbb07843ffea1d4658dfe060b6f9ccd96d34be801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 1 + remote_htlc_signature = 30450221008db80f8531104820b3e894492b4463f074f965b542e1b5c153ddfb108a5ea642022030b203d857a2b3581c2087a7bf17c95d04fadc1c6cdae88c620477f2dccb1ee4 + output htlc_success_tx 4: 02000000000101d515a15e9175fd315bb8d4e768f28684801a9e5a9acdfeba34f7b3b3b3a9ba1d0200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004830450221008db80f8531104820b3e894492b4463f074f965b542e1b5c153ddfb108a5ea642022030b203d857a2b3581c2087a7bf17c95d04fadc1c6cdae88c620477f2dccb1ee483483045022100e5fbae857c47dbfc050a05924bd449fc9804798bd6442002c578437dc34450810220296589bc387645512345299e307116aaac4ce9fc752abcd1936b802d03526312012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000 + name: commitment tx with two outputs untrimmed (minimum feerate) to_local_msat: 6988000000 to_remote_msat: 3000000000 local_feerate_per_kw: 4894 remote_signature = 3045022100e784a66b1588575801e237d35e510fd92a81ae3a4a2a1b90c031ad803d07b3f3022021bc5f16501f167607d63b681442da193eb0a76b4b7fd25c2ed4f8b28fd35b95 output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80044a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994ad0886a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004830450221009f16ac85d232e4eddb3fcd750a68ebf0b58e3356eaada45d3513ede7e817bf4c02207c2b043b4e5f971261975406cb955219fa56bffe5d834a833694b5abc1ce4cfd01483045022100e784a66b1588575801e237d35e510fd92a81ae3a4a2a1b90c031ad803d07b3f3022021bc5f16501f167607d63b681442da193eb0a76b4b7fd25c2ed4f8b28fd35b9501475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 - num_htlcs: 0 \ No newline at end of file + num_htlcs: 0 + + name: commitment tx with two outputs untrimmed (maximum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 6216009 + remote_signature = 3045022100ee67ddd6b3739f3189151063365585ff153ac17e34751da0c90e8034e388a6e2022077aa76cd469604e6af1c00b600d0f4ed0876b11f06336edde3388d517a1ef5e8 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80044a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb399422020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80ec0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a04004830450221008bf6fa6aae9706f68f42006bbf2c3ed5c807487059ce5e5f8e2c2646d60b8a4902201c42e0894e321bf33eaa2d06370ad43368d55611916623fd3589f838d760f45e01483045022100ee67ddd6b3739f3189151063365585ff153ac17e34751da0c90e8034e388a6e2022077aa76cd469604e6af1c00b600d0f4ed0876b11f06336edde3388d517a1ef5e801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 0 + + name: commitment tx with one output untrimmed (minimum feerate) + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 6216010 + remote_signature = 30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80024a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a04004830450221009ad80792e3038fe6968d12ff23e6888a565c3ddd065037f357445f01675d63f3022018384915e5f1f4ae157e15debf4f49b61c8d9d2b073c7d6f97c4a68caa3ed4c1014830450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 0 + + name: commitment tx with fee greater than funder amount + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 6216500 + remote_signature = 30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80024a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a04004830450221009ad80792e3038fe6968d12ff23e6888a565c3ddd065037f357445f01675d63f3022018384915e5f1f4ae157e15debf4f49b61c8d9d2b073c7d6f97c4a68caa3ed4c1014830450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + num_htlcs: 0 + + name: commitment tx with 3 htlc outputs, 2 offered having the same amount and preimage + to_local_msat: 6988000000 + to_remote_msat: 3000000000 + local_feerate_per_kw: 253 + output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994e80300000000000022002010f88bf09e56f14fb4543fd26e47b0db50ea5de9cf3fc46434792471082621ae881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994aae9c6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206b6f71bc7ebc7c6cdefb1a5a36f06a8e270396cd61a203a492d7e75fed2a33d602202a5e2b9ffe8a023302258e8e5fa925cfa9b6b6ba5cc53af22476ed6b38a066180147304402204eb66c90038a47186c4506436a46db761397f40bbe29612ae3e68cf39f463a320220621b8c4135c54dbad92866db3524706b46d7f194c225bfa804ad528345d7cdf201475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220 + output htlc_success_tx 0: 02000000000101c79e5fe4cdd18a9d78534ad7b00406e0274fdf0cd39adbc57fb28200fcfaeec10200000000010000000136030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100db2e6f9c53ba0b399e12129014f6915e467de7d67ea1cff3a9cec6aa780bcdc40220277f9876b2cc200773b82a53bfb522259f8e1af2399627a817547e4cb143080a83473044022011f1fa9e1bfbf70b2efd53d75e4947c47335567495c697b79cbf568be2842350022006489dd709aab9e25e1c9a314f4bbdf27c7201422f585c0e58d2b82280b5f701012000000000000000000000000000000000000000000000000000000000000000008d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac6851b2756800000000 + output htlc_timeout_tx 1: 02000000000101c79e5fe4cdd18a9d78534ad7b00406e0274fdf0cd39adbc57fb28200fcfaeec103000000000100000001e0120000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100915a62a2df7a8da967053525c97783f365cf69987f9b9ddc12d739d2e5a43ce0022055eade45ee13d438d811ffb6851c776dc853f39d350f2a7b74db55be6cc3f97983473044022033d2965dedc5bf45e2179b2fc6b45e83eeb5cfa578806dbdd93475ceef751adf0220405ae7c13795f64f753cf431957778fa8c9be336f056a763c5091bcdb2d96c7e01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6851b27568f9010000 + output htlc_timeout_tx 2: 02000000000101c79e5fe4cdd18a9d78534ad7b00406e0274fdf0cd39adbc57fb28200fcfaeec104000000000100000001e0120000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d5b4178088c9012b7bc527357ffb0b53400f22b9ab623c917bc36ede76f2ad4002205624290ef9850e2591db46ed2d8cc6407363063798c18ba0cfa6ddc9fc62f0cc83483045022100de2b23c17311533079950dd77a1b5b0ae72efbbf0348580f029fe27915afa4df02207448948f441aa92382fd2519b02f30f67d5c9ad1cefb6755869aca7800a8135101008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6851b27568fa010000 + num_htlcs: 3 diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala index 89e37f28f8..fe72deba64 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala @@ -365,7 +365,7 @@ class ClosingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with assert(fulfill1.paymentPreimage === ra1) // scenario 2: bob claims the htlc output from his own commit tx using its preimage (let's assume both parties had published their commitment tx) - val claimHtlcSuccessTx = Transaction(version = 0, txIn = TxIn(outPoint = OutPoint(randomBytes32, 0), signatureScript = ByteVector.empty, sequence = 0, witness = Scripts.witnessHtlcSuccess(Transactions.PlaceHolderSig, Transactions.PlaceHolderSig, ra1, ByteVector.fill(130)(33))) :: Nil, txOut = Nil, lockTime = 0) + val claimHtlcSuccessTx = Transaction(version = 0, txIn = TxIn(outPoint = OutPoint(randomBytes32, 0), signatureScript = ByteVector.empty, sequence = 0, witness = Scripts.witnessHtlcSuccess(Transactions.PlaceHolderSig, Transactions.PlaceHolderSig, ra1, ByteVector.fill(130)(33), Transactions.DefaultCommitmentFormat)) :: Nil, txOut = Nil, lockTime = 0) alice ! WatchEventSpent(BITCOIN_OUTPUT_SPENT, claimHtlcSuccessTx) val fulfill2 = relayerA.expectMsgType[ForwardOnChainFulfill] assert(fulfill2.htlc === htlca1) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala index ac9f5f9ff1..94b5856bc7 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala @@ -1084,7 +1084,7 @@ class IntegrationSpec extends TestKitBaseClass with BitcoindService with AnyFunS generateBlocks(bitcoincli, 2, Some(address)) // and we wait for C'channel to close awaitCond(stateListener.expectMsgType[ChannelStateChanged].currentState == CLOSED, max = 30 seconds) - awaitAnnouncements(nodes.filterKeys(_ == "A").toMap, 9, 11, 24) + awaitAnnouncements(nodes.filterKeys(_ == "A").toMap, 9, 11, 24) } test("propagate a failure upstream when a downstream htlc times out (local commit)") { @@ -1302,8 +1302,8 @@ class IntegrationSpec extends TestKitBaseClass with BitcoindService with AnyFunS val previouslyReceivedByC = res.filter(_ \ "address" == JString(finalAddressC)).flatMap(_ \ "txids" \\ classOf[JString]) // F will publish the commitment above, which is now revoked val revokedCommitTx = localCommitF.commitTx.tx - val htlcSuccess = Transactions.addSigs(htlcSuccessTxs.head.txinfo.asInstanceOf[Transactions.HtlcSuccessTx], htlcSuccessTxs.head.localSig, htlcSuccessTxs.head.remoteSig, preimage1).tx - val htlcTimeout = Transactions.addSigs(htlcTimeoutTxs.head.txinfo.asInstanceOf[Transactions.HtlcTimeoutTx], htlcTimeoutTxs.head.localSig, htlcTimeoutTxs.head.remoteSig).tx + val htlcSuccess = Transactions.addSigs(htlcSuccessTxs.head.txinfo.asInstanceOf[Transactions.HtlcSuccessTx], htlcSuccessTxs.head.localSig, htlcSuccessTxs.head.remoteSig, preimage1, commitmentsF.commitmentFormat).tx + val htlcTimeout = Transactions.addSigs(htlcTimeoutTxs.head.txinfo.asInstanceOf[Transactions.HtlcTimeoutTx], htlcTimeoutTxs.head.localSig, htlcTimeoutTxs.head.remoteSig, commitmentsF.commitmentFormat).tx Transaction.correctlySpends(htlcSuccess, Seq(revokedCommitTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) Transaction.correctlySpends(htlcTimeout, Seq(revokedCommitTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // we then generate blocks to make the htlc timeout (nothing will happen in the channel because all of them have already been fulfilled) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala index edcc0232c3..eaf4580a66 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala @@ -17,7 +17,7 @@ package fr.acinq.eclair.transactions import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} -import fr.acinq.bitcoin.{ByteVector32, Crypto, Script, ScriptFlags, Transaction} +import fr.acinq.bitcoin.{ByteVector32, Crypto, SIGHASH_ANYONECANPAY, SIGHASH_SINGLE, Script, ScriptFlags, Transaction} import fr.acinq.eclair.channel.ChannelVersion import fr.acinq.eclair.channel.Helpers.Funding import fr.acinq.eclair.crypto.Generators @@ -201,9 +201,9 @@ trait TestVectorsSpec extends AnyFunSuite with Logging { localIsFunder = true, outputs = outputs) val local_sig = Transactions.sign(tx, Local.funding_privkey) - logger.info(s"# local_signature = ${local_sig.dropRight(1).toHex}") + logger.info(s"# local_signature = ${Scripts.der(local_sig).dropRight(1).toHex}") val remote_sig = Transactions.sign(tx, Remote.funding_privkey) - logger.info(s"remote_signature: ${remote_sig.dropRight(1).toHex}") + logger.info(s"remote_signature: ${Scripts.der(remote_sig).dropRight(1).toHex}") Transactions.addSigs(tx, Local.funding_pubkey, Remote.funding_pubkey, local_sig, remote_sig) } @@ -239,34 +239,34 @@ trait TestVectorsSpec extends AnyFunSuite with Logging { htlcTxs.collect { case tx: HtlcSuccessTx => - val remoteSig = Transactions.sign(tx, Remote.htlc_privkey) + val remoteSig = Transactions.sign(tx, Remote.htlc_privkey, Scripts.htlcRemoteSighash(commitmentFormat)) val htlcIndex = htlcScripts.indexOf(Script.parse(tx.input.redeemScript)) logger.info(s"# signature for output ${tx.input.outPoint.index} (htlc $htlcIndex)") - logger.info(s"remote_htlc_signature: ${remoteSig.dropRight(1).toHex}") + logger.info(s"remote_htlc_signature: ${Scripts.der(remoteSig).dropRight(1).toHex}") case tx: HtlcTimeoutTx => - val remoteSig = Transactions.sign(tx, Remote.htlc_privkey) + val remoteSig = Transactions.sign(tx, Remote.htlc_privkey, Scripts.htlcRemoteSighash(commitmentFormat)) val htlcIndex = htlcScripts.indexOf(Script.parse(tx.input.redeemScript)) logger.info(s"# signature for output ${tx.input.outPoint.index} (htlc $htlcIndex)") - logger.info(s"remote_htlc_signature: ${remoteSig.dropRight(1).toHex}") + logger.info(s"remote_htlc_signature: ${Scripts.der(remoteSig).dropRight(1).toHex}") } val signedTxs = htlcTxs collect { case tx: HtlcSuccessTx => val localSig = Transactions.sign(tx, Local.htlc_privkey) - val remoteSig = Transactions.sign(tx, Remote.htlc_privkey) + val remoteSig = Transactions.sign(tx, Remote.htlc_privkey, Scripts.htlcRemoteSighash(commitmentFormat)) val preimage = paymentPreimages.find(p => Crypto.sha256(p) == tx.paymentHash).get - val tx1 = Transactions.addSigs(tx, localSig, remoteSig, preimage) + val tx1 = Transactions.addSigs(tx, localSig, remoteSig, preimage, commitmentFormat) Transaction.correctlySpends(tx1.tx, Seq(commitTx.tx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) val htlcIndex = htlcScripts.indexOf(Script.parse(tx.input.redeemScript)) - logger.info(s"# local_signature = ${localSig.dropRight(1).toHex}") + logger.info(s"# local_signature = ${Scripts.der(localSig).dropRight(1).toHex}") logger.info(s"output htlc_success_tx $htlcIndex: ${tx1.tx}") tx1 case tx: HtlcTimeoutTx => val localSig = Transactions.sign(tx, Local.htlc_privkey) - val remoteSig = Transactions.sign(tx, Remote.htlc_privkey) - val tx1 = Transactions.addSigs(tx, localSig, remoteSig) + val remoteSig = Transactions.sign(tx, Remote.htlc_privkey, Scripts.htlcRemoteSighash(commitmentFormat)) + val tx1 = Transactions.addSigs(tx, localSig, remoteSig, commitmentFormat) Transaction.correctlySpends(tx1.tx, Seq(commitTx.tx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) - logger.info(s"# local_signature = ${localSig.dropRight(1).toHex}") + logger.info(s"# local_signature = ${Scripts.der(localSig).dropRight(1).toHex}") val htlcIndex = htlcScripts.indexOf(Script.parse(tx.input.redeemScript)) logger.info(s"output htlc_timeout_tx $htlcIndex: ${tx1.tx}") tx1 @@ -289,92 +289,72 @@ trait TestVectorsSpec extends AnyFunSuite with Logging { } test("commitment tx with all five HTLCs untrimmed (minimum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with all five HTLCs untrimmed (minimum feerate)" - val (commitTx, _) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - } + val name = "commitment tx with all five HTLCs untrimmed (minimum feerate)" + val (commitTx, _) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) } test("commitment tx with seven outputs untrimmed (maximum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with seven outputs untrimmed (maximum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with seven outputs untrimmed (maximum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with six outputs untrimmed (minimum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with six outputs untrimmed (minimum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with six outputs untrimmed (minimum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with six outputs untrimmed (maximum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with six outputs untrimmed (maximum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with six outputs untrimmed (maximum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with five outputs untrimmed (minimum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with five outputs untrimmed (minimum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with five outputs untrimmed (minimum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with five outputs untrimmed (maximum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with five outputs untrimmed (maximum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with five outputs untrimmed (maximum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with four outputs untrimmed (minimum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with four outputs untrimmed (minimum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with four outputs untrimmed (minimum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with four outputs untrimmed (maximum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with four outputs untrimmed (maximum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with four outputs untrimmed (maximum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with three outputs untrimmed (minimum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with three outputs untrimmed (minimum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with three outputs untrimmed (minimum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with three outputs untrimmed (maximum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with three outputs untrimmed (maximum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with three outputs untrimmed (maximum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with two outputs untrimmed (minimum feerate)") { @@ -385,52 +365,43 @@ trait TestVectorsSpec extends AnyFunSuite with Logging { } test("commitment tx with two outputs untrimmed (maximum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with two outputs untrimmed (maximum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with two outputs untrimmed (maximum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with one output untrimmed (minimum feerate)") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with one output untrimmed (minimum feerate)" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx.txOut.length == 1) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with one output untrimmed (minimum feerate)" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } test("commitment tx with fee greater than funder amount") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with fee greater than funder amount" - val (commitTx, htlcTxs) = run(name, htlcs.toSet) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - verifyHtlcTxs(name, htlcTxs) - } + val name = "commitment tx with fee greater than funder amount" + val (commitTx, htlcTxs) = run(name, htlcs.toSet) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + verifyHtlcTxs(name, htlcTxs) } // Added to the spec in https://github.com/lightningnetwork/lightning-rfc/pull/539 test("commitment tx with 3 htlc outputs, 2 offered having the same amount and preimage") { - if (commitmentFormat == DefaultCommitmentFormat) { - val name = "commitment tx with 3 htlc outputs, 2 offered having the same amount and preimage" - val preimage = hex"0505050505050505050505050505050505050505050505050505050505050505" - val someHtlcs = Seq( - IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000.msat, Crypto.sha256(paymentPreimages(0)), CltvExpiry(500), TestConstants.emptyOnionPacket)), - OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 5000000.msat, Crypto.sha256(preimage), CltvExpiry(505), TestConstants.emptyOnionPacket)), - OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 5000000.msat, Crypto.sha256(preimage), CltvExpiry(506), TestConstants.emptyOnionPacket)) - ) - - val (commitTx, htlcTxs) = run(name, someHtlcs.toSet[DirectedHtlc]) - assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) - - assert(htlcTxs.size == 3) // one htlc-success-tx + two htlc-timeout-tx - assert(htlcTxs(0).tx == Transaction.read(tests(name)("output htlc_success_tx 0"))) - assert(htlcTxs(1).tx == Transaction.read(tests(name)("output htlc_timeout_tx 1"))) - assert(htlcTxs(2).tx == Transaction.read(tests(name)("output htlc_timeout_tx 2"))) - } + val name = "commitment tx with 3 htlc outputs, 2 offered having the same amount and preimage" + val preimage = hex"0505050505050505050505050505050505050505050505050505050505050505" + val someHtlcs = Seq( + IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000.msat, Crypto.sha256(paymentPreimages(0)), CltvExpiry(500), TestConstants.emptyOnionPacket)), + OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 5000000.msat, Crypto.sha256(preimage), CltvExpiry(505), TestConstants.emptyOnionPacket)), + OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 5000000.msat, Crypto.sha256(preimage), CltvExpiry(506), TestConstants.emptyOnionPacket)) + ) + + val (commitTx, htlcTxs) = run(name, someHtlcs.toSet[DirectedHtlc]) + assert(commitTx.tx == Transaction.read(tests(name)("output commit_tx"))) + + assert(htlcTxs.size == 3) // one htlc-success-tx + two htlc-timeout-tx + assert(htlcTxs(0).tx == Transaction.read(tests(name)("output htlc_success_tx 0"))) + assert(htlcTxs(1).tx == Transaction.read(tests(name)("output htlc_timeout_tx 1"))) + assert(htlcTxs(2).tx == Transaction.read(tests(name)("output htlc_timeout_tx 2"))) } } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala index a57d99521f..70d0d73c3c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala @@ -278,7 +278,7 @@ class TransactionsSpec extends AnyFunSuite with Logging { for (htlcTimeoutTx <- htlcTimeoutTxs) { val localSig = sign(htlcTimeoutTx, localHtlcPriv) val remoteSig = sign(htlcTimeoutTx, remoteHtlcPriv) - val signed = addSigs(htlcTimeoutTx, localSig, remoteSig) + val signed = addSigs(htlcTimeoutTx, localSig, remoteSig, DefaultCommitmentFormat) assert(checkSpendable(signed).isSuccess) } } @@ -306,7 +306,7 @@ class TransactionsSpec extends AnyFunSuite with Logging { for ((htlcSuccessTx, paymentPreimage) <- (htlcSuccessTxs(1), paymentPreimage2) :: (htlcSuccessTxs(0), paymentPreimage4) :: Nil) { val localSig = sign(htlcSuccessTx, localHtlcPriv) val remoteSig = sign(htlcSuccessTx, remoteHtlcPriv) - val signedTx = addSigs(htlcSuccessTx, localSig, remoteSig, paymentPreimage) + val signedTx = addSigs(htlcSuccessTx, localSig, remoteSig, paymentPreimage, DefaultCommitmentFormat) assert(checkSpendable(signedTx).isSuccess) // check remote sig assert(checkSig(htlcSuccessTx, remoteSig, remoteHtlcPriv.publicKey)) @@ -318,7 +318,7 @@ class TransactionsSpec extends AnyFunSuite with Logging { val localSig = sign(claimHtlcDelayed, localDelayedPaymentPriv) val signedTx = addSigs(claimHtlcDelayed, localSig) assert(checkSpendable(signedTx).isSuccess) - // local can't claim delayed output of htlc4 timeout tx because it is below the dust limit + // local can't claim delayed output of htlc4 success tx because it is below the dust limit val claimHtlcDelayed1 = makeClaimDelayedOutputTx(htlcSuccessTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) assert(claimHtlcDelayed1 === Left(AmountBelowDustLimit)) } @@ -350,6 +350,16 @@ class TransactionsSpec extends AnyFunSuite with Logging { val signed = addSigs(mainPenaltyTx, sig) assert(checkSpendable(signed).isSuccess) } + { + // remote spends htlc1's htlc-timeout tx with revocation key + val Right(claimHtlcDelayedPenaltyTx) = makeClaimDelayedOutputPenaltyTx(htlcTimeoutTxs(1).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + val sig = sign(claimHtlcDelayedPenaltyTx, localRevocationPriv) + val signed = addSigs(claimHtlcDelayedPenaltyTx, sig) + assert(checkSpendable(signed).isSuccess) + // remote can't claim revoked output of htlc3's htlc-timeout tx because it is below the dust limit + val claimHtlcDelayedPenaltyTx1 = makeClaimDelayedOutputPenaltyTx(htlcTimeoutTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + assert(claimHtlcDelayedPenaltyTx1 === Left(AmountBelowDustLimit)) + } { // remote spends offered HTLC output with revocation key val script = Script.write(Scripts.htlcOffered(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, Crypto.ripemd160(htlc1.paymentHash), DefaultCommitmentFormat)) @@ -362,6 +372,16 @@ class TransactionsSpec extends AnyFunSuite with Logging { val signed = addSigs(htlcPenaltyTx, sig, localRevocationPriv.publicKey) assert(checkSpendable(signed).isSuccess) } + { + // remote spends htlc2's htlc-success tx with revocation key + val Right(claimHtlcDelayedPenaltyTx) = makeClaimDelayedOutputPenaltyTx(htlcSuccessTxs(1).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + val sig = sign(claimHtlcDelayedPenaltyTx, localRevocationPriv) + val signed = addSigs(claimHtlcDelayedPenaltyTx, sig) + assert(checkSpendable(signed).isSuccess) + // remote can't claim revoked output of htlc4's htlc-success tx because it is below the dust limit + val claimHtlcDelayedPenaltyTx1 = makeClaimDelayedOutputPenaltyTx(htlcSuccessTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + assert(claimHtlcDelayedPenaltyTx1 === Left(AmountBelowDustLimit)) + } { // remote spends received HTLC output with revocation key val script = Script.write(Scripts.htlcReceived(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, Crypto.ripemd160(htlc2.paymentHash), htlc2.cltvExpiry, DefaultCommitmentFormat)) @@ -457,13 +477,17 @@ class TransactionsSpec extends AnyFunSuite with Logging { toLocal = 400.mbtc.toMilliSatoshi, toRemote = 300.mbtc.toMilliSatoshi) - val commitTx = { + val (commitTx, commitTxOutputs, htlcTimeoutTxs, htlcSuccessTxs) = { val commitTxNumber = 0x404142434445L val outputs = makeCommitTxOutputs(localIsFunder = true, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, remotePaymentPriv.publicKey, localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localFundingPriv.publicKey, remoteFundingPriv.publicKey, spec, AnchorOutputsCommitmentFormat) val txinfo = makeCommitTx(commitInput, commitTxNumber, localPaymentPriv.publicKey, remotePaymentPriv.publicKey, localIsFunder = true, outputs) val localSig = Transactions.sign(txinfo, localPaymentPriv) val remoteSig = Transactions.sign(txinfo, remotePaymentPriv) - Transactions.addSigs(txinfo, localFundingPriv.publicKey, remoteFundingPriv.publicKey, localSig, remoteSig) + val commitTx = Transactions.addSigs(txinfo, localFundingPriv.publicKey, remoteFundingPriv.publicKey, localSig, remoteSig) + val (htlcTimeoutTxs, htlcSuccessTxs) = makeHtlcTxs(commitTx.tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, spec.feeratePerKw, outputs, AnchorOutputsCommitmentFormat) + assert(htlcTimeoutTxs.size == 2) // htlc1 and htlc3 + assert(htlcSuccessTxs.size == 3) // htlc2a, htlc2b and htlc4 + (commitTx, outputs, htlcTimeoutTxs, htlcSuccessTxs) } { @@ -508,6 +532,114 @@ class TransactionsSpec extends AnyFunSuite with Logging { val signed = addSigs(mainPenaltyTx, sig) assert(checkSpendable(signed).isSuccess) } + { + // local spends received htlc with HTLC-timeout tx + for (htlcTimeoutTx <- htlcTimeoutTxs) { + val localSig = sign(htlcTimeoutTx, localHtlcPriv) + val remoteSig = sign(htlcTimeoutTx, remoteHtlcPriv, Scripts.htlcRemoteSighash(AnchorOutputsCommitmentFormat)) + val signedTx = addSigs(htlcTimeoutTx, localSig, remoteSig, AnchorOutputsCommitmentFormat) + assert(checkSpendable(signedTx).isSuccess) + } + } + { + // local spends delayed output of htlc1 timeout tx + val Right(claimHtlcDelayed) = makeClaimDelayedOutputTx(htlcTimeoutTxs(1).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + val localSig = sign(claimHtlcDelayed, localDelayedPaymentPriv) + val signedTx = addSigs(claimHtlcDelayed, localSig) + assert(checkSpendable(signedTx).isSuccess) + // local can't claim delayed output of htlc3 timeout tx because it is below the dust limit + val claimHtlcDelayed1 = makeClaimDelayedOutputTx(htlcTimeoutTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + assert(claimHtlcDelayed1 === Left(OutputNotFound)) + } + { + // local spends offered htlc with HTLC-success tx + for ((htlcSuccessTx, paymentPreimage) <- (htlcSuccessTxs(0), paymentPreimage4) :: (htlcSuccessTxs(1), paymentPreimage2) :: (htlcSuccessTxs(2), paymentPreimage2) :: Nil) { + val localSig = sign(htlcSuccessTx, localHtlcPriv) + val remoteSig = sign(htlcSuccessTx, remoteHtlcPriv, Scripts.htlcRemoteSighash(AnchorOutputsCommitmentFormat)) + val signedTx = addSigs(htlcSuccessTx, localSig, remoteSig, paymentPreimage, AnchorOutputsCommitmentFormat) + assert(checkSpendable(signedTx).isSuccess) + } + } + { + // local spends delayed output of htlc2a and htlc2b success txs + val Right(claimHtlcDelayedA) = makeClaimDelayedOutputTx(htlcSuccessTxs(1).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + val Right(claimHtlcDelayedB) = makeClaimDelayedOutputTx(htlcSuccessTxs(2).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + for (claimHtlcDelayed <- Seq(claimHtlcDelayedA, claimHtlcDelayedB)) { + val localSig = sign(claimHtlcDelayed, localDelayedPaymentPriv) + val signedTx = addSigs(claimHtlcDelayed, localSig) + assert(checkSpendable(signedTx).isSuccess) + } + // local can't claim delayed output of htlc4 success tx because it is below the dust limit + val claimHtlcDelayed1 = makeClaimDelayedOutputTx(htlcSuccessTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + assert(claimHtlcDelayed1 === Left(AmountBelowDustLimit)) + } + { + // remote spends local->remote htlc outputs directly in case of success + for ((htlc, paymentPreimage) <- (htlc1, paymentPreimage1) :: (htlc3, paymentPreimage3) :: Nil) { + val Right(claimHtlcSuccessTx) = makeClaimHtlcSuccessTx(commitTx.tx, commitTxOutputs, localDustLimit, remoteHtlcPriv.publicKey, localHtlcPriv.publicKey, localRevocationPriv.publicKey, finalPubKeyScript, htlc, feeratePerKw, AnchorOutputsCommitmentFormat) + val localSig = sign(claimHtlcSuccessTx, remoteHtlcPriv) + val signed = addSigs(claimHtlcSuccessTx, localSig, paymentPreimage) + assert(checkSpendable(signed).isSuccess) + } + } + { + // remote spends htlc1's htlc-timeout tx with revocation key + val Right(claimHtlcDelayedPenaltyTx) = makeClaimDelayedOutputPenaltyTx(htlcTimeoutTxs(1).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + val sig = sign(claimHtlcDelayedPenaltyTx, localRevocationPriv) + val signed = addSigs(claimHtlcDelayedPenaltyTx, sig) + assert(checkSpendable(signed).isSuccess) + // remote can't claim revoked output of htlc3's htlc-timeout tx because it is below the dust limit + val claimHtlcDelayedPenaltyTx1 = makeClaimDelayedOutputPenaltyTx(htlcTimeoutTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + assert(claimHtlcDelayedPenaltyTx1 === Left(AmountBelowDustLimit)) + } + { + // remote spends remote->local htlc output directly in case of timeout + for (htlc <- Seq(htlc2a, htlc2b)) { + val Right(claimHtlcTimeoutTx) = makeClaimHtlcTimeoutTx(commitTx.tx, commitTxOutputs, localDustLimit, remoteHtlcPriv.publicKey, localHtlcPriv.publicKey, localRevocationPriv.publicKey, finalPubKeyScript, htlc, feeratePerKw, AnchorOutputsCommitmentFormat) + val remoteSig = sign(claimHtlcTimeoutTx, remoteHtlcPriv) + val signed = addSigs(claimHtlcTimeoutTx, remoteSig) + assert(checkSpendable(signed).isSuccess) + } + } + { + // remote spends htlc2a/htlc2b's htlc-success tx with revocation key + val Right(claimHtlcDelayedPenaltyTxA) = makeClaimDelayedOutputPenaltyTx(htlcSuccessTxs(1).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + val Right(claimHtlcDelayedPenaltyTxB) = makeClaimDelayedOutputPenaltyTx(htlcSuccessTxs(2).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + for (claimHtlcSuccessPenaltyTx <- Seq(claimHtlcDelayedPenaltyTxA, claimHtlcDelayedPenaltyTxB)) { + val sig = sign(claimHtlcSuccessPenaltyTx, localRevocationPriv) + val signed = addSigs(claimHtlcSuccessPenaltyTx, sig) + assert(checkSpendable(signed).isSuccess) + } + // remote can't claim revoked output of htlc4's htlc-success tx because it is below the dust limit + val claimHtlcDelayedPenaltyTx1 = makeClaimDelayedOutputPenaltyTx(htlcSuccessTxs(0).tx, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, finalPubKeyScript, feeratePerKw) + assert(claimHtlcDelayedPenaltyTx1 === Left(AmountBelowDustLimit)) + } + { + // remote spends offered htlc output with revocation key + val script = Script.write(Scripts.htlcOffered(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, Crypto.ripemd160(htlc1.paymentHash), AnchorOutputsCommitmentFormat)) + val Some(htlcOutputIndex) = commitTxOutputs.zipWithIndex.find { + case (CommitmentOutputLink(_, _, OutHtlc(OutgoingHtlc(someHtlc))), _) => someHtlc.id == htlc1.id + case _ => false + }.map(_._2) + val Right(htlcPenaltyTx) = makeHtlcPenaltyTx(commitTx.tx, htlcOutputIndex, script, localDustLimit, finalPubKeyScript, feeratePerKw) + val sig = sign(htlcPenaltyTx, localRevocationPriv) + val signed = addSigs(htlcPenaltyTx, sig, localRevocationPriv.publicKey) + assert(checkSpendable(signed).isSuccess) + } + { + // remote spends received htlc output with revocation key + for (htlc <- Seq(htlc2a, htlc2b)) { + val script = Script.write(Scripts.htlcReceived(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, Crypto.ripemd160(htlc.paymentHash), htlc.cltvExpiry, AnchorOutputsCommitmentFormat)) + val Some(htlcOutputIndex) = commitTxOutputs.zipWithIndex.find { + case (CommitmentOutputLink(_, _, InHtlc(IncomingHtlc(someHtlc))), _) => someHtlc.id == htlc.id + case _ => false + }.map(_._2) + val Right(htlcPenaltyTx) = makeHtlcPenaltyTx(commitTx.tx, htlcOutputIndex, script, localDustLimit, finalPubKeyScript, feeratePerKw) + val sig = sign(htlcPenaltyTx, localRevocationPriv) + val signed = addSigs(htlcPenaltyTx, sig, localRevocationPriv.publicKey) + assert(checkSpendable(signed).isSuccess) + } + } } test("sort the htlc outputs using BIP69 and cltv expiry") {