fix blockheader serializer so all values are big-endian

This commit is contained in:
Tom McCabe 2016-06-09 10:19:55 -05:00
parent 621195f785
commit 45afb86beb
6 changed files with 32 additions and 49 deletions

View file

@ -84,9 +84,7 @@ sealed trait BlockHeader extends NetworkElement with BitcoinSLogger {
*
* @return
*/
def hash : DoubleSha256Digest = {
DoubleSha256Digest(BitcoinSUtil.flipEndianess(CryptoUtil.doubleSHA256(bytes).hex))
}
def hash : DoubleSha256Digest = CryptoUtil.doubleSHA256(bytes)
override def hex : String = RawBlockHeaderSerializer.write(this)

View file

@ -106,7 +106,7 @@ sealed trait ChainParams {
val tx = Transaction(TransactionConstants.version,Seq(input), Seq(output), TransactionConstants.lockTime)
val prevBlockHash = DoubleSha256Digest("0000000000000000000000000000000000000000000000000000000000000000")
//TODO: Replace this with a merkle root hash computed algorithmically
val merkleRootHash = DoubleSha256Digest("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")
val merkleRootHash = DoubleSha256Digest("3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a")
val genesisBlockHeader = BlockHeader(version,prevBlockHash,merkleRootHash,time,nBits,nonce)
val genesisBlock = Block(genesisBlockHeader,CompactSizeUInt(1,1),Seq(tx))
genesisBlock

View file

@ -55,8 +55,8 @@ trait RawBlockHeaderSerializer extends RawBitcoinSerializer[BlockHeader] {
val versionSubPadding = addPrecedingZero(headerVersion)
val version = addPadding(8,versionSubPadding)
val prevHash = BitcoinSUtil.flipEndianess(blockHeader.previousBlockHash.hex)
val merkleRoot = BitcoinSUtil.flipEndianess(blockHeader.merkleRootHash.hex)
val prevHash = blockHeader.previousBlockHash.hex
val merkleRoot = blockHeader.merkleRootHash.hex
val time = BitcoinSUtil.flipEndianess(blockHeader.time.toHexString)
val nBits = BitcoinSUtil.flipEndianess(blockHeader.nBits.toHexString)

View file

@ -27,7 +27,7 @@ class ChainParamsTest extends FlatSpec with MustMatchers {
genesisBlock.hex must be (hex)
}
it must "hash the bitcoin genesis block" in {
genesisBlock.blockHeader.hash.hex must be ("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
genesisBlock.blockHeader.hash.hex must be ("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000")
}
it must "compute the script signature for the coinbase tx in the mainnet genesis block" in {

View file

@ -5,6 +5,7 @@ import org.bitcoins.core.util.BitcoinSUtil
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Values transmitted in the network are big-endian.
* Created by tom on 6/3/16.
*/
class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
@ -13,15 +14,13 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
//https://insight.bitpay.com/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
val version = "01000000"
val prevBlockHash = "0000000000000000000000000000000000000000000000000000000000000000"
val merkleRoot = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
val merkleRootFlipped = "3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A".toLowerCase
val merkleRoot = "3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A".toLowerCase
val timeStamp = "29AB5F49".toLowerCase
val nBits = "FFFF001D".toLowerCase
val nonce = "1DAC2B7C".toLowerCase
val hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
val hash = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"
val hex = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
val writtenHex = version + prevBlockHash + merkleRootFlipped + timeStamp + nBits + nonce //prevHash not flipped b/c all zeroes
"BlockHeader" must "parse genesis block header" in {
val blockHeader = RawBlockHeaderSerializer.read(hex)
blockHeader.version must be (java.lang.Long.parseLong(BitcoinSUtil.flipEndianess(version), 16))
@ -39,7 +38,7 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
it must "write genesis block header" in {
val blockHeader = RawBlockHeaderSerializer.read(hex)
RawBlockHeaderSerializer.write(blockHeader) must be (writtenHex)
RawBlockHeaderSerializer.write(blockHeader) must be (hex)
}
it must "parse different block header with known values from dev reference" in {
@ -47,13 +46,13 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
//https://bitcoin.org/en/developer-reference#block-headers
//https://insight.bitpay.com/block/000000000000000009a11b3972c8e532fe964de937c9e0096b43814e67af3728
val version2 = "02000000"
val prevBlockHash2 = "00000000000000000cca48eb4b330d91e8d946d344ca302a86a280161b0bffb6"
val merkleRoot2 = "7114b3aa8a049bbc12cdde1008a2dd70e2ed045f698593ca869394ee52aa109d"
val prevBlockHash2 = "b6ff0b1b1680a2862a30ca44d346d9e8910d334beb48ca0c0000000000000000"
val merkleRoot2 = "9d10aa52ee949386ca9385695f04ede270dda20810decd12bc9b048aaab31471"
val timeStamp2 = "24d95a54"
val nBits2 = "30c31b18"
val nonce2 = "fe9f0864"
val hex2 = version2 + prevBlockHash2 + merkleRoot2 + timeStamp2 + nBits2 + nonce2
val hash = "000000000000000009a11b3972c8e532fe964de937c9e0096b43814e67af3728"
val hash = "2837af674e81436b09e0c937e94d96fe32e5c872391ba1090000000000000000"
val blockHeader = RawBlockHeaderSerializer.read(hex2)
blockHeader.version must be (2)
blockHeader.previousBlockHash must be (DoubleSha256Digest(prevBlockHash2))
@ -66,16 +65,13 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
it must "parse/write testnet block header" in {
//https://test-insight.bitpay.com/block/00000000009fdf81e6efa251bc1902aedc07dc499cbe17db6e33db61eb64a7c5
val version = "00000020"
val prevBlockHash = "0000000000f2dcc3d0b1d39296a24de96bb56185734d00932b101a5ed30fcd06"
val merkleRoot = "244e2160bc723be6a5f82fe3133daeafce417da3560e89bdc6c50aa20774fb8d"
val prevBlockHashFlipped = "06cd0fd35e1a102b93004d738561b56be94da29692d3b1d0c3dcf20000000000"
val merkleRootFlipped = "8dfb7407a20ac5c6bd890e56a37d41ceafae3d13e32ff8a5e63b72bc60214e24"
val prevBlockHash = "06cd0fd35e1a102b93004d738561b56be94da29692d3b1d0c3dcf20000000000"
val merkleRoot = "8dfb7407a20ac5c6bd890e56a37d41ceafae3d13e32ff8a5e63b72bc60214e24"
val timeStamp = "0ae75557" //1465247498
val nBits = "FFFF001D".toLowerCase
val nonce = "43e3fe9e"
val hex = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
val writtenHex = version + prevBlockHashFlipped + merkleRootFlipped + timeStamp + nBits + nonce
val hash = "00000000009fdf81e6efa251bc1902aedc07dc499cbe17db6e33db61eb64a7c5"
val hash = "c5a764eb61db336edb17be9c49dc07dcae0219bc51a2efe681df9f0000000000"
val blockHeader = RawBlockHeaderSerializer.read(hex)
blockHeader.version must be (536870912)
blockHeader.previousBlockHash must be (DoubleSha256Digest(prevBlockHash))
@ -84,6 +80,6 @@ class RawBlockHeaderSerializerTest extends FlatSpec with MustMatchers{
blockHeader.nBits must be (486604799)
blockHeader.nonce must be (2667504451L)
blockHeader.hash must be (DoubleSha256Digest(hash))
RawBlockHeaderSerializer.write(blockHeader) must be (writtenHex)
RawBlockHeaderSerializer.write(blockHeader) must be (hex)
}
}

View file

@ -15,14 +15,12 @@ class RawBlockSerializerTest extends FlatSpec with MustMatchers with BitcoinSLog
//https://webbtc.com/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
val version = "01000000"
val prevBlockHash = "0000000000000000000000000000000000000000000000000000000000000000"
val merkleRoot = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
val merkleRootFlipped = "3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A".toLowerCase
val merkleRoot = "3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A".toLowerCase
val timeStamp = "29AB5F49".toLowerCase
val nBits = "FFFF001D".toLowerCase
val nonce = "1DAC2B7C".toLowerCase
val hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
val header = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
val writtenHeader = version + prevBlockHash + merkleRootFlipped + timeStamp + nBits + nonce //prevHash not flipped b/c all zeroes
val rawTx1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4" +
"d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e2062726" +
"96e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678" +
@ -32,7 +30,6 @@ class RawBlockSerializerTest extends FlatSpec with MustMatchers with BitcoinSLog
val txSeq = List(tx1)
val uInt = CompactSizeUInt(1, 1)
val hex = header + uInt.hex + rawTx1
val writtenHex = writtenHeader + uInt.hex + rawTx1
"RawBlockSerializer" must "parse genesis block" in {
val block = RawBlockSerializer.read(hex)
@ -40,27 +37,24 @@ class RawBlockSerializerTest extends FlatSpec with MustMatchers with BitcoinSLog
block.txCount must be (uInt)
block.blockHeader must be (RawBlockHeaderSerializer.read(header))
block.transactions must be (txSeq)
block.blockHeader.hash.hex must be ("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
block.hex must be (writtenHex)
block.blockHeader.hash.hex must be ("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000")
block.hex must be (hex)
}
it must "write genesis block" in {
val block = RawBlockSerializer.read(hex)
RawBlockSerializer.write(block) must be(writtenHex)
RawBlockSerializer.write(block) must be(hex)
}
it must "parse/write a block other than genesis" in {
//https://test-insight.bitpay.com/block/00000000009fdf81e6efa251bc1902aedc07dc499cbe17db6e33db61eb64a7c5
val version = "00000020"
val merkleRoot = "244e2160bc723be6a5f82fe3133daeafce417da3560e89bdc6c50aa20774fb8d"
val prevBlockHash = "0000000000f2dcc3d0b1d39296a24de96bb56185734d00932b101a5ed30fcd06"
val merkleRootFlipped = "8dfb7407a20ac5c6bd890e56a37d41ceafae3d13e32ff8a5e63b72bc60214e24" // flipped
val prevBlockHashFlipped = "06cd0fd35e1a102b93004d738561b56be94da29692d3b1d0c3dcf20000000000" //flipped
val merkleRoot = "8dfb7407a20ac5c6bd890e56a37d41ceafae3d13e32ff8a5e63b72bc60214e24"
val prevBlockHash = "06cd0fd35e1a102b93004d738561b56be94da29692d3b1d0c3dcf20000000000"
val timeStamp = "0ae75557" //1465247498
val nBits = "FFFF001D".toLowerCase
val nonce = "43e3fe9e"
val header = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
val writtenHeader = version + prevBlockHashFlipped + merkleRootFlipped + timeStamp + nBits + nonce
val rawTx1 = "0100000001000000000000000000000000000000000000000000000000000000000" +
"0000000ffffffff04031d410dffffffff04f8f3b1110000000017a914349ef962198fcc875f45" +
"e786598272ecace9818d87286bee000000000017a914349ef962198fcc875f45e786598272ecac" +
@ -70,32 +64,28 @@ class RawBlockSerializerTest extends FlatSpec with MustMatchers with BitcoinSLog
val txSeq = List(tx1)
val uInt = CompactSizeUInt(1, 1)
val hex = header + uInt.hex + rawTx1
val writtenHex = writtenHeader + uInt.hex + rawTx1
//matches real hex from
//https://test.webbtc.com/block/00000000009fdf81e6efa251bc1902aedc07dc499cbe17db6e33db61eb64a7c5.hex
val block = RawBlockSerializer.read(hex)
block.blockHeader.hex must be (writtenHeader)
block.blockHeader.hex must be (header)
block.transactions must be (txSeq)
block.blockHeader.hash.hex must be ("00000000009fdf81e6efa251bc1902aedc07dc499cbe17db6e33db61eb64a7c5")
block.hex must be (writtenHex)
block.blockHeader.hash.hex must be ("c5a764eb61db336edb17be9c49dc07dcae0219bc51a2efe681df9f0000000000")
block.hex must be (hex)
block.txCount must be (uInt)
block.txCount.num must be (1)
RawBlockSerializer.write(block) must be (writtenHex)
RawBlockSerializer.write(block) must be (hex)
}
it must "parse block with more than 1 transaction" in {
//https://test.webbtc.com/block/000000000000189efaecf3ed9108b9de5320671c66a161a038f87b3e11493d5f.json
val version = "00000020"
val prevBlockHash = "0000000000d874314a3d72f62fe4ef2c9faa09f4f37747e8d99509317c3be3cd"
val merkleRoot = "85a6607c24ea4db917264d4e7722b69888e02d6469579ed466eea663a86c83cf"
val prevBlockHashFlipped = BitcoinSUtil.flipEndianess("0000000000d874314a3d72f62fe4ef2c9faa09f4f37747e8d99509317c3be3cd")
val merkleRootFlipped = BitcoinSUtil.flipEndianess("85a6607c24ea4db917264d4e7722b69888e02d6469579ed466eea663a86c83cf")
val prevBlockHash = "cde33b7c310995d9e84777f3f409aa9f2cefe42ff6723d4a3174d80000000000"
val merkleRoot = "cf836ca863a6ee66d49e5769642de08898b622774e4d2617b94dea247c60a685"
val timeStamp = "90895757" //in hex. 1465354640 as long
val nBits = "6271191a"
val nonce = "8f548695"
val header = version + prevBlockHash + merkleRoot + timeStamp + nBits + nonce
val writtenHeader = version + prevBlockHashFlipped + merkleRootFlipped + timeStamp + nBits + nonce
val rawTx1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1f0" +
"343430d2f48616f4254432f48616f427463506f6f6c2f0504ecfde9ff0400ffffffff01757fa012000000001976a9149" +
"f9a1576ec07a376fa1955bd063674cc341154d188ac00000000"
@ -112,17 +102,16 @@ class RawBlockSerializerTest extends FlatSpec with MustMatchers with BitcoinSLog
val txSeq = List(tx1, tx2)
val uInt = CompactSizeUInt(2,1)
val hex = header + uInt.hex + rawTx1 + rawTx2
val writtenHex = writtenHeader + uInt.hex + rawTx1 + rawTx2
val block = RawBlockSerializer.read(hex)
block.blockHeader.hash.hex must be ("000000000000189efaecf3ed9108b9de5320671c66a161a038f87b3e11493d5f")
block.blockHeader.hash.hex must be ("5f3d49113e7bf838a061a1661c672053deb90891edf3ecfa9e18000000000000")
block.blockHeader.version must be (536870912)
block.blockHeader.previousBlockHash must be (DoubleSha256Digest("0000000000d874314a3d72f62fe4ef2c9faa09f4f37747e8d99509317c3be3cd"))
block.blockHeader.merkleRootHash must be (DoubleSha256Digest("85a6607c24ea4db917264d4e7722b69888e02d6469579ed466eea663a86c83cf"))
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 must be (RawBlockHeaderSerializer.read(header))
block.txCount.num must be (txSeq.size)
block.hex must be (writtenHex)
block.hex must be (hex)
}
}