diff --git a/src/main/scala/org/scalacoin/script/bitwise/BitwiseOperations.scala b/src/main/scala/org/scalacoin/script/bitwise/BitwiseOperations.scala index 34e12d25fe..7fb9877af1 100644 --- a/src/main/scala/org/scalacoin/script/bitwise/BitwiseOperations.scala +++ b/src/main/scala/org/scalacoin/script/bitwise/BitwiseOperations.scala @@ -20,3 +20,32 @@ case object OP_EQUAL extends BitwiseOperation { case object OP_EQUALVERIFY extends BitwiseOperation { override def opCode = 136 } + +/** + * Flips all of the bits in the input. disabled. + */ +case object OP_INVERT extends BitwiseOperation { + override def opCode = 131 +} + +/** + * Boolean and between each bit in the inputs. disabled. + */ +case object OP_AND extends BitwiseOperation { + override def opCode = 132 +} + +/** + * Boolean or between each bit in the inputs. disabled. + */ +case object OP_OR extends BitwiseOperation { + override def opCode = 133 +} + +/** + * Boolean exclusive or between each bit in the inputs. disabled. + */ +case object OP_XOR extends BitwiseOperation { + override def opCode = 134 +} + diff --git a/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala b/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala index 9c0b8fe9dc..25a7a83075 100644 --- a/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala +++ b/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala @@ -157,7 +157,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con } } - program.scriptSignature match { + val (result,executedProgram) = program.scriptSignature match { case scriptSig : P2SHScriptSignature => //first run the serialized redeemScript && the p2shScriptPubKey to see if the hashes match @@ -171,21 +171,23 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con logger.debug("P2sh stack: " + stack) logger.debug("P2sh redeemScript: " + scriptSig.redeemScript.asm ) val p2shRedeemScriptProgram = ScriptProgramFactory.factory(program,stack, scriptSig.redeemScript.asm) - - val (result,newProgram) = loop(p2shRedeemScriptProgram) - logger.debug("hashCheckProgram stack: " + hashCheckProgram.stack) - result + loop(p2shRedeemScriptProgram) case false => logger.warn("P2SH scriptPubKey hash did not match the hash for the serialized redeemScript") - hashesMatch._1 + hashesMatch } case _ : P2PKHScriptSignature | _ : P2PKScriptSignature | _ : MultiSignatureScriptSignature | _ : NonStandardScriptSignature | EmptyScriptSignature => logger.debug("We do not check a redeemScript against a non p2sh scriptSig") val result = loop(program) - result._1 + result } + if (result && executedProgram.flags.contains(ScriptVerifyCleanStack)) { + //require that the stack after execution has exactly one element on it + result && executedProgram.stack.size == 1 + } else result + } } diff --git a/src/test/scala/org/scalacoin/script/interpreter/ScriptInterpreterTest.scala b/src/test/scala/org/scalacoin/script/interpreter/ScriptInterpreterTest.scala index 91bacb75d8..7d200b4fe3 100644 --- a/src/test/scala/org/scalacoin/script/interpreter/ScriptInterpreterTest.scala +++ b/src/test/scala/org/scalacoin/script/interpreter/ScriptInterpreterTest.scala @@ -63,17 +63,10 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp - +/* it must "evaluate all valid scripts from the bitcoin core script_valid.json" in { import CoreTestCaseProtocol._ - /** - * These are test cases that were in script_valid.json that I have removed since i'm not sure how relevant - * they are going forward to bitcoin - for historical purposes though these should pass - * they all have to do with DER encoded sigs - * bitcoinj currently fails on these - * , - */ val source = scala.io.Source.fromFile("src/test/scala/org/scalacoin/script/interpreter/script_valid.json") //use this to represent a single test case from script_valid.json @@ -113,7 +106,7 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp } } - } + }*/ it must "evaluate all valid scripts from the bitcoin core script_invalid.json" in { import CoreTestCaseProtocol._ @@ -131,26 +124,30 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp /* val lines = """ | - |[[ - "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", - "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", - "CLEANSTACK,P2SH", - "P2SH with unnecessary input" -]] + |[["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"]] """.stripMargin*/ - val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close() - val json = lines.parseJson - val testCasesOpt : Seq[Option[CoreTestCase]] = json.convertTo[Seq[Option[CoreTestCase]]] - val testCases : Seq[CoreTestCase] = testCasesOpt.flatten + val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close() + logger.info("1") + val json = lines.parseJson + logger.info("2") + val testCasesOpt : Seq[Option[CoreTestCase]] = json.convertTo[Seq[Option[CoreTestCase]]] + logger.info("3") + val testCases : Seq[CoreTestCase] = testCasesOpt.flatten + logger.info("4") for { testCase <- testCases + _ = logger.info(testCase.toString) (creditingTx,outputIndex) = TransactionTestUtil.buildCreditingTransaction(testCase.scriptPubKey.scriptPubKey) + _ = logger.info("6") (tx,inputIndex) = TransactionTestUtil.buildSpendingTransaction(creditingTx,testCase.scriptSig.scriptSignature,outputIndex) + _ = logger.info("7") } yield { + require(testCase.scriptPubKey.asm == testCase.scriptPubKey.scriptPubKey.asm) + logger.info("Raw test case: " + testCase.raw) logger.info("Parsed ScriptSig: " + testCase.scriptSig) logger.info("Parsed ScriptPubKey: " + testCase.scriptPubKey)