Skip to content

Commit 7fda599

Browse files
committed
Add support for setting nLocktime
We add `nLocktime` to `closing_complete`, to allow the initiator to decide what value to use to provide better anonymity and protection against fee sniping.
1 parent f6391b7 commit 7fda599

File tree

7 files changed

+23
-22
lines changed

7 files changed

+23
-22
lines changed

eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -687,26 +687,26 @@ object Helpers {
687687
}
688688

689689
/** We are the closer: we sign closing transactions for which we pay the fees. */
690-
def makeSimpleClosingTx(keyManager: ChannelKeyManager, commitment: FullCommitment, localScriptPubkey: ByteVector, remoteScriptPubkey: ByteVector, feerate: FeeratePerKw): Either[ChannelException, (ClosingTxs, ClosingComplete)] = {
690+
def makeSimpleClosingTx(currentBlockHeight: BlockHeight, keyManager: ChannelKeyManager, commitment: FullCommitment, localScriptPubkey: ByteVector, remoteScriptPubkey: ByteVector, feerate: FeeratePerKw): Either[ChannelException, (ClosingTxs, ClosingComplete)] = {
691691
require(isValidFinalScriptPubkey(localScriptPubkey, allowAnySegwit = true, allowOpReturn = true), "invalid localScriptPubkey")
692692
require(isValidFinalScriptPubkey(remoteScriptPubkey, allowAnySegwit = true, allowOpReturn = true), "invalid remoteScriptPubkey")
693693
val closingFee = {
694-
val dummyClosingTxs = Transactions.makeSimpleClosingTxs(commitment.commitInput, commitment.localCommit.spec, SimpleClosingTxFee.PaidByUs(0 sat), localScriptPubkey, remoteScriptPubkey)
694+
val dummyClosingTxs = Transactions.makeSimpleClosingTxs(commitment.commitInput, commitment.localCommit.spec, SimpleClosingTxFee.PaidByUs(0 sat), currentBlockHeight.toLong, localScriptPubkey, remoteScriptPubkey)
695695
dummyClosingTxs.preferred_opt match {
696696
case Some(dummyTx) =>
697697
val dummySignedTx = Transactions.addSigs(dummyTx, Transactions.PlaceHolderPubKey, Transactions.PlaceHolderPubKey, Transactions.PlaceHolderSig, Transactions.PlaceHolderSig)
698698
SimpleClosingTxFee.PaidByUs(Transactions.weight2fee(feerate, dummySignedTx.tx.weight()))
699699
case None => return Left(CannotGenerateClosingTx(commitment.channelId))
700700
}
701701
}
702-
val closingTxs = Transactions.makeSimpleClosingTxs(commitment.commitInput, commitment.localCommit.spec, closingFee, localScriptPubkey, remoteScriptPubkey)
702+
val closingTxs = Transactions.makeSimpleClosingTxs(commitment.commitInput, commitment.localCommit.spec, closingFee, currentBlockHeight.toLong, localScriptPubkey, remoteScriptPubkey)
703703
// The actual fee we're paying will be bigger than the one we previously computed if we omit our output.
704704
val actualFee = closingTxs.preferred_opt match {
705705
case Some(closingTx) if closingTx.fee > 0.sat => closingTx.fee
706706
case _ => return Left(CannotGenerateClosingTx(commitment.channelId))
707707
}
708708
val localFundingPubKey = keyManager.fundingPublicKey(commitment.localParams.fundingKeyPath, commitment.fundingTxIndex)
709-
val closingComplete = ClosingComplete(commitment.channelId, actualFee, TlvStream(Set(
709+
val closingComplete = ClosingComplete(commitment.channelId, actualFee, currentBlockHeight.toLong, TlvStream(Set(
710710
closingTxs.localAndRemote_opt.map(tx => ClosingTlv.CloserAndClosee(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat))),
711711
closingTxs.localOnly_opt.map(tx => ClosingTlv.CloserNoClosee(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat))),
712712
closingTxs.remoteOnly_opt.map(tx => ClosingTlv.NoCloserClosee(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat))),
@@ -721,7 +721,7 @@ object Helpers {
721721
*/
722722
def signSimpleClosingTx(keyManager: ChannelKeyManager, commitment: FullCommitment, localScriptPubkey: ByteVector, remoteScriptPubkey: ByteVector, closingComplete: ClosingComplete): Either[ChannelException, (ClosingTx, ClosingSig)] = {
723723
val closingFee = SimpleClosingTxFee.PaidByThem(closingComplete.fees)
724-
val closingTxs = Transactions.makeSimpleClosingTxs(commitment.commitInput, commitment.localCommit.spec, closingFee, localScriptPubkey, remoteScriptPubkey)
724+
val closingTxs = Transactions.makeSimpleClosingTxs(commitment.commitInput, commitment.localCommit.spec, closingFee, closingComplete.lockTime, localScriptPubkey, remoteScriptPubkey)
725725
// If our output isn't dust, they must provide a signature for a transaction that includes it.
726726
// Note that we're the closee, so we look for signatures including the closee output.
727727
(closingTxs.localAndRemote_opt, closingTxs.localOnly_opt) match {

eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
735735
// there are no pending signed changes, let's directly negotiate a closing transaction
736736
if (Features.canUseFeature(d.commitments.params.localParams.initFeatures, d.commitments.params.remoteParams.initFeatures, Features.SimpleClose)) {
737737
val closingFeerate = nodeParams.onChainFeeConf.getClosingFeerate(nodeParams.currentFeerates)
738-
MutualClose.makeSimpleClosingTx(keyManager, d.commitments.latest, localShutdown.scriptPubKey, remoteShutdownScript, closingFeerate) match {
738+
MutualClose.makeSimpleClosingTx(nodeParams.currentBlockHeight, keyManager, d.commitments.latest, localShutdown.scriptPubKey, remoteShutdownScript, closingFeerate) match {
739739
case Left(f) =>
740740
log.warning("cannot create local closing txs, waiting for remote closing_complete: {}", f.getMessage)
741741
goto(NEGOTIATING_SIMPLE) using DATA_NEGOTIATING_SIMPLE(d.commitments, localShutdown, remoteShutdown, Nil, Nil) storing() sending sendList
@@ -1331,7 +1331,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
13311331
if (commitments1.hasNoPendingHtlcsOrFeeUpdate) {
13321332
if (Features.canUseFeature(d.commitments.params.localParams.initFeatures, d.commitments.params.remoteParams.initFeatures, Features.SimpleClose)) {
13331333
val closingFeerate = nodeParams.onChainFeeConf.getClosingFeerate(nodeParams.currentFeerates)
1334-
MutualClose.makeSimpleClosingTx(keyManager, d.commitments.latest, localShutdown.scriptPubKey, remoteShutdown.scriptPubKey, closingFeerate) match {
1334+
MutualClose.makeSimpleClosingTx(nodeParams.currentBlockHeight, keyManager, d.commitments.latest, localShutdown.scriptPubKey, remoteShutdown.scriptPubKey, closingFeerate) match {
13351335
case Left(f) =>
13361336
log.warning("cannot create local closing txs, waiting for remote closing_complete: {}", f.getMessage)
13371337
goto(NEGOTIATING_SIMPLE) using DATA_NEGOTIATING_SIMPLE(d.commitments, localShutdown, remoteShutdown, Nil, Nil) storing() sending revocation
@@ -1382,7 +1382,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
13821382
log.debug("switching to NEGOTIATING spec:\n{}", commitments1.latest.specs2String)
13831383
if (Features.canUseFeature(d.commitments.params.localParams.initFeatures, d.commitments.params.remoteParams.initFeatures, Features.SimpleClose)) {
13841384
val closingFeerate = nodeParams.onChainFeeConf.getClosingFeerate(nodeParams.currentFeerates)
1385-
MutualClose.makeSimpleClosingTx(keyManager, d.commitments.latest, localShutdown.scriptPubKey, remoteShutdown.scriptPubKey, closingFeerate) match {
1385+
MutualClose.makeSimpleClosingTx(nodeParams.currentBlockHeight, keyManager, d.commitments.latest, localShutdown.scriptPubKey, remoteShutdown.scriptPubKey, closingFeerate) match {
13861386
case Left(f) =>
13871387
log.warning("cannot create local closing txs, waiting for remote closing_complete: {}", f.getMessage)
13881388
goto(NEGOTIATING_SIMPLE) using DATA_NEGOTIATING_SIMPLE(d.commitments, localShutdown, remoteShutdown, Nil, Nil) storing()
@@ -1561,7 +1561,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
15611561
if (remoteShutdown.scriptPubKey != d.remoteShutdown.scriptPubKey) {
15621562
// Our peer changed their closing script: we sign a new version of our closing transaction using the new script.
15631563
val feerate = nodeParams.onChainFeeConf.getClosingFeerate(nodeParams.currentFeerates)
1564-
MutualClose.makeSimpleClosingTx(keyManager, d.commitments.latest, d.localShutdown.scriptPubKey, remoteShutdown.scriptPubKey, feerate) match {
1564+
MutualClose.makeSimpleClosingTx(nodeParams.currentBlockHeight, keyManager, d.commitments.latest, d.localShutdown.scriptPubKey, remoteShutdown.scriptPubKey, feerate) match {
15651565
case Left(_) => stay() using d.copy(remoteShutdown = remoteShutdown) storing()
15661566
case Right((closingTxs, closingComplete)) => stay() using d.copy(remoteShutdown = remoteShutdown, proposedClosingTxs = d.proposedClosingTxs :+ closingTxs) storing() sending closingComplete
15671567
}
@@ -1622,7 +1622,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
16221622
if (localShutdown_opt.nonEmpty || c.feerates.nonEmpty) {
16231623
val localScript = localShutdown_opt.map(_.scriptPubKey).getOrElse(d.localShutdown.scriptPubKey)
16241624
val feerate = c.feerates.map(_.preferred).getOrElse(nodeParams.onChainFeeConf.getClosingFeerate(nodeParams.currentFeerates))
1625-
MutualClose.makeSimpleClosingTx(keyManager, d.commitments.latest, localScript, d.remoteShutdown.scriptPubKey, feerate) match {
1625+
MutualClose.makeSimpleClosingTx(nodeParams.currentBlockHeight, keyManager, d.commitments.latest, localScript, d.remoteShutdown.scriptPubKey, feerate) match {
16261626
case Left(f) => handleCommandError(f, c)
16271627
case Right((closingTxs, closingComplete)) =>
16281628
log.info("new closing transaction created with script={} fees={}", localScript, closingComplete.fees)
@@ -2284,7 +2284,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
22842284
// We retransmit our shutdown: we may have updated our script and they may not have received it.
22852285
// We also sign a new round of closing transactions since network fees may have changed while we were offline.
22862286
val closingFeerate = nodeParams.onChainFeeConf.getClosingFeerate(nodeParams.currentFeerates)
2287-
Closing.MutualClose.makeSimpleClosingTx(keyManager, d.commitments.latest, d.localShutdown.scriptPubKey, d.remoteShutdown.scriptPubKey, closingFeerate) match {
2287+
Closing.MutualClose.makeSimpleClosingTx(nodeParams.currentBlockHeight, keyManager, d.commitments.latest, d.localShutdown.scriptPubKey, d.remoteShutdown.scriptPubKey, closingFeerate) match {
22882288
case Left(_) => goto(NEGOTIATING_SIMPLE) using d sending d.localShutdown
22892289
case Right((closingTxs, closingComplete)) => goto(NEGOTIATING_SIMPLE) using d.copy(proposedClosingTxs = d.proposedClosingTxs :+ closingTxs) sending Seq(d.localShutdown, closingComplete)
22902290
}

eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,10 +840,10 @@ object Transactions {
840840
val all: Seq[ClosingTx] = Seq(localAndRemote_opt, localOnly_opt, remoteOnly_opt).flatten
841841
}
842842

843-
def makeSimpleClosingTxs(input: InputInfo, spec: CommitmentSpec, fee: SimpleClosingTxFee, localScriptPubKey: ByteVector, remoteScriptPubKey: ByteVector): ClosingTxs = {
843+
def makeSimpleClosingTxs(input: InputInfo, spec: CommitmentSpec, fee: SimpleClosingTxFee, lockTime: Long, localScriptPubKey: ByteVector, remoteScriptPubKey: ByteVector): ClosingTxs = {
844844
require(spec.htlcs.isEmpty, "there shouldn't be any pending htlcs")
845845

846-
val txNoOutput = Transaction(2, Seq(TxIn(input.outPoint, ByteVector.empty, sequence = 0xFFFFFFFDL)), Nil, 0)
846+
val txNoOutput = Transaction(2, Seq(TxIn(input.outPoint, ByteVector.empty, sequence = 0xFFFFFFFDL)), Nil, lockTime)
847847

848848
val (toLocalAmount, toRemoteAmount) = fee match {
849849
case SimpleClosingTxFee.PaidByUs(fee) => (spec.toLocal.truncateToSatoshi - fee, spec.toRemote.truncateToSatoshi)

eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecs.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ object LightningMessageCodecs {
230230
val closingCompleteCodec: Codec[ClosingComplete] = (
231231
("channelId" | bytes32) ::
232232
("fees" | satoshi) ::
233+
("lockTime" | uint32) ::
233234
("tlvStream" | ClosingTlv.closingTlvCodec)).as[ClosingComplete]
234235

235236
val closingSigCodec: Codec[ClosingSig] = (

eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ case class ClosingSigned(channelId: ByteVector32,
345345
val feeRange_opt = tlvStream.get[ClosingSignedTlv.FeeRange]
346346
}
347347

348-
case class ClosingComplete(channelId: ByteVector32, fees: Satoshi, tlvStream: TlvStream[ClosingTlv] = TlvStream.empty) extends ChannelMessage with HasChannelId {
348+
case class ClosingComplete(channelId: ByteVector32, fees: Satoshi, lockTime: Long, tlvStream: TlvStream[ClosingTlv] = TlvStream.empty) extends ChannelMessage with HasChannelId {
349349
val closerNoCloseeSig_opt: Option[ByteVector64] = tlvStream.get[ClosingTlv.CloserNoClosee].map(_.sig)
350350
val noCloserCloseeSig_opt: Option[ByteVector64] = tlvStream.get[ClosingTlv.NoCloserClosee].map(_.sig)
351351
val closerAndCloseeSig_opt: Option[ByteVector64] = tlvStream.get[ClosingTlv.CloserAndClosee].map(_.sig)

eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
831831
{
832832
// Different amounts, both outputs untrimmed, local is closer (option_simple_close):
833833
val spec = CommitmentSpec(Set.empty, feeratePerKw, 150_000_000 msat, 250_000_000 msat)
834-
val closingTxs = makeSimpleClosingTxs(commitInput, spec, SimpleClosingTxFee.PaidByUs(5_000 sat), localPubKeyScript, remotePubKeyScript)
834+
val closingTxs = makeSimpleClosingTxs(commitInput, spec, SimpleClosingTxFee.PaidByUs(5_000 sat), 0, localPubKeyScript, remotePubKeyScript)
835835
assert(closingTxs.localAndRemote_opt.nonEmpty)
836836
assert(closingTxs.localOnly_opt.nonEmpty)
837837
assert(closingTxs.remoteOnly_opt.isEmpty)
@@ -868,7 +868,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
868868
{
869869
// Their output is trimmed (option_simple_close):
870870
val spec = CommitmentSpec(Set.empty, feeratePerKw, 150_000_000 msat, 1_000_000 msat)
871-
val closingTxs = makeSimpleClosingTxs(commitInput, spec, SimpleClosingTxFee.PaidByThem(800 sat), localPubKeyScript, remotePubKeyScript)
871+
val closingTxs = makeSimpleClosingTxs(commitInput, spec, SimpleClosingTxFee.PaidByThem(800 sat), 0, localPubKeyScript, remotePubKeyScript)
872872
assert(closingTxs.all.size == 1)
873873
assert(closingTxs.localOnly_opt.nonEmpty)
874874
val toLocal = closingTxs.localOnly_opt.flatMap(_.toLocalOutput).get
@@ -886,7 +886,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
886886
{
887887
// Our output is trimmed (option_simple_close):
888888
val spec = CommitmentSpec(Set.empty, feeratePerKw, 1_000_000 msat, 150_000_000 msat)
889-
val closingTxs = makeSimpleClosingTxs(commitInput, spec, SimpleClosingTxFee.PaidByUs(800 sat), localPubKeyScript, remotePubKeyScript)
889+
val closingTxs = makeSimpleClosingTxs(commitInput, spec, SimpleClosingTxFee.PaidByUs(800 sat), 0, localPubKeyScript, remotePubKeyScript)
890890
assert(closingTxs.all.size == 1)
891891
assert(closingTxs.remoteOnly_opt.nonEmpty)
892892
assert(closingTxs.remoteOnly_opt.flatMap(_.toLocalOutput).isEmpty)

eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecsSpec.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,11 @@ class LightningMessageCodecsSpec extends AnyFunSuite {
385385
val sig2 = ByteVector64(hex"02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202")
386386
val sig3 = ByteVector64(hex"03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303")
387387
val testCases = Seq(
388-
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451" -> ClosingComplete(channelId, 1105 sat),
389-
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 024001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" -> ClosingComplete(channelId, 1105 sat, TlvStream(ClosingTlv.NoCloserClosee(sig1))),
390-
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 034001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" -> ClosingComplete(channelId, 1105 sat, TlvStream(ClosingTlv.CloserAndClosee(sig1))),
391-
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 014001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 034002020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" -> ClosingComplete(channelId, 1105 sat, TlvStream(ClosingTlv.CloserNoClosee(sig1), ClosingTlv.CloserAndClosee(sig2))),
392-
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 014001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 024002020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202 034003030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303" -> ClosingComplete(channelId, 1105 sat, TlvStream(ClosingTlv.CloserNoClosee(sig1), ClosingTlv.NoCloserClosee(sig2), ClosingTlv.CloserAndClosee(sig3))),
388+
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 00000000" -> ClosingComplete(channelId, 1105 sat, 0),
389+
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 000c96a8 024001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" -> ClosingComplete(channelId, 1105 sat, 825_000, TlvStream(ClosingTlv.NoCloserClosee(sig1))),
390+
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 00000000 034001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" -> ClosingComplete(channelId, 1105 sat, 0, TlvStream(ClosingTlv.CloserAndClosee(sig1))),
391+
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 00000000 014001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 034002020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" -> ClosingComplete(channelId, 1105 sat, 0, TlvStream(ClosingTlv.CloserNoClosee(sig1), ClosingTlv.CloserAndClosee(sig2))),
392+
hex"0028 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 0000000000000451 00000000 014001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 024002020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202 034003030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303" -> ClosingComplete(channelId, 1105 sat, 0, TlvStream(ClosingTlv.CloserNoClosee(sig1), ClosingTlv.NoCloserClosee(sig2), ClosingTlv.CloserAndClosee(sig3))),
393393
hex"0029 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86" -> ClosingSig(channelId),
394394
hex"0029 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 024001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" -> ClosingSig(channelId, TlvStream(ClosingTlv.NoCloserClosee(sig1))),
395395
hex"0029 58a00a6f14e69a2e97b18cf76f755c8551fea9947cf7b6ece9d641013eba5f86 034001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" -> ClosingSig(channelId, TlvStream(ClosingTlv.CloserAndClosee(sig1))),

0 commit comments

Comments
 (0)