From 07699d2e4cc6a60c0844a613ce83828606897c0f Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Tue, 23 Feb 2016 09:40:53 -0600 Subject: [PATCH] Fixing bug of parsing empty script sigs --- .../TransactionSignatureSerializer.scala | 2 +- .../script/RawScriptSignatureParser.scala | 2 - .../transaction/TransactionFactory.scala | 3 + .../TransactionSignatureSerializerTest.scala | 65 +++++++------------ .../script/RawScriptSignatureParserTest.scala | 9 ++- 5 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/main/scala/org/scalacoin/crypto/TransactionSignatureSerializer.scala b/src/main/scala/org/scalacoin/crypto/TransactionSignatureSerializer.scala index 7f82733f08..595f16c50a 100644 --- a/src/main/scala/org/scalacoin/crypto/TransactionSignatureSerializer.scala +++ b/src/main/scala/org/scalacoin/crypto/TransactionSignatureSerializer.scala @@ -139,7 +139,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper { } case SIGHASH_ALL => //just need to add the hash type and hash the tx - CryptoUtil.doubleSHA256(txWithInputSigsRemoved.bytes ++ List(hashType.byte)) + txWithInputSigsRemoved.bytes ++ List(hashType.byte) } } diff --git a/src/main/scala/org/scalacoin/marshallers/script/RawScriptSignatureParser.scala b/src/main/scala/org/scalacoin/marshallers/script/RawScriptSignatureParser.scala index 781e09eae1..466d57199f 100644 --- a/src/main/scala/org/scalacoin/marshallers/script/RawScriptSignatureParser.scala +++ b/src/main/scala/org/scalacoin/marshallers/script/RawScriptSignatureParser.scala @@ -11,8 +11,6 @@ import org.scalacoin.util.ScalacoinUtil trait RawScriptSignatureParser extends RawBitcoinSerializer[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) ScriptSignatureImpl(scriptSig,ScalacoinUtil.encodeHex(bytes)) } diff --git a/src/main/scala/org/scalacoin/protocol/transaction/TransactionFactory.scala b/src/main/scala/org/scalacoin/protocol/transaction/TransactionFactory.scala index 3db6a6fce0..3552481389 100644 --- a/src/main/scala/org/scalacoin/protocol/transaction/TransactionFactory.scala +++ b/src/main/scala/org/scalacoin/protocol/transaction/TransactionFactory.scala @@ -55,6 +55,9 @@ trait TransactionFactory { this : Transaction => */ def factory(hex : String) : Transaction = RawTransactionParser.read(hex) + + def factory(bytes : Array[Byte]) : Transaction = factory(bytes.toSeq) + } sealed trait TransactionFactoryHelper diff --git a/src/test/scala/org/scalacoin/crypto/TransactionSignatureSerializerTest.scala b/src/test/scala/org/scalacoin/crypto/TransactionSignatureSerializerTest.scala index d6d447f087..7d42e8150c 100644 --- a/src/test/scala/org/scalacoin/crypto/TransactionSignatureSerializerTest.scala +++ b/src/test/scala/org/scalacoin/crypto/TransactionSignatureSerializerTest.scala @@ -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 scriptPubKey = bitcoinjScriptToScriptPubKey(multiSigScript) - val creditingTx = Transaction.factory("01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000") - - 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 spendingTx = Transaction.factory(bitcoinjMultiSigTransaction.bitcoinSerialize()) + /*val txSignatureSerializer = new BaseTransactionSignatureSerializer(spendingTx) 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 */ 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 val txHex = "01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000" - 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 params = TestNet3Params.get() val creditingTx = new org.bitcoinj.core.Transaction(params,ScalacoinUtil.decodeHex(txHex).toArray) - val output = creditingTx.getOutput(1); - val spendTx = new org.bitcoinj.core.Transaction(params); - val address = new org.bitcoinj.core.Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H"); - val outputScript = org.bitcoinj.script.ScriptBuilder.createOutputScript(address); + val output = creditingTx.getOutput(1) + val spendTx = new org.bitcoinj.core.Transaction(params) + val address = new org.bitcoinj.core.Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H") + val outputScript = org.bitcoinj.script.ScriptBuilder.createOutputScript(address) spendTx.addOutput(output.getValue(), outputScript) - spendTx.addInput(output); - val multisigScript = ScriptBuilder.createMultiSigOutputScript(2, util.Arrays.asList(key1, key2, key3)); - val sighash = spendTx.hashForSignature(0, multisigScript, SigHash.ALL, false); - ScalacoinUtil.encodeHex(sighash.getBytes) + spendTx.addInput(output) + spendTx } diff --git a/src/test/scala/org/scalacoin/marshallers/script/RawScriptSignatureParserTest.scala b/src/test/scala/org/scalacoin/marshallers/script/RawScriptSignatureParserTest.scala index 90431ddda3..350b5cf5ec 100644 --- a/src/test/scala/org/scalacoin/marshallers/script/RawScriptSignatureParserTest.scala +++ b/src/test/scala/org/scalacoin/marshallers/script/RawScriptSignatureParserTest.scala @@ -1,6 +1,6 @@ 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.util.TestUtil 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) + } }