def testNewDifficultyMatch(self): prevBlockHash = 0x000000000000000005d1e9e192a43a19e2fbd933ffb27df2623187ad5ce10adc startBlock = 342720 self.c.setInitialParent(prevBlockHash, startBlock-1, 1) # start at 0, for difficultyAdjustment tests otherwise getBlockHash out of bounds count = 2016 with open("test/headers/blockchain_headers") as f: f.seek(80 * startBlock) bhBytes = f.read(80 * count) assert self.c.bulkStoreHeader(bhBytes, count) == startBlock-1+count assert self.c.getLastBlockHeight() == startBlock-1+count assert self.c.getChainWork() == count*44455415962 + 1 # score starts at 1 # adding a low difficulty block should fail since bits!=newBits version = 2 hashMerkleRoot = 0 # doesn't matter time = 1424648937 # same as real block 344736 bits = 0x207FFFFF # REGTEST_EASIEST_DIFFICULTY nonce = 0 hashPrevBlock = 0x00000000000000000f9e30784bd647e91f6923263a674c9c5c18084fe79a41f8 # block 344735 bhBytes = getHeaderBytes(version, hashPrevBlock, hashMerkleRoot, time, bits, nonce) blockHash = dblSha256Flip(bhBytes) assert blockHash == 0x0016127022e6debe87071eb0091918d2fccbcef0d46a046bcaf71309b0528044 assert self.c.getBlockchainHead() == hashPrevBlock eventArr = [] self.s.block.log_listeners.append(lambda x: eventArr.append(self.c._translator.listen(x))) assert self.c.storeBlockHeader(bhBytes) == 0 assert eventArr == [{'_event_type': 'StoreHeader', 'blockHash': blockHash, 'returnCode': self.ERR_RETARGET }] eventArr.pop() # add the real block version = 2 hashMerkleRoot = 0x734c8b7ea7767005409c23a4b907d07329dadc4bac573b2c809f642eec4de26b time = 1424648937 bits = 404196666 nonce = 550403378 hashPrevBlock = 0x00000000000000000f9e30784bd647e91f6923263a674c9c5c18084fe79a41f8 # block 344735 bhBytes = getHeaderBytes(version, hashPrevBlock, hashMerkleRoot, time, bits, nonce) assert dblSha256Flip(bhBytes) == 0x00000000000000001097f043cca218169e00623c9962b25a0b159eaca2d8ca25 assert self.c.getBlockchainHead() == hashPrevBlock assert self.c.storeBlockHeader(bhBytes) == startBlock-1+count + 1 assert count + 1 == 2017
def testDifficultyShouldBeSame(self): prevBlockHash = 0x000000000000000005d1e9e192a43a19e2fbd933ffb27df2623187ad5ce10adc startBlock = 342720 self.c.setInitialParent(prevBlockHash, startBlock-1, 1) count = 3 with open("test/headers/blockchain_headers") as f: f.seek(80 * startBlock) bhBytes = f.read(80 * count) assert self.c.bulkStoreHeader(bhBytes, count) == startBlock-1+count assert self.c.getLastBlockHeight() == startBlock-1+count assert self.c.getChainWork() == count*44455415962 + 1 # score starts at 1 # adding a low difficulty block should fail since bits!=prevBits version = 1 hashMerkleRoot = 0 # doesn't matter time = 1423499049 # same as real block 342723 bits = 0x207FFFFF # REGTEST_EASIEST_DIFFICULTY nonce = 0 hashPrevBlock = 0x000000000000000004db26747ccd2feb6341c18282a33e2c5d8eb84a1b12d951 # block 342722 bhBytes = getHeaderBytes(version, hashPrevBlock, hashMerkleRoot, time, bits, nonce) blockHash = dblSha256Flip(bhBytes) assert blockHash == 0x2afa6cec2435698406ff2138ae6162469857524c7849970e5bb82039e90a099b eventArr = [] self.s.block.log_listeners.append(lambda x: eventArr.append(self.c._translator.listen(x))) assert self.c.storeBlockHeader(bhBytes) == 0 assert eventArr == [{'_event_type': 'StoreHeader', 'blockHash': blockHash, 'returnCode': self.ERR_DIFFICULTY }] eventArr.pop()
def testVerifyFailAfterReorg(self): block100kPrev = 0x000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250 self.c.setInitialParent(block100kPrev, 99999, 1) # tx for verification: values are from block 100K tx = 0x8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87 txIndex = 0 sibling = [None] * 2 sibling[0] = 0xfff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4 sibling[1] = 0x8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49 # insert (easy) blocks # using script/mine.py these are the next 7 blocks # nonce: 0 blockhash: 11bb7c5555b8eab7801b1c4384efcab0d869230fcf4a8f043abad255c99105f8 # nonce: 0 blockhash: 178930a916fa91dd29b2716387b7e024a6b3b2d2efa86bc45c86be223b07a4e5 # nonce: 0 blockhash: 7b3c348edbb3645b34b30259105a941890e95e0ecc0a1c243ff48260d746e456 # nonce: 0 blockhash: 02c67135bd91986f9aaf3f0818baab439202fe5c34400c2c10bff6cd1336d436 # nonce: 1 blockhash: 6e60065cc981914c23897143c75f0cde6e456df65f23afd41ddc6e6ce86b2b63 # nonce: 1 blockhash: 38a052cdf4ef0fddf2de88e687163db7f39cb8de738fa9f5e871a72fc74c57c1 # nonce: 0 blockhash: 2b80a2f4b68e9ebfd4975f5f14a340501d24c3adf041ad9be4cd2576e827328c REGTEST_EASIEST_DIFFICULTY = 0x207fFFFFL version = 1 # real merkle of block100k hashMerkleRoot = 0xf3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 time = 1293623863 # from block100k bits = REGTEST_EASIEST_DIFFICULTY nonce = 1 hashPrevBlock = block100kPrev for i in range(7): nonce = 1 if (i in [4,5]) else 0 blockHeaderBytes = getHeaderBytes(version, hashPrevBlock, hashMerkleRoot, time, bits, nonce) res = self.c.storeBlockHeader(blockHeaderBytes) hashPrevBlock = dblSha256Flip(blockHeaderBytes) assert res == i+100000 # testingonlySetHeaviest is needed because the difficulty from # REGTEST_EASIEST_DIFFICULTY becomes 0 and so the score does not # increase, meaning that heaviesBlock also does not change self.c.testingonlySetHeaviest(0x2b80a2f4b68e9ebfd4975f5f14a340501d24c3adf041ad9be4cd2576e827328c) firstEasyBlock = 0x11bb7c5555b8eab7801b1c4384efcab0d869230fcf4a8f043abad255c99105f8 res = self.c.helperVerifyHash__(tx, txIndex, sibling, firstEasyBlock) assert res == 1 # reorg: add headers with more PoW (difficulty) # add headers one by one and tx should only be verified when the # last header is added, ie tx has enough confirmations headers = [ "0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710", "0100000006e533fd1ada86391f3f6c343204b0d278d4aaec1c0b20aa27ba0300000000006abbb3eb3d733a9fe18967fd7d4c117e4ccbbac5bec4d910d900b3ae0793e77f54241b4d4c86041b4089cc9b", "0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf93", "01000000aff7e0c7dc29d227480c2aa79521419640a161023b51cdb28a3b0100000000003779fc09d638c4c6da0840c41fa625a90b72b125015fd0273f706d61f3be175faa271b4d4c86041b142dca82", "01000000e1c5ba3a6817d53738409f5e7229ffd098d481147b002941a7a002000000000077ed2af87aa4f9f450f8dbd15284720c3fd96f565a13c9de42a3c1440b7fc6a50e281b4d4c86041b08aecda2", "0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d63", "0100000045dc58743362fe8d8898a7506faa816baed7d391c9bc0b13b0da00000000000021728a2f4f975cc801cb3c672747f1ead8a946b2702b7bd52f7b86dd1aa0c975c02a1b4d4c86041b7b47546d" ] blockHeaderBytes = map(lambda x: x.decode('hex'), headers) block100k = 0x000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506 for i in range(7): res = self.c.storeBlockHeader(blockHeaderBytes[i]) assert res == i+100000 # firstEasyBlock should no longer verify since it is no longer on the main chain res = self.c.helperVerifyHash__(tx, txIndex, sibling, firstEasyBlock) assert res == self.ERR_CHAIN # block100k should only verify when it has enough confirmations res = self.c.helperVerifyHash__(tx, txIndex, sibling, block100k) exp = 1 if i==6 else self.ERR_CONFIRMATIONS assert res == exp
def testHeadersFrom100K(self): block100kPrev = 0x000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250 self.c.setInitialParent(block100kPrev, 99999, 1) headers = [ "0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710", "0100000006e533fd1ada86391f3f6c343204b0d278d4aaec1c0b20aa27ba0300000000006abbb3eb3d733a9fe18967fd7d4c117e4ccbbac5bec4d910d900b3ae0793e77f54241b4d4c86041b4089cc9b", "0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf93", "01000000aff7e0c7dc29d227480c2aa79521419640a161023b51cdb28a3b0100000000003779fc09d638c4c6da0840c41fa625a90b72b125015fd0273f706d61f3be175faa271b4d4c86041b142dca82", "01000000e1c5ba3a6817d53738409f5e7229ffd098d481147b002941a7a002000000000077ed2af87aa4f9f450f8dbd15284720c3fd96f565a13c9de42a3c1440b7fc6a50e281b4d4c86041b08aecda2", "0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d63", "0100000045dc58743362fe8d8898a7506faa816baed7d391c9bc0b13b0da00000000000021728a2f4f975cc801cb3c672747f1ead8a946b2702b7bd52f7b86dd1aa0c975c02a1b4d4c86041b7b47546d" ] blockHeaderBytes = map(lambda x: x.decode('hex'), headers) for i in range(7): res = self.c.storeBlockHeader(blockHeaderBytes[i]) # print('@@@@ real chain score: ' + str(self.c.getChainWork())) assert res == i+100000 chainWork = self.c.getChainWork() # block hashes b0 = 0x000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506 b1 = 0x00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090 # block #100001 b2 = 0x0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af b3 = 0x000000000002a0a74129007b1481d498d0ff29725e9f403837d517683abac5e1 b4 = 0x000000000000b0b8b4e8105d62300d63c8ec1a1df0af1c2cdbd943b156a8cd79 b5 = 0x000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45 b6 = 0x0000000000009b958a82c10804bd667722799cc3b457bc061cd4b7779110cd60 # values are from block 100K tx = 0x8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87 txIndex = 0 sibling = [None] * 2 sibling[0] = 0xfff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4 sibling[1] = 0x8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49 txBlockHash = 0xdead res = self.c.helperVerifyHash__(tx, txIndex, sibling, txBlockHash) assert res == self.ERR_CHAIN # b1 is within6confirms so should NOT verify # TODO use proper tx, txIndex, sibling. Should also test that # when another header is added, the tx does verify txBlockHash = b1 res = self.c.helperVerifyHash__(tx, txIndex, sibling, txBlockHash) assert res == self.ERR_CONFIRMATIONS # verifyTx should only return 1 for b0 txBlockHash = b0 res = self.c.helperVerifyHash__(tx, txIndex, sibling, txBlockHash) assert res == 1 assert b6 == self.c.getBlockchainHead() # insert (fake) blocks that will not be on main chain # using script/mine.py (commit 3908709) these are the next 7 blocks # nonce: 0 blockhash: 11bb7c5555b8eab7801b1c4384efcab0d869230fcf4a8f043abad255c99105f8 # nonce: 0 blockhash: 178930a916fa91dd29b2716387b7e024a6b3b2d2efa86bc45c86be223b07a4e5 # nonce: 0 blockhash: 7b3c348edbb3645b34b30259105a941890e95e0ecc0a1c243ff48260d746e456 # nonce: 0 blockhash: 02c67135bd91986f9aaf3f0818baab439202fe5c34400c2c10bff6cd1336d436 # nonce: 1 blockhash: 6e60065cc981914c23897143c75f0cde6e456df65f23afd41ddc6e6ce86b2b63 # nonce: 1 blockhash: 38a052cdf4ef0fddf2de88e687163db7f39cb8de738fa9f5e871a72fc74c57c1 # nonce: 0 blockhash: 2b80a2f4b68e9ebfd4975f5f14a340501d24c3adf041ad9be4cd2576e827328c # https://bitcoin.org/en/developer-reference#target-nbits # Difficulty 1, the minimum allowed difficulty, is represented on # mainnet and the current testnet by the nBits value 0x1d00ffff. # Regtest mode uses a different difficulty 1 value of 0x207fffff, # the highest possible value below uint32_max which can be encoded; # this allows near-instant building of blocks in regtest mode. REGTEST_EASIEST_DIFFICULTY = 0x207fFFFFL version = 1 # real merkle of block100k hashMerkleRoot = 0xf3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 time = 1293623863 # from block100k bits = REGTEST_EASIEST_DIFFICULTY nonce = 1 hashPrevBlock = block100kPrev for i in range(7): nonce = 1 if (i in [4,5]) else 0 blockHeaderBytes = getHeaderBytes(version, hashPrevBlock, hashMerkleRoot, time, bits, nonce) res = self.c.storeBlockHeader(blockHeaderBytes) hashPrevBlock = dblSha256Flip(blockHeaderBytes) # print('@@@@ fake chain score: ' + str(self.c.getChainWork())) assert res == i+100000 # fake blocks are stored since there is possibility they can become the main chain assert self.c.getChainWork() == chainWork # chainWork should not change assert b6 == self.c.getBlockchainHead() # forked block should NOT verify txBlockHash = 0x11bb7c5555b8eab7801b1c4384efcab0d869230fcf4a8f043abad255c99105f8 res = self.c.helperVerifyHash__(tx, txIndex, sibling, txBlockHash) assert res == self.ERR_CHAIN # b0 should still verify txBlockHash = b0 res = self.c.helperVerifyHash__(tx, txIndex, sibling, txBlockHash) assert res == 1