mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-20 10:13:26 +01:00
Signer UTXOSpendingInfo refactor (#830)
* Refactored Signer interface to use TxSigComponent and UTXOSpendingInfo Fixed all the broken things Replaced TxSigComponent with unsigned Transaction in Signer interface to remove illegal states * Added p2sh throw case in Signer
This commit is contained in:
parent
19783ea546
commit
1b51ad689f
@ -6,7 +6,9 @@ import org.bitcoins.core.policy.Policy
|
||||
import org.bitcoins.core.protocol.script._
|
||||
import org.bitcoins.core.protocol.transaction._
|
||||
import org.bitcoins.core.script.crypto.HashType
|
||||
import org.bitcoins.core.script.flag.ScriptFlag
|
||||
import org.bitcoins.core.wallet.builder.TxBuilderError
|
||||
import org.bitcoins.core.wallet.utxo.UTXOSpendingInfo
|
||||
import scodec.bits.ByteVector
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
@ -16,50 +18,37 @@ sealed abstract class Signer {
|
||||
|
||||
/**
|
||||
* The method used to sign a bitcoin unspent transaction output
|
||||
* @param signers the [[Signer]] needed to sign the utxo
|
||||
* @param output the utxo we are spending
|
||||
* @param unsignedTx the unsigned transaction which is spending the utxo
|
||||
* @param inputIndex the input index inside of the unsigned transaction which spends the utxo
|
||||
* @param hashType the signature hashing algorithm we should use to sign the utxo
|
||||
* @param spendingInfo - The information required for signing
|
||||
* @param unsignedTx the external Transaction that needs an input signed
|
||||
* @param isDummySignature - do not sign the tx for real, just use a dummy signature this is useful for fee estimation
|
||||
* @return
|
||||
*/
|
||||
def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
sign(signers,
|
||||
output,
|
||||
unsignedTx,
|
||||
inputIndex,
|
||||
hashType,
|
||||
isDummySignature,
|
||||
overrides = NestedSigning.NoOverrides)
|
||||
sign(
|
||||
spendingInfo,
|
||||
unsignedTx,
|
||||
isDummySignature,
|
||||
scriptPubKeyToSatisfy = spendingInfo.output.scriptPubKey
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The method used to sign a bitcoin unspent transaction output that is potentially nested
|
||||
* @param signers the [[Signer]] needed to sign the utxo
|
||||
* @param output the utxo we are spending
|
||||
* @param unsignedTx the unsigned transaction which is spending the utxo
|
||||
* @param inputIndex the input index inside of the unsigned transaction which spends the utxo
|
||||
* @param hashType the signature hashing algorithm we should use to sign the utxo
|
||||
* @param spendingInfo - The information required for signing
|
||||
* @param unsignedTx the external Transaction that needs an input signed
|
||||
* @param isDummySignature - do not sign the tx for real, just use a dummy signature this is useful for fee estimation
|
||||
* @param overrides specifies things that should be overriden when signing such as TxSigComponent if this is nested
|
||||
* @param scriptPubKeyToSatisfy - specifies the ScriptPubKey for which a ScriptSignature needs to be generated
|
||||
* @return
|
||||
*/
|
||||
def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent]
|
||||
|
||||
def doSign(
|
||||
@ -74,80 +63,61 @@ sealed abstract class Signer {
|
||||
TransactionSignatureCreator.createSig(sigComponent, sign, hashType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** For use when signing nested ScriptPubKeys.
|
||||
*
|
||||
* This will require the hash to be signed to come from some external
|
||||
* (to the Signer being used) TxSigComponent (think P2SH, P2WSH).
|
||||
*
|
||||
* This will also require that the ScriptPubKey that the nested Signer
|
||||
* looks at needs to be overriden (not output.scriptPubKey)
|
||||
*/
|
||||
sealed abstract class OverridesForNestedSigning {
|
||||
protected val flags: Seq[ScriptFlag] = Policy.standardFlags
|
||||
|
||||
/** Depending on the external [[ScriptPubKey scriptpubkey]] type, there
|
||||
* are different rules for which script is meant to be signed.
|
||||
*
|
||||
* For instance, if you are spending a [[P2PKHScriptPubKey p2pkh]]
|
||||
* you sign the p2pkh script itself.
|
||||
*
|
||||
* If you are signing a [[P2WPKHWitnessSPKV0 p2wpkh spk]], you sign the
|
||||
* re-constructed [[P2PKHScriptPubKey p2pkh]] that is associated with p2wpkh script.
|
||||
*
|
||||
* If you are signing a [[LockTimeScriptPubKey locktime spk]], you must sign
|
||||
* the entire [[LockTimeScriptPubKey]], not the nested script.
|
||||
*/
|
||||
def sigComponentToSignOpt: Option[TxSigComponent]
|
||||
|
||||
/** This represents the [[ScriptPubKey scriptpubkey]] for which a valid ScriptSignature is
|
||||
* being generated. This is usually some nested SPK such as a redeem script in P2SH and P2WSH.
|
||||
*/
|
||||
def scriptPubKeyToSatisfyOpt: Option[ScriptPubKey]
|
||||
}
|
||||
|
||||
object NestedSigning {
|
||||
|
||||
/** The NoOverrides case where a Signer is used raw, without nesting */
|
||||
case object NoOverrides extends OverridesForNestedSigning {
|
||||
override val sigComponentToSignOpt: Option[TxSigComponent] = None
|
||||
override val scriptPubKeyToSatisfyOpt: Option[ScriptPubKey] = None
|
||||
protected def relevantInfo(
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction): (Seq[Sign], TransactionOutput, UInt32, HashType) = {
|
||||
(spendingInfo.signers,
|
||||
spendingInfo.output,
|
||||
inputIndex(spendingInfo, unsignedTx),
|
||||
spendingInfo.hashType)
|
||||
}
|
||||
|
||||
/** For P2WSH signing, this will be passed to the nested Signer */
|
||||
case class P2WSHOverrides(
|
||||
externalSigComponent: TxSigComponent,
|
||||
redeemScript: ScriptPubKey)
|
||||
extends OverridesForNestedSigning {
|
||||
override val sigComponentToSignOpt: Option[TxSigComponent] = Some(
|
||||
externalSigComponent)
|
||||
override val scriptPubKeyToSatisfyOpt: Option[ScriptPubKey] = Some(
|
||||
redeemScript)
|
||||
protected def inputIndex(
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
tx: Transaction): UInt32 = {
|
||||
tx.inputs.zipWithIndex
|
||||
.find(_._1.previousOutput == spendingInfo.outPoint) match {
|
||||
case Some((_, index)) => UInt32(index)
|
||||
case None =>
|
||||
throw new IllegalArgumentException(
|
||||
"Transaction did not contain expected input.")
|
||||
}
|
||||
}
|
||||
|
||||
/** For Locktime signing, this will be passed to the nested Signer.
|
||||
*
|
||||
* @param nestedSPK This should be [[LockTimeScriptPubKey.nestedScriptPubKey]]
|
||||
*/
|
||||
case class LockTimeOverrides(nestedSPK: ScriptPubKey)
|
||||
extends OverridesForNestedSigning {
|
||||
override val sigComponentToSignOpt: Option[TxSigComponent] = None
|
||||
override val scriptPubKeyToSatisfyOpt: Option[ScriptPubKey] = Some(
|
||||
nestedSPK)
|
||||
}
|
||||
protected def sigComponent(
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction): TxSigComponent = {
|
||||
val index = inputIndex(spendingInfo, unsignedTx)
|
||||
|
||||
/** For signing when a LockTime script is nested, such as within P2WSH.
|
||||
*
|
||||
* @param nestedSPK This should be [[LockTimeScriptPubKey.nestedScriptPubKey]]
|
||||
*/
|
||||
case class NestedLockTimeOverrides(
|
||||
externalSigComponent: TxSigComponent,
|
||||
nestedSPK: ScriptPubKey)
|
||||
extends OverridesForNestedSigning {
|
||||
override val sigComponentToSignOpt: Option[TxSigComponent] = Some(
|
||||
externalSigComponent)
|
||||
override val scriptPubKeyToSatisfyOpt: Option[ScriptPubKey] = Some(
|
||||
nestedSPK)
|
||||
spendingInfo.output.scriptPubKey match {
|
||||
case _: WitnessScriptPubKey =>
|
||||
val wtx = unsignedTx match {
|
||||
case btx: BaseTransaction =>
|
||||
val transactionWitnessOpt =
|
||||
spendingInfo.scriptWitnessOpt.map(scriptWit =>
|
||||
TransactionWitness(Vector(scriptWit)))
|
||||
val transactionWitness =
|
||||
transactionWitnessOpt.getOrElse(EmptyWitness)
|
||||
|
||||
WitnessTransaction(btx.version,
|
||||
btx.inputs,
|
||||
btx.outputs,
|
||||
btx.lockTime,
|
||||
transactionWitness)
|
||||
case wtx: WitnessTransaction => wtx
|
||||
}
|
||||
|
||||
WitnessTxSigComponent(wtx, index, spendingInfo.output, flags)
|
||||
case _: P2SHScriptPubKey =>
|
||||
throw new IllegalStateException(
|
||||
"Signers do not currently interface with P2SH as this is handled externally in TxBuilder.scala"
|
||||
)
|
||||
case _: ScriptPubKey =>
|
||||
BaseTxSigComponent(unsignedTx, index, spendingInfo.output, flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,34 +128,26 @@ sealed abstract class BitcoinSigner extends Signer
|
||||
sealed abstract class P2PKSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
val spk = overrides.scriptPubKeyToSatisfyOpt match {
|
||||
case None => output.scriptPubKey
|
||||
case Some(nestedScript) => nestedScript
|
||||
}
|
||||
val (signers, output, inputIndex, hashType) =
|
||||
relevantInfo(spendingInfo, unsignedTx)
|
||||
if (signers.size != 1) {
|
||||
Future.fromTry(TxBuilderError.TooManySigners)
|
||||
} else {
|
||||
val sign: ByteVector => Future[ECDigitalSignature] =
|
||||
signers.head.signFunction
|
||||
val unsignedInput = unsignedTx.inputs(inputIndex.toInt)
|
||||
val flags = Policy.standardFlags
|
||||
|
||||
val signed: Future[TxSigComponent] = spk match {
|
||||
val signed: Future[TxSigComponent] = scriptPubKeyToSatisfy match {
|
||||
case _: P2PKScriptPubKey =>
|
||||
val sigComponent = overrides.sigComponentToSignOpt match {
|
||||
case None =>
|
||||
BaseTxSigComponent(unsignedTx, inputIndex, output, flags)
|
||||
case Some(sigComponent) => sigComponent
|
||||
}
|
||||
val signature = doSign(sigComponent, sign, hashType, isDummySignature)
|
||||
val signature = doSign(sigComponent(spendingInfo, unsignedTx),
|
||||
sign,
|
||||
hashType,
|
||||
isDummySignature)
|
||||
signature.map { sig =>
|
||||
val p2pkScriptSig = P2PKScriptSignature(sig)
|
||||
val signedInput = TransactionInput(unsignedInput.previousOutput,
|
||||
@ -226,38 +188,30 @@ object P2PKSigner extends P2PKSigner
|
||||
sealed abstract class P2PKHSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
val spk = overrides.scriptPubKeyToSatisfyOpt match {
|
||||
case None => output.scriptPubKey
|
||||
case Some(nestedScript) => nestedScript
|
||||
}
|
||||
val (signers, output, inputIndex, hashType) =
|
||||
relevantInfo(spendingInfo, unsignedTx)
|
||||
if (signers.size != 1) {
|
||||
Future.fromTry(TxBuilderError.TooManySigners)
|
||||
} else {
|
||||
val sign = signers.head.signFunction
|
||||
val pubKey = signers.head.publicKey
|
||||
val unsignedInput = unsignedTx.inputs(inputIndex.toInt)
|
||||
val flags = Policy.standardFlags
|
||||
|
||||
val signed: Future[TxSigComponent] = spk match {
|
||||
val signed: Future[TxSigComponent] = scriptPubKeyToSatisfy match {
|
||||
case p2pkh: P2PKHScriptPubKey =>
|
||||
if (p2pkh != P2PKHScriptPubKey(pubKey)) {
|
||||
Future.fromTry(TxBuilderError.WrongPublicKey)
|
||||
} else {
|
||||
val sigComponent = overrides.sigComponentToSignOpt match {
|
||||
case None =>
|
||||
BaseTxSigComponent(unsignedTx, inputIndex, output, flags)
|
||||
case Some(sigComponent) => sigComponent
|
||||
}
|
||||
val signature =
|
||||
doSign(sigComponent, sign, hashType, isDummySignature)
|
||||
doSign(sigComponent(spendingInfo, unsignedTx),
|
||||
sign,
|
||||
hashType,
|
||||
isDummySignature)
|
||||
signature.map { sig =>
|
||||
val p2pkhScriptSig = P2PKHScriptSignature(sig, pubKey)
|
||||
val signedInput = TransactionInput(unsignedInput.previousOutput,
|
||||
@ -298,37 +252,30 @@ object P2PKHSigner extends P2PKHSigner
|
||||
sealed abstract class MultiSigSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(
|
||||
signersWithPubKeys: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
val spk = overrides.scriptPubKeyToSatisfyOpt match {
|
||||
case None => output.scriptPubKey
|
||||
case Some(nestedScript) => nestedScript
|
||||
}
|
||||
val (signersWithPubKeys, output, inputIndex, hashType) =
|
||||
relevantInfo(spendingInfo, unsignedTx)
|
||||
val signers = signersWithPubKeys.map(_.signFunction)
|
||||
val unsignedInput = unsignedTx.inputs(inputIndex.toInt)
|
||||
val flags = Policy.standardFlags
|
||||
|
||||
val signed: Future[TxSigComponent] = spk match {
|
||||
val signed: Future[TxSigComponent] = scriptPubKeyToSatisfy match {
|
||||
case multiSigSPK: MultiSignatureScriptPubKey =>
|
||||
val requiredSigs = multiSigSPK.requiredSigs
|
||||
if (signers.size < requiredSigs) {
|
||||
Future.fromTry(TxBuilderError.WrongSigner)
|
||||
} else {
|
||||
val sigComponent = overrides.sigComponentToSignOpt match {
|
||||
case None =>
|
||||
BaseTxSigComponent(unsignedTx, inputIndex, output, flags)
|
||||
case Some(sigComponent) => sigComponent
|
||||
}
|
||||
val signaturesNested = 0
|
||||
.until(requiredSigs)
|
||||
.map(i =>
|
||||
doSign(sigComponent, signers(i), hashType, isDummySignature))
|
||||
.map(
|
||||
i =>
|
||||
doSign(sigComponent(spendingInfo, unsignedTx),
|
||||
signers(i),
|
||||
hashType,
|
||||
isDummySignature))
|
||||
val signatures = Future.sequence(signaturesNested)
|
||||
signatures.map { sigs =>
|
||||
val multiSigScriptSig = MultiSignatureScriptSignature(sigs)
|
||||
@ -350,10 +297,7 @@ sealed abstract class MultiSigSigner extends BitcoinSigner {
|
||||
wtx.lockTime,
|
||||
wtx.witness)
|
||||
}
|
||||
BaseTxSigComponent(signedTx,
|
||||
inputIndex,
|
||||
output,
|
||||
Policy.standardFlags)
|
||||
BaseTxSigComponent(signedTx, inputIndex, output, flags)
|
||||
}
|
||||
}
|
||||
case _: P2PKScriptPubKey | _: P2PKHScriptPubKey | _: P2SHScriptPubKey |
|
||||
@ -370,18 +314,18 @@ sealed abstract class MultiSigSigner extends BitcoinSigner {
|
||||
object MultiSigSigner extends MultiSigSigner
|
||||
|
||||
sealed abstract class P2WPKHSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] =
|
||||
if (overrides != NestedSigning.NoOverrides) {
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
if (scriptPubKeyToSatisfy != spendingInfo.output.scriptPubKey) {
|
||||
Future.fromTry(TxBuilderError.NestedWitnessSPK)
|
||||
} else {
|
||||
val (signers, output, inputIndex, hashType) =
|
||||
relevantInfo(spendingInfo, unsignedTx)
|
||||
unsignedTx match {
|
||||
case wtx: WitnessTransaction =>
|
||||
if (signers.size != 1) {
|
||||
@ -424,7 +368,7 @@ sealed abstract class P2WPKHSigner extends BitcoinSigner {
|
||||
val wtxComp = WitnessTxSigComponentRaw(unsignedWtx,
|
||||
inputIndex,
|
||||
witOutput,
|
||||
Policy.standardFlags)
|
||||
flags)
|
||||
|
||||
val signature = doSign(wtxComp, sign, hashType, isDummySignature)
|
||||
|
||||
@ -437,10 +381,7 @@ sealed abstract class P2WPKHSigner extends BitcoinSigner {
|
||||
unsignedWtx.outputs,
|
||||
unsignedWtx.lockTime,
|
||||
signedTxWitness)
|
||||
WitnessTxSigComponentRaw(signedTx,
|
||||
inputIndex,
|
||||
witOutput,
|
||||
Policy.standardFlags)
|
||||
WitnessTxSigComponentRaw(signedTx, inputIndex, witOutput, flags)
|
||||
}
|
||||
|
||||
}
|
||||
@ -452,27 +393,27 @@ sealed abstract class P2WPKHSigner extends BitcoinSigner {
|
||||
btx.outputs,
|
||||
btx.lockTime,
|
||||
EmptyWitness)
|
||||
sign(signers, output, wtx, inputIndex, hashType, isDummySignature)
|
||||
|
||||
sign(spendingInfo, wtx, isDummySignature)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
object P2WPKHSigner extends P2WPKHSigner
|
||||
|
||||
sealed abstract class P2WSHSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
if (overrides != NestedSigning.NoOverrides) {
|
||||
if (scriptPubKeyToSatisfy != spendingInfo.output.scriptPubKey) {
|
||||
Future.fromTry(TxBuilderError.NestedWitnessSPK)
|
||||
} else {
|
||||
val (_, output, inputIndex, _) = relevantInfo(spendingInfo, unsignedTx)
|
||||
val spk = output.scriptPubKey
|
||||
val flags = Policy.standardFlags
|
||||
|
||||
spk match {
|
||||
case _: P2WSHWitnessSPKV0 =>
|
||||
@ -491,8 +432,7 @@ sealed abstract class P2WSHSigner extends BitcoinSigner {
|
||||
Future.fromTry(TxBuilderError.NoRedeemScript)
|
||||
case EmptyScriptWitness => Future.fromTry(TxBuilderError.NoWitness)
|
||||
}
|
||||
val sigComponent =
|
||||
WitnessTxSigComponentRaw(wtx, inputIndex, output, flags)
|
||||
|
||||
val signerF: Future[Signer] = redeemScriptF.flatMap {
|
||||
case _: P2PKScriptPubKey => Future.successful(P2PKSigner)
|
||||
case _: P2PKHScriptPubKey => Future.successful(P2PKHSigner)
|
||||
@ -510,14 +450,7 @@ sealed abstract class P2WSHSigner extends BitcoinSigner {
|
||||
}
|
||||
val signedSigComponentF = signerF.flatMap { signer =>
|
||||
redeemScriptF.flatMap { redeemScript =>
|
||||
signer.sign(
|
||||
signers,
|
||||
output,
|
||||
wtx,
|
||||
inputIndex,
|
||||
hashType,
|
||||
isDummySignature,
|
||||
NestedSigning.P2WSHOverrides(sigComponent, redeemScript))
|
||||
signer.sign(spendingInfo, wtx, isDummySignature, redeemScript)
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,21 +485,14 @@ sealed abstract class P2WSHSigner extends BitcoinSigner {
|
||||
object P2WSHSigner extends P2WSHSigner
|
||||
|
||||
sealed abstract class LockTimeSigner extends BitcoinSigner {
|
||||
override def sign(
|
||||
signers: Seq[Sign],
|
||||
output: TransactionOutput,
|
||||
unsignedTx: Transaction,
|
||||
inputIndex: UInt32,
|
||||
hashType: HashType,
|
||||
isDummySignature: Boolean,
|
||||
overrides: OverridesForNestedSigning)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
val spk = overrides.scriptPubKeyToSatisfyOpt match {
|
||||
case None => output.scriptPubKey
|
||||
case Some(nestedScript) => nestedScript
|
||||
}
|
||||
|
||||
spk match {
|
||||
override def sign(
|
||||
spendingInfo: UTXOSpendingInfo,
|
||||
unsignedTx: Transaction,
|
||||
isDummySignature: Boolean,
|
||||
scriptPubKeyToSatisfy: ScriptPubKey)(
|
||||
implicit ec: ExecutionContext): Future[TxSigComponent] = {
|
||||
scriptPubKeyToSatisfy match {
|
||||
case lockSPK: LockTimeScriptPubKey =>
|
||||
val signerF = lockSPK.nestedScriptPubKey match {
|
||||
case _: P2PKScriptPubKey => Future.successful(P2PKSigner)
|
||||
@ -580,23 +506,10 @@ sealed abstract class LockTimeSigner extends BitcoinSigner {
|
||||
Future.fromTry(TxBuilderError.WrongSigner)
|
||||
}
|
||||
signerF.flatMap { signer =>
|
||||
val overridesForNestedSigning =
|
||||
overrides.sigComponentToSignOpt match {
|
||||
case None =>
|
||||
NestedSigning.LockTimeOverrides(lockSPK.nestedScriptPubKey)
|
||||
case Some(sigComponent) =>
|
||||
NestedSigning.NestedLockTimeOverrides(
|
||||
externalSigComponent = sigComponent,
|
||||
lockSPK.nestedScriptPubKey)
|
||||
}
|
||||
|
||||
signer.sign(signers,
|
||||
output,
|
||||
signer.sign(spendingInfo,
|
||||
unsignedTx,
|
||||
inputIndex,
|
||||
hashType,
|
||||
isDummySignature,
|
||||
overridesForNestedSigning)
|
||||
lockSPK.nestedScriptPubKey)
|
||||
}
|
||||
case _: P2SHScriptPubKey => Future.fromTry(TxBuilderError.NestedP2SHSPK)
|
||||
case _: P2WPKHWitnessSPKV0 | _: P2WSHWitnessSPKV0 =>
|
||||
|
@ -11,6 +11,7 @@ import org.bitcoins.core.script.constant.ScriptNumber
|
||||
import org.bitcoins.core.script.crypto.HashType
|
||||
import org.bitcoins.core.util.BitcoinSLogger
|
||||
import org.bitcoins.core.wallet.signer.{MultiSigSigner, P2PKHSigner, P2PKSigner}
|
||||
import org.bitcoins.core.wallet.utxo.BitcoinUTXOSpendingInfo
|
||||
import org.scalacheck.Gen
|
||||
|
||||
import scala.concurrent.Await
|
||||
@ -296,13 +297,14 @@ sealed abstract class ScriptGenerators extends BitcoinSLogger {
|
||||
creditingTx,
|
||||
scriptSig,
|
||||
outputIndex)
|
||||
txSigComponentFuture = P2PKSigner.sign(
|
||||
Seq(privateKey),
|
||||
spendingInfo = BitcoinUTXOSpendingInfo(
|
||||
TransactionOutPoint(creditingTx.txIdBE, inputIndex),
|
||||
creditingTx.outputs(outputIndex.toInt),
|
||||
spendingTx,
|
||||
inputIndex,
|
||||
hashType,
|
||||
false)
|
||||
Seq(privateKey),
|
||||
None,
|
||||
None,
|
||||
hashType)
|
||||
txSigComponentFuture = P2PKSigner.sign(spendingInfo, spendingTx, false)
|
||||
txSigComponent = Await.result(txSigComponentFuture, timeout)
|
||||
//add the signature to the scriptSig instead of having an empty scriptSig
|
||||
signedScriptSig = txSigComponent.scriptSignature
|
||||
@ -330,13 +332,14 @@ sealed abstract class ScriptGenerators extends BitcoinSLogger {
|
||||
creditingTx,
|
||||
EmptyScriptSignature,
|
||||
outputIndex)
|
||||
txSigComponentFuture = P2PKHSigner.sign(
|
||||
Seq(privateKey),
|
||||
spendingInfo = BitcoinUTXOSpendingInfo(
|
||||
TransactionOutPoint(creditingTx.txIdBE, inputIndex),
|
||||
creditingTx.outputs(outputIndex.toInt),
|
||||
unsignedTx,
|
||||
inputIndex,
|
||||
hashType,
|
||||
false)
|
||||
Seq(privateKey),
|
||||
None,
|
||||
None,
|
||||
hashType)
|
||||
txSigComponentFuture = P2PKHSigner.sign(spendingInfo, unsignedTx, false)
|
||||
txSigComponent = Await.result(txSigComponentFuture, timeout)
|
||||
signedScriptSig = txSigComponent.scriptSignature
|
||||
.asInstanceOf[P2PKHScriptSignature]
|
||||
@ -369,13 +372,16 @@ sealed abstract class ScriptGenerators extends BitcoinSLogger {
|
||||
creditingTx,
|
||||
scriptSig,
|
||||
outputIndex)
|
||||
txSigComponentFuture = MultiSigSigner.sign(
|
||||
privateKeys,
|
||||
spendingInfo = BitcoinUTXOSpendingInfo(
|
||||
TransactionOutPoint(creditingTx.txIdBE, inputIndex),
|
||||
creditingTx.outputs(outputIndex.toInt),
|
||||
spendingTx,
|
||||
inputIndex,
|
||||
hashType,
|
||||
false)
|
||||
privateKeys,
|
||||
None,
|
||||
None,
|
||||
hashType)
|
||||
txSigComponentFuture = MultiSigSigner.sign(spendingInfo,
|
||||
spendingTx,
|
||||
false)
|
||||
txSigComponent = Await.result(txSigComponentFuture, timeout)
|
||||
signedScriptSig = txSigComponent.scriptSignature
|
||||
.asInstanceOf[MultiSignatureScriptSignature]
|
||||
|
Loading…
Reference in New Issue
Block a user