refactor numbers in BlockHeader and Block

This commit is contained in:
Tom McCabe 2016-06-28 15:08:26 -05:00
parent e6fff6a7c8
commit efc3d41437
5 changed files with 42 additions and 37 deletions

View File

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

View File

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

View File

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

View File

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

View File

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