def test_regular_block_template(self): manager = self.create_peer('testnet', tx_storage=self.tx_storage) # add 100 blocks blocks = add_new_blocks(manager, 100, advance_clock=15) block_templates = manager.get_block_templates() self.assertEqual(len(block_templates), 1) self.assertEqual( block_templates[0], BlockTemplate( versions={0, 3}, reward=settings.INITIAL_TOKEN_UNITS_PER_BLOCK * 100, weight=1.0, timestamp_now=int(manager.reactor.seconds()), timestamp_min=blocks[-1].timestamp + 1, timestamp_max=blocks[-1].timestamp + settings.MAX_DISTANCE_BETWEEN_BLOCKS - 1, # parents=[blocks[-1].hash, self.genesis_txs[-1].hash, self.genesis_txs[-2].hash], parents=block_templates[0].parents, parents_any=[], height=101, # genesis is 0 score=sum_weights(blocks[-1].get_metadata().score, 1.0), )) self.assertConsensusValid(manager)
def _handle_request(self, data: Dict) -> None: # only request accepted is a 'mining.notify' notification if data['method'] != 'mining.notify': self.log.warn('unknown method received', data=data) return block_templates = BlockTemplates(BlockTemplate.from_dict(d) for d in data.get('params', [])) if self._queue.done(): self._queue = self.loop.create_future() self._queue.set_result(block_templates)
async def submit(self, block: Block) -> Optional[BlockTemplate]: resp: Union[bool, Dict] = await self._do_request('mining.submit', { 'hexdata': bytes(block).hex(), }) if resp: assert isinstance(resp, Dict) error = resp.get('error') if error: raise APIError(error) return BlockTemplate.from_dict(resp['result']) return None
def test_block_template_after_genesis(self): manager = self.create_peer('testnet', tx_storage=self.tx_storage) block_templates = manager.get_block_templates() self.assertEqual(len(block_templates), 1) self.assertEqual(block_templates[0], BlockTemplate( versions={0, 3}, reward=settings.INITIAL_TOKEN_UNITS_PER_BLOCK * 100, weight=1.0, timestamp_now=int(manager.reactor.seconds()), timestamp_min=settings.GENESIS_TIMESTAMP + 3, timestamp_max=0xffffffff, # no limit for next block after genesis # parents=[tx.hash for tx in self.genesis_blocks + self.genesis_txs], parents=block_templates[0].parents, parents_any=[], height=1, # genesis is 0 score=sum_weights(self.genesis_blocks[0].weight, 1.0), ))
def _make_block_template(self, parent_block: Block, parent_txs: 'ParentTxs', current_timestamp: int, with_weight_decay: bool = False) -> BlockTemplate: """ Further implementation of making block template, used by make_block_template and make_custom_block_template """ assert parent_block.hash is not None # the absolute minimum would be the previous timestamp + 1 timestamp_abs_min = parent_block.timestamp + 1 # and absolute maximum limited by max time between blocks if not parent_block.is_genesis: timestamp_abs_max = parent_block.timestamp + settings.MAX_DISTANCE_BETWEEN_BLOCKS - 1 else: timestamp_abs_max = 0xffffffff assert timestamp_abs_max > timestamp_abs_min # actual minimum depends on the timestamps of the parent txs # it has to be at least the max timestamp of parents + 1 timestamp_min = max(timestamp_abs_min, parent_txs.max_timestamp + 1) assert timestamp_min <= timestamp_abs_max # when we have weight decay, the max timestamp will be when the next decay happens if with_weight_decay and settings.WEIGHT_DECAY_ENABLED: # we either have passed the first decay or not, the range will vary depending on that if timestamp_min > timestamp_abs_min + settings.WEIGHT_DECAY_ACTIVATE_DISTANCE: timestamp_max_decay = timestamp_min + settings.WEIGHT_DECAY_WINDOW_SIZE else: timestamp_max_decay = timestamp_abs_min + settings.WEIGHT_DECAY_ACTIVATE_DISTANCE timestamp_max = min(timestamp_abs_max, timestamp_max_decay) else: timestamp_max = timestamp_abs_max timestamp = min(max(current_timestamp, timestamp_min), timestamp_max) weight = daa.calculate_next_weight(parent_block, timestamp) parent_block_metadata = parent_block.get_metadata() height = parent_block_metadata.height + 1 parents = [parent_block.hash] + parent_txs.must_include parents_any = parent_txs.can_include # simplify representation when you only have one to choose from if len(parents) + len(parents_any) == 3: parents.extend(sorted(parents_any)) parents_any = [] assert len(parents) + len( parents_any) >= 3, 'There should be enough parents to choose from' assert 1 <= len(parents) <= 3, 'Impossible number of parents' if __debug__ and len(parents) == 3: assert len( parents_any ) == 0, 'Extra parents to choose from that cannot be chosen' return BlockTemplate( versions={ TxVersion.REGULAR_BLOCK.value, TxVersion.MERGE_MINED_BLOCK.value }, reward=daa.get_tokens_issued_per_block(height), weight=weight, timestamp_now=current_timestamp, timestamp_min=timestamp_min, timestamp_max=timestamp_max, parents=parents, parents_any=parents_any, height=height, score=sum_weights(parent_block_metadata.score, weight), )