def _validate_custom(self): for amount in self.amounts: if amount == 0: logger.warning('Amount cannot be 0 - %s', self.amounts) logger.warning('TransferTokenTransaction') return False if self.fee < 0: logger.info('TransferTokenTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) return False if len(self.addrs_to) != len(self.amounts): logger.warning( '[TransferTokenTransaction] Mismatch number of addresses to & amounts' ) logger.warning('>> Length of addresses_to %s', len(self.addrs_to)) logger.warning('>> Length of amounts %s', len(self.amounts)) return False if not OptimizedAddressState.address_is_valid(self.addr_from): logger.warning( '[TransferTokenTransaction] Invalid address addr_from: %s', bin2hstr(self.addr_from)) return False for addr_to in self.addrs_to: if not OptimizedAddressState.address_is_valid(addr_to): logger.warning( '[TransferTokenTransaction] Invalid address addr_to: %s', bin2hstr(addr_to)) return False return True
def __next__(self): tx_timestamp = self.transaction_pool_obj.get_pending_transaction() if not tx_timestamp: raise StopIteration tx, timestamp = tx_timestamp if not self.chain_manager.validate_all(tx, check_nonce=False): return False is_valid_pool_state = tx.validate_transaction_pool( self.transaction_pool_obj.transaction_pool) if not is_valid_pool_state: logger.info('>>>TX %s failed is_valid_pool_state', bin2hstr(tx.txhash)) return False logger.info('A TXN has been Processed %s', bin2hstr(tx.txhash)) self.transaction_pool_obj.add_tx_to_pool( tx, self.chain_manager.last_block.block_number, timestamp) self.broadcast_tx(tx) return True
def test_from_json(self, m_logger): tx = Transaction.from_json(test_json_Token) tx.sign(self.alice) self.assertIsInstance(tx, TokenTransaction) # Test that common Transaction components were copied over. self.assertEqual('010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual('01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(b'xrd', tx.symbol) self.assertEqual(b'Quantum Resistant Ledger', tx.name) self.assertEqual('010317463dcd581b679b4754f46c6425125489a2826894e3c42a590efb6806450ce6bf52716c', bin2hstr(tx.owner)) self.assertEqual('ff84da605e9c9cd04d68503be7922110b4cc147837f8687ad18aa54b7bc5632d', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(test_signature_Token, bin2hstr(tx.signature)) total_supply = 0 for initial_balance in tx.initial_balances: total_supply += initial_balance.amount self.assertEqual(600000000, total_supply) self.assertEqual(1, tx.fee)
def test_from_json(self, m_logger): tx = Transaction.from_json(test_json_Simple) tx.sign(self.alice) self.assertIsInstance(tx, TransferTransaction) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual( '554f546305d4aed6ec71c759942b721b904ab9d65eeac3c954c08c652181c4e8', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(test_signature_Simple, bin2hstr(tx.signature)) # Test that specific content was copied over. self.assertEqual( '0103001d65d7e59aed5efbeae64246e0f3184d7c42411421eb385ba30f2c1c005a85ebc4419cfd', bin2hstr(tx.addrs_to[0])) self.assertEqual(100, tx.total_amount) self.assertEqual(1, tx.fee)
def validate_or_raise(self, verify_signature=True) -> bool: """ This method will validate a transaction and raise exception if problems are found :return: True if the exception is valid, exceptions otherwise :rtype: bool """ if not self._validate_custom(): raise ValueError("Custom validation failed") self._coinbase_filter() expected_transaction_hash = self.generate_txhash() if verify_signature and self.txhash != expected_transaction_hash: logger.warning('Invalid Transaction hash') logger.warning('Expected Transaction hash %s', bin2hstr(expected_transaction_hash)) logger.warning('Found Transaction hash %s', bin2hstr(self.txhash)) raise ValueError("Invalid Transaction Hash") if verify_signature: # Temporarily disabled following new added lines. # TODO: Review Juan # if not XMSS.validate_signature(self.signature, self.PK): # raise ValueError("Invalid xmss signature") if not XmssFast.verify(self.get_data_hash(), self.signature, self.PK): raise ValueError("Invalid xmss signature") return True
def test_from_json(self, m_logger): tx = Transaction.from_json(test_json_TransferToken) tx.sign(self.alice) self.assertIsInstance(tx, TransferTokenTransaction) # Test that common Transaction components were copied over. self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(b'000000000000000', tx.token_txhash) self.assertEqual(200000, tx.total_amount) self.assertEqual( '390b159b34cffd29d4271a19679ff227df2ccd471078f177a7b58ca5f5d999f0', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) # z = bin2hstr(tx.signature) # print('"', end='') # for i in range(len(z)): # print(z[i], end='') # if (i + 1) % 64 == 0: # print('" \\', end='') # print('') # print(' ' * len('test_signature_TransferToken = '), end='') # print('"', end='') self.assertEqual(test_signature_TransferToken, bin2hstr(tx.signature)) self.assertEqual(1, tx.fee)
def to_plain_blocks(self, block): pheader = xrdwallet_pb2.PlainBlockHeader() pheader.hash_header = bin2hstr(block.header.hash_header) pheader.block_number = block.header.block_number pheader.timestamp_seconds = block.header.timestamp_seconds pheader.hash_header_prev = bin2hstr(block.header.hash_header_prev) pheader.reward_block = block.header.reward_block pheader.reward_fee = block.header.reward_fee pheader.merkle_root = bin2hstr(block.header.merkle_root) pheader.mining_nonce = block.header.mining_nonce pheader.extra_nonce = block.header.extra_nonce pblock = xrdwallet_pb2.PlainBlock() pblock.header.MergeFrom(pheader) for tx in block.transactions: pblock.transactions.extend([self.to_plain_transaction(tx)]) for genesis_balance in block.genesis_balance: pgb = xrdwallet_pb2.PlainGenesisBalance() pgb.address = self.address_to_qaddress(genesis_balance.address) pgb.balance = genesis_balance.balance pblock.genesis_balance.extend([pgb]) return pblock
def test_hash(self, time_mock): header_hash = self.block_header.generate_headerhash(config.dev) self.assertEquals( 'ac021e63df860ea930ea9de05e350d3f74af35341688134f92957f1dac3a62fb', bin2hstr(header_hash)) self.assertEquals(bin2hstr(header_hash), bin2hstr(self.block_header.headerhash)) self.assertEquals(32, len(self.block_header.headerhash))
def test_hash_nonce(self, time_mock): self.block_header.set_nonces(config.dev, 100, 0) header_hash = self.block_header.generate_headerhash(config.dev) self.assertEquals( 'b6f937020f9876f3c6887e7a6759201411ed8826ed9ce4283ffe48e1aa90d692', bin2hstr(header_hash)) self.assertEquals(bin2hstr(header_hash), bin2hstr(self.block_header.headerhash)) self.assertEquals(32, len(self.block_header.headerhash))
def start_mining(self, parent_block: Block, parent_difficulty, dev_config: DevConfig): logger.debug('!!! Mine #{} | {} ({}) | {} -> {} | {} '.format( self._mining_block.block_number, self._measurement, self._mining_block.timestamp - parent_block.timestamp, UInt256ToString(parent_difficulty), UInt256ToString(self._current_difficulty), bin2hstr(bytearray(self._current_target)))) logger.debug('!!! Mine #{} | blob: {}'.format( self._mining_block.block_number, bin2hstr(bytearray(self._mining_block.mining_blob(dev_config))))) miner = self.get_miner(parent_block.block_number + 1, dev_config) miner.start_mining(self._mining_block, self._current_target, dev_config)
def _validate_extended(self, state_container: StateContainer) -> bool: if state_container.block_number < state_container.current_dev_config.hard_fork_heights[ 0]: logger.warning( "[LatticeTransaction] Hard Fork Feature not yet activated") return False dev_config = state_container.current_dev_config if len( self.pk1 ) > dev_config.lattice_pk1_max_length: # TODO: to fix kyber pk value logger.warning('Kyber PK length cannot be more than %s bytes', dev_config.lattice_pk1_max_length) logger.warning('Found length %s', len(self.pk1)) return False if len( self.pk2 ) > dev_config.lattice_pk2_max_length: # TODO: to fix dilithium pk value logger.warning('Dilithium PK length cannot be more than %s bytes', dev_config.lattice_pk2_max_length) logger.warning('Found length %s', len(self.pk2)) return False if len( self.pk3 ) > dev_config.lattice_pk3_max_length: # TODO: to fix ecdsa pk value logger.warning('ECDSA PK length cannot be more than %s bytes', dev_config.lattice_pk3_max_length) logger.warning('Found length %s', len(self.pk3)) return False tx_balance = state_container.addresses_state[self.addr_from].balance if tx_balance < self.fee: logger.info( 'State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, amount: %s', tx_balance, self.fee) return False if (self.addr_from, self.pk1, self.pk2, self.pk3) in state_container.lattice_pk.data: logger.info( 'State validation failed for %s because: Lattice PKs already exists for this address', bin2hstr(self.txhash)) return False return True
def _validate_extended(self, state_container: StateContainer): if len(self.message_data) > 0: if state_container.block_number < state_container.current_dev_config.hard_fork_heights[ 0]: logger.warning( "[TransferTransaction] Hard Fork Feature not yet activated" ) return False if len( self.addrs_to ) > state_container.current_dev_config.transaction_multi_output_limit: logger.warning( '[TransferTransaction] Number of addresses exceeds max limit') logger.warning('Number of addresses %s', len(self.addrs_to)) logger.warning('Number of amounts %s', len(self.amounts)) return False if len(self.message_data ) > state_container.current_dev_config.message_max_length: logger.warning( "[TransferTransaction] Message data is greater than message max length limit" ) logger.warning("Message data length %s", len(self.message_data)) logger.warning( "Message data length limit %s", state_container.current_dev_config.message_max_length) return False tx_balance = state_container.addresses_state[self.addr_from].balance total_amount = self.total_amount for addr_to in self.addrs_to: if MultiSigAddressState.address_is_valid(addr_to): if addr_to not in state_container.addresses_state: logger.warning( '[TransferTransaction] Multi Sig Address doesnt exist: %s', bin2hstr(addr_to)) return False if tx_balance < total_amount + self.fee: logger.info( 'State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, fee: %s, amount: %s', tx_balance, self.fee, total_amount) return False return True
def validate_signature(signature, PK): height = XMSS.get_height_from_sig_size(len(signature)) if height == 0 or 2 * int(bin2hstr(PK)[2:4]) != height: return False return True
def GetLastBlockHeader(self, request: xrdmining_pb2.GetLastBlockHeaderReq, context) -> xrdmining_pb2.GetLastBlockHeaderResp: response = xrdmining_pb2.GetLastBlockHeaderResp() blockheader, block_metadata = self.xrdnode.get_blockheader_and_metadata( request.height) response.difficulty = int(bin2hstr(block_metadata.block_difficulty), 16) response.height = blockheader.block_number response.timestamp = blockheader.timestamp response.reward = blockheader.block_reward + blockheader.fee_reward response.hash = bin2hstr(blockheader.headerhash) response.depth = self.xrdnode.block_height - blockheader.block_number return response
def broadcast_tx(self, tx: TransferTransaction): logger.info('<<<Transmitting TX: %s', bin2hstr(tx.txhash)) if isinstance(tx, MessageTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.MT elif isinstance(tx, TransferTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.TX elif isinstance(tx, TokenTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.TK elif isinstance(tx, TransferTokenTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.TT elif isinstance(tx, SlaveTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.SL elif isinstance(tx, LatticeTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.LT elif isinstance(tx, MultiSigCreate): legacy_type = xrdlegacy_pb2.LegacyMessage.MC elif isinstance(tx, MultiSigSpend): legacy_type = xrdlegacy_pb2.LegacyMessage.MS elif isinstance(tx, MultiSigVote): legacy_type = xrdlegacy_pb2.LegacyMessage.MV else: raise ValueError('Invalid Transaction Type') self.register_and_broadcast(legacy_type, tx.get_message_hash(), tx.pbdata)
def _get_xmss_by_index_no_cache(self, idx) -> Optional[XMSS]: """ Generates an XMSS tree based on the information contained in the wallet :param idx: The index of the address item :return: An XMSS tree object """ if idx >= len(self._address_items): return None item = self._address_items[idx] extended_seed = mnemonic2bin(item.mnemonic.strip()) tmp_xmss = XMSS.from_extended_seed(extended_seed) tmp_xmss.set_ots_index(item.index) if item.qaddress != 'Q' + bin2hstr(tmp_xmss.address): raise Exception("Mnemonic and address do not match.") if item.hexseed != tmp_xmss.hexseed: raise Exception("hexseed does not match.") if item.mnemonic != tmp_xmss.mnemonic: raise Exception("mnemonic does not match.") if item.height != tmp_xmss.height: raise Exception("height does not match.") return tmp_xmss
def _get_Qaddress(addr: bytes) -> str: """ Gets an address in QHex format :param addr: :return: """ return 'Q' + bin2hstr(addr)
def test_blob(self, time_mock): self.assertEquals( '00501846b24200c31fca7172a7f701ae50322579cfdf1d7777daab4ce6ead70b76debb2c51a1' 'c700000000000000000000000000000000002b80aecec05ad5c7c4f2259c8f69e2966a6ce102', bin2hstr(self.block_header.mining_blob(config.dev))) self.assertEquals(config.dev.mining_blob_size_in_bytes, len(self.block_header.mining_blob(config.dev)))
def handle_block(self, source, message: xrdlegacy_pb2.LegacyMessage): # block received """ Block This function processes any new block received. :return: """ P2PBaseObserver._validate_message(message, xrdlegacy_pb2.LegacyMessage.BK) try: block = Block(message.block) except Exception as e: logger.error( 'block rejected - unable to decode serialised data %s', source.peer) logger.exception(e) return logger.info('>>>Received block from %s %s %s', source.peer.full_address, block.block_number, bin2hstr(block.headerhash)) if not source.factory.master_mr.isRequested(block.headerhash, source, block): return source.factory.pow.pre_block_logic( block) # FIXME: Ignores return value source.factory.master_mr.register(xrdlegacy_pb2.LegacyMessage.BK, block.headerhash, message.block)
def _validate_extended(self, state_container: StateContainer) -> bool: if len(self.addr_to) != 0: if state_container.block_number < state_container.current_dev_config.hard_fork_heights[ 0]: logger.warning( "[MessageTransaction] Hard Fork Feature not yet activated") return False if len( self.message_hash ) > state_container.current_dev_config.message_max_length: # TODO: Move to dev config logger.warning( 'Message length cannot be more than %s', state_container.current_dev_config.message_max_length) logger.warning('Found message length %s', len(self.message_hash)) return False tx_balance = state_container.addresses_state[self.addr_from].balance if tx_balance < self.fee: logger.info( 'State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, amount: %s', tx_balance, self.fee) return False return True
def get_xmss_by_item(self, item: AddressItem, ots_index=-1) -> XMSS: """ Generates an XMSS tree based on the given AddressItem :param item: :param ots_index: :return: """ extended_seed = mnemonic2bin(item.mnemonic.strip()) tmp_xmss = XMSS.from_extended_seed(extended_seed) if ots_index > -1: tmp_xmss.set_ots_index(ots_index) else: tmp_xmss.set_ots_index(item.index) if item.qaddress != 'Q' + bin2hstr(tmp_xmss.address): raise Exception("Mnemonic and address do not match.") if item.hexseed != tmp_xmss.hexseed: raise Exception("hexseed does not match.") if item.mnemonic != tmp_xmss.mnemonic: raise Exception("mnemonic does not match.") if item.height != tmp_xmss.height: raise Exception("height does not match.") return tmp_xmss
def _validate_custom(self): if self.fee < 0: logger.warning('MultiSigVote [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) return False return True
def _validate_extended(self, state_container: StateContainer): if (len(self.addrs_to) > state_container.current_dev_config. transaction_multi_output_limit or len(self.amounts) > state_container.current_dev_config. transaction_multi_output_limit): logger.warning( '[TransferTokenTransaction] Number of addresses or amounts exceeds max limit' ) logger.warning('Number of addresses %s', len(self.addrs_to)) logger.warning('Number of amounts %s', len(self.amounts)) return False if len(self.addrs_to) == 0: logger.warning("[TransferTokenTransaction] No Addrs To found") return False tx_balance = state_container.addresses_state[self.addr_from].balance total_amount = self.total_amount if self.fee < 0 or total_amount < 0: logger.info( '[TransferTokenTransaction] State validation failed for %s because: ', bin2hstr(self.txhash)) logger.info('Txn amount: %s, Fee: %s', total_amount, self.fee) return False if tx_balance < self.fee: logger.info( '[TransferTokenTransaction] State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, Fee: %s', tx_balance, self.fee) return False if (self.addr_from, self.token_txhash) not in state_container.tokens.data: logger.info('%s doesnt own any such token %s ', bin2hstr(self.addr_from), bin2hstr(self.token_txhash)) return False token_balance = state_container.tokens.data[(self.addr_from, self.token_txhash)] if token_balance.balance < total_amount: logger.info('Insufficient amount of token') logger.info('Token Balance: %s, Sent Token Amount: %s', token_balance.balance, total_amount) return False return True
def test_wrap_message_works(self): veData = xrdlegacy_pb2.VEData(version="version", genesis_prev_hash=b'genesis_hash') msg = xrdlegacy_pb2.LegacyMessage( func_name=xrdlegacy_pb2.LegacyMessage.VE, veData=veData) self.assertEqual( '000000191a170a0776657273696f6e120c67656e657369735f68617368', bin2hstr(P2PProtocol._wrap_message(msg)))
def to_plain_transaction(self, tx): ptx = xrdwallet_pb2.PlainTransaction() if not tx.WhichOneof('transactionType'): return ptx if tx.master_addr: ptx.master_addr = self.address_to_qaddress(tx.master_addr) ptx.fee = tx.fee ptx.public_key = bin2hstr(tx.public_key) ptx.signature = bin2hstr(tx.signature) ptx.nonce = tx.nonce ptx.transaction_hash = bin2hstr(tx.transaction_hash) if tx.WhichOneof('transactionType') != 'coinbase': ptx.signer_addr = self.get_address_from_pk(ptx.public_key) if tx.WhichOneof('transactionType') == "transfer": ptx.transfer.amounts.extend(tx.transfer.amounts) for addr in tx.transfer.addrs_to: ptx.transfer.addrs_to.extend([self.address_to_qaddress(addr)]) elif tx.WhichOneof('transactionType') == 'coinbase': ptx.coinbase.addr_to = self.address_to_qaddress( tx.coinbase.addr_to) ptx.coinbase.amount = tx.coinbase.amount elif tx.WhichOneof('transactionType') == 'lattice_public_key': ptx.lattice_public_key.MergeFrom(ptx.lattice_public_key()) ptx.lattice_public_key.kyber_pk = bin2hstr( tx.lattice_public_key.kyber_pk) ptx.lattice_public_key.dilithium_pk = bin2hstr( tx.lattice_public_key.dilithium_pk) elif tx.WhichOneof('transactionType') == 'message': ptx.message.message_hash = bin2hstr(tx.message.message_hash) elif tx.WhichOneof('transactionType') == 'token': ptx.token.symbol = tx.token.symbol ptx.token.name = tx.token.name ptx.token.owner = self.address_to_qaddress(tx.token.owner) ptx.token.decimals = tx.token.decimals for initial_balance in tx.token.initial_balances: ptx.token.initial_balances.extend( [self.to_plain_address_amount(initial_balance)]) elif tx.WhichOneof('transactionType') == 'transfer_token': ptx.transfer_token.token_txhash = bin2hstr( tx.transfer_token.token_txhash) ptx.transfer_token.addrs_to.extend( self.addresses_to_qaddress(tx.transfer_token.addrs_to)) ptx.transfer_token.amounts.extend(tx.transfer_token.amounts) elif tx.WhichOneof('transactionType') == 'slave': for slave_pk in tx.slave.slave_pks: ptx.slave.slave_pks.extend([bin2hstr(slave_pk)]) ptx.slave.access_types.extend(tx.slave.access_types) return ptx
def _validate_custom(self) -> bool: if self.fee < 0: logger.info( 'State validation failed for %s because: Negative send', bin2hstr(self.txhash)) return False return True
def get_transaction(self, tx_hash: str): txhash = bytes(hstr2bin(tx_hash)) response = self._public_stub.GetTransaction( xrd_pb2.GetTransactionReq(tx_hash=txhash)) block_header_hash = None if response.block_header_hash: block_header_hash = bin2hstr(response.block_header_hash) return self.to_plain_transaction(response.tx), str( response.confirmations), response.block_number, block_header_hash
def _validate_custom(self) -> bool: if len(self.message_hash) == 0: logger.warning('Message cannot be empty') return False if len(self.addr_to) > 0 and not ( OptimizedAddressState.address_is_valid(self.addr_to)): logger.warning('[MessageTransaction] Invalid address addr_to: %s', bin2hstr(self.addr_to)) return False if self.fee < 0: logger.info( 'State validation failed for %s because: Negative send', bin2hstr(self.txhash)) return False return True
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 get_random_master(): random_master = get_random_xmss(config.dev.xmss_tree_height) slave_data = json.loads( json.dumps([ bin2hstr(random_master.address), [random_master.extended_seed], None ])) slave_data[0] = bytes(hstr2bin(slave_data[0])) return slave_data