mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 18:47:38 +01:00
Implementing OP_PICK script operation
This commit is contained in:
parent
09458675a4
commit
4aeb30ca6d
4 changed files with 63 additions and 5 deletions
|
@ -48,6 +48,8 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
|
||||||
case OP_DROP :: t => loop(opDrop(program))
|
case OP_DROP :: t => loop(opDrop(program))
|
||||||
case OP_IFDUP :: t => loop(opIfDup(program))
|
case OP_IFDUP :: t => loop(opIfDup(program))
|
||||||
case OP_NIP :: t => loop(opNip(program))
|
case OP_NIP :: t => loop(opNip(program))
|
||||||
|
case OP_OVER :: t => loop(opOver(program))
|
||||||
|
case OP_PICK :: t => loop(opPick(program))
|
||||||
//arithmetic operations
|
//arithmetic operations
|
||||||
case OP_ADD :: t => loop(opAdd(program))
|
case OP_ADD :: t => loop(opAdd(program))
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.scalacoin.script.stack
|
||||||
|
|
||||||
import org.scalacoin.script.{ScriptProgramImpl, ScriptProgram}
|
import org.scalacoin.script.{ScriptProgramImpl, ScriptProgram}
|
||||||
import org.scalacoin.script.constant._
|
import org.scalacoin.script.constant._
|
||||||
|
import org.scalacoin.util.ScalacoinUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
|
@ -99,8 +100,41 @@ trait StackInterpreter {
|
||||||
require(program.script.headOption.isDefined && program.script.head == OP_NIP, "Top of script stack must be OP_NIP")
|
require(program.script.headOption.isDefined && program.script.head == OP_NIP, "Top of script stack must be OP_NIP")
|
||||||
require(program.stack.size > 1,"Stack must have at least two items on it for OP_NIP")
|
require(program.stack.size > 1,"Stack must have at least two items on it for OP_NIP")
|
||||||
program.stack match {
|
program.stack match {
|
||||||
case h :: h1 :: t => ScriptProgramImpl(h :: t, program.script.tail, program.transaction, program.altStack)
|
case h :: _ :: t => ScriptProgramImpl(h :: t, program.script.tail, program.transaction, program.altStack)
|
||||||
|
case h :: t => throw new RuntimeException("Stack must have at least two items on it for OP_NIP")
|
||||||
|
case Nil => throw new RuntimeException("Stack must have at least two items on it for OP_NIP")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the second-to-top stack item to the top.
|
||||||
|
* @param program
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
def opOver(program : ScriptProgram) : ScriptProgram = {
|
||||||
|
require(program.script.headOption.isDefined && program.script.head == OP_OVER, "Top of script stack must be OP_OVER")
|
||||||
|
require(program.stack.size > 1,"Stack must have at least two items on it for OP_OVER")
|
||||||
|
program.stack match {
|
||||||
|
case _ :: h1 :: _ => ScriptProgramImpl(h1 :: program.stack, program.script.tail, program.transaction, program.altStack)
|
||||||
|
case h :: t => throw new RuntimeException("Stack must have at least two items on it for OP_OVER")
|
||||||
|
case Nil => throw new RuntimeException("Stack must have at least two items on it for OP_OVER")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item n back in the stack is copied to the top.
|
||||||
|
* @param program
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
def opPick(program : ScriptProgram) : ScriptProgram = {
|
||||||
|
require(program.script.headOption.isDefined && program.script.head == OP_PICK, "Top of script stack must be OP_PICK")
|
||||||
|
require(program.stack.size > 1,"Stack must have at least two items on it for OP_PICK")
|
||||||
|
|
||||||
|
val n = ScalacoinUtil.hexToInt(program.stack.head.hex)
|
||||||
|
val newStackTop = program.stack.tail(n)
|
||||||
|
ScriptProgramImpl(newStackTop :: program.stack.tail, program.script.tail, program.transaction, program.altStack)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.scalacoin.marshallers.script
|
||||||
import org.scalacoin.script.arithmetic.OP_ADD
|
import org.scalacoin.script.arithmetic.OP_ADD
|
||||||
import org.scalacoin.script.bitwise.OP_EQUAL
|
import org.scalacoin.script.bitwise.OP_EQUAL
|
||||||
import org.scalacoin.script.constant.{ScriptNumberImpl, OP_1, OP_1NEGATE, ScriptConstantImpl}
|
import org.scalacoin.script.constant.{ScriptNumberImpl, OP_1, OP_1NEGATE, ScriptConstantImpl}
|
||||||
|
import org.scalacoin.script.stack.OP_PICK
|
||||||
import org.scalacoin.util.{ScalacoinUtil, TestUtil}
|
import org.scalacoin.util.{ScalacoinUtil, TestUtil}
|
||||||
import org.scalatest.{FlatSpec, MustMatchers}
|
import org.scalatest.{FlatSpec, MustMatchers}
|
||||||
|
|
||||||
|
@ -58,10 +59,10 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
|
||||||
parse(str) must equal (List(OP_1NEGATE, ScriptConstantImpl("3e8"), OP_ADD))
|
parse(str) must equal (List(OP_1NEGATE, ScriptConstantImpl("3e8"), OP_ADD))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* it must "parse a decimal number as a ScriptNumber if it is under 75" in {
|
it must "parse an OP_PICK" in {
|
||||||
val str = "ADD 21 EQUAL"
|
val str = "PICK"
|
||||||
parse(str) must equal (List(OP_ADD, ScriptNumberImpl(21), OP_EQUAL))
|
parse(str) must equal (List(OP_PICK))
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.scalacoin.script.stack
|
package org.scalacoin.script.stack
|
||||||
|
|
||||||
import org.scalacoin.script.ScriptProgramImpl
|
import org.scalacoin.script.ScriptProgramImpl
|
||||||
|
import org.scalacoin.script.bitwise.OP_EQUAL
|
||||||
import org.scalacoin.script.constant.{OP_1, OP_0, ScriptConstantImpl}
|
import org.scalacoin.script.constant.{OP_1, OP_0, ScriptConstantImpl}
|
||||||
import org.scalacoin.util.{TestUtil, ScalacoinUtil}
|
import org.scalacoin.util.{TestUtil, ScalacoinUtil}
|
||||||
import org.scalatest.{FlatSpec, MustMatchers}
|
import org.scalatest.{FlatSpec, MustMatchers}
|
||||||
|
@ -106,6 +107,26 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
||||||
|
|
||||||
newProgram.stack must be (List(OP_0))
|
newProgram.stack must be (List(OP_0))
|
||||||
newProgram.script.isEmpty must be (true)
|
newProgram.script.isEmpty must be (true)
|
||||||
|
}
|
||||||
|
|
||||||
|
it must "evaluate an OP_OVER correctly" in {
|
||||||
|
val stack = List(OP_0,OP_1)
|
||||||
|
val script = List(OP_OVER)
|
||||||
|
val program = ScriptProgramImpl(stack,script,TestUtil.transaction,List())
|
||||||
|
val newProgram = opOver(program)
|
||||||
|
newProgram.stack must be (List(OP_1,OP_0,OP_1))
|
||||||
|
newProgram.script.isEmpty must be (true)
|
||||||
|
}
|
||||||
|
|
||||||
|
it must "evaluate an OP_PICK correctly" in {
|
||||||
|
val stack = List(OP_0, ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"))
|
||||||
|
val script = List(OP_PICK)
|
||||||
|
val program = ScriptProgramImpl(stack,script,TestUtil.transaction,List())
|
||||||
|
val newProgram = opPick(program)
|
||||||
|
|
||||||
|
newProgram.stack must be (List(ScriptConstantImpl("14"),ScriptConstantImpl("14"),
|
||||||
|
ScriptConstantImpl("15"), ScriptConstantImpl("16")))
|
||||||
|
newProgram.script.isEmpty must be (true)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue