core: Fix divergence in behavior between TransactionSignatureSerializer.hashForSignature() methods (#5765)

This commit is contained in:
Chris Stewart 2024-11-13 10:03:40 -06:00 committed by GitHub
parent 17f965fd45
commit c5d57de618
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 25 deletions

View File

@ -1,15 +1,16 @@
package org.bitcoins.core.crypto
import org.bitcoins.core.number.{Int32, UInt32}
import org.bitcoins.core.policy.Policy
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.protocol.script.*
import org.bitcoins.core.protocol.transaction.*
import org.bitcoins.core.script.constant.ScriptToken
import org.bitcoins.core.script.crypto._
import org.bitcoins.core.script.crypto.*
import org.bitcoins.core.serializers.transaction.RawTransactionOutputParser
import org.bitcoins.core.util.{BitcoinScriptUtil, BytesUtil}
import org.bitcoins.core.wallet.utxo.{InputInfo, InputSigningInfo}
import org.bitcoins.crypto._
import org.bitcoins.crypto.*
import scodec.bits.ByteVector
/** Created by chris on 2/16/16. Wrapper that serializes like Transaction, but
@ -466,27 +467,13 @@ sealed abstract class TransactionSignatureSerializer {
spendingTransaction: Transaction,
signingInfo: InputSigningInfo[InputInfo],
hashType: HashType,
taprootOptions: TaprootSerializationOptions): DoubleSha256Digest = {
val inputIndexOpt =
TxUtil.inputIndexOpt(signingInfo.inputInfo, spendingTransaction)
if (inputIndexOpt.isEmpty) {
errorHash
} else if (
(hashType.isInstanceOf[SIGHASH_SINGLE] || hashType
.isInstanceOf[SIGHASH_SINGLE_ANYONECANPAY]) &&
inputIndexOpt.get >= spendingTransaction.outputs.size &&
signingInfo.sigVersion != SigVersionWitnessV0
) {
errorHash
} else {
val serializedTxForSignature =
serializeForSignature(spendingTransaction,
signingInfo,
hashType,
taprootOptions)
CryptoUtil.doubleSHA256(serializedTxForSignature)
}
taprootOptions: TaprootSerializationOptions): HashDigest = {
val txSigComponent = TxSigComponent(
inputInfo = signingInfo.inputInfo,
unsignedTx = spendingTransaction,
outputMap = signingInfo.inputInfo.previousOutputMap,
flags = Policy.standardFlags)
hashForSignature(txSigComponent, hashType, taprootOptions)
}
/** Sets the input's sequence number to zero EXCEPT for the input at

View File

@ -6,6 +6,7 @@ import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.script.*
import org.bitcoins.core.protocol.transaction.*
import org.bitcoins.core.script.constant.{OP_TRUE, ScriptConstant}
import org.bitcoins.core.script.util.PreviousOutputMap
import org.bitcoins.core.util.{BitcoinScriptUtil, BytesUtil}
import org.bitcoins.crypto.{
ECDigitalSignature,
@ -77,6 +78,8 @@ sealed trait InputInfo {
: ECSignatureParams[this.type] = {
signerMaterial.copy(inputInfo = this)
}
def previousOutputMap: PreviousOutputMap
}
object InputInfo {
@ -347,6 +350,7 @@ object InputInfo {
sealed trait RawInputInfo extends InputInfo {
override def scriptPubKey: RawScriptPubKey
override def previousOutputMap: PreviousOutputMap = PreviousOutputMap.empty
}
object RawInputInfo {
@ -422,6 +426,8 @@ case class EmptyInputInfo(outPoint: TransactionOutPoint, amount: CurrencyUnit)
ConditionalPath.NoCondition
override def pubKeys: Vector[ECPublicKey] = Vector.empty
override def requiredSigs: Int = 0
override def previousOutputMap: PreviousOutputMap = PreviousOutputMap.empty
}
case class P2PKInputInfo(
@ -550,6 +556,7 @@ case class LockTimeInputInfo(
sealed trait SegwitV0NativeInputInfo extends InputInfo {
def scriptWitness: ScriptWitnessV0
override def previousOutputMap: PreviousOutputMap = PreviousOutputMap.empty
}
object SegwitV0NativeInputInfo {
@ -623,6 +630,7 @@ case class UnassignedSegwitNativeInputInfo(
pubKeys: Vector[ECPublicKey])
extends InputInfo {
override def requiredSigs: Int = pubKeys.length
override def previousOutputMap: PreviousOutputMap = PreviousOutputMap.empty
}
sealed trait P2SHInputInfo extends InputInfo {
@ -637,6 +645,8 @@ sealed trait P2SHInputInfo extends InputInfo {
override def pubKeys: Vector[ECPublicKey] = nestedInputInfo.pubKeys
override def requiredSigs: Int = nestedInputInfo.requiredSigs
override def previousOutputMap: PreviousOutputMap = PreviousOutputMap.empty
}
case class P2SHNonSegwitInputInfo(