Fixing bug of parsing empty script sigs

This commit is contained in:
Chris Stewart 2016-02-23 09:40:53 -06:00
parent 5c85d57be2
commit 07699d2e4c
5 changed files with 37 additions and 44 deletions

View file

@ -139,7 +139,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper {
} }
case SIGHASH_ALL => case SIGHASH_ALL =>
//just need to add the hash type and hash the tx //just need to add the hash type and hash the tx
CryptoUtil.doubleSHA256(txWithInputSigsRemoved.bytes ++ List(hashType.byte)) txWithInputSigsRemoved.bytes ++ List(hashType.byte)
} }
} }

View file

@ -11,8 +11,6 @@ import org.scalacoin.util.ScalacoinUtil
trait RawScriptSignatureParser extends RawBitcoinSerializer[ScriptSignature] { trait RawScriptSignatureParser extends RawBitcoinSerializer[ScriptSignature] {
def read(bytes : List[Byte]) : ScriptSignature = { def read(bytes : List[Byte]) : ScriptSignature = {
require(bytes.size > 0, this.getClass().toString + " cannot parse an empty byte list")
//see https://bitcoin.org/en/developer-reference#txout for example
val scriptSig : List[ScriptToken] = ScriptParser.parse(bytes) val scriptSig : List[ScriptToken] = ScriptParser.parse(bytes)
ScriptSignatureImpl(scriptSig,ScalacoinUtil.encodeHex(bytes)) ScriptSignatureImpl(scriptSig,ScalacoinUtil.encodeHex(bytes))
} }

View file

@ -55,6 +55,9 @@ trait TransactionFactory { this : Transaction =>
*/ */
def factory(hex : String) : Transaction = RawTransactionParser.read(hex) def factory(hex : String) : Transaction = RawTransactionParser.read(hex)
def factory(bytes : Array[Byte]) : Transaction = factory(bytes.toSeq)
} }
sealed trait TransactionFactoryHelper sealed trait TransactionFactoryHelper

View file

@ -55,34 +55,12 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers {
val multiSigScript : org.bitcoinj.script.Script = ScriptBuilder.createMultiSigOutputScript(2, util.Arrays.asList(key1, key2, key3)); val multiSigScript : org.bitcoinj.script.Script = ScriptBuilder.createMultiSigOutputScript(2, util.Arrays.asList(key1, key2, key3));
val scriptPubKey = bitcoinjScriptToScriptPubKey(multiSigScript) val scriptPubKey = bitcoinjScriptToScriptPubKey(multiSigScript)
val creditingTx = Transaction.factory("01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000") val spendingTx = Transaction.factory(bitcoinjMultiSigTransaction.bitcoinSerialize())
val output = creditingTx.outputs(1)
val address = new org.bitcoinj.core.Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
val addressHash = new ScriptConstantImpl(address.getHash160.toList)
val outputScript : ScriptPubKey = ScriptPubKeyFactory.factory(
UpdateScriptPubKeyAsm(Seq(OP_DUP, OP_HASH160, addressHash, OP_EQUALVERIFY, OP_CHECKSIG))
)
ScalacoinUtil.encodeHex(outputScript.bytes)
val spendingTxOut : TransactionOutput = TransactionOutput.factory(output.value,outputScript)
val spendingTxIn : TransactionInput = TransactionInput.factory(spendingTxOut,creditingTx)
val spendingTxWithOutput = Transaction.empty.factory(
UpdateTransactionOutputs(Seq(spendingTxOut))
)
println(spendingTxWithOutput.bytes)
val spendingTx = spendingTxWithOutput.factory(UpdateTransactionInputs(Seq(spendingTxIn)))
println(spendingTxIn.bytes)
println(spendingTx.bytes)
val txSignatureSerializer = new BaseTransactionSignatureSerializer(spendingTx)
val bitcoinjSigHash = createBitcoinjMultiSigScriptHashForSig
/*val txSignatureSerializer = new BaseTransactionSignatureSerializer(spendingTx)
val sigBytes = txSignatureSerializer.serialize(0,scriptPubKey,SIGHASH_ALL) val sigBytes = txSignatureSerializer.serialize(0,scriptPubKey,SIGHASH_ALL)
ScalacoinUtil.encodeHex(sigBytes) must be (bitcoinjSigHash)
spendingTx.hex must be (ScalacoinUtil.encodeHex(bitcoinjMultiSigTransaction.bitcoinSerialize()))*/
} }
@ -93,24 +71,31 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers {
* @return * @return
*/ */
private def createBitcoinjMultiSigScriptHashForSig : String = { private def createBitcoinjMultiSigScriptHashForSig : String = {
val params = TestNet3Params.get()
val key1 = new DumpedPrivateKey(params, "cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT").getKey()
val key2 = new DumpedPrivateKey(params, "cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo").getKey()
val key3 = new DumpedPrivateKey(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg").getKey()
val spendTx = bitcoinjMultiSigTransaction
val multisigScript = ScriptBuilder.createMultiSigOutputScript(2, util.Arrays.asList(key1, key2, key3))
val sighash = spendTx.hashForSignature(0, multisigScript, SigHash.ALL, false)
ScalacoinUtil.encodeHex(sighash.getBytes)
}
private def bitcoinjMultiSigTransaction : org.bitcoinj.core.Transaction = {
//https://github.com/bitcoinj/bitcoinj/blob/master/core/src/test/java/org/bitcoinj/script/ScriptTest.java#L127 //https://github.com/bitcoinj/bitcoinj/blob/master/core/src/test/java/org/bitcoinj/script/ScriptTest.java#L127
val txHex = "01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000" val txHex = "01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000"
val params = TestNet3Params.get(); val params = TestNet3Params.get()
val key1 = new DumpedPrivateKey(params, "cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT").getKey();
val key2 = new DumpedPrivateKey(params, "cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo").getKey();
val key3 = new DumpedPrivateKey(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg").getKey();
val creditingTx = new org.bitcoinj.core.Transaction(params,ScalacoinUtil.decodeHex(txHex).toArray) val creditingTx = new org.bitcoinj.core.Transaction(params,ScalacoinUtil.decodeHex(txHex).toArray)
val output = creditingTx.getOutput(1); val output = creditingTx.getOutput(1)
val spendTx = new org.bitcoinj.core.Transaction(params); val spendTx = new org.bitcoinj.core.Transaction(params)
val address = new org.bitcoinj.core.Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H"); val address = new org.bitcoinj.core.Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H")
val outputScript = org.bitcoinj.script.ScriptBuilder.createOutputScript(address); val outputScript = org.bitcoinj.script.ScriptBuilder.createOutputScript(address)
spendTx.addOutput(output.getValue(), outputScript) spendTx.addOutput(output.getValue(), outputScript)
spendTx.addInput(output); spendTx.addInput(output)
val multisigScript = ScriptBuilder.createMultiSigOutputScript(2, util.Arrays.asList(key1, key2, key3)); spendTx
val sighash = spendTx.hashForSignature(0, multisigScript, SigHash.ALL, false);
ScalacoinUtil.encodeHex(sighash.getBytes)
} }

View file

@ -1,6 +1,6 @@
package org.scalacoin.marshallers.script package org.scalacoin.marshallers.script
import org.scalacoin.protocol.script.ScriptSignature import org.scalacoin.protocol.script.{ScriptSignatureFactory, ScriptSignature}
import org.scalacoin.script.constant.{OP_PUSHDATA1, ScriptConstantImpl, BytesToPushOntoStackImpl, OP_0} import org.scalacoin.script.constant.{OP_PUSHDATA1, ScriptConstantImpl, BytesToPushOntoStackImpl, OP_0}
import org.scalacoin.util.TestUtil import org.scalacoin.util.TestUtil
import org.scalatest.{FlatSpec, MustMatchers} import org.scalatest.{FlatSpec, MustMatchers}
@ -55,4 +55,11 @@ class RawScriptSignatureParserTest extends FlatSpec with MustMatchers with RawSc
) )
} }
it must "read a empty script sig" in {
val emptyScriptSig = ScriptSignatureFactory.empty
val parsedScriptSig = RawScriptSignatureParser.read(emptyScriptSig.hex)
parsedScriptSig.hex must be (emptyScriptSig.hex)
}
} }