mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-20 10:13:26 +01:00
Adding transaction input raw serializer, fixing bugs with ScriptSignature parser
This commit is contained in:
parent
bbff4ee676
commit
21cf91b5d0
@ -11,10 +11,14 @@ import org.scalacoin.util.ScalacoinUtil
|
||||
trait RawScriptSignatureParser extends RawBitcoinSerializer[ScriptSignature] with ScriptParser {
|
||||
|
||||
def read(bytes : List[Byte]) : ScriptSignature = {
|
||||
val scriptSig : List[ScriptToken] = parse(bytes)
|
||||
//first byte indicates how large the ENTIRE script signature is
|
||||
//see https://bitcoin.org/en/developer-reference#txout for example
|
||||
val scriptSigSize = bytes.head.toInt
|
||||
val scriptSig : List[ScriptToken] = parse(bytes.tail)
|
||||
ScriptSignatureImpl(scriptSig,ScalacoinUtil.encodeHex(bytes))
|
||||
}
|
||||
|
||||
def write(scriptSig : ScriptSignature) : String = scriptSig.hex
|
||||
|
||||
}
|
||||
|
||||
object RawScriptSignatureParser extends RawScriptSignatureParser
|
||||
|
@ -0,0 +1,43 @@
|
||||
package org.scalacoin.marshallers.transaction
|
||||
|
||||
import org.scalacoin.marshallers.RawBitcoinSerializer
|
||||
import org.scalacoin.marshallers.script.RawScriptSignatureParser
|
||||
import org.scalacoin.protocol.script.ScriptSignature
|
||||
import org.scalacoin.protocol.transaction.{TransactionInputImpl, TransactionOutPoint, TransactionInput}
|
||||
import org.scalacoin.util.ScalacoinUtil
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
/**
|
||||
* Created by chris on 1/13/16.
|
||||
* https://bitcoin.org/en/developer-reference#txin
|
||||
*/
|
||||
trait RawTransactionInputParser extends RawBitcoinSerializer[Seq[TransactionInput]] {
|
||||
|
||||
override def read(bytes : List[Byte]) : Seq[TransactionInput] = {
|
||||
require(bytes.size > 0, "You passed in an empty list to read")
|
||||
val numInputs = bytes.head.toInt
|
||||
@tailrec
|
||||
def loop(bytes : List[Byte], accum : List[TransactionInput], inputsLeftToParse : Int) : Seq[TransactionInput] = {
|
||||
if (inputsLeftToParse > 0) {
|
||||
val outPointBytesSize = 36
|
||||
val outPointBytes = bytes.take(outPointBytesSize)
|
||||
val outPoint : TransactionOutPoint = RawTransactionOutPointParser.read(outPointBytes)
|
||||
val scriptSigSize = bytes(outPointBytesSize).toInt
|
||||
val scriptSigBytes = bytes.slice(outPointBytesSize, outPointBytesSize + scriptSigSize + 1)
|
||||
val scriptSig : ScriptSignature = RawScriptSignatureParser.read(scriptSigBytes)
|
||||
val sequenceBytes = bytes.slice(outPointBytesSize + scriptSigSize + 1 , outPointBytesSize + scriptSigSize + 6)
|
||||
val sequenceNumberHex : String = ScalacoinUtil.encodeHex(sequenceBytes)
|
||||
val sequenceNumber : Long = BigInt(sequenceNumberHex,16).toLong
|
||||
val txInput = TransactionInputImpl(outPoint, scriptSig,sequenceNumber)
|
||||
val newAccum = txInput :: accum
|
||||
val bytesToBeParsed = bytes.slice(scriptSigSize + 5, bytes.size)
|
||||
loop(bytesToBeParsed, newAccum, inputsLeftToParse - 1)
|
||||
} else accum
|
||||
}
|
||||
|
||||
loop(bytes.tail, List(), numInputs).reverse
|
||||
}
|
||||
|
||||
override def write(inputs : Seq[TransactionInput]) = ???
|
||||
}
|
@ -9,21 +9,22 @@ import org.scalacoin.util.ScalacoinUtil
|
||||
* https://bitcoin.org/en/developer-reference#outpoint
|
||||
*
|
||||
*/
|
||||
trait RawTransactionOutPointMarshaller extends RawBitcoinSerializer[TransactionOutPoint] {
|
||||
trait RawTransactionOutPointParser extends RawBitcoinSerializer[TransactionOutPoint] {
|
||||
|
||||
|
||||
override def read(bytes : List[Byte]) : TransactionOutPoint = {
|
||||
val txId : List[Byte] = bytes.slice(0,16)
|
||||
val index : BigInt = BigInt(bytes.slice(16, bytes.size).toArray)
|
||||
val txId : List[Byte] = bytes.slice(0,32).reverse
|
||||
val index : BigInt = BigInt(bytes.slice(32, bytes.size).toArray)
|
||||
TransactionOutPointImpl(ScalacoinUtil.encodeHex(txId), index.toInt)
|
||||
}
|
||||
|
||||
def write(outPoint : TransactionOutPoint) : String = {
|
||||
val indexBytes : List[Byte] = List(0x00,0x00,0x00,outPoint.vout.toByte)
|
||||
outPoint.txId + ScalacoinUtil.encodeHex(indexBytes)
|
||||
val littleEndianTxId = ScalacoinUtil.encodeHex(ScalacoinUtil.decodeHex(outPoint.txId).reverse)
|
||||
littleEndianTxId + ScalacoinUtil.encodeHex(indexBytes)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
object RawTransactionOutPointMarshaller extends RawTransactionOutPointMarshaller
|
||||
object RawTransactionOutPointParser extends RawTransactionOutPointParser
|
||||
|
@ -13,9 +13,9 @@ class RawScriptSignatureParserTest extends FlatSpec with MustMatchers with RawSc
|
||||
//https://bitcoin.org/en/developer-reference#raw-transaction-format
|
||||
val rawScriptSig = "494830450221008949f0cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb388ab8935022079656090d7f6bac4c9a94e0aad311a4268e082a725f8aeae0573fb12ff866a5f01"
|
||||
"RawScriptSignatureParser" must "parse a raw scriptSig" in {
|
||||
val scriptSig : ScriptSignature = read(rawScriptSig)
|
||||
val scriptSig : ScriptSignature = RawScriptSignatureParser.read(rawScriptSig)
|
||||
|
||||
scriptSig.asm must be (Seq(ScriptConstantImpl("4830450221008949f0cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb388ab8935022079656090d7f6bac4c9a94e0aad311a4268e082a725f8aeae0573fb12ff866a5f01")))
|
||||
scriptSig.asm must be (Seq(ScriptConstantImpl("30450221008949f0cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb388ab8935022079656090d7f6bac4c9a94e0aad311a4268e082a725f8aeae0573fb12ff866a5f01")))
|
||||
scriptSig.hex must be (rawScriptSig)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
package org.scalacoin.marshallers.transaction
|
||||
|
||||
import org.scalacoin.protocol.transaction.TransactionInput
|
||||
import org.scalacoin.script.constant.{ScriptConstantImpl, OP_0}
|
||||
import org.scalatest.{ FlatSpec, MustMatchers}
|
||||
|
||||
/**
|
||||
* Created by chris on 1/13/16.
|
||||
*/
|
||||
class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawTransactionInputParser {
|
||||
|
||||
//txid cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6
|
||||
val rawTxInput = "01" +
|
||||
"85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000" +
|
||||
"6f0047304402207df6dd8dad22d49c3c83d8031733c32a53719278eb7985d3b35b375d776f84f102207054f9209a1e87d55feafc90aa04c33008e5bae9191da22aeaa16efde96f41f00125512102b022902a0fdd71e831c37e4136c2754a59887be0618fb75336d7ab67e2982ff551ae" +
|
||||
"ffffffff"
|
||||
"RawTransactionInputParser" must "parse a raw serialized transaction input" in {
|
||||
|
||||
val txInputs : Seq[TransactionInput] = read(rawTxInput)
|
||||
|
||||
txInputs.head.previousOutput.vout must be (0)
|
||||
txInputs.head.previousOutput.txId must be ("e17d316006850c1764301befcf82c8c84cd1794f3f0d0382b296df2edab0d685")
|
||||
txInputs.head.sequence must be (BigInt("4294967295"))
|
||||
txInputs.head.scriptSignature.hex must be ("6f0047304402207df6dd8dad22d49c3c83d8031733c32a53719278eb7985d3b35b375d776f84f102207054f9209a1e87d55feafc90aa04c33008e5bae9191da22aeaa16efde96f41f00125512102b022902a0fdd71e831c37e4136c2754a59887be0618fb75336d7ab67e2982ff551ae")
|
||||
txInputs.head.scriptSignature.asm must be (Seq(OP_0,
|
||||
ScriptConstantImpl("304402207df6dd8dad22d49c3c83d8031733c32a53719278eb7985d3b35b375d776f84f102207054f9209a1e87d55feafc90aa04c33008e5bae9191da22aeaa16efde96f41f001"),
|
||||
ScriptConstantImpl("512102b022902a0fdd71e831c37e4136c2754a59887be0618fb75336d7ab67e2982ff551ae")
|
||||
))
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.scalacoin.marshallers.transaction
|
||||
|
||||
import org.scalacoin.protocol.transaction.TransactionOutPointImpl
|
||||
import org.scalatest.{FlatSpec, MustMatchers}
|
||||
|
||||
/**
|
||||
* Created by chris on 1/11/16.
|
||||
*/
|
||||
class RawTransactionOutPointParserTest extends FlatSpec with MustMatchers {
|
||||
//txid cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6
|
||||
val rawOutPoint = "85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000"
|
||||
"RawTransactionOutPointMarshaller" must "read a raw outpoint into a native scala TransactionOutPoint" in {
|
||||
val outPoint = RawTransactionOutPointParser.read(rawOutPoint)
|
||||
outPoint.txId must be ("e17d316006850c1764301befcf82c8c84cd1794f3f0d0382b296df2edab0d685")
|
||||
outPoint.vout must be (0)
|
||||
}
|
||||
|
||||
it must "write a TransactionOutPoint to a serialized format" in {
|
||||
val outPoint = RawTransactionOutPointParser.read(rawOutPoint)
|
||||
val actualSerialization = RawTransactionOutPointParser.write(outPoint)
|
||||
actualSerialization must be (rawOutPoint)
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -12,7 +12,7 @@ import org.scalatest.{MustMatchers, FlatSpec}
|
||||
* Created by chris on 1/11/16.
|
||||
* https://bitcoin.org/en/developer-reference#txout
|
||||
*/
|
||||
class RawTransactionOutputMarshallerTest extends FlatSpec with MustMatchers with RawTransactionOutputParser {
|
||||
class RawTransactionOutputParserTest extends FlatSpec with MustMatchers with RawTransactionOutputParser {
|
||||
|
||||
//txid cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6
|
||||
val rawTxOutput = "02204e00000000000017a914eda8ae08b5c9f973f49543e90a7c292367b3337c87" +
|
||||
|
Loading…
Reference in New Issue
Block a user