Adding signature for parse function

This commit is contained in:
Chris Stewart 2016-01-07 22:02:29 -06:00
parent 3df808a82b
commit 327844fa3b
7 changed files with 129 additions and 3 deletions

View File

@ -11,6 +11,17 @@ trait ScriptOperation {
sealed trait Constant extends ScriptOperation sealed trait Constant extends ScriptOperation
/**
* Represent a pubkey or hash of a pub key on our stack
*
* @param str
*/
case class ConstantImpl(str : String) extends ScriptOperation {
//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.)
*/ */

View File

@ -17,6 +17,26 @@ trait CryptoInterpreter extends ScalacoinUtil {
(hash :: stack, script.tail) (hash :: stack, script.tail)
} }
/**
* The entire transaction's outputs, inputs, and script (from the most
* recently-executed OP_CODESEPARATOR to the end) are hashed.
* The signature used by OP_CHECKSIG must be a valid signature for this hash and public key.
* If it is, 1 is returned, 0 otherwise.
* @param inputScript
* @param script
* @return
*/
/*
def checkSig(inputScript : List[String], script : List[ScriptOperation]) : Boolean = {
require(inputScript.size > 1, "We must have at least 2 inputs for our OP_CHECKSIG operation")
require(script.headOption.isDefined && script.head == OP_CHECKSIG, "The top script stack element must be OP_CHECKSIG")
val pubKey = inputScript.head
val signature = inputScript(1)
???
}
*/
/*def codeSeparator()*/
/** /**
* Does the following computation * Does the following computation

View File

@ -1,16 +1,51 @@
package org.scalacoin.script.interpreter package org.scalacoin.script.interpreter
import org.scalacoin.script.ScriptOperation import org.scalacoin.script.{ConstantImpl, ScriptOperation}
import org.scalacoin.script.stack.OP_DUP import org.scalacoin.script.bitwise.{OP_EQUAL, BitwiseInterpreter, OP_EQUALVERIFY}
import org.scalacoin.script.control.ControlOperationsInterpreter
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160, CryptoInterpreter}
import org.scalacoin.script.stack.{StackInterpreter, OP_DUP}
import scala.annotation.tailrec
import scala.collection.immutable.Stack import scala.collection.immutable.Stack
/** /**
* Created by chris on 1/6/16. * Created by chris on 1/6/16.
*/ */
trait ScriptInterpreter { trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with ControlOperationsInterpreter
with BitwiseInterpreter {
/**
* Runs an entire script though our script programming language and
* returns true or false depending on if the script was valid
* @param stack
* @param script
* @return
*/
def run(inputScript : List[String], outputScript : List[ScriptOperation]) : Boolean = {
@tailrec
def loop(scripts : (List[String], List[ScriptOperation])) : Boolean = {
val (inputScript,outputScript) = (scripts._1, scripts._2)
outputScript match {
case OP_DUP :: t => loop(opDup(inputScript,outputScript))
case OP_HASH160 :: t => loop(hash160(inputScript,outputScript))
case OP_EQUAL :: t => loop(equal(inputScript, outputScript))
//TODO: Implement these
case ConstantImpl(x) :: t if x == "1" => throw new RuntimeException("Not implemented yet")
case ConstantImpl(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???
case ConstantImpl(x) :: t => loop(x :: inputScript, outputScript.tail)
//these cases result in our boolean result
case OP_EQUALVERIFY :: t => equalVerify(inputScript,outputScript)
/*case OP_CHECKSIG :: t => checkSig(inputScript,outputScript)*/
}
}
loop((inputScript,outputScript))
}
} }

View File

@ -0,0 +1,16 @@
package org.scalacoin.script.parsing
/**
* Created by chris on 1/7/16.
*/
trait ScriptParser {
/**
* Parses a script inside of a transaction
* @param str
* @tparam T
* @return
*/
def parse[T](str : String) : List[T] = ???
}

View File

@ -1,5 +1,8 @@
package org.scalacoin.script.interpreter package org.scalacoin.script.interpreter
import org.scalacoin.script.bitwise.OP_EQUALVERIFY
import org.scalacoin.script.{ConstantImpl, ScriptOperation}
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,4 +13,17 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp
/* "ScriptInterpreter" must "evaluate a valid script to true" in {
//this is in asm format, not hex
val inputScript =
List("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01",
"02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652")
//this is asm format, not hex
val outputScript : List[ScriptOperation] =
List(OP_DUP,OP_HASH160,ConstantImpl("e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b"),OP_EQUALVERIFY, OP_CHECKSIG)
val result = run(inputScript, outputScript)
result must be (true)
}*/
} }

View File

@ -0,0 +1,16 @@
package org.scalacoin.script.parsing
import org.scalacoin.util.TestUtil
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/7/16.
*/
class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser {
"ScriptParser" must "parse an input script" in {
val parsedInput = parse(TestUtil.p2khInputScriptNotParsed)
parsedInput must be (TestUtil.p2pkhInputScript)
}
}

View File

@ -1,6 +1,10 @@
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.bitwise.OP_EQUALVERIFY
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160}
import org.scalacoin.script.stack.OP_DUP
/** /**
* Created by chris on 12/2/15. * Created by chris on 12/2/15.
@ -12,4 +16,12 @@ object TestUtil {
val bitcoinAddress = BitcoinAddress("1C4kYhyLftmkn48YarSoLupxHfYFo8kp64") val bitcoinAddress = BitcoinAddress("1C4kYhyLftmkn48YarSoLupxHfYFo8kp64")
val multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey") val multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey")
val assetAddress = AssetAddress("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA") val assetAddress = AssetAddress("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA")
val p2khInputScriptNotParsed =
"3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01" +
" 02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c365
val p2khInputScript = List("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01",
"02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652")2"
val p2pkhOutputScriptNotParsed = "OP_DUP OP_HASH160 e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b OP_EQUALVERIFY OP_CHECKSI
val p2khOutputScript = List(OP_DUP,OP_HASH160,ConstantImpl("e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b"),OP_EQUALVERIFY, OP_CHECKSIG)
} }