Skip to content

Commit 8b71c7e

Browse files
committed
ChannelKeyManager: add an extra output parameter to sign() methods
This outputs are typically wallet inputs added to a transaction to bump it.
1 parent dd87c39 commit 8b71c7e

File tree

14 files changed

+236
-126
lines changed

14 files changed

+236
-126
lines changed

eclair-core/src/main/scala/fr/acinq/eclair/SpendFromChannelAddress.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ trait SpendFromChannelAddress {
4848
Transactions.SpliceTx(inputInfo, unsignedTx), // classify as splice, doesn't really matter
4949
localFundingPubkey,
5050
TxOwner.Local, // unused
51-
DefaultCommitmentFormat // unused
51+
DefaultCommitmentFormat, // unused
52+
Nil
5253
)
5354
witness = Scripts.witness2of2(localSig, remoteSig, localFundingPubkey.publicKey, remoteFundingPubkey)
5455
signedTx = unsignedTx.updateWitness(0, witness)

eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BitcoinCoreClient.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ class BitcoinCoreClient(val rpcClient: BitcoinJsonRPCClient, val lockUtxos: Bool
305305
})
306306
}
307307

308-
private def utxoUpdatePsbt(psbt: Psbt)(implicit ec: ExecutionContext): Future[Psbt] = {
308+
def utxoUpdatePsbt(psbt: Psbt)(implicit ec: ExecutionContext): Future[Psbt] = {
309309
val encoded = Base64.getEncoder.encodeToString(Psbt.write(psbt).toByteArray)
310310
rpcClient.invoke("utxoupdatepsbt", encoded).map(json => {
311311
val JString(base64) = json

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,10 @@ object LocalCommit {
218218
case class RemoteCommit(index: Long, spec: CommitmentSpec, txid: TxId, remotePerCommitmentPoint: PublicKey) {
219219
def sign(keyManager: ChannelKeyManager, params: ChannelParams, fundingTxIndex: Long, remoteFundingPubKey: PublicKey, commitInput: InputInfo): CommitSig = {
220220
val (remoteCommitTx, htlcTxs) = Commitment.makeRemoteTxs(keyManager, params.channelConfig, params.channelFeatures, index, params.localParams, params.remoteParams, fundingTxIndex, remoteFundingPubKey, commitInput, remotePerCommitmentPoint, spec)
221-
val sig = keyManager.sign(remoteCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex), TxOwner.Remote, params.commitmentFormat)
221+
val sig = keyManager.sign(remoteCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex), TxOwner.Remote, params.commitmentFormat, Nil)
222222
val channelKeyPath = keyManager.keyPath(params.localParams, params.channelConfig)
223223
val sortedHtlcTxs = htlcTxs.sortBy(_.input.outPoint.index)
224-
val htlcSigs = sortedHtlcTxs.map(keyManager.sign(_, keyManager.htlcPoint(channelKeyPath), remotePerCommitmentPoint, TxOwner.Remote, params.commitmentFormat))
224+
val htlcSigs = sortedHtlcTxs.map(keyManager.sign(_, keyManager.htlcPoint(channelKeyPath), remotePerCommitmentPoint, TxOwner.Remote, params.commitmentFormat, Nil))
225225
CommitSig(params.channelId, sig, htlcSigs.toList)
226226
}
227227
}
@@ -622,11 +622,11 @@ case class Commitment(fundingTxIndex: Long,
622622
// remote commitment will include all local proposed changes + remote acked changes
623623
val spec = CommitmentSpec.reduce(remoteCommit.spec, changes.remoteChanges.acked, changes.localChanges.proposed)
624624
val (remoteCommitTx, htlcTxs) = Commitment.makeRemoteTxs(keyManager, params.channelConfig, params.channelFeatures, remoteCommit.index + 1, params.localParams, params.remoteParams, fundingTxIndex, remoteFundingPubKey, commitInput, remoteNextPerCommitmentPoint, spec)
625-
val sig = keyManager.sign(remoteCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex), TxOwner.Remote, params.commitmentFormat)
625+
val sig = keyManager.sign(remoteCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex), TxOwner.Remote, params.commitmentFormat, Nil)
626626

627627
val sortedHtlcTxs: Seq[TransactionWithInputInfo] = htlcTxs.sortBy(_.input.outPoint.index)
628628
val channelKeyPath = keyManager.keyPath(params.localParams, params.channelConfig)
629-
val htlcSigs = sortedHtlcTxs.map(keyManager.sign(_, keyManager.htlcPoint(channelKeyPath), remoteNextPerCommitmentPoint, TxOwner.Remote, params.commitmentFormat))
629+
val htlcSigs = sortedHtlcTxs.map(keyManager.sign(_, keyManager.htlcPoint(channelKeyPath), remoteNextPerCommitmentPoint, TxOwner.Remote, params.commitmentFormat, Nil))
630630

631631
// NB: IN/OUT htlcs are inverted because this is the remote commit
632632
log.info(s"built remote commit number=${remoteCommit.index + 1} toLocalMsat=${spec.toLocal.toLong} toRemoteMsat=${spec.toRemote.toLong} htlc_in={} htlc_out={} feeratePerKw=${spec.commitTxFeerate} txid=${remoteCommitTx.tx.txid} fundingTxId=$fundingTxId", spec.htlcs.collect(DirectedHtlc.outgoing).map(_.id).mkString(","), spec.htlcs.collect(DirectedHtlc.incoming).map(_.id).mkString(","))
@@ -659,7 +659,7 @@ case class Commitment(fundingTxIndex: Long,
659659
/** Return a fully signed commit tx, that can be published as-is. */
660660
def fullySignedLocalCommitTx(params: ChannelParams, keyManager: ChannelKeyManager): CommitTx = {
661661
val unsignedCommitTx = localCommit.commitTxAndRemoteSig.commitTx
662-
val localSig = keyManager.sign(unsignedCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex), TxOwner.Local, params.commitmentFormat)
662+
val localSig = keyManager.sign(unsignedCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex), TxOwner.Local, params.commitmentFormat, Nil)
663663
val RemoteSignature.FullSignature(remoteSig) = localCommit.commitTxAndRemoteSig.remoteSig
664664
val commitTx = addSigs(unsignedCommitTx, keyManager.fundingPublicKey(params.localParams.fundingKeyPath, fundingTxIndex).publicKey, remoteFundingPubKey, localSig, remoteSig)
665665
// We verify the remote signature when receiving their commit_sig, so this check should always pass.

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ object Helpers {
701701
log.debug("making closing tx with closing fee={} and commitments:\n{}", closingFees.preferred, commitment.specs2String)
702702
val dustLimit = commitment.localParams.dustLimit.max(commitment.remoteParams.dustLimit)
703703
val closingTx = Transactions.makeClosingTx(commitment.commitInput, localScriptPubkey, remoteScriptPubkey, commitment.localParams.paysClosingFees, dustLimit, closingFees.preferred, commitment.localCommit.spec)
704-
val localClosingSig = keyManager.sign(closingTx, keyManager.fundingPublicKey(commitment.localParams.fundingKeyPath, commitment.fundingTxIndex), TxOwner.Local, commitment.params.commitmentFormat)
704+
val localClosingSig = keyManager.sign(closingTx, keyManager.fundingPublicKey(commitment.localParams.fundingKeyPath, commitment.fundingTxIndex), TxOwner.Local, commitment.params.commitmentFormat, Nil)
705705
val closingSigned = ClosingSigned(commitment.channelId, closingFees.preferred, localClosingSig, TlvStream(ClosingSignedTlv.FeeRange(closingFees.min, closingFees.max)))
706706
log.debug(s"signed closing txid=${closingTx.tx.txid} with closing fee=${closingSigned.feeSatoshis}")
707707
log.debug(s"closingTxid=${closingTx.tx.txid} closingTx=${closingTx.tx}}")
@@ -741,9 +741,9 @@ object Helpers {
741741
}
742742
val localFundingPubKey = keyManager.fundingPublicKey(commitment.localParams.fundingKeyPath, commitment.fundingTxIndex)
743743
val closingComplete = ClosingComplete(commitment.channelId, localScriptPubkey, remoteScriptPubkey, closingFee.fee, currentBlockHeight.toLong, TlvStream(Set(
744-
closingTxs.localAndRemote_opt.map(tx => ClosingTlv.CloserAndCloseeOutputs(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat))),
745-
closingTxs.localOnly_opt.map(tx => ClosingTlv.CloserOutputOnly(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat))),
746-
closingTxs.remoteOnly_opt.map(tx => ClosingTlv.CloseeOutputOnly(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat))),
744+
closingTxs.localAndRemote_opt.map(tx => ClosingTlv.CloserAndCloseeOutputs(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat, Nil))),
745+
closingTxs.localOnly_opt.map(tx => ClosingTlv.CloserOutputOnly(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat, Nil))),
746+
closingTxs.remoteOnly_opt.map(tx => ClosingTlv.CloseeOutputOnly(keyManager.sign(tx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat, Nil))),
747747
).flatten[ClosingTlv]))
748748
Right(closingTxs, closingComplete)
749749
}
@@ -774,7 +774,7 @@ object Helpers {
774774
closingTxsWithSigs.headOption match {
775775
case Some((closingTx, remoteSig, sigToTlv)) =>
776776
val localFundingPubKey = keyManager.fundingPublicKey(commitment.localParams.fundingKeyPath, commitment.fundingTxIndex)
777-
val localSig = keyManager.sign(closingTx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat)
777+
val localSig = keyManager.sign(closingTx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat, Nil)
778778
val signedClosingTx = Transactions.addSigs(closingTx, localFundingPubKey.publicKey, commitment.remoteFundingPubKey, localSig, remoteSig)
779779
Transactions.checkSpendable(signedClosingTx) match {
780780
case Failure(_) => Left(InvalidCloseSignature(commitment.channelId, signedClosingTx.tx.txid))
@@ -800,7 +800,7 @@ object Helpers {
800800
closingTxsWithSig.headOption match {
801801
case Some((closingTx, remoteSig)) =>
802802
val localFundingPubKey = keyManager.fundingPublicKey(commitment.localParams.fundingKeyPath, commitment.fundingTxIndex)
803-
val localSig = keyManager.sign(closingTx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat)
803+
val localSig = keyManager.sign(closingTx, localFundingPubKey, TxOwner.Local, commitment.params.commitmentFormat, Nil)
804804
val signedClosingTx = Transactions.addSigs(closingTx, localFundingPubKey.publicKey, commitment.remoteFundingPubKey, localSig, remoteSig)
805805
Transactions.checkSpendable(signedClosingTx) match {
806806
case Failure(_) => Left(InvalidCloseSignature(commitment.channelId, signedClosingTx.tx.txid))
@@ -882,7 +882,7 @@ object Helpers {
882882
// first we will claim our main output as soon as the delay is over
883883
val mainDelayedTx = withTxGenerationLog("local-main-delayed") {
884884
Transactions.makeClaimLocalDelayedOutputTx(tx, commitment.localParams.dustLimit, localRevocationPubkey, commitment.remoteParams.toSelfDelay, localDelayedPubkey, finalScriptPubKey, feeratePerKwDelayed).map(claimDelayed => {
885-
val sig = keyManager.sign(claimDelayed, keyManager.delayedPaymentPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat)
885+
val sig = keyManager.sign(claimDelayed, keyManager.delayedPaymentPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat, Nil)
886886
Transactions.addSigs(claimDelayed, sig)
887887
})
888888
}
@@ -947,7 +947,7 @@ object Helpers {
947947
if (hash2Preimage.contains(paymentHash)) {
948948
// We immediately spend incoming htlcs for which we have the preimage.
949949
Some(txInfo.input.outPoint -> withTxGenerationLog("htlc-success") {
950-
val localSig = keyManager.sign(txInfo, keyManager.htlcPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat)
950+
val localSig = keyManager.sign(txInfo, keyManager.htlcPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat, Nil)
951951
Right(Transactions.addSigs(txInfo, localSig, remoteSig, hash2Preimage(paymentHash), commitment.params.commitmentFormat))
952952
})
953953
} else if (failedIncomingHtlcs.contains(txInfo.htlcId)) {
@@ -968,7 +968,7 @@ object Helpers {
968968
// claim the output, we will learn the preimage from their transaction, otherwise we will get our funds
969969
// back after the timeout.
970970
Some(txInfo.input.outPoint -> withTxGenerationLog("htlc-timeout") {
971-
val localSig = keyManager.sign(txInfo, keyManager.htlcPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat)
971+
val localSig = keyManager.sign(txInfo, keyManager.htlcPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat, Nil)
972972
Right(Transactions.addSigs(txInfo, localSig, remoteSig, commitment.params.commitmentFormat))
973973
})
974974
}.flatten.toMap
@@ -991,7 +991,7 @@ object Helpers {
991991
// Note that this will return None if the transaction wasn't one of our HTLC transactions, which may happen
992992
// if our peer was able to claim the HTLC output before us (race condition between success and timeout).
993993
Transactions.makeHtlcDelayedTx(tx, commitment.localParams.dustLimit, localRevocationPubkey, commitment.remoteParams.toSelfDelay, localDelayedPubkey, finalScriptPubKey, feeratePerKwDelayed).map(claimDelayed => {
994-
val sig = keyManager.sign(claimDelayed, keyManager.delayedPaymentPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat)
994+
val sig = keyManager.sign(claimDelayed, keyManager.delayedPaymentPoint(channelKeyPath), localPerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat, Nil)
995995
Transactions.addSigs(claimDelayed, sig)
996996
})
997997
}
@@ -1073,13 +1073,13 @@ object Helpers {
10731073
params.commitmentFormat match {
10741074
case DefaultCommitmentFormat => withTxGenerationLog("remote-main") {
10751075
Transactions.makeClaimP2WPKHOutputTx(tx, params.localParams.dustLimit, localPubkey, finalScriptPubKey, feeratePerKwMain).map(claimMain => {
1076-
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), remotePerCommitmentPoint, TxOwner.Local, params.commitmentFormat)
1076+
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), remotePerCommitmentPoint, TxOwner.Local, params.commitmentFormat, Nil)
10771077
Transactions.addSigs(claimMain, localPubkey, sig)
10781078
})
10791079
}
10801080
case _: AnchorOutputsCommitmentFormat => withTxGenerationLog("remote-main-delayed") {
10811081
Transactions.makeClaimRemoteDelayedOutputTx(tx, params.localParams.dustLimit, localPaymentPoint, finalScriptPubKey, feeratePerKwMain).map(claimMain => {
1082-
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), TxOwner.Local, params.commitmentFormat)
1082+
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), TxOwner.Local, params.commitmentFormat, Nil)
10831083
Transactions.addSigs(claimMain, sig)
10841084
})
10851085
}
@@ -1126,7 +1126,7 @@ object Helpers {
11261126
if (hash2Preimage.contains(add.paymentHash)) {
11271127
// We immediately spend incoming htlcs for which we have the preimage.
11281128
Some(claimHtlcTx.input.outPoint -> withTxGenerationLog("claim-htlc-success") {
1129-
val sig = keyManager.sign(claimHtlcTx, keyManager.htlcPoint(channelKeyPath), remoteCommit.remotePerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat)
1129+
val sig = keyManager.sign(claimHtlcTx, keyManager.htlcPoint(channelKeyPath), remoteCommit.remotePerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat, Nil)
11301130
Right(Transactions.addSigs(claimHtlcTx, sig, hash2Preimage(add.paymentHash)))
11311131
})
11321132
} else if (failedIncomingHtlcs.contains(add.id)) {
@@ -1152,7 +1152,7 @@ object Helpers {
11521152
Transactions.makeClaimHtlcTimeoutTx(remoteCommitTx.tx, outputs, commitment.localParams.dustLimit, localHtlcPubkey, remoteHtlcPubkey, remoteRevocationPubkey, finalScriptPubKey, add, feeratePerKwHtlc, commitment.params.commitmentFormat)
11531153
}.map(claimHtlcTx => {
11541154
Some(claimHtlcTx.input.outPoint -> withTxGenerationLog("claim-htlc-timeout") {
1155-
val sig = keyManager.sign(claimHtlcTx, keyManager.htlcPoint(channelKeyPath), remoteCommit.remotePerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat)
1155+
val sig = keyManager.sign(claimHtlcTx, keyManager.htlcPoint(channelKeyPath), remoteCommit.remotePerCommitmentPoint, TxOwner.Local, commitment.params.commitmentFormat, Nil)
11561156
Right(Transactions.addSigs(claimHtlcTx, sig))
11571157
})
11581158
})
@@ -1220,13 +1220,13 @@ object Helpers {
12201220
case ct => ct.commitmentFormat match {
12211221
case DefaultCommitmentFormat => withTxGenerationLog("remote-main") {
12221222
Transactions.makeClaimP2WPKHOutputTx(commitTx, localParams.dustLimit, localPaymentPubkey, finalScriptPubKey, feerateMain).map(claimMain => {
1223-
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), remotePerCommitmentPoint, TxOwner.Local, commitmentFormat)
1223+
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), remotePerCommitmentPoint, TxOwner.Local, commitmentFormat, Nil)
12241224
Transactions.addSigs(claimMain, localPaymentPubkey, sig)
12251225
})
12261226
}
12271227
case _: AnchorOutputsCommitmentFormat => withTxGenerationLog("remote-main-delayed") {
12281228
Transactions.makeClaimRemoteDelayedOutputTx(commitTx, localParams.dustLimit, localPaymentPoint, finalScriptPubKey, feerateMain).map(claimMain => {
1229-
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), TxOwner.Local, commitmentFormat)
1229+
val sig = keyManager.sign(claimMain, keyManager.paymentPoint(channelKeyPath), TxOwner.Local, commitmentFormat, Nil)
12301230
Transactions.addSigs(claimMain, sig)
12311231
})
12321232
}
@@ -1236,7 +1236,7 @@ object Helpers {
12361236
// then we punish them by stealing their main output
12371237
val mainPenaltyTx = withTxGenerationLog("main-penalty") {
12381238
Transactions.makeMainPenaltyTx(commitTx, localParams.dustLimit, remoteRevocationPubkey, finalScriptPubKey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, feeratePenalty).map(txinfo => {
1239-
val sig = keyManager.sign(txinfo, keyManager.revocationPoint(channelKeyPath), remotePerCommitmentSecret, TxOwner.Local, commitmentFormat)
1239+
val sig = keyManager.sign(txinfo, keyManager.revocationPoint(channelKeyPath), remotePerCommitmentSecret, TxOwner.Local, commitmentFormat, Nil)
12401240
Transactions.addSigs(txinfo, sig)
12411241
})
12421242
}
@@ -1256,7 +1256,7 @@ object Helpers {
12561256
val htlcRedeemScript = htlcsRedeemScripts(txOut.publicKeyScript)
12571257
withTxGenerationLog("htlc-penalty") {
12581258
Transactions.makeHtlcPenaltyTx(commitTx, outputIndex, htlcRedeemScript, localParams.dustLimit, finalScriptPubKey, feeratePenalty).map(htlcPenalty => {
1259-
val sig = keyManager.sign(htlcPenalty, keyManager.revocationPoint(channelKeyPath), remotePerCommitmentSecret, TxOwner.Local, commitmentFormat)
1259+
val sig = keyManager.sign(htlcPenalty, keyManager.revocationPoint(channelKeyPath), remotePerCommitmentSecret, TxOwner.Local, commitmentFormat, Nil)
12601260
Transactions.addSigs(htlcPenalty, sig, remoteRevocationPubkey)
12611261
})
12621262
}
@@ -1312,7 +1312,7 @@ object Helpers {
13121312
val penaltyTxs = Transactions.makeClaimHtlcDelayedOutputPenaltyTxs(htlcTx, localParams.dustLimit, remoteRevocationPubkey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, finalScriptPubKey, feeratePerKwPenalty).flatMap(claimHtlcDelayedOutputPenaltyTx => {
13131313
withTxGenerationLog("htlc-delayed-penalty") {
13141314
claimHtlcDelayedOutputPenaltyTx.map(htlcDelayedPenalty => {
1315-
val sig = keyManager.sign(htlcDelayedPenalty, keyManager.revocationPoint(channelKeyPath), remotePerCommitmentSecret, TxOwner.Local, commitmentFormat)
1315+
val sig = keyManager.sign(htlcDelayedPenalty, keyManager.revocationPoint(channelKeyPath), remotePerCommitmentSecret, TxOwner.Local, commitmentFormat, Nil)
13161316
val signedTx = Transactions.addSigs(htlcDelayedPenalty, sig)
13171317
// We need to make sure that the tx is indeed valid.
13181318
Transaction.correctlySpends(signedTx.tx, Seq(htlcTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)

0 commit comments

Comments
 (0)