async def gather_subblocks(self, total_contacts, current_height=0, current_hash='0' * 64, quorum_ratio=0.66, adequate_ratio=0.5, expected_subblocks=4): self.sbc_inbox.expected_subblocks = expected_subblocks block = storage.get_latest_block_height(self.driver) self.log.info( f'Expecting {expected_subblocks} subblocks from {total_contacts} delegates.' ) contenders = BlockContender(total_contacts=total_contacts, required_consensus=quorum_ratio, total_subblocks=expected_subblocks, acceptable_consensus=adequate_ratio) # Add timeout condition. started = time.time() last_log = started while (not contenders.block_has_consensus() and contenders.responses < contenders.total_contacts) and \ time.time() - started < self.seconds_to_timeout: if self.sbc_inbox.has_sbc(): sbcs = await self.sbc_inbox.receive_sbc( ) # Can probably make this raw sync code self.log.info('Pop it in there.') contenders.add_sbcs(sbcs) if time.time() - last_log > 5: self.log.error( f'Waiting for contenders for {int(time.time() - started)}s.' ) last_log = time.time() await asyncio.sleep(0) if time.time() - started > self.seconds_to_timeout: self.log.error( f'Block timeout. Too many delegates are offline! Kick out the non-responsive ones! {block}' ) self.log.info('Done aggregating new block.') block = contenders.get_current_best_block() self.log.error(block) self.sbc_inbox.q.clear() # self.log.info(f'Best block: {block}') return block_from_subblocks(block, previous_hash=current_hash, block_num=current_height + 1)
def test_should_process_block_true_if_expected_block_equal_to_block(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) self.assertTrue(node.should_process(block))
def generate_blocks(number_of_blocks): previous_hash = '0' * 64 previous_number = 0 blocks = [] for i in range(number_of_blocks): new_block = canonical.block_from_subblocks(subblocks=[], previous_hash=previous_hash, block_num=previous_number + 1) blocks.append(new_block) previous_hash = new_block['hash'] previous_number += 1 return blocks
def test_process_new_block_updates_state(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) node.process_new_block(block) self.assertEqual(storage.get_latest_block_height(node.driver), 1) self.assertEqual(storage.get_latest_block_hash(node.driver), block['hash'])
def generate_blocks(number_of_blocks, subblocks=[]): previous_hash = '0' * 64 previous_number = 0 blocks = [] for i in range(number_of_blocks): if len(subblocks) > i: subblock = subblocks[i] else: subblock = [] new_block = canonical.block_from_subblocks(subblocks=subblock, previous_hash=previous_hash, block_num=previous_number + 1) blocks.append(new_block) previous_hash = new_block['hash'] previous_number += 1 return blocks
def test_process_new_block_clears_cache(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node( socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver, store=True, blocks=self.blocks, ) node.driver.cache['test'] = 123 node.process_new_block(block) self.assertIsNone(node.driver.cache.get('test'))
def test_process_new_block_stores_block_if_should_store(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node( socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver, store=True, blocks=self.blocks, ) node.process_new_block(block) b = node.blocks.get_block(1) self.assertEqual(b, block)