mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-20 10:13:26 +01:00
Major refactor of types for ScriptOperations, overarching type is now ScriptToken
This commit is contained in:
parent
b70bf70dd2
commit
731648ece1
@ -4,12 +4,15 @@ package org.scalacoin.script
|
|||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
trait ScriptOperation {
|
|
||||||
|
trait ScriptToken
|
||||||
|
|
||||||
|
trait ScriptOperation extends ScriptToken {
|
||||||
def opCode : Int
|
def opCode : Int
|
||||||
def hex : String = Integer.toHexString(opCode)
|
def hex : String = Integer.toHexString(opCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait Constant extends ScriptOperation
|
sealed trait ScriptConstant extends ScriptToken
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,168 +20,164 @@ sealed trait Constant extends ScriptOperation
|
|||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
*/
|
*/
|
||||||
case class ConstantImpl(str : String) extends ScriptOperation {
|
case class ScriptConstantImpl(str : String) extends ScriptConstant
|
||||||
//TODO: Get around this op code some how, constants don't have op codes
|
|
||||||
override def opCode = -1
|
|
||||||
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
|
* An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
|
||||||
*/
|
*/
|
||||||
case object OP_0 extends Constant {
|
case object OP_0 extends ScriptOperation {
|
||||||
override def opCode = 0
|
override def opCode = 0
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
|
* An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
|
||||||
*/
|
*/
|
||||||
case object OP_FALSE extends Constant {
|
case object OP_FALSE extends ScriptOperation {
|
||||||
override def opCode = OP_0.opCode
|
override def opCode = OP_0.opCode
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The next byte contains the number of bytes to be pushed onto the stack.
|
* The next byte contains the number of bytes to be pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_PUSHDATA1 extends Constant {
|
case object OP_PUSHDATA1 extends ScriptOperation {
|
||||||
override def opCode = 76
|
override def opCode = 76
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The next two bytes contain the number of bytes to be pushed onto the stack.
|
* The next two bytes contain the number of bytes to be pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_PUSHDATA2 extends Constant {
|
case object OP_PUSHDATA2 extends ScriptOperation {
|
||||||
override def opCode = 77
|
override def opCode = 77
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The next four bytes contain the number of bytes to be pushed onto the stack.
|
* The next four bytes contain the number of bytes to be pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_PUSHDATA4 extends Constant {
|
case object OP_PUSHDATA4 extends ScriptOperation {
|
||||||
override def opCode = 78
|
override def opCode = 78
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number -1 is pushed onto the stack.
|
* The number -1 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_1NEGATE extends Constant {
|
case object OP_1NEGATE extends ScriptOperation {
|
||||||
override def opCode = 79
|
override def opCode = 79
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 1 is pushed onto the stack.
|
* The number 1 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_TRUE extends Constant {
|
case object OP_TRUE extends ScriptOperation {
|
||||||
override def opCode = 81
|
override def opCode = 81
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 1 is pushed onto the stack.
|
* The number 1 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_1 extends Constant {
|
case object OP_1 extends ScriptOperation {
|
||||||
override def opCode = OP_TRUE.opCode
|
override def opCode = OP_TRUE.opCode
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 2 is pushed onto the stack.
|
* The number 2 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_2 extends Constant {
|
case object OP_2 extends ScriptOperation {
|
||||||
override def opCode = 82
|
override def opCode = 82
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 3 is pushed onto the stack.
|
* The number 3 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_3 extends Constant {
|
case object OP_3 extends ScriptOperation {
|
||||||
override def opCode = 83
|
override def opCode = 83
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 4 is pushed onto the stack.
|
* The number 4 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_4 extends Constant {
|
case object OP_4 extends ScriptOperation {
|
||||||
override def opCode = 84
|
override def opCode = 84
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 5 is pushed onto the stack.
|
* The number 5 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_5 extends Constant {
|
case object OP_5 extends ScriptOperation {
|
||||||
override def opCode = 85
|
override def opCode = 85
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 6 is pushed onto the stack.
|
* The number 6 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_6 extends Constant {
|
case object OP_6 extends ScriptOperation {
|
||||||
override def opCode = 86
|
override def opCode = 86
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 7 is pushed onto the stack.
|
* The number 7 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_7 extends Constant {
|
case object OP_7 extends ScriptOperation {
|
||||||
override def opCode = 87
|
override def opCode = 87
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 8 is pushed onto the stack.
|
* The number 8 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_8 extends Constant {
|
case object OP_8 extends ScriptOperation {
|
||||||
override def opCode = 88
|
override def opCode = 88
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 9 is pushed onto the stack.
|
* The number 9 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_9 extends Constant {
|
case object OP_9 extends ScriptOperation {
|
||||||
override def opCode = 89
|
override def opCode = 89
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 10 is pushed onto the stack.
|
* The number 10 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_10 extends Constant {
|
case object OP_10 extends ScriptOperation {
|
||||||
override def opCode = 90
|
override def opCode = 90
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 11 is pushed onto the stack.
|
* The number 11 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_11 extends Constant {
|
case object OP_11 extends ScriptOperation {
|
||||||
override def opCode = 91
|
override def opCode = 91
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 12 is pushed onto the stack.
|
* The number 12 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_12 extends Constant {
|
case object OP_12 extends ScriptOperation {
|
||||||
override def opCode = 92
|
override def opCode = 92
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 13 is pushed onto the stack.
|
* The number 13 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_13 extends Constant {
|
case object OP_13 extends ScriptOperation {
|
||||||
override def opCode = 93
|
override def opCode = 93
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 14 is pushed onto the stack.
|
* The number 14 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_14 extends Constant {
|
case object OP_14 extends ScriptOperation {
|
||||||
override def opCode = 94
|
override def opCode = 94
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 15 is pushed onto the stack.
|
* The number 15 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_15 extends Constant {
|
case object OP_15 extends ScriptOperation {
|
||||||
override def opCode = 95
|
override def opCode = 95
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number 16 is pushed onto the stack.
|
* The number 16 is pushed onto the stack.
|
||||||
*/
|
*/
|
||||||
case object OP_16 extends Constant {
|
case object OP_16 extends ScriptOperation {
|
||||||
override def opCode = 96
|
override def opCode = 96
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.scalacoin.script.bitwise
|
package org.scalacoin.script.bitwise
|
||||||
|
|
||||||
import org.scalacoin.script.ScriptOperation
|
import org.scalacoin.script.{ScriptConstantImpl, ScriptToken, ScriptOperation}
|
||||||
import org.scalacoin.script.control.{OP_VERIFY, ControlOperationsInterpreter}
|
import org.scalacoin.script.control.{OP_VERIFY, ControlOperationsInterpreter}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,11 +14,11 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
|
|||||||
* @param script
|
* @param script
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def equal(stack : List[String], script : List[ScriptOperation]) : (List[String], List[ScriptOperation]) = {
|
def equal(stack : List[ScriptToken], script : List[ScriptToken]) : (List[ScriptToken], List[ScriptToken]) = {
|
||||||
require(stack.size > 1, "Stack size must be 2 or more to compare the top two values")
|
require(stack.size > 1, "Stack size must be 2 or more to compare the top two values")
|
||||||
require(script.headOption.isDefined && script.head == OP_EQUAL, "Script operation must be OP_EQUAL")
|
require(script.headOption.isDefined && script.head == OP_EQUAL, "Script operation must be OP_EQUAL")
|
||||||
val newStack = stack match {
|
val newStack = stack match {
|
||||||
case h :: h1 :: t => if (h == h1) "1" :: t else "0" :: t
|
case h :: h1 :: t => if (h == h1) ScriptConstantImpl("1") :: t else ScriptConstantImpl("0") :: t
|
||||||
}
|
}
|
||||||
(newStack,script.tail)
|
(newStack,script.tail)
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
|
|||||||
* @param script
|
* @param script
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def equalVerify(stack : List[String], script : List[ScriptOperation]) : Boolean = {
|
def equalVerify(stack : List[ScriptToken], script : List[ScriptToken]) : Boolean = {
|
||||||
require(stack.size > 1, "Stack size must be 2 or more to compare the top two values")
|
require(stack.size > 1, "Stack size must be 2 or more to compare the top two values")
|
||||||
require(script.headOption.isDefined && script.head == OP_EQUALVERIFY, "Script operation must be OP_EQUALVERIFY")
|
require(script.headOption.isDefined && script.head == OP_EQUALVERIFY, "Script operation must be OP_EQUALVERIFY")
|
||||||
//first replace OP_EQUALVERIFY with OP_EQUAL and OP_VERIFY
|
//first replace OP_EQUALVERIFY with OP_EQUAL and OP_VERIFY
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.scalacoin.script.control
|
package org.scalacoin.script.control
|
||||||
|
|
||||||
import org.scalacoin.script.ScriptOperation
|
import org.scalacoin.script.{ScriptConstantImpl, ScriptToken, ScriptOperation}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
@ -14,9 +14,9 @@ trait ControlOperationsInterpreter {
|
|||||||
* @param script
|
* @param script
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def verify(stack : List[String], script : List[ScriptOperation]) : Boolean = {
|
def verify(stack : List[ScriptToken], script : List[ScriptToken]) : Boolean = {
|
||||||
require(stack.size > 0, "Stack must not be empty to verify it")
|
require(stack.size > 0, "Stack must not be empty to verify it")
|
||||||
require(script.headOption.isDefined && script.head == OP_VERIFY, "Top of script stack must be OP_VERIFY")
|
require(script.headOption.isDefined && script.head == OP_VERIFY, "Top of script stack must be OP_VERIFY")
|
||||||
if (stack.head == "1") true else false
|
if (stack.head == ScriptConstantImpl("1")) true else false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.scalacoin.script.crypto
|
package org.scalacoin.script.crypto
|
||||||
|
|
||||||
import org.scalacoin.script.ScriptOperation
|
import org.scalacoin.script.{ScriptConstantImpl, ScriptConstant, ScriptToken, ScriptOperation}
|
||||||
import org.scalacoin.util.ScalacoinUtil
|
import org.scalacoin.util.ScalacoinUtil
|
||||||
|
|
||||||
|
|
||||||
@ -9,11 +9,14 @@ import org.scalacoin.util.ScalacoinUtil
|
|||||||
*/
|
*/
|
||||||
trait CryptoInterpreter extends ScalacoinUtil {
|
trait CryptoInterpreter extends ScalacoinUtil {
|
||||||
|
|
||||||
def hash160(stack : List[String], script : List[ScriptOperation]) : (List[String], List[ScriptOperation]) = {
|
def hash160(stack : List[ScriptToken], script : List[ScriptToken]) : (List[ScriptToken], List[ScriptToken]) = {
|
||||||
require(stack.headOption.isDefined, "The top of the stack must be defined")
|
require(stack.headOption.isDefined, "The top of the stack must be defined")
|
||||||
require(script.headOption.isDefined && script.head == OP_HASH160, "Script operation must be OP_HASH160")
|
require(script.headOption.isDefined && script.head == OP_HASH160, "Script operation must be OP_HASH160")
|
||||||
val stackTop = stack.head
|
val stackTop = stack.head
|
||||||
val hash = sha256Hash160(stackTop)
|
val hash = stackTop match {
|
||||||
|
case ScriptConstantImpl(x) => sha256Hash160(x)
|
||||||
|
case _ => throw new RuntimeException("Stack top should be of type ScriptConstant to call hash160 on it")
|
||||||
|
}
|
||||||
(hash :: stack, script.tail)
|
(hash :: stack, script.tail)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,10 +47,10 @@ trait CryptoInterpreter extends ScalacoinUtil {
|
|||||||
* @param hex
|
* @param hex
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private def sha256Hash160(hex : String) = {
|
private def sha256Hash160(hex : String) : ScriptConstant = {
|
||||||
val bytes = decodeHex(hex)
|
val bytes = decodeHex(hex)
|
||||||
val hash = org.bitcoinj.core.Utils.sha256hash160(bytes)
|
val hash = org.bitcoinj.core.Utils.sha256hash160(bytes)
|
||||||
encodeHex(hash)
|
ScriptConstantImpl(encodeHex(hash))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.scalacoin.script.interpreter
|
package org.scalacoin.script.interpreter
|
||||||
|
|
||||||
import org.scalacoin.script.{ConstantImpl, ScriptOperation}
|
import org.scalacoin.script.{ScriptToken, ScriptConstantImpl}
|
||||||
import org.scalacoin.script.bitwise.{OP_EQUAL, BitwiseInterpreter, OP_EQUALVERIFY}
|
import org.scalacoin.script.bitwise.{OP_EQUAL, BitwiseInterpreter, OP_EQUALVERIFY}
|
||||||
import org.scalacoin.script.control.ControlOperationsInterpreter
|
import org.scalacoin.script.control.ControlOperationsInterpreter
|
||||||
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160, CryptoInterpreter}
|
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160, CryptoInterpreter}
|
||||||
@ -24,20 +24,20 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
def run(inputScript : List[String], outputScript : List[ScriptOperation]) : Boolean = {
|
def run(inputScript : List[ScriptToken], outputScript : List[ScriptToken]) : Boolean = {
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
def loop(scripts : (List[String], List[ScriptOperation])) : Boolean = {
|
def loop(scripts : (List[ScriptToken], List[ScriptToken])) : Boolean = {
|
||||||
val (inputScript,outputScript) = (scripts._1, scripts._2)
|
val (inputScript,outputScript) = (scripts._1, scripts._2)
|
||||||
outputScript match {
|
outputScript match {
|
||||||
case OP_DUP :: t => loop(opDup(inputScript,outputScript))
|
case OP_DUP :: t => loop(opDup(inputScript,outputScript))
|
||||||
case OP_HASH160 :: t => loop(hash160(inputScript,outputScript))
|
case OP_HASH160 :: t => loop(hash160(inputScript,outputScript))
|
||||||
case OP_EQUAL :: t => loop(equal(inputScript, outputScript))
|
case OP_EQUAL :: t => loop(equal(inputScript, outputScript))
|
||||||
//TODO: Implement these
|
//TODO: Implement these
|
||||||
case ConstantImpl(x) :: t if x == "1" => throw new RuntimeException("Not implemented yet")
|
case ScriptConstantImpl(x) :: t if x == "1" => throw new RuntimeException("Not implemented yet")
|
||||||
case ConstantImpl(x) :: t if x == "0" => throw new RuntimeException("Not implemented yet")
|
case ScriptConstantImpl(x) :: t if x == "0" => throw new RuntimeException("Not implemented yet")
|
||||||
//TODO: is this right? I need to just push a constant on the input stack???
|
//TODO: is this right? I need to just push a constant on the input stack???
|
||||||
case ConstantImpl(x) :: t => loop(x :: inputScript, outputScript.tail)
|
case ScriptConstantImpl(x) :: t => loop((ScriptConstantImpl(x) :: inputScript, t))
|
||||||
//these cases result in our boolean result
|
//these cases result in our boolean result
|
||||||
case OP_EQUALVERIFY :: t => equalVerify(inputScript,outputScript)
|
case OP_EQUALVERIFY :: t => equalVerify(inputScript,outputScript)
|
||||||
/*case OP_CHECKSIG :: t => checkSig(inputScript,outputScript)*/
|
/*case OP_CHECKSIG :: t => checkSig(inputScript,outputScript)*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.scalacoin.script.parsing
|
package org.scalacoin.script.parsing
|
||||||
|
|
||||||
import org.scalacoin.script.ScriptOperation
|
import org.scalacoin.script._
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
@ -16,25 +16,24 @@ trait ScriptParser extends {
|
|||||||
* @tparam T
|
* @tparam T
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def parseInputScript(str : String) : List[String] = {
|
def parseInputScript(str : String) : List[ScriptToken] = ???
|
||||||
str.split(" ").toList
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an output script of a transaction
|
* Parses an output script of a transaction
|
||||||
* @param str
|
* @param str
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
/* def parseOutputScript(str : String) : List[ScriptOperation] = {
|
def parseOutputScript(str : String) : List[ScriptToken] = {
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
def loop(operations : List[String], accum : List[ScriptOperation]) : List[ScriptOperation] = {
|
def loop(operations : List[String], accum : List[ScriptToken]) : List[ScriptToken] = {
|
||||||
operations match {
|
operations match {
|
||||||
case h :: t if ()
|
case h :: t if (ScriptOperationFactory.fromString(h).isDefined) =>
|
||||||
|
loop(t,ScriptOperationFactory.fromString(h).get :: accum)
|
||||||
|
case h :: t => loop(t, ScriptConstantImpl(h) :: accum)
|
||||||
|
case h :: t if (h == "0") => loop(t, OP_0 :: accum)
|
||||||
|
case Nil => accum
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
loop(str.split(" ").toList.reverse, List())
|
||||||
loop(str.split(" ").toList, List())
|
}
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.scalacoin.script.stack
|
package org.scalacoin.script.stack
|
||||||
|
|
||||||
import org.scalacoin.script.ScriptOperation
|
import org.scalacoin.script.{ScriptToken, ScriptOperation}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
@ -13,7 +13,7 @@ trait StackInterpreter {
|
|||||||
* @param script
|
* @param script
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def opDup(stack : List[String], script : List[ScriptOperation]) : (List[String], List[ScriptOperation]) = {
|
def opDup(stack : List[ScriptToken], script : List[ScriptToken]) : (List[ScriptToken], List[ScriptToken]) = {
|
||||||
require(script.headOption.isDefined && script.head == OP_DUP, "Top of the script stack must be OP_DUP")
|
require(script.headOption.isDefined && script.head == OP_DUP, "Top of the script stack must be OP_DUP")
|
||||||
require(stack.headOption.isDefined, "Cannot duplicate the top element on an empty stack")
|
require(stack.headOption.isDefined, "Cannot duplicate the top element on an empty stack")
|
||||||
stack match {
|
stack match {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
package org.scalacoin.script.bitwise
|
package org.scalacoin.script.bitwise
|
||||||
|
|
||||||
|
import org.scalacoin.script.ScriptConstantImpl
|
||||||
import org.scalatest.{MustMatchers, FlatSpec}
|
import org.scalatest.{MustMatchers, FlatSpec}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
*/
|
*/
|
||||||
class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInterpreter {
|
class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInterpreter {
|
||||||
private val pubKeyHash = "5238C71458E464D9FF90299ABCA4A1D7B9CB76AB".toLowerCase
|
private val pubKeyHash = ScriptConstantImpl("5238C71458E464D9FF90299ABCA4A1D7B9CB76AB".toLowerCase)
|
||||||
|
|
||||||
"BitwiseInterpreter" must "evaluate OP_EQUAL" in {
|
"BitwiseInterpreter" must "evaluate OP_EQUAL" in {
|
||||||
val stack = List(pubKeyHash, pubKeyHash)
|
val stack = List(pubKeyHash, pubKeyHash)
|
||||||
val script = List(OP_EQUAL)
|
val script = List(OP_EQUAL)
|
||||||
|
|
||||||
val (newStack,newScript) = equal(stack,script)
|
val (newStack,newScript) = equal(stack,script)
|
||||||
newStack.head.toInt must be (1)
|
newStack.head must be (ScriptConstantImpl("1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "throw an exception for OP_EQUAL when we don't have enough items on the stack" in {
|
it must "throw an exception for OP_EQUAL when we don't have enough items on the stack" in {
|
||||||
@ -36,7 +37,7 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
|
|||||||
}
|
}
|
||||||
|
|
||||||
it must "evaluate OP_EQUALVERIFY to false given two different pub keys" in {
|
it must "evaluate OP_EQUALVERIFY to false given two different pub keys" in {
|
||||||
val uniquePubKey = pubKeyHash +"0"
|
val uniquePubKey = ScriptConstantImpl(pubKeyHash +"0")
|
||||||
val stack = List(pubKeyHash,uniquePubKey)
|
val stack = List(pubKeyHash,uniquePubKey)
|
||||||
val script = List(OP_EQUALVERIFY)
|
val script = List(OP_EQUALVERIFY)
|
||||||
val result = equalVerify(stack,script)
|
val result = equalVerify(stack,script)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.scalacoin.script.control
|
package org.scalacoin.script.control
|
||||||
|
|
||||||
|
import org.scalacoin.script.ScriptConstantImpl
|
||||||
import org.scalatest.{MustMatchers, FlatSpec}
|
import org.scalatest.{MustMatchers, FlatSpec}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,21 +9,21 @@ import org.scalatest.{MustMatchers, FlatSpec}
|
|||||||
class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with ControlOperationsInterpreter {
|
class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with ControlOperationsInterpreter {
|
||||||
|
|
||||||
"ControlOperationsInterpreter" must "have OP_VERIFY evaluate to true with '1' on the stack" in {
|
"ControlOperationsInterpreter" must "have OP_VERIFY evaluate to true with '1' on the stack" in {
|
||||||
val stack = List("1")
|
val stack = List(ScriptConstantImpl("1"))
|
||||||
val script = List(OP_VERIFY)
|
val script = List(OP_VERIFY)
|
||||||
val result = verify(stack,script)
|
val result = verify(stack,script)
|
||||||
result must be (true)
|
result must be (true)
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "have OP_VERIFY evaluate to false with '0' on the stack" in {
|
it must "have OP_VERIFY evaluate to false with '0' on the stack" in {
|
||||||
val stack = List("0")
|
val stack = List(ScriptConstantImpl("0"))
|
||||||
val script = List(OP_VERIFY)
|
val script = List(OP_VERIFY)
|
||||||
val result = verify(stack,script)
|
val result = verify(stack,script)
|
||||||
result must be (false)
|
result must be (false)
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "have OP_VERIFY evaluate to false with '2' on the stack" in {
|
it must "have OP_VERIFY evaluate to false with '2' on the stack" in {
|
||||||
val stack = List("2")
|
val stack = List(ScriptConstantImpl("2"))
|
||||||
val script = List(OP_VERIFY)
|
val script = List(OP_VERIFY)
|
||||||
val result = verify(stack,script)
|
val result = verify(stack,script)
|
||||||
result must be (false)
|
result must be (false)
|
||||||
@ -38,7 +39,7 @@ class ControlOperationsInterpreterTest extends FlatSpec with MustMatchers with C
|
|||||||
|
|
||||||
it must "fail for verify when there is nothing on the script stack" in {
|
it must "fail for verify when there is nothing on the script stack" in {
|
||||||
intercept[IllegalArgumentException] {
|
intercept[IllegalArgumentException] {
|
||||||
val stack = List("1")
|
val stack = List(ScriptConstantImpl("1"))
|
||||||
val script = List()
|
val script = List()
|
||||||
val result = verify(stack,script)
|
val result = verify(stack,script)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.scalacoin.script.interpreter
|
package org.scalacoin.script.interpreter
|
||||||
|
|
||||||
import org.scalacoin.script.bitwise.OP_EQUALVERIFY
|
import org.scalacoin.script.bitwise.OP_EQUALVERIFY
|
||||||
import org.scalacoin.script.{ConstantImpl, ScriptOperation}
|
import org.scalacoin.script.{ ScriptOperation}
|
||||||
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160}
|
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160}
|
||||||
import org.scalacoin.script.stack.OP_DUP
|
import org.scalacoin.script.stack.OP_DUP
|
||||||
import org.scalatest.{MustMatchers, FlatSpec}
|
import org.scalatest.{MustMatchers, FlatSpec}
|
||||||
|
@ -10,12 +10,22 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser {
|
|||||||
|
|
||||||
|
|
||||||
"ScriptParser" must "parse an input script" in {
|
"ScriptParser" must "parse an input script" in {
|
||||||
val parsedInput = parseInputScript(TestUtil.p2pkhInputScriptNotParsed)
|
/* val parsedInput = parseInputScript(TestUtil.p2pkhInputScriptNotParsedAsm)
|
||||||
parsedInput must be (TestUtil.p2pkhInputScript)
|
parsedInput must be (TestUtil.p2pkhInputScriptAsm)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "parse an output script" in {
|
it must "parse a pay-to-pubkey-hash output script" in {
|
||||||
val parsedOutput = parseOutputScript(TestUtil.p2pkhOutputScriptNotParsed)
|
val parsedOutput = parseOutputScript(TestUtil.p2pkhOutputScriptNotParsedAsm)
|
||||||
parsedOutput must be (TestUtil.p2pkhOutputScript)
|
parsedOutput must be (TestUtil.p2pkhOutputScriptAsm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "parse a pay-to-script-hash output script" in {
|
||||||
|
val parsedOutput = parseOutputScript(TestUtil.p2shOutputScriptNotParsedAsm)
|
||||||
|
parsedOutput must be (TestUtil.p2shOutputScriptAsm)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* it must "parse a pay-to-script-hash input script" in {
|
||||||
|
val parsedInput = parseInput
|
||||||
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
package org.scalacoin.script.stack
|
package org.scalacoin.script.stack
|
||||||
|
|
||||||
|
import org.scalacoin.script.ScriptConstantImpl
|
||||||
import org.scalatest.{FlatSpec, MustMatchers}
|
import org.scalatest.{FlatSpec, MustMatchers}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
*/
|
*/
|
||||||
class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpreter {
|
class StackInterpreterTest extends FlatSpec with MustMatchers with StackInterpreter {
|
||||||
|
val stack = List(ScriptConstantImpl("Hello"),ScriptConstantImpl("World"))
|
||||||
"StackInterpreter" must "duplicate elements on top of the stack" in {
|
"StackInterpreter" must "duplicate elements on top of the stack" in {
|
||||||
val stack = List("Hello","World")
|
|
||||||
val script = List(OP_DUP)
|
val script = List(OP_DUP)
|
||||||
val (newStack,newScript) = opDup(stack,script)
|
val (newStack,newScript) = opDup(stack,script)
|
||||||
|
|
||||||
newStack.head must be ("Hello")
|
newStack.head must be (ScriptConstantImpl("Hello"))
|
||||||
newStack(1) must be ("Hello")
|
newStack(1) must be (ScriptConstantImpl("Hello"))
|
||||||
newStack(2) must be ("World")
|
newStack(2) must be (ScriptConstantImpl("World"))
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "throw an exception when calling opDup without an OP_DUP on top of the script stack" in {
|
it must "throw an exception when calling opDup without an OP_DUP on top of the script stack" in {
|
||||||
|
|
||||||
intercept[IllegalArgumentException] {
|
intercept[IllegalArgumentException] {
|
||||||
val stack = List("Hello","World")
|
|
||||||
val script = List()
|
val script = List()
|
||||||
val (newStack,newScript) = opDup(stack,script)
|
val (newStack,newScript) = opDup(stack,script)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.scalacoin.util
|
package org.scalacoin.util
|
||||||
|
|
||||||
import org.scalacoin.protocol.{AssetAddress, BitcoinAddress}
|
import org.scalacoin.protocol.{AssetAddress, BitcoinAddress}
|
||||||
import org.scalacoin.script.ConstantImpl
|
import org.scalacoin.script.ScriptConstantImpl
|
||||||
import org.scalacoin.script.bitwise.OP_EQUALVERIFY
|
import org.scalacoin.script.bitwise.{OP_EQUAL, OP_EQUALVERIFY}
|
||||||
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160}
|
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160}
|
||||||
import org.scalacoin.script.stack.OP_DUP
|
import org.scalacoin.script.stack.OP_DUP
|
||||||
|
|
||||||
@ -17,11 +17,26 @@ object TestUtil {
|
|||||||
val multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey")
|
val multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey")
|
||||||
val assetAddress = AssetAddress("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA")
|
val assetAddress = AssetAddress("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA")
|
||||||
|
|
||||||
val p2pkhInputScriptNotParsed =
|
val p2pkhInputScriptNotParsedAsm =
|
||||||
"3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01" +
|
"3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01" +
|
||||||
" 02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652"
|
" 02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652"
|
||||||
val p2pkhInputScript = List("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01",
|
val p2pkhInputScriptAsm = List("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01",
|
||||||
"02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652")
|
"02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652")
|
||||||
val p2pkhOutputScriptNotParsed = "OP_DUP OP_HASH160 e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b OP_EQUALVERIFY OP_CHECKSIG"
|
val p2pkhOutputScriptNotParsedAsm = "OP_DUP OP_HASH160 e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b OP_EQUALVERIFY OP_CHECKSIG"
|
||||||
val p2pkhOutputScript = List(OP_DUP,OP_HASH160,ConstantImpl("e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b"),OP_EQUALVERIFY, OP_CHECKSIG)
|
val p2pkhOutputScriptAsm = List(OP_DUP,OP_HASH160,ScriptConstantImpl("e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b"),OP_EQUALVERIFY, OP_CHECKSIG)
|
||||||
|
|
||||||
|
|
||||||
|
val p2shInputScriptNotParsedAsm =
|
||||||
|
"""0
|
||||||
|
|3045022100884c8a4776f4aa2a70f25f6bc0071929ade0ff4987844347e051e018c267aae402201fcec5dd052e7b01198bb57e1b58696c38ccd9d0b408c55047cac89b47287b4101
|
||||||
|
|3045022100b064d492712a080b726ecf37de2957b783fa411edae33bd13005e62d6a45d02302201b82b632df54cf1204758c2b5a3599f1f9a80da3d508951695bfcf8d2c2cce0f01
|
||||||
|
|522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452ae
|
||||||
|
|""".stripMargin
|
||||||
|
|
||||||
|
val p2shInputScript = List(
|
||||||
|
|
||||||
|
)
|
||||||
|
val p2shOutputScriptNotParsedAsm = "OP_HASH160 8ce5408cfeaddb7ccb2545ded41ef47810945484 OP_EQUAL"
|
||||||
|
val p2shOutputScriptAsm = List(OP_HASH160, ScriptConstantImpl("8ce5408cfeaddb7ccb2545ded41ef47810945484"), OP_EQUAL)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user