mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 23:08:31 +01:00
Refactoring stack interpreter to remove redudancy on error throwing
This commit is contained in:
parent
4d43762cdf
commit
cb21705228
3 changed files with 137 additions and 22 deletions
|
@ -48,7 +48,6 @@ trait StackInterpreter {
|
|||
def opDepth(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_DEPTH, "Top of script stack must be OP_DEPTH")
|
||||
require(program.script.size >= 1, "OP_DEPTH requires at least two elements on the script stack")
|
||||
val operation = program.script.head
|
||||
val stackSize = program.stack.size
|
||||
|
||||
val numberToPush : ScriptNumber= if (stackSize == 0) OP_0 else ScriptNumberImpl(stackSize)
|
||||
|
@ -98,11 +97,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
def opNip(program : ScriptProgram) : ScriptProgram = {
|
||||
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")
|
||||
program.stack match {
|
||||
case h :: _ :: t => ScriptProgramFactory.factory(program, h :: t, program.script.tail)
|
||||
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")
|
||||
case h :: t => throw new IllegalArgumentException("Stack must have at least two items on it for OP_NIP")
|
||||
case Nil => throw new IllegalArgumentException("Stack must have at least two items on it for OP_NIP")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,11 +112,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
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 :: _ => ScriptProgramFactory.factory(program, h1 :: program.stack, program.script.tail)
|
||||
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")
|
||||
case h :: t => throw new IllegalArgumentException("Stack must have at least two items on it for OP_OVER")
|
||||
case Nil => throw new IllegalArgumentException("Stack must have at least two items on it for OP_OVER")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,11 +156,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
def opRot(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_ROT, "Top of script stack must be OP_ROT")
|
||||
require(program.stack.size > 2,"Stack must have at least 3 items on it for OP_ROT")
|
||||
|
||||
val newStack = program.stack match {
|
||||
case h :: h1 :: h2 :: t => h2 :: h :: h1 :: t
|
||||
case _ => throw new RuntimeException("Stack must have at least 3 items on it for OP_ROT")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 3 items on it for OP_ROT")
|
||||
}
|
||||
ScriptProgramFactory.factory(program, newStack,program.script.tail)
|
||||
}
|
||||
|
@ -176,11 +172,9 @@ trait StackInterpreter {
|
|||
*/
|
||||
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")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 5 items on it for OP_2ROT")
|
||||
}
|
||||
ScriptProgramFactory.factory(program, newStack,program.script.tail)
|
||||
}
|
||||
|
@ -218,11 +212,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
def opTuck(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_TUCK, "Top of script stack must be OP_TUCK")
|
||||
require(program.stack.size > 1,"Stack must have at least 2 items on it for OP_TUCK")
|
||||
|
||||
val newStack = program.stack match {
|
||||
case h :: h1 :: t => h1 :: h :: h1 :: t
|
||||
case _ => throw new RuntimeException("Stack must have at least 2 items on it for OP_TUCK")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 2 items on it for OP_TUCK")
|
||||
}
|
||||
ScriptProgramFactory.factory(program, newStack, program.script.tail)
|
||||
}
|
||||
|
@ -235,11 +228,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
def op2Dup(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_2DUP, "Top of script stack must be OP_2DUP")
|
||||
require(program.stack.size > 1,"Stack must have at least 2 items on it for OP_2DUP")
|
||||
|
||||
val newStack = program.stack match {
|
||||
case h :: h1 :: t => h :: h1 :: h :: h1 :: t
|
||||
case _ => throw new RuntimeException("Stack must have at least 2 items on it for OP_2DUP")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 2 items on it for OP_2DUP")
|
||||
}
|
||||
ScriptProgramFactory.factory(program, newStack, program.script.tail)
|
||||
}
|
||||
|
@ -251,10 +243,9 @@ trait StackInterpreter {
|
|||
*/
|
||||
def op3Dup(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_3DUP, "Top of script stack must be OP_3DUP")
|
||||
require(program.stack.size > 2,"Stack must have at least 3 items on it for OP_3DUP")
|
||||
val newStack = program.stack match {
|
||||
case h :: h1 :: h2 :: t => h :: h1 :: h2 :: h :: h1 :: h2 :: t
|
||||
case _ => throw new RuntimeException("Stack must have at least 3 items on it for OP_3DUP")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 3 items on it for OP_3DUP")
|
||||
}
|
||||
ScriptProgramFactory.factory(program,newStack,program.script.tail)
|
||||
}
|
||||
|
@ -268,10 +259,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
def op2Over(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_2OVER, "Top of script stack must be OP_2OVER")
|
||||
require(program.stack.size > 3,"Stack must have at least 4 items on it for OP_2OVER")
|
||||
|
||||
val newStack = program.stack match {
|
||||
case h :: h1 :: h2 :: h3 :: t => h2 :: h3 :: h :: h1 :: h2 :: h3 :: t
|
||||
case _ => throw new RuntimeException("Stack must have at least 4 items on it for OP_2OVER")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 4 items on it for OP_2OVER")
|
||||
}
|
||||
ScriptProgramFactory.factory(program, newStack,program.script.tail)
|
||||
}
|
||||
|
@ -283,11 +274,10 @@ trait StackInterpreter {
|
|||
*/
|
||||
def op2Swap(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_2SWAP, "Top of script stack must be OP_2SWAP")
|
||||
require(program.stack.size > 3,"Stack must have at least 4 items on it for OP_2SWAP")
|
||||
|
||||
val newStack = program.stack match {
|
||||
case h :: h1 :: h2 :: h3 :: t => h2 :: h3 :: h :: h1 :: t
|
||||
case _ => throw new RuntimeException("Stack must have at least 4 items on it for OP_2SWAP")
|
||||
case _ => throw new IllegalArgumentException("Stack must have at least 4 items on it for OP_2SWAP")
|
||||
}
|
||||
ScriptProgramFactory.factory(program,newStack,program.script.tail)
|
||||
}
|
||||
|
|
|
@ -109,6 +109,28 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 2 elements on the stack for OP_NIP" in {
|
||||
val stack = List(OP_0)
|
||||
val script = List(OP_NIP)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = opNip(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "throw an exception if there is no elements on the stack for OP_NIP" in {
|
||||
val stack = List()
|
||||
val script = List(OP_NIP)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = opNip(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "evaluate an OP_OVER correctly" in {
|
||||
val stack = List(OP_0,OP_1)
|
||||
val script = List(OP_OVER)
|
||||
|
@ -118,6 +140,28 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 2 elements on the stack for OP_OVER" in {
|
||||
val stack = List(OP_0)
|
||||
val script = List(OP_OVER)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = opOver(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "throw an exception if there is no elements on the stack for OP_OVER" in {
|
||||
val stack = List()
|
||||
val script = List(OP_OVER)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = opOver(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "evaluate an OP_PICK correctly" in {
|
||||
val stack = List(OP_0, ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"))
|
||||
val script = List(OP_PICK)
|
||||
|
@ -151,6 +195,18 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 3 elements on the stack for OP_ROT" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"))
|
||||
val script = List(OP_ROT)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = opRot(program)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it must "evaluate an OP_2ROT correctly" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"),
|
||||
ScriptConstantImpl("17"), ScriptConstantImpl("18"), ScriptConstantImpl("19"))
|
||||
|
@ -163,6 +219,18 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 6 elements on the stack for OP_2ROT" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"),
|
||||
ScriptConstantImpl("17"), ScriptConstantImpl("18"))
|
||||
val script = List(OP_2ROT)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = op2Rot(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "evalauate an OP_2DROP correctly" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"),
|
||||
ScriptConstantImpl("17"), ScriptConstantImpl("18"), ScriptConstantImpl("19"))
|
||||
|
@ -197,6 +265,17 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 2 elements on the stack for OP_TUCK" in {
|
||||
val stack = List(OP_0)
|
||||
val script = List(OP_TUCK)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = opTuck(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "evaluate an OP_2DUP correctly" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"),
|
||||
ScriptConstantImpl("17"), ScriptConstantImpl("18"), ScriptConstantImpl("19"))
|
||||
|
@ -209,6 +288,17 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 2 elements on the stack for OP_2DUP" in {
|
||||
val stack = List(OP_0)
|
||||
val script = List(OP_2DUP)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = op2Dup(program)
|
||||
}
|
||||
}
|
||||
|
||||
it must "evaluate an OP_3DUP correctly" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"),
|
||||
ScriptConstantImpl("17"), ScriptConstantImpl("18"), ScriptConstantImpl("19"))
|
||||
|
@ -235,6 +325,17 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 4 elements on the stack for OP_2OVER" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"))
|
||||
val script = List(OP_2OVER)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = op2Over(program)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it must "evaluate an OP_2SWAP correctly" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"),
|
||||
|
@ -247,4 +348,15 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
|
|||
ScriptConstantImpl("15"), ScriptConstantImpl("18"), ScriptConstantImpl("19")))
|
||||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
|
||||
it must "throw an exception if there is less than 4 elements on the stack for OP_2SWAP" in {
|
||||
val stack = List(ScriptConstantImpl("14"), ScriptConstantImpl("15"), ScriptConstantImpl("16"))
|
||||
val script = List(OP_2SWAP)
|
||||
|
||||
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
val newProgram = op2Swap(program)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,4 +110,17 @@ class BinaryTreeTest extends FlatSpec with MustMatchers {
|
|||
val tree = Node[String]("Hello",Node("there",Leaf("1"),Leaf("2")),Node("3",Empty,Leaf("4")))
|
||||
tree.replace(Node("thre",Leaf("1"),Leaf("2")),Empty)() must be (tree)
|
||||
}
|
||||
|
||||
it must "insert an element into an empty binary tree" in {
|
||||
Empty.insert(1) must be (Leaf(1))
|
||||
}
|
||||
|
||||
it must "insert an element into a leaf binary tree" in {
|
||||
Leaf(1).insert(2) must be (Node(1,Leaf(2),Empty))
|
||||
}
|
||||
|
||||
it must "insert an element into a node binary tree" in {
|
||||
Node(1,Empty,Empty).insert(2) must be (Node(1,Leaf(2),Empty))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue