Merge pull request #93 from Christewart/fix_control_flow_bug

Fix control flow bug
This commit is contained in:
Chris Stewart 2017-09-25 15:58:45 -05:00 committed by GitHub
commit bee2ad2303
19 changed files with 570 additions and 560 deletions

View file

@ -16,4 +16,4 @@ mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => {
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false)
testOptions in Test += Tests.Argument("-oF")
//testOptions in Test += Tests.Argument("-oF")

View file

@ -12,7 +12,7 @@ import scala.annotation.tailrec
/**
* Created by chris on 1/25/16.
*/
trait ArithmeticInterpreter extends ControlOperationsInterpreter {
sealed abstract class ArithmeticInterpreter {
private def logger = BitcoinSLogger.logger
/** a is added to b. */
def opAdd(program : ScriptProgram) : ScriptProgram = {
@ -102,7 +102,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
numEqualResult match {
case _ : ExecutionInProgressScriptProgram =>
val verifyProgram = ScriptProgram(numEqualResult, numEqualResult.stack, OP_VERIFY :: numEqualResult.script)
val verifyResult = opVerify(verifyProgram)
val verifyResult = ControlOperationsInterpreter.opVerify(verifyProgram)
verifyResult
case _ : PreExecutionScriptProgram | _ : ExecutedScriptProgram =>
numEqualResult
@ -361,3 +361,5 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
}
}
}
object ArithmeticInterpreter extends ArithmeticInterpreter

View file

@ -10,7 +10,7 @@ import org.bitcoins.core.util.BitcoinSLogger
/**
* Created by chris on 1/6/16.
*/
trait BitwiseInterpreter extends ControlOperationsInterpreter {
sealed abstract class BitwiseInterpreter {
private def logger = BitcoinSLogger.logger
/** Returns 1 if the inputs are exactly equal, 0 otherwise. */
def opEqual(program : ScriptProgram) : ScriptProgram = {
@ -43,7 +43,7 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
//first replace OP_EQUALVERIFY with OP_EQUAL and OP_VERIFY
val simpleScript = OP_EQUAL :: OP_VERIFY :: program.script.tail
val newProgram: ScriptProgram = opEqual(ScriptProgram(program, program.stack, simpleScript))
opVerify(newProgram) match {
ControlOperationsInterpreter.opVerify(newProgram) match {
case p: PreExecutionScriptProgram => p
case p: ExecutedScriptProgram =>
if (p.error.isDefined) ScriptProgram(p, ScriptErrorEqualVerify)
@ -55,4 +55,6 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
ScriptProgram(program,ScriptErrorInvalidStackOperation)
}
}
}
}
object BitwiseInterpreter extends BitwiseInterpreter

View file

@ -10,7 +10,7 @@ import scala.annotation.tailrec
/**
* Created by chris on 1/24/16.
*/
trait ConstantInterpreter {
sealed abstract class ConstantInterpreter {
private def logger = BitcoinSLogger.logger
/** The next byte contains the number of bytes to be pushed onto the stack. */
@ -128,3 +128,5 @@ trait ConstantInterpreter {
case _ => throw new IllegalArgumentException("Token must be BytesToPushOntoStack to push a number of bytes onto the stack")
}
}
object ConstantInterpreter extends ConstantInterpreter

View file

@ -1,6 +1,6 @@
package org.bitcoins.core.script.control
import org.bitcoins.core.protocol.script.SigVersionWitnessV0
import org.bitcoins.core.protocol.script.{SigVersionWitnessV0, SignatureVersion}
import org.bitcoins.core.script.ScriptProgram
import org.bitcoins.core.script.constant._
import org.bitcoins.core.script.flag.ScriptFlagUtil
@ -12,7 +12,7 @@ import scala.annotation.tailrec
/**
* Created by chris on 1/6/16.
*/
trait ControlOperationsInterpreter {
sealed abstract class ControlOperationsInterpreter {
private def logger = BitcoinSLogger.logger
/** If the top stack value is not 0, the statements are executed. The top stack value is removed. */
def opIf(program : ScriptProgram) : ScriptProgram = {
@ -29,11 +29,7 @@ trait ControlOperationsInterpreter {
} else if (program.stack.isEmpty) {
logger.error("We do not have any stack elements for our OP_IF")
ScriptProgram(program,ScriptErrorUnbalancedConditional)
} else if (sigVersion == SigVersionWitnessV0 && minimalIfEnabled
&& (stackTop.get.bytes.size > 1 ||
(stackTop.get.bytes.size == 1 && stackTop.get.bytes.head != 1))) {
//see: https://github.com/bitcoin/bitcoin/blob/528472111b4965b1a99c4bcf08ac5ec93d87f10f/src/script/interpreter.cpp#L447-L452
//https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-August/013014.html
} else if (isNotMinimalStackTop(stackTop,sigVersion,minimalIfEnabled)) {
logger.error("OP_IF argument was not minimally encoded, got: " + stackTop)
ScriptProgram(program, ScriptErrorMinimalIf)
} else if (program.stackTopIsTrue) {
@ -53,41 +49,38 @@ trait ControlOperationsInterpreter {
ScriptProgram(program, program.stack.tail,scriptWithoutOpIf.toList)
}
}
/** Checks if the stack top is NOT minimially encoded */
private def isNotMinimalStackTop(stackTopOpt: Option[ScriptToken], sigVersion: SignatureVersion,
minimalIfEnabled: Boolean): Boolean = {
//see: https://github.com/bitcoin/bitcoin/blob/528472111b4965b1a99c4bcf08ac5ec93d87f10f/src/script/interpreter.cpp#L447-L452
//https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-August/013014.html
val isNotMinimal = stackTopOpt.map { stackTop =>
(sigVersion == SigVersionWitnessV0 && minimalIfEnabled
&& (stackTop.bytes.size > 1 ||
(stackTop.bytes.size == 1 && stackTop.bytes.head != 1)))
}
isNotMinimal.isDefined && isNotMinimal.get
}
/** If the top stack value is 0, the statements are executed. The top stack value is removed. */
def opNotIf(program : ScriptProgram) : ScriptProgram = {
//TODO: Try and reduce this down to using OP_IF by inverting the stack top
require(program.script.headOption.contains(OP_NOTIF), "Script top was not OP_NOTIF")
val binaryTree = parseBinaryTree(program.script)
val minimalIfEnabled = ScriptFlagUtil.minimalIfEnabled(program.flags)
val sigVersion = program.txSignatureComponent.sigVersion
val flags = program.flags
val minimalIfEnabled = ScriptFlagUtil.minimalIfEnabled(flags)
val stackTop = program.stack.headOption
logger.debug("Parsed binary tree: " + binaryTree)
if (!checkMatchingOpIfOpNotIfOpEndIf(program.originalScript)) {
logger.error("We do not have a matching OP_ENDIF for every OP_NOTIF we have")
ScriptProgram(program,ScriptErrorUnbalancedConditional)
} else if (program.stack.isEmpty) {
logger.error("We do not have any stack elements for our OP_NOTIF")
ScriptProgram(program,ScriptErrorUnbalancedConditional)
} else if (sigVersion == SigVersionWitnessV0 && minimalIfEnabled
&& (stackTop.get.bytes.size > 1 ||
(stackTop.get.bytes.size == 1 && stackTop.get.bytes.head != 1))) {
//see: https://github.com/bitcoin/bitcoin/blob/528472111b4965b1a99c4bcf08ac5ec93d87f10f/src/script/interpreter.cpp#L447-L452
//https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-August/013014.html
logger.error("OP_NOTIF argument was not minimally encoded, got: " + stackTop)
ScriptProgram(program, ScriptErrorMinimalIf)
} else if (program.stackTopIsTrue) {
//remove the OP_NOTIF
val scriptWithoutOpIf : BinaryTree[ScriptToken] = removeFirstOpIf(binaryTree)
ScriptProgram(program, program.stack.tail,scriptWithoutOpIf.toList)
val oldStackTop = program.stack.headOption
if (isNotMinimalStackTop(oldStackTop,sigVersion,minimalIfEnabled)) {
//need to duplicate minimal check, we cannot accurately invert the stack
//top for OP_IF otherwise
ScriptProgram(program,ScriptErrorMinimalIf)
} else {
//if the left branch contains and OP_NOTIF & OP_ENDIF there must be a nested OP_IF or OP_NOTIF
//remove OP_ELSE from binary tree
val newTreeWithoutOpElse = removeFirstOpElse(binaryTree)
val newScript = newTreeWithoutOpElse.toList
ScriptProgram(program, program.stack.tail,newScript.tail)
val script = OP_IF :: program.script.tail
val stackTop = if (program.stackTopIsTrue) ScriptNumber.zero else ScriptNumber.one
val stack = if (program.stack.nonEmpty) stackTop :: program.stack.tail else Nil
val newProgram = ScriptProgram(program,stack,script)
opIf(newProgram)
}
}
/** Evaluates the [[OP_ELSE]] operator. */
@ -102,16 +95,7 @@ trait ControlOperationsInterpreter {
case Empty => Empty
case leaf : Leaf[ScriptToken] => leaf
case node : Node[ScriptToken] =>
if (node.r.value == Some(OP_ELSE)) {
val replacementTree = node.r.left.getOrElse(Empty).findFirstDFS[ScriptToken](OP_ENDIF)().getOrElse(Empty)
val replacementNode = replacementTree match {
case Empty => Empty
case leaf : Leaf[ScriptToken] => Node(leaf.v, Empty, node.r.right.getOrElse(Empty))
case node1 : Node[ScriptToken] => Node(node1.v,node1.l,node.r.right.getOrElse(Empty))
}
Node(node.v,node.l,replacementNode)
}
else node
removeFirstOpElse(node)
}
ScriptProgram(program, program.stack,treeWithNextOpElseRemoved.toList.tail)
}
@ -151,38 +135,48 @@ trait ControlOperationsInterpreter {
}
/** Parses a list of [[ScriptToken]]s into its corresponding [[BinaryTree]] */
def parseBinaryTree(script : List[ScriptToken]) : BinaryTree[ScriptToken] = {
val bTree = loop(script,Empty)
bTree
def parseBinaryTree(script : List[ScriptToken]): BinaryTree[ScriptToken] = {
//@tailrec
def loop(remaining: List[ScriptToken], parentTree: BinaryTree[ScriptToken]): (BinaryTree[ScriptToken], List[ScriptToken]) = {
if (remaining.isEmpty) (parentTree,Nil)
else {
if (parentTree.right.isDefined && parentTree.right.get.value == Some(OP_ELSE)) {
//for the case of OP_IF OP_1 OP_ELSE OP_2 OP_ELSE OP_3 ... OP_ELSE OP_N OP_ENDIF
val (elseTree,newRemaining) = loop(remaining, parentTree.right.getOrElse(Empty))
(Node(parentTree.value.get, parentTree.left.getOrElse(Empty), elseTree),newRemaining)
} else {
val (tree, newRemaining) = parse(remaining,parentTree)
loop(newRemaining,tree)
}
}
}
val (t, remaining) = loop(script,Empty)
require(remaining.isEmpty, "Should not have any script tokens after parsing a binary tree, got: " + remaining)
t
}
/** The loop that parses a list of [[ScriptToken]]s into a [[BinaryTree]]. */
@tailrec
private def loop(script : List[ScriptToken], tree : BinaryTree[ScriptToken]) : BinaryTree[ScriptToken] = {
/* logger.debug("Script : " + script)
logger.debug("Tree: " + tree)*/
script match {
case OP_IF :: t =>
val (newTail, parsedTree) = parseOpIf(script)
val newTree = insertSubTree(tree,parsedTree)
loop(newTail, newTree)
case OP_NOTIF :: t =>
val (newTail, parsedTree) = parseOpNotIf(script)
val newTree = insertSubTree(tree,parsedTree)
loop(newTail, newTree)
case OP_ELSE :: t =>
val (newTail, parsedTree) = parseOpElse(script)
val newTree = insertSubTree(tree,parsedTree)
loop(newTail, newTree)
case OP_ENDIF :: t =>
val (newTail, parsedTree) = parseOpEndIf(script)
val newTree = insertSubTree(tree,parsedTree)
loop(newTail, newTree)
case (x: ScriptConstant) :: t => loop(t, insertSubTree(tree, Leaf(x)))
case (x: BytesToPushOntoStack) :: t => loop(t, insertSubTree(tree, Leaf(x)))
case h :: t => loop(t,insertSubTree(tree,Leaf(h)))
case Nil => tree
}
private def parse(script : List[ScriptToken],
tree : BinaryTree[ScriptToken]): (BinaryTree[ScriptToken], List[ScriptToken]) = script match {
case OP_ENDIF :: t =>
val ifTree = insertSubTree(tree,Leaf(OP_ENDIF))
(ifTree,t)
case h :: t if (h == OP_IF || h == OP_NOTIF) =>
val (ifTree,remaining) = parse(t, Leaf(h))
val fullTree = insertSubTree(tree,ifTree)
(fullTree,remaining)
case h :: t if h == OP_ELSE =>
val (subTree,remaining) = parse(t,Node(OP_ELSE,Empty,Empty))
val opElseTree = tree match {
case Empty => subTree
case l: Leaf[ScriptToken] => Node(l.v,Empty,subTree)
case n: Node[ScriptToken] => Node(n.v,n.l,insertSubTree(n.r,subTree))
}
(opElseTree,remaining)
case h :: t => parse(t,insertSubTree(tree,Leaf(h)))
case Nil =>
logger.debug("Done parsing tree, got: " + tree)
(tree,Nil)
}
/**
@ -191,58 +185,24 @@ trait ControlOperationsInterpreter {
* @param subTree the parse tree that needs to be inserted into the control flow of the program
* @return the full parse tree combined
*/
private def insertSubTree(tree : BinaryTree[ScriptToken],subTree : BinaryTree[ScriptToken]) : BinaryTree[ScriptToken] = {
//TODO: Optimize this to a tailrec function
//logger.debug("Inserting subTree: " + subTree + " into tree: " + tree)
tree match {
case Empty => subTree
case leaf : Leaf[ScriptToken] => Node(leaf.v, subTree, Empty)
case node : Node[ScriptToken] =>
if (subTree.value.isDefined && subTree.value.get == OP_ELSE) {
//need to insert the OP_ELSE within the proper OP_IF
//get count of OP_IFs and OP_ENDIFS inside of the tree
val opIfCount = node.l.count[ScriptToken](OP_IF)
val opNotIfCount = node.l.count[ScriptToken](OP_NOTIF)
val opEndIfCount = node.l.count[ScriptToken](OP_ENDIF)
//means that the subtree is not balanced, need to insert the OP_ELSE inside
//the left subtree
if (opIfCount + opNotIfCount != opEndIfCount) Node(node.v,insertSubTree(tree.left.get,subTree),node.r)
else Node(node.v,node.l,insertSubTree(tree.right.getOrElse(Empty),subTree))
} else if (node.r.value.isDefined && node.r.value.get == OP_ELSE) {
//since there is an OP_ELSE defined to right
//we need to insert all script tokens on that node
Node(node.v,node.l,insertSubTree(node.r,subTree))
}
else Node(node.v, insertSubTree(node.l, subTree), node.r)
//@tailrec
private def insertSubTree(tree: BinaryTree[ScriptToken],
subTree: BinaryTree[ScriptToken]): BinaryTree[ScriptToken] = tree match {
case Empty => subTree
case leaf: Leaf[ScriptToken] =>
if (subTree == Empty) leaf
else if (subTree == Leaf(OP_ENDIF)) Node(leaf.v,Empty,subTree)
else Node(leaf.v,subTree,Empty)
case node : Node[ScriptToken] if (node.v == OP_IF || node.v == OP_NOTIF || node.v == OP_ELSE || node.v == OP_ENDIF) =>
if (subTree.value.isDefined && Seq(OP_ELSE,OP_ENDIF).contains(subTree.value.get)) {
Node(node.v,node.l,insertSubTree(node.r,subTree))
} else if (node.r != Empty && Seq(OP_ELSE,OP_ENDIF).contains(node.r.value.get)) {
Node(node.v,node.l,insertSubTree(node.r,subTree))
} else {
Node(node.v,insertSubTree(node.l,subTree),node.r)
}
}
/** Parses an [[OP_IF]] [[ScriptToken]]. */
private def parseOpIf(script : List[ScriptToken]) : (List[ScriptToken],BinaryTree[ScriptToken]) = script match {
case OP_IF :: t => (t, Node(OP_IF,Empty,Empty))
case h :: t => throw new IllegalArgumentException("Cannot parse " + h + " as an OP_IF")
case Nil => (script,Empty)
}
/** Parses an [[OP_NOTIF]] [[ScriptToken]]. */
private def parseOpNotIf(script : List[ScriptToken]) : (List[ScriptToken],BinaryTree[ScriptToken]) = script match {
case OP_NOTIF :: t => (t, Node(OP_NOTIF,Empty,Empty))
case h :: t => throw new IllegalArgumentException("Cannot parse " + h + " as an OP_NOTIF")
case Nil => (script,Empty)
}
/** Parses an [[OP_ELSE]] [[ScriptToken]]. */
private def parseOpElse(script : List[ScriptToken]) : (List[ScriptToken],BinaryTree[ScriptToken]) = script match {
case OP_ELSE :: t => (t,Node(OP_ELSE,Empty,Empty))
case h :: t => throw new RuntimeException("Cannot parse " + h + " as an OP_ELSE")
case Nil => (script,Empty)
}
/** Parses an [[OP_ENDIF]] [[ScriptToken]]. */
private def parseOpEndIf(script : List[ScriptToken]) : (List[ScriptToken],BinaryTree[ScriptToken]) = script match {
case OP_ENDIF :: t => (t,Leaf(OP_ENDIF))
case h :: t => throw new IllegalArgumentException("Cannot parse " + h + " as an OP_ENDIF")
case Nil => (script,Empty)
case node: Node[ScriptToken] =>
Node(node.v,insertSubTree(node.l,subTree), node.r)
}
/** Checks if an [[OP_IF]]/[[OP_NOTIF]] [[ScriptToken]] has a matching [[OP_ENDIF]] */
@ -253,7 +213,7 @@ trait ControlOperationsInterpreter {
case OP_ENDIF :: t => loop(t,counter-1)
case OP_IF :: t => loop(t, counter + 1)
case OP_NOTIF :: t => loop(t, counter + 1)
case (token : ScriptToken) :: t => loop(t, counter)
case (_: ScriptToken) :: t => loop(t, counter)
case Nil => counter == 0
}
loop(script,0)
@ -286,72 +246,38 @@ trait ControlOperationsInterpreter {
/** Removes the first [[OP_ELSE]] expression encountered in the script. */
def removeFirstOpElse(script : List[ScriptToken]) : List[ScriptToken] = {
if (script.contains(OP_ELSE)) {
val firstOpElseIndex = findFirstOpElse(script)
val scriptWithoutFirstOpElse = script.zipWithIndex.filter(_._2 != firstOpElseIndex.get).map(_._1)
val nextOpElseIndex = findFirstOpElse(scriptWithoutFirstOpElse)
if(nextOpElseIndex.isDefined) {
script.slice(0,firstOpElseIndex.get) ++ script.slice(nextOpElseIndex.get + 1, script.size)
} else {
val firstOpEndIfIndex = findFirstOpEndIf(script)
script.slice(0,firstOpElseIndex.get) ++ script.slice(firstOpEndIfIndex.get, script.size)
}
} else script
removeFirstOpElse(parseBinaryTree(script)).toList
}
/** Removes the first [[OP_ELSE]] in a [[BinaryTree]]. */
def removeFirstOpElse(tree : BinaryTree[ScriptToken]) : BinaryTree[ScriptToken] = {
//@tailrec
def loop(child: BinaryTree[ScriptToken], parent: Node[ScriptToken]): BinaryTree[ScriptToken] = child match {
case Empty => Empty
case l: Leaf[ScriptToken] => l
case Node(OP_ELSE,_,r) => r
case n: Node[ScriptToken] =>
Node(n.v,n.l,loop(n.r,n))
}
tree match {
case Empty => Empty
case leaf : Leaf[ScriptToken] => leaf
case node : Node[ScriptToken] =>
logger.debug("Node: " + node)
//need to traverse the tree to see if there is an OP_ENDIF on the left hand side
val leftBranchContainsOpElse = node.l.contains[ScriptToken](OP_ELSE)()
val leftBranchContainsOpIf = node.l.contains[ScriptToken](OP_IF)()
logger.debug("leftBranchContainsOpElse " + leftBranchContainsOpElse)
logger.debug("leftBranchContainsOpIf " + leftBranchContainsOpIf)
if (leftBranchContainsOpElse && !leftBranchContainsOpIf) {
//if the left branch contains an OP_ELSE but no OP_IF
//then we need to delete the OP_ELSE in the left branch
val subTree: Option[BinaryTree[ScriptToken]] = node.l.findFirstDFS[ScriptToken](OP_ELSE)()
logger.debug("Sub tree: " + subTree)
//need to remove the subtree for the OP_ELSE
//need to insert the right branch of the subtree into the original place of the OP_ELSE
if (subTree.isDefined) tree.replace(subTree.get, subTree.get.right.getOrElse(Empty))
else tree
} else if (node.r.value == Some(OP_ELSE) && node.r.left.isDefined && node.r.left.get.value == Some(OP_ENDIF)) {
logger.debug("============================**********************************")
Node(node.v,node.l,node.r.left.getOrElse(Empty))
} else if (node.r.value == Some(OP_ELSE)) {
Node(node.v,node.l,node.r.right.getOrElse(Empty))
} else tree
case l: Leaf[ScriptToken] => l
case n: Node[ScriptToken] =>
val result = Node(n.v,n.l,loop(n.r, n))
result
}
}
/** Removes the first [[OP_IF]] encountered in the script. */
def removeFirstOpIf(script : List[ScriptToken]) : List[ScriptToken] = {
val firstOpIfIndex = script.indexOf(OP_IF)
val matchingOpEndIfIndex = findMatchingOpEndIf(script)
val opIfExpression = script.slice(firstOpIfIndex,matchingOpEndIfIndex)
val hasNestedIfExpression = opIfExpression.count(_ == OP_IF) > 1
val (firstOpElseIndex,_) = findFirstIndexesOpElseOpEndIf(opIfExpression)
if (firstOpElseIndex.isDefined && !hasNestedIfExpression) {
script.slice(0,firstOpIfIndex) ++ script.slice(firstOpElseIndex.get,script.size)
} else if (opIfExpression.contains(OP_IF)) {
//if there is an OP_IF inside of the sub script then any OP_ELSES inside of there are bound to
//that OP_IF
script.slice(0,firstOpIfIndex) ++ script.slice(matchingOpEndIfIndex,script.size)
} else script.slice(0,firstOpIfIndex) ++ script.slice(matchingOpEndIfIndex,script.size)
removeFirstOpIf(parseBinaryTree(script)).toList
}
/** Removes the first occurrence of [[OP_IF]] or [[OP_NOTIF]] in the [[BinaryTree]]. */
def removeFirstOpIf(tree : BinaryTree[ScriptToken]) : BinaryTree[ScriptToken] = {
require(tree.value.isDefined && (tree.value.get == OP_IF || tree.value.get == OP_NOTIF) , "Top of the tree must be OP_IF or OP_NOTIF to remove the OP_IF or OP_NOTIF")
if (tree.right.isDefined && tree.right.get.value == Some(OP_ELSE)) tree.right.getOrElse(Empty)
else tree.findFirstDFS[ScriptToken](OP_ENDIF)().getOrElse(Empty)
tree.right.getOrElse(Empty)
}
/** Finds the indexes of our [[OP_ELSE]] (if it exists) and our [[OP_ENDIF]]. */
@ -368,3 +294,5 @@ trait ControlOperationsInterpreter {
matchingOpEndIfIndex.get
}
}
object ControlOperationsInterpreter extends ControlOperationsInterpreter

View file

@ -14,7 +14,7 @@ import scala.annotation.tailrec
/**
* Created by chris on 1/6/16.
*/
trait CryptoInterpreter extends ControlOperationsInterpreter {
sealed abstract class CryptoInterpreter {
private def logger = BitcoinSLogger.logger
@ -95,7 +95,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter {
programFromOpCheckSig match {
case _ : PreExecutionScriptProgram | _ : ExecutedScriptProgram =>
programFromOpCheckSig
case _ : ExecutionInProgressScriptProgram => opVerify(programFromOpCheckSig)
case _ : ExecutionInProgressScriptProgram => ControlOperationsInterpreter.opVerify(programFromOpCheckSig)
}
}
}
@ -229,7 +229,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter {
programFromOpCheckMultiSig match {
case _ : PreExecutionScriptProgram | _ : ExecutedScriptProgram =>
programFromOpCheckMultiSig
case _ : ExecutionInProgressScriptProgram => opVerify(programFromOpCheckMultiSig)
case _ : ExecutionInProgressScriptProgram => ControlOperationsInterpreter.opVerify(programFromOpCheckMultiSig)
}
}
}
@ -286,3 +286,5 @@ trait CryptoInterpreter extends ControlOperationsInterpreter {
ScriptProgram(program,ScriptErrorSigNullFail)
}
}
object CryptoInterpreter extends CryptoInterpreter

View file

@ -26,9 +26,7 @@ import scala.util.{Failure, Success, Try}
/**
* Created by chris on 1/6/16.
*/
trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with ControlOperationsInterpreter
with BitwiseInterpreter with ConstantInterpreter with ArithmeticInterpreter with SpliceInterpreter
with LockTimeInterpreter {
sealed abstract class ScriptInterpreter {
private def logger = BitcoinSLogger.logger
/**
@ -309,86 +307,86 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
loop(ScriptProgram(p, ScriptErrorStackSize),opCount)
//stack operations
case OP_DUP :: t => loop(opDup(p),calcOpCount(opCount,OP_DUP))
case OP_DEPTH :: t => loop(opDepth(p),calcOpCount(opCount,OP_DEPTH))
case OP_TOALTSTACK :: t => loop(opToAltStack(p),calcOpCount(opCount,OP_TOALTSTACK))
case OP_FROMALTSTACK :: t => loop(opFromAltStack(p),calcOpCount(opCount,OP_FROMALTSTACK))
case OP_DROP :: t => loop(opDrop(p),calcOpCount(opCount,OP_DROP))
case OP_IFDUP :: t => loop(opIfDup(p),calcOpCount(opCount,OP_IFDUP))
case OP_NIP :: t => loop(opNip(p),calcOpCount(opCount,OP_NIP))
case OP_OVER :: t => loop(opOver(p),calcOpCount(opCount,OP_OVER))
case OP_PICK :: t => loop(opPick(p),calcOpCount(opCount,OP_PICK))
case OP_ROLL :: t => loop(opRoll(p),calcOpCount(opCount,OP_ROLL))
case OP_ROT :: t => loop(opRot(p),calcOpCount(opCount,OP_ROT))
case OP_2ROT :: t => loop(op2Rot(p),calcOpCount(opCount,OP_2ROT))
case OP_2DROP :: t => loop(op2Drop(p),calcOpCount(opCount,OP_2DROP))
case OP_SWAP :: t => loop(opSwap(p),calcOpCount(opCount,OP_SWAP))
case OP_TUCK :: t => loop(opTuck(p),calcOpCount(opCount,OP_TUCK))
case OP_2DUP :: t => loop(op2Dup(p),calcOpCount(opCount,OP_2DUP))
case OP_3DUP :: t => loop(op3Dup(p),calcOpCount(opCount,OP_3DUP))
case OP_2OVER :: t => loop(op2Over(p),calcOpCount(opCount,OP_2OVER))
case OP_2SWAP :: t => loop(op2Swap(p),calcOpCount(opCount,OP_2SWAP))
case OP_DUP :: t => loop(StackInterpreter.opDup(p),calcOpCount(opCount,OP_DUP))
case OP_DEPTH :: t => loop(StackInterpreter.opDepth(p),calcOpCount(opCount,OP_DEPTH))
case OP_TOALTSTACK :: t => loop(StackInterpreter.opToAltStack(p),calcOpCount(opCount,OP_TOALTSTACK))
case OP_FROMALTSTACK :: t => loop(StackInterpreter.opFromAltStack(p),calcOpCount(opCount,OP_FROMALTSTACK))
case OP_DROP :: t => loop(StackInterpreter.opDrop(p),calcOpCount(opCount,OP_DROP))
case OP_IFDUP :: t => loop(StackInterpreter.opIfDup(p),calcOpCount(opCount,OP_IFDUP))
case OP_NIP :: t => loop(StackInterpreter.opNip(p),calcOpCount(opCount,OP_NIP))
case OP_OVER :: t => loop(StackInterpreter.opOver(p),calcOpCount(opCount,OP_OVER))
case OP_PICK :: t => loop(StackInterpreter.opPick(p),calcOpCount(opCount,OP_PICK))
case OP_ROLL :: t => loop(StackInterpreter.opRoll(p),calcOpCount(opCount,OP_ROLL))
case OP_ROT :: t => loop(StackInterpreter.opRot(p),calcOpCount(opCount,OP_ROT))
case OP_2ROT :: t => loop(StackInterpreter.op2Rot(p),calcOpCount(opCount,OP_2ROT))
case OP_2DROP :: t => loop(StackInterpreter.op2Drop(p),calcOpCount(opCount,OP_2DROP))
case OP_SWAP :: t => loop(StackInterpreter.opSwap(p),calcOpCount(opCount,OP_SWAP))
case OP_TUCK :: t => loop(StackInterpreter.opTuck(p),calcOpCount(opCount,OP_TUCK))
case OP_2DUP :: t => loop(StackInterpreter.op2Dup(p),calcOpCount(opCount,OP_2DUP))
case OP_3DUP :: t => loop(StackInterpreter.op3Dup(p),calcOpCount(opCount,OP_3DUP))
case OP_2OVER :: t => loop(StackInterpreter.op2Over(p),calcOpCount(opCount,OP_2OVER))
case OP_2SWAP :: t => loop(StackInterpreter.op2Swap(p),calcOpCount(opCount,OP_2SWAP))
//arithmetic operations
case OP_ADD :: t => loop(opAdd(p),calcOpCount(opCount,OP_ADD))
case OP_1ADD :: t => loop(op1Add(p),calcOpCount(opCount,OP_1ADD))
case OP_1SUB :: t => loop(op1Sub(p),calcOpCount(opCount,OP_1SUB))
case OP_SUB :: t => loop(opSub(p),calcOpCount(opCount,OP_SUB))
case OP_ABS :: t => loop(opAbs(p),calcOpCount(opCount,OP_ABS))
case OP_NEGATE :: t => loop(opNegate(p),calcOpCount(opCount,OP_NEGATE))
case OP_NOT :: t => loop(opNot(p),calcOpCount(opCount,OP_NOT))
case OP_0NOTEQUAL :: t => loop(op0NotEqual(p),calcOpCount(opCount,OP_0NOTEQUAL))
case OP_BOOLAND :: t => loop(opBoolAnd(p),calcOpCount(opCount,OP_BOOLAND))
case OP_BOOLOR :: t => loop(opBoolOr(p),calcOpCount(opCount,OP_BOOLOR))
case OP_NUMEQUAL :: t => loop(opNumEqual(p),calcOpCount(opCount,OP_NUMEQUAL))
case OP_NUMEQUALVERIFY :: t => loop(opNumEqualVerify(p),calcOpCount(opCount,OP_NUMEQUALVERIFY))
case OP_NUMNOTEQUAL :: t => loop(opNumNotEqual(p),calcOpCount(opCount,OP_NUMNOTEQUAL))
case OP_LESSTHAN :: t => loop(opLessThan(p),calcOpCount(opCount,OP_LESSTHAN))
case OP_GREATERTHAN :: t => loop(opGreaterThan(p),calcOpCount(opCount,OP_GREATERTHAN))
case OP_LESSTHANOREQUAL :: t => loop(opLessThanOrEqual(p),calcOpCount(opCount,OP_LESSTHANOREQUAL))
case OP_GREATERTHANOREQUAL :: t => loop(opGreaterThanOrEqual(p),calcOpCount(opCount,OP_GREATERTHANOREQUAL))
case OP_MIN :: t => loop(opMin(p),calcOpCount(opCount,OP_MIN))
case OP_MAX :: t => loop(opMax(p),calcOpCount(opCount,OP_MAX))
case OP_WITHIN :: t => loop(opWithin(p),calcOpCount(opCount,OP_WITHIN))
case OP_ADD :: t => loop(ArithmeticInterpreter.opAdd(p),calcOpCount(opCount,OP_ADD))
case OP_1ADD :: t => loop(ArithmeticInterpreter.op1Add(p),calcOpCount(opCount,OP_1ADD))
case OP_1SUB :: t => loop(ArithmeticInterpreter.op1Sub(p),calcOpCount(opCount,OP_1SUB))
case OP_SUB :: t => loop(ArithmeticInterpreter.opSub(p),calcOpCount(opCount,OP_SUB))
case OP_ABS :: t => loop(ArithmeticInterpreter.opAbs(p),calcOpCount(opCount,OP_ABS))
case OP_NEGATE :: t => loop(ArithmeticInterpreter.opNegate(p),calcOpCount(opCount,OP_NEGATE))
case OP_NOT :: t => loop(ArithmeticInterpreter.opNot(p),calcOpCount(opCount,OP_NOT))
case OP_0NOTEQUAL :: t => loop(ArithmeticInterpreter.op0NotEqual(p),calcOpCount(opCount,OP_0NOTEQUAL))
case OP_BOOLAND :: t => loop(ArithmeticInterpreter.opBoolAnd(p),calcOpCount(opCount,OP_BOOLAND))
case OP_BOOLOR :: t => loop(ArithmeticInterpreter.opBoolOr(p),calcOpCount(opCount,OP_BOOLOR))
case OP_NUMEQUAL :: t => loop(ArithmeticInterpreter.opNumEqual(p),calcOpCount(opCount,OP_NUMEQUAL))
case OP_NUMEQUALVERIFY :: t => loop(ArithmeticInterpreter.opNumEqualVerify(p),calcOpCount(opCount,OP_NUMEQUALVERIFY))
case OP_NUMNOTEQUAL :: t => loop(ArithmeticInterpreter.opNumNotEqual(p),calcOpCount(opCount,OP_NUMNOTEQUAL))
case OP_LESSTHAN :: t => loop(ArithmeticInterpreter.opLessThan(p),calcOpCount(opCount,OP_LESSTHAN))
case OP_GREATERTHAN :: t => loop(ArithmeticInterpreter.opGreaterThan(p),calcOpCount(opCount,OP_GREATERTHAN))
case OP_LESSTHANOREQUAL :: t => loop(ArithmeticInterpreter.opLessThanOrEqual(p),calcOpCount(opCount,OP_LESSTHANOREQUAL))
case OP_GREATERTHANOREQUAL :: t => loop(ArithmeticInterpreter.opGreaterThanOrEqual(p),calcOpCount(opCount,OP_GREATERTHANOREQUAL))
case OP_MIN :: t => loop(ArithmeticInterpreter.opMin(p),calcOpCount(opCount,OP_MIN))
case OP_MAX :: t => loop(ArithmeticInterpreter.opMax(p),calcOpCount(opCount,OP_MAX))
case OP_WITHIN :: t => loop(ArithmeticInterpreter.opWithin(p),calcOpCount(opCount,OP_WITHIN))
//bitwise operations
case OP_EQUAL :: t => loop(opEqual(p),calcOpCount(opCount,OP_EQUAL))
case OP_EQUAL :: t => loop(BitwiseInterpreter.opEqual(p),calcOpCount(opCount,OP_EQUAL))
case OP_EQUALVERIFY :: t => loop(opEqualVerify(p),calcOpCount(opCount,OP_EQUALVERIFY))
case OP_EQUALVERIFY :: t => loop(BitwiseInterpreter.opEqualVerify(p),calcOpCount(opCount,OP_EQUALVERIFY))
case OP_0 :: t => loop(ScriptProgram(p, ScriptNumber.zero :: p.stack, t),calcOpCount(opCount,OP_0))
case (scriptNumberOp : ScriptNumberOperation) :: t =>
loop(ScriptProgram(p, ScriptNumber(scriptNumberOp.underlying) :: p.stack, t),calcOpCount(opCount,scriptNumberOp))
case (bytesToPushOntoStack: BytesToPushOntoStack) :: t =>
loop(pushScriptNumberBytesToStack(p),calcOpCount(opCount,bytesToPushOntoStack))
loop(ConstantInterpreter.pushScriptNumberBytesToStack(p),calcOpCount(opCount,bytesToPushOntoStack))
case (scriptNumber: ScriptNumber) :: t =>
loop(ScriptProgram(p, scriptNumber :: p.stack, t),calcOpCount(opCount,scriptNumber))
case OP_PUSHDATA1 :: t => loop(opPushData1(p),calcOpCount(opCount,OP_PUSHDATA1))
case OP_PUSHDATA2 :: t => loop(opPushData2(p),calcOpCount(opCount,OP_PUSHDATA2))
case OP_PUSHDATA4 :: t => loop(opPushData4(p),calcOpCount(opCount,OP_PUSHDATA4))
case OP_PUSHDATA1 :: t => loop(ConstantInterpreter.opPushData1(p),calcOpCount(opCount,OP_PUSHDATA1))
case OP_PUSHDATA2 :: t => loop(ConstantInterpreter.opPushData2(p),calcOpCount(opCount,OP_PUSHDATA2))
case OP_PUSHDATA4 :: t => loop(ConstantInterpreter.opPushData4(p),calcOpCount(opCount,OP_PUSHDATA4))
case (x : ScriptConstant) :: t => loop(ScriptProgram(p, x :: p.stack, t),calcOpCount(opCount,x))
//control operations
case OP_IF :: t => loop(opIf(p),calcOpCount(opCount,OP_IF))
case OP_NOTIF :: t => loop(opNotIf(p),calcOpCount(opCount,OP_NOTIF))
case OP_ELSE :: t => loop(opElse(p),calcOpCount(opCount,OP_ELSE))
case OP_ENDIF :: t => loop(opEndIf(p),calcOpCount(opCount,OP_ENDIF))
case OP_RETURN :: t => loop(opReturn(p),calcOpCount(opCount,OP_RETURN))
case OP_IF :: t => loop(ControlOperationsInterpreter.opIf(p),calcOpCount(opCount,OP_IF))
case OP_NOTIF :: t => loop(ControlOperationsInterpreter.opNotIf(p),calcOpCount(opCount,OP_NOTIF))
case OP_ELSE :: t => loop(ControlOperationsInterpreter.opElse(p),calcOpCount(opCount,OP_ELSE))
case OP_ENDIF :: t => loop(ControlOperationsInterpreter.opEndIf(p),calcOpCount(opCount,OP_ENDIF))
case OP_RETURN :: t => loop(ControlOperationsInterpreter.opReturn(p),calcOpCount(opCount,OP_RETURN))
case OP_VERIFY :: t => loop(opVerify(p),calcOpCount(opCount,OP_VERIFY))
case OP_VERIFY :: t => loop(ControlOperationsInterpreter.opVerify(p),calcOpCount(opCount,OP_VERIFY))
//crypto operations
case OP_HASH160 :: t => loop(opHash160(p),calcOpCount(opCount,OP_HASH160))
case OP_CHECKSIG :: t => loop(opCheckSig(p),calcOpCount(opCount,OP_CHECKSIG))
case OP_CHECKSIGVERIFY :: t => loop(opCheckSigVerify(p),calcOpCount(opCount,OP_CHECKSIGVERIFY))
case OP_SHA1 :: t => loop(opSha1(p),calcOpCount(opCount,OP_SHA1))
case OP_RIPEMD160 :: t => loop(opRipeMd160(p),calcOpCount(opCount,OP_RIPEMD160))
case OP_SHA256 :: t => loop(opSha256(p),calcOpCount(opCount,OP_SHA256))
case OP_HASH256 :: t => loop(opHash256(p),calcOpCount(opCount,OP_HASH256))
case OP_CODESEPARATOR :: t => loop(opCodeSeparator(p),calcOpCount(opCount,OP_CODESEPARATOR))
case OP_HASH160 :: t => loop(CryptoInterpreter.opHash160(p),calcOpCount(opCount,OP_HASH160))
case OP_CHECKSIG :: t => loop(CryptoInterpreter.opCheckSig(p),calcOpCount(opCount,OP_CHECKSIG))
case OP_CHECKSIGVERIFY :: t => loop(CryptoInterpreter.opCheckSigVerify(p),calcOpCount(opCount,OP_CHECKSIGVERIFY))
case OP_SHA1 :: t => loop(CryptoInterpreter.opSha1(p),calcOpCount(opCount,OP_SHA1))
case OP_RIPEMD160 :: t => loop(CryptoInterpreter.opRipeMd160(p),calcOpCount(opCount,OP_RIPEMD160))
case OP_SHA256 :: t => loop(CryptoInterpreter.opSha256(p),calcOpCount(opCount,OP_SHA256))
case OP_HASH256 :: t => loop(CryptoInterpreter.opHash256(p),calcOpCount(opCount,OP_HASH256))
case OP_CODESEPARATOR :: t => loop(CryptoInterpreter.opCodeSeparator(p), calcOpCount(opCount,OP_CODESEPARATOR))
case OP_CHECKMULTISIG :: t =>
opCheckMultiSig(p) match {
CryptoInterpreter.opCheckMultiSig(p) match {
case newProgram : ExecutedScriptProgram =>
//script was marked invalid for other reasons, don't need to update the opcount
loop(newProgram,opCount)
@ -397,7 +395,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
loop(newProgram,newOpCount)
}
case OP_CHECKMULTISIGVERIFY :: t =>
opCheckMultiSigVerify(p) match {
CryptoInterpreter.opCheckMultiSigVerify(p) match {
case newProgram : ExecutedScriptProgram =>
//script was marked invalid for other reasons, don't need to update the opcount
loop(newProgram,opCount)
@ -432,12 +430,14 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
logger.error("Undefined operation found which automatically fails the script: " + reservedOperation)
loop(ScriptProgram(p,ScriptErrorBadOpCode),calcOpCount(opCount,reservedOperation))
//splice operations
case OP_SIZE :: t => loop(opSize(p),calcOpCount(opCount,OP_SIZE))
case OP_SIZE :: t => loop(SpliceInterpreter.opSize(p),calcOpCount(opCount,OP_SIZE))
//locktime operations
case OP_CHECKLOCKTIMEVERIFY :: t =>
//check if CLTV is enforced yet
if (ScriptFlagUtil.checkLockTimeVerifyEnabled(p.flags)) loop(opCheckLockTimeVerify(p),calcOpCount(opCount,OP_CHECKLOCKTIMEVERIFY))
if (ScriptFlagUtil.checkLockTimeVerifyEnabled(p.flags)) {
loop(LockTimeInterpreter.opCheckLockTimeVerify(p),calcOpCount(opCount,OP_CHECKLOCKTIMEVERIFY))
}
//if not, check to see if we should discourage p
else if (ScriptFlagUtil.discourageUpgradableNOPs(p.flags)) {
logger.error("We cannot execute a NOP when the ScriptVerifyDiscourageUpgradableNOPs is set")
@ -447,7 +447,9 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
else loop(ScriptProgram(p, p.script.tail, ScriptProgram.Script),calcOpCount(opCount,OP_CHECKLOCKTIMEVERIFY))
case OP_CHECKSEQUENCEVERIFY :: t =>
//check if CLTV is enforced yet
if (ScriptFlagUtil.checkSequenceVerifyEnabled(p.flags)) loop(opCheckSequenceVerify(p),calcOpCount(opCount,OP_CHECKSEQUENCEVERIFY))
if (ScriptFlagUtil.checkSequenceVerifyEnabled(p.flags)) {
loop(LockTimeInterpreter.opCheckSequenceVerify(p),calcOpCount(opCount,OP_CHECKSEQUENCEVERIFY))
}
//if not, check to see if we should discourage p
else if (ScriptFlagUtil.discourageUpgradableNOPs(p.flags)) {
logger.error("We cannot execute a NOP when the ScriptVerifyDiscourageUpgradableNOPs is set")

View file

@ -13,7 +13,7 @@ import scala.annotation.tailrec
/**
* Created by chris on 2/8/16.
*/
trait LockTimeInterpreter {
sealed abstract class LockTimeInterpreter {
private def logger = BitcoinSLogger.logger
/**

View file

@ -8,7 +8,7 @@ import org.bitcoins.core.util.BitcoinSLogger
/**
* Created by chris on 2/4/16.
*/
trait SpliceInterpreter {
sealed abstract class SpliceInterpreter {
private def logger = BitcoinSLogger.logger
/** Pushes the string length of the top element of the stack (without popping it). */
@ -30,3 +30,5 @@ trait SpliceInterpreter {
}
}
}
object SpliceInterpreter extends SpliceInterpreter

View file

@ -14,7 +14,7 @@ import scala.util.{Failure, Success, Try}
* Stack operations implemented in the script programming language
* https://en.bitcoin.it/wiki/Script#Stack
*/
trait StackInterpreter {
sealed abstract class StackInterpreter {
private def logger = BitcoinSLogger.logger
/** Duplicates the element on top of the stack
@ -286,5 +286,6 @@ trait StackInterpreter {
}
}
}
}
object StackInterpreter extends StackInterpreter

View file

@ -100,7 +100,7 @@ trait BinaryTree[+T] {
}
}
def toSeq : Seq[T] = {
def toSeq: Seq[T] = {
@tailrec
def loop(tree : BinaryTree[T], accum : List[T], remainder : List[BinaryTree[T]]) : List[T] = tree match {
case Leaf(x) => if (remainder.isEmpty) accum ++ List(x) else loop(remainder.head,accum ++ List(x),remainder.tail)
@ -108,10 +108,10 @@ trait BinaryTree[+T] {
case Node(v,l,r) =>
loop(l,accum ++ List(v), r :: remainder)
}
loop(this,List(),List())
loop(this,Nil,Nil)
}
def toList : List[T] = toSeq.toList
def toList: List[T] = toSeq.toList
}
case class Node[T](v: T, l: BinaryTree[T], r: BinaryTree[T]) extends BinaryTree[T]

View file

@ -11,13 +11,15 @@ import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/25/16.
*/
class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with ArithmeticInterpreter {
class ArithmeticInterpreterTest extends FlatSpec with MustMatchers {
val AI = ArithmeticInterpreter
"ArithmeticInterpreter" must "perform an OP_ADD correctly" in {
val stack = List(ScriptNumber.one, ScriptNumber(2))
val script = List(OP_ADD)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opAdd(program)
val newProgram = AI.opAdd(program)
newProgram.stack.head must be (ScriptNumber(3))
newProgram.script.isEmpty must be (true)
}
@ -27,7 +29,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_1ADD)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op1Add(program)
val newProgram = AI.op1Add(program)
newProgram.stack.head must be (ScriptNumber.one)
newProgram.script.isEmpty must be (true)
@ -38,7 +40,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List()
val script = List(OP_1ADD)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(op1Add(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(AI.op1Add(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -47,7 +49,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_1SUB)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op1Sub(program)
val newProgram = AI.op1Sub(program)
newProgram.stack.head must be (ScriptNumber(-1))
newProgram.script.isEmpty must be (true)
@ -58,7 +60,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List()
val script = List(OP_1SUB)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(op1Sub(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(AI.op1Sub(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -66,7 +68,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.one,ScriptNumber.zero)
val script = List(OP_SUB)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSub(program)
val newProgram = AI.opSub(program)
newProgram.stack.head must be (ScriptNumber(-1))
newProgram.script.isEmpty must be (true)
@ -76,7 +78,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List()
val script = List(OP_SUB)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opSub(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(AI.opSub(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -84,7 +86,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber(-1))
val script = List(OP_ABS)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opAbs(program)
val newProgram = AI.opAbs(program)
newProgram.stack.head must be (ScriptNumber.one)
newProgram.script.isEmpty must be (true)
@ -94,7 +96,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_ABS)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opAbs(program)
val newProgram = AI.opAbs(program)
newProgram.stack.head must be (ScriptNumber.zero)
newProgram.script.isEmpty must be (true)
@ -103,7 +105,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List()
val script = List(OP_ABS)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opAbs(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(AI.opAbs(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -111,7 +113,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_NEGATE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNegate(program)
val newProgram = AI.opNegate(program)
newProgram.stack.head must be (ScriptNumber.zero)
newProgram.script.isEmpty must be (true)
@ -121,7 +123,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.one)
val script = List(OP_NEGATE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNegate(program)
val newProgram = AI.opNegate(program)
newProgram.stack.head must be (ScriptNumber(-1))
newProgram.script.isEmpty must be (true)
@ -131,7 +133,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber(-1))
val script = List(OP_NEGATE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNegate(program)
val newProgram = AI.opNegate(program)
newProgram.stack.head must be (ScriptNumber.one)
newProgram.script.isEmpty must be (true)
@ -141,7 +143,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List()
val script = List(OP_NEGATE)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opNegate(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(AI.opNegate(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -149,7 +151,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_NOT)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNot(program)
val newProgram = AI.opNot(program)
newProgram.stackTopIsTrue must be (true)
newProgram.stack.head must be (OP_TRUE)
@ -160,7 +162,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.one)
val script = List(OP_NOT)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNot(program)
val newProgram = AI.opNot(program)
newProgram.stackTopIsFalse must be (true)
newProgram.stack.head must be (OP_FALSE)
@ -171,7 +173,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_0NOTEQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op0NotEqual(program)
val newProgram = AI.op0NotEqual(program)
newProgram.stack.head must be (OP_FALSE)
newProgram.script.isEmpty must be (true)
@ -181,7 +183,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.one)
val script = List(OP_0NOTEQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op0NotEqual(program)
val newProgram = AI.op0NotEqual(program)
newProgram.stack.head must be (OP_TRUE)
newProgram.script.isEmpty must be (true)
@ -191,7 +193,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.zero)
val script = List(OP_BOOLAND)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opBoolAnd(program)
val newProgram = AI.opBoolAnd(program)
newProgram.stackTopIsFalse must be (true)
newProgram.stack.head must be (OP_FALSE)
@ -200,7 +202,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack1 = List(OP_0, OP_0)
val script1 = List(OP_BOOLAND)
val program1 = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram1 = opBoolAnd(program)
val newProgram1 = AI.opBoolAnd(program)
newProgram.stackTopIsFalse must be (true)
newProgram1.stack.head must be (OP_FALSE)
@ -211,7 +213,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, OP_1)
val script = List(OP_BOOLAND)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opBoolAnd(program)
val newProgram = AI.opBoolAnd(program)
newProgram.stackTopIsTrue must be (false)
newProgram.stack.head must be (OP_FALSE)
@ -223,7 +225,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.one, ScriptNumber.one)
val script = List(OP_BOOLOR)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opBoolOr(program)
val newProgram = AI.opBoolOr(program)
newProgram.stack.head must be (OP_TRUE)
newProgram.script.isEmpty must be (true)
@ -233,7 +235,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.zero)
val script = List(OP_BOOLOR)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opBoolOr(program)
val newProgram = AI.opBoolOr(program)
newProgram.stack.head must be (OP_FALSE)
newProgram.script.isEmpty must be (true)
@ -243,7 +245,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_BOOLOR)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opBoolOr(program)
val newProgram = AI.opBoolOr(program)
newProgram.stack.head must be (OP_TRUE)
newProgram.script.isEmpty must be (true)
@ -253,7 +255,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.zero)
val script = List(OP_NUMEQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNumEqual(program)
val newProgram = AI.opNumEqual(program)
newProgram.stackTopIsTrue must be (true)
newProgram.stack.head must be (OP_TRUE)
@ -264,7 +266,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.zero)
val script = List(OP_NUMEQUALVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opNumEqualVerify(program)
val newProgram = AI.opNumEqualVerify(program)
newProgram.isInstanceOf[ExecutionInProgressScriptProgram] must be (true)
newProgram.stack.isEmpty must be (true)
}
@ -273,7 +275,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_NUMEQUALVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opNumEqualVerify(program)
val newProgram = AI.opNumEqualVerify(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorVerify))
}
@ -282,7 +284,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_NUMEQUALVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opNumEqualVerify(program)
val newProgram = AI.opNumEqualVerify(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -292,7 +294,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.zero)
val script = List(OP_NUMNOTEQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNumNotEqual(program)
val newProgram = AI.opNumNotEqual(program)
newProgram.stack.head must be (OP_FALSE)
newProgram.script.isEmpty must be (true)
@ -304,7 +306,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_NUMNOTEQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNumNotEqual(program)
val newProgram = AI.opNumNotEqual(program)
newProgram.stack.head must be (OP_TRUE)
newProgram.script.isEmpty must be (true)
@ -314,7 +316,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_LESSTHAN)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opLessThan(program)
val newProgram = AI.opLessThan(program)
newProgram.stack.head must be (OP_FALSE)
newProgram.script.isEmpty must be (true)
@ -323,7 +325,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val script1 = List(OP_LESSTHAN)
ScriptProgram(TestUtil.testProgram, stack,script)
val program1 = ScriptProgram(TestUtil.testProgram,stack1,script1)
val newProgram1 = opLessThan(program1)
val newProgram1 = AI.opLessThan(program1)
newProgram1.stack.head must be (OP_FALSE)
newProgram1.script.isEmpty must be (true)
@ -331,7 +333,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack2 = List(ScriptNumber.one, ScriptNumber.zero)
val script2 = List(OP_LESSTHAN)
val program2 = ScriptProgram(TestUtil.testProgram, stack2,script2)
val newProgram2 = opLessThan(program2)
val newProgram2 = AI.opLessThan(program2)
newProgram2.stack.head must be (OP_TRUE)
newProgram2.script.isEmpty must be (true)
@ -341,7 +343,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_LESSTHANOREQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opLessThanOrEqual(program)
val newProgram = AI.opLessThanOrEqual(program)
newProgram.stack.head must be (OP_FALSE)
newProgram.script.isEmpty must be (true)
@ -350,7 +352,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val script1 = List(OP_LESSTHANOREQUAL)
ScriptProgram(TestUtil.testProgram, stack,script)
val program1 = ScriptProgram(TestUtil.testProgram,stack1,script1)
val newProgram1 = opLessThanOrEqual(program1)
val newProgram1 = AI.opLessThanOrEqual(program1)
newProgram1.stack.head must be (OP_TRUE)
newProgram1.script.isEmpty must be (true)
@ -358,7 +360,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack2 = List(ScriptNumber.one, ScriptNumber.zero)
val script2 = List(OP_LESSTHANOREQUAL)
val program2 = ScriptProgram(TestUtil.testProgram, stack2,script2)
val newProgram2 = opLessThanOrEqual(program2)
val newProgram2 = AI.opLessThanOrEqual(program2)
newProgram2.stack.head must be (OP_TRUE)
newProgram2.script.isEmpty must be (true)
@ -368,7 +370,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_GREATERTHAN)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opGreaterThan(program)
val newProgram = AI.opGreaterThan(program)
newProgram.stack.head must be (OP_TRUE)
newProgram.script.isEmpty must be (true)
@ -376,7 +378,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack1 = List(ScriptNumber.zero, ScriptNumber.zero)
val script1 = List(OP_GREATERTHAN)
val program1 = ScriptProgram(TestUtil.testProgram,stack1,script1)
val newProgram1 = opGreaterThan(program1)
val newProgram1 = AI.opGreaterThan(program1)
newProgram1.stack.head must be (OP_FALSE)
newProgram1.script.isEmpty must be (true)
@ -384,7 +386,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack2 = List(ScriptNumber.one, ScriptNumber.zero)
val script2 = List(OP_GREATERTHAN)
val program2 = ScriptProgram(TestUtil.testProgram, stack2,script2)
val newProgram2 = opGreaterThan(program2)
val newProgram2 = AI.opGreaterThan(program2)
newProgram2.stack.head must be (OP_FALSE)
newProgram2.script.isEmpty must be (true)
@ -394,7 +396,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_GREATERTHANOREQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opGreaterThanOrEqual(program)
val newProgram = AI.opGreaterThanOrEqual(program)
newProgram.stack.head must be (OP_TRUE)
newProgram.script.isEmpty must be (true)
@ -402,7 +404,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack1 = List(ScriptNumber.zero, ScriptNumber.zero)
val script1 = List(OP_GREATERTHANOREQUAL)
val program1 = ScriptProgram(TestUtil.testProgram,stack1,script1)
val newProgram1 = opGreaterThanOrEqual(program1)
val newProgram1 = AI.opGreaterThanOrEqual(program1)
newProgram1.stack.head must be (OP_TRUE)
newProgram1.script.isEmpty must be (true)
@ -410,7 +412,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack2 = List(ScriptNumber.one, ScriptNumber.zero)
val script2 = List(OP_GREATERTHANOREQUAL)
val program2 = ScriptProgram(TestUtil.testProgram, stack2,script2)
val newProgram2 = opGreaterThanOrEqual(program2)
val newProgram2 = AI.opGreaterThanOrEqual(program2)
newProgram2.stack.head must be (OP_FALSE)
newProgram2.script.isEmpty must be (true)
@ -421,7 +423,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_MIN)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opMin(program)
val newProgram = AI.opMin(program)
newProgram.stack must be (List(ScriptNumber.zero))
}
@ -430,7 +432,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_MIN)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opMin(program)
val newProgram = AI.opMin(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
@ -440,7 +442,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero, ScriptNumber.one)
val script = List(OP_MAX)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opMax(program)
val newProgram = AI.opMax(program)
newProgram.stack must be (List(ScriptNumber.one))
}
@ -449,7 +451,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber.zero)
val script = List(OP_MAX)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opMax(program)
val newProgram = AI.opMax(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
@ -459,7 +461,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber(2), ScriptNumber.one, ScriptNumber.zero)
val script = List(OP_WITHIN)
val program = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script), Seq[ScriptFlag]())
val newProgram = opWithin(program)
val newProgram = AI.opWithin(program)
newProgram.stack must be (List(OP_FALSE))
newProgram.script.isEmpty must be (true)
@ -467,7 +469,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack1 = List(ScriptNumber.one, OP_0, ScriptNumber.zero)
val script1 = List(OP_WITHIN)
val program1 = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress, stack1,script1), Seq[ScriptFlag]())
val newProgram1 = opWithin(program1)
val newProgram1 = AI.opWithin(program1)
newProgram1.stack must be (List(OP_TRUE))
newProgram1.script.isEmpty must be (true)
}
@ -476,7 +478,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber("00"), ScriptNumber.one, ScriptNumber.one)
val script = List(OP_WITHIN)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opWithin(program)
val newProgram = AI.opWithin(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorUnknownError))
}
@ -485,7 +487,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber("0000000000000000"), ScriptNumber.one, ScriptNumber.one)
val script = List(OP_WITHIN)
val program = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script), Seq[ScriptFlag]())
val newProgram = opWithin(program)
val newProgram = AI.opWithin(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorUnknownError))
}
@ -494,7 +496,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(ScriptNumber("0000000000000000"), ScriptNumber.one)
val script = List(OP_WITHIN)
val program = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script), Seq[ScriptFlag]())
val newProgram = opWithin(program)
val newProgram = AI.opWithin(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -506,7 +508,7 @@ class ArithmeticInterpreterTest extends FlatSpec with MustMatchers with Arithmet
val stack = List(scriptConstant1, scriptConstant2)
val script = List(OP_ADD)
val program = ScriptProgram(TestUtil.testProgram, stack, script)
val newProgram = opAdd(program)
val newProgram = AI.opAdd(program)
newProgram.stack must be (List(ScriptNumber.zero))
newProgram.script.isEmpty must be (true)
}

View file

@ -10,14 +10,14 @@ import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/6/16.
*/
class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInterpreter {
class BitwiseInterpreterTest extends FlatSpec with MustMatchers {
private val pubKeyHash = ScriptConstant("5238C71458E464D9FF90299ABCA4A1D7B9CB76AB".toLowerCase)
val BI = BitwiseInterpreter
"BitwiseInterpreter" must "evaluate OP_EQUAL" in {
val stack = List(pubKeyHash, pubKeyHash)
val script = List(OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opEqual(program)
val newProgram = BI.opEqual(program)
newProgram.stack.head must be (OP_TRUE)
}
@ -26,20 +26,20 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
val stack = List(OP_1, OP_TRUE)
val script = List(OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack, script)
val newProgram = opEqual(program)
val newProgram = BI.opEqual(program)
newProgram.stack.head must be (OP_TRUE)
}
it must "throw an exception for OP_EQUAL when we don't have enough items on the stack" in {
intercept[IllegalArgumentException] {
opEqual(ScriptProgram(TestUtil.testProgram, List(),List()))
BI.opEqual(ScriptProgram(TestUtil.testProgram, List(),List()))
}
}
it must "throw an exception for OP_EQUAL when we don't have enough items on the script stack" in {
intercept[IllegalArgumentException] {
opEqual(ScriptProgram(TestUtil.testProgram, List(),List()))
BI.opEqual(ScriptProgram(TestUtil.testProgram, List(),List()))
}
}
@ -47,7 +47,7 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
val stack = List(pubKeyHash, pubKeyHash)
val script = List(OP_EQUALVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val result = opEqualVerify(program)
val result = BI.opEqualVerify(program)
//if verification fails it will transform the script to a ExecutedProgram with an error set
result.isInstanceOf[ExecutedScriptProgram] must be (false)
}
@ -57,7 +57,7 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
val stack = List(pubKeyHash,uniquePubKey)
val script = List(OP_EQUALVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val result = opEqualVerify(program)
val result = BI.opEqualVerify(program)
result.stackTopIsTrue must be (false)
}
@ -66,19 +66,19 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
val stack = List(ScriptNumber(2), ScriptConstant("02"))
val script = List(OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
opEqual(program).stack.head must be (OP_TRUE)
BI.opEqual(program).stack.head must be (OP_TRUE)
val stack1 = List( ScriptConstant("02"),ScriptNumber(2))
val script1 = List(OP_EQUAL)
val program1 = ScriptProgram(TestUtil.testProgram, stack1,script1)
opEqual(program1).stack.head must be (OP_TRUE)
BI.opEqual(program1).stack.head must be (OP_TRUE)
}
it must "evaluate an OP_0 and ScriptNumberImpl(0) to equal" in {
val stack = List(OP_0, ScriptNumber.zero)
val script = List(OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
opEqual(program).stack.head must be (OP_TRUE)
BI.opEqual(program).stack.head must be (OP_TRUE)
}
@ -86,7 +86,7 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
val stack = List(OP_0)
val script = List(OP_EQUALVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack, script)
val newProgram = opEqualVerify(program)
val newProgram = BI.opEqualVerify(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}

View file

@ -11,8 +11,8 @@ import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/24/16.
*/
class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantInterpreter {
class ConstantInterpreterTest extends FlatSpec with MustMatchers {
val CI = ConstantInterpreter
"ConstantInterpreter" must "interpret OP_PUSHDATA1 correctly" in {
val byteConstantSize = 76
val byteConstant = for { x <- 0 until byteConstantSize} yield 0x0.toByte
@ -20,7 +20,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = List()
val script = List(OP_PUSHDATA1,ScriptNumber(byteConstantSize), scriptConstant,OP_7,OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opPushData1(program)
val newProgram = CI.opPushData1(program)
newProgram.stack must be (List(scriptConstant))
newProgram.script must be (List(OP_7,OP_EQUAL))
}
@ -32,7 +32,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = List()
val script = List(OP_PUSHDATA2, ScriptNumber(256), scriptConstant, OP_8, OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opPushData2(program)
val newProgram = CI.opPushData2(program)
newProgram.stack must be (List(scriptConstant))
newProgram.script must be (List(OP_8,OP_EQUAL))
}
@ -44,7 +44,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = List()
val script = List(OP_PUSHDATA4, ScriptNumber(byteConstantSize), scriptConstant, OP_9, OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opPushData4(program)
val newProgram = CI.opPushData4(program)
newProgram.stack must be (List(scriptConstant))
newProgram.script must be (List(OP_9, OP_EQUAL))
}
@ -54,7 +54,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = List()
val script = List(BytesToPushOntoStack(2), ScriptNumber.one, OP_0)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = pushScriptNumberBytesToStack(program)
val newProgram = CI.pushScriptNumberBytesToStack(program)
newProgram.script.isEmpty must be (true)
newProgram.stack must be (List(ScriptConstant("0100")))
}
@ -63,20 +63,20 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = List()
val script = List(OP_PUSHDATA1,BytesToPushOntoStack(0))
val program = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack,script),Seq[ScriptFlag]())
val newProgram = opPushData1(program)
val newProgram = CI.opPushData1(program)
newProgram.stackTopIsFalse must be (true)
newProgram.stack must be (List(ScriptNumber.zero))
val stack1 = List()
val script1 = List(OP_PUSHDATA2,BytesToPushOntoStack(0))
val program1 = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack1,script1),Seq[ScriptFlag]())
val newProgram1 = opPushData2(program1)
val newProgram1 = CI.opPushData2(program1)
newProgram1.stack must be (List(ScriptNumber.zero))
val stack2 = List()
val script2 = List(OP_PUSHDATA4,BytesToPushOntoStack(0))
val program2 = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack2,script2),Seq[ScriptFlag]())
val newProgram2 = opPushData4(program2)
val newProgram2 = CI.opPushData4(program2)
newProgram2.stack must be (List(ScriptNumber.zero))
}
@ -85,7 +85,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val script = List(OP_PUSHDATA1,BytesToPushOntoStack(1))
val program = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script),Seq[ScriptFlag]())
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opPushData1(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(CI.opPushData1(program))
newProgram.error must be (Some(ScriptErrorBadOpCode))
}
@ -104,15 +104,15 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
//purposely call incorrect functions to mismatch opCodes
intercept[IllegalArgumentException] {
opPushData1(program2)
CI.opPushData1(program2)
}
intercept[IllegalArgumentException] {
opPushData2(program4)
CI.opPushData2(program4)
}
intercept[IllegalArgumentException] {
opPushData4(program1)
CI.opPushData4(program1)
}
}
@ -123,7 +123,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val program = ScriptProgram(TestUtil.testProgram, stack,script)
intercept[IllegalArgumentException] {
pushScriptNumberBytesToStack(program)
CI.pushScriptNumberBytesToStack(program)
}
}
@ -131,7 +131,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = List()
val script = List(OP_PUSHDATA4,ScriptNumber.zero)
val program = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack,script),Seq[ScriptFlag](ScriptVerifyMinimalData))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opPushData4(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(CI.opPushData4(program))
newProgram.error must be (Some(ScriptErrorMinimalData))
}
@ -141,7 +141,7 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val stack = Nil
val script = List(OP_PUSHDATA1, OP_3, constant)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opPushData1(program)
val newProgram = CI.opPushData1(program)
newProgram.stack must be (Seq(constant))
}

