You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

invalidblockrequest.py 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2015-2016 The Bitcoin Core developers
  3. # Distributed under the MIT software license, see the accompanying
  4. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. """Test node responses to invalid blocks.
  6. In this test we connect to one node over p2p, and test block requests:
  7. 1) Valid blocks should be requested and become chain tip.
  8. 2) Invalid block with duplicated transaction should be re-requested.
  9. 3) Invalid block with bad coinbase value should be rejected and not
  10. re-requested.
  11. """
  12. from test_framework.test_framework import ComparisonTestFramework
  13. from test_framework.util import *
  14. from test_framework.comptool import TestManager, TestInstance, RejectResult
  15. from test_framework.blocktools import *
  16. import copy
  17. import time
  18. # Use the ComparisonTestFramework with 1 node: only use --testbinary.
  19. class InvalidBlockRequestTest(ComparisonTestFramework):
  20. ''' Can either run this test as 1 node with expected answers, or two and compare them.
  21. Change the "outcome" variable from each TestInstance object to only do the comparison. '''
  22. def set_test_params(self):
  23. self.num_nodes = 1
  24. self.setup_clean_chain = True
  25. def run_test(self):
  26. test = TestManager(self, self.options.tmpdir)
  27. test.add_all_connections(self.nodes)
  28. self.tip = None
  29. self.block_time = None
  30. NetworkThread().start() # Start up network handling in another thread
  31. test.run()
  32. def get_tests(self):
  33. if self.tip is None:
  34. self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0)
  35. self.block_time = int(time.time())+1
  36. '''
  37. Create a new block with an anyone-can-spend coinbase
  38. '''
  39. height = 1
  40. block = create_block(self.tip, create_coinbase(height), self.block_time)
  41. self.block_time += 1
  42. block.solve()
  43. # Save the coinbase for later
  44. self.block1 = block
  45. self.tip = block.sha256
  46. height += 1
  47. yield TestInstance([[block, True]])
  48. '''
  49. Now we need that block to mature so we can spend the coinbase.
  50. '''
  51. test = TestInstance(sync_every_block=False)
  52. for i in range(100):
  53. block = create_block(self.tip, create_coinbase(height), self.block_time)
  54. block.solve()
  55. self.tip = block.sha256
  56. self.block_time += 1
  57. test.blocks_and_transactions.append([block, True])
  58. height += 1
  59. yield test
  60. '''
  61. Now we use merkle-root malleability to generate an invalid block with
  62. same blockheader.
  63. Manufacture a block with 3 transactions (coinbase, spend of prior
  64. coinbase, spend of that spend). Duplicate the 3rd transaction to
  65. leave merkle root and blockheader unchanged but invalidate the block.
  66. '''
  67. block2 = create_block(self.tip, create_coinbase(height), self.block_time)
  68. self.block_time += 1
  69. # b'0x51' is OP_TRUE
  70. tx1 = create_transaction(self.block1.vtx[0], 0, b'\x51', 50 * COIN)
  71. tx2 = create_transaction(tx1, 0, b'\x51', 50 * COIN)
  72. block2.vtx.extend([tx1, tx2])
  73. block2.hashMerkleRoot = block2.calc_merkle_root()
  74. block2.rehash()
  75. block2.solve()
  76. orig_hash = block2.sha256
  77. block2_orig = copy.deepcopy(block2)
  78. # Mutate block 2
  79. block2.vtx.append(tx2)
  80. assert_equal(block2.hashMerkleRoot, block2.calc_merkle_root())
  81. assert_equal(orig_hash, block2.rehash())
  82. assert(block2_orig.vtx != block2.vtx)
  83. self.tip = block2.sha256
  84. yield TestInstance([[block2, RejectResult(16, b'bad-txns-duplicate')], [block2_orig, True]])
  85. height += 1
  86. '''
  87. Make sure that a totally screwed up block is not valid.
  88. '''
  89. block3 = create_block(self.tip, create_coinbase(height), self.block_time)
  90. self.block_time += 1
  91. block3.vtx[0].vout[0].nValue = 100 * COIN # Too high!
  92. block3.vtx[0].sha256=None
  93. block3.vtx[0].calc_sha256()
  94. block3.hashMerkleRoot = block3.calc_merkle_root()
  95. block3.rehash()
  96. block3.solve()
  97. yield TestInstance([[block3, RejectResult(16, b'bad-cb-amount')]])
  98. if __name__ == '__main__':
  99. InvalidBlockRequestTest().main()