Skip to content

Commit d6689dd

Browse files
committed
Refactor tx signing (no functional changes)
1 parent c45d278 commit d6689dd

File tree

6 files changed

+72
-65
lines changed

6 files changed

+72
-65
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ object LocalCommit {
228228
fundingTxIndex: Long, remoteFundingPubKey: PublicKey, commitInput: InputInfo,
229229
commit: CommitSig, localCommitIndex: Long, spec: CommitmentSpec, localPerCommitmentPoint: PublicKey): Either[ChannelException, LocalCommit] = {
230230
val (localCommitTx, htlcTxs) = Commitment.makeLocalTxs(keyManager, params.channelConfig, params.channelFeatures, localCommitIndex, params.localParams, params.remoteParams, fundingTxIndex, remoteFundingPubKey, commitInput, localPerCommitmentPoint, spec)
231-
if (!checkSig(localCommitTx, commit.signature, remoteFundingPubKey, TxOwner.Remote, params.commitmentFormat)) {
231+
if (!localCommitTx.checkSig(commit.signature, remoteFundingPubKey, TxOwner.Remote, params.commitmentFormat)) {
232232
return Left(InvalidCommitmentSignature(params.channelId, fundingTxId, fundingTxIndex, localCommitTx.tx))
233233
}
234234
val sortedHtlcTxs = htlcTxs.sortBy(_.input.outPoint.index)
@@ -238,7 +238,7 @@ object LocalCommit {
238238
val remoteHtlcPubkey = Generators.derivePubKey(params.remoteParams.htlcBasepoint, localPerCommitmentPoint)
239239
val htlcTxsAndRemoteSigs = sortedHtlcTxs.zip(commit.htlcSignatures).toList.map {
240240
case (htlcTx: HtlcTx, remoteSig) =>
241-
if (!checkSig(htlcTx, remoteSig, remoteHtlcPubkey, TxOwner.Remote, params.commitmentFormat)) {
241+
if (!htlcTx.checkSig(remoteSig, remoteHtlcPubkey, TxOwner.Remote, params.commitmentFormat)) {
242242
return Left(InvalidHtlcSignature(params.channelId, htlcTx.tx.txid))
243243
}
244244
HtlcTxAndRemoteSig(htlcTx, remoteSig)

eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalChannelKeyManager.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class LocalChannelKeyManager(seed: ByteVector, chainHash: BlockHash) extends Cha
113113
Metrics.SignTxCount.withTags(tags).increment()
114114
KamonExt.time(Metrics.SignTxDuration.withTags(tags)) {
115115
val privateKey = privateKeys.get(publicKey.path)
116-
Transactions.sign(tx, privateKey.privateKey, txOwner, commitmentFormat)
116+
tx.sign(privateKey.privateKey, txOwner, commitmentFormat)
117117
}
118118
}
119119

@@ -134,7 +134,7 @@ class LocalChannelKeyManager(seed: ByteVector, chainHash: BlockHash) extends Cha
134134
KamonExt.time(Metrics.SignTxDuration.withTags(tags)) {
135135
val privateKey = privateKeys.get(publicKey.path)
136136
val currentKey = Generators.derivePrivKey(privateKey.privateKey, remotePoint)
137-
Transactions.sign(tx, currentKey, txOwner, commitmentFormat)
137+
tx.sign(currentKey, txOwner, commitmentFormat)
138138
}
139139
}
140140

@@ -154,7 +154,7 @@ class LocalChannelKeyManager(seed: ByteVector, chainHash: BlockHash) extends Cha
154154
KamonExt.time(Metrics.SignTxDuration.withTags(tags)) {
155155
val privateKey = privateKeys.get(publicKey.path)
156156
val currentKey = Generators.revocationPrivKey(privateKey.privateKey, remoteSecret)
157-
Transactions.sign(tx, currentKey, txOwner, commitmentFormat)
157+
tx.sign(currentKey, txOwner, commitmentFormat)
158158
}
159159
}
160160

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

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,23 @@ object Transactions {
118118
}
119119
/** Sighash flags to use when signing the transaction. */
120120
def sighash(txOwner: TxOwner, commitmentFormat: CommitmentFormat): Int = SIGHASH_ALL
121+
122+
def sign(key: PrivateKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64 = Transactions.sign(this, key, sighash(txOwner, commitmentFormat))
123+
124+
def sign(key: PrivateKey, sighashType: Int): ByteVector64 = {
125+
// NB: the tx may have multiple inputs, we will only sign the one provided in txinfo.input. Bear in mind that the
126+
// signature will be invalidated if other inputs are added *afterwards* and sighashType was SIGHASH_ALL.
127+
val inputIndex = tx.txIn.zipWithIndex.find(_._1.outPoint == input.outPoint).get._2
128+
Transactions.sign(tx, input.redeemScript, input.txOut.amount, key, sighashType, inputIndex)
129+
}
130+
131+
def checkSig(sig: ByteVector64, pubKey: PublicKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): Boolean = {
132+
val sighash = this.sighash(txOwner, commitmentFormat)
133+
val data = Transaction.hashForSigning(tx, inputIndex = 0, input.redeemScript, sighash, input.txOut.amount, SIGVERSION_WITNESS_V0)
134+
Crypto.verifySignature(data, sig, pubKey)
135+
}
121136
}
137+
122138
sealed trait ReplaceableTransactionWithInputInfo extends TransactionWithInputInfo {
123139
/** Block before which the transaction must be confirmed. */
124140
def confirmationTarget: ConfirmationTarget
@@ -852,15 +868,13 @@ object Transactions {
852868
sig64
853869
}
854870

855-
def sign(txinfo: TransactionWithInputInfo, key: PrivateKey, sighashType: Int): ByteVector64 = {
871+
private def sign(txinfo: TransactionWithInputInfo, key: PrivateKey, sighashType: Int): ByteVector64 = {
856872
// NB: the tx may have multiple inputs, we will only sign the one provided in txinfo.input. Bear in mind that the
857873
// signature will be invalidated if other inputs are added *afterwards* and sighashType was SIGHASH_ALL.
858874
val inputIndex = txinfo.tx.txIn.zipWithIndex.find(_._1.outPoint == txinfo.input.outPoint).get._2
859875
sign(txinfo.tx, txinfo.input.redeemScript, txinfo.input.txOut.amount, key, sighashType, inputIndex)
860876
}
861877

862-
def sign(txinfo: TransactionWithInputInfo, key: PrivateKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64 = sign(txinfo, key, txinfo.sighash(txOwner, commitmentFormat))
863-
864878
def addSigs(commitTx: CommitTx, localFundingPubkey: PublicKey, remoteFundingPubkey: PublicKey, localSig: ByteVector64, remoteSig: ByteVector64): CommitTx = {
865879
val witness = Scripts.witness2of2(localSig, remoteSig, localFundingPubkey, remoteFundingPubkey)
866880
commitTx.copy(tx = commitTx.tx.updateWitness(0, witness))
@@ -935,11 +949,4 @@ object Transactions {
935949
// NB: we don't verify the other inputs as they should only be wallet inputs used to RBF the transaction
936950
Try(Transaction.correctlySpends(txinfo.tx, Map(txinfo.input.outPoint -> txinfo.input.txOut), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS))
937951
}
938-
939-
def checkSig(txinfo: TransactionWithInputInfo, sig: ByteVector64, pubKey: PublicKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): Boolean = {
940-
val sighash = txinfo.sighash(txOwner, commitmentFormat)
941-
val data = Transaction.hashForSigning(txinfo.tx, inputIndex = 0, txinfo.input.redeemScript, sighash, txinfo.input.txOut.amount, SIGVERSION_WITNESS_V0)
942-
Crypto.verifySignature(data, sig, pubKey)
943-
}
944-
945952
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,9 @@ trait TestVectorsSpec extends AnyFunSuite with Logging {
209209
remotePaymentBasePoint = Remote.payment_basepoint,
210210
localIsChannelOpener = true,
211211
outputs = outputs)
212-
val local_sig = Transactions.sign(tx, Local.funding_privkey, TxOwner.Local, commitmentFormat)
212+
val local_sig = tx.sign(Local.funding_privkey, TxOwner.Local, commitmentFormat)
213213
logger.info(s"# local_signature = ${Scripts.der(local_sig).dropRight(1).toHex}")
214-
val remote_sig = Transactions.sign(tx, Remote.funding_privkey, TxOwner.Remote, commitmentFormat)
214+
val remote_sig = tx.sign(Remote.funding_privkey, TxOwner.Remote, commitmentFormat)
215215
logger.info(s"remote_signature: ${Scripts.der(remote_sig).dropRight(1).toHex}")
216216
Transactions.addSigs(tx, Local.funding_pubkey, Remote.funding_pubkey, local_sig, remote_sig)
217217
}
@@ -248,8 +248,8 @@ trait TestVectorsSpec extends AnyFunSuite with Logging {
248248

249249
val signedTxs = htlcTxs.collect {
250250
case tx: HtlcSuccessTx =>
251-
val localSig = Transactions.sign(tx, Local.htlc_privkey, TxOwner.Local, commitmentFormat)
252-
val remoteSig = Transactions.sign(tx, Remote.htlc_privkey, TxOwner.Remote, commitmentFormat)
251+
val localSig = tx.sign(Local.htlc_privkey, TxOwner.Local, commitmentFormat)
252+
val remoteSig = tx.sign(Remote.htlc_privkey, TxOwner.Remote, commitmentFormat)
253253
val htlcIndex = htlcScripts.indexOf(Script.parse(tx.input.redeemScript))
254254
val preimage = paymentPreimages.find(p => Crypto.sha256(p) == tx.paymentHash).get
255255
val tx1 = Transactions.addSigs(tx, localSig, remoteSig, preimage, commitmentFormat)
@@ -260,8 +260,8 @@ trait TestVectorsSpec extends AnyFunSuite with Logging {
260260
logger.info(s"htlc_success_tx (htlc #$htlcIndex): ${tx1.tx}")
261261
tx1
262262
case tx: HtlcTimeoutTx =>
263-
val localSig = Transactions.sign(tx, Local.htlc_privkey, TxOwner.Local, commitmentFormat)
264-
val remoteSig = Transactions.sign(tx, Remote.htlc_privkey, TxOwner.Remote, commitmentFormat)
263+
val localSig = tx.sign(Local.htlc_privkey, TxOwner.Local, commitmentFormat)
264+
val remoteSig = tx.sign(Remote.htlc_privkey, TxOwner.Remote, commitmentFormat)
265265
val htlcIndex = htlcScripts.indexOf(Script.parse(tx.input.redeemScript))
266266
val tx1 = Transactions.addSigs(tx, localSig, remoteSig, commitmentFormat)
267267
Transaction.correctlySpends(tx1.tx, Seq(commitTx.tx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)

0 commit comments

Comments
 (0)