mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 23:08:31 +01:00
Merge pull request #6 from TomMcCabe/refactor_number_system
Refactor number system
This commit is contained in:
commit
8cb8bcc0f2
44 changed files with 457 additions and 330 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
}
|
|
@ -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 block’s 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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue