def test_fork_grow_no_reconverge(self): stream = open(self.chain.blk_files[0], 'r') # Mock reconverge method self.chain.reconverge = MagicMock() # Add one block block1 = self.chain.handle_stream_block(BlockFactory.from_stream(stream)['block']) # Add 10 blocks to the main chain for i in range(10): self.chain.handle_stream_block(BlockFactory.from_stream(stream)['block']) # simulate fork block2 = BlockFactory.from_stream(stream)['block'] block2.previousblockhash = block1.hash added = self.chain.handle_stream_block(block2) # make sure its not on the main chain self.assertNotEqual(added.chain, MAIN_CHAIN) self.chain.db.update_block = MagicMock() # simulate fork grow block3 = BlockFactory.from_stream(stream)['block'] block3.previousblockhash = block2.hash added = self.chain.handle_stream_block(block3) # check if it belongs to the same sidechain as block2 self.assertEqual(added.chain, block2.chain) self.assertTrue(self.chain.db.update_block.called) # Reconverge shouldn't be called self.assertFalse(self.chain.reconverge.called)
def test_fork_grow_reconverge(self): stream = open(self.chain.blk_files[0], 'r') # Add one block block1 = self.chain.handle_stream_block(BlockFactory.from_stream(stream)['block']) # Add the second block (we'll use it to check if reconverge worked) block2 = self.chain.handle_stream_block(BlockFactory.from_stream(stream)['block']) # Make sure it's initially on the main chain self.assertEqual(block2.chain, MAIN_CHAIN) # Add 10 blocks to the main chain for i in range(10): self.chain.handle_stream_block(BlockFactory.from_stream(stream)['block']) # Simulate fork on block1 block3 = BlockFactory.from_stream(stream)['block'] block3.previousblockhash = block1.hash added = self.chain.handle_stream_block(block3) self.assertNotEqual(added.chain, MAIN_CHAIN) # Simulate fork grow and reconverge block4 = BlockFactory.from_stream(stream)['block'] block4.previousblockhash = block3.hash block4.work += 10000000 added = self.chain.handle_stream_block(block4) # After the reconverge the added block should be on the main chain self.assertEqual(added.chain, MAIN_CHAIN) # And it should be the tip of the main chain self.assertEqual(added.hash, self.chain.chain_peak.hash) # Block2 should not be on the main chain any more self.assertNotEqual(self.chain.db.get_block(block2.hash).chain, MAIN_CHAIN)
def test_fork_reconverge(self): # Create 3 blocks stream = open(self.chain.blk_files[0], 'r') block1 = BlockFactory.from_stream(stream)['block'] block2 = BlockFactory.from_stream(stream)['block'] block3 = BlockFactory.from_stream(stream)['block'] # Simulate fork - the 3rd block now points to the 1st # instead to the 2nd block so it forks from the main chain block3.previousblockhash = block1.hash # Increase work so reconverge happens block3.work = block3.work + 1000000000 self.chain.handle_stream_block(block1) added = self.chain.handle_stream_block(block2) # Block2 should initially be on the main chain self.assertEqual(added.chain, MAIN_CHAIN) added = self.chain.handle_stream_block(block3) # After the reconverge the newest block should be on the main chain self.assertEqual(added.chain, MAIN_CHAIN) # And it should be the tip of the main chain self.assertEqual(self.chain.chain_peak.hash, block3.hash) # After the reconverge block2 should be on a sidechain self.assertNotEqual(self.chain.db.get_block(block2.hash), MAIN_CHAIN) self.assertEqual(self.chain.num_convergences, 1) self.assertEqual(len(self.chain.db.block_cache), 2)
def test_fork_no_reconverge(self): # Create 3 blocks stream = open(self.chain.blk_files[0], 'r') block1 = BlockFactory.from_stream(stream)['block'] block2 = BlockFactory.from_stream(stream)['block'] block3 = BlockFactory.from_stream(stream)['block'] # Mock reconverge method self.chain.reconverge = MagicMock() # Simulate fork - the 3rd block now points to the 1st # instead to the 2nd block so it forks from the main chain block3.previousblockhash = block1.hash self.chain.handle_stream_block(block1) self.chain.handle_stream_block(block2) added = self.chain.handle_stream_block(block3) # The added block should not be on the main chain self.assertEqual(added.chain, MAIN_CHAIN + 1) self.assertEqual(added.height, block1.height + 1) # Reconverge shouldn't be called self.assertFalse(self.chain.reconverge.called)
def test_append_to_main_chain(self): self.chain.db.put_block = MagicMock() stream = open(self.chain.blk_files[0], 'r') block1 = BlockFactory.from_stream(stream)['block'] block2 = BlockFactory.from_stream(stream)['block'] self.chain.handle_stream_block(block1) added_block = self.chain.handle_stream_block(block2) self.assertEqual(added_block.height, block1.height + 1) self.assertEqual(added_block.chainwork, block1.chainwork + block2.work) self.assertEqual(added_block.chain, 0) self.assertEqual(self.chain.chain_peak.hash, block2.hash) # Persistence check self.assertEqual(self.chain.db.put_block.call_count, 1)
def test_from_stream(self): stream = open('test_data/blk00001.dat', 'r') block = BlockFactory.from_stream(stream) self.assertIsNotNone(block) self.assertIsNotNone(block.bits) self.assertIsNone(block.chain) self.assertIsNone(block.chainwork) self.assertIsNotNone(block.dat) self.assertIsNotNone(block.difficulty) self.assertIsNotNone(block.hash) self.assertIsNone(block.height) self.assertIsNotNone(block.merkleroot) self.assertIsNone(block.nextblockhash) self.assertIsNotNone(block.nonce) self.assertIsNotNone(block.previousblockhash) self.assertIsNotNone(block.size) self.assertIsNotNone(block.target) self.assertIsNotNone(block.time) self.assertIsNotNone(block.total) self.assertIsNotNone(block.tx) self.assertIsNotNone(block.version) self.assertIsNotNone(block.work) for tr in block.tx: self._check_transaction(tr) for vin in tr.vin: self._check_vin(vin) for vout in tr.vout: self._check_vout(vout)
def test_from_rpc(self): with open('test_data/rpc_data.json') as json_data: data = simplejson.load(json_data) block = BlockFactory.from_rpc(data['block'], data['transactions']) self.assertIsNotNone(block) self.assertIsNotNone(block.bits) self.assertIsNone(block.chain) self.assertIsNotNone(block.chainwork) self.assertIsNone(block.dat) self.assertIsNotNone(block.difficulty) self.assertIsNotNone(block.hash) self.assertIsNotNone(block.height) self.assertIsNotNone(block.merkleroot) self.assertIsNotNone(block.nextblockhash) self.assertIsNotNone(block.nonce) self.assertIsNotNone(block.previousblockhash) self.assertIsNotNone(block.size) self.assertIsNotNone(block.target) self.assertIsNotNone(block.time) self.assertIsNotNone(block.total) self.assertIsNotNone(block.tx) self.assertIsNotNone(block.version) self.assertIsNotNone(block.work) for tr in block.tx: self._check_transaction(tr) for vin in tr.vin: self._check_vin(vin) for vout in tr.vout: self._check_vout(vout)
def setUp(self): self.db = MagicMock() self.example_block = BlockFactory.from_mongo(EXAMPLE_MONGO_BLOCK) self.db.blocks.find_one = MagicMock(return_value=EXAMPLE_MONGO_BLOCK) self.chain = ExploderSyncer( database=self.db, blocks_dir="/home/vagrant/.gamecredits/blocks/", rpc_client=MagicMock() ) self.db.blocks.create_index = MagicMock() self.SYNC_LIMIT = 100
def setUp(self): self.fake_mongo = MagicMock() self.fake_mongo.blocks.find_one.return_value = None self.fake_rpc = MagicMock() self.fake_rpc.getblockcount = MagicMock(return_value=10000) self.db = DatabaseGateway(database=self.fake_mongo, cache_size=1000) self.db.highest_block = PropertyMock(return_value=None) self.chain = ExploderSyncer( database=self.db, blocks_dir="/home/vagrant/.gamecredits/blocks/", rpc_client=self.fake_rpc ) self.example_block = BlockFactory.from_mongo(EXAMPLE_MONGO_BLOCK)