diff --git a/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala b/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala index c39accce90..ef9dadac59 100644 --- a/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala +++ b/src/main/scala/org/scalacoin/script/interpreter/ScriptInterpreter.scala @@ -52,6 +52,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con case OP_PICK :: t => loop(opPick(program)) case OP_ROLL :: t => loop(opRoll(program)) case OP_ROT :: t => loop(opRot(program)) + case OP_2ROT :: t => loop(op2Rot(program)) //arithmetic operations case OP_ADD :: t => loop(opAdd(program)) diff --git a/src/main/scala/org/scalacoin/script/stack/StackInterpreter.scala b/src/main/scala/org/scalacoin/script/stack/StackInterpreter.scala index 65b9a51d8f..d9916f2ad0 100644 --- a/src/main/scala/org/scalacoin/script/stack/StackInterpreter.scala +++ b/src/main/scala/org/scalacoin/script/stack/StackInterpreter.scala @@ -153,6 +153,7 @@ trait StackInterpreter { /** * The top three items on the stack are rotated to the left. + * x1 x2 x3 -> x2 x3 x1 * @param program * @return */ @@ -167,4 +168,21 @@ trait StackInterpreter { ScriptProgramImpl(newStack,program.script.tail,program.transaction,program.altStack) } + /** + * The fifth and sixth items back are moved to the top of the stack. + * x1 x2 x3 x4 x5 x6 -> x3 x4 x5 x6 x1 x2 + * @param program + * @return + */ + def op2Rot(program : ScriptProgram) : ScriptProgram = { + require(program.script.headOption.isDefined && program.script.head == OP_2ROT, "Top of script stack must be OP_2ROT") + require(program.stack.size > 5,"Stack must have at least 5 items on it for OP_2ROT") + + val newStack = program.stack match { + case h :: h1 :: h2 :: h3 :: h4 :: h5 :: t => h4 :: h5 :: h :: h1 :: h2 :: h3 :: t + case _ => throw new RuntimeException("Stack must have at least 5 items on it for OP_2ROT") + } + ScriptProgramImpl(newStack,program.script.tail,program.transaction,program.altStack) + } + } diff --git a/src/test/scala/org/scalacoin/script/stack/StackInterpreterTest.scala b/src/test/scala/org/scalacoin/script/stack/StackInterpreterTest.scala index b8839f1361..68432b486e 100644 --- a/src/test/scala/org/scalacoin/script/stack/StackInterpreterTest.scala +++ b/src/test/scala/org/scalacoin/script/stack/StackInterpreterTest.scala @@ -149,6 +149,17 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre newProgram.stack must be (List(ScriptConstantImpl("16"),ScriptConstantImpl("14"),ScriptConstantImpl("15"))) newProgram.script.isEmpty must be (true) + } + it must "evaluate an OP_2ROT correctly" in { + val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"), + ScriptConstantImpl("17"), ScriptConstantImpl("18"), ScriptConstantImpl("19")) + val script = List(OP_2ROT) + val program = ScriptProgramImpl(stack,script,TestUtil.transaction,List()) + val newProgram = op2Rot(program) + + newProgram.stack must be (List(ScriptConstantImpl("18"),ScriptConstantImpl("19"),ScriptConstantImpl("14"), + ScriptConstantImpl("15"),ScriptConstantImpl("16"), ScriptConstantImpl("17"))) + newProgram.script.isEmpty must be (true) } }