mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 06:57:51 +01:00
Merge pull request #93 from Christewart/fix_control_flow_bug
Fix control flow bug
This commit is contained in:
commit
bee2ad2303
19 changed files with 570 additions and 560 deletions
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
@ -56,3 +56,5 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object BitwiseInterpreter extends BitwiseInterpreter
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
/**
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue