mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 06:57:51 +01:00
merging in segwit branch changes
This commit is contained in:
commit
9012c9acc7
13 changed files with 100 additions and 201 deletions
|
@ -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
|
||||
|
|
|
@ -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]]
|
||||
*/
|
||||
|
@ -54,7 +52,6 @@ sealed trait WitnessV0TransactionSignatureComponent extends TransactionSignature
|
|||
|
||||
}
|
||||
|
||||
|
||||
object TransactionSignatureComponent {
|
||||
|
||||
private case class BaseTransactionSignatureComponentImpl(transaction : Transaction, inputIndex : UInt32,
|
||||
|
@ -85,7 +82,6 @@ object TransactionSignatureComponent {
|
|||
case w: WitnessV0TransactionSignatureComponent =>
|
||||
TransactionSignatureComponent(w.transaction,w.inputIndex,scriptPubKey,w.flags,w.amount,w.sigVersion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object WitnessV0TransactionSignatureComponent {
|
||||
|
@ -93,7 +89,6 @@ object WitnessV0TransactionSignatureComponent {
|
|||
scriptPubKey : ScriptPubKey, flags : Seq[ScriptFlag],
|
||||
amount: CurrencyUnit, sigVersion: SignatureVersion) extends WitnessV0TransactionSignatureComponent
|
||||
|
||||
|
||||
def apply(transaction : Transaction, inputIndex : UInt32, scriptPubKey : ScriptPubKey,
|
||||
flags : Seq[ScriptFlag], amount: CurrencyUnit, sigVersion: SignatureVersion) : WitnessV0TransactionSignatureComponent = {
|
||||
WitnessV0TransactionSignatureComponentImpl(transaction,inputIndex, scriptPubKey, flags, amount,sigVersion)
|
||||
|
|
|
@ -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]]
|
||||
|
@ -222,30 +219,18 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
|
|||
val serialization = serializeForSignature(spendingTx,inputIndex,script,hashType,amount,sigVersion)
|
||||
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,t.sigVersion)
|
||||
case w : WitnessV0TransactionSignatureComponent =>
|
||||
hashForSignature(w.transaction,w.inputIndex, script, hashType,w.amount, w.sigVersion)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
@ -253,12 +238,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
|
||||
|
@ -271,7 +251,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
|
||||
|
@ -293,38 +273,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)) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue