Merge pull request #6 from TomMcCabe/refactor_number_system

Refactor number system
This commit is contained in:
Chris Stewart 2016-07-12 10:21:18 -05:00 committed by GitHub
commit 8cb8bcc0f2
44 changed files with 457 additions and 330 deletions

View file

@ -23,7 +23,6 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
* Checks the signature of a scriptSig in the spending transaction against the
* given scriptPubKey & explicitly given public key
* This is useful for instances of non standard scriptSigs
*
* @param txSignatureComponent the relevant transaction information for signature checking
* @param script the current script state inside the interpreter - this is needed in the case of OP_CODESEPARATORS
* @param pubKey the public key the signature is being checked against
@ -69,7 +68,7 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
val sigsRemoved = removeSignatureFromScript(signature,script)
sigsRemoved
}
val hashTypeByte = if (signature.bytes.size > 0) signature.bytes.last else 0x00.toByte
val hashTypeByte = if (signature.bytes.nonEmpty) signature.bytes.last else 0x00.toByte
val hashType = HashTypeFactory.fromByte(hashTypeByte)
val hashForSignature = TransactionSignatureSerializer.hashForSignature(txSignatureComponent.transaction,
txSignatureComponent.inputIndex,
@ -84,7 +83,6 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
* This is a helper function to check digital signatures against public keys
* if the signature does not match this public key, check it against the next
* public key in the sequence
*
* @param txSignatureComponent the tx signature component that contains all relevant transaction information
* @param script the script state this is needed in case there is an OP_CODESEPARATOR inside the script
* @param sigs the signatures that are being checked for validity
@ -138,8 +136,7 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
/**
* Removes the given digtial signature from the list of script tokens if it exists
*
* Removes the given digital signature from the list of script tokens if it exists
* @param signature
* @param script
* @return
@ -157,7 +154,6 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
/**
* Removes the list of digital signatures from the list of script tokens
*
* @param sigs
* @param script
* @return

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.crypto
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.ScriptPubKey
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.script.flag.ScriptFlag
@ -23,14 +24,14 @@ trait TransactionSignatureComponent {
*
* @return
*/
def inputIndex : Int
def inputIndex : UInt32
/**
* The script signature being checked
*
* @return
*/
def scriptSignature = transaction.inputs(inputIndex).scriptSignature
def scriptSignature = transaction.inputs(inputIndex.toInt).scriptSignature
/**
* The scriptPubKey for which the input is being checked against
*

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.crypto
import org.bitcoins.core.currency.CurrencyUnits
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.RawBitcoinSerializerHelper
import org.bitcoins.core.serializers.transaction.RawTransactionOutputParser
import org.bitcoins.core.protocol.script._
@ -38,7 +39,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param hashType
* @return
*/
def serializeForSignature(spendingTransaction : Transaction, inputIndex : Int, script : Seq[ScriptToken], hashType : HashType) : Seq[Byte] = {
def serializeForSignature(spendingTransaction : Transaction, inputIndex : UInt32, script : Seq[ScriptToken], hashType : HashType) : Seq[Byte] = {
logger.debug("Serializing for signature")
logger.debug("Script: " + script)
// Clear input scripts in preparation for signing. If we're signing a fresh
@ -63,7 +64,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
logger.info("After Bitcoin-S Script to be connected: " + scriptWithOpCodeSeparatorsRemoved)
val inputToSign = inputSigsRemoved(inputIndex)
val inputToSign = inputSigsRemoved(inputIndex.toInt)
// Set the input to the script of its output. Bitcoin Core does this but the step has no obvious purpose as
// the signature covers the hash of the prevout transaction which obviously includes the output script
@ -74,7 +75,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
val updatedInputs = for {
(input,index) <- inputSigsRemoved.zipWithIndex
} yield {
if (index == inputIndex) inputWithConnectedScript
if (UInt32(index) == inputIndex) inputWithConnectedScript
else input
}
@ -90,7 +91,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
sigHashNoneTx.bytes ++ sigHashBytes
case SIGHASH_SINGLE =>
if (inputIndex >= spendingTransaction.outputs.size) {
if (inputIndex >= UInt32(spendingTransaction.outputs.size)) {
// comment copied from bitcoinj
// The input index is beyond the number of outputs, it's a buggy signature made by a broken
// Bitcoin implementation. Bitcoin Core also contains a bug in handling this case:
@ -142,13 +143,13 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param hashType
* @return
*/
def hashForSignature(spendingTransaction : Transaction, inputIndex : Int, script : Seq[ScriptToken], hashType : HashType) : DoubleSha256Digest = {
def hashForSignature(spendingTransaction : Transaction, inputIndex : UInt32, script : Seq[ScriptToken], hashType : HashType) : DoubleSha256Digest = {
//these first two checks are in accordance with behavior in bitcoin core
//https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1112-L1123
if (inputIndex >= spendingTransaction.inputs.size) {
if (inputIndex >= UInt32(spendingTransaction.inputs.size)) {
logger.warn("Our inputIndex is out of the range of the inputs in the spending transaction")
errorHash
} else if(hashType == SIGHASH_SINGLE && inputIndex >= spendingTransaction.outputs.size) {
} else if(hashType == SIGHASH_SINGLE && inputIndex >= UInt32(spendingTransaction.outputs.size)) {
logger.warn("When we have a SIGHASH_SINGLE we cannot have more inputs than outputs")
errorHash
} else {
@ -168,12 +169,12 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param inputIndex
* @return
*/
private def setSequenceNumbersZero(inputs : Seq[TransactionInput], inputIndex : Int) : Seq[TransactionInput] = {
private def setSequenceNumbersZero(inputs : Seq[TransactionInput], inputIndex : UInt32) : Seq[TransactionInput] = {
for {
(input,index) <- inputs.zipWithIndex
} yield {
if (index == inputIndex) input
else TransactionInput(input,0)
if (UInt32(index) == inputIndex) input
else TransactionInput(input,UInt32.zero)
}
}
@ -185,11 +186,11 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param inputIndex
* @return
*/
private def updateInputIndex(inputs : Seq[TransactionInput], updatedInput : TransactionInput, inputIndex : Int) : Seq[TransactionInput] = {
private def updateInputIndex(inputs : Seq[TransactionInput], updatedInput : TransactionInput, inputIndex : UInt32) : Seq[TransactionInput] = {
for {
(input,index) <- inputs.zipWithIndex
} yield {
if (inputIndex == index) updatedInput
if (inputIndex == UInt32(index)) updatedInput
else input
}
}
@ -201,7 +202,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param inputIndex
* @return
*/
private def sigHashNone(spendingTransaction : Transaction, inputIndex : Int) : Transaction = {
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
//means that no outputs are signed at all
@ -220,7 +221,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param inputIndex
* @return
*/
private def sigHashSingle(spendingTransaction : Transaction, inputIndex : Int) : Transaction = {
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
// In SIGHASH_SINGLE the outputs after the matching input index are deleted, and the outputs before
@ -228,11 +229,11 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
val updatedOutputsOpt : Seq[Option[TransactionOutput]] = for {
(output,index) <- spendingTransaction.outputs.zipWithIndex
} yield {
if (index < inputIndex) {
if (UInt32(index) < inputIndex) {
logger.debug("Updating tx output to null in bitcoin core")
Some(EmptyTransactionOutput)
}
else if (index == inputIndex) Some(output)
else if (UInt32(index) == inputIndex) Some(output)
else None
}
val updatedOutputs : Seq[TransactionOutput] = updatedOutputsOpt.flatten
@ -253,7 +254,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
* @param inputIndex
* @return
*/
private def sigHashAll(spendingTransaction : Transaction, inputIndex : Int) : Transaction = {
private def sigHashAll(spendingTransaction : Transaction, inputIndex : UInt32) : Transaction = {
spendingTransaction
}

View file

@ -15,6 +15,7 @@ import scala.util.{Failure, Success, Try}
sealed trait Number extends NetworkElement with BitcoinSLogger {
type A
def underlying : A
def toInt : Int
}
/**
@ -77,6 +78,15 @@ sealed trait UInt32 extends UnsignedNumber with NumberOperations[UInt32] {
override def <= (num : UInt32): Boolean = underlying <= num.underlying
def | (num : UInt32) : UInt32 = UInt32(underlying | num.underlying)
override def hex = BitcoinSUtil.encodeHex(underlying).slice(8,16)
override def toInt = {
require(underlying <= Int.MaxValue, "Overflow error when casting " + this + " to an integer.")
underlying.toInt
}
/**
* Checks the result of the arithmetic operation to see if an error occurred
* if an error does occur throw it, else return the [[UInt32]]
@ -122,6 +132,11 @@ sealed trait UInt64 extends UnsignedNumber with NumberOperations[UInt64] {
override def <= (num : UInt64): Boolean = underlying <= num.underlying
override def toInt = {
require(underlying <= Int.MaxValue, "Overflow error when casting " + this + " to an integer.")
underlying.toInt
}
/**
* Checks the result of the arithmetic operation to see if an error occurred
* if an error does occur throw it, else return the [[UInt64]]
@ -183,6 +198,12 @@ sealed trait Int32 extends SignedNumber with NumberOperations[Int32] {
override def <= (num : Int32): Boolean = underlying <= num.underlying
override def toInt = {
if (underlying > Int.MaxValue) throw new IllegalArgumentException("Overflow error when casting " + this +
" to an integer.")
else underlying.toInt
}
/**
* Checks the result of the arithmetic operation to see if an error occurred
* if an error does occur throw it, else return the [[Int32]]
@ -225,6 +246,12 @@ sealed trait Int64 extends SignedNumber with NumberOperations[Int64] {
override def <= (num : Int64): Boolean = underlying <= num.underlying
override def toInt = {
require(underlying <= Int.MaxValue, "Overflow error when casting " + this + " to an integer.")
underlying.toInt
}
/**
* Checks the result of the arithmetic operation to see if an error occurred
* if an error does occur throw it, else return the [[Int64]]
@ -267,7 +294,7 @@ trait BaseNumbers[T] {
}
object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers[UInt32] {
private case class UInt32Impl(underlying : Long, hex : String) extends UInt32 {
private case class UInt32Impl(underlying : Long) extends UInt32 {
require(underlying >= 0, "We cannot have a negative number in an unsigned number, got: " + underlying)
require(underlying <= 4294967295L, "We cannot have a number larger than 2^32 -1 in UInt32, got: " + underlying)
}
@ -283,10 +310,10 @@ object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers[UInt3
val individualByteValues = for {
(byte,index) <- bytes.reverse.zipWithIndex
} yield NumberUtil.calculateUnsignedNumberFromByte(index, byte)
UInt32Impl(individualByteValues.sum.toLong, BitcoinSUtil.encodeHex(bytes))
UInt32Impl(individualByteValues.sum.toLong)
}
def apply(long : Long) : UInt32 = UInt32Impl(long, BitcoinSUtil.encodeHex(long).slice(8,16))
def apply(long : Long) : UInt32 = UInt32Impl(long)
}

View file

@ -53,6 +53,11 @@ object Block extends Factory[Block] {
BlockImpl(blockHeader, txCount, transactions)
}
def apply(blockHeader : BlockHeader, transactions : Seq[Transaction]) : Block = {
val txCount = CompactSizeUInt(transactions.size)
Block(blockHeader, txCount, transactions)
}
def fromBytes(bytes : Seq[Byte]) : Block = RawBlockSerializer.read(bytes)
}

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.protocol.blockchain
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.blockchain.RawBlockHeaderSerializer
import org.bitcoins.core.util.{BitcoinSUtil, CryptoUtil, BitcoinSLogger, Factory}
@ -29,7 +30,7 @@ sealed trait BlockHeader extends NetworkElement with BitcoinSLogger {
*
* @return the version number for this block
*/
def version : Long
def version : UInt32
/**
@ -59,7 +60,7 @@ sealed trait BlockHeader extends NetworkElement with BitcoinSLogger {
*
* @return the time when the miner started solving the block
*/
def time : Long
def time : UInt32
/**
* An encoded version of the target threshold this blocks header hash must be less than or equal to.
@ -68,7 +69,7 @@ sealed trait BlockHeader extends NetworkElement with BitcoinSLogger {
*
* @return
*/
def nBits : Long
def nBits : UInt32
/**
* An arbitrary number miners change to modify the header hash in order to produce a hash below the target threshold.
@ -77,10 +78,11 @@ sealed trait BlockHeader extends NetworkElement with BitcoinSLogger {
*
* @return the nonce used to try and solve a block
*/
def nonce : Long
def nonce : UInt32
/**
* Returns the block's hash
*
* @return
*/
def hash : DoubleSha256Digest = CryptoUtil.doubleSHA256(bytes)
@ -95,11 +97,11 @@ sealed trait BlockHeader extends NetworkElement with BitcoinSLogger {
*/
object BlockHeader extends Factory[BlockHeader] {
private sealed case class BlockHeaderImpl(version : Long, previousBlockHash : DoubleSha256Digest,
merkleRootHash : DoubleSha256Digest, time : Long, nBits : Long, nonce : Long) extends BlockHeader
private sealed case class BlockHeaderImpl(version : UInt32, previousBlockHash : DoubleSha256Digest,
merkleRootHash : DoubleSha256Digest, time : UInt32, nBits : UInt32, nonce : UInt32) extends BlockHeader
def apply(version : Long, previousBlockHash : DoubleSha256Digest, merkleRootHash : DoubleSha256Digest,
time : Long, nBits : Long, nonce : Long) : BlockHeader = {
def apply(version : UInt32, previousBlockHash : DoubleSha256Digest, merkleRootHash : DoubleSha256Digest,
time : UInt32, nBits : UInt32, nonce : UInt32) : BlockHeader = {
BlockHeaderImpl(version,previousBlockHash,merkleRootHash,time,nBits,nonce)
}

View file

@ -3,7 +3,7 @@ package org.bitcoins.core.protocol.blockchain
import org.bitcoins.core.consensus.Merkle
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.currency.{CurrencyUnit, Satoshis}
import org.bitcoins.core.number.Int64
import org.bitcoins.core.number.{UInt32, Int64}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptSignature}
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionConstants, TransactionInput, TransactionOutput}
@ -71,7 +71,7 @@ sealed trait ChainParams {
* @param amount the block reward for the gensis block (50 BTC in Bitcoin)
* @return the newly minted genesis block
*/
def createGenesisBlock(time : Long, nonce : Long, nBits : Long, version : Int, amount : CurrencyUnit) : Block = {
def createGenesisBlock(time : UInt32, nonce : UInt32, nBits : UInt32, version : UInt32, amount : CurrencyUnit) : Block = {
val timestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
val asm = Seq(BytesToPushOntoStack(65), ScriptConstant("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"), OP_CHECKSIG)
val genesisOutputScript = ScriptPubKey.fromAsm(asm)
@ -88,8 +88,8 @@ sealed trait ChainParams {
* @param amount the block reward for the genesis block (50 BTC in Bitcoin)
* @return the newly minted genesis block
*/
def createGenesisBlock(timestamp : String, scriptPubKey : ScriptPubKey, time : Long, nonce : Long, nBits : Long,
version : Int, amount : CurrencyUnit) : Block = {
def createGenesisBlock(timestamp : String, scriptPubKey : ScriptPubKey, time : UInt32, nonce : UInt32, nBits : UInt32,
version : UInt32, amount : CurrencyUnit) : Block = {
val timestampHex = timestamp.toCharArray.map(_.toByte)
//see https://bitcoin.stackexchange.com/questions/13122/scriptsig-coinbase-structure-of-the-genesis-block
@ -115,7 +115,7 @@ object MainNetChainParams extends ChainParams {
override def networkId = "main"
override def genesisBlock = createGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, Satoshis(Int64(5000000000L)))
override def genesisBlock = createGenesisBlock(UInt32(1231006505), UInt32(2083236893), UInt32(0x1d00ffff), UInt32.one, Satoshis(Int64(5000000000L)))
override def requireStandardTransaction = true
@ -138,7 +138,7 @@ object TestNetChainParams extends ChainParams {
override def networkId = "test"
override def genesisBlock = createGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, Satoshis(Int64(5000000000L)))
override def genesisBlock = createGenesisBlock(UInt32(1296688602), UInt32(414098458), UInt32(0x1d00ffff), UInt32.one, Satoshis(Int64(5000000000L)))
override def requireStandardTransaction = true
@ -160,7 +160,7 @@ object TestNetChainParams extends ChainParams {
object RegTestNetChainParams extends ChainParams {
override def networkId = "regtest"
override def genesisBlock = createGenesisBlock(1296688602, 2, 0x207fffff, 1, Satoshis(Int64(5000000000L)))
override def genesisBlock = createGenesisBlock(UInt32(1296688602), UInt32(2), UInt32(0x207fffff), UInt32.one, Satoshis(Int64(5000000000L)))
override def requireStandardTransaction = TestNetChainParams.requireStandardTransaction
/**

View file

@ -73,7 +73,7 @@ trait MultiSignatureScriptPubKey extends ScriptPubKey {
//magic number 2 represents the maxSig operation and the OP_CHECKMULTISIG operation at the end of the asm
val numSigsRequired = asmWithoutPushOps(opCheckMultiSigIndex - maxSigs.toInt - 2)
numSigsRequired match {
case x : ScriptNumber => x.num
case x : ScriptNumber => x.underlying
case _ => throw new RuntimeException("The first element of the multisignature pubkey must be a script number operation\n" +
"operation: " + numSigsRequired +
"\nscriptPubKey: " + this)
@ -91,7 +91,7 @@ trait MultiSignatureScriptPubKey extends ScriptPubKey {
0.toLong
} else {
asm(checkMultiSigIndex - 1) match {
case x : ScriptNumber => x.num
case x : ScriptNumber => x.underlying
case _ => throw new RuntimeException("The element preceding a OP_CHECKMULTISIG operation in a multisignature pubkey must be a script number operation")
}
}

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.transaction.RawTransactionParser
import org.bitcoins.core.util.{Factory, BitcoinSUtil, CryptoUtil}
@ -14,6 +15,7 @@ sealed trait Transaction extends NetworkElement {
/**
* The sha256(sha256(tx)) of this transaction
* Note that this is the big endian encoding of the hash NOT the little endian encoding displayed on block explorers
*
* @return
*/
def txId : DoubleSha256Digest = CryptoUtil.doubleSHA256(bytes)
@ -23,7 +25,7 @@ sealed trait Transaction extends NetworkElement {
*
* @return
*/
def version : Long
def version : UInt32
/**
* The inputs for this transaction
@ -44,7 +46,7 @@ sealed trait Transaction extends NetworkElement {
*
* @return
*/
def lockTime : Long
def lockTime : UInt32
override def hex = RawTransactionParser.write(this)
@ -73,8 +75,8 @@ case object EmptyTransaction extends Transaction {
object Transaction extends Factory[Transaction] {
private sealed case class TransactionImpl(version : Long, inputs : Seq[TransactionInput],
outputs : Seq[TransactionOutput], lockTime : Long) extends Transaction
private sealed case class TransactionImpl(version : UInt32, inputs : Seq[TransactionInput],
outputs : Seq[TransactionOutput], lockTime : UInt32) extends Transaction
/**
* Updates a transaction outputs
*
@ -102,7 +104,7 @@ object Transaction extends Factory[Transaction] {
* @param lockTime
* @return
*/
def factory(oldTx : Transaction, lockTime : Long) : Transaction = {
def factory(oldTx : Transaction, lockTime : UInt32) : Transaction = {
TransactionImpl(oldTx.version,oldTx.inputs,oldTx.outputs,lockTime)
}
@ -126,12 +128,12 @@ object Transaction extends Factory[Transaction] {
def fromBytes(bytes : Seq[Byte]) : Transaction = RawTransactionParser.read(bytes)
def apply(bytes : Array[Byte]) : Transaction = factory(bytes)
def apply(oldTx : Transaction, lockTime : Long) : Transaction = factory(oldTx,lockTime)
def apply(oldTx : Transaction, lockTime : UInt32) : Transaction = factory(oldTx,lockTime)
def apply(oldTx : Transaction, updatedInputs : UpdateTransactionInputs) : Transaction = factory(oldTx, updatedInputs)
def apply(oldTx : Transaction, updatedOutputs : UpdateTransactionOutputs) : Transaction = factory(oldTx, updatedOutputs)
def apply(version : Long, inputs : Seq[TransactionInput],
outputs : Seq[TransactionOutput], lockTime : Long) : Transaction = {
def apply(version : UInt32, inputs : Seq[TransactionInput],
outputs : Seq[TransactionOutput], lockTime : UInt32) : Transaction = {
TransactionImpl(version,inputs,outputs,lockTime)
}
}

View file

@ -1,13 +1,15 @@
package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.number.UInt32
/**
* Created by chris on 2/12/16.
*/
trait TransactionConstants {
lazy val version = 1
lazy val lockTime = 0
lazy val sequence = 4294967295L
lazy val version = UInt32.one
lazy val lockTime = UInt32.zero
lazy val sequence = UInt32(4294967295L)
/**
* If bit (1 << 31) of the sequence number is set,
@ -16,20 +18,20 @@ trait TransactionConstants {
*
* @return the mask that ben used with a bitwise and to indicate if the sequence number has any meaning
*/
def locktimeDisabledFlag = 1L << 31
def locktimeDisabledFlag = UInt32(1L << 31)
/**
* If a transaction's input's sequence number encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field.
*/
def sequenceLockTimeMask = 0x0000ffff
def sequenceLockTimeMask = UInt32(0x0000ffff)
/**
* If the transaction input sequence number encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
* otherwise it specifies blocks with a granularity of 1.
*/
def sequenceLockTimeTypeFlag = (1L << 22)
def sequenceLockTimeTypeFlag = UInt32(1L << 22)
/**
@ -38,7 +40,7 @@ trait TransactionConstants {
*
* @return
*/
def locktimeThreshold = 500000000
def locktimeThreshold = UInt32(500000000)
}
object TransactionConstants extends TransactionConstants

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.transaction.RawTransactionInputParser
import org.bitcoins.core.protocol.{CompactSizeUInt, NetworkElement}
import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptSignature}
@ -14,7 +15,7 @@ sealed trait TransactionInput extends NetworkElement {
def previousOutput : TransactionOutPoint
def scriptSignature : ScriptSignature
def sequence : Long
def sequence : UInt32
def scriptSigCompactSizeUInt : CompactSizeUInt = CompactSizeUInt.calculateCompactSizeUInt(scriptSignature.bytes)
@ -49,7 +50,7 @@ object TransactionInput extends Factory[TransactionInput] {
apply(oldInput.previousOutput,scriptSig,oldInput.sequence)
}
private sealed case class TransactionInputImpl(previousOutput : TransactionOutPoint,
scriptSignature : ScriptSignature, sequence : Long) extends TransactionInput
scriptSignature : ScriptSignature, sequence : UInt32) extends TransactionInput
private sealed case class CoinbaseInputImpl(
scriptSignature : ScriptSignature) extends CoinbaseInput
@ -59,12 +60,13 @@ object TransactionInput extends Factory[TransactionInput] {
factory(oldInput,scriptSig)
}
private def factory(oldInput : TransactionInput,sequenceNumber : Long) : TransactionInput = {
private def factory(oldInput : TransactionInput,sequenceNumber : UInt32) : TransactionInput = {
TransactionInputImpl(oldInput.previousOutput, oldInput.scriptSignature,sequenceNumber)
}
/**
* Creates a transaction input from a given output and the output's transaction
*
* @param oldInput
* @param output
* @param outputsTransaction
@ -80,7 +82,7 @@ object TransactionInput extends Factory[TransactionInput] {
}
private def factory(outPoint : TransactionOutPoint, scriptSignature : ScriptSignature, sequenceNumber : Long) : TransactionInput = {
private def factory(outPoint : TransactionOutPoint, scriptSignature : ScriptSignature, sequenceNumber : UInt32) : TransactionInput = {
outPoint match {
case EmptyTransactionOutPoint => CoinbaseInputImpl(scriptSignature)
case _ : TransactionOutPoint => TransactionInputImpl(outPoint, scriptSignature, sequenceNumber)
@ -105,16 +107,17 @@ object TransactionInput extends Factory[TransactionInput] {
def apply(oldInput : TransactionInput, scriptPubKey: ScriptPubKey) : TransactionInput = factory(oldInput, scriptPubKey)
def apply(oldInput : TransactionInput,sequenceNumber : Long) : TransactionInput = factory(oldInput, sequenceNumber)
def apply(oldInput : TransactionInput,sequenceNumber : UInt32) : TransactionInput = factory(oldInput, sequenceNumber)
def apply(oldInput : TransactionInput,output : TransactionOutput, outputsTransaction : Transaction) : TransactionInput = factory(oldInput,output,outputsTransaction)
def apply(oldInput : TransactionInput, outPoint: TransactionOutPoint) : TransactionInput = factory(oldInput,outPoint)
def apply(outPoint : TransactionOutPoint, scriptSignature : ScriptSignature, sequenceNumber : Long) : TransactionInput = factory(outPoint,scriptSignature,sequenceNumber)
def apply(outPoint : TransactionOutPoint, scriptSignature : ScriptSignature, sequenceNumber : UInt32) : TransactionInput = factory(outPoint,scriptSignature,sequenceNumber)
/**
* Creates a coinbase input - coinbase inputs always have an empty outpoint
*
* @param scriptSignature this can contain anything, miners use this to signify support for various protocol BIPs
* @return the coinbase input
*/

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.transaction.RawTransactionOutPointParser
import org.bitcoins.core.util.{BitcoinSUtil, Factory}
@ -21,7 +22,7 @@ sealed trait TransactionOutPoint extends NetworkElement {
*
* @return
*/
def vout : Int
def vout : UInt32
//https://bitcoin.org/en/developer-reference#outpoint
override def size = 36
@ -29,15 +30,21 @@ sealed trait TransactionOutPoint extends NetworkElement {
override def hex = RawTransactionOutPointParser.write(this)
}
/**
* UInt32s cannot hold negative numbers, but sometimes the Bitcoin Protocol requires the vout to be -1, which is serialized
* as "0xFFFFFFFF".
* https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/primitives/transaction.h
* http://stackoverflow.com/questions/2711522/what-happens-if-i-assign-a-negative-value-to-an-unsigned-variable
*/
case object EmptyTransactionOutPoint extends TransactionOutPoint {
def txId = DoubleSha256Digest(
BitcoinSUtil.decodeHex("0000000000000000000000000000000000000000000000000000000000000000"))
def vout = -1
def vout = UInt32("ffffffff")
}
object TransactionOutPoint extends Factory[TransactionOutPoint] {
private sealed case class TransactionOutPointImpl(txId : DoubleSha256Digest, vout : Int) extends TransactionOutPoint
private sealed case class TransactionOutPointImpl(txId : DoubleSha256Digest, vout : UInt32) extends TransactionOutPoint
/**
* Creates a transaction outpoint from a TransactionOutput & it's parent transaction
*
@ -45,12 +52,12 @@ object TransactionOutPoint extends Factory[TransactionOutPoint] {
* @return
*/
private def factory(output : TransactionOutput, parentTransaction : Transaction) : TransactionOutPoint = {
val indexOfOutput = parentTransaction.outputs.indexOf(output)
if (indexOfOutput == -1) throw new RuntimeException("This output is not contained in the parent transaction")
val indexOfOutput = UInt32(parentTransaction.outputs.indexOf(output))
if (indexOfOutput.toInt == (-1)) throw new RuntimeException("This output is not contained in the parent transaction")
else factory(parentTransaction.txId,indexOfOutput)
}
private def factory(txId : DoubleSha256Digest, index : Int) = {
private def factory(txId : DoubleSha256Digest, index : UInt32) = {
if (txId == EmptyTransactionOutPoint.txId && index == EmptyTransactionOutPoint.vout) {
EmptyTransactionOutPoint
} else TransactionOutPointImpl(txId, index)
@ -60,6 +67,6 @@ object TransactionOutPoint extends Factory[TransactionOutPoint] {
def apply(output : TransactionOutput,parentTransaction : Transaction) : TransactionOutPoint = factory(output,parentTransaction)
def apply(txId : DoubleSha256Digest, index: Int) : TransactionOutPoint = factory(txId,index)
def apply(txId : DoubleSha256Digest, index: UInt32) : TransactionOutPoint = factory(txId,index)
}

View file

@ -2,6 +2,7 @@ package org.bitcoins.core.script
import org.bitcoins.core.crypto.{TransactionSignatureComponentFactory, TransactionSignatureComponent}
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.{ScriptSignature, ScriptPubKey}
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.script.constant._
@ -338,9 +339,9 @@ object ScriptProgram {
* @param flags the flags which we are enforcing inside of the script interpreter
* @return the script program representing all of this information
*/
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : Int,
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32,
flags : Seq[ScriptFlag]) : PreExecutionScriptProgram = {
val script = transaction.inputs(inputIndex).scriptSignature.asm
val script = transaction.inputs(inputIndex.toInt).scriptSignature.asm
apply(transaction,scriptPubKey,inputIndex,script.toList,flags)
}
@ -355,7 +356,7 @@ object ScriptProgram {
* @param flags the flags which we are enforcing inside of the script interpreter
* @return the script program representing all of this information
*/
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : Int, script : Seq[ScriptToken],
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, script : Seq[ScriptToken],
flags : Seq[ScriptFlag]) : PreExecutionScriptProgram = {
val txSignatureComponent = TransactionSignatureComponentFactory.factory(transaction,inputIndex,scriptPubKey,flags)
PreExecutionScriptProgramImpl(txSignatureComponent,List(),script.toList,script.toList,List(),flags)
@ -374,7 +375,7 @@ object ScriptProgram {
* @param script the script that we need to execute
* @param flags the flags which we are enforcing inside of the script interpeter
*/
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : Int, stack : Seq[ScriptToken],
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, stack : Seq[ScriptToken],
script : Seq[ScriptToken], flags : Seq[ScriptFlag]) : ScriptProgram = {
val program = factory(transaction,scriptPubKey,inputIndex,script,flags)
apply(program,stack,Stack)
@ -414,13 +415,13 @@ object ScriptProgram {
def apply(oldProgram : ScriptProgram, stack : Seq[ScriptToken], script : Seq[ScriptToken], altStack : Seq[ScriptToken],
updateIndicator: UpdateIndicator) : ScriptProgram = factory(oldProgram, stack, script, altStack)
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : Int,
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32,
flags : Seq[ScriptFlag]) : PreExecutionScriptProgram = factory(transaction, scriptPubKey, inputIndex, flags)
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : Int, script : Seq[ScriptToken],
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, script : Seq[ScriptToken],
flags : Seq[ScriptFlag]) : PreExecutionScriptProgram = factory(transaction, scriptPubKey, inputIndex, script, flags)
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : Int, stack : Seq[ScriptToken],
def apply(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32, stack : Seq[ScriptToken],
script : Seq[ScriptToken], flags : Seq[ScriptFlag]) : ScriptProgram = factory(transaction, scriptPubKey, inputIndex, stack, script, flags)
def apply(txSignatureComponent : TransactionSignatureComponent, stack : Seq[ScriptToken], script : Seq[ScriptToken]) : ScriptProgram =

View file

@ -70,7 +70,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
require(program.script.headOption.isDefined && program.script.head == OP_ABS, "Script top must be OP_ABS")
performUnaryArithmeticOperation(program, x => x match {
case ScriptNumber.zero => ScriptNumber.zero
case _ : ScriptNumber => ScriptNumber(x.num.abs)
case _ : ScriptNumber => ScriptNumber(x.underlying.abs)
})
}
@ -105,7 +105,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
*/
def op0NotEqual(program : ScriptProgram) : ScriptProgram = {
require(program.script.headOption.isDefined && program.script.head == OP_0NOTEQUAL, "Script top must be OP_0NOTEQUAL")
performUnaryArithmeticOperation(program, x => if(x.num == 0) OP_FALSE else OP_TRUE)
performUnaryArithmeticOperation(program, x => if(x.underlying == 0) OP_FALSE else OP_TRUE)
}
@ -187,7 +187,7 @@ trait ArithmeticInterpreter extends ControlOperationsInterpreter {
require(program.script.headOption.isDefined && program.script.head == OP_NUMNOTEQUAL,
"Script top must be OP_NUMNOTEQUAL")
performBinaryBooleanOperation(program, (x,y) => {
x.num != y.num
x.underlying != y.underlying
})
}

View file

@ -29,13 +29,13 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
val h1 = program.stack.tail.head
val result = (h,h1) match {
case (OP_0,ScriptNumber.zero) | (ScriptNumber.zero, OP_0) =>
OP_0.num == ScriptNumber.zero.num
OP_0.underlying == ScriptNumber.zero.underlying
case (OP_FALSE,ScriptNumber.zero) | (ScriptNumber.zero, OP_FALSE) =>
OP_FALSE.num == ScriptNumber.zero.num
OP_FALSE.underlying == ScriptNumber.zero.underlying
case (OP_TRUE,ScriptNumber.one) | (ScriptNumber.one, OP_TRUE) =>
OP_TRUE.num == ScriptNumber.one.num
OP_TRUE.underlying == ScriptNumber.one.underlying
case (OP_1, ScriptNumber.one) | (ScriptNumber.one, OP_1) =>
OP_1.num == ScriptNumber.one.num
OP_1.underlying == ScriptNumber.one.underlying
case _ => h.bytes == h1.bytes
}
val scriptBoolean = if (result) OP_TRUE else OP_FALSE

View file

@ -159,7 +159,7 @@ trait ConstantInterpreter extends BitcoinSLogger {
*/
private def bytesNeededForPushOp(token : ScriptToken) : Long = token match {
case scriptNumber: BytesToPushOntoStack => scriptNumber.opCode
case scriptNumber: ScriptNumber => scriptNumber.num
case scriptNumber: ScriptNumber => scriptNumber.underlying
case scriptConstant : ScriptConstant =>
val constantFlippedEndianess = BitcoinSUtil.flipEndianess(scriptConstant.hex)
java.lang.Long.parseLong(constantFlippedEndianess,16)

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.script.constant
import org.bitcoins.core.number.Int64
import org.bitcoins.core.script.ScriptOperationFactory
import org.bitcoins.core.util.{BitcoinSUtil, BitcoinScriptUtil, Factory}
@ -16,7 +17,6 @@ import scala.util.{Failure, Success, Try}
sealed trait ScriptToken {
/**
* The hexadecimal representation of this script token
*
* @return
*/
def hex : String
@ -29,7 +29,6 @@ sealed trait ScriptToken {
/**
* The conversion from the byte representation of a token to a number
*
* @return
*/
def toLong = ScriptNumberUtil.toLong(hex)
@ -55,7 +54,6 @@ sealed trait ScriptConstant extends ScriptToken {
def isShortestEncoding : Boolean = BitcoinScriptUtil.isShortestEncoding(this)
}
/**
* Represents a number in the Script language
*/
@ -64,22 +62,28 @@ sealed trait ScriptNumber extends ScriptConstant {
* The underlying number of the ScriptNumber
* @return
*/
def num : Long
def underlying : Long
def + (that : ScriptNumber) : ScriptNumber = ScriptNumber(num + that.num)
def + (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying + that.underlying)
def - = ScriptNumber(-underlying)
def - (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying - that.underlying)
def * (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying * that.underlying)
def - = ScriptNumber(-num)
def - (that : ScriptNumber) : ScriptNumber = ScriptNumber(num - that.num)
def * (that : ScriptNumber) : ScriptNumber = ScriptNumber(num * that.num)
def < (that : ScriptNumber) : Boolean = underlying < that.underlying
def <= (that : ScriptNumber) : Boolean = underlying <= that.underlying
def > (that : ScriptNumber) : Boolean = underlying > that.underlying
def >= (that : ScriptNumber) : Boolean = underlying >= that.underlying
def < (that : ScriptNumber) : Boolean = num < that.num
def <= (that : ScriptNumber) : Boolean = num <= that.num
def > (that : ScriptNumber) : Boolean = num > that.num
def >= (that : ScriptNumber) : Boolean = num >= that.num
def < (that : Int64) : Boolean = underlying < that.underlying
def <= (that : Int64) : Boolean = underlying <= that.underlying
def > (that : Int64) : Boolean = underlying > that.underlying
def >= (that : Int64) : Boolean = underlying >= that.underlying
def &(that : ScriptNumber) : ScriptNumber = ScriptNumber(num & that.num)
def | (that : ScriptNumber) : ScriptNumber = ScriptNumber(num | that.num)
def & (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying & that.underlying)
def & (that : Int64) : ScriptNumber = ScriptNumber(underlying & that.underlying)
def | (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying | that.underlying)
/**
* This equality just checks that the underlying scala numbers are equivalent, NOT if the numbers
@ -88,38 +92,35 @@ sealed trait ScriptNumber extends ScriptConstant {
* @param that
* @return
*/
def numEqual(that : ScriptNumber) : Boolean = num == that.num
def numEqual(that : ScriptNumber) : Boolean = underlying == that.underlying
override def toLong = num match {
override def toLong = underlying match {
case 0 => 0L
case _ : Long => super.toLong
}
def toInt = underlying.toInt
}
object ScriptNumber extends Factory[ScriptNumber] {
/**
* This represents a script number inside of bitcoin
*
* @param num the number being represented
* @param underlying the number being represented
* @param hex the hex representation of the number - this can be different than the obvious value for
* the number. For instance we could have padded the number with another word of zeros
*/
private case class ScriptNumberImpl(num : Long, override val hex : String) extends ScriptNumber
private case class ScriptNumberImpl(underlying : Long, override val hex : String) extends ScriptNumber
/**
* Represents the number zero inside of bitcoin's script language
*
* @return
*/
lazy val zero : ScriptNumber = ScriptNumberImpl(0,"")
/**
* Represents the number one inside of bitcoin's script language
*
* @return
*/
lazy val one : ScriptNumber = ScriptNumberImpl(1)
@ -138,8 +139,8 @@ object ScriptNumber extends Factory[ScriptNumber] {
else ScriptNumberImpl(ScriptNumberUtil.toLong(bytes), BitcoinSUtil.encodeHex(bytes))
}
def apply(num : Long) : ScriptNumber = {
if (num == 0) zero else apply(ScriptNumberUtil.longToHex(num))
def apply(underlying : Long) : ScriptNumber = {
if (underlying == 0) zero else apply(ScriptNumberUtil.longToHex(underlying))
}
def apply(hex : String, requireMinimal : Boolean) : Try[ScriptNumber] = {
@ -153,24 +154,18 @@ object ScriptNumber extends Factory[ScriptNumber] {
def apply(bytes : Seq[Byte], requireMinimal : Boolean) : Try[ScriptNumber] = apply(BitcoinSUtil.encodeHex(bytes),requireMinimal)
/**
* Companion object for ScriptNumberImpl that gives us access to more constructor types for the
* ScriptNumberImpl case class
*/
private object ScriptNumberImpl {
def apply(num : Long) : ScriptNumber = ScriptNumberImpl(num, ScriptNumberUtil.longToHex(num))
def apply(underlying : Long) : ScriptNumber = ScriptNumberImpl(underlying, ScriptNumberUtil.longToHex(underlying))
def apply(hex : String) : ScriptNumber = ScriptNumberImpl(ScriptNumberUtil.toLong(hex), hex)
def apply(bytes : Seq[Byte]) : ScriptNumber = ScriptNumberImpl(ScriptNumberUtil.toLong(bytes))
def apply(int64: Int64) : ScriptNumber = ScriptNumberImpl(int64.underlying)
}
}
/**
* The next byte contains the number of bytes to be pushed onto the stack.
*/
@ -209,24 +204,21 @@ case object OP_PUSHDATA4 extends ScriptOperation {
def max = 4294967295L
}
/**
* Represents a script number operation where the the number in the operation is pushed onto the stack
* i.e. OP_0 would be push 0 onto the stack, OP_1 would be push 1 onto the stack
*/
sealed trait ScriptNumberOperation extends ScriptNumber with ScriptOperation {
override def hex = opCode.toHexString
}
/**
* An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
*/
case object OP_0 extends ScriptNumberOperation {
override def opCode = 0
override def hex = "00"
override def num = 0
override def underlying = 0
}
/**
* An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
@ -234,7 +226,7 @@ case object OP_0 extends ScriptNumberOperation {
case object OP_FALSE extends ScriptNumberOperation {
override def opCode = OP_0.opCode
override def hex = OP_0.hex
override def num = OP_0.num
override def underlying = OP_0.underlying
override def bytes = OP_0.bytes
}
@ -243,7 +235,7 @@ case object OP_FALSE extends ScriptNumberOperation {
*/
case object OP_TRUE extends ScriptNumberOperation {
override def opCode = 81
override def num = 1
override def underlying = 1
}
/**
@ -251,7 +243,7 @@ case object OP_TRUE extends ScriptNumberOperation {
*/
case object OP_1NEGATE extends ScriptNumberOperation {
override def opCode = 79
override def num = -1
override def underlying = -1
}
@ -260,7 +252,7 @@ case object OP_1NEGATE extends ScriptNumberOperation {
*/
case object OP_1 extends ScriptNumberOperation {
override def opCode = OP_TRUE.opCode
override def num = OP_TRUE.num
override def underlying = OP_TRUE.underlying
}
/**
@ -268,7 +260,7 @@ case object OP_1 extends ScriptNumberOperation {
*/
case object OP_2 extends ScriptNumberOperation {
override def opCode = 82
override def num = 2
override def underlying = 2
}
/**
@ -276,7 +268,7 @@ case object OP_2 extends ScriptNumberOperation {
*/
case object OP_3 extends ScriptNumberOperation {
override def opCode = 83
override def num = 3
override def underlying = 3
}
/**
@ -284,7 +276,7 @@ case object OP_3 extends ScriptNumberOperation {
*/
case object OP_4 extends ScriptNumberOperation {
override def opCode = 84
override def num = 4
override def underlying = 4
}
/**
@ -292,7 +284,7 @@ case object OP_4 extends ScriptNumberOperation {
*/
case object OP_5 extends ScriptNumberOperation {
override def opCode = 85
override def num = 5
override def underlying = 5
}
/**
@ -300,7 +292,7 @@ case object OP_5 extends ScriptNumberOperation {
*/
case object OP_6 extends ScriptNumberOperation {
override def opCode = 86
override def num = 6
override def underlying = 6
}
/**
@ -308,7 +300,7 @@ case object OP_6 extends ScriptNumberOperation {
*/
case object OP_7 extends ScriptNumberOperation {
override def opCode = 87
override def num = 7
override def underlying = 7
}
/**
@ -316,7 +308,7 @@ case object OP_7 extends ScriptNumberOperation {
*/
case object OP_8 extends ScriptNumberOperation {
override def opCode = 88
override def num = 8
override def underlying = 8
}
/**
@ -324,7 +316,7 @@ case object OP_8 extends ScriptNumberOperation {
*/
case object OP_9 extends ScriptNumberOperation {
override def opCode = 89
override def num = 9
override def underlying = 9
}
/**
@ -332,7 +324,7 @@ case object OP_9 extends ScriptNumberOperation {
*/
case object OP_10 extends ScriptNumberOperation {
override def opCode = 90
override def num = 10
override def underlying = 10
}
/**
@ -340,7 +332,7 @@ case object OP_10 extends ScriptNumberOperation {
*/
case object OP_11 extends ScriptNumberOperation {
override def opCode = 91
override def num = 11
override def underlying = 11
}
/**
@ -348,7 +340,7 @@ case object OP_11 extends ScriptNumberOperation {
*/
case object OP_12 extends ScriptNumberOperation {
override def opCode = 92
override def num = 12
override def underlying = 12
}
/**
@ -356,7 +348,7 @@ case object OP_12 extends ScriptNumberOperation {
*/
case object OP_13 extends ScriptNumberOperation {
override def opCode = 93
override def num = 13
override def underlying = 13
}
/**
@ -364,7 +356,7 @@ case object OP_13 extends ScriptNumberOperation {
*/
case object OP_14 extends ScriptNumberOperation {
override def opCode = 94
override def num = 14
override def underlying = 14
}
/**
@ -372,7 +364,7 @@ case object OP_14 extends ScriptNumberOperation {
*/
case object OP_15 extends ScriptNumberOperation {
override def opCode = 95
override def num = 15
override def underlying = 15
}
/**
@ -380,7 +372,7 @@ case object OP_15 extends ScriptNumberOperation {
*/
case object OP_16 extends ScriptNumberOperation {
override def opCode = 96
override def num = 16
override def underlying = 16
}
@ -390,18 +382,16 @@ object ScriptNumberOperation extends ScriptOperationFactory[ScriptNumberOperatio
/**
* Finds the script number operation based on the given integer
*
* @param num
* @param underlying
* @return
*/
def fromNumber(num : Int) : Option[ScriptNumberOperation] = operations.find(_.num == num)
def fromNumber(underlying : Int) : Option[ScriptNumberOperation] = operations.find(_.underlying == underlying)
}
object ScriptConstant extends Factory[ScriptConstant] {
/**
* Represent a pubkey or hash of a pub key on our stack
*
* @param hex
*/
private case class ScriptConstantImpl(hex : String) extends ScriptConstant {
@ -412,7 +402,6 @@ object ScriptConstant extends Factory[ScriptConstant] {
lazy val negativeOne = ScriptConstant("81")
/**
* Creates a script constant from a sequence of bytes
*
* @param bytes
* @return
*/

View file

@ -226,8 +226,8 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
}
logger.debug("nPossibleSignatures: " + nPossibleSignatures)
val (pubKeysScriptTokens, stackWithoutPubKeys) =
(program.stack.tail.slice(0, nPossibleSignatures.num.toInt),
program.stack.tail.slice(nPossibleSignatures.num.toInt, program.stack.tail.size))
(program.stack.tail.slice(0, nPossibleSignatures.toInt),
program.stack.tail.slice(nPossibleSignatures.toInt, program.stack.tail.size))
val pubKeys = pubKeysScriptTokens.map(key => ECPublicKey(key.bytes))
logger.debug("Public keys on the stack: " + pubKeys)
@ -235,13 +235,13 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
logger.debug("mRequiredSignatures: " + mRequiredSignatures)
//+1 is for the fact that we have the # of sigs + the script token indicating the # of sigs
val signaturesScriptTokens = program.stack.tail.slice(nPossibleSignatures.num.toInt + 1,
nPossibleSignatures.num.toInt + mRequiredSignatures.num.toInt + 1)
val signaturesScriptTokens = program.stack.tail.slice(nPossibleSignatures.toInt + 1,
nPossibleSignatures.toInt + mRequiredSignatures.toInt + 1)
val signatures = signaturesScriptTokens.map(token => ECDigitalSignature(token.bytes))
logger.debug("Signatures on the stack: " + signatures)
//this contains the extra Script OP that is required for OP_CHECKMULTISIG
val stackWithoutPubKeysAndSignatures = stackWithoutPubKeys.tail.slice(mRequiredSignatures.num.toInt, stackWithoutPubKeys.tail.size)
val stackWithoutPubKeysAndSignatures = stackWithoutPubKeys.tail.slice(mRequiredSignatures.toInt, stackWithoutPubKeys.tail.size)
logger.debug("stackWithoutPubKeysAndSignatures: " + stackWithoutPubKeysAndSignatures)
if (pubKeys.size > ScriptSettings.maxPublicKeysPerMultiSig) {
logger.error("We have more public keys than the maximum amount of public keys allowed")
@ -265,7 +265,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
val isValidSignatures: TransactionSignatureCheckerResult =
TransactionSignatureChecker.multiSignatureEvaluator(executionInProgressScriptProgram.txSignatureComponent,
removedOpCodeSeparatorsScript, signatures,
pubKeys, program.flags, mRequiredSignatures.num)
pubKeys, program.flags, mRequiredSignatures.underlying)
//remove the extra op for OP_CHECKMULTISIG from the stack
val restOfStack = stackWithoutPubKeysAndSignatures.tail

View file

@ -259,7 +259,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
case OP_0 :: t => loop(ScriptProgram(p, ScriptNumber.zero :: p.stack, t))
case (scriptNumberOp : ScriptNumberOperation) :: t =>
loop(ScriptProgram(p, ScriptNumber(scriptNumberOp.num) :: p.stack, t))
loop(ScriptProgram(p, ScriptNumber(scriptNumberOp.underlying) :: p.stack, t))
case (bytesToPushOntoStack: BytesToPushOntoStack) :: t =>
loop(pushScriptNumberBytesToStack(p))
case (scriptNumber: ScriptNumber) :: t =>
@ -294,10 +294,10 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
//script was marked invalid for other reasons, don't need to update the opcount
loop(newProgram)
case newProgram : ExecutionInProgressScriptProgram =>
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).num.toInt
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).toInt
loop(newProgram)
case newProgram : PreExecutionScriptProgram =>
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).num.toInt
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).toInt
loop(newProgram)
}
@ -307,10 +307,10 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
//script was marked invalid for other reasons, don't need to update the opcount
loop(newProgram)
case newProgram : ExecutionInProgressScriptProgram =>
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).num.toInt
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).toInt
loop(newProgram)
case newProgram : PreExecutionScriptProgram =>
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).num.toInt
opCount = opCount + BitcoinScriptUtil.numPossibleSignaturesOnStack(program).toInt
loop(newProgram)
}
//reserved operations

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.script.locktime
import org.bitcoins.core.number.{Int64, UInt32}
import org.bitcoins.core.protocol.transaction.TransactionConstants
import org.bitcoins.core.script.ScriptProgram
import org.bitcoins.core.script.constant.{ScriptConstant, ScriptNumber, ScriptToken}
@ -32,7 +33,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
final def opCheckLockTimeVerify(program : ScriptProgram) : ScriptProgram = {
require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY,
"Script top must be OP_CHECKLOCKTIMEVERIFY")
val input = program.txSignatureComponent.transaction.inputs(program.txSignatureComponent.inputIndex)
val input = program.txSignatureComponent.transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
val transaction = program.txSignatureComponent.transaction
if (program.stack.size == 0) {
logger.error("Transaction validation failing in OP_CHECKLOCKTIMEVERIFY because we have no stack items")
@ -45,10 +46,10 @@ trait LockTimeInterpreter extends BitcoinSLogger {
case s : ScriptNumber if (s < ScriptNumber.zero) =>
logger.error("OP_CHECKLOCKTIMEVERIFY marks tx as invalid if the stack top is negative")
ScriptProgram(program,ScriptErrorNegativeLockTime)
case s : ScriptNumber if (s >= ScriptNumber(500000000) && transaction.lockTime < 500000000) =>
case s : ScriptNumber if (s >= ScriptNumber(500000000) && transaction.lockTime < UInt32(500000000)) =>
logger.error("OP_CHECKLOCKTIMEVERIFY marks the tx as invalid if stack top >= 500000000 & tx locktime < 500000000")
ScriptProgram(program,ScriptErrorUnsatisfiedLocktime)
case s : ScriptNumber if (s < ScriptNumber(500000000) && transaction.lockTime >= 500000000) =>
case s : ScriptNumber if (s < ScriptNumber(500000000) && transaction.lockTime >= UInt32(500000000)) =>
logger.error("OP_CHECKLOCKTIMEVERIFY marks the tx as invalid if stack top < 500000000 & tx locktime >= 500000000")
ScriptProgram(program,ScriptErrorUnsatisfiedLocktime)
case s : ScriptNumber =>
@ -99,7 +100,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
//see BIP68 for semantic of locktimeDisableFalg
logger.info("Locktime disable flag was set so OP_CHECKSEQUENCEVERIFY is treated as a NOP")
ScriptProgram(program,program.script.tail,ScriptProgram.Script)
case s : ScriptNumber if (isLockTimeBitOff(s) && program.txSignatureComponent.transaction.version < 2) =>
case s : ScriptNumber if (isLockTimeBitOff(s) && program.txSignatureComponent.transaction.version < UInt32(2)) =>
logger.error("OP_CSV fails if locktime bit is not set and the tx version < 2")
ScriptProgram(program, ScriptErrorUnsatisfiedLocktime)
case s : ScriptNumber =>
@ -130,20 +131,19 @@ trait LockTimeInterpreter extends BitcoinSLogger {
* @return if the given script number is valid or not
*/
def checkSequence(program : ScriptProgram, nSequence : ScriptNumber) : Boolean = {
val inputIndex = program.txSignatureComponent.inputIndex
val inputIndex = program.txSignatureComponent.inputIndex.toInt
logger.debug("inputIndex: " + inputIndex)
val transaction = program.txSignatureComponent.transaction
val txToSequence : ScriptNumber = ScriptNumber(transaction.inputs(inputIndex).sequence)
val txToSequence : Int64 = Int64(transaction.inputs(inputIndex).sequence.underlying)
if (program.txSignatureComponent.transaction.version < 2) {
if (program.txSignatureComponent.transaction.version < UInt32(2)) {
logger.error("Transaction version is too low for OP_CSV")
return false
}
val nLockTimeMask : Long = TransactionConstants.sequenceLockTimeTypeFlag | TransactionConstants.sequenceLockTimeMask
val txToSequenceMasked : ScriptNumber = txToSequence & ScriptNumber(nLockTimeMask)
val nSequenceMasked : ScriptNumber = nSequence & ScriptNumber(nLockTimeMask)
val nLockTimeMask : UInt32 = TransactionConstants.sequenceLockTimeTypeFlag | TransactionConstants.sequenceLockTimeMask
val txToSequenceMasked : Int64 = Int64(txToSequence.underlying & nLockTimeMask.underlying)
val nSequenceMasked : ScriptNumber = nSequence & Int64(nLockTimeMask.underlying)
logger.info("tx sequence number: " + transaction.inputs(inputIndex).sequence)
logger.info("txToSequenceMasked: " + txToSequenceMasked)
@ -158,10 +158,10 @@ trait LockTimeInterpreter extends BitcoinSLogger {
// unless the type of nSequenceMasked being tested is the same as
// the nSequenceMasked in the transaction.
if (!(
(txToSequenceMasked < ScriptNumber(TransactionConstants.sequenceLockTimeTypeFlag) &&
nSequenceMasked < ScriptNumber(TransactionConstants.sequenceLockTimeTypeFlag)) ||
(txToSequenceMasked >= ScriptNumber(TransactionConstants.sequenceLockTimeTypeFlag) &&
nSequenceMasked >= ScriptNumber(TransactionConstants.sequenceLockTimeTypeFlag))
(txToSequenceMasked < Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying) &&
nSequenceMasked < Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying)) ||
(txToSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying) &&
nSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying))
)) {
logger.error("The nSequence mask is not the same as it was in the transaction")
return false
@ -169,7 +169,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
// Now that we know we're comparing apples-to-apples, the
// comparison is a simple numeric one.
if (nSequenceMasked > txToSequenceMasked) {
if (nSequenceMasked > Int64(txToSequenceMasked.underlying)) {
logger.error("OP_CSV fails because locktime in transaction has not been met yet")
return false
}
@ -194,15 +194,15 @@ trait LockTimeInterpreter extends BitcoinSLogger {
// unless the type of nLockTime being tested is the same as
// the nLockTime in the transaction.
val transaction = program.txSignatureComponent.transaction
val input = transaction.inputs(program.txSignatureComponent.inputIndex)
val input = transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
if (!(
(transaction.lockTime < TransactionConstants.locktimeThreshold && locktime.num < TransactionConstants.locktimeThreshold) ||
(transaction.lockTime >= TransactionConstants.locktimeThreshold && locktime.num >= TransactionConstants.locktimeThreshold)
(transaction.lockTime < TransactionConstants.locktimeThreshold && UInt32(locktime.underlying) < TransactionConstants.locktimeThreshold) ||
(transaction.lockTime >= TransactionConstants.locktimeThreshold && UInt32(locktime.underlying) >= TransactionConstants.locktimeThreshold)
)) return false
// Now that we know we're comparing apples-to-apples, the
// comparison is a simple numeric one.
if (locktime.num > transaction.lockTime) return false
if (locktime > Int64(transaction.lockTime.underlying)) return false
// Finally the nLockTime feature can be disabled and thus
// CHECKLOCKTIMEVERIFY bypassed if every txin has been
@ -225,5 +225,5 @@ trait LockTimeInterpreter extends BitcoinSLogger {
* @param s
* @return
*/
def isLockTimeBitOff(s : ScriptNumber) : Boolean = (s.num & TransactionConstants.locktimeDisabledFlag) == 0
def isLockTimeBitOff(s : ScriptNumber) : Boolean = (s.underlying & TransactionConstants.locktimeDisabledFlag.underlying) == 0
}

View file

@ -170,9 +170,9 @@ trait StackInterpreter extends BitcoinSLogger {
executeOpWithStackTopAsNumberArg(program, { number : ScriptNumber =>
logger.info("Script number for OP_PICK: " + number)
//check if n is within the bound of the script
(number.num >= 0 && number.num < program.stack.tail.size) match {
(number.underlying >= 0 && number.underlying < program.stack.tail.size) match {
case true =>
val newStackTop = program.stack.tail(number.num.toInt)
val newStackTop = program.stack.tail(number.toInt)
ScriptProgram(program, newStackTop :: program.stack.tail, program.script.tail)
case false =>
logger.error("The index for OP_PICK would have caused an index out of bounds exception")
@ -191,9 +191,9 @@ trait StackInterpreter extends BitcoinSLogger {
require(program.script.headOption.isDefined && program.script.head == OP_ROLL, "Top of script stack must be OP_ROLL")
require(program.stack.size > 0,"Stack must have at least one items on it for OP_ROLL")
executeOpWithStackTopAsNumberArg(program, (number : ScriptNumber) =>
(number.num >= 0 && number.num < program.stack.tail.size) match {
(number.underlying >= 0 && number.underlying < program.stack.tail.size) match {
case true =>
val newStackTop = program.stack.tail(number.num.toInt)
val newStackTop = program.stack.tail(number.toInt)
//removes the old instance of the stack top, appends the new index to the head
val newStack = newStackTop :: program.stack.tail.diff(List(newStackTop))
ScriptProgram(program,newStack,program.script.tail)

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.serializers.blockchain
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.util.{CryptoUtil, BitcoinSUtil}
@ -22,7 +23,7 @@ trait RawBlockHeaderSerializer extends RawBitcoinSerializer[BlockHeader] {
//version first 4 bytes
val versionBytes = bytes.slice(0,4)
val versionHex = BitcoinSUtil.encodeHex(versionBytes.reverse)
val version = java.lang.Long.parseLong(versionHex, 16)
val version = UInt32(versionHex)
//previous header hash next 32 bytes
val prevBlockHashBytes = bytes.slice(4, 36)
val prevBlockHash : DoubleSha256Digest = DoubleSha256Digest(prevBlockHashBytes)
@ -32,15 +33,15 @@ trait RawBlockHeaderSerializer extends RawBitcoinSerializer[BlockHeader] {
//time 4 bytes
val timeBytes = bytes.slice(68,72)
val timeHex = BitcoinSUtil.encodeHex(timeBytes.reverse)
val time = java.lang.Long.parseLong(timeHex, 16)
val time = UInt32(timeHex)
//nbits 4 bytes
val nBitsBytes = bytes.slice(72,76)
val nBitsHex = BitcoinSUtil.encodeHex(nBitsBytes.reverse)
val nBits = java.lang.Long.parseLong(nBitsHex, 16)
val nBits = UInt32(nBitsHex)
//nonce 4 bytes
val nonceBytes = bytes.slice(76,80)
val nonceHex = BitcoinSUtil.encodeHex(nonceBytes.reverse)
val nonce = java.lang.Long.parseLong(nonceHex, 16)
val nonce = UInt32(nonceHex)
BlockHeader(version,prevBlockHash, merkleRoot, time, nBits, nonce)
}
@ -53,16 +54,16 @@ trait RawBlockHeaderSerializer extends RawBitcoinSerializer[BlockHeader] {
def write(blockHeader: BlockHeader) : String = {
//TODO: By happenstance, flipEndianess function adds a leading '0' if we have hex number less than 10.
//We need to explicitly handle this case in our write function in the future.
val headerVersion = BitcoinSUtil.flipEndianess(blockHeader.version.toHexString)
val headerVersion = BitcoinSUtil.flipEndianess(blockHeader.version.hex)
val versionSubPadding = addPrecedingZero(headerVersion)
val version = addPadding(8,versionSubPadding)
val prevHash = blockHeader.previousBlockHash.hex
val merkleRoot = blockHeader.merkleRootHash.hex
val time = addPadding(8,BitcoinSUtil.flipEndianess(blockHeader.time.toHexString))
val nBits = addPadding(8,BitcoinSUtil.flipEndianess(blockHeader.nBits.toHexString))
val nonce = addPadding(8,BitcoinSUtil.flipEndianess(blockHeader.nonce.toHexString))
val time = addPadding(8,BitcoinSUtil.flipEndianess(blockHeader.time.hex))
val nBits = addPadding(8,BitcoinSUtil.flipEndianess(blockHeader.nBits.hex))
val nonce = addPadding(8,BitcoinSUtil.flipEndianess(blockHeader.nonce.hex))
version + prevHash + merkleRoot + time + nBits + nonce
}

View file

@ -18,7 +18,7 @@ trait RawTransactionInputParser extends RawBitcoinSerializer[Seq[TransactionInpu
override def read(bytes : List[Byte]) : Seq[TransactionInput] = {
require(bytes.size > 0, "You passed in an empty list to read")
require(bytes.nonEmpty, "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] = {
@ -54,7 +54,7 @@ trait RawTransactionInputParser extends RawBitcoinSerializer[Seq[TransactionInpu
val outPoint = RawTransactionOutPointParser.write(input.previousOutput)
val varInt = input.scriptSigCompactSizeUInt.hex
val scriptSig = RawScriptSignatureParser.write(input.scriptSignature)
val sequence = addPadding(8,BitcoinSUtil.flipEndianess(UInt32(input.sequence).hex))
val sequence = addPadding(8,BitcoinSUtil.flipEndianess(input.sequence.hex))
outPoint + varInt + scriptSig + sequence
}
@ -85,7 +85,7 @@ trait RawTransactionInputParser extends RawBitcoinSerializer[Seq[TransactionInpu
logger.info("Sequence bytes: " + BitcoinSUtil.encodeHex(sequenceBytes))
val sequenceNumberHex : String = BitcoinSUtil.encodeHex(sequenceBytes)
val sequenceNumberFlippedEndianess = BitcoinSUtil.flipEndianess(sequenceNumberHex)
val sequenceNumber : Long = java.lang.Long.parseLong(sequenceNumberFlippedEndianess,16)
val sequenceNumber : UInt32 = UInt32(sequenceNumberFlippedEndianess)
logger.debug("Parsed sequence number: " + sequenceNumber)
val txInput = TransactionInput(outPoint,scriptSig,sequenceNumber)
(txInput, bytes.slice(lastInputByte, bytes.length))

View file

@ -3,7 +3,7 @@ package org.bitcoins.core.serializers.transaction
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.protocol.transaction.TransactionOutPoint
import org.bitcoins.core.protocol.transaction.{EmptyTransactionOutPoint, TransactionOutPoint}
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil, NumberUtil}
@ -20,17 +20,20 @@ trait RawTransactionOutPointParser extends RawBitcoinSerializer[TransactionOutPo
val indexBytes = bytes.slice(32, bytes.size)
logger.debug("Index bytes: " + BitcoinSUtil.encodeHex(indexBytes.reverse))
val byteNumbers : Seq[BigInt] = for {
(byte,index) <- indexBytes.zipWithIndex
} yield NumberUtil.calculateUnsignedNumberFromByte(index, byte)
logger.debug("Byte numbers: " + byteNumbers)
val index = byteNumbers.sum
TransactionOutPoint(DoubleSha256Digest(txId), index.toInt)
val index = UInt32(indexBytes.reverse)
TransactionOutPoint(DoubleSha256Digest(txId), index)
}
def write(outPoint : TransactionOutPoint) : String = {
val indexHexWithoutPadding : String = BitcoinSUtil.flipEndianess(BitcoinSUtil.encodeHex(outPoint.vout))
val indexHex = addPadding(8,indexHexWithoutPadding)
val indexHexWithoutPadding : String = BitcoinSUtil.flipEndianess(outPoint.vout.hex)
//UInt32s cannot hold negative numbers, but sometimes the Bitcoin Protocol requires the vout to be -1, which is serialized
//as "0xFFFFFFFF".
//https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/primitives/transaction.h
//http://stackoverflow.com/questions/2711522/what-happens-if-i-assign-a-negative-value-to-an-unsigned-variable
val indexHex = outPoint match {
case EmptyTransactionOutPoint => "ffffffff"
case outPoint : TransactionOutPoint => addPadding(8,indexHexWithoutPadding)
}
val txIdHex = outPoint.txId.hex
txIdHex + indexHex
}

View file

@ -76,7 +76,7 @@ trait BitcoinScriptUtil {
val multiSigCount : Long = script.zipWithIndex.map { case (token, index) =>
if (multiSigOps.contains(token) && index != 0) {
script(index-1) match {
case scriptNum : ScriptNumber => scriptNum.num
case scriptNum : ScriptNumber => scriptNum.underlying
case scriptConstant : ScriptConstant => ScriptNumberUtil.toLong(scriptConstant.hex)
case _ : ScriptToken => ScriptSettings.maxPublicKeysPerMultiSig
}
@ -117,7 +117,7 @@ trait BitcoinScriptUtil {
require(program.script.headOption == Some(OP_CHECKMULTISIG) || program.script.headOption == Some(OP_CHECKMULTISIGVERIFY),
"We can only parse the nubmer of signatures the stack when we are executing a OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY op")
val nPossibleSignatures = numPossibleSignaturesOnStack(program)
val stackWithoutPubKeys = program.stack.tail.slice(nPossibleSignatures.num.toInt,program.stack.tail.size)
val stackWithoutPubKeys = program.stack.tail.slice(nPossibleSignatures.toInt,program.stack.tail.size)
val mRequiredSignatures : ScriptNumber = stackWithoutPubKeys.head match {
case s: ScriptNumber => s
case s : ScriptConstant => ScriptNumber(s.bytes)

View file

@ -6,6 +6,7 @@ import org.bitcoinj.core.{DumpedPrivateKey, Sha256Hash, Utils}
import org.bitcoinj.core.Transaction.SigHash
import org.bitcoinj.params.TestNet3Params
import org.bitcoinj.script.{ScriptBuilder, ScriptChunk, ScriptOpCodes}
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.script.ScriptParser
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction._
@ -32,7 +33,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val sigBytes : Seq[Byte] = TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm,SIGHASH_ALL())
val sigBytes : Seq[Byte] = TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm,SIGHASH_ALL())
val bitcoinjSerialization = BitcoinSUtil.encodeHex(
BitcoinJSignatureSerialization.serializeForSignature(BitcoinJTestUtil.multiSigTransaction,0,
BitcoinJTestUtil.multiSigScript.getProgram(),SIGHASH_ALL().byte)
@ -46,7 +47,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val spendingTx = Transaction(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize())
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val bitcoinsTxSigHash = TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm,SIGHASH_ALL())
val bitcoinsTxSigHash = TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm,SIGHASH_ALL())
val bitcoinjTxSigHash = BitcoinSUtil.encodeHex(
BitcoinJSignatureSerialization.hashForSignature(BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram(),SIGHASH_ALL().byte)
)
@ -59,7 +60,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val serialiazedTxForSig : Seq[Byte] =
TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm,SIGHASH_SINGLE)
TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm,SIGHASH_SINGLE)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.serializeForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_SINGLE.byte))
@ -72,7 +73,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm,SIGHASH_SINGLE)
TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm,SIGHASH_SINGLE)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.hashForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_SINGLE.byte))
@ -85,7 +86,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val serialiazedTxForSig : Seq[Byte] =
TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm,SIGHASH_NONE)
TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm,SIGHASH_NONE)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.serializeForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_NONE.byte))
@ -98,7 +99,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm,SIGHASH_NONE)
TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm,SIGHASH_NONE)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.hashForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_NONE.byte))
@ -112,7 +113,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val serializedTxForSig : Seq[Byte] =
TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_ANYONECANPAY)
TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_ANYONECANPAY)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.serializeForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_ANYONECANPAY.byte))
@ -126,7 +127,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_ANYONECANPAY)
TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_ANYONECANPAY)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.hashForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_ANYONECANPAY.byte))
@ -139,7 +140,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val serializedTxForSig : Seq[Byte] =
TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_ALL_ANYONECANPAY)
TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_ALL_ANYONECANPAY)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.serializeForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_ALL_ANYONECANPAY.byte))
@ -152,7 +153,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val serializedTxForSig : Seq[Byte] =
TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_SINGLE_ANYONECANPAY)
TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_SINGLE_ANYONECANPAY)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.serializeForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_SINGLE_ANYONECANPAY.byte))
@ -165,7 +166,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val serializedTxForSig : Seq[Byte] =
TransactionSignatureSerializer.serializeForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_NONE_ANYONECANPAY)
TransactionSignatureSerializer.serializeForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_NONE_ANYONECANPAY)
val bitcoinjSigSerialization = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.serializeForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_NONE_ANYONECANPAY.byte))
@ -178,7 +179,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_ALL_ANYONECANPAY)
TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_ALL_ANYONECANPAY)
val bitcoinjTxHashForSig = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.hashForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_ALL_ANYONECANPAY.byte))
@ -191,7 +192,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_SINGLE_ANYONECANPAY)
TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_SINGLE_ANYONECANPAY)
val bitcoinjTxHashForSig = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.hashForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_SINGLE_ANYONECANPAY.byte))
@ -204,7 +205,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
spendingTx.hex must be (BitcoinSUtil.encodeHex(BitcoinJTestUtil.multiSigTransaction.bitcoinSerialize()))
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,0,scriptPubKey.asm, SIGHASH_NONE_ANYONECANPAY)
TransactionSignatureSerializer.hashForSignature(spendingTx,UInt32.zero,scriptPubKey.asm, SIGHASH_NONE_ANYONECANPAY)
val bitcoinjTxHashForSig = BitcoinSUtil.encodeHex(BitcoinJSignatureSerialization.hashForSignature(
BitcoinJTestUtil.multiSigTransaction,0,BitcoinJTestUtil.multiSigScript.getProgram,SIGHASH_NONE_ANYONECANPAY.byte))
@ -221,7 +222,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val rawTx = TestUtil.simpleRawTransaction
val rawParentTx = TestUtil.parentSimpleRawTransaction
val bitcoinjTx = new org.bitcoinj.core.Transaction(params,Utils.HEX.decode(rawTx))
val input = bitcoinjTx.getInput(inputIndex)
val input = bitcoinjTx.getInput(inputIndex.toInt)
val scriptSig = input.getScriptSig
val parentTx = new org.bitcoinj.core.Transaction(params,Utils.HEX.decode(rawParentTx))
val parentOutput = parentTx.getOutput(input.getOutpoint.getIndex)
@ -231,7 +232,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val pubKey : Array[Byte] = scriptSig.getPubKey
val signature : Array[Byte] = scriptSig.getChunks().get(0).data
val bitcoinjSerializeForSig : Seq[Byte] =
BitcoinJSignatureSerialization.serializeForSignature(bitcoinjTx,inputIndex,
BitcoinJSignatureSerialization.serializeForSignature(bitcoinjTx,inputIndex.toInt,
parentOutput.getScriptBytes, SIGHASH_ALL().byte)
@ -252,13 +253,13 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val rawTx = TestUtil.simpleRawTransaction
val rawParentTx = TestUtil.parentSimpleRawTransaction
val bitcoinjTx = new org.bitcoinj.core.Transaction(params,Utils.HEX.decode(rawTx))
val input = bitcoinjTx.getInput(inputIndex)
val input = bitcoinjTx.getInput(inputIndex.toInt)
val scriptSig = input.getScriptSig
val parentTx = new org.bitcoinj.core.Transaction(params,Utils.HEX.decode(rawParentTx))
val parentOutput = parentTx.getOutput(input.getOutpoint.getIndex)
val bitcoinjSerializeForSig : Seq[Byte] =
BitcoinJSignatureSerialization.serializeForSignature(bitcoinjTx,inputIndex,
BitcoinJSignatureSerialization.serializeForSignature(bitcoinjTx,inputIndex.toInt,
parentOutput.getScriptBytes, SIGHASH_ALL().byte)
val hashType = spendingInput.scriptSignature.hashType(spendingInput.scriptSignature.signatures.head)
@ -282,7 +283,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val bitcoinjTx = BitcoinjConversions.transaction(spendingTx)
val hashType = spendingInput.scriptSignature.hashType(spendingInput.scriptSignature.signatures.head)
val bitcoinjHashForSig : Seq[Byte] = BitcoinJSignatureSerialization.serializeForSignature(
bitcoinjTx, inputIndex, creditingOutput.scriptPubKey.bytes.toArray, hashType.byte
bitcoinjTx, inputIndex.toInt, creditingOutput.scriptPubKey.bytes.toArray, hashType.byte
)
val hashedTxForSig : String = BitcoinSUtil.encodeHex(
TransactionSignatureSerializer.serializeForSignature(spendingTx,inputIndex,creditingOutput.scriptPubKey.asm,hashType
@ -303,7 +304,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val bitcoinjTx = BitcoinjConversions.transaction(spendingTx)
val hashType = spendingInput.scriptSignature.hashType(spendingInput.scriptSignature.signatures.head)
val bitcoinjHashForSig : Seq[Byte] = BitcoinJSignatureSerialization.hashForSignature(
bitcoinjTx, inputIndex, creditingOutput.scriptPubKey.bytes.toArray, hashType.byte
bitcoinjTx, inputIndex.toInt, creditingOutput.scriptPubKey.bytes.toArray, hashType.byte
)
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,inputIndex,creditingOutput.scriptPubKey.asm, hashType)
@ -317,7 +318,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
it must "hash a transaction that has script operations after OP_CHECKSIGVERIFY" in {
//this example is from tx_valid.json
val rawTx = "01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000"
val inputIndex = 0
val inputIndex = UInt32.zero
val spendingTx = Transaction(rawTx)
val scriptPubKeyFromString = ScriptParser.fromString("DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 " +
"EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed02" +
@ -328,7 +329,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
val bitcoinjTx = BitcoinjConversions.transaction(spendingTx)
val bitcoinjHashForSig : Seq[Byte] = BitcoinJSignatureSerialization.hashForSignature(
bitcoinjTx, inputIndex, scriptPubKey.bytes.toArray, SIGHASH_ALL(0x01).byte
bitcoinjTx, inputIndex.toInt, scriptPubKey.bytes.toArray, SIGHASH_ALL(0x01).byte
)
val hashedTxForSig =
@ -341,9 +342,9 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
//this is from a test case inside of tx_valid.json
//https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json#L91
val rawTx = "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000"
val inputIndex = 0
val inputIndex = UInt32.zero
val spendingTx = Transaction(rawTx)
require(spendingTx.inputs(inputIndex).scriptSignature.hex == "48304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101",
require(spendingTx.inputs(inputIndex.toInt).scriptSignature.hex == "48304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101",
"Script sig not right")
val scriptPubKeyFromString = ScriptParser.fromString("0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG")
val scriptPubKey = ScriptPubKey.fromAsm(scriptPubKeyFromString)
@ -361,14 +362,14 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
//this is from a test case inside of tx_valid.json
//https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json#L91
val rawTx = "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000"
val inputIndex = 1
val inputIndex = UInt32.one
val spendingTx = Transaction(rawTx)
val scriptPubKeyFromString = ScriptParser.fromString("0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG")
val scriptPubKey = ScriptPubKey.fromAsm(scriptPubKeyFromString)
val bitcoinjTx = BitcoinjConversions.transaction(spendingTx)
val bitcoinjHashForSig : Seq[Byte] = BitcoinJSignatureSerialization.hashForSignature(
bitcoinjTx, inputIndex, scriptPubKey.bytes.toArray, SIGHASH_ALL_ANYONECANPAY.byte
bitcoinjTx, inputIndex.toInt, scriptPubKey.bytes.toArray, SIGHASH_ALL_ANYONECANPAY.byte
)
val hashedTxForSig =
TransactionSignatureSerializer.hashForSignature(spendingTx,inputIndex,scriptPubKey.asm,SIGHASH_ALL_ANYONECANPAY)
@ -381,7 +382,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
//this is from a test case inside of tx_valid.json
//https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json#L96
val rawTx = "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000"
val inputIndex = 0
val inputIndex = UInt32.zero
val spendingTx = Transaction(rawTx)
val scriptPubKeyFromString = ScriptParser.fromString("DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG")
val scriptPubKey = ScriptPubKey.fromAsm(scriptPubKeyFromString)
@ -398,7 +399,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
//this is from a test case inside of tx_valid.json
//https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json#L96
val rawTx = "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000"
val inputIndex = 2
val inputIndex = UInt32(2)
val spendingTx = Transaction(rawTx)
val scriptPubKeyFromString = ScriptParser.fromString("DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG")
val scriptPubKey = ScriptPubKey.fromAsm(scriptPubKeyFromString)
@ -414,7 +415,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
//this is from a test case inside of tx_valid.json
//https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json#L102
val rawTx = "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000"
val inputIndex = 0
val inputIndex = UInt32.zero
val spendingTx = Transaction(rawTx)
val scriptPubKeyFromString = ScriptParser.fromString("0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG")
val scriptPubKey = ScriptPubKey.fromAsm(scriptPubKeyFromString)
@ -428,7 +429,7 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers with
//this is from a test case inside of tx_invalid.json
//https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_invalid.json#L75
val rawTx = "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000"
val inputIndex = 0
val inputIndex = UInt32.zero
val spendingTx = Transaction(rawTx)
val scriptPubKeyFromString = ScriptParser.fromString("0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG")
val scriptPubKey = ScriptPubKey.fromAsm(scriptPubKeyFromString)

View file

@ -80,7 +80,6 @@ class UInt32Spec extends Properties("UInt32") with BitcoinSLogger {
}
}
property("== & !=") = {
Prop.forAll(NumberGenerator.uInt32s, NumberGenerator.uInt32s) { (num1 : UInt32, num2 : UInt32) =>
if (num1.underlying == num2.underlying) num1 == num2
@ -88,6 +87,11 @@ class UInt32Spec extends Properties("UInt32") with BitcoinSLogger {
}
}
property("|") =
Prop.forAll(NumberGenerator.uInt32s, NumberGenerator.uInt32s) { (num1 : UInt32, num2 : UInt32) =>
UInt32(num1.underlying | num2.underlying) == (num1 | num2)
}
}

View file

@ -8,9 +8,8 @@ import org.scalacheck.{Prop, Properties}
*/
class CompactSizeUIntSpec extends Properties("CompactSizeUIntSpec") {
property("Serialization symmetry") =
Prop.forAll(NumberGenerator.positiveLongs) { num : Long =>
CompactSizeUInt.parseCompactSizeUInt(CompactSizeUInt(num).hex).num == num
Prop.forAll(NumberGenerator.compactSizeUInts) { compact : CompactSizeUInt =>
CompactSizeUInt.parseCompactSizeUInt(compact.hex).hex == compact.hex
}
}

View file

@ -0,0 +1,15 @@
package org.bitcoins.core.protocol.blockchain
import org.bitcoins.core.gen.BlockchainElementsGenerator
import org.scalacheck.{Prop, Properties}
/**
* Created by tom on 7/6/16.
*/
class BlockHeaderSpec extends Properties("BlockHeaderSpec") {
property("serialization symmetry") =
Prop.forAll(BlockchainElementsGenerator.blockHeader) { header =>
//BlockHeader(header.version, header.previousBlockHash, header.merkleRootHash, header.time, header.nBits, header.nonce) == header
BlockHeader(header.hex).hex == header.hex
}
}

View file

@ -21,6 +21,8 @@ class TransactionInputTest extends FlatSpec with MustMatchers {
it must "write a transaction output to hex accurately" in {
val input = TransactionInput(TestUtil.rawTxInput)
TransactionInput.fromHex(TestUtil.rawTxInput).hex must be (TestUtil.rawTxInput)
}

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.TestUtil
import org.scalatest.{FlatSpec, MustMatchers}
@ -9,7 +10,7 @@ import org.scalatest.{FlatSpec, MustMatchers}
class TransactionOutPointTest extends FlatSpec with MustMatchers {
"TransactionOutPoint" must "define an empty transaction outpoint" in {
EmptyTransactionOutPoint.txId.hex must be ("0000000000000000000000000000000000000000000000000000000000000000")
EmptyTransactionOutPoint.vout must be (-1)
EmptyTransactionOutPoint.vout must be (UInt32.max)
}
it must "read then write a transaction outpoint" in {

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.transaction.testprotocol.CoreTransactionTestCase
import org.bitcoins.core.protocol.transaction.testprotocol.CoreTransactionTestCaseProtocol._
import org.bitcoins.core.script.ScriptProgram
@ -89,7 +90,7 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
require(outPoint.txId == input.previousOutput.txId,
"OutPoint txId not the same as input prevout txid\noutPoint.txId: " + outPoint.txId + "\n" +
"input prevout txid: " + input.previousOutput.txId)
val program = ScriptProgram(tx,scriptPubKey,inputIndex,testCase.flags)
val program = ScriptProgram(tx,scriptPubKey,UInt32(inputIndex),testCase.flags)
withClue(testCase.raw) {
ScriptInterpreter.run(program) must equal (ScriptOk)
}
@ -103,14 +104,14 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
//use this to represent a single test case from script_valid.json
/* val lines =
val lines =
"""
|[
|[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 CHECKLOCKTIMEVERIFY 1"]],
|"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"]
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", "P2SH"]
|]
""".stripMargin*/
val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
""".stripMargin
//val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
val json = lines.parseJson
val testCasesOpt : Seq[Option[CoreTransactionTestCase]] = json.convertTo[Seq[Option[CoreTransactionTestCase]]]
val testCases : Seq[CoreTransactionTestCase] = testCasesOpt.flatten
@ -126,9 +127,11 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
logger.info("ScriptPubKey: " + scriptPubKey)
logger.info("OutPoint: " + outPoint)
logger.info("Flags after parsing: " + testCase.flags)
logger.info("spending tx: " + testCase.spendingTx)
logger.info("" + testCase.scriptPubKeys)
val isValidTx = ScriptInterpreter.checkTransaction(tx)
if (isValidTx) {
val program = ScriptProgram(tx,scriptPubKey,inputIndex,testCase.flags)
val program = ScriptProgram(tx,scriptPubKey,UInt32(inputIndex),testCase.flags)
ScriptInterpreter.run(program) == ScriptOk
} else {
logger.error("Transaction does not pass CheckTransaction()")
@ -137,7 +140,7 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
}
withClue(testCase.raw) {
//only one input is required to be false to make the transaction invalid
txInputValidity.exists(_ == false) must be (true)
txInputValidity.contains(false) must be (true)
}
}
}

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.script
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.script.constant.{OP_1, OP_0}
import org.bitcoins.core.script.flag.ScriptFlagFactory
import org.bitcoins.core.util.TestUtil
@ -49,7 +50,7 @@ class ScriptProgramFactoryTest extends FlatSpec with MustMatchers {
it must "update the script program to the given stack and script" in {
val stack = List(OP_0)
val script = List(OP_1)
val program = ScriptProgram(TestUtil.transaction, TestUtil.scriptPubKey, 0, stack,script, ScriptFlagFactory.empty)
val program = ScriptProgram(TestUtil.transaction, TestUtil.scriptPubKey, UInt32.zero, stack,script, ScriptFlagFactory.empty)
program.stack must be (stack)
program.script must be (script)
}

View file

@ -23,7 +23,7 @@ class ScriptNumberFactoryTest extends FlatSpec with MustMatchers {
it must "create a negative number from hex" in {
val hex = "008080"
val number = -32768
ScriptNumber(hex).num must be (number)
ScriptNumber(hex).underlying must be (number)
}
it must "create a negative number from hex and have the same underlying hex representation" in {

View file

@ -0,0 +1,54 @@
package org.bitcoins.core.script.constant
import org.bitcoins.core.gen.NumberGenerator
import org.bitcoins.core.util.BitcoinSLogger
import org.scalacheck.{Prop, Properties}
/**
* Created by tom on 7/5/16.
*/
class ScriptNumberSpec extends Properties("ScriptNumberSpec") with BitcoinSLogger {
property("Additive identity") =
Prop.forAll(NumberGenerator.scriptNumbers) { num : ScriptNumber =>
num + ScriptNumber.zero == num
}
property("Subtraction identity") =
Prop.forAll(NumberGenerator.scriptNumbers) { num : ScriptNumber =>
num - ScriptNumber.zero == num
}
property("Multiplicative identity") =
Prop.forAll(NumberGenerator.scriptNumbers) { num : ScriptNumber =>
num * ScriptNumber.one == num
}
property("< >=") =
Prop.forAll(NumberGenerator.scriptNumbers, NumberGenerator.scriptNumbers) { (num1 : ScriptNumber, num2 : ScriptNumber) =>
if (num1.underlying < num2.underlying) num1 < num2
else num1 >= num2
}
property("> <=") =
Prop.forAll(NumberGenerator.scriptNumbers, NumberGenerator.scriptNumbers) { (num1 : ScriptNumber, num2 : ScriptNumber) =>
if (num1.underlying > num2.underlying) num1 > num2
else num1 <= num2
}
property("== & !=") =
Prop.forAll(NumberGenerator.scriptNumbers, NumberGenerator.scriptNumbers) { (num1 : ScriptNumber, num2 : ScriptNumber) =>
if (num1.underlying == num2.underlying) num1 == num2
else num1 != num2
}
property("add two script numbers") =
Prop.forAll(NumberGenerator.scriptNumbers, NumberGenerator.scriptNumbers) { (num1 : ScriptNumber, num2: ScriptNumber) =>
num1 + num2 == ScriptNumber(num1.underlying + num2.underlying)
}
property("subtract a script number from another script number") =
Prop.forAll(NumberGenerator.scriptNumbers, NumberGenerator.scriptNumbers) { (num1 : ScriptNumber, num2: ScriptNumber) =>
num1 - num2 == ScriptNumber(num1.underlying - num2.underlying)
}
property("multiply two script numbers") =
Prop.forAll(NumberGenerator.scriptNumbers, NumberGenerator.scriptNumbers) { (num1 : ScriptNumber, num2: ScriptNumber) =>
num1 * num2 == ScriptNumber(num1.underlying * num2.underlying)
}
property("multiply a script number by zero should return zero") =
Prop.forAll(NumberGenerator.scriptNumbers) { (num1 : ScriptNumber) =>
num1 * ScriptNumber.zero == ScriptNumber.zero
}
}

View file

@ -1,13 +1,12 @@
package org.bitcoins.core.script.crypto
import org.bitcoins.core.crypto.TransactionSignatureSerializer
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptSignature}
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.script.result._
import org.bitcoins.core.script._
import org.bitcoins.core.script.arithmetic.OP_NOT
import org.bitcoins.core.script.flag.{ScriptFlagFactory, ScriptVerifyDerSig, ScriptVerifyNullDummy}
import org.bitcoins.core.script.constant._
import org.bitcoins.core.script.flag.{ScriptFlagFactory, ScriptVerifyDerSig, ScriptVerifyNullDummy}
import org.bitcoins.core.script.result._
import org.bitcoins.core.util.{BitcoinSLogger, ScriptProgramTestUtil, TestUtil, TransactionTestUtil}
import org.scalatest.{FlatSpec, MustMatchers}
@ -157,7 +156,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val script = List(OP_CHECKMULTISIG)
val baseProgram = ScriptProgram(spendingTx,creditingTx.outputs(0).scriptPubKey,0,ScriptFlagFactory.empty)
val baseProgram = ScriptProgram(spendingTx,creditingTx.outputs(0).scriptPubKey,UInt32.zero,ScriptFlagFactory.empty)
val program = ScriptProgram(baseProgram,stack,script)
val newProgram = opCheckMultiSig(program)
@ -174,7 +173,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers with CryptoInterp
val input = TransactionInput(EmptyTransactionOutPoint, scriptSig, TransactionConstants.sequence)
val tx = Transaction(TestUtil.transaction,UpdateTransactionInputs(Seq(input)))
val baseProgram = ScriptProgram.toExecutionInProgress(ScriptProgram(tx,TestUtil.scriptPubKey,0,flags))
val baseProgram = ScriptProgram.toExecutionInProgress(ScriptProgram(tx,TestUtil.scriptPubKey,UInt32.zero,flags))
val stack = Seq(OP_0,OP_0,OP_1)
val script = Seq(OP_CHECKMULTISIG)
val program = ScriptProgram(baseProgram,stack,script)

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.script.locktime
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.policy.Policy
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionConstants, TransactionInput, UpdateTransactionInputs}
import org.bitcoins.core.script.result._
@ -33,9 +34,9 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
it must "mark the transaction as invalid if the stack top is negative" in {
val stack = Seq(ScriptNumber(-1))
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),0)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),UInt32.zero)
val txAdjustedSequenceNumber = Transaction(TestUtil.transaction,UpdateTransactionInputs(Seq(txInputAdjustedSequenceNumber)))
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,0)
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,UInt32.zero)
val baseProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgramTestUtil.toPreExecutionScriptProgram(ScriptProgram(baseProgram,stack,script))
@ -46,9 +47,9 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
it must "mark the transaction as invalid if the locktime on the tx is < 500000000 && stack top is >= 500000000" in {
val stack = Seq(ScriptNumber(500000000))
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),0)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),UInt32.zero)
val txAdjustedSequenceNumber = Transaction(TestUtil.transaction,UpdateTransactionInputs(Seq(txInputAdjustedSequenceNumber)))
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,0)
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,UInt32.zero)
val baseProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgramTestUtil.toPreExecutionScriptProgram(ScriptProgram(baseProgram,stack,script))
@ -59,9 +60,9 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
it must "mark the transaction as invalid if the locktime on the tx is >= 500000000 && stack top is < 500000000" in {
val stack = Seq(ScriptNumber(499999999))
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),0)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),UInt32.zero)
val txAdjustedSequenceNumber = Transaction(TestUtil.transaction,UpdateTransactionInputs(Seq(txInputAdjustedSequenceNumber)))
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,500000000)
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,UInt32(500000000))
val baseProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgramTestUtil.toPreExecutionScriptProgram(ScriptProgram(baseProgram,stack,script))
@ -73,10 +74,10 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
it must "mark the transaction as invalid if the stack top item is greater than the tx locktime" in {
val stack = Seq(ScriptNumber(499999999))
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),0)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),UInt32.zero)
val txAdjustedSequenceNumber = Transaction(TestUtil.transaction,
UpdateTransactionInputs(Seq(txInputAdjustedSequenceNumber)))
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,0)
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,UInt32.zero)
val baseProgram = ScriptProgram.toExecutionInProgress(ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags))
val program = ScriptProgram(baseProgram,stack,script)
@ -90,10 +91,10 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
it must "mark the transaction as valid if the locktime on the tx is < 500000000 && stack top is < 500000000" in {
val stack = Seq(ScriptNumber(0))
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),0)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),UInt32.zero)
val txAdjustedSequenceNumber = Transaction(TestUtil.transaction,
UpdateTransactionInputs(Seq(txInputAdjustedSequenceNumber)))
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,0)
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,UInt32.zero)
val baseProgram = ScriptProgram.toExecutionInProgress(ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags))
val program = ScriptProgram(baseProgram,stack,script)
@ -106,9 +107,9 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
it must "mark the transaction as valid if the locktime on the tx is >= 500000000 && stack top is >= 500000000" in {
val stack = Seq(ScriptNumber(500000000))
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),0)
val txInputAdjustedSequenceNumber = TransactionInput(TestUtil.transaction.inputs(0),UInt32.zero)
val txAdjustedSequenceNumber = Transaction(TestUtil.transaction,UpdateTransactionInputs(Seq(txInputAdjustedSequenceNumber)))
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,500000000)
val adjustedLockTimeTx = Transaction(txAdjustedSequenceNumber,UInt32(500000000))
val baseProgram : PreExecutionScriptProgram = ScriptProgram(adjustedLockTimeTx,TestUtil.testProgram.txSignatureComponent.scriptPubKey,
TestUtil.testProgram.txSignatureComponent.inputIndex,TestUtil.testProgram.flags)
val program = ScriptProgram(baseProgram,stack,script)
@ -146,7 +147,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
}
it must "treat OP_CHECKSEQUENCEVERIFY as a NOP if the locktime disabled flag is set in the sequence number" in {
val stack = List(ScriptNumber(TransactionConstants.locktimeDisabledFlag))
val stack = List(ScriptNumber(TransactionConstants.locktimeDisabledFlag.underlying))
val script = List(OP_CHECKSEQUENCEVERIFY)
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
val newProgram = opCheckSequenceVerify(program)

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.serializers.blockchain
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.BitcoinSUtil
import org.scalatest.{FlatSpec, MustMatchers}
@ -23,12 +24,12 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
val hex = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
"BlockHeader" must "parse genesis block header" in {
val blockHeader = RawBlockHeaderSerializer.read(hex)
blockHeader.version must be (java.lang.Long.parseLong(BitcoinSUtil.flipEndianess(version), 16))
blockHeader.version must be (UInt32(BitcoinSUtil.flipEndianess(version)))
blockHeader.previousBlockHash must be (DoubleSha256Digest(prevBlockHash))
blockHeader.merkleRootHash must be (DoubleSha256Digest(merkleRoot))
blockHeader.time must be (java.lang.Long.parseLong(BitcoinSUtil.flipEndianess(timeStamp), 16))
blockHeader.nBits must be (java.lang.Long.parseLong(BitcoinSUtil.flipEndianess(nBits), 16))
blockHeader.nonce must be (java.lang.Long.parseLong(BitcoinSUtil.flipEndianess(nonce), 16))
blockHeader.time must be (UInt32(BitcoinSUtil.flipEndianess(timeStamp)))
blockHeader.nBits must be (UInt32(BitcoinSUtil.flipEndianess(nBits)))
blockHeader.nonce must be (UInt32(BitcoinSUtil.flipEndianess(nonce)))
}
it must "properly hash genesis block header to return genesis block hash" in {
@ -54,11 +55,11 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
val hex2 = version2 + prevBlockHash2 + merkleRoot2 + timeStamp2 + nBits2 + nonce2
val hash = "2837af674e81436b09e0c937e94d96fe32e5c872391ba1090000000000000000"
val blockHeader = RawBlockHeaderSerializer.read(hex2)
blockHeader.version must be (2)
blockHeader.version must be (UInt32(2))
blockHeader.previousBlockHash must be (DoubleSha256Digest(prevBlockHash2))
blockHeader.merkleRootHash must be (DoubleSha256Digest(merkleRoot2))
blockHeader.time must be (1415239972)
blockHeader.nonce must be (1678286846)
blockHeader.time must be (UInt32(1415239972))
blockHeader.nonce must be (UInt32(1678286846))
blockHeader.hash must be (DoubleSha256Digest(hash))
}
@ -73,12 +74,12 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
val hex = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
val hash = "c5a764eb61db336edb17be9c49dc07dcae0219bc51a2efe681df9f0000000000"
val blockHeader = RawBlockHeaderSerializer.read(hex)
blockHeader.version must be (536870912)
blockHeader.version must be (UInt32(536870912))
blockHeader.previousBlockHash must be (DoubleSha256Digest(prevBlockHash))
blockHeader.merkleRootHash must be (DoubleSha256Digest(merkleRoot))
blockHeader.time must be (1465247498)
blockHeader.nBits must be (486604799)
blockHeader.nonce must be (2667504451L)
blockHeader.time must be (UInt32(1465247498))
blockHeader.nBits must be (UInt32(486604799))
blockHeader.nonce must be (UInt32(2667504451L))
blockHeader.hash must be (DoubleSha256Digest(hash))
RawBlockHeaderSerializer.write(blockHeader) must be (hex)
}

View file

@ -1,6 +1,7 @@
package org.bitcoins.core.serializers.blockchain
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil}
@ -105,11 +106,11 @@ class RawBlockSerializerTest extends FlatSpec with MustMatchers with BitcoinSLog
val block = RawBlockSerializer.read(hex)
block.blockHeader.hash.hex must be ("5f3d49113e7bf838a061a1661c672053deb90891edf3ecfa9e18000000000000")
block.blockHeader.version must be (536870912)
block.blockHeader.version must be (UInt32(536870912))
block.blockHeader.previousBlockHash must be (DoubleSha256Digest(prevBlockHash))
block.blockHeader.merkleRootHash must be (DoubleSha256Digest(merkleRoot))
block.blockHeader.time must be (1465354640)
block.blockHeader.nBits must be (437875042)
block.blockHeader.time must be (UInt32(1465354640))
block.blockHeader.nBits must be (UInt32(437875042))
block.blockHeader must be (RawBlockHeaderSerializer.read(header))
block.txCount.num must be (txSeq.size)
block.hex must be (hex)

View file

@ -2,6 +2,7 @@ package org.bitcoins.core.serializers.transaction
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.P2PKScriptSignature
import org.bitcoins.core.protocol.transaction.{TransactionConstants, TransactionInput, TransactionOutPoint}
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil, TestUtil}
@ -20,11 +21,11 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
"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.vout must be (UInt32.zero)
txInputs.head.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("e17d316006850c1764301befcf82c8c84cd1794f3f0d0382b296df2edab0d685"))
txInputs.head.scriptSignature.hex must be (TestUtil.rawP2shInputScript)
txInputs.head.scriptSignature.asm must be (TestUtil.p2shInputScript.asm)
txInputs.head.sequence must be (BigInt("4294967295"))
txInputs.head.sequence must be (UInt32(4294967295L))
}
@ -35,10 +36,10 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
val firstInput = txInputs.head
val secondInput = txInputs(1)
firstInput.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("0140d0ed6c9feeb68ea727723a82bbaf0d143fc1d3810265d4dca7ebe6e380df"))
firstInput.previousOutput.vout must be (27)
firstInput.previousOutput.vout must be (UInt32(27))
firstInput.scriptSignature.hex must be ("473044022040f91c48f4011bf2e2edb6621bfa8fb802241de939cb86f1872c99c580ef0fe402204fc27388bc525e1b655b5f5b35f9d601d28602432dd5672f29e0a47f5b8bbb26012102c114f376c98d12a0540c3a81ab99bb1c5234245c05e8239d09f48229f9ebf011")
secondInput.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("0140d0ed6c9feeb68ea727723a82bbaf0d143fc1d3810265d4dca7ebe6e380df"))
secondInput.previousOutput.vout must be (52)
secondInput.previousOutput.vout must be (UInt32(52))
secondInput.scriptSignature.hex must be ("483045022100cf317c320d078c5b884c44e7488825dab5bcdf3f88c66314ac925770cd8773a7022033fde60d33cc2842ea73fce5d9cf4f8da6fadf414a75b7085efdcd300407f438012102605c23537b27b80157c770cd23e066cd11db3800d3066a38b9b592fc08ae9c70")
}
@ -78,7 +79,7 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
txInputs.head.scriptSignature.hex must be ("483045022100ad8e961fe3c22b2647d92b078f4c0cf81b3106ea5bf8b900ab8646aa4430216f022071d4edc2b5588be20ac4c2d07edd8ed069e10b2402d3dce2d3b835ccd075f283014104fa79182bbc26c708b5d9f36b8635947d4a834ea356cf612ede08395c295f962e0b1dc2557aba34188640e51a58ed547f2c89c8265cd0c04ff890d8435648746e")
txInputs(1).previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("3063ca8537bd097ba0c2e9dfdd40e373aa0b61c2bb0594fbfd3e04b331922136"))
txInputs(1).previousOutput.vout must be (0)
txInputs(1).previousOutput.vout must be (UInt32.zero)
txInputs(1).scriptSignature.hex must be ("483045022100cb097f8720d0c4665e8771fff5181b30584fd9e7d437fae21b440c94fe76d56902206f9b539ae26ec9688c54272d6a3309d93f17fb9835f382fff1ebeead84af2763014104fa79182bbc26c708b5d9f36b8635947d4a834ea356cf612ede08395c295f962e0b1dc2557aba34188640e51a58ed547f2c89c8265cd0c04ff890d8435648746e")
val serializedTx = RawTransactionInputParser.write(txInputs)
@ -94,17 +95,17 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
val txInput = RawTransactionInputParser.read(rawTxInput)
txInput.size must be (1)
txInput.head.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("e99eb3e6551844d0db252ef242c043796b3b0ccfb126c0ae09f9dd0230e2f10d"))
txInput.head.previousOutput.vout must be (0)
txInput.head.previousOutput.vout must be (UInt32.zero)
txInput.head.scriptSignature.hex must be ("004730440220028c02f14654a0cc12c7e3229adb09d5d35bebb6ba1057e39adb1b2706607b0d0220564fab12c6da3d5acef332406027a7ff1cbba980175ffd880e1ba1bf40598f6b014830450221009362f8d67b60773745e983d07ba10efbe566127e244b724385b2ca2e47292dda022033def393954c320653843555ddbe7679b35cc1cacfe1dad923977de8cd6cc6d7014c695221025e9adcc3d65c11346c8a6069d6ebf5b51b348d1d6dc4b95e67480c34dc0bc75c21030585b3c80f4964bf0820086feda57c8e49fa1eab925db7c04c985467973df96521037753a5e3e9c4717d3f81706b38a6fb82b5fb89d29e580d7b98a37fea8cdefcad53ae")
txInput.head.scriptSigCompactSizeUInt.num must be (txInput.head.scriptSignature.size)
txInput.head.sequence must be (4294967295L)
txInput.head.sequence must be (UInt32(4294967295L))
RawTransactionInputParser.write(txInput) must be (rawTxInput)
//parse the second input on the tx cddda897b0e9322937ee1f4fd5d6147d60f04a0f4d3b461e4f87066ac3918f2a
val rawTxInput2 = "01d11533b0f283fca193e361a91ca7ddfc66592e20fd6eaf5dc0f1ef5fed05818000000000fdfe0000483045022100b4062edd75b5b3117f28ba937ed737b10378f762d7d374afabf667180dedcc62022005d44c793a9d787197e12d5049da5e77a09046014219b31e9c6b89948f648f1701483045022100b3b0c0273fc2c531083701f723e03ea3d9111e4bbca33bdf5b175cec82dcab0802206650462db37f9b4fe78da250a3b339ab11e11d84ace8f1b7394a1f6db0960ba4014c695221025e9adcc3d65c11346c8a6069d6ebf5b51b348d1d6dc4b95e67480c34dc0bc75c21030585b3c80f4964bf0820086feda57c8e49fa1eab925db7c04c985467973df96521037753a5e3e9c4717d3f81706b38a6fb82b5fb89d29e580d7b98a37fea8cdefcad53aeffffffff"
val txInput2 = RawTransactionInputParser.read(rawTxInput2).head
txInput2.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("808105ed5feff1c05daf6efd202e5966fcdda71ca961e393a1fc83f2b03315d1"))
txInput2.previousOutput.vout must be (0)
txInput2.previousOutput.vout must be (UInt32.zero)
txInput2.scriptSignature.hex must be ("00483045022100b4062edd75b5b3117f28ba937ed737b10378f762d7d374afabf667180dedcc62022005d44c793a9d787197e12d5049da5e77a09046014219b31e9c6b89948f648f1701483045022100b3b0c0273fc2c531083701f723e03ea3d9111e4bbca33bdf5b175cec82dcab0802206650462db37f9b4fe78da250a3b339ab11e11d84ace8f1b7394a1f6db0960ba4014c695221025e9adcc3d65c11346c8a6069d6ebf5b51b348d1d6dc4b95e67480c34dc0bc75c21030585b3c80f4964bf0820086feda57c8e49fa1eab925db7c04c985467973df96521037753a5e3e9c4717d3f81706b38a6fb82b5fb89d29e580d7b98a37fea8cdefcad53ae")
}
@ -134,14 +135,14 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
val secondInput = txInputs.tail.head
firstInput.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("e99eb3e6551844d0db252ef242c043796b3b0ccfb126c0ae09f9dd0230e2f10d"))
firstInput.previousOutput.vout must be (0)
firstInput.previousOutput.vout must be (UInt32.zero)
firstInput.scriptSignature.hex must be ("004730440220028c02f14654a0cc12c7e3229adb09d5d35bebb6ba1057e39adb1b2706607b0d0220564fab12c6da3d5acef332406027a7ff1cbba980175ffd880e1ba1bf40598f6b014830450221009362f8d67b60773745e983d07ba10efbe566127e244b724385b2ca2e47292dda022033def393954c320653843555ddbe7679b35cc1cacfe1dad923977de8cd6cc6d7014c695221025e9adcc3d65c11346c8a6069d6ebf5b51b348d1d6dc4b95e67480c34dc0bc75c21030585b3c80f4964bf0820086feda57c8e49fa1eab925db7c04c985467973df96521037753a5e3e9c4717d3f81706b38a6fb82b5fb89d29e580d7b98a37fea8cdefcad53ae")
firstInput.sequence must be (4294967295L)
firstInput.sequence must be (UInt32(4294967295L))
txInputs(1).previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("808105ed5feff1c05daf6efd202e5966fcdda71ca961e393a1fc83f2b03315d1"))
txInputs(1).previousOutput.vout must be (0)
txInputs(1).previousOutput.vout must be (UInt32.zero)
txInputs(1).scriptSignature.hex must be ("00483045022100b4062edd75b5b3117f28ba937ed737b10378f762d7d374afabf667180dedcc62022005d44c793a9d787197e12d5049da5e77a09046014219b31e9c6b89948f648f1701483045022100b3b0c0273fc2c531083701f723e03ea3d9111e4bbca33bdf5b175cec82dcab0802206650462db37f9b4fe78da250a3b339ab11e11d84ace8f1b7394a1f6db0960ba4014c695221025e9adcc3d65c11346c8a6069d6ebf5b51b348d1d6dc4b95e67480c34dc0bc75c21030585b3c80f4964bf0820086feda57c8e49fa1eab925db7c04c985467973df96521037753a5e3e9c4717d3f81706b38a6fb82b5fb89d29e580d7b98a37fea8cdefcad53ae")
txInputs(1).sequence must be (4294967295L)
txInputs(1).sequence must be (UInt32(4294967295L))
RawTransactionInputParser.write(txInputs) must be (rawTxInputs)
}
@ -156,7 +157,7 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
val inputs = RawTransactionInputParser.read(rawTxInput)
inputs.head.scriptSignature.hex must be ("4730440220048e15422cf62349dc586ffb8c749d40280781edd5064ff27a5910ff5cf225a802206a82685dbc2cf195d158c29309939d5a3cd41a889db6f766f3809fff35722305012103dcfc9882c1b3ae4e03fb6cac08bdb39e284e81d70c7aa8b27612457b2774509b")
inputs.head.previousOutput.vout must be (1)
inputs.head.previousOutput.vout must be (UInt32.one)
inputs.head.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("65bd23d3fb0ac9d3ee0195aae8d033d6689dacf71907902b27a7ad6f6441a7cd"))
inputs.head.sequence must be (TransactionConstants.sequence)
}
@ -171,7 +172,7 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
it must "read and write an input with everything that is empty besides the sequence number" in {
val rawInput = "0100010000000000000000000000000000000000000000000000000000000000000000000000ffff0000"
val input = RawTransactionInputParser.read(rawInput)
input.head.sequence must be (65535)
input.head.sequence must be (UInt32(65535))
RawTransactionInputParser.write(input) must be (rawInput)
}
@ -184,8 +185,8 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers with RawT
it must "write then read this list of inputs with large sequence numbers" in {
val input = List(TransactionInput(TransactionOutPoint(
DoubleSha256Digest("ba3dd35a9b55c48114590d9bce52686ffd4b52f9c3f530bf65ad89d2b6109703"),1311080620),
P2PKScriptSignature("46304402204a77315e14decd47650f5ecc2c84a411c6ae7049e01637ebbd8f63eaab007c2e0220425cff64ca35a6fe426459eb4b7596cea75fdb057c843518046568f6ecba81b3"),30250565))
DoubleSha256Digest("ba3dd35a9b55c48114590d9bce52686ffd4b52f9c3f530bf65ad89d2b6109703"),UInt32(1311080620)),
P2PKScriptSignature("46304402204a77315e14decd47650f5ecc2c84a411c6ae7049e01637ebbd8f63eaab007c2e0220425cff64ca35a6fe426459eb4b7596cea75fdb057c843518046568f6ecba81b3"),UInt32(30250565)))
val hex = RawTransactionInputParser.write(input)

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.serializers.transaction
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.BitcoinSUtil
import org.scalatest.{FlatSpec, MustMatchers}
@ -13,12 +14,12 @@ class RawTransactionOutPointParserTest extends FlatSpec with MustMatchers {
"RawTransactionOutPointParser" must "read a raw outpoint into a native scala TransactionOutPoint" in {
val outPoint = RawTransactionOutPointParser.read(rawOutPoint)
outPoint.txId.hex must be (BitcoinSUtil.flipEndianess("e17d316006850c1764301befcf82c8c84cd1794f3f0d0382b296df2edab0d685"))
outPoint.vout must be (0)
outPoint.vout must be (UInt32.zero)
}
it must "parse a large vout for an outpoint" in {
val outPoint = RawTransactionOutPointParser.read(rawOutPointLargeVout)
outPoint.vout must be (52)
outPoint.vout must be (UInt32(52))
outPoint.txId.hex must be (BitcoinSUtil.flipEndianess("0140d0ed6c9feeb68ea727723a82bbaf0d143fc1d3810265d4dca7ebe6e380df"))
}
it must "write a TransactionOutPoint to a serialized format" in {
@ -54,7 +55,7 @@ class RawTransactionOutPointParserTest extends FlatSpec with MustMatchers {
//vout should be 20183580
val rawOutPoint = "4435c4ea162d51135c9b2bbb867a86f25001c246224b60e8ab2307edce7fc28a0ca13f13"
val outPoint = RawTransactionOutPointParser.read(rawOutPoint)
outPoint.vout must be (322937100)
outPoint.vout must be (UInt32(322937100))
outPoint.hex must be (rawOutPoint)
}

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.serializers.transaction
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.transaction.{TransactionConstants, Transaction}
import org.bitcoins.core.util.{BitcoinSUtil, TestUtil}
import org.scalatest.{FlatSpec, MustMatchers}
@ -11,10 +12,10 @@ class RawTransactionParserTest extends FlatSpec with MustMatchers {
"RawTransactionParser" must "parse a raw transaction" in {
val tx : Transaction = RawTransactionParser.read(TestUtil.rawTransaction)
tx.version must be (1)
tx.version must be (UInt32.one)
tx.inputs.size must be (2)
tx.outputs.size must be (2)
tx.lockTime must be (0)
tx.lockTime must be (UInt32.zero)
tx.txId.hex must be (BitcoinSUtil.flipEndianess("44e504f5b7649d215be05ad9f09026dee95201244a3b218013c504a6a49a26ff"))
}
it must "parse a transaction correctly with a locktime" in {
@ -22,7 +23,7 @@ class RawTransactionParserTest extends FlatSpec with MustMatchers {
val rawTx = "0100000002fc37adbd036fb51b3f4f6f70474270939d6ff8c4ea697639f2b57dd6359e3070010000008b483045022100ad8e961fe3c22b2647d92b078f4c0cf81b3106ea5bf8b900ab8646aa4430216f022071d4edc2b5588be20ac4c2d07edd8ed069e10b2402d3dce2d3b835ccd075f283014104fa79182bbc26c708b5d9f36b8635947d4a834ea356cf612ede08395c295f962e0b1dc2557aba34188640e51a58ed547f2c89c8265cd0c04ff890d8435648746e0000000036219231b3043efdfb9405bbc2610baa73e340dddfe9c2a07b09bd3785ca6330000000008b483045022100cb097f8720d0c4665e8771fff5181b30584fd9e7d437fae21b440c94fe76d56902206f9b539ae26ec9688c54272d6a3309d93f17fb9835f382fff1ebeead84af2763014104fa79182bbc26c708b5d9f36b8635947d4a834ea356cf612ede08395c295f962e0b1dc2557aba34188640e51a58ed547f2c89c8265cd0c04ff890d8435648746effffffff02905f0100000000001976a914a45bc47d00c3d2b0d0ea37cbf74b94cd1986ea7988aca0860100000000001976a914a45bc47d00c3d2b0d0ea37cbf74b94cd1986ea7988ac77d3a655"
val tx : Transaction = RawTransactionParser.read(rawTx)
tx.txId.hex must be (BitcoinSUtil.flipEndianess("bdc221db675c06dbee2ae75d33e31cad4e2555efea10c337ff32c8cdf97f8e74"))
tx.lockTime must be (1436996471)
tx.lockTime must be (UInt32(1436996471))
}
it must "write a transaction with a locktime" in {
@ -54,7 +55,7 @@ class RawTransactionParserTest extends FlatSpec with MustMatchers {
val tx = RawTransactionParser.read(TestUtil.parentSimpleRawTransaction)
tx.inputs.size must be (1)
tx.inputs.head.scriptSignature.hex must be ("4730440220048e15422cf62349dc586ffb8c749d40280781edd5064ff27a5910ff5cf225a802206a82685dbc2cf195d158c29309939d5a3cd41a889db6f766f3809fff35722305012103dcfc9882c1b3ae4e03fb6cac08bdb39e284e81d70c7aa8b27612457b2774509b")
tx.inputs.head.previousOutput.vout must be (1)
tx.inputs.head.previousOutput.vout must be (UInt32.one)
tx.inputs.head.previousOutput.txId.hex must be (BitcoinSUtil.flipEndianess("65bd23d3fb0ac9d3ee0195aae8d033d6689dacf71907902b27a7ad6f6441a7cd"))
tx.inputs.head.sequence must be (TransactionConstants.sequence)
tx.outputs.size must be (2)

View file

@ -1,5 +1,6 @@
package org.bitcoins.core.util
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.script.{RawScriptSignatureParser, RawScriptPubKeyParser}
import org.bitcoins.core.serializers.transaction.{RawTransactionInputParser, RawTransactionParser}
import org.bitcoins.core.policy.Policy
@ -143,7 +144,7 @@ object TestUtil {
val rawScriptSig = "483045022100ad8e961fe3c22b2647d92b078f4c0cf81b3106ea5bf8b900ab8646aa4430216f022071d4edc2b5588be20ac4c2d07edd8ed069e10b2402d3dce2d3b835ccd075f283014104fa79182bbc26c708b5d9f36b8635947d4a834ea356cf612ede08395c295f962e0b1dc2557aba34188640e51a58ed547f2c89c8265cd0c04ff890d8435648746e"
def scriptSig = ScriptSignature(rawScriptSig)
def testProgram : ScriptProgram = ScriptProgram(TransactionTestUtil.testTransaction,
EmptyScriptPubKey,0,List(),Policy.standardScriptVerifyFlags)
EmptyScriptPubKey,UInt32.zero,List(),Policy.standardScriptVerifyFlags)
def testProgramPreExecution = testProgram match {
case p : PreExecutionScriptProgram => p

View file

@ -2,6 +2,7 @@ package org.bitcoins.core.util
import org.bitcoins.core.crypto.{ECPrivateKey, ECPublicKey}
import org.bitcoins.core.currency.CurrencyUnits
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction._
@ -35,20 +36,20 @@ trait TransactionTestUtil extends BitcoinSLogger {
* @param scriptPubKey
* @return the transaction and the output index of the scriptPubKey
*/
def buildCreditingTransaction(scriptPubKey : ScriptPubKey) : (Transaction,Int) = {
def buildCreditingTransaction(scriptPubKey : ScriptPubKey) : (Transaction,UInt32) = {
//this needs to be all zeros according to these 3 lines in bitcoin core
//https://github.com/bitcoin/bitcoin/blob/605c17844ea32b6d237db6d83871164dc7d59dab/src/test/script_tests.cpp#L64
//https://github.com/bitcoin/bitcoin/blob/80d1f2e48364f05b2cdf44239b3a1faa0277e58e/src/primitives/transaction.h#L32
//https://github.com/bitcoin/bitcoin/blob/605c17844ea32b6d237db6d83871164dc7d59dab/src/uint256.h#L40
val outpoint = TransactionOutPoint(EmptyTransactionOutPoint.txId,0xFFFFFFFF)
val outpoint = EmptyTransactionOutPoint
val scriptSignature = ScriptSignature("0000")
val input = TransactionInput(outpoint,scriptSignature,TransactionConstants.sequence)
val output = TransactionOutput(CurrencyUnits.zero,scriptPubKey)
val tx = Transaction(TransactionConstants.version,Seq(input),Seq(output),TransactionConstants.lockTime)
(tx,0)
(tx,UInt32.zero)
}
/**
@ -56,9 +57,9 @@ trait TransactionTestUtil extends BitcoinSLogger {
* @param creditingTx
* @param scriptSignature
* @param outputIndex
* @return the built spending transaction adn the input index for the script signature
* @return the built spending transaction and the input index for the script signature
*/
def buildSpendingTransaction(creditingTx : Transaction,scriptSignature : ScriptSignature, outputIndex : Int) : (Transaction,Int) = {
def buildSpendingTransaction(creditingTx : Transaction,scriptSignature : ScriptSignature, outputIndex : UInt32) : (Transaction,UInt32) = {
/*
CMutableTransaction txSpend;
txSpend.nVersion = 1;
@ -78,7 +79,7 @@ trait TransactionTestUtil extends BitcoinSLogger {
val tx = Transaction(TransactionConstants.version,Seq(input),Seq(output),TransactionConstants.lockTime)
/* val expectedHex = "01000000019ce5586f04dd407719ab7e2ed3583583b9022f29652702cfac5ed082013461fe000000004847304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001ffffffff0100000000000000000000000000"
require(tx.hex == expectedHex,"\nExpected hex: " + expectedHex + "\nActual hex: " + tx.hex)*/
(tx,0)
(tx,UInt32.zero)
}
@ -89,16 +90,16 @@ trait TransactionTestUtil extends BitcoinSLogger {
* Returns a transaction, the input that is spending the output, and the inputIndex inside of the tx
* @return
*/
def transactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, Int, TransactionOutput) = {
def transactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, UInt32, TransactionOutput) = {
val spendingTx = TestUtil.simpleTransaction
val creditingTx = TestUtil.parentSimpleTransaction
logger.info("Crediting transaction: " + creditingTx)
val creditingOutput = TestUtil.parentSimpleTransaction.outputs(spendingTx.inputs.head.previousOutput.vout)
val creditingOutput = TestUtil.parentSimpleTransaction.outputs(spendingTx.inputs.head.previousOutput.vout.toInt)
//make sure the outpoint index and the outpoint txid are correct
require(spendingTx.inputs.head.previousOutput.txId == creditingTx.txId)
require(spendingTx.inputs.head.previousOutput.vout == 0)
require(spendingTx.inputs.head.previousOutput.vout == UInt32.zero)
(spendingTx,spendingTx.inputs.head,0, creditingOutput)
(spendingTx,spendingTx.inputs.head,UInt32.zero, creditingOutput)
}
def signedMultiSignatureTransaction : (Transaction, Int, ScriptPubKey, Seq[ECPublicKey]) = {
@ -113,12 +114,12 @@ trait TransactionTestUtil extends BitcoinSLogger {
* Returns a p2sh transaction with its corresponding crediting output
* @return
*/
def p2shTransactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, Int, TransactionOutput) = {
def p2shTransactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, UInt32, TransactionOutput) = {
val creditingTx = TestUtil.p2sh2Of2CreditingTx
val spendingTx = TestUtil.p2sh2Of2Tx
val inputIndex = 0
val input = spendingTx.inputs(inputIndex)
(spendingTx, input, inputIndex, creditingTx.outputs(input.previousOutput.vout))
val inputIndex = UInt32.zero
val input = spendingTx.inputs(inputIndex.toInt)
(spendingTx, input, inputIndex, creditingTx.outputs(input.previousOutput.vout.toInt))
}
//https://tbtc.blockr.io/api/v1/tx/raw/d77d905fc29f86bc3db39fdb68cfcab4e35f677d4f2ec33ed749912e0fa5f385
@ -134,10 +135,10 @@ trait TransactionTestUtil extends BitcoinSLogger {
* Returns a p2sh transaction that has 2 of 3 signatures with the creiditing output
* @return
*/
def p2sh2Of3TransactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, Int, TransactionOutput) = {
val inputIndex = 0
val input = p2sh2Of3Transaction.inputs(inputIndex)
val output = p2sh2Of3CreditingTransaction.outputs(input.previousOutput.vout)
def p2sh2Of3TransactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, UInt32, TransactionOutput) = {
val inputIndex = UInt32.zero
val input = p2sh2Of3Transaction.inputs(inputIndex.toInt)
val output = p2sh2Of3CreditingTransaction.outputs(input.previousOutput.vout.toInt)
(p2sh2Of3Transaction,input,inputIndex,output)
}
@ -146,7 +147,7 @@ trait TransactionTestUtil extends BitcoinSLogger {
* Builds a transaction with a non strict der encoded signature
* @return the transaction and the inputIndex of the non strict der encoded signature
*/
def transactionWithNonStrictDerSignature : (Transaction, Int) = {
def transactionWithNonStrictDerSignature : (Transaction, UInt32) = {
val (creditingTx,outputIndex) = buildCreditingTransaction(TestUtil.scriptPubKey)
val (spendingTx,inputIndex) = buildSpendingTransaction(creditingTx,TestUtil.scriptSigNotStrictDerEncoded,outputIndex)
(spendingTx,inputIndex)
@ -157,9 +158,9 @@ trait TransactionTestUtil extends BitcoinSLogger {
* Returns a valid transaction that spends a p2pkh output at the inputIndex
* @return
*/
def p2pkhTransactionWithCreditingScriptPubKey : (Transaction, Int, ScriptPubKey) = {
def p2pkhTransactionWithCreditingScriptPubKey : (Transaction, UInt32, ScriptPubKey) = {
val outputIndex = TestUtil.simpleTransaction.inputs.head.previousOutput.vout
(TestUtil.simpleTransaction, 0, TestUtil.parentSimpleTransaction.outputs(outputIndex).scriptPubKey)
(TestUtil.simpleTransaction, UInt32.zero, TestUtil.parentSimpleTransaction.outputs(outputIndex.toInt).scriptPubKey)
}