From 1f3bffe4fbc3f13172097a1478daabdb18c4cb2a Mon Sep 17 00:00:00 2001 From: Tom McCabe Date: Mon, 19 Dec 2016 16:21:53 -0600 Subject: [PATCH] more clean up w/ whitespaces and docs --- .../bitcoins/core/crypto/CryptoParams.scala | 11 +-- .../TransactionSignatureComponent.scala | 7 -- .../TransactionSignatureSerializer.scala | 55 +++----------- .../core/protocol/CompactSizeUInt.scala | 75 ++++--------------- .../protocol/transaction/Transaction.scala | 5 +- .../script/constant/ConstantInterpreter.scala | 6 +- .../core/script/crypto/HashType.scala | 1 - .../serializers/RawBitcoinSerializer.scala | 25 +------ .../RawBitcoinSerializerHelper.scala | 17 +---- .../core/util/BitcoinScriptUtil.scala | 2 +- .../core/protocol/CompactSizeUIntTest.scala | 8 +- .../constant/ConstantInterpreterTest.scala | 54 ++++++++++++- .../core/util/ScriptProgramTestUtil.scala | 32 ++------ .../org/bitcoins/core/util/TestUtil.scala | 7 -- 14 files changed, 101 insertions(+), 204 deletions(-) diff --git a/src/main/scala/org/bitcoins/core/crypto/CryptoParams.scala b/src/main/scala/org/bitcoins/core/crypto/CryptoParams.scala index 75418e16f3..bb20ae0002 100644 --- a/src/main/scala/org/bitcoins/core/crypto/CryptoParams.scala +++ b/src/main/scala/org/bitcoins/core/crypto/CryptoParams.scala @@ -9,20 +9,13 @@ import org.spongycastle.crypto.params.ECDomainParameters */ trait CryptoParams { - /** - * This is the parameters for the elliptic curve bitcoin uses - * @return - */ + /** This is the parameters for the elliptic curve bitcoin uses. */ def params = SECNamedCurves.getByName("secp256k1") - /** - * The curve that bitcoin uses - * @return - */ + /** The curve that bitcoin uses. */ def curve = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()) - /** * This is used for canonicalising the S value of a digital signature. * https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures diff --git a/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureComponent.scala b/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureComponent.scala index 8054280984..2453d33416 100644 --- a/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureComponent.scala +++ b/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureComponent.scala @@ -30,7 +30,6 @@ sealed trait TransactionSignatureComponent { /** Represents the serialization algorithm used to verify/create signatures for Bitcoin */ def sigVersion: SignatureVersion - } /** The [[TransactionSignatureComponent]] used to evaluate the the original Satoshi transaction digest algorithm */ @@ -38,7 +37,6 @@ sealed trait BaseTransactionSignatureComponent extends TransactionSignatureCompo override def sigVersion = SigVersionBase } - /** The [[TransactionSignatureComponent]] used to represent all the components necessarily for BIP143 * [[https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki]] */ @@ -53,11 +51,8 @@ sealed trait WitnessV0TransactionSignatureComponent extends TransactionSignature /** The digest algorithm used to serialized/hash a transaction for signature creation/verification */ override def sigVersion: SignatureVersion = SigVersionWitnessV0 - - } - object TransactionSignatureComponent { private case class BaseTransactionSignatureComponentImpl(transaction : Transaction, inputIndex : UInt32, @@ -82,7 +77,6 @@ object TransactionSignatureComponent { case w: WitnessV0TransactionSignatureComponent => TransactionSignatureComponent(w.transaction,w.inputIndex,scriptPubKey,w.flags,w.amount) } - } object WitnessV0TransactionSignatureComponent { @@ -90,7 +84,6 @@ object WitnessV0TransactionSignatureComponent { scriptPubKey : ScriptPubKey, flags : Seq[ScriptFlag], amount: CurrencyUnit) extends WitnessV0TransactionSignatureComponent - def apply(transaction : WitnessTransaction, inputIndex : UInt32, scriptPubKey : ScriptPubKey, flags : Seq[ScriptFlag], amount: CurrencyUnit) : WitnessV0TransactionSignatureComponent = { WitnessV0TransactionSignatureComponentImpl(transaction,inputIndex, scriptPubKey, flags, amount) diff --git a/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureSerializer.scala b/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureSerializer.scala index e460cee85b..d10c94fc1e 100644 --- a/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureSerializer.scala +++ b/src/main/scala/org/bitcoins/core/crypto/TransactionSignatureSerializer.scala @@ -79,6 +79,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit val txWithInputSigsRemoved = Transaction(spendingTransaction,UpdateTransactionInputs(updatedInputs)) val sigHashBytes = hashType.num.bytes.reverse //check the hash type + //TODO: could probably be optimized w/ HO function hashType match { case _: SIGHASH_NONE => val sigHashNoneTx : Transaction = sigHashNone(txWithInputSigsRemoved,inputIndex) @@ -126,9 +127,6 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit } } - - - /** * Serializes then hashes a transaction for signing * this is an implementation of it's bitcoinj equivalent found here @@ -157,7 +155,6 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit } } - /** Implements the new serialization algorithm defined in BIP141 * [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki]] * [[https://github.com/bitcoin/bitcoin/blob/f8528134fc188abc5c7175a19680206964a8fade/src/script/interpreter.cpp#L1113]] @@ -216,30 +213,18 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit val serialization = serializeForSignature(spendingTx,inputIndex,script,hashType,amount) CryptoUtil.doubleSHA256(serialization) } - /** - * Wrapper function for hashForSignature - * @param txSigComponent this contains the transaction and inputIndex for hashForSignature - * @param hashType - * @return - */ + /** Wrapper function for hashForSignature. */ def hashForSignature(txSigComponent: TransactionSignatureComponent, hashType: HashType): DoubleSha256Digest = { val script = BitcoinScriptUtil.calculateScriptForSigning(txSigComponent,txSigComponent.scriptPubKey.asm) txSigComponent match { case t : BaseTransactionSignatureComponent => hashForSignature(t.transaction,t.inputIndex,script,hashType) - case t : WitnessV0TransactionSignatureComponent => - hashForSignature(t.transaction,t.inputIndex, script, hashType,t.amount) + case w : WitnessV0TransactionSignatureComponent => + hashForSignature(w.transaction,w.inputIndex, script, hashType,w.amount) } } - - - /** - * Sets the input's sequence number to zero EXCEPT for the input at inputIndex - * @param inputs - * @param inputIndex - * @return - */ + /** Sets the input's sequence number to zero EXCEPT for the input at inputIndex. */ private def setSequenceNumbersZero(inputs : Seq[TransactionInput], inputIndex : UInt32) : Seq[TransactionInput] = for { (input,index) <- inputs.zipWithIndex } yield { @@ -247,12 +232,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit else TransactionInput(input,UInt32.zero) } - /** - * Executes the SIGHASH_NONE procedure on a spending transaction for the input specified by inputIndex - * @param spendingTransaction - * @param inputIndex - * @return - */ + /** Executes the [[SIGHASH_NONE]] procedure on a spending transaction for the input specified by inputIndex. */ private def sigHashNone(spendingTransaction : Transaction, inputIndex : UInt32) : Transaction = { //following this implementation from bitcoinj //https://github.com/bitcoinj/bitcoinj/blob/09a2ca64d2134b0dcbb27b1a6eb17dda6087f448/core/src/main/java/org/bitcoinj/core/Transaction.java#L957 @@ -265,7 +245,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit sigHashNoneTx } - /** Executes the SIGHASH_SINGLE procedure on a spending transaction for the input specified by inputIndex */ + /** Executes the [[SIGHASH_SINGLE]] procedure on a spending transaction for the input specified by inputIndex */ private def sigHashSingle(spendingTransaction : Transaction, inputIndex : UInt32) : Transaction = { //following this implementation from bitcoinj //https://github.com/bitcoinj/bitcoinj/blob/09a2ca64d2134b0dcbb27b1a6eb17dda6087f448/core/src/main/java/org/bitcoinj/core/Transaction.java#L964 @@ -287,38 +267,23 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit //create blank inputs with sequence numbers set to zero EXCEPT //the input at the inputIndex val updatedInputs : Seq[TransactionInput] = setSequenceNumbersZero(spendingTxOutputsEmptied.inputs,inputIndex) - val sigHashSingleTx = Transaction(spendingTxOutputsEmptied,UpdateTransactionInputs(updatedInputs)) sigHashSingleTx } - /** - * Executes the SIGHASH_ALL procedure on a spending transaction at inputIndex - * @param spendingTransaction - * @param inputIndex - * @return - */ + /** Executes the [[SIGHASH_ALL]] procedure on a spending transaction at inputIndex. */ private def sigHashAll(spendingTransaction : Transaction, inputIndex : UInt32) : Transaction = { spendingTransaction } - /** - * Executes the SIGHASH_ANYONECANPAY procedure on a spending transaction at inputIndex - * @param spendingTransaction - * @param input - * @return - */ + /** Executes the [[SIGHASH_ANYONECANPAY]] procedure on a spending transaction at inputIndex. */ private def sigHashAnyoneCanPay(spendingTransaction : Transaction, input : TransactionInput) : Transaction = { val txWithEmptyInputs = Transaction.emptyInputs(spendingTransaction) val txWithInputsRemoved = Transaction(txWithEmptyInputs,UpdateTransactionInputs(Seq(input))) txWithInputsRemoved } - /** - * Removes OP_CODESEPARATOR operations then returns the script - * format - * @return - */ + /** Removes [[OP_CODESEPARATOR]] operations then returns the script. */ def removeOpCodeSeparators(script : Seq[ScriptToken]) : Seq[ScriptToken] = { logger.info("Tokens: " + script) if (script.contains(OP_CODESEPARATOR)) { diff --git a/src/main/scala/org/bitcoins/core/protocol/CompactSizeUInt.scala b/src/main/scala/org/bitcoins/core/protocol/CompactSizeUInt.scala index afedb4c0e4..17f468c82a 100644 --- a/src/main/scala/org/bitcoins/core/protocol/CompactSizeUInt.scala +++ b/src/main/scala/org/bitcoins/core/protocol/CompactSizeUInt.scala @@ -15,16 +15,10 @@ import org.bitcoins.core.util.{BitcoinSUtil, Factory} */ trait CompactSizeUInt { - /** - * The number parsed from VarInt - * @return - */ + /** The number parsed from VarInt. */ def num: UInt64 - /** - * The length of the VarInt in bytes - * @return - */ + /** The length of the VarInt in bytes. */ def size: Long def hex = size match { @@ -61,13 +55,9 @@ object CompactSizeUInt extends Factory[CompactSizeUInt] { else if (num.underlying <= UInt32.max.underlying) 5 else 9 } - /** - * This function is responsible for calculating what the compact size unsigned integer is for a + /** This function is responsible for calculating what the compact size unsigned integer is for a * sequence of bytes - * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * @param bytes - * @return - */ + * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers. */ def calculateCompactSizeUInt(bytes : Seq[Byte]) : CompactSizeUInt = { //means we can represent the number with a single byte if (bytes.size <= 252) CompactSizeUInt(UInt64(bytes.size),1) @@ -78,29 +68,17 @@ object CompactSizeUInt extends Factory[CompactSizeUInt] { else CompactSizeUInt(UInt64(bytes.size),9) } - /** - * Responsible for calculating what the compact size uint is for this hex string - * @param hex - * @return - */ + /** Responsible for calculating what the [[CompactSizeUInt]] is for this hex string. */ def calculateCompactSizeUInt(hex : String) : CompactSizeUInt = calculateCompactSizeUInt(BitcoinSUtil.decodeHex(hex)) - /** - * Parses a VarInt from a string of hex characters - * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * @param hex - * @return - */ + /** Parses a VarInt from a string of hex characters + * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers. */ def parseCompactSizeUInt(hex : String) : CompactSizeUInt = parseCompactSizeUInt(BitcoinSUtil.decodeHex(hex)) - /** - * Parses a CompactSizeUInt from a sequence of bytes - * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * @param bytes - * @return - */ + /** Parses a [[CompactSizeUInt]] from a sequence of bytes + * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers. */ def parseCompactSizeUInt(bytes : Seq[Byte]) : CompactSizeUInt = { - require(bytes.size > 0, "Cannot parse a VarInt if the byte array is size 0") + require(bytes.nonEmpty, "Cannot parse a VarInt if the byte array is size 0") //8 bit number if (UInt64(Seq(bytes.head)).underlying < 253) CompactSizeUInt(UInt64(Seq(bytes.head)),1) @@ -112,12 +90,8 @@ object CompactSizeUInt extends Factory[CompactSizeUInt] { else CompactSizeUInt(UInt64(bytes.slice(1,9).reverse),9) } - /** - * Returns the size of a VarInt in the number of bytes - * https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer - * @param byte - * @return - */ + /** Returns the size of a VarInt in the number of bytes + * https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer. */ def parseCompactSizeUIntSize(byte : Byte) : Long = { //8 bit number if (parseLong(byte) < 253) 1 @@ -129,13 +103,8 @@ object CompactSizeUInt extends Factory[CompactSizeUInt] { else 9 } - - /** - * Parses the compact size uint from a script signature - * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * @param script - * @return - */ + /** Parses the [[CompactSizeUInt]] from a [[ScriptSignature]]. + * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers. */ def parseCompactSizeUInt(script : ScriptSignature) : CompactSizeUInt = { if (script.bytes.size <=252 ) { CompactSizeUInt(UInt64(script.bytes.size),1) @@ -147,22 +116,6 @@ object CompactSizeUInt extends Factory[CompactSizeUInt] { else CompactSizeUInt(UInt64(script.bytes.size),9) } - /** - * Parses a compact size uint from a script pubkey - * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * @param scriptPubKey - * @return - */ - def parseCompactSizeUInt(scriptPubKey : ScriptPubKey) : CompactSizeUInt = { - if (scriptPubKey.bytes.size <=252 ) { - CompactSizeUInt(UInt64(scriptPubKey.bytes.size),1) - } else if (scriptPubKey.bytes.size <= 0xffff) { - CompactSizeUInt(UInt64(scriptPubKey.bytes.size),3) - } else if (scriptPubKey.bytes.size <= 0xffffffffL) { - CompactSizeUInt(UInt64(scriptPubKey.bytes.size),5) - } else CompactSizeUInt(UInt64(scriptPubKey.bytes.size),9) - } - private def parseLong(hex : String) : Long = java.lang.Long.parseLong(hex,16) private def parseLong(bytes : List[Byte]) : Long = parseLong(BitcoinSUtil.encodeHex(bytes)) diff --git a/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala b/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala index 2094672aac..6396f13143 100644 --- a/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala +++ b/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala @@ -31,10 +31,7 @@ sealed trait Transaction extends NetworkElement { def lockTime : UInt32 - /** - * Determines if this transaction is a coinbase transaction - * @return - */ + /** Determines if this transaction is a coinbase transaction. */ def isCoinbase : Boolean = inputs.size match { case 1 => inputs.head match { case coinbase : CoinbaseInput => true diff --git a/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala b/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala index f19e27003c..fdb8ee10da 100644 --- a/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala +++ b/src/main/scala/org/bitcoins/core/script/constant/ConstantInterpreter.scala @@ -105,11 +105,9 @@ trait ConstantInterpreter extends BitcoinSLogger { } else { //for the case where we have to push 0 bytes onto the stack, which is technically the empty byte vector program.script(1) match { - case OP_0 | BytesToPushOntoStack.zero | ScriptNumber.zero - | ScriptNumber.negativeZero if (ScriptFlagUtil.requireMinimalData(program.flags)) => - ScriptProgram(program,ScriptErrorMinimalData) case OP_0 | BytesToPushOntoStack.zero | ScriptNumber.zero | ScriptNumber.negativeZero => - ScriptProgram(program, ScriptNumber.zero :: program.stack, program.script.tail.tail) + if (ScriptFlagUtil.requireMinimalData(program.flags)) ScriptProgram(program,ScriptErrorMinimalData) + else ScriptProgram(program, ScriptNumber.zero :: program.stack, program.script.tail.tail) case _ : ScriptToken => pushScriptNumberBytesToStack(ScriptProgram(program, program.script, ScriptProgram.Script)) } diff --git a/src/main/scala/org/bitcoins/core/script/crypto/HashType.scala b/src/main/scala/org/bitcoins/core/script/crypto/HashType.scala index 9a882f7c9f..337374ad59 100644 --- a/src/main/scala/org/bitcoins/core/script/crypto/HashType.scala +++ b/src/main/scala/org/bitcoins/core/script/crypto/HashType.scala @@ -132,7 +132,6 @@ object HashType extends Factory[HashType] { case class SIGHASH_ALL(override val num: Int32) extends HashType { require(HashType.isSIGHASH_ALL(num), "SIGHASH_ALL acts as a 'catch-all' for undefined hashtypes, and has a default " + "value of one. Your input was: " + num + ", which is of hashType: " + HashType(num)) - override def byte = HashType.sigHashAllByte } object SIGHASH_ALL { diff --git a/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializer.scala b/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializer.scala index ba5c8e1519..a35929761a 100644 --- a/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializer.scala +++ b/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializer.scala @@ -8,33 +8,16 @@ import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil} */ trait RawBitcoinSerializer[T] extends RawBitcoinSerializerHelper with BitcoinSLogger { - /** - * Reads a hexadecimal value and transforms it into the native - * scala type T - * @param hex - * @return - */ + /** Reads a hexadecimal value and transforms it into the native scala type T. */ def read(hex : String) : T = read(BitcoinSUtil.decodeHex(hex)) - /** - * Reads in bytes and transforms it into the appropriate scala type T - * @param bytes - * @return - */ + /** Reads in bytes and transforms it into the appropriate scala type T. */ def read(bytes : List[Byte]) : T - /** - * Reads in bytes and transforms it into the appropriate scala type T - * @param bytes - * @return - */ + /** Reads in bytes and transforms it into the appropriate scala type T. */ def read(bytes : Seq[Byte]) : T = read(bytes.toList) - /** - * Takes a type T and writes it into the appropriate hexadecimal serialization for type T - * @param t - * @return - */ + /** Takes a type T and writes it into the appropriate hexadecimal serialization for type T. */ def write(t : T) : String } diff --git a/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializerHelper.scala b/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializerHelper.scala index 6b55ad1d34..d364b2df29 100644 --- a/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializerHelper.scala +++ b/src/main/scala/org/bitcoins/core/serializers/RawBitcoinSerializerHelper.scala @@ -5,15 +5,10 @@ package org.bitcoins.core.serializers */ trait RawBitcoinSerializerHelper { - /** - * Adds the amount padding bytes needed to fix the size of the hex string + /** Adds the amount padding bytes needed to fix the size of the hex string * for instance, vouts are required to be 4 bytes. If the number is just 1 * it will only take 1 byte. We need to pad the byte with an extra 3 bytes so the result is - * 01000000 instead of just 01 - * @param charactersNeeded - * @param hex - * @return - */ + * 01000000 instead of just 01. */ def addPadding(charactersNeeded : Int, hex : String) : String = { val paddingNeeded = charactersNeeded - hex.size val padding = for { i <- 0 until paddingNeeded} yield "0" @@ -21,12 +16,8 @@ trait RawBitcoinSerializerHelper { paddedHex } - /** - * Adds a preceding zero to a hex string. - * Example: if '1' was passed in, it would return the hex string '01' - * @param hex - * @return - */ + /** Adds a preceding zero to a hex string. + * Example: if '1' was passed in, it would return the hex string '01'.*/ def addPrecedingZero(hex : String) = { if (hex.size == 1) "0" + hex else hex } diff --git a/src/main/scala/org/bitcoins/core/util/BitcoinScriptUtil.scala b/src/main/scala/org/bitcoins/core/util/BitcoinScriptUtil.scala index 9ff4dbe742..5d5574ea73 100644 --- a/src/main/scala/org/bitcoins/core/util/BitcoinScriptUtil.scala +++ b/src/main/scala/org/bitcoins/core/util/BitcoinScriptUtil.scala @@ -286,7 +286,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger { //Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. //In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually // present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 - // We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also + // We can compute in advance for our pubkey, embed it in the scriptPubKey, and then also // using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' //signature would still be in the hashed script, and the normal signature would fail." logger.info("Replacing redeemScript in txSignature component") diff --git a/src/test/scala/org/bitcoins/core/protocol/CompactSizeUIntTest.scala b/src/test/scala/org/bitcoins/core/protocol/CompactSizeUIntTest.scala index ed5324ed96..45a29b8284 100644 --- a/src/test/scala/org/bitcoins/core/protocol/CompactSizeUIntTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/CompactSizeUIntTest.scala @@ -70,7 +70,6 @@ class CompactSizeUIntTest extends FlatSpec with MustMatchers { CompactSizeUInt.parseCompactSizeUInt(str3) must be (CompactSizeUInt(UInt64(4294967295L),9)) } - it must "parse a variable length integer the same from a tx input and a script sig" in { CompactSizeUInt.parseCompactSizeUInt(TestUtil.txInput.head.scriptSignature.bytes) must be (TestUtil.txInput.head.scriptSignature.compactSizeUInt) } @@ -94,9 +93,13 @@ class CompactSizeUIntTest extends FlatSpec with MustMatchers { CompactSizeUInt.parseCompactSizeUInt(ScriptSignature(s2)) must be (CompactSizeUInt(UInt64(73085), 5)) } - it must "parse 32 bit number and 64 bit number as compactsizeuints" in { + it must "parse 8 bit, 16 bit, 32 bit number and 64 bit number as compactsizeuints" in { + val bit8 = 1.toByte + val bit16 = 253.toByte val bit32 = 254.toByte val bit64 = 255.toByte + CompactSizeUInt.parseCompactSizeUIntSize(bit8) must be (1) + CompactSizeUInt.parseCompactSizeUIntSize(bit16) must be (3) CompactSizeUInt.parseCompactSizeUIntSize(bit32) must be (5) CompactSizeUInt.parseCompactSizeUIntSize(bit64) must be (9) } @@ -107,5 +110,4 @@ class CompactSizeUIntTest extends FlatSpec with MustMatchers { CompactSizeUInt.parseCompactSizeUInt(emptyBytes) } } - } diff --git a/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala b/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala index 2a854229b3..ed15d0e7a7 100644 --- a/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala +++ b/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala @@ -1,9 +1,11 @@ package org.bitcoins.core.script.constant -import org.bitcoins.core.script.ScriptProgram +import org.bitcoins.core.script.crypto.OP_CHECKMULTISIGVERIFY +import org.bitcoins.core.script.interpreter.ScriptInterpreter +import org.bitcoins.core.script.{ScriptOperation, ScriptProgram} import org.bitcoins.core.script.bitwise.OP_EQUAL -import org.bitcoins.core.script.flag.ScriptFlag -import org.bitcoins.core.script.result.ScriptErrorBadOpCode +import org.bitcoins.core.script.flag.{ScriptVerifyMinimalData, ScriptFlag} +import org.bitcoins.core.script.result.{ScriptErrorMinimalData, ScriptErrorBadOpCode} import org.bitcoins.core.util.{ScriptProgramTestUtil, TestUtil} import org.scalatest.{FlatSpec, MustMatchers} @@ -81,7 +83,6 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn newProgram2.stack must be (List(ScriptNumber.zero)) } - it must "mark a program as invalid if we have do not have enough bytes to be pushed onto the stack by the push operation" in { val stack = List() val script = List(OP_PUSHDATA1,BytesToPushOntoStack(1)) @@ -91,5 +92,50 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn newProgram.error must be (Some(ScriptErrorBadOpCode)) } + it must "fail the require statement if the first op_code in the program's script doesn't match the OP_PUSHDATA we're looking for" in { + val stack1 = List() + val script1 = List(OP_PUSHDATA1,BytesToPushOntoStack(0)) + val program1 = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack1,script1),Seq[ScriptFlag]()) + val stack2 = List() + val script2 = List(OP_PUSHDATA2,BytesToPushOntoStack(0)) + val program2 = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack2,script2),Seq[ScriptFlag]()) + + val stack4 = List() + val script4 = List(OP_PUSHDATA4,BytesToPushOntoStack(0)) + val program4 = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack4,script4),Seq[ScriptFlag]()) + + //purposely call incorrect functions to mismatch opCodes + intercept[IllegalArgumentException] { + opPushData1(program2) + } + + intercept[IllegalArgumentException] { + opPushData2(program4) + } + + intercept[IllegalArgumentException] { + opPushData4(program1) + } + } + + it must "throw exception when parsing bytes need for a push op for a script token other than" + + "BytesToPushOntoStack, ScriptNumber, or ScriptConstant" in { + val stack = List() + val script = List(OP_CHECKMULTISIGVERIFY, ScriptNumber.one, OP_0) + val program = ScriptProgram(TestUtil.testProgram, stack,script) + + intercept[IllegalArgumentException] { + pushScriptNumberBytesToStack(program) + } + } + + it must "return ScriptErrorMinimalData if program contains ScriptVerifyMinimalData flag and 2nd item in script is" + + " zero" in { + val stack = List() + val script = List(OP_PUSHDATA4,ScriptNumber.zero) + val program = ScriptProgram(ScriptProgram(TestUtil.testProgram, stack,script),Seq[ScriptFlag](ScriptVerifyMinimalData)) + val newProgram = ScriptProgramTestUtil.toExecutedScriptProgram(opPushData4(program)) + newProgram.error must be (Some(ScriptErrorMinimalData)) + } } diff --git a/src/test/scala/org/bitcoins/core/util/ScriptProgramTestUtil.scala b/src/test/scala/org/bitcoins/core/util/ScriptProgramTestUtil.scala index 2091f32930..368a97d77a 100644 --- a/src/test/scala/org/bitcoins/core/util/ScriptProgramTestUtil.scala +++ b/src/test/scala/org/bitcoins/core/util/ScriptProgramTestUtil.scala @@ -7,44 +7,28 @@ import org.bitcoins.core.script.{ExecutionInProgressScriptProgram, PreExecutionS */ trait ScriptProgramTestUtil { - /** - * Matches a ScriptProgram to an ExecutedScriptProgram or else throws an exception - * useful for testing purposes - * - * @param p - * @return - */ + /** Matches a [[ScriptProgram]] to an [[ExecutedScriptProgram]] or else throws an exception + * useful for testing purposes.*/ def toExecutedScriptProgram(p : ScriptProgram) : ExecutedScriptProgram = p match { case e : ExecutedScriptProgram => e case _ : PreExecutionScriptProgram | _ : ExecutionInProgressScriptProgram => - throw new RuntimeException("Should be a executed script proram") + throw new RuntimeException("Should be an executed script program") } - /** - * Matches a ScriptProgram to a PreExecutionScriptProgram or else throws an exception - * useful to for test purposes - * - * @param p - * @return - */ + /** Matches a [[ScriptProgram]] to a [[PreExecutionScriptProgram]] or else throws an exception + * useful for test purposes. */ def toPreExecutionScriptProgram(p : ScriptProgram) : PreExecutionScriptProgram = p match { case e : PreExecutionScriptProgram => e case _ : ExecutionInProgressScriptProgram | _ : ExecutedScriptProgram => - throw new RuntimeException("Must be a pre executed scirpt program") + throw new RuntimeException("Must be a pre executed script program") } - /** - * Matches a ScriptProgram to a ExecutionInProgressScriptProgram or else throws an exception - * - * @param p - * @return - */ + /** Matches a [[ScriptProgram]] to a [[ExecutionInProgressScriptProgram]] or else throws an exception.*/ def toExecutionInProgressScriptProgram(p : ScriptProgram) : ExecutionInProgressScriptProgram = p match { case e : ExecutionInProgressScriptProgram => e case _ : PreExecutionScriptProgram | _ : ExecutedScriptProgram => - throw new RuntimeException("Must be a execution in progress script program") + throw new RuntimeException("Must be an execution in progress script program") } } - object ScriptProgramTestUtil extends ScriptProgramTestUtil \ No newline at end of file diff --git a/src/test/scala/org/bitcoins/core/util/TestUtil.scala b/src/test/scala/org/bitcoins/core/util/TestUtil.scala index cc063fb440..296dcf5953 100644 --- a/src/test/scala/org/bitcoins/core/util/TestUtil.scala +++ b/src/test/scala/org/bitcoins/core/util/TestUtil.scala @@ -53,7 +53,6 @@ object TestUtil { ScriptConstant("512102b022902a0fdd71e831c37e4136c2754a59887be0618fb75336d7ab67e2982ff551ae") ) - val p2shOutputScript = "17a914eda8ae08b5c9f973f49543e90a7c292367b3337c87" val p2shOutputScriptNotParsedAsm = "OP_HASH160 eda8ae08b5c9f973f49543e90a7c292367b3337c OP_EQUAL" val p2shOutputScriptAsm = List(OP_HASH160, BytesToPushOntoStack(20), ScriptConstant("eda8ae08b5c9f973f49543e90a7c292367b3337c"), OP_EQUAL) @@ -62,8 +61,6 @@ object TestUtil { val rawP2shInputScriptSigHashSingle = "fdfd0000483045022100dfcfafcea73d83e1c54d444a19fb30d17317f922c19e2ff92dcda65ad09cba24022001e7a805c5672c49b222c5f2f1e67bb01f87215fb69df184e7c16f66c1f87c290347304402204a657ab8358a2edb8fd5ed8a45f846989a43655d2e8f80566b385b8f5a70dab402207362f870ce40f942437d43b6b99343419b14fb18fa69bee801d696a39b3410b8034c695221023927b5cd7facefa7b85d02f73d1e1632b3aaf8dd15d4f9f359e37e39f05611962103d2c0e82979b8aba4591fe39cffbf255b3b9c67b3d24f94de79c5013420c67b802103ec010970aae2e3d75eef0b44eaa31d7a0d13392513cd0614ff1c136b3b1020df53ae" def p2shInputScriptSigHashSingle = ScriptSignature(rawP2shInputScriptSigHashSingle) - - //p2sh script for a 2 of 2 //https://tbtc.blockr.io/api/v1/tx/raw/2f18c646a2b2ee8ee1f295bb5a0f5cc51c5e820a123a14b0c0e170f9777518bb val rawP2shInputScript2Of2 = "da0047304402207d764cb90c9fd84b74d33a47cf3a0ffead9ded98333776becd6acd32c4426dac02203905a0d064e7f53d07793e86136571b6e4f700c1cfb888174e84d78638335b8101483045022100906aaca39f022acd8b7a38fd2f92aca9e9f35cfeaee69a6f13e1d083ae18222602204c9ed96fc6c4de56fd85c679fc59c16ee1ccc80c42563b86174e1a506fc007c8014752210369d26ebd086523384a0f89f293d4c327a65fa73332d8efd1097cb35231295b832102480863e5c4a4e9763f5380c44fcfe6a3b7787397076cf9ea1049303a9d34f72152ae" @@ -100,7 +97,6 @@ object TestUtil { "02c02b00000000000017a914b0b06365c482eb4eabe6e0630029fb8328ea098487e81c0000000000001976a914938da2b50fd6d8acdfa20e30df0e7d8092f0bc7588ac00000000" def transaction = Transaction(rawTransaction) - //txid cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6 val rawTxInput = "01" + "85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000" + @@ -151,15 +147,12 @@ object TestUtil { def testProgramExecutionInProgress = ScriptProgram.toExecutionInProgress(testProgramPreExecution) - - val rawP2PKScriptSig = "4847304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001" def p2pkScriptSig = ScriptSignature(rawP2PKScriptSig) val rawP2PKScriptPubKey = "43410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" def p2pkScriptPubKey = ScriptPubKey(rawP2PKScriptPubKey) - /** * This is a script sig that doesn't have a signature strictly der encoded * Zero-length R is correctly encoded