Adding 'asmBytes' val to ScriptSignature -- this is the raw byte array from the scriptSig WITHOUT the a CompactSizeUInt bytes at the beginning

This commit is contained in:
Chris Stewart 2016-12-02 16:32:20 -06:00
parent 974829cc2d
commit ed0a1b37e7
6 changed files with 30 additions and 52 deletions

View File

@ -27,6 +27,8 @@ sealed trait ScriptSignature extends NetworkElement with BitcoinSLogger {
*/
lazy val asm : Seq[ScriptToken] = ScriptParser.fromBytes(bytes.splitAt(compactSizeUInt.size.toInt)._2)
/** Byte vector for script program WITHOUT the [[CompactSizeUInt]], this is the raw byte vector that can be run */
lazy val asmBytes = asm.flatMap(_.bytes)
/**

View File

@ -5,7 +5,7 @@ import org.bitcoins.core.crypto.{BaseTransactionSignatureComponent, TransactionS
import org.bitcoins.core.currency.CurrencyUnit
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptWitness, SignatureVersion}
import org.bitcoins.core.protocol.transaction.{Transaction, WitnessTransaction}
import org.bitcoins.core.protocol.transaction.{BaseTransaction, Transaction, WitnessTransaction}
import org.bitcoins.core.script.constant._
import org.bitcoins.core.script.flag.ScriptFlag
import org.bitcoins.core.script.result._
@ -328,6 +328,14 @@ object ScriptProgram {
script,originalScript, altStack,flags, witness, txSigComponent.sigVersion, amount)
}
def apply(transaction: BaseTransaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
flags: Seq[ScriptFlag]): PreExecutionScriptProgram = {
val t = TransactionSignatureComponent(transaction,inputIndex,scriptPubKey,flags)
PreExecutionScriptProgramImpl(t,stack.toList,script.toList,originalScript.toList,altStack.toList,flags)
}
/** Creates a fresh instance of [[org.bitcoins.core.script.PreExecutionScriptProgram]] */
def apply(transaction: Transaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32, flags: Seq[ScriptFlag]): PreExecutionScriptProgram = {
val t = TransactionSignatureComponent(transaction,inputIndex,scriptPubKey,flags)

View File

@ -4,6 +4,7 @@ import org.bitcoins.core.script.constant.ScriptToken
import org.bitcoins.core.consensus.Consensus
import org.bitcoins.core.crypto.{BaseTransactionSignatureComponent, WitnessV0TransactionSignatureComponent}
import org.bitcoins.core.currency.{CurrencyUnit, CurrencyUnits}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction.{EmptyTransactionOutPoint, Transaction}
import org.bitcoins.core.script._
@ -115,7 +116,9 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
//we need to run the deserialized redeemScript & the scriptSignature without the serialized redeemScript
val stack = scriptPubKeyExecutedProgram.stack
logger.debug("P2sh stack: " + stack)
val redeemScript = ScriptPubKey(stack.head.bytes)
val redeemScriptBytes = stack.head.bytes
val c = CompactSizeUInt.calculateCompactSizeUInt(redeemScriptBytes)
val redeemScript = ScriptPubKey(c.bytes ++ redeemScriptBytes)
logger.debug("Redeem script asm: " + redeemScript.asm)
val p2shRedeemScriptProgram = ScriptProgram(scriptPubKeyExecutedProgram.txSignatureComponent,stack.tail,
redeemScript.asm)
@ -411,8 +414,8 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
val noDuplicateInputs = prevOutputTxIds.distinct.size == prevOutputTxIds.size
val isValidScriptSigForCoinbaseTx = transaction.isCoinbase match {
case true => transaction.inputs.head.scriptSignature.size >= 2 &&
transaction.inputs.head.scriptSignature.size <= 100
case true => transaction.inputs.head.scriptSignature.asmBytes.size >= 2 &&
transaction.inputs.head.scriptSignature.asmBytes.size <= 100
case false =>
//since this is not a coinbase tx we cannot have any empty previous outs inside of inputs
!transaction.inputs.exists(_.previousOutput == EmptyTransactionOutPoint)

View File

@ -13,7 +13,7 @@ import org.scalacheck.{Prop, Properties}
* Created by chris on 7/25/16.
*/
class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCreatorSpec") with BitcoinSLogger {
/* property("Must generate a valid signature for a p2pk transaction") =
property("Must generate a valid signature for a p2pk transaction") =
Prop.forAll(TransactionGenerators.signedP2PKTransaction) {
case (txSignatureComponent: TransactionSignatureComponent, _) =>
//run it through the interpreter
@ -40,7 +40,7 @@ class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCr
val result = ScriptInterpreter.run(program)
result == ScriptOk
}*/
}
property("generate a valid signature for a p2sh transaction") =
Prop.forAll(TransactionGenerators.signedP2SHTransaction) {
@ -52,7 +52,7 @@ class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCr
Seq(ScriptOk, ScriptErrorPushSize).contains(result)
}
/* property("generate a valid signature for a valid and spendable cltv transaction") =
property("generate a valid signature for a valid and spendable cltv transaction") =
Prop.forAllNoShrink(TransactionGenerators.spendableCLTVTransaction :| "cltv_spendable") {
case (txSignatureComponent: TransactionSignatureComponent, _, scriptNumber) =>
//run it through the interpreter
@ -93,5 +93,5 @@ class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCr
val result = ScriptInterpreter.run(program)
Seq(ScriptErrorUnsatisfiedLocktime, ScriptErrorPushSize).contains(result)
}*/
}
}

