Refactoring WitnessTransactionSignatureComponent to take in a 'Transaction' type instead of a 'WitnessTransaction' type -- this is needed for the case of trying to spend a witness scriptPubKey with a base transaction. This won't succeed, but should be possible to try and run through the interpreter

This commit is contained in:
Chris Stewart 2016-12-16 15:21:18 -06:00
parent df18ddec51
commit 27d23b1ca9
6 changed files with 28 additions and 36 deletions

View file

@ -3,7 +3,7 @@ package org.bitcoins.core.crypto
import org.bitcoins.core.currency.CurrencyUnit
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutput, WitnessTransaction}
import org.bitcoins.core.protocol.transaction.{BaseTransaction, Transaction, TransactionOutput, WitnessTransaction}
import org.bitcoins.core.script.flag.ScriptFlag
/**
@ -44,9 +44,10 @@ sealed trait BaseTransactionSignatureComponent extends TransactionSignatureCompo
*/
sealed trait WitnessV0TransactionSignatureComponent extends TransactionSignatureComponent {
override def transaction: WitnessTransaction
def witness: ScriptWitness = transaction.witness.witnesses(inputIndex.toInt)
def witness: ScriptWitness = transaction match {
case wtx: WitnessTransaction => wtx.witness.witnesses(inputIndex.toInt)
case btx: BaseTransaction => EmptyScriptWitness
}
/** The amount of [[CurrencyUnit]] this input is spending */
def amount: CurrencyUnit
@ -60,7 +61,7 @@ object TransactionSignatureComponent {
scriptPubKey : ScriptPubKey, flags : Seq[ScriptFlag]) extends BaseTransactionSignatureComponent
def apply(transaction : WitnessTransaction, inputIndex : UInt32, scriptPubKey : ScriptPubKey,
def apply(transaction : Transaction, inputIndex : UInt32, scriptPubKey : ScriptPubKey,
flags : Seq[ScriptFlag], amount: CurrencyUnit, signatureVersion: SignatureVersion) : TransactionSignatureComponent = {
signatureVersion match {
case SigVersionBase =>
@ -88,19 +89,19 @@ object TransactionSignatureComponent {
}
object WitnessV0TransactionSignatureComponent {
private case class WitnessV0TransactionSignatureComponentImpl(transaction : WitnessTransaction, inputIndex : UInt32,
private case class WitnessV0TransactionSignatureComponentImpl(transaction : Transaction, inputIndex : UInt32,
scriptPubKey : ScriptPubKey, flags : Seq[ScriptFlag],
amount: CurrencyUnit, sigVersion: SignatureVersion) extends WitnessV0TransactionSignatureComponent
def apply(transaction : WitnessTransaction, inputIndex : UInt32, scriptPubKey : ScriptPubKey,
def apply(transaction : Transaction, inputIndex : UInt32, scriptPubKey : ScriptPubKey,
flags : Seq[ScriptFlag], amount: CurrencyUnit, sigVersion: SignatureVersion) : WitnessV0TransactionSignatureComponent = {
WitnessV0TransactionSignatureComponentImpl(transaction,inputIndex, scriptPubKey, flags, amount,sigVersion)
}
/** Note: The output passed here is the output we are spending,
* we use the [[CurrencyUnit]] and [[ScriptPubKey]] in that output for signing */
def apply(transaction : WitnessTransaction, inputIndex : UInt32, output : TransactionOutput,
def apply(transaction : Transaction, inputIndex : UInt32, output : TransactionOutput,
flags : Seq[ScriptFlag], sigVersion: SignatureVersion): WitnessV0TransactionSignatureComponent = {
WitnessV0TransactionSignatureComponent(transaction,inputIndex,output.scriptPubKey,flags,output.value, sigVersion)
}

View file

@ -162,7 +162,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki]]
* [[https://github.com/bitcoin/bitcoin/blob/f8528134fc188abc5c7175a19680206964a8fade/src/script/interpreter.cpp#L1113]]
*/
def serializeForSignature(spendingTx: WitnessTransaction, inputIndex: UInt32, script: Seq[ScriptToken], hashType: HashType,
def serializeForSignature(spendingTx: Transaction, inputIndex: UInt32, script: Seq[ScriptToken], hashType: HashType,
amount: CurrencyUnit, signatureVersion: SignatureVersion): Seq[Byte] = signatureVersion match {
case SigVersionBase =>
serializeForSignature(spendingTx,inputIndex,script,hashType)
@ -216,7 +216,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* [[https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki]]
* NOTE: This covers the amount of [[CurrencyUnit]] we are spending in the output
* */
def hashForSignature(spendingTx: WitnessTransaction, inputIndex: UInt32, script: Seq[ScriptToken], hashType: HashType,
def hashForSignature(spendingTx: Transaction, inputIndex: UInt32, script: Seq[ScriptToken], hashType: HashType,
amount: CurrencyUnit, sigVersion: SignatureVersion): DoubleSha256Digest = {
val serialization = serializeForSignature(spendingTx,inputIndex,script,hashType,amount,sigVersion)

View file

@ -21,6 +21,12 @@ sealed trait ScriptWitness extends NetworkElement {
override def hex = RawScriptWitnessParser.write(this)
}
case object EmptyScriptWitness extends ScriptWitness {
override def stack = Nil
override def hex = "00"
}
object ScriptWitness extends Factory[ScriptWitness] {
private case class ScriptWitnessImpl(stack: Seq[Seq[Byte]]) extends ScriptWitness
@ -28,10 +34,6 @@ object ScriptWitness extends Factory[ScriptWitness] {
override def fromBytes(bytes: Seq[Byte]): ScriptWitness = RawScriptWitnessParser.read(bytes)
/*
def fromHex(stack: Seq[Seq[String]]): ScriptWitness = ScriptWitness(stack.flatMap(_.map(BitcoinSUtil.decodeHex(_))))
*/
def apply(signature: ECDigitalSignature, publicKey: ECPublicKey): ScriptWitness = {
val sigConstant = signature.bytes
val pubKeyConstant = publicKey.bytes

View file

@ -233,7 +233,7 @@ object ScriptProgram {
* @param amount the amount of [[CurrencyUnit]] we are spending in this input
* @return the script program representing all of this information
*/
def apply(transaction: WitnessTransaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32,
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32,
flags : Seq[ScriptFlag],
amount: CurrencyUnit) : PreExecutionScriptProgram = {
val script = transaction.inputs(inputIndex.toInt).scriptSignature.asm
@ -246,13 +246,13 @@ object ScriptProgram {
ScriptProgram(p,stack,script)
}
def apply(transaction: WitnessTransaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, script : Seq[ScriptToken],
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, script : Seq[ScriptToken],
flags : Seq[ScriptFlag], amount: CurrencyUnit) : PreExecutionScriptProgram = {
val sigVersion = BitcoinScriptUtil.parseSigVersion(transaction,scriptPubKey,inputIndex)
ScriptProgram(transaction,scriptPubKey,inputIndex,Nil,script,script,Nil,flags,sigVersion,amount)
}
def apply(transaction: WitnessTransaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, stack : Seq[ScriptToken],
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, stack : Seq[ScriptToken],
script : Seq[ScriptToken], flags : Seq[ScriptFlag], witness: ScriptWitness,
amount: CurrencyUnit) : ScriptProgram = {
val program = ScriptProgram(transaction,scriptPubKey,inputIndex,flags, amount)
@ -290,7 +290,7 @@ object ScriptProgram {
}
/** Creates a fresh [[PreExecutionScriptProgram]] */
def apply(transaction: WitnessTransaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
def apply(transaction: Transaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
flags: Seq[ScriptFlag], sigVersion: SignatureVersion,
amount: CurrencyUnit): PreExecutionScriptProgram = {

View file

@ -4,7 +4,7 @@ import org.bitcoins.core.crypto._
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.script.{CLTVScriptPubKey, CSVScriptPubKey, EmptyScriptPubKey, _}
import org.bitcoins.core.protocol.transaction.WitnessTransaction
import org.bitcoins.core.protocol.transaction.{Transaction, WitnessTransaction}
import org.bitcoins.core.script.ScriptProgram.PreExecutionScriptProgramImpl
import org.bitcoins.core.script.constant._
import org.bitcoins.core.script.crypto.{OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, OP_CHECKSIG, OP_CHECKSIGVERIFY}
@ -382,14 +382,14 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
}
/** Given a tx, scriptPubKey and the input index we are checking the tx, it derives the appropriate [[SignatureVersion]] to use */
def parseSigVersion(wtx: WitnessTransaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32): SignatureVersion = scriptPubKey match {
def parseSigVersion(tx: Transaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32): SignatureVersion = scriptPubKey match {
case _ : WitnessScriptPubKeyV0 | _: UnassignedWitnessScriptPubKey =>
SigVersionWitnessV0
case _: P2SHScriptPubKey =>
val scriptSig = wtx.inputs(inputIndex.toInt).scriptSignature
val scriptSig = tx.inputs(inputIndex.toInt).scriptSignature
scriptSig match {
case s : P2SHScriptSignature =>
parseSigVersion(wtx,s.redeemScript,inputIndex)
parseSigVersion(tx,s.redeemScript,inputIndex)
case _ : P2PKScriptSignature | _: P2PKHScriptSignature | _:MultiSignatureScriptSignature | _: NonStandardScriptSignature
| _: CLTVScriptSignature | _: CSVScriptSignature | EmptyScriptSignature => SigVersionBase
}

View file

@ -66,19 +66,8 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
//use this to represent a single test case from script_valid.json
/* val lines =
"""
|[ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
| ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
| ["0000000000000000000000000000000000000000000000000000000000000100", 2, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1002],
| ["0000000000000000000000000000000000000000000000000000000000000100", 3, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1003],
| ["0000000000000000000000000000000000000000000000000000000000000100", 4, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1004],
| ["0000000000000000000000000000000000000000000000000000000000000100", 5, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1005],
| ["0000000000000000000000000000000000000000000000000000000000000100", 6, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1006],
| ["0000000000000000000000000000000000000000000000000000000000000100", 7, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1007],
| ["0000000000000000000000000000000000000000000000000000000000000100", 8, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1008],
| ["0000000000000000000000000000000000000000000000000000000000000100", 9, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1009],
| ["0000000000000000000000000000000000000000000000000000000000000100", 10, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1010],
| ["0000000000000000000000000000000000000000000000000000000000000100", 11, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1011]],
| "0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"]
|[ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
| "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS"]
|]
""".stripMargin*/
val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
@ -102,7 +91,7 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
"OutPoint txId not the same as input prevout txid\noutPoint.txId: " + outPoint.txId + "\n" +
"input prevout txid: " + input.previousOutput.txId)
val program = amountOpt match {
case Some(amount) => ScriptProgram(tx.asInstanceOf[WitnessTransaction],scriptPubKey,UInt32(inputIndex),testCase.flags,amount)
case Some(amount) => ScriptProgram(tx,scriptPubKey,UInt32(inputIndex),testCase.flags,amount)
case None => ScriptProgram(tx,scriptPubKey,UInt32(inputIndex),testCase.flags)
}