def try_calculate_total_difficulty( self, block_hash: Sha256Hash, new_block_parts: NewBlockParts) -> Optional[int]: previous_block_hash = new_block_parts.get_previous_block_hash() previous_block_total_difficulty = None for known_block_hash, known_total_difficulty in self._last_known_difficulties: if previous_block_hash == known_block_hash: previous_block_total_difficulty = known_total_difficulty break if previous_block_total_difficulty is None: logger.debug( "Unable to calculate total difficulty after block {}.", convert.bytes_to_hex(block_hash.binary)) return None block_total_difficulty = previous_block_total_difficulty + new_block_parts.get_block_difficulty( ) self._last_known_difficulties.append( (block_hash, block_total_difficulty)) logger.debug("Calculated total difficulty after block {} = {}.", convert.bytes_to_hex(block_hash.binary), block_total_difficulty) return block_total_difficulty
def msg_new_block_hashes(self, msg: NewBlockHashesEthProtocolMessage): if not self.node.should_process_block_hash(msg.block_hash()): return block_hash_number_pairs = [] for block_hash, block_number in msg.get_block_hash_number_pairs(): block_stats.add_block_event_by_block_hash( block_hash, BlockStatEventType.BLOCK_ANNOUNCED_BY_BLOCKCHAIN_NODE, network_num=self.connection.network_num, more_info="Protocol: {}, Network: {}. {}".format( self.node.opts.blockchain_protocol, self.node.opts.blockchain_network, msg.extra_stats_data()), block_height=block_number, ) gateway_bdn_performance_stats_service.log_block_message_from_blockchain_node( False) if block_hash in self.node.blocks_seen.contents: self.node.on_block_seen_by_blockchain_node( block_hash, block_number=block_number) block_stats.add_block_event_by_block_hash( block_hash, BlockStatEventType. BLOCK_RECEIVED_FROM_BLOCKCHAIN_NODE_IGNORE_SEEN, network_num=self.connection.network_num, block_height=block_number, ) self.connection.log_info( "Ignoring duplicate block {} from local blockchain node.", block_hash) continue recovery_cancelled = self.node.on_block_seen_by_blockchain_node( block_hash, block_number=block_number) if recovery_cancelled: continue self.node.track_block_from_node_handling_started(block_hash) block_hash_number_pairs.append((block_hash, block_number)) self.connection.log_info( "Fetching block {} from local Ethereum node.", block_hash) if not block_hash_number_pairs: return for block_hash, block_number in block_hash_number_pairs: # pyre-fixme[6]: Expected `memoryview` for 1st param but got `None`. self.pending_new_block_parts.add( block_hash, NewBlockParts(None, None, block_number)) self.connection.enqueue_msg( GetBlockHeadersEthProtocolMessage(None, block_hash.binary, 1, 0, False)) self.request_block_body( [block_hash for block_hash, _ in block_hash_number_pairs])
def test_new_block_parts(self): txs = [] txs_bytes = [] txs_hashes = [] tx_count = 10 for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(1) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) block_header = mock_eth_messages.get_dummy_block_header(1) uncles = [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] block_number = 100000 block_body = TransientBlockBody(txs, uncles) block_header_bytes = memoryview( rlp.encode(BlockHeader.serialize(block_header))) block_body_bytes = memoryview( rlp.encode(TransientBlockBody.serialize(block_body))) new_block_parts = NewBlockParts(block_header_bytes, block_body_bytes, block_number) self.assertIsInstance(new_block_parts.get_block_hash(), Sha256Hash) self.assertIsInstance(new_block_parts.get_previous_block_hash(), Sha256Hash) self.assertEqual(1, new_block_parts.get_block_difficulty())
def test_new_block_internal_eth_message_to_from_new_block_parts(self): txs = [] txs_bytes = [] txs_hashes = [] tx_count = 10 for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(1) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) block_header = mock_eth_messages.get_dummy_block_header(1) uncles = [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] block_number = 100000 block_body = TransientBlockBody(txs, uncles) block_header_bytes = memoryview( rlp.encode(BlockHeader.serialize(block_header))) block_body_bytes = memoryview( rlp.encode(TransientBlockBody.serialize(block_body))) new_block_parts = NewBlockParts(block_header_bytes, block_body_bytes, block_number) new_block_internal_eth_msg = InternalEthBlockInfo.from_new_block_parts( new_block_parts) self.assertIsNotNone(new_block_internal_eth_msg) self.assertTrue(new_block_internal_eth_msg.rawbytes()) parsed_new_block_parts = new_block_internal_eth_msg.to_new_block_parts( ) self.assertIsInstance(parsed_new_block_parts, NewBlockParts) self.assertEqual(block_header_bytes, parsed_new_block_parts.block_header_bytes) self.assertEqual(block_body_bytes, parsed_new_block_parts.block_body_bytes) self.assertEqual(block_number, parsed_new_block_parts.block_number)
def to_new_block_parts(self) -> NewBlockParts: _, msg_itm_len, msg_itm_start = rlp_utils.consume_length_prefix( self._memory_view, 0) msg_itm_bytes = self._memory_view[msg_itm_start:] offset = 0 _, header_len, header_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) header_bytes = msg_itm_bytes[offset:header_start + header_len] offset = header_start + header_len _, txs_len, txs_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) txs_bytes = msg_itm_bytes[offset:txs_start + txs_len] offset = txs_start + txs_len _, uncles_len, uncles_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) uncles_bytes = msg_itm_bytes[offset:uncles_start + uncles_len] offset = uncles_start + uncles_len _, total_difficulty_len, total_difficulty_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) offset = total_difficulty_start + total_difficulty_len block_number, _ = rlp_utils.decode_int(msg_itm_bytes, offset) block_body_prefix = rlp_utils.get_length_prefix_list( len(txs_bytes) + len(uncles_bytes)) block_body_bytes = bytearray( len(block_body_prefix) + len(txs_bytes) + len(uncles_bytes)) block_body_bytes[:len(block_body_prefix)] = block_body_prefix written_bytes = len(block_body_prefix) block_body_bytes[written_bytes:written_bytes + len(txs_bytes)] = txs_bytes written_bytes += len(txs_bytes) block_body_bytes[written_bytes:written_bytes + len(uncles_bytes)] = uncles_bytes written_bytes += len(uncles_bytes) return NewBlockParts(header_bytes, block_body_bytes, block_number)