Adding transaction test utilility functions to build transactions for tests

This commit is contained in:
Chris Stewart 2016-02-12 10:50:28 -06:00
parent 0c486b303b
commit 5c8d915755
6 changed files with 70 additions and 41 deletions

View File

@ -3,6 +3,7 @@ package org.scalacoin.protocol.transaction
import org.scalacoin.currency.Satoshis
import org.scalacoin.marshallers.transaction.TransactionElement
import org.scalacoin.protocol.{NetworkVarInt, VarInt}
import org.scalacoin.util.ScalacoinUtil
/**
* Created by chris on 7/14/15.
@ -19,6 +20,7 @@ trait Transaction extends TransactionElement {
def inputsSize = inputs.map(_.size).sum
def outputsSize = outputs.map(_.size).sum
//https://bitcoin.org/en/developer-reference#raw-transaction-format
override def size = 4 + inputsSize + outputsSize + 4
}

View File

@ -0,0 +1,10 @@
package org.scalacoin.protocol.transaction
/**
* Created by chris on 2/12/16.
*/
object TransactionConstants {
val version = 1
val lockTime = 0
}

View File

@ -71,50 +71,23 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with ScalacoinUtil
ScriptProgramFactory.factory(program, newStackTop :: program.stack.tail, program.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[ScriptToken], script : List[ScriptToken], fullScript : List[ScriptToken]) : 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)
???
}
/**
* 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
* https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L818
* @param program
* @return
*/
def checkSig(tx : Transaction, scriptPubKey : ScriptPubKey) : Boolean = {
val inputIndex = 0
val signature : ScriptToken = tx.inputs.head.scriptSignature.asm.head
val pubKey : ScriptToken = tx.inputs.head.scriptSignature.asm(1)
def opCheckSig(program : ScriptProgram) : ScriptProgram = {
require(program.script.headOption.isDefined && program.script.head == OP_CHECKSIG, "Script top must be OP_CHECKSIG")
require(program.stack.size > 1, "Stack must have at least 2 items on it for OP_CHECKSIG")
val pubKey = program.stack.head
val signature = program.stack.tail.head
val hashType = HashTypeFactory.fromByte(ScalacoinUtil.decodeHex(signature.hex.last))
//delete ECDSA signature
val inputWithoutScriptSig : Seq[ScriptToken] = tx.inputs.head.scriptSignature.asm.tail
val fullScriptWithoutScripgSig : Seq[ScriptToken] = inputWithoutScriptSig ++ scriptPubKey.asm
val hashTypeOpt : Option[HashType] = HashTypeFactory.fromByte(ScalacoinUtil.decodeHex(signature.hex).last)
require(hashTypeOpt.isDefined, "We must have a hash type be the last byte on the given signature")
val hashType = hashTypeOpt.get
//hash for signature
val hash : String = hashForSignature(inputWithoutScriptSig,tx,inputIndex,hashType)
???
}

View File

@ -33,8 +33,8 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn
val script = List(OP_PUSHDATA4, ScriptConstantImpl("01000000"), ScriptNumberImpl(9), OP_9, OP_EQUAL)
val program = ScriptProgramFactory.factory(TestUtil.testProgram, stack,script)
val newProgram = opPushData4(program)
newProgram.stack must be (List(ScriptNumberImpl(9)))
newProgram.script must be (List(OP_9, OP_EQUAL))
newProgram.stack must be (List())
newProgram.script must be (List(ScriptNumberImpl(9),OP_9, OP_EQUAL))
}

View File

@ -63,13 +63,13 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp
val source = scala.io.Source.fromFile("src/test/scala/org/scalacoin/script/interpreter/script_valid.json")
//use this to represent a single test case from script_valid.json
/* val lines =
val lines =
"""
|
|[["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"]]
""".stripMargin*/
|[["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC"]]
""".stripMargin
val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
//val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
val json = lines.parseJson
val testCasesOpt : Seq[Option[CoreTestCase]] = json.convertTo[Seq[Option[CoreTestCase]]]
val testCases : Seq[CoreTestCase] = testCasesOpt.flatten

View File

@ -0,0 +1,44 @@
package org.scalacoin.util
import org.scalacoin.currency.CurrencyUnits
import org.scalacoin.protocol.script.{ScriptSignatureImpl, ScriptPubKey, ScriptPubKeyImpl, ScriptSignature}
import org.scalacoin.protocol.transaction._
import org.scalacoin.script.constant.{OP_0, ScriptToken}
/**
* Created by chris on 2/12/16.
*/
trait TransactionTestUtil {
/**
* Mimics the test utility found in bitcoin core
* https://github.com/bitcoin/bitcoin/blob/605c17844ea32b6d237db6d83871164dc7d59dab/src/test/script_tests.cpp#L73
* @param scriptSignature
* @param tx
*/
def buildSpendingTransaction(scriptSignature : ScriptSignature, tx : Transaction) : Transaction = {
val outpoint = TransactionOutPointImpl(tx.txId,0)
val input = TransactionInputImpl(outpoint,scriptSignature,0xFFFFFFFF)
//empty script pubkey
val scriptPubKey = ScriptPubKeyImpl(Seq(),"",Seq())
val output = TransactionOutputImpl(CurrencyUnits.oneSatoshi,0,scriptPubKey)
TransactionImpl("",TransactionConstants.version,Seq(input),Seq(output),TransactionConstants.lockTime)
}
/**
* Mimics this test utility found in bitcoin core
* https://github.com/bitcoin/bitcoin/blob/605c17844ea32b6d237db6d83871164dc7d59dab/src/test/script_tests.cpp#L57
* @param scriptPubKey
* @return
*/
def buildCreditingTransaction(scriptPubKey : ScriptPubKey) : Transaction = {
val outpoint = TransactionOutPointImpl("",0)
val scriptSignature = ScriptSignatureImpl(Seq(OP_0,OP_0),"0000")
val input = TransactionInputImpl(outpoint,scriptSignature,0xFFFFFFFF)
val output = TransactionOutputImpl(CurrencyUnits.oneSatoshi,0,scriptPubKey)
TransactionImpl("",TransactionConstants.version,Seq(input),Seq(output),TransactionConstants.lockTime)
}
}