View file

@ -5,21 +5,25 @@ import org.bitcoins.core.script.ScriptProgram
import org.bitcoins.core.script.arithmetic.OP_ADD
import org.bitcoins.core.script.bitwise.OP_EQUAL
import org.bitcoins.core.script.constant._
import org.bitcoins.core.script.crypto.OP_CHECKSIG
import org.bitcoins.core.script.locktime.OP_CHECKSEQUENCEVERIFY
import org.bitcoins.core.script.reserved.{OP_RESERVED, OP_VER}
import org.bitcoins.core.script.result.{ScriptErrorInvalidStackOperation, ScriptErrorOpReturn}
import org.bitcoins.core.script.stack.OP_DROP
import org.bitcoins.core.util._
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/6/16.
*/
class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with ControlOperationsInterpreter {
class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers {
private def logger = BitcoinSLogger.logger
val COI = ControlOperationsInterpreter
"ControlOperationsInterpreter" must "have OP_VERIFY evaluate to true with '1' on the stack" in {
val stack = List(OP_TRUE)
val script = List(OP_VERIFY)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val result = opVerify(program)
val result = COI.opVerify(program)
result.stack.isEmpty must be (true)
result.script.isEmpty must be (true)
}
@ -30,14 +34,14 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
val stack = ScriptParser.fromString("0x09 0x00000000 0x00000000 0x10")
val script = List(OP_VERIFY)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val result = opVerify(program)
val result = COI.opVerify(program)
}
it must "have OP_VERIFY evaluate to false with '0' on the stack" in {
val stack = List(OP_FALSE)
val script = List(OP_VERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val result = opVerify(program)
val result = COI.opVerify(program)
result.stackTopIsFalse must be (true)
}
@ -46,7 +50,7 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
val stack = List()
val script = List(OP_VERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val result = ScriptProgramTestUtil.toExecutedScriptProgram(opVerify(program))
val result = ScriptProgramTestUtil.toExecutedScriptProgram(COI.opVerify(program))
result.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -56,102 +60,127 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
val stack = List(ScriptConstant("1"))
val script = List()
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val result = opVerify(program)
val result = COI.opVerify(program)
}
}
it must "find the first index of our OP_ENDIF in a list of script tokens" in {
val l = List(OP_ENDIF)
findFirstOpEndIf(l) must be (Some(0))
findFirstOpEndIf(List(OP_IF,OP_ELSE,OP_ENDIF,OP_ENDIF)) must be (Some(2))
findFirstOpEndIf(List(OP_0,OP_1,OP_2)) must be (None)
findFirstOpEndIf(List(OP_IF, OP_RESERVED, OP_ENDIF, OP_1)) must be (Some(2))
COI.findFirstOpEndIf(l) must be (Some(0))
COI.findFirstOpEndIf(List(OP_IF,OP_ELSE,OP_ENDIF,OP_ENDIF)) must be (Some(2))
COI.findFirstOpEndIf(List(OP_0,OP_1,OP_2)) must be (None)
COI.findFirstOpEndIf(List(OP_IF, OP_RESERVED, OP_ENDIF, OP_1)) must be (Some(2))
}
it must "find the last index of our OP_ENDIF in a list of script tokens" in {
val l = List(OP_ENDIF)
findLastOpEndIf(l) must be (Some(0))
findLastOpEndIf(List(OP_IF,OP_ELSE,OP_ENDIF,OP_ENDIF)) must be (Some(3))
findLastOpEndIf(List(OP_0,OP_1,OP_2)) must be (None)
findLastOpEndIf(List(OP_IF, OP_RESERVED, OP_ENDIF, OP_ENDIF, OP_1)) must be (Some(3))
COI.findLastOpEndIf(l) must be (Some(0))
COI.findLastOpEndIf(List(OP_IF,OP_ELSE,OP_ENDIF,OP_ENDIF)) must be (Some(3))
COI.findLastOpEndIf(List(OP_0,OP_1,OP_2)) must be (None)
COI.findLastOpEndIf(List(OP_IF, OP_RESERVED, OP_ENDIF, OP_ENDIF, OP_1)) must be (Some(3))
}
it must "find the first indexes of OP_ELSE in a list of script tokens" in {
findFirstOpElse(List(OP_ELSE)) must be (Some(0))
findFirstOpElse(List(OP_IF,OP_ELSE,OP_ENDIF,OP_ELSE)) must be (Some(1))
findFirstOpElse(List(OP_0,OP_1,OP_2)) must be (None)
COI.findFirstOpElse(List(OP_ELSE)) must be (Some(0))
COI.findFirstOpElse(List(OP_IF,OP_ELSE,OP_ENDIF,OP_ELSE)) must be (Some(1))
COI.findFirstOpElse(List(OP_0,OP_1,OP_2)) must be (None)
}
it must "find the first indexes of OP_ELSE and OP_ENDIF in a list of script tokens" in {
findFirstIndexesOpElseOpEndIf(List(OP_ELSE,OP_ENDIF)) must be (Some(0),Some(1))
findFirstIndexesOpElseOpEndIf(List(OP_IF, OP_ELSE,OP_ENDIF, OP_IF,OP_ELSE,OP_ENDIF)) must be (Some(1),Some(2))
findFirstIndexesOpElseOpEndIf(List(OP_IF,OP_IF)) must be (None,None)
COI.findFirstIndexesOpElseOpEndIf(List(OP_ELSE,OP_ENDIF)) must be (Some(0),Some(1))
COI.findFirstIndexesOpElseOpEndIf(List(OP_IF, OP_ELSE,OP_ENDIF, OP_IF,OP_ELSE,OP_ENDIF)) must be (Some(1),Some(2))
COI.findFirstIndexesOpElseOpEndIf(List(OP_IF,OP_IF)) must be (None,None)
}
it must "remove the first OP_IF expression in a script" in {
removeFirstOpIf(List(OP_IF,OP_ELSE,OP_ENDIF)) must be (List(OP_ELSE,OP_ENDIF))
removeFirstOpIf(List(OP_ELSE,OP_ENDIF)) must be (List(OP_ELSE,OP_ENDIF))
removeFirstOpIf(List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)) must be (List(OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF))
removeFirstOpIf(List(OP_IF,OP_ENDIF)) must be (List(OP_ENDIF))
COI.removeFirstOpIf(List(OP_IF,OP_ELSE,OP_ENDIF)) must be (List(OP_ELSE,OP_ENDIF))
COI.removeFirstOpIf(List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)) must be (List(OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF))
COI.removeFirstOpIf(List(OP_IF,OP_ENDIF)) must be (List(OP_ENDIF))
}
it must "remove the first OP_ELSE expression in a script" in {
removeFirstOpElse(List(OP_IF,OP_ELSE,OP_ENDIF)) must be (List(OP_IF,OP_ENDIF))
removeFirstOpElse(List(OP_IF,OP_ENDIF)) must be (List(OP_IF,OP_ENDIF))
removeFirstOpElse(List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)) must be (List(OP_IF, OP_1, OP_ELSE, OP_3, OP_ENDIF))
COI.removeFirstOpElse(List(OP_IF,OP_ELSE,OP_ENDIF)) must be (List(OP_IF,OP_ENDIF))
COI.removeFirstOpElse(List(OP_IF,OP_ENDIF)) must be (List(OP_IF,OP_ENDIF))
COI.removeFirstOpElse(List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)) must be (List(OP_IF, OP_1, OP_ELSE, OP_3, OP_ENDIF))
}
it must "remove the first OP_ELSE in a binary tree" in {
val script1 = List(OP_IF,OP_ELSE,OP_ENDIF)
val bTree1 = parseBinaryTree(script1)
removeFirstOpElse(bTree1).toSeq must be (List(OP_IF,OP_ENDIF))
val bTree1 = COI.parseBinaryTree(script1)
COI.removeFirstOpElse(bTree1).toSeq must be (List(OP_IF,OP_ENDIF))
val script2 = List(OP_IF,OP_ENDIF)
val bTree2 = parseBinaryTree(script2)
removeFirstOpElse(bTree2).toSeq must be (script2)
val bTree2 = COI.parseBinaryTree(script2)
bTree2 must be (Node(OP_IF, Empty, Leaf(OP_ENDIF)))
COI.removeFirstOpElse(bTree2).toSeq must be (script2)
val script3 = List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)
val bTree3 = parseBinaryTree(script3)
removeFirstOpElse(bTree3).toSeq must be (List(OP_IF, OP_1, OP_ELSE, OP_3, OP_ENDIF))
val bTree3 = COI.parseBinaryTree(script3)
COI.removeFirstOpElse(bTree3).toSeq must be (List(OP_IF, OP_1, OP_ELSE, OP_3, OP_ENDIF))
}
it must "find a matching OP_ENDIF for an OP_IF" in {
//https://gist.github.com/Christewart/381dc1dbbb07e62501c3
val script = List(OP_IF, OP_1, OP_IF, OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ELSE, OP_1, OP_IF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF, OP_ADD, OP_2, OP_EQUAL)
findMatchingOpEndIf(script) must be (20)
COI.findMatchingOpEndIf(script) must be (20)
}
it must "parse a script as a binary tree then convert it back to the original list" in {
val script0 = List(OP_IF,OP_ENDIF)
parseBinaryTree(script0).toSeq must be (script0)
val bTree = COI.parseBinaryTree(script0)
bTree.right.get must be (Leaf(OP_ENDIF))
bTree.toSeq must be (script0)
val script1 = List(OP_IF,OP_0,OP_ELSE,OP_1,OP_ENDIF)
val bTree1 = parseBinaryTree(script1)
val bTree1 = COI.parseBinaryTree(script1)
bTree1.toSeq must be (script1)
val script2 = List(OP_IF,OP_ELSE, OP_ELSE,OP_ENDIF)
parseBinaryTree(script2).toSeq must be (script2)
COI.parseBinaryTree(script2).toSeq must be (script2)
val script3 = List(OP_IF, OP_1, OP_ELSE, OP_0, OP_ENDIF)
val bTree3 = parseBinaryTree(script3)
val bTree3 = COI.parseBinaryTree(script3)
bTree3.toSeq must be (script3)
val script4 = List(OP_IF, OP_IF, OP_0, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_IF, OP_2, OP_ELSE, OP_3, OP_ENDIF, OP_ENDIF)
val bTree4 = parseBinaryTree(script4)
val script5 = List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)
COI.parseBinaryTree(script5).toSeq must be (script5)
val script6 = List(OP_IF, OP_IF, OP_1, OP_ENDIF, OP_ELSE, OP_2, OP_ENDIF)
val tree6 = COI.parseBinaryTree(script6)
tree6.left.get must be (Node(OP_IF, Leaf(OP_1), Leaf(OP_ENDIF)))
tree6.right.get must be (Node(OP_ELSE,Leaf(OP_2), Leaf(OP_ENDIF)))
COI.parseBinaryTree(script6).toSeq must be (script6)
val script7 = List(OP_IF,OP_1,OP_ELSE, OP_IF, OP_2, OP_ENDIF, OP_ENDIF)
val tree7 = COI.parseBinaryTree(script7)
val expectedTree7 = Node(OP_IF, Leaf(OP_1), Node(OP_ELSE, Node(OP_IF, Leaf(OP_2), Leaf(OP_ENDIF)), Leaf(OP_ENDIF)))
tree7 must be (expectedTree7)
tree7.left must be (expectedTree7.left)
tree7.right must be (expectedTree7.right)
val subTree1 = Node(OP_IF,Leaf(OP_0),Node(OP_ELSE,Leaf(OP_1),Leaf(OP_ENDIF)))
val subTree2 = Node(OP_ELSE,Node(OP_IF, Leaf(OP_2),Node(OP_ELSE,Leaf(OP_3), Leaf(OP_ENDIF))),Leaf(OP_ENDIF))
val expected: BinaryTree[ScriptToken] = Node(OP_IF,subTree1,subTree2)
val script4 = List(OP_IF, OP_IF, OP_0, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_IF, OP_2, OP_ELSE, OP_3, OP_ENDIF, OP_ENDIF)
val bTree4 = COI.parseBinaryTree(script4)
bTree4.left.get must be (subTree1)
bTree4.right.get must be (subTree2)
bTree4 must be (expected)
logger.debug("bTree4: " + bTree4)
bTree4.toSeq must be (script4)
val script5 = List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)
parseBinaryTree(script5).toSeq must be (script5)
}
val script8 = List(OP_IF, OP_0, OP_ENDIF, OP_2)
val tree8 = COI.parseBinaryTree(script8)
tree8.toSeq must be (script8)
}
it must "parse a script into a binary tree and have the OP_IF expression on the left branch and the OP_ELSE expression on the right branch"in {
val script = List(OP_IF,OP_0,OP_ELSE,OP_1,OP_ENDIF)
val bTree = parseBinaryTree(script)
val bTree = COI.parseBinaryTree(script)
bTree.value.get must be (OP_IF)
bTree.left.isDefined must be (true)
@ -164,12 +193,12 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
bTree.right.get.left.get.value must be (Some(OP_1))
bTree.right.get.right.isDefined must be (true)
bTree.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.right.get.value must be (Some(OP_ENDIF))
}
it must "parse nested OP_ELSE statements into the same branch" in {
val script = List(OP_IF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)
val bTree = parseBinaryTree(script)
val bTree = COI.parseBinaryTree(script)
bTree.value.get must be (OP_IF)
bTree.left.isDefined must be (true)
@ -188,7 +217,7 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
bTree.right.get.right.get.left.get.value must be (Some(OP_3))
bTree.right.get.right.get.right.isDefined must be (true)
bTree.right.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.right.get.right.get.value must be (Some(OP_ENDIF))
bTree.toSeq must be (script)
@ -196,43 +225,91 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
it must "parse a binary tree from a script with nested OP_IFs and OP_ELSES on both branches" in {
val script = List(OP_IF, OP_IF, OP_0, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_IF, OP_2, OP_ELSE, OP_3, OP_ENDIF, OP_ENDIF)
val bTree = parseBinaryTree(script)
val bTree = COI.parseBinaryTree(script)
bTree.value must be (Some(OP_IF))
bTree.left.get.value must be (Some(OP_IF))
bTree.left.get.right.get.value must be (Some(OP_ELSE))
bTree.left.get.right.get.left.get.value must be (Some(OP_1))
bTree.left.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.left.get.right.get.right.get.value must be (Some(OP_ENDIF))
bTree.right.get.value must be (Some(OP_ELSE))
bTree.right.get.left.get.value must be (Some(OP_IF))
bTree.right.get.left.get.left.get.value must be (Some(OP_2))
bTree.right.get.left.get.right.get.value must be (Some(OP_ELSE))
bTree.right.get.left.get.right.get.left.get.value must be (Some(OP_3))
bTree.right.get.left.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.left.get.right.get.right.get.value must be (Some(OP_ENDIF))
}
it must "parse a binary tree from a script where constants are nested inside of OP_IF OP_ELSE branches" in {
//"0" "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL"
val script = List(OP_IF, OP_1,OP_IF,OP_RETURN,OP_ELSE,OP_RETURN,OP_ELSE,OP_RETURN, OP_ENDIF,
OP_ELSE, OP_1, OP_IF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL)
val bTree = parseBinaryTree(script)
val script = List(OP_IF, OP_0, OP_IF, OP_1, OP_ENDIF, OP_ELSE, OP_2, OP_ENDIF)
val bTree = COI.parseBinaryTree(script)
bTree.left.get.value.get must be (OP_0)
bTree.left.get.left.get.value.get must be (OP_IF)
bTree.toSeq must be (script)
bTree.right.get.right.get.left.get.left.get.left.get.value must be (Some(OP_ADD))
bTree.right.get.right.get.left.get.left.get.left.get.left.get.value must be (Some(OP_2))
bTree.right.get.right.get.left.get.left.get.left.get.left.get.left.get.value must be (Some(OP_EQUAL))
val script1 = List(OP_IF, OP_1, OP_ELSE, OP_2, OP_IF, OP_3, OP_ENDIF, OP_ENDIF)
val bTree1 = COI.parseBinaryTree(script1)
bTree1.toSeq must be (script1)
val script2 = List(OP_IF, OP_0, OP_ELSE, OP_1, OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)
val bTree2 = COI.parseBinaryTree(script2)
bTree2.left.get must be (Leaf(OP_0))
bTree2.right.get must be (Node(OP_ELSE,Leaf(OP_1),Node(OP_ELSE, Leaf(OP_2), Node(OP_ELSE, Leaf(OP_3), Leaf(OP_ENDIF)))))
bTree2.toSeq must be (script2)
val script3 = List(
OP_IF, OP_0,
OP_ELSE,
OP_IF, OP_1, OP_ENDIF,
OP_ELSE, OP_2, OP_ENDIF
)
val bTree3 = COI.parseBinaryTree(script3)
bTree3.toSeq must be (script3)
//"0" "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL"
val script4 = List(
OP_IF, OP_0,
OP_IF, OP_1, OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF,
OP_ELSE, OP_4,
OP_IF, OP_5, OP_ELSE, OP_6, OP_ELSE, OP_7, OP_ENDIF,
OP_ELSE, OP_8, OP_ENDIF,
OP_ADD, OP_9, OP_EQUAL)
val subTree40 = Node(OP_IF, Leaf(OP_1), Node(OP_ELSE, Leaf(OP_2), Node(OP_ELSE, Leaf(OP_3), Leaf(OP_ENDIF))))
val subTree41 = Node(OP_0, subTree40, Empty)
val subTree42 = Node(OP_IF, Leaf(OP_5), Node(OP_ELSE, Leaf(OP_6), Node(OP_ELSE, Leaf(OP_7), Leaf(OP_ENDIF))))
val subTree43 = Node(OP_ADD, Node(OP_9, Leaf(OP_EQUAL),Empty),Empty)
val subTree44 = Node(OP_ELSE, Leaf(OP_8), Node(OP_ENDIF, subTree43, Empty))
val subTree45 = Node(OP_ELSE, Node(OP_4, subTree42, Empty), subTree44)
val expectedBTree4 = Node(OP_IF,subTree41, subTree45)
val bTree4 = COI.parseBinaryTree(script4)
bTree4.left.get must be (subTree41)
bTree4.right.get.left.get must be (subTree45.l)
bTree4.right.get.right.get must be (subTree45.r)
bTree4 must be (expectedBTree4)
bTree4.toSeq must be (script4)
bTree4.right.get.right.get.right.get.left.get.value must be (Some(OP_ADD))
bTree4.right.get.right.get.right.get.left.get.left.get.value must be (Some(OP_9))
bTree4.right.get.right.get.right.get.left.get.left.get.left.get.value must be (Some(OP_EQUAL))
}
it must "parse a binary tree where there are nested OP_ELSES in the outer most OP_ELSE" in {
//https://gist.github.com/Christewart/a5253cf708903323ddc6
val script = List(OP_IF,OP_1, OP_IF,OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN,OP_ENDIF,
OP_ELSE, OP_1,OP_IF,OP_1,OP_ELSE,
OP_RETURN,OP_ELSE,OP_1,OP_ENDIF, OP_ELSE,OP_RETURN,OP_ENDIF,OP_ADD,OP_2,OP_EQUAL)
val script = List(OP_IF, OP_1,
OP_IF,OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN,OP_ENDIF,
OP_ELSE, OP_1,
OP_IF,OP_1,OP_ELSE, OP_RETURN,OP_ELSE,OP_1,OP_ENDIF,
OP_ELSE,OP_RETURN,OP_ENDIF,
OP_ADD,OP_2,OP_EQUAL)
val bTree = parseBinaryTree(script)
val bTree = COI.parseBinaryTree(script)
bTree.toSeq must be (script)
@ -242,64 +319,60 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
bTree.right.get.right.get.value must be (Some(OP_ELSE))
bTree.right.get.right.get.left.get.value must be (Some(OP_RETURN))
bTree.right.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.right.get.left.get.left.get.left.get.value must be (Some(OP_ADD))
bTree.right.get.right.get.right.get.value must be (Some(OP_ENDIF))
bTree.right.get.right.get.right.get.left.get.value must be (Some(OP_ADD))
}
it must "parse a binary tree that has OP_NOTIFs" in {
val script = List(OP_NOTIF, OP_1,OP_ELSE, OP_2, OP_ELSE, OP_3, OP_ENDIF)
val bTree = parseBinaryTree(script)
val bTree = COI.parseBinaryTree(script)
bTree.value.get must be (OP_NOTIF)
bTree.left.isDefined must be (true)
bTree.left.get.value must be (Some(OP_1))
bTree.right.isDefined must be (true)
bTree.right.get.value must be (Some(OP_ELSE))
bTree.right.get.left.isDefined must be (true)
bTree.right.get.left.get.value must be (Some(OP_2))
bTree.right.get.right.isDefined must be (true)
bTree.right.get.right.get.value must be (Some(OP_ELSE))
bTree.right.get.right.get.left.isDefined must be (true)
bTree.right.get.right.get.left.get.value must be (Some(OP_3))
bTree.right.get.right.get.right.isDefined must be (true)
bTree.right.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.right.get.right.get.value must be (Some(OP_ENDIF))
bTree.toSeq must be (script)
}
it must "parse a binary tree with nested OP_NOTIFs" in {
val script = List(OP_NOTIF, OP_NOTIF, OP_0, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_NOTIF, OP_2, OP_ELSE, OP_3, OP_ENDIF, OP_ENDIF)
val bTree = parseBinaryTree(script)
val script = List(OP_NOTIF,
OP_NOTIF, OP_0, OP_ELSE, OP_1, OP_ENDIF,
OP_ELSE,
OP_NOTIF, OP_2, OP_ELSE, OP_3, OP_ENDIF,
OP_ENDIF)
val bTree = COI.parseBinaryTree(script)
bTree.value must be (Some(OP_NOTIF))
bTree.left.get.value must be (Some(OP_NOTIF))
bTree.left.get.right.get.value must be (Some(OP_ELSE))
bTree.left.get.right.get.left.get.value must be (Some(OP_1))
bTree.left.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.left.get.right.get.right.get.value must be (Some(OP_ENDIF))
bTree.right.get.value must be (Some(OP_ELSE))
bTree.right.get.left.get.value must be (Some(OP_NOTIF))
bTree.right.get.left.get.left.get.value must be (Some(OP_2))
bTree.right.get.left.get.right.get.value must be (Some(OP_ELSE))
bTree.right.get.left.get.right.get.left.get.value must be (Some(OP_3))
bTree.right.get.left.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.left.get.right.get.right.get.value must be (Some(OP_ENDIF))
}
it must "evaluate an OP_IF correctly" in {
val stack = List(OP_0)
val script = List(OP_IF, OP_RESERVED, OP_ENDIF, OP_1)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.stack.isEmpty must be (true)
newProgram.script must be (List(OP_ENDIF,OP_1))
}
@ -308,48 +381,48 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
val stack = List(OP_0)
val script = List(OP_IF, OP_VER, OP_ELSE, OP_1, OP_ENDIF)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.script must be (List(OP_ELSE,OP_1,OP_ENDIF))
}
it must "check that every OP_IF has a matching OP_ENDIF" in {
val script0 = List()
checkMatchingOpIfOpNotIfOpEndIf(script0) must be (true)
COI.checkMatchingOpIfOpNotIfOpEndIf(script0) must be (true)
val script1 = List(OP_IF, OP_ENDIF)
checkMatchingOpIfOpNotIfOpEndIf(script1) must be (true)
COI.checkMatchingOpIfOpNotIfOpEndIf(script1) must be (true)
val script2 = List(OP_IF)
checkMatchingOpIfOpNotIfOpEndIf(script2) must be (false)
COI.checkMatchingOpIfOpNotIfOpEndIf(script2) must be (false)
val script3 = List(OP_IF,OP_IF,OP_NOTIF,OP_ELSE,OP_ELSE,OP_ELSE,OP_ENDIF,OP_ENDIF,OP_ENDIF)
checkMatchingOpIfOpNotIfOpEndIf(script3) must be (true)
COI.checkMatchingOpIfOpNotIfOpEndIf(script3) must be (true)
}
it must "evaluate an OP_IF block correctly if the stack top is true" in {
val stack = List(OP_1)
val script = List(OP_IF, OP_1, OP_ELSE, OP_0, OP_ENDIF)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.stack must be (List())
newProgram.script must be (List(OP_1))
newProgram.stack must be (Nil)
newProgram.script must be (List(OP_1,OP_ENDIF))
}
it must "evalute an OP_IF block with and leave the remaining operations outside of the OP_IF" in {
val stack = List(OP_TRUE)
val script = List(OP_IF, OP_ELSE, OP_ENDIF, OP_ELSE)
val script = List(OP_IF, OP_ELSE, OP_ENDIF, OP_1)
val program = ScriptProgram(TestUtil.testProgram, stack, script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.stack.isEmpty must be (true)
newProgram.script must be (List(OP_ENDIF,OP_ELSE))
newProgram.script must be (List(OP_ENDIF,OP_1))
}
it must "evaluate a weird case using multiple OP_ELSEs" in {
val stack = List(ScriptNumber(1))
val stack = List(ScriptNumber.one)
val script = List(OP_IF, OP_ELSE, OP_0, OP_ELSE, OP_1, OP_ENDIF)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.script must be (List(OP_ELSE,OP_1,OP_ENDIF))
@ -364,10 +437,10 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
OP_IF, OP_2, OP_ELSE, OP_3, OP_ENDIF,
OP_ENDIF)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.stack.isEmpty must be (true)
newProgram.script must be (List(OP_IF,OP_0,OP_ELSE,OP_1,OP_ENDIF))
newProgram.script must be (List(OP_IF,OP_0,OP_ELSE,OP_1,OP_ENDIF,OP_ENDIF))
}
it must "evaluate a nested OP_IFs OP_ELSES correctly when the stack top is 0" in {
@ -376,35 +449,33 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
//"0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE
// RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL"
val script = List(OP_IF,OP_1,
OP_IF,OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN,OP_ENDIF,
OP_IF,OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN,OP_ENDIF,
OP_ELSE, OP_1,
OP_IF,OP_1,OP_ELSE, OP_RETURN,OP_ELSE,OP_1,OP_ENDIF,
OP_IF,OP_1,OP_ELSE, OP_RETURN,OP_ELSE,OP_1,OP_ENDIF,
OP_ELSE,OP_RETURN,OP_ENDIF,OP_ADD,OP_2,OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.stack.isEmpty must be (true)
newProgram.script must be (List(OP_ELSE, OP_1,OP_IF,OP_1,OP_ELSE,
OP_RETURN,OP_ELSE,OP_1,OP_ENDIF,OP_ELSE, OP_RETURN,OP_ENDIF,OP_ADD,OP_2,OP_EQUAL))
val newProgram1 = opElse(newProgram)
val newProgram1 = COI.opElse(newProgram)
newProgram1.stack.isEmpty must be (true)
newProgram1.script must be (List(OP_1,OP_IF,OP_1,OP_ELSE,
OP_RETURN,OP_ELSE,OP_1,OP_ENDIF,OP_ENDIF,OP_ADD,OP_2,OP_EQUAL))
}
it must "remove the first OP_ELSE if the stack top is true for an OP_IF" in {
val stack = List(ScriptNumber(1))
val script = List(OP_IF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIf(program)
val newProgram = COI.opIf(program)
newProgram.stack.isEmpty must be (true)
newProgram.script must be (List(OP_1,OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF, OP_ADD, OP_2, OP_EQUAL))
@ -414,90 +485,90 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
val stack = List(ScriptNumber(1), ScriptNumber(1))
val script = List(OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF, OP_ADD, OP_2, OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opEndIf(program)
val newProgram = COI.opEndIf(program)
newProgram.stack must be (stack)
newProgram.script must be (script.tail)
}
it must "parse a partial script correctly" in {
val script = List(OP_IF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL)
val bTree = parseBinaryTree(script)
bTree.value must be (Some(OP_IF))
bTree.left.get.value must be (Some(OP_1))
bTree.right.get.value must be (Some(OP_ELSE))
bTree.right.get.left.get.value must be (Some(OP_RETURN))
bTree.right.get.right.get.value must be (Some(OP_ELSE))
bTree.right.get.right.get.left.get.value must be (Some(OP_1))
bTree.right.get.right.get.left.get.left.get.value must be (Some(OP_ENDIF))
bTree.right.get.right.get.left.get.left.get.left.get.value must be (Some(OP_ELSE))
it must "parse a partially executed script correctly" in {
val script = List(OP_ENDIF, OP_ENDIF, OP_ADD, OP_2, OP_EQUAL)
val bTree = COI.parseBinaryTree(script)
bTree must be (Node(OP_ENDIF, Empty, Node(OP_ENDIF, Node(OP_ADD, Node(OP_2, Leaf(OP_EQUAL),Empty),Empty),Empty)))
bTree.toSeq must be (script)
}
it must "mechanically evaluate this entire script correctly" in {
val stack = List(ScriptNumber(1))
val stack = List(ScriptNumber.one)
val script = List(OP_NOTIF, OP_0,
OP_NOTIF, OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ELSE, OP_0, OP_NOTIF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_NOTIF, OP_RETURN, OP_ELSE, OP_RETURN, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ELSE, OP_0,
OP_NOTIF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF,
OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNotIf(program)
val newProgram = COI.opNotIf(program)
newProgram.stack.isEmpty must be (true)
newProgram.script must be (List(OP_ELSE, OP_0, OP_NOTIF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ELSE, OP_RETURN, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL))
val newProgram1 = opElse(newProgram)
val newProgram1 = COI.opElse(newProgram)
newProgram1.stack.isEmpty must be (true)
newProgram1.script must be (List(OP_0, OP_NOTIF, OP_1, OP_ELSE, OP_RETURN, OP_ELSE, OP_1, OP_ENDIF, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL))
val newProgram2 = opNotIf(ScriptProgram(newProgram1,List(OP_0),newProgram1.script.tail))
logger.info("newProgram1.script.tail: " + newProgram1.script.tail)
val tree = COI.parseBinaryTree(newProgram1.script.tail)
tree.toSeq must be (newProgram1.script.tail)
val newProgram2 = COI.opNotIf(ScriptProgram(newProgram1,List(OP_0),newProgram1.script.tail))
newProgram2.stack.isEmpty must be (true)
newProgram2.script must be (List(OP_1,OP_ELSE, OP_1, OP_ENDIF, OP_ENDIF,
OP_ADD, OP_2, OP_EQUAL))
val newProgram3 = opElse(ScriptProgram(newProgram2,List(OP_1),newProgram2.script.tail))
val newProgram3 = COI.opElse(ScriptProgram(newProgram2,List(OP_1),newProgram2.script.tail))
newProgram3.stack must be (List(OP_1))
newProgram3.script must be (List(OP_1,OP_ENDIF,OP_ENDIF,OP_ADD, OP_2, OP_EQUAL))
val newProgram4 = opEndIf(ScriptProgram(newProgram3, newProgram3.script.head :: newProgram3.stack, newProgram3.script.tail))
val newProgram4 = COI.opEndIf(ScriptProgram(newProgram3, newProgram3.script.head :: newProgram3.stack, newProgram3.script.tail))
newProgram4.stack must be (List(OP_1,OP_1))
newProgram4.script must be (List(OP_ENDIF,OP_ADD, OP_2, OP_EQUAL))
val newProgram5 = opEndIf(newProgram4)
val newProgram5 = COI.opEndIf(newProgram4)
newProgram5.stack must be (List(OP_1,OP_1))
newProgram5.script must be (List(OP_ADD, OP_2, OP_EQUAL))
}
it must "mark a transaction as invalid if it is trying to spend an OP_RETURN output" in {
val stack = Seq()
val script = Seq(OP_RETURN)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opReturn(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(COI.opReturn(program))
newProgram.error must be (Some(ScriptErrorOpReturn))
}
it must "remove nothing when trying to remove an OP_ELSE if the tree is empty" in {
removeFirstOpElse(Empty) must be (Empty)
COI.removeFirstOpElse(Empty) must be (Empty)
}
it must "remove an OP_ELSE from the left branch from a binary tree if an OP_IF DNE on the left branch" in {
val tree = Node(OP_0,Node(OP_ELSE,Empty,Empty),Empty)
val tree = Node(OP_0,Empty,Node(OP_ELSE,Empty,Empty))
removeFirstOpElse(tree) must be (Node(OP_0,Empty,Empty))
COI.removeFirstOpElse(tree) must be (Node(OP_0,Empty,Empty))
}
it must "remove the first OP_IF expression a sequence" in {
val asm = List(OP_IF,OP_0,OP_ELSE,OP_1,OP_ENDIF)
removeFirstOpIf(asm) must be (Seq(OP_ELSE,OP_1,OP_ENDIF))
COI.removeFirstOpIf(asm) must be (Seq(OP_ELSE,OP_1,OP_ENDIF))
}
}

View file

@ -14,15 +14,15 @@ import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/6/16.
*/
class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterpreter {
class CryptoInterpreterTest extends FlatSpec with MustMatchers {
private def logger = BitcoinSLogger.logger
val stack = List(ScriptConstant("02218AD6CDC632E7AE7D04472374311CEBBBBF0AB540D2D08C3400BB844C654231".toLowerCase))
val CI = CryptoInterpreter
"CryptoInterpreter" must "evaluate OP_HASH160 correctly when it is on top of the script stack" in {
val script = List(OP_HASH160)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opHash160(program)
val newProgram = CI.opHash160(program)
newProgram.stack.head must be (ScriptConstant("5238C71458E464D9FF90299ABCA4A1D7B9CB76AB".toLowerCase))
newProgram.script.size must be (0)
@ -32,7 +32,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = List()
val script = List(OP_HASH160)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val executedProgram : ExecutedScriptProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opHash160(program))
val executedProgram : ExecutedScriptProgram = ScriptProgramTestUtil.toExecutedScriptProgram(CI.opHash160(program))
executedProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -41,7 +41,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
intercept[IllegalArgumentException] {
val script = List()
val program = ScriptProgram(TestUtil.testProgram, stack,script)
opHash160(program)
CI.opHash160(program)
}
}
@ -49,7 +49,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = List(ScriptConstant(""))
val script = List(OP_RIPEMD160)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opRipeMd160(program)
val newProgram = CI.opRipeMd160(program)
newProgram.stack must be (List(ScriptConstant("9c1185a5c5e9fc54612808977ee8f548b2258d31")))
newProgram.script.isEmpty must be (true)
}
@ -58,7 +58,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = List(ScriptConstant("ab"))
val script = List(OP_SHA1)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSha1(program)
val newProgram = CI.opSha1(program)
newProgram.stack.head must be (ScriptConstant("fe83f217d464f6fdfa5b2b1f87fe3a1a47371196"))
newProgram.script.isEmpty must be (true)
}
@ -67,7 +67,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = List(ScriptConstant(""))
val script = List(OP_SHA256)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSha256(program)
val newProgram = CI.opSha256(program)
newProgram.stack must be (List(ScriptConstant("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")))
newProgram.script.isEmpty must be (true)
}
@ -76,7 +76,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = List(ScriptConstant(""))
val script = List(OP_HASH256)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opHash256(program)
val newProgram = CI.opHash256(program)
newProgram.stack must be (List(ScriptConstant("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456")))
newProgram.script.isEmpty must be (true)
}
@ -86,7 +86,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = List(OP_CHECKMULTISIG)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val programNoFlags = ScriptProgram(program, ScriptFlagFactory.empty)
val newProgram = opCheckMultiSig(programNoFlags)
val newProgram = CI.opCheckMultiSig(programNoFlags)
newProgram.stack must be (List(OP_TRUE))
newProgram.script.isEmpty must be (true)
}
@ -96,7 +96,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = List(OP_CHECKMULTISIG,OP_16,OP_16,OP_16,OP_16)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val programNoFlags = ScriptProgram(program, ScriptFlagFactory.empty)
val newProgram = opCheckMultiSig(programNoFlags)
val newProgram = CI.opCheckMultiSig(programNoFlags)
newProgram.stack must be (List(OP_TRUE, OP_16,OP_16,OP_16))
newProgram.script must be (List(OP_16,OP_16,OP_16,OP_16))
}
@ -106,8 +106,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = List(OP_CHECKMULTISIGVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val programNoFlags = ScriptProgram(program, ScriptFlagFactory.empty)
val newProgram = opCheckMultiSigVerify(programNoFlags)
println(newProgram.script)
val newProgram = CI.opCheckMultiSigVerify(programNoFlags)
newProgram.script.isEmpty must be (true)
newProgram.stack.isEmpty must be (true)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (false)
@ -118,7 +117,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = List(OP_CHECKMULTISIGVERIFY,OP_16,OP_16,OP_16,OP_16)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val programNoFlags = ScriptProgram(program, ScriptFlagFactory.empty)
val newProgram = opCheckMultiSigVerify(programNoFlags)
val newProgram = CI.opCheckMultiSigVerify(programNoFlags)
newProgram.stack must be (List(OP_16,OP_16,OP_16))
newProgram.script must be (List(OP_16,OP_16,OP_16,OP_16))
newProgram.isInstanceOf[ExecutedScriptProgram] must be (false)
@ -130,9 +129,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = List(OP_CHECKMULTISIG)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val programNoFlags = ScriptProgram(program, ScriptFlagFactory.empty)
logger.warn("Running OP_CHECKMULTISIG program")
val newProgram = opCheckMultiSig(programNoFlags)
logger.warn("Ran OP_CHECKMULTISIG program")
val newProgram = CI.opCheckMultiSig(programNoFlags)
newProgram.stack must be (List(OP_TRUE))
newProgram.script.isEmpty must be (true)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (false)
@ -149,7 +146,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = Seq(OP_0,OP_0,OP_1)
val script = Seq(OP_CHECKMULTISIG)
val program = ScriptProgram(baseProgram,stack,script)
val executedProgram = opCheckMultiSig(program)
val executedProgram = CI.opCheckMultiSig(program)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(executedProgram)
newProgram.error must be (Some(ScriptErrorSigNullDummy))
@ -162,7 +159,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = Seq(OP_CHECKSIG)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val programWithFlags = ScriptProgram(program,flags)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opCheckSig(programWithFlags))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(CI.opCheckSig(programWithFlags))
newProgram.error must be (Some(ScriptErrorSigDer))
}
@ -171,7 +168,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val stack = List()
val script = Seq(OP_CODESEPARATOR)
val program = ScriptProgram(ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script),script,ScriptProgram.OriginalScript)
val newProgram = ScriptProgramTestUtil.toExecutionInProgressScriptProgram(opCodeSeparator(program))
val newProgram = ScriptProgramTestUtil.toExecutionInProgressScriptProgram(CI.opCodeSeparator(program))
newProgram.lastCodeSeparator must be (Some(0))
}

