def test_generate_multi_sig_address(self): creation_tx_hash = bytes( hstr2bin("5a4c37ef7e5b7cc5a2a58ab730269ed8" "f4cbf08a005dc3508e31465535e1d6bb")) address = MultiSigAddressState.generate_multi_sig_address( creation_tx_hash) expected_address = bytes( hstr2bin("1100003674370317e1cac0ca13f896ab5b6472a" "261ba0d2b2961d3adba1b9060f6e8f7fe2088fb")) self.assertEqual(address, expected_address) self.assertFalse(OptimizedAddressState.address_is_valid(address))
def get_mining_address(mining_address: str): try: if not mining_address: mining_address = bytes(hstr2bin(config.user.mining_address[1:])) else: mining_address = bytes(hstr2bin(mining_address[1:])) if not AddressState.address_is_valid(mining_address): raise ValueError('Mining Address Validation Failed') return mining_address except Exception as e: logger.info('Failed Parsing Mining Address %s', e) return None
def get_migration_transactions(signing_xmss, filename): transactions = [] with open(filename, 'r') as f: json_data = json.load(f) count = 1 addrs_to = [] amounts = [] output_limit = config.dev.transaction_multi_output_limit for addr in json_data: try: addrs_to.append(bytes(hstr2bin(addr[1:]))) except: # noqa print("Invalid Address ", addr) raise Exception amounts.append(json_data[addr]) count += 1 if count % output_limit == 0: transactions.append( create_tx(addrs_to, amounts, signing_xmss, count // output_limit)) addrs_to = [] amounts = [] if addrs_to: transactions.append( create_tx(addrs_to, amounts, signing_xmss, (count // output_limit) + 1)) return transactions
def test_relayTokenTxnBySlave(self): with set_xrd_dir("wallet_ver1"): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=xrd_pb2.PushTransactionResp(error_code=xrd_pb2.PushTransactionResp.SUBMITTED)) service = WalletAPIService(walletd) resp = service.AddNewAddressWithSlaves(xrdwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) slaves = walletd.get_slave_list(qaddress) addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=xrd_pb2.GetAddressStateResp(state=addr_state.pbdata)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) qaddresses = [alice_xmss.qaddress, bob_xmss.qaddress] amounts = [1000000000, 1000000000] resp = service.RelayTokenTxnBySlave( xrdwallet_pb2.RelayTokenTxnBySlaveReq(symbol=b'xrd', name=b'Quantum Resistant Ledger', owner=alice_xmss.qaddress, decimals=5, addresses=qaddresses, amounts=amounts, fee=100000000, master_address=qaddress), context=None) self.assertEqual(resp.code, 0) self.assertIsNotNone(resp.tx)
def test_parse_buffer_works(self): self.channel._buffer = bytes( hstr2bin( '000000191a170a0776657273696f6e120c67656e657369735f68617368' + '000000191a170a0776657273696f6e120c67656e657369735f68617368')) messages = self.channel._parse_buffer([0]) self.assertEqual(2, len(list(messages)))
def test_trusted_message_count(self, send, get_peer): channel = P2PProtocol() with mock.patch('xrd.core.misc.ntp.getTime') as time_mock: time_mock.return_value = channel.connected_at + 100 get_peer.return_value = IPMetadata('192.168.0.1', 1000) self.assertFalse(self.peer_manager.trusted_peer(channel)) for _ in range(config.dev.trust_min_msgcount - 1): buffer = bytes(hstr2bin('000000191a170a0776657273696f6e120c67656e657369735f68617368')) channel.dataReceived(buffer) self.assertFalse(self.peer_manager.trusted_peer(channel)) buffer = bytes(hstr2bin('000000191a170a0776657273696f6e120c67656e657369735f68617368')) channel.dataReceived(buffer) self.assertTrue(self.peer_manager.trusted_peer(channel))
def test_monitor_chain_state_peer_with_higher_difficulty_found( self, mock_get_block_metadata): """ xrdNode.monitor_chain_state() basically: 1. Tells P2PPeerManager to clean the list of channels/P2PProtocols, i.e. remove any we haven't heard from for a long time, and make sure our list of channels and the list of their statuses is in sync. 2. Gets the last block from the State 3. Broadcasts our State based on the last Block to our peers 4. Ask P2PPeerManager to return the channel (if any) who has a higher difficulty than our chain. If a channel with a higher difficulty is found, get its list of headerhashes. """ m_block = Mock(autospec=Block, name='mock last Block', block_number=2, headerhash=b'deadbeef') m_block_metadata = Mock(autospec=BlockMetadata, cumulative_difficulty=hstr2bin('01')) m_channel = Mock(autospec=P2PProtocol, addr_remote='1.1.1.1') self.xrdnode.peer_manager.get_better_difficulty.return_value = m_channel mock_get_block_metadata.return_value = m_block_metadata self.chain_manager._last_block = m_block self.xrdnode.monitor_chain_state() self.xrdnode.peer_manager.monitor_chain_state.assert_called_once() self.xrdnode.peer_manager.get_better_difficulty.assert_called_once() m_channel.send_get_headerhash_list.assert_called_once()
def parse_hexblob(blob: str) -> bytes: """ Binary conversions from hexstring are handled by bytes(hstr2bin()). :param blob: :return: """ return bytes(hstr2bin(blob))
def test_relaySlaveTxnBySlave(self): with set_xrd_dir("wallet_ver1"): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=xrd_pb2.PushTransactionResp(error_code=xrd_pb2.PushTransactionResp.SUBMITTED)) service = WalletAPIService(walletd) resp = service.AddNewAddressWithSlaves(xrdwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) slaves = walletd.get_slave_list(qaddress) addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=xrd_pb2.GetAddressStateResp(state=addr_state.pbdata)) alice_xmss = get_alice_xmss(4) slave_pks = [alice_xmss.pk] access_types = [0] resp = service.RelaySlaveTxnBySlave( xrdwallet_pb2.RelaySlaveTxnBySlaveReq(slave_pks=slave_pks, access_types=access_types, fee=100000000, master_address=qaddress), context=None) self.assertEqual(resp.code, 0) self.assertIsNotNone(resp.tx)
def test_getNodeInfo(self): with set_xrd_dir("wallet_ver1"): walletd = WalletD() service = WalletAPIService(walletd) block_last_hash_str = 'c23f47a10a8c53cc5ded096369255a32c4a218682a961d0ee7db22c500000000' version = "1.0.0" num_connections = 10 num_known_peers = 200 uptime = 10000 block_height = 102345 block_last_hash = bytes(hstr2bin(block_last_hash_str)) network_id = "network id" node_info = xrd_pb2.NodeInfo(version=version, num_connections=num_connections, num_known_peers=num_known_peers, uptime=uptime, block_height=block_height, block_last_hash=block_last_hash, network_id=network_id) walletd._public_stub.GetNodeState = Mock( return_value=xrd_pb2.GetNodeStateResp(info=node_info)) resp = service.GetNodeInfo(xrdwallet_pb2.NodeInfoReq(), context=None) self.assertEqual(resp.version, version) self.assertEqual(resp.num_connections, str(num_connections)) self.assertEqual(resp.num_known_peers, str(num_known_peers)) self.assertEqual(resp.uptime, uptime) self.assertEqual(resp.block_height, block_height) self.assertEqual(resp.block_last_hash, block_last_hash_str) self.assertEqual(resp.network_id, network_id)
def token_list(ctx, owner): """ Fetch the list of tokens owned by an address. """ try: owner_address = parse_qaddress(owner) except Exception as e: click.echo("Error validating arguments: {}".format(e)) quit(1) try: stub = ctx.obj.get_stub_public_api() address_state_req = xrd_pb2.GetAddressStateReq(address=owner_address) address_state_resp = stub.GetAddressState(address_state_req, timeout=CONNECTION_TIMEOUT) for token_hash in address_state_resp.state.tokens: get_object_req = xrd_pb2.GetObjectReq(query=bytes(hstr2bin(token_hash))) get_object_resp = stub.GetObject(get_object_req, timeout=CONNECTION_TIMEOUT) click.echo('Hash: %s' % (token_hash,)) click.echo('Symbol: %s' % (get_object_resp.transaction.tx.token.symbol.decode(),)) click.echo('Name: %s' % (get_object_resp.transaction.tx.token.name.decode(),)) click.echo('Balance: %s' % (address_state_resp.state.tokens[token_hash],)) except Exception as e: print("Error {}".format(str(e)))
def submitblock(blob): stub = get_mining_stub() request = xrdmining_pb2.SubmitMinedBlockReq(blob=bytes(hstr2bin(blob))) response = stub.SubmitMinedBlock(request=request, timeout=10) if response.error: raise Exception # Mining pool expected exception when block submission fails return {'status': 'OK', 'error': 0}
def addresses(self) -> List[bytes]: """ Returns all address items in the wallet :return: """ return [ bytes(hstr2bin(item.qaddress[1:])) for item in self._address_items ]
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
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 get_total_balance(self) -> int: self.authenticate() addresses = [] for item in self._wallet.address_items: addresses.append(bytes(hstr2bin(item.qaddress[1:]))) response = self._public_stub.GetTotalBalance( xrd_pb2.GetTotalBalanceReq(addresses=addresses)) return response.balance
def test_parse_buffer_invalid_data(self, logger): self.channel._buffer = bytes( hstr2bin( '0000000000000000000000000000000000000000000000000000000000' + '1111111111111111111111111111111111111111111111111111111111')) messages = self.channel._parse_buffer([0]) messages_list = list(messages) self.assertEqual(0, len(messages_list)) logger.warning.assert_called_with( "Problem parsing message. Banning+Dropping connection")
def main(): if len(sys.argv) > 2: print("Unexpected arguments") sys.exit(0) elif len(sys.argv) == 1: print("Missing Filename") sys.exit(0) filename = sys.argv[1] if sys.version_info.major > 2: seed = bytes(hstr2bin(input('Enter extended hexseed: '))) else: seed = bytes(hstr2bin(raw_input('Enter extended hexseed: '))) # noqa dist_xmss = XMSS.from_extended_seed(seed) transactions = get_migration_transactions(signing_xmss=dist_xmss, filename=filename) block = Block.create(dev_config=config.dev, block_number=0, prev_headerhash=config.user.genesis_prev_headerhash, prev_timestamp=config.user.genesis_timestamp, transactions=transactions, miner_address=dist_xmss.address, seed_height=None, seed_hash=None) block.set_nonces(config.dev, 0, 0) block._data.genesis_balance.extend([ xrd_pb2.GenesisBalance(address=config.dev.coinbase_address, balance=105000000000000000) ]) with open('genesis.yml', 'w') as f: yaml.dump(json.loads(block.to_json()), f)
def merkle_tx_hash(hashes): # TODO: Clean this, move to C++ # FIXME: Review and consider (CVE-2012-2459) and bitcoin source code """ merkle tree root hash of tx from pool for next POW block :param hashes: :return: >>> bin2hstr(merkle_tx_hash([b'0', b'1']) ) # FIXME: This input is not realistic '938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4' >>> bin2hstr(merkle_tx_hash([b'0', b'1', b'2']) ) '22073806c4a9967bed132107933c5ec151d602847274f6b911d0086c2a41adc0' >>> bin2hstr(merkle_tx_hash([b'0', b'1', b'2', b'3']) ) 'f16689fdb29d871013c77feede7231de127b7a2e8b4a9c020375408cfb51a241' >>> merkle_tx_hash(['938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4']) '938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4' >>> bin2hstr(merkle_tx_hash('938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4')) '938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4' >>> bin2hstr(merkle_tx_hash([b'0', b'938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4'])) # FIXME: This input is not realistic '40243e694d9c015d5097590bcc9df82683d8ba4006d58c6abb5e1a6bee5ec6dc' """ if isinstance(hashes, str): # it is a single hash string rather than a list.. return hstr2bin(hashes) if isinstance(hashes, list) and len(hashes) == 1: # it is a single hash string rather than a list.. return hashes[0] j = int(ceil(log(len(hashes), 2))) l_array = [hashes] for x in range(j): next_layer = [] i = len(l_array[x]) % 2 + len(l_array[x]) // 2 z = 0 for _ in range(i): if len(l_array[x]) == z + 1: next_layer.append(l_array[x][z]) else: next_layer.append(sha256(l_array[x][z] + l_array[x][z + 1])) z += 2 l_array.append(next_layer) # if len(l_array[-1]) == 1: # return tuple(l_array[-1]) res = bytes(itertools.chain(*l_array[-1])) return res
def GetTransferTokenTxn(self, request: xrd_pb2.TransferTokenTxnReq, context) -> xrd_pb2.TransferCoinsResp: logger.debug("[PublicAPI] GetTransferTokenTxn") bin_token_txhash = bytes(hstr2bin(request.token_txhash.decode())) tx = self.xrdnode.create_transfer_token_txn( addrs_to=request.addresses_to, token_txhash=bin_token_txhash, amounts=request.amounts, fee=request.fee, xmss_pk=request.xmss_pk, master_addr=request.master_addr) extended_transaction_unsigned = xrd_pb2.TransactionExtended( tx=tx.pbdata, addr_from=tx.addr_from, size=tx.size) return xrd_pb2.TransferCoinsResp( extended_transaction_unsigned=extended_transaction_unsigned)
def relay_transfer_token_txn(self, qaddresses_to: list, amounts: list, token_txhash: str, fee: int, master_qaddress, signer_address: str, ots_index: int): self.authenticate() index, xmss = self._get_wallet_index_xmss(signer_address, ots_index) self.verify_ots(signer_address, xmss, user_ots_index=ots_index) tx = TransferTokenTransaction.create( token_txhash=bytes(hstr2bin(token_txhash)), addrs_to=self.qaddresses_to_address(qaddresses_to), amounts=amounts, fee=fee, xmss_pk=xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) self.sign_and_push_transaction(tx, xmss, index) return self.to_plain_transaction(tx.pbdata)
def get_slaves(alice_ots_index, txn_nonce): # [master_address: bytes, slave_seeds: list, slave_txn: json] slave_xmss = get_slave_xmss() alice_xmss = get_alice_xmss() alice_xmss.set_ots_index(alice_ots_index) slave_txn = SlaveTransaction.create([slave_xmss.pk], [1], 0, alice_xmss.pk) slave_txn._data.nonce = txn_nonce slave_txn.sign(alice_xmss) slave_data = json.loads( json.dumps([ bin2hstr(alice_xmss.address), [slave_xmss.extended_seed], slave_txn.to_json() ])) slave_data[0] = bytes(hstr2bin(slave_data[0])) return slave_data
def add_address_from_seed(self, seed=None) -> str: self.authenticate() words = seed.split() if len(words) == 34: bin_seed = mnemonic2bin(seed) elif len(seed) == 102: bin_seed = hstr2bin(seed) else: raise ValueError("Invalid Seed") address_from_seed = XMSS.from_extended_seed(bin_seed) if self._wallet.get_xmss_by_qaddress(address_from_seed.qaddress, self._passphrase): raise Exception("Address is already in the wallet") self._wallet.append_xmss(address_from_seed) self._encrypt_last_item() self._wallet.save() return address_from_seed.qaddress
def relay_transfer_token_txn_by_slave(self, qaddresses_to: list, amounts: list, token_txhash: str, fee: int, master_qaddress): self.authenticate() index, group_index, slave_index, slave_xmss = self.get_slave_xmss( master_qaddress) if slave_index == -1: raise Exception("No Slave Found") tx = TransferTokenTransaction.create( token_txhash=bytes(hstr2bin(token_txhash)), addrs_to=self.qaddresses_to_address(qaddresses_to), amounts=amounts, fee=fee, xmss_pk=slave_xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) self.sign_and_push_transaction(tx, slave_xmss, index, group_index, slave_index) return self.to_plain_transaction(tx.pbdata)
def test_getAddressFromPK(self): p2p_factory = Mock(spec=P2PFactory) p2p_factory.sync_state = SyncState() p2p_factory.num_connections = 23 p2p_factory.pow = Mock() chain_manager = Mock(spec=ChainManager) chain_manager.height = 0 xrdnode = xrdNode(mining_address=b'') xrdnode.set_chain_manager(chain_manager) xrdnode._p2pfactory = p2p_factory xrdnode._pow = p2p_factory.pow service = PublicAPIService(xrdnode) pk = hstr2bin('01060057ac9cb6085a8135631dcf018dff46d9c368a0b64d508f512e584199b6800' 'f8cfcb672b931398a023680fe0308ed4b6ec75877d684bc2ccf11703e8369f064e7') request = xrd_pb2.GetAddressFromPKReq(pk=bytes(pk)) response = service.GetAddressFromPK(request=request, context=None) self.assertEqual('010600b56d161c7de8aa741962e3e49b973b7e53456fa47f2443d69f17c632f29c8b1aab7d2491', bin2hstr(response.address))
def test_getTransaction(self): with set_xrd_dir("wallet_ver1"): walletd = WalletD() service = WalletAPIService(walletd) tx = xrd_pb2.Transaction() tx.fee = 10 tx.transaction_hash = b'1234' tx.message.message_hash = b'hello' pk = '01020016ecb9f39b9f4275d5a49e232346a15ae2fa8c50a2927daeac189b8c5f2d1' \ '8bc4e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e' tx.public_key = bytes(hstr2bin(pk)) walletd._public_stub.GetTransaction = Mock( return_value=xrd_pb2.GetTransactionResp(tx=tx, confirmations=10)) resp = service.GetTransaction(xrdwallet_pb2.TransactionReq(tx_hash=tx.transaction_hash), context=None) self.assertEqual(resp.code, 0) self.assertIsNotNone(resp.tx) self.assertEqual(resp.tx.transaction_hash, bin2hstr(tx.transaction_hash)) self.assertEqual(resp.confirmations, "10")
def get_block_to_mine(self, wallet_address, tx_pool, last_block, last_block_difficulty) -> list: dev_config = self._chain_manager.get_config_by_block_number( last_block.block_number + 1) try: mining_address = bytes(hstr2bin(wallet_address[1:].decode())) if not OptimizedAddressState.address_is_valid(mining_address): raise ValueError( "[get_block_to_mine] Invalid Wallet Address %s", wallet_address) except Exception as e: raise ValueError("Error while decoding wallet address %s", e) if self._mining_block: if last_block.headerhash == self._mining_block.prev_headerhash: if self._mining_block.transactions[ 0].coinbase.addr_to == mining_address: return [ bin2hstr(self._mining_block.mining_blob(dev_config)), int(bin2hstr(self._current_difficulty), 16) ] else: self._mining_block.update_mining_address( dev_config, mining_address) # Updates only Miner Address self.prepare_next_unmined_block_template(mining_address, tx_pool, last_block, last_block_difficulty, dev_config=dev_config) return [ bin2hstr(self._mining_block.mining_blob(dev_config)), int(bin2hstr(self._current_difficulty), 16) ]
def transfer(destinations, fee, mixin, unlock_time): if len(destinations) > config.dev.transaction_multi_output_limit: raise Exception('Payment Failed: Amount exceeds the allowed limit') addrs_to = [] amounts = [] for tx in destinations: addrs_to.append(bytes(hstr2bin(tx['address'][1:]))) # Skipping 'Q' amounts.append(tx['amount']) stub = get_public_stub() xmss = get_unused_payment_xmss(stub) if not xmss: raise Exception('Payment Failed: No Unused Payment XMSS found') tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, message_data=None, fee=fee, xmss_pk=xmss.pk, master_addr=payment_slaves[0]) tx.sign(xmss) response = stub.PushTransaction(request=xrd_pb2.PushTransactionReq( transaction_signed=tx.pbdata)) if response.error_code != 3: raise Exception('Transaction Submission Failed, Response Code: %s', response.error_code) response = {'tx_hash': bin2hstr(tx.txhash)} return response
def wallet_recover(ctx, seed_type): """ Recovers a wallet from a hexseed or mnemonic (32 words) """ seed = click.prompt('Please enter your %s' % (seed_type,)) seed = seed.lower().strip() if seed_type == 'mnemonic': words = seed.split() if len(words) != 34: print('You have entered %s words' % (len(words),)) print('Mnemonic seed must contain only 34 words') return bin_seed = mnemonic2bin(seed) else: if len(seed) != 102: print('You have entered hexseed of %s characters' % (len(seed),)) print('Hexseed must be of only 102 characters.') return bin_seed = hstr2bin(seed) wallet = Wallet(wallet_path=ctx.obj.wallet_path) recovered_xmss = XMSS.from_extended_seed(bin_seed) print('Recovered Wallet Address : %s' % (Wallet._get_Qaddress(recovered_xmss.address),)) for addr in wallet.address_items: if recovered_xmss.qaddress == addr.qaddress: print('Wallet Address is already in the wallet list') return if click.confirm('Do you want to save the recovered wallet?'): click.echo('Saving...') wallet.append_xmss(recovered_xmss) wallet.save() click.echo('Done') _print_addresses(ctx, wallet.address_items, config.user.wallet_dir)
def bhstr2bin(a_string: str) -> bytes: return bytes(hstr2bin(a_string))