View File

@ -70,7 +70,7 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
| "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"]
|
|]
""".stripMargin*/
""".stripMargin */
val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
val json = lines.parseJson
val testCasesOpt : Seq[Option[CoreTransactionTestCase]] = json.convertTo[Seq[Option[CoreTransactionTestCase]]]
@ -97,6 +97,7 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
}
}
it must "read all of the tx_invalid.json's contents and return a ScriptError" in {
@ -107,8 +108,8 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
/* val lines =
"""
|[
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", "P2SH"]
|[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]],
|"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", "P2SH"]
|]
""".stripMargin*/
val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
@ -140,7 +141,7 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
}
withClue(testCase.raw) {
//only one input is required to be false to make the transaction invalid
txInputValidity.exists(_ == false) must be (false)
txInputValidity.exists(_ == false) must be (true)
}
}
}

View File

@ -2,7 +2,7 @@ package org.bitcoins.core.script.crypto
import org.bitcoins.core.currency.CurrencyUnits
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptSignature, SigVersionBase}
import org.bitcoins.core.protocol.script.{P2SHScriptSignature, ScriptPubKey, ScriptSignature, SigVersionBase}
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.script._
import org.bitcoins.core.script.constant._
@ -16,7 +16,7 @@ import org.scalatest.{FlatSpec, MustMatchers}
*/
class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterpreter with BitcoinSLogger {
val stack = List(ScriptConstant("02218AD6CDC632E7AE7D04472374311CEBBBBF0AB540D2D08C3400BB844C654231".toLowerCase))
/*
"CryptoInterpreter" must "evaluate OP_HASH160 correctly when it is on top of the script stack" in {
val script = List(OP_HASH160)
@ -134,44 +134,8 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
newProgram.script.isEmpty must be (true)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (false)
}
*/
it must "evaluate an OP_CHECKMULTISIG for a p2sh transaction" in {
val rawScriptSig = "fc0047304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf80014730440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca014c6952210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae"
val p2shScriptSig = ScriptSignature(rawScriptSig)
val rawScriptPubKey = "17a914c9e4a896d149702d0d1695434feddd52e24ad78d87"
val p2shScriptPubKey = ScriptPubKey(rawScriptPubKey)
val (creditingTx,outputIndex) = TransactionTestUtil.buildCreditingTransaction(p2shScriptPubKey)
val (spendingTx,inputIndex) = TransactionTestUtil.buildSpendingTransaction(creditingTx,p2shScriptSig,outputIndex)
val stack = List(ScriptNumber(3),
ScriptConstant("03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640"),
ScriptConstant("038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508"),
ScriptConstant("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),
ScriptNumber(2),
ScriptConstant("30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01"),
ScriptConstant("304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001"),
OP_0)
val script = List(OP_CHECKMULTISIG)
val baseProgram = ScriptProgram(spendingTx,creditingTx.outputs(0).scriptPubKey,UInt32.zero,
ScriptFlagFactory.empty)
val program = ScriptProgram(baseProgram,stack,script)
val newProgram = opCheckMultiSig(program)
newProgram.stackTopIsTrue must be (true)
newProgram.stack.size must be (1)
newProgram.script.isEmpty must be (true)
}
/* it must "mark a transaction invalid when the NULLDUMMY flag is set for a OP_CHECKMULTISIG operation & the scriptSig does not begin with OP_0" in {
it must "mark a transaction invalid when the NULLDUMMY flag is set for a OP_CHECKMULTISIG operation & the scriptSig does not begin with OP_0" in {
val flags = Seq(ScriptVerifyNullDummy)
val scriptSig = ScriptSignature.fromAsm(Seq(OP_1))
val input = TransactionInput(EmptyTransactionOutPoint, scriptSig, TransactionConstants.sequence)
@ -206,6 +170,6 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val program = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script),script,ScriptProgram.OriginalScript)
val newProgram = ScriptProgramTestUtil.toExecutionInProgressScriptProgram(opCodeSeparator(program))
newProgram.lastCodeSeparator must be (Some(0))
}*/
}
}