def update_counters(self): time_diff = ntp.getTime() - self.last_rate_limit_update if time_diff > 60: self.out_counter = 0 self.in_counter = 0 self.last_rate_limit_update = ntp.getTime() return
def block_received(self, source, block: Block): self.pow.last_pb_time = ntp.getTime() logger.info('>>> Received Block #%d %s', block.block_number, bin2hstr(block.headerhash)) if source != self._target_channel: if self._target_channel is None: logger.warning('Received block and target channel is None') else: logger.warning('Received block from unexpected peer') logger.warning('Expected peer: %s', self._target_channel.peer) logger.warning('Found peer: %s', source.peer) return if block.block_number != self._last_requested_block_number: logger.warning('Did not match %s', self._last_requested_block_number) self._xrd_node.peer_manager.ban_channel(source) return target_start_blocknumber = self._target_node_header_hash.block_number expected_headerhash = self._target_node_header_hash.headerhashes[ block.block_number - target_start_blocknumber] if block.headerhash != expected_headerhash: logger.warning('Did not match headerhash') logger.warning('Expected headerhash %s', expected_headerhash) logger.warning('Found headerhash %s', block.headerhash) self._xrd_node.peer_manager.ban_channel(source) return if not block.validate(self._chain_manager, self.pow.future_blocks): logger.warning('Syncing Failed: Block Validation Failed') self._xrd_node.peer_manager.ban_channel(source) return if self._chain_manager.add_block(block, check_stale=False): if self._chain_manager.last_block.headerhash == block.headerhash: self.pow.suspend_mining_timestamp = ntp.getTime( ) + config.dev.sync_delay_mining else: logger.warning('Failed to Add Block') self._xrd_node.peer_manager.ban_channel(source) return try: reactor.download_monitor.cancel() except Exception as e: logger.warning("PB: %s", e) if self.is_syncing_finished(): return self._last_requested_block_number += 1 self.peer_fetch_block()
def handle_message_received(source, message: xrdlegacy_pb2.LegacyMessage): """ Message Receipt This function accepts message receipt from peer, checks if the message hash already been received or not. In case its a already received message, it is ignored. Otherwise the request is made to get the full message. :return: """ mr_data = message.mrData msg_hash = mr_data.hash # FIXME: Separate into respective message handlers if mr_data.type not in MessageReceipt.allowed_types: return if mr_data.type == xrdlegacy_pb2.LegacyMessage.TX and source.factory.sync_state.state != ESyncState.synced: return if mr_data.type == xrdlegacy_pb2.LegacyMessage.TX: if ntp.getTime() < source.factory.pow.suspend_mining_timestamp: return if source.factory._chain_manager.tx_pool.is_full_pending_transaction_pool( ): logger.warning( 'TX pool size full, incoming tx dropped. mr hash: %s', bin2hstr(msg_hash)) return if mr_data.type == xrdlegacy_pb2.LegacyMessage.BK: if mr_data.block_number > source.factory.chain_height + config.dev.max_margin_block_number: logger.debug('Skipping block #%s as beyond lead limit', mr_data.block_number) return if mr_data.block_number < source.factory.chain_height - config.dev.min_margin_block_number: logger.debug('Skipping block #%s as beyond the limit', mr_data.block_number) return if not source.factory.is_block_present(mr_data.prev_headerhash): logger.debug('Skipping block #%s as prev_headerhash not found', mr_data.block_number) return if source.factory.master_mr.contains(msg_hash, mr_data.type): return source.factory.master_mr.add_peer(msg_hash, mr_data.type, source, mr_data) if source.factory.master_mr.is_callLater_active( msg_hash): # Ignore if already requested return source.factory.request_full_message(mr_data)
def monitor_bk(self): # FIXME: Too many magic numbers / timing constants # FIXME: This is obsolete time_diff1 = ntp.getTime() - self.last_pow_cycle if 90 < time_diff1: if self.sync_state.state == ESyncState.unsynced: if ntp.getTime() - self.last_bk_time > 120: self.last_pow_cycle = ntp.getTime() logger.info(' POW cycle activated by monitor_bk() ') self.update_node_state(ESyncState.synced) reactor.monitor_bk = reactor.callLater(60, self.monitor_bk) return time_diff2 = ntp.getTime() - self.last_pb_time if self.sync_state.state == ESyncState.syncing and time_diff2 > 60: self.update_node_state(ESyncState.unsynced) self.epoch_diff = -1 reactor.monitor_bk = reactor.callLater(60, self.monitor_bk)
def _refresh(self): # TODO: refactored from banned peers. Rework to use a priority queue instead current_time = ntp.getTime() len_before = len(self._data) self._data = {k: v for k, v in self._data.items() if v > current_time} len_after = len(self._data) # FIXME: Drop peers beyond configuration limit if len_before != len_after: self._store()
def monitor_chain_state(self): self.peer_manager.monitor_chain_state() last_block = self._chain_manager.last_block block_metadata = self._chain_manager.get_block_metadata(last_block.headerhash) node_chain_state = xrd_pb2.NodeChainState(block_number=last_block.block_number, header_hash=last_block.headerhash, cumulative_difficulty=bytes(block_metadata.cumulative_difficulty), version=config.dev.version, timestamp=ntp.getTime()) self.peer_manager.broadcast_chain_state(node_chain_state=node_chain_state) channel = self.peer_manager.get_better_difficulty(block_metadata.cumulative_difficulty) logger.debug('Got better difficulty %s', channel) if channel: logger.debug('Connection id >> %s', channel.peer) channel.send_get_headerhash_list(self._chain_manager.height) reactor.callLater(config.user.chain_state_broadcast_period, self.monitor_chain_state)
def __init__(self): self._buffer = bytes() # Need to use composition instead of inheritance here self._observable = P2PObservable(self) self.last_rate_limit_update = 0 self.rate_limit = config.user.peer_rate_limit self.in_counter = 0 self.out_counter = 0 self.bytes_sent = 0 self.outgoing_queue = PriorityQueue(maxsize=config.user.p2p_q_size) self._connected_at = ntp.getTime() self._valid_message_count = 0 self._public_port = 0
def __init__(self, mining_address: bytes): self.start_time = ntp.getTime() self._sync_state = SyncState() self.peer_manager = P2PPeerManager() self.peer_manager.load_peer_addresses() self.p2pchain_manager = P2PChainManager() self.tx_manager = P2PTxManagement() self._chain_manager = None # FIXME: REMOVE. This is temporary self._p2pfactory = None # FIXME: REMOVE. This is temporary self._pow = None self.mining_address = mining_address reactor.callLater(10, self.monitor_chain_state)
def _mine_next(self, parent_block): if ntp.getTime() < self.suspend_mining_timestamp: return if config.user.mining_enabled: logger.debug('try get_block_metadata') parent_metadata = self.chain_manager.get_block_metadata( parent_block.headerhash) logger.debug('try prepare_next_unmined_block_template') dev_config = self.chain_manager.get_config_by_block_number( parent_block.block_number + 1) self.miner.prepare_next_unmined_block_template( mining_address=self.mining_address, tx_pool=self.chain_manager.tx_pool, parent_block=parent_block, parent_difficulty=parent_metadata.block_difficulty, dev_config=dev_config) logger.info('Mining Block #%s', parent_block.block_number + 1) self.miner.start_mining(parent_block, parent_metadata.block_difficulty, dev_config)
def pre_block_logic(self, block: Block): logger.debug('LOCK - TRY - pre_block_logic') with self.miner.lock: logger.debug('LOCK - LOCKED - pre_block_logic') if not block.validate(self.chain_manager, self.future_blocks): logger.warning('Block Validation failed for #%s %s', block.block_number, bin2hstr(block.headerhash)) return False dev_config = self.chain_manager.get_config_by_block_number( block.block_number) if block.is_future_block(dev_config): delay = abs(block.timestamp - ntp.getTime()) + 1 reactor.callLater(delay, self.process_future_blocks) self.add_future_block(block) return True logger.debug('Inside add_block') result = self.chain_manager.add_block(block) logger.debug('trigger_miner %s', self.chain_manager.trigger_miner) if self.chain_manager.trigger_miner: logger.debug('try last block') last_block = self.chain_manager.last_block logger.debug('got last block') self._mine_next(last_block) if not result: logger.debug('Block Rejected %s %s', block.block_number, bin2hstr(block.headerhash)) return False reactor.callLater(0, self.broadcast_block, block) logger.debug('LOCK - RELEASE - pre_block_logic') return result
def _handler_state_synced(self): self.last_pow_cycle = ntp.getTime() last_block = self.chain_manager.last_block self._mine_next(last_block)
def _handler_state_syncing(self): self.last_pb_time = ntp.getTime()
def _handler_state_unsynced(self): self.miner.cancel() self.last_bk_time = ntp.getTime() self.restart_unsynced_logic()
def isSynced(self, block_timestamp) -> bool: if block_timestamp + config.dev.minimum_minting_delay > ntp.getTime(): self.update_node_state(ESyncState.synced) return True return False
def is_future_block(self, dev_config: DevConfig) -> bool: if self.timestamp > ntp.getTime() + dev_config.block_max_drift: return True return False
def connection_time(self): return ntp.getTime() - self._connected_at
def is_expired(self): return self.timestamp - ntp.getTime() > config.user.outgoing_message_expiry
def __init__(self, priority, message): self.priority = priority self.timestamp = int(ntp.getTime()) self.message = message
def uptime(self): return ntp.getTime() - self.start_time
def test_getTime(self): setDrift() time = getTime() self.assertIsNotNone(time)
def add(self, x): current_time = ntp.getTime() self._data[x] = current_time + self.expiration_time self._store()
def uptime_network(self): block_one = self._chain_manager.get_block_by_number(1) network_uptime = 0 if block_one: network_uptime = ntp.getTime() - block_one.timestamp return network_uptime
def __init__(self, tx: Transaction, block_number: int, timestamp: int=None): self._transaction = tx self._block_number = block_number self._timestamp = timestamp if not self._timestamp: self._timestamp = ntp.getTime()