missed some opCode require statements w/ multiple clauses

This commit is contained in:
Tom McCabe 2016-12-15 17:56:34 -06:00
parent c1ae07b5a1
commit eb948328a5
2 changed files with 40 additions and 42 deletions

View file

@ -16,31 +16,31 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** a is added to b. */
def opAdd(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_ADD, "Script top must be OP_ADD")
require(program.script.headOption.contains(OP_ADD), "Script top must be OP_ADD")
performBinaryArithmeticOperation(program, (x,y) => x + y)
}
/** Increments the stack top by 1. */
def op1Add(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_1ADD, "Script top must be OP_1ADD")
require(program.script.headOption.contains(OP_1ADD), "Script top must be OP_1ADD")
performUnaryArithmeticOperation(program, x => x + ScriptNumber.one)
}
/** Decrements the stack top by 1. */
def op1Sub(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_1SUB, "Script top must be OP_1SUB")
require(program.script.headOption.contains(OP_1SUB), "Script top must be OP_1SUB")
performUnaryArithmeticOperation(program, x => x - ScriptNumber.one )
}
/** b is subtracted from a. */
def opSub(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_SUB, "Script top must be OP_SUB")
require(program.script.headOption.contains(OP_SUB), "Script top must be OP_SUB")
performBinaryArithmeticOperation(program, (x,y) => y - x)
}
/** Takes the absolute value of the stack top. */
def opAbs(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_ABS, "Script top must be OP_ABS")
require(program.script.headOption.contains(OP_ABS), "Script top must be OP_ABS")
performUnaryArithmeticOperation(program, x => x match {
case ScriptNumber.zero => ScriptNumber.zero
case _ : ScriptNumber => ScriptNumber(x.underlying.abs)
@ -49,25 +49,25 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** Negates the stack top. */
def opNegate(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_NEGATE, "Script top must be OP_NEGATE")
require(program.script.headOption.contains(OP_NEGATE), "Script top must be OP_NEGATE")
performUnaryArithmeticOperation(program, x => x -)
}
/** If the input is 0 or 1, it is flipped. Otherwise the output will be 0. */
def opNot(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_NOT, "Script top must be OP_NOT")
require(program.script.headOption.contains(OP_NOT), "Script top must be OP_NOT")
performUnaryArithmeticOperation(program, x => if (program.stackTopIsFalse) OP_TRUE else OP_FALSE)
}
/** Returns 0 if the input is 0. 1 otherwise. */
def op0NotEqual(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_0NOTEQUAL, "Script top must be OP_0NOTEQUAL")
require(program.script.headOption.contains(OP_0NOTEQUAL), "Script top must be OP_0NOTEQUAL")
performUnaryArithmeticOperation(program, x => if(x.underlying == 0) OP_FALSE else OP_TRUE)
}
/** If both a and b are not 0, the output is 1. Otherwise 0. */
def opBoolAnd(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_BOOLAND, "Script top must be OP_BOOLAND")
require(program.script.headOption.contains(OP_BOOLAND), "Script top must be OP_BOOLAND")
performBinaryBooleanOperation(program,(x,y) => {
val xIsFalse = (x == ScriptNumber.zero || x == OP_0)
val yIsFalse = (y == ScriptNumber.zero || y == OP_0)
@ -77,7 +77,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** If a or b is not 0, the output is 1. Otherwise 0. */
def opBoolOr(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_BOOLOR, "Script top must be OP_BOOLOR")
require(program.script.headOption.contains(OP_BOOLOR), "Script top must be OP_BOOLOR")
performBinaryBooleanOperation(program, (x,y) => {
if (x == y && (x == ScriptNumber.zero || x == OP_0)) false else true
})
@ -85,13 +85,13 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** Returns 1 if the numbers are equal, 0 otherwise. */
def opNumEqual(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_NUMEQUAL, "Script top must be OP_NUMEQUAL")
require(program.script.headOption.contains(OP_NUMEQUAL), "Script top must be OP_NUMEQUAL")
performBinaryBooleanOperation(program,(x,y) => x.numEqual(y))
}
/** Same as [[OP_NUMEQUAL]], but runs [[OP_VERIFY]] afterward. */
def opNumEqualVerify(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_NUMEQUALVERIFY,
require(program.script.headOption.contains(OP_NUMEQUALVERIFY),
"Script top must be OP_NUMEQUALVERIFY")
if (program.stack.size < 2) {
logger.error("OP_NUMEQUALVERIFY requires two stack elements")
@ -112,7 +112,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** Returns 1 if the numbers are not equal, 0 otherwise. */
def opNumNotEqual(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_NUMNOTEQUAL,
require(program.script.headOption.contains(OP_NUMNOTEQUAL),
"Script top must be OP_NUMNOTEQUAL")
performBinaryBooleanOperation(program, (x,y) => {
x.underlying != y.underlying
@ -121,35 +121,35 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** Returns 1 if a is less than b, 0 otherwise. */
def opLessThan(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_LESSTHAN,
require(program.script.headOption.contains(OP_LESSTHAN),
"Script top must be OP_LESSTHAN")
performBinaryBooleanOperation(program, (x,y) => y < x)
}
/** Returns 1 if a is greater than b, 0 otherwise. */
def opGreaterThan(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_GREATERTHAN,
require(program.script.headOption.contains(OP_GREATERTHAN),
"Script top must be OP_GREATERTHAN")
performBinaryBooleanOperation(program, (x,y) => y > x)
}
/** Returns 1 if a is less than or equal to b, 0 otherwise. */
def opLessThanOrEqual(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_LESSTHANOREQUAL,
require(program.script.headOption.contains(OP_LESSTHANOREQUAL),
"Script top must be OP_LESSTHANOREQUAL")
performBinaryBooleanOperation(program, (x,y) => y <= x)
}
/** Returns 1 if a is greater than or equal to b, 0 otherwise. */
def opGreaterThanOrEqual(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_GREATERTHANOREQUAL,
require(program.script.headOption.contains(OP_GREATERTHANOREQUAL),
"Script top must be OP_GREATERTHANOREQUAL")
performBinaryBooleanOperation(program, (x,y) => y >= x)
}
/** Returns the smaller of a and b. */
def opMin(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_MIN,
require(program.script.headOption.contains(OP_MIN),
"Script top must be OP_MIN")
if (program.stack.size < 2) {
logger.error("OP_MAX requires at least two stack elements")
@ -161,7 +161,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** Returns the larger of a and b. */
def opMax(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_MAX,
require(program.script.headOption.contains(OP_MAX),
"Script top must be OP_MAX")
if (program.stack.size < 2) {
logger.error("OP_MAX requires at least two stack elements")
@ -173,7 +173,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
/** Returns 1 if x is within the specified range (left-inclusive), 0 otherwise. */
def opWithin(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_WITHIN,
require(program.script.headOption.contains(OP_WITHIN),
"Script top must be OP_WITHIN")
if (program.stack.size < 3) {
logger.error("OP_WITHIN requires at least 3 elements on the stack")

View file

@ -19,7 +19,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Duplicates the element on top of the stack
* expects the first element in script to be the OP_DUP operation. */
def opDup(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_DUP, "Top of the script stack must be OP_DUP")
require(program.script.headOption.contains(OP_DUP), "Top of the script stack must be OP_DUP")
program.stack match {
case h :: t => ScriptProgram(program, h :: program.stack, program.script.tail)
case Nil =>
@ -30,7 +30,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** If the top stack value is not 0, duplicate it. */
def opIfDup(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_IFDUP, "Top of the script stack must be OP_DUP")
require(program.script.headOption.contains(OP_IFDUP), "Top of the script stack must be OP_DUP")
if (program.stack.nonEmpty) {
if (program.stack.head == ScriptNumber.zero) return ScriptProgram(program, program.stack, program.script.tail)
ScriptProgram(program, program.stack.head :: program.stack, program.script.tail)
@ -42,7 +42,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Puts the number of stack items onto the stack. */
def opDepth(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_DEPTH, "Top of script stack must be OP_DEPTH")
require(program.script.headOption.contains(OP_DEPTH), "Top of script stack must be OP_DEPTH")
require(program.script.nonEmpty, "OP_DEPTH requires at least two elements on the script stack")
val stackSize = program.stack.size
val numberToPush : ScriptNumber = ScriptNumber(stackSize)
@ -51,7 +51,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Puts the input onto the top of the alt stack. Removes it from the main stack. */
def opToAltStack(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_TOALTSTACK, "Top of script stack must be OP_TOALTSTACK")
require(program.script.headOption.contains(OP_TOALTSTACK), "Top of script stack must be OP_TOALTSTACK")
if (program.stack.nonEmpty) {
ScriptProgram(program, program.stack.tail,
program.script.tail, program.stack.head :: program.altStack, ScriptProgram.AltStack)
@ -63,7 +63,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Puts the input onto the top of the main stack. Removes it from the alt stack. */
def opFromAltStack(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_FROMALTSTACK, "Top of script stack must be OP_FROMALTSTACK")
require(program.script.headOption.contains(OP_FROMALTSTACK), "Top of script stack must be OP_FROMALTSTACK")
if (program.altStack.nonEmpty) {
ScriptProgram(program, program.altStack.head :: program.stack,
program.script.tail, program.altStack.tail, ScriptProgram.AltStack)
@ -75,7 +75,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Removes the top stack item. */
def opDrop(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_DROP, "Top of script stack must be OP_DROP")
require(program.script.headOption.contains(OP_DROP), "Top of script stack must be OP_DROP")
if (program.stack.nonEmpty) {
ScriptProgram(program, program.stack.tail, program.script.tail)
} else {
@ -87,7 +87,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Removes the second-to-top stack item. */
def opNip(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_NIP, "Top of script stack must be OP_NIP")
require(program.script.headOption.contains(OP_NIP), "Top of script stack must be OP_NIP")
program.stack match {
case h :: _ :: t => ScriptProgram(program, h :: t, program.script.tail)
case h :: t =>
@ -102,7 +102,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Copies the second-to-top stack item to the top. */
def opOver(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_OVER, "Top of script stack must be OP_OVER")
require(program.script.headOption.contains(OP_OVER), "Top of script stack must be OP_OVER")
program.stack match {
case _ :: h1 :: _ => ScriptProgram(program, h1 :: program.stack, program.script.tail)
case h :: t => logger.error("Stack must have at least two items on it for OP_OVER")
@ -115,8 +115,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** The item n back in the stack is copied to the top. */
def opPick(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_PICK, "Top of script stack must be OP_PICK")
require(program.stack.nonEmpty,"Stack must have at least two items on it for OP_PICK")
require(program.script.headOption.contains(OP_PICK), "Top of script stack must be OP_PICK")
executeOpWithStackTopAsNumberArg(program, { number : ScriptNumber =>
logger.info("Script number for OP_PICK: " + number)
//check if n is within the bound of the script
@ -132,10 +131,9 @@ trait StackInterpreter extends BitcoinSLogger {
/** The item n back in the stack is moved to the top. */
def opRoll(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_ROLL, "Top of script stack must be OP_ROLL")
require(program.stack.nonEmpty,"Stack must have at least one items on it for OP_ROLL")
require(program.script.headOption.contains(OP_ROLL), "Top of script stack must be OP_ROLL")
executeOpWithStackTopAsNumberArg(program, (number : ScriptNumber) =>
if (number.underlying >= 0 && number.underlying < program.stack.tail.size) {
if (number.underlying >= 0 && number.underlying < program.stack.tail.size) {
val newStackTop = program.stack.tail(number.toInt)
//removes the old instance of the stack top, appends the new index to the head
val newStack = newStackTop :: program.stack.tail.diff(List(newStackTop))
@ -150,7 +148,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** The top three items on the stack are rotated to the left.
* Ex: x1 x2 x3 -> x2 x3 x1 */
def opRot(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_ROT, "Top of script stack must be OP_ROT")
require(program.script.headOption.contains(OP_ROT), "Top of script stack must be OP_ROT")
program.stack match {
case h :: h1 :: h2 :: t =>
val newStack = h2 :: h :: h1 :: t
@ -164,7 +162,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** The fifth and sixth items back are moved to the top of the stack.
* Ex. x1 x2 x3 x4 x5 x6 -> x3 x4 x5 x6 x1 x2 */
def op2Rot(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_2ROT, "Top of script stack must be OP_2ROT")
require(program.script.headOption.contains(OP_2ROT), "Top of script stack must be OP_2ROT")
program.stack match {
case h :: h1 :: h2 :: h3 :: h4 :: h5 :: t =>
val newStack = h4 :: h5 :: h :: h1 :: h2 :: h3 :: t
@ -177,7 +175,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Removes the top two stack items. */
def op2Drop(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_2DROP, "Top of script stack must be OP_2DROP")
require(program.script.headOption.contains(OP_2DROP), "Top of script stack must be OP_2DROP")
if (program.stack.size > 1) {
ScriptProgram(program, program.stack.tail.tail, program.script.tail)
} else {
@ -189,7 +187,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** The top two items on the stack are swapped. */
def opSwap(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_SWAP, "Top of script stack must be OP_SWAP")
require(program.script.headOption.contains(OP_SWAP), "Top of script stack must be OP_SWAP")
if (program.stack.size > 1) {
val newStack = program.stack.tail.head :: program.stack.head :: program.stack.tail.tail
ScriptProgram(program, newStack, program.script.tail)
@ -202,7 +200,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** The item at the top of the stack is copied and inserted before the second-to-top item. */
def opTuck(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_TUCK, "Top of script stack must be OP_TUCK")
require(program.script.headOption.contains(OP_TUCK), "Top of script stack must be OP_TUCK")
program.stack match {
case h :: h1 :: t =>
val newStack = h :: h1 :: h:: t
@ -216,7 +214,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Duplicates the top two stack items. */
def op2Dup(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_2DUP, "Top of script stack must be OP_2DUP")
require(program.script.headOption.contains(OP_2DUP), "Top of script stack must be OP_2DUP")
program.stack match {
case h :: h1 :: t =>
val newStack = h :: h1 :: h :: h1 :: t
@ -229,7 +227,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Duplicates the top three stack items. */
def op3Dup(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_3DUP, "Top of script stack must be OP_3DUP")
require(program.script.headOption.contains(OP_3DUP), "Top of script stack must be OP_3DUP")
program.stack match {
case h :: h1 :: h2 :: t =>
val newStack = h :: h1 :: h2 :: h :: h1 :: h2 :: t
@ -242,7 +240,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Copies the pair of items two spaces back in the stack to the front. */
def op2Over(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_2OVER, "Top of script stack must be OP_2OVER")
require(program.script.headOption.contains(OP_2OVER), "Top of script stack must be OP_2OVER")
program.stack match {
case h :: h1 :: h2 :: h3 :: t =>
val newStack = h2 :: h3 :: h :: h1 :: h2 :: h3 :: t
@ -255,7 +253,7 @@ trait StackInterpreter extends BitcoinSLogger {
/** Swaps the top two pairs of items. */
def op2Swap(program : ScriptProgram) : ScriptProgram = {
require(program.script.nonEmpty && program.script.head == OP_2SWAP, "Top of script stack must be OP_2SWAP")
require(program.script.headOption.contains(OP_2SWAP), "Top of script stack must be OP_2SWAP")
program.stack match {
case h :: h1 :: h2 :: h3 :: t =>
val newStack = h2 :: h3 :: h :: h1 :: t