View file

@ -1,27 +1,24 @@
package org.bitcoins.core.script.locktime
import org.bitcoins.core.currency.CurrencyUnits
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.policy.Policy
import org.bitcoins.core.protocol.script.SigVersionBase
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionConstants, TransactionInput, UpdateTransactionInputs}
import org.bitcoins.core.script.result._
import org.bitcoins.core.script.{ExecutedScriptProgram, ExecutionInProgressScriptProgram, PreExecutionScriptProgram, ScriptProgram}
import org.bitcoins.core.script.constant.{OP_0, ScriptNumber}
import org.bitcoins.core.script.result._
import org.bitcoins.core.script.{ExecutedScriptProgram, PreExecutionScriptProgram, ScriptProgram}
import org.bitcoins.core.util.{ScriptProgramTestUtil, TestUtil}
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 3/30/16.
*/
class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeInterpreter {
class LockTimeInterpreterTest extends FlatSpec with MustMatchers {
val LTI = LockTimeInterpreter
"LockTimeInterpreter" must "mark the transaction invalid if the stack is empty" in {
val stack = Seq()
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opCheckLockTimeVerify(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(LTI.opCheckLockTimeVerify(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -29,7 +26,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val stack = Seq(OP_0)
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opCheckLockTimeVerify(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(LTI.opCheckLockTimeVerify(program))
newProgram.error must be (Some(ScriptErrorUnsatisfiedLocktime))
}
@ -42,7 +39,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val baseProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgramTestUtil.toPreExecutionScriptProgram(ScriptProgram(baseProgram,stack,script))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opCheckLockTimeVerify(ScriptProgram.toExecutionInProgress(program)))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(LTI.opCheckLockTimeVerify(ScriptProgram.toExecutionInProgress(program)))
newProgram.error must be (Some(ScriptErrorNegativeLockTime))
}
@ -55,7 +52,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val baseProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgramTestUtil.toPreExecutionScriptProgram(ScriptProgram(baseProgram,stack,script))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opCheckLockTimeVerify(ScriptProgram.toExecutionInProgress(program)))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(LTI.opCheckLockTimeVerify(ScriptProgram.toExecutionInProgress(program)))
newProgram.error must be (Some(ScriptErrorUnsatisfiedLocktime))
}
@ -68,7 +65,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val baseProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgramTestUtil.toPreExecutionScriptProgram(ScriptProgram(baseProgram,stack,script))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opCheckLockTimeVerify(ScriptProgram.toExecutionInProgress(program)))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(LTI.opCheckLockTimeVerify(ScriptProgram.toExecutionInProgress(program)))
newProgram.error must be (Some(ScriptErrorUnsatisfiedLocktime))
}
@ -84,7 +81,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags))
val program = ScriptProgram(baseProgram,stack,script)
val newProgram = opCheckLockTimeVerify(program)
val newProgram = LTI.opCheckLockTimeVerify(program)
//if an error is hit, the newProgram will be an instance of ExecutedScriptProgram
//if an error is not hit it will still be a ExecutionInProgressScriptProgram
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
@ -102,7 +99,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags))
val program = ScriptProgram(baseProgram,stack,script)
val newProgram = opCheckLockTimeVerify(program)
val newProgram = LTI.opCheckLockTimeVerify(program)
//if an error is hit, the newProgram will be an instance of ExecutedScriptProgram
//if an error is not hit it will still be a ExecutionInProgressScriptProgram
newProgram.isInstanceOf[ExecutedScriptProgram] must be (false)
@ -119,7 +116,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags
)
val program = ScriptProgram(baseProgram,stack,script)
val newProgram = opCheckLockTimeVerify(program)
val newProgram = LTI.opCheckLockTimeVerify(program)
//if an error is hit, the newProgram will be an instance of ExecutedScriptProgram
//if an error is not hit it will still be a ExecutionInProgressScriptProgram
newProgram.isInstanceOf[ExecutedScriptProgram] must be (false)
@ -129,7 +126,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val stack = List()
val script = List(OP_CHECKSEQUENCEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = opCheckSequenceVerify(program)
val newProgram = LTI.opCheckSequenceVerify(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -138,7 +135,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val stack = List(ScriptNumber.negativeOne)
val script = List(OP_CHECKSEQUENCEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = opCheckSequenceVerify(program)
val newProgram = LTI.opCheckSequenceVerify(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorNegativeLockTime))
}
@ -147,7 +144,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val stack = List(ScriptNumber("0100"))
val script = List(OP_CHECKSEQUENCEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = opCheckSequenceVerify(program)
val newProgram = LTI.opCheckSequenceVerify(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorUnknownError))
}
@ -156,7 +153,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
val stack = List(ScriptNumber(TransactionConstants.locktimeDisabledFlag.underlying))
val script = List(OP_CHECKSEQUENCEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = opCheckSequenceVerify(program)
val newProgram = LTI.opCheckSequenceVerify(program)
newProgram.stack must be (stack)
newProgram.script.isEmpty must be (true)
}

View file

@ -10,13 +10,14 @@ import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 2/4/16.
*/
class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterpreter {
class SpliceInterpreterTest extends FlatSpec with MustMatchers {
val SI = SpliceInterpreter
"SpliceInterpreter" must "evaluate an OP_SIZE on OP_0 correctly" in {
val stack = List(OP_0)
val script = List(OP_SIZE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSize(program)
val newProgram = SI.opSize(program)
newProgram.stack must be (List(OP_0,OP_0))
newProgram.script.isEmpty must be (true)
@ -26,7 +27,7 @@ class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterp
val stack = List(ScriptNumber.zero)
val script = List(OP_SIZE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSize(program)
val newProgram = SI.opSize(program)
newProgram.stack must be (List(ScriptNumber.zero,ScriptNumber.zero))
newProgram.script.isEmpty must be (true)
}
@ -35,7 +36,7 @@ class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterp
val stack = List(ScriptConstant("7f"))
val script = List(OP_SIZE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSize(program)
val newProgram = SI.opSize(program)
newProgram.stack must be (List(ScriptNumber(1),ScriptConstant("7f")))
newProgram.script.isEmpty must be (true)
}
@ -45,7 +46,7 @@ class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterp
val stack = List(ScriptNumber(128))
val script = List(OP_SIZE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSize(program)
val newProgram = SI.opSize(program)
newProgram.stack must be (List(ScriptNumber(2), ScriptNumber(128)))
newProgram.script.isEmpty must be (true)
}
@ -55,7 +56,7 @@ class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterp
val stack = List(ScriptNumber(-1))
val script = List(OP_SIZE)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSize(program)
val newProgram = SI.opSize(program)
newProgram.stack must be (List(ScriptNumber.one,ScriptNumber(-1)))
newProgram.script.isEmpty must be (true)
}
@ -64,7 +65,7 @@ class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterp
val stack = List()
val script = List(OP_SIZE)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opSize(program)
val newProgram = SI.opSize(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}

View file

@ -10,15 +10,16 @@ import org.bitcoins.core.script.result._
/**
* Created by chris on 1/6/16.
*/
class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpreter {
class StackInterpreterTest extends FlatSpec with MustMatchers {
val element1 = ScriptConstant("1234")
val element2 = ScriptConstant("abcd")
val stack = List(element1,element2)
val SI = StackInterpreter
"StackInterpreter" must "duplicate elements on top of the stack" in {
val script = List(OP_DUP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opDup(program)
val newProgram = SI.opDup(program)
newProgram.stack.head must be (element1)
newProgram.stack(1) must be (element1)
@ -29,7 +30,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
intercept[IllegalArgumentException] {
val script = List()
val program = ScriptProgram(TestUtil.testProgram, stack,script)
opDup(program)
SI.opDup(program)
}
}
@ -37,14 +38,14 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List()
val script = List(OP_DUP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
ScriptProgramTestUtil.toExecutedScriptProgram(opDup(program)).error must be (Some(ScriptErrorInvalidStackOperation))
ScriptProgramTestUtil.toExecutedScriptProgram(SI.opDup(program)).error must be (Some(ScriptErrorInvalidStackOperation))
}
it must "evaluate the OP_DEPTH operator correctly" in {
val script = List(OP_DEPTH)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opDepth(program)
val newProgram = SI.opDepth(program)
newProgram.stack.head.hex must be (BitcoinSUtil.encodeHex(stack.size.toByte))
}
@ -53,7 +54,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List()
val script = List(OP_DEPTH)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opDepth(program)
val newProgram = SI.opDepth(program)
newProgram.stack.head must be (ScriptNumber.zero)
}
@ -61,7 +62,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(OP_0)
val script = List(OP_TOALTSTACK)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opToAltStack(program)
val newProgram = SI.opToAltStack(program)
newProgram.stack.isEmpty must be (true)
newProgram.script.isEmpty must be (true)
@ -73,7 +74,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(OP_0)
val script = List(OP_DROP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opDrop(program)
val newProgram = SI.opDrop(program)
newProgram.stack.isEmpty must be (true)
newProgram.script.isEmpty must be (true)
@ -83,7 +84,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List()
val script = List(OP_DROP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opDrop(program)
val newProgram = SI.opDrop(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -92,14 +93,14 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptNumber.zero)
val script = List(OP_IFDUP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opIfDup(program)
val newProgram = SI.opIfDup(program)
newProgram.stack must be (stack)
newProgram.script.isEmpty must be (true)
val stack1 = List(OP_1)
val program1 = ScriptProgram(TestUtil.testProgram, stack1,script)
val newProgram1 = opIfDup(program1)
val newProgram1 = SI.opIfDup(program1)
newProgram1.stack must be (List(OP_1,OP_1))
newProgram1.script.isEmpty must be (true)
@ -111,7 +112,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opNip(program)
val newProgram = SI.opNip(program)
newProgram.stack must be (List(OP_0))
newProgram.script.isEmpty must be (true)
@ -122,7 +123,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_NIP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opNip(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.opNip(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -132,7 +133,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_NIP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opNip(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.opNip(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -140,7 +141,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(OP_0,OP_1)
val script = List(OP_OVER)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opOver(program)
val newProgram = SI.opOver(program)
newProgram.stack must be (List(OP_1,OP_0,OP_1))
newProgram.script.isEmpty must be (true)
}
@ -150,7 +151,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_OVER)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opOver(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.opOver(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -160,7 +161,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_OVER)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opOver(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.opOver(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -169,7 +170,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptNumber.zero, ScriptConstant("14"), ScriptConstant("15"), ScriptConstant("16"))
val script = List(OP_PICK)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opPick(program)
val newProgram = SI.opPick(program)
newProgram.stack must be (List(ScriptConstant("14"),ScriptConstant("14"),
ScriptConstant("15"), ScriptConstant("16")))
@ -180,7 +181,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptNumber.one)
val script = List(OP_PICK)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opPick(program)
val newProgram = SI.opPick(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
@ -190,7 +191,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptNumber.zero, ScriptConstant("14"), ScriptConstant("15"), ScriptConstant("16"))
val script = List(OP_ROLL)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opRoll(program)
val newProgram = SI.opRoll(program)
newProgram.stack must be (List(ScriptConstant("14"),
ScriptConstant("15"), ScriptConstant("16")))
@ -201,7 +202,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptNumber.one)
val script = List(OP_ROLL)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opRoll(program)
val newProgram = SI.opRoll(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
@ -211,7 +212,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptNumber("0100"))
val script = List(OP_ROLL)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opRoll(program)
val newProgram = SI.opRoll(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
@ -221,7 +222,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptConstant("14"), ScriptConstant("15"), ScriptConstant("16"))
val script = List(OP_ROT)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opRot(program)
val newProgram = SI.opRot(program)
newProgram.stack must be (List(ScriptConstant("16"),ScriptConstant("14"),ScriptConstant("15")))
newProgram.script.isEmpty must be (true)
@ -232,7 +233,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_ROT)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opRot(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.opRot(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -242,7 +243,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_2ROT)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op2Rot(program)
val newProgram = SI.op2Rot(program)
newProgram.stack must be (List(ScriptConstant("18"),ScriptConstant("19"),ScriptConstant("14"),
ScriptConstant("15"),ScriptConstant("16"), ScriptConstant("17")))
@ -255,7 +256,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_2ROT)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(op2Rot(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.op2Rot(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -264,7 +265,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_2DROP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op2Drop(program)
val newProgram = SI.op2Drop(program)
newProgram.stack must be (List(ScriptConstant("16"),
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19")))
@ -274,7 +275,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptConstant("14"))
val script = List(OP_2DROP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = op2Drop(program)
val newProgram = SI.op2Drop(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -284,7 +285,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_SWAP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opSwap(program)
val newProgram = SI.opSwap(program)
newProgram.stack must be (List(ScriptConstant("15"),ScriptConstant("14"), ScriptConstant("16"),
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19")))
newProgram.script.isEmpty must be (true)
@ -294,7 +295,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptConstant("14"))
val script = List(OP_SWAP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = opSwap(program)
val newProgram = SI.opSwap(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -304,7 +305,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_TUCK)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = opTuck(program)
val newProgram = SI.opTuck(program)
newProgram.stack must be (List(ScriptConstant("14"),ScriptConstant("15"),ScriptConstant("14"), ScriptConstant("16"),
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19")))
newProgram.script.isEmpty must be (true)
@ -315,7 +316,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_TUCK)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opTuck(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.opTuck(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -325,7 +326,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_2DUP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op2Dup(program)
val newProgram = SI.op2Dup(program)
newProgram.stack must be (List(ScriptConstant("14"),ScriptConstant("15"),
ScriptConstant("14"),ScriptConstant("15"), ScriptConstant("16"),
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19")))
@ -337,7 +338,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_2DUP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(op2Dup(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.op2Dup(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -347,7 +348,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_3DUP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op3Dup(program)
val newProgram = SI.op3Dup(program)
newProgram.stack must be (List(ScriptConstant("14"),ScriptConstant("15"),ScriptConstant("16"),
ScriptConstant("14"),ScriptConstant("15"), ScriptConstant("16"),
@ -359,7 +360,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val stack = List(ScriptConstant("14"), ScriptConstant("15"))
val script = List(OP_3DUP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = op3Dup(program)
val newProgram = SI.op3Dup(program)
newProgram.isInstanceOf[ExecutedScriptProgram] must be (true)
newProgram.asInstanceOf[ExecutedScriptProgram].error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -369,7 +370,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_2OVER)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op2Over(program)
val newProgram = SI.op2Over(program)
newProgram.stack must be (List(ScriptConstant("16"),
ScriptConstant("17"), ScriptConstant("14"),ScriptConstant("15"), ScriptConstant("16"),
@ -382,7 +383,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_2OVER)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(op2Over(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.op2Over(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -392,7 +393,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
ScriptConstant("17"), ScriptConstant("18"), ScriptConstant("19"))
val script = List(OP_2SWAP)
val program = ScriptProgram(TestUtil.testProgram, stack,script)
val newProgram = op2Swap(program)
val newProgram = SI.op2Swap(program)
newProgram.stack must be (List(ScriptConstant("16"), ScriptConstant("17"),ScriptConstant("14"),
ScriptConstant("15"), ScriptConstant("18"), ScriptConstant("19")))
@ -404,7 +405,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val script = List(OP_2SWAP)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(op2Swap(program))
val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(SI.op2Swap(program))
newProgram.error must be (Some(ScriptErrorInvalidStackOperation))
}
@ -414,7 +415,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpre
val altStack = List(OP_0)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script)
val programWithAltStack = ScriptProgram(program, altStack ,ScriptProgram.AltStack)
val executedProgram = opFromAltStack(programWithAltStack)
val executedProgram = SI.opFromAltStack(programWithAltStack)
executedProgram.stack must be (altStack)
}
}