diff --git a/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala b/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala index fdb8ee10da..669aa3b1d9 100644 --- a/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala +++ b/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala @@ -37,7 +37,6 @@ trait ConstantInterpreter extends BitcoinSLogger { bytesNeededForPushOp(program.script(1)) case _ : ScriptToken => bytesNeededForPushOp(program.script.head) } - /** Parses the script tokens that need to be pushed onto our stack. */ @tailrec def takeUntilBytesNeeded(scriptTokens : List[ScriptToken], accum : List[ScriptToken]) : (List[ScriptToken],List[ScriptToken]) = { @@ -56,8 +55,8 @@ trait ConstantInterpreter extends BitcoinSLogger { } val (newScript,bytesToPushOntoStack) = program.script.head match { - case OP_PUSHDATA1 | OP_PUSHDATA2 | OP_PUSHDATA4 => takeUntilBytesNeeded(program.script.tail.tail, List()) - case _: ScriptToken => takeUntilBytesNeeded(program.script.tail, List()) + case OP_PUSHDATA1 | OP_PUSHDATA2 | OP_PUSHDATA4 => takeUntilBytesNeeded(program.script.tail.tail, Nil) + case _: ScriptToken => takeUntilBytesNeeded(program.script.tail, Nil) } logger.debug("new script: " + newScript) logger.debug("Bytes to push onto stack: " + bytesToPushOntoStack) @@ -73,13 +72,16 @@ trait ConstantInterpreter extends BitcoinSLogger { logger.error("We can push this constant onto the stack with OP_0 - OP_16 instead of using a script constant") ScriptProgram(program,ScriptErrorMinimalData) } else if (bytesNeeded != bytesToPushOntoStack.map(_.bytes.size).sum) { + logger.error("Incorrect amount of bytes being pushed onto the stack") + logger.error("Bytes needed: " + bytesNeeded) + logger.error("Number of byte received: " + bytesToPushOntoStack.map(_.bytes.size).sum) ScriptProgram(program,ScriptErrorBadOpCode) } else if (ScriptFlagUtil.requireMinimalData(program.flags) && !BitcoinScriptUtil.isMinimalPush(program.script.head,constant)) { - logger.debug("Pushing operation: " + program.script.head) - logger.debug("Constant parsed: " + constant) - logger.debug("Constant size: " + constant.bytes.size) - ScriptProgram(program,ScriptErrorMinimalData) + logger.debug("Pushing operation: " + program.script.head) + logger.debug("Constant parsed: " + constant) + logger.debug("Constant size: " + constant.bytes.size) + ScriptProgram(program,ScriptErrorMinimalData) } else ScriptProgram.apply(program, constant :: program.stack, newScript) } @@ -90,7 +92,7 @@ trait ConstantInterpreter extends BitcoinSLogger { //constant telling OP_PUSHDATA how many bytes need to go onto the stack //for instance OP_PUSHDATA1 OP_0 val scriptNumOp = program.script(1).bytes match { - case h :: t => ScriptNumberOperation(h) + case h :: t => ScriptNumberOperation.fromNumber(h.toInt) case Nil => None } if (ScriptFlagUtil.requireMinimalData(program.flags) && program.script(1).bytes.size == 1 && @@ -117,6 +119,7 @@ trait ConstantInterpreter extends BitcoinSLogger { /** Parses the bytes needed for a push op (for instance OP_PUSHDATA1). */ private def bytesNeededForPushOp(token : ScriptToken) : Long = token match { case scriptNumber: BytesToPushOntoStack => scriptNumber.opCode + case scriptNumOp: ScriptNumberOperation => scriptNumOp.opCode case scriptNumber: ScriptNumber => scriptNumber.underlying case scriptConstant : ScriptConstant => val constantFlippedEndianness = BitcoinSUtil.flipEndianness(scriptConstant.hex) diff --git a/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala b/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala index fe70e14d01..6d187f111f 100644 --- a/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala +++ b/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala @@ -127,12 +127,22 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn } } - it must "return ScriptErrorMinimalData if program contains ScriptVerifyMinimalData flag and 2nd item in script is" + - " zero" in { + it must "return ScriptErrorMinimalData if program contains ScriptVerifyMinimalData flag and 2nd item in script is zero" in { val stack = List() val script = List(OP_PUSHDATA4,ScriptNumber.zero) val program = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack,script),Seq[ScriptFlag](ScriptVerifyMinimalData)) val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opPushData4(program)) newProgram.error must be (Some(ScriptErrorMinimalData)) } + + it must "push a constant onto the stack that is using OP_PUSHDATA1 where the pushop can be interpreted as a script number operation" in { + val constant = ScriptConstant("01000000010000000000000000000000000000000000000000000000000000000000000000" + + "ffffffff00ffffffff014a7afa8f7d52fd9e17a914b167f19394cd656c34f843ac2387e602007fd15b8700000000") + val stack = Nil + val script = List(OP_PUSHDATA1, OP_3, constant) + val program = ScriptProgram(TestUtil.testProgram, stack,script) + val newProgram = opPushData1(program) + newProgram.stack must be (Seq(constant)) + + } }