def get_unused_payment_xmss(public_stub): global payment_slaves global payment_xmss master_address = payment_slaves[0] master_address_state = get_addr_state(master_address) if payment_xmss: addr_state = get_addr_state(payment_xmss.address) if set_unused_ots_key(payment_xmss, addr_state, payment_xmss.ots_index): if valid_payment_permission(public_stub, master_address_state, payment_xmss, payment_slaves[2]): return payment_xmss else: payment_xmss = None if not payment_xmss: unused_ots_found = False for slave_seed in payment_slaves[1]: xmss = XMSS.from_extended_seed(slave_seed) addr_state = get_addr_state(xmss.address) if set_unused_ots_key(xmss, addr_state): # Unused ots_key_found payment_xmss = xmss unused_ots_found = True break if not unused_ots_found: # Unused ots_key_found return None if not valid_payment_permission(public_stub, master_address_state, payment_xmss, payment_slaves[2]): return None return payment_xmss
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_mining_xmss(self): if self._mining_xmss: addr_state = self.state.get_address(self._mining_xmss.address) if self.set_unused_ots_key(self._mining_xmss, addr_state, self._mining_xmss.ots_index): if self.valid_mining_permission(): return self._mining_xmss else: self._mining_xmss = None return None if not self._mining_xmss: self._master_address = self._slaves[0] unused_ots_found = False for slave_seed in self._slaves[1]: xmss = XMSS.from_extended_seed(slave_seed) addr_state = self.state.get_address(xmss.address) if self.set_unused_ots_key(xmss, addr_state): # Unused ots_key_found self._mining_xmss = xmss unused_ots_found = True break if not unused_ots_found: # Unused ots_key_found logger.warning('No OTS-KEY left for mining') return None if self._master_address == self._mining_xmss.address: return self._mining_xmss if not self.valid_mining_permission(): return None return self._mining_xmss
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([qrl_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 generate_slave_from_input(slaves_filename): # FIXME: Refactor and improve error handling extended_seed = '' logger.warning('No Slave Seeds found!!') logger.warning('It is highly recommended to use the slave for mining') try: ans = input('Do you want to use main wallet for mining? (Y/N) ') if ans == 'N': quit(0) extended_seed = input( 'Enter hex or mnemonic seed of mining wallet ').encode() except KeyboardInterrupt: quit(0) bin_extended_seed = None if len(extended_seed) == 102: # hexseed bin_extended_seed = hstr2bin(extended_seed.decode()) elif len(extended_seed.split()) == 34: bin_extended_seed = mnemonic2bin(extended_seed.decode()) if bin_extended_seed is None: logger.warning('Invalid XMSS seed') quit(1) addrBundle = XMSS.from_extended_seed(bin_extended_seed) slaves = [ bin2hstr(addrBundle.xmss.address), [addrBundle.xmss.extended_seed], None ] write_slaves(slaves_filename, slaves)
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 test_multi_output_transaction_add_block(self, time_mock): # Test that adding block with a multi-output Transaction updates everybody's balances correctly. self.chain_manager.load(self.genesis_block) extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) transfer_transaction = TransferTransaction.create( addrs_to=[alice.address, random_xmss.address], amounts=[ 40 * int(config.dev.shor_per_quanta), 59 * int(config.dev.shor_per_quanta) ], fee=1 * config.dev.shor_per_quanta, xmss_pk=bob.pk) transfer_transaction._data.nonce = 1 transfer_transaction.sign(bob) time_mock.return_value = 1615270948 # Very high to get an easy difficulty block_1 = Block.create(block_number=1, prev_headerhash=self.genesis_block.headerhash, prev_timestamp=self.genesis_block.timestamp, transactions=[transfer_transaction], miner_address=alice.address) block_1.set_nonces(129, 0) # Uncomment only to determine the correct mining_nonce of above blocks # from qrl.core.PoWValidator import PoWValidator # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): # block_1.set_nonces(block_1.mining_nonce + 1) # print(block_1.mining_nonce) self.assertTrue(block_1.validate(self.chain_manager, {})) result = self.chain_manager.add_block(block_1) self.assertTrue(result) self.assertEqual(self.chain_manager.last_block, block_1) bob_addr_state = self.state.get_address_state(bob.address) alice_addr_state = self.state.get_address_state(alice.address) random_addr_state = self.state.get_address_state(random_xmss.address) self.assertEqual(bob_addr_state.balance, 0) self.assertEqual( alice_addr_state.balance, 140 * int(config.dev.shor_per_quanta) + block_1.block_reward + block_1.fee_reward) self.assertEqual(random_addr_state.balance, 159 * int(config.dev.shor_per_quanta))
def get_new_address(signature_tree_height=config.dev.xmss_tree_height, seed=None) -> AddressBundle: """ Get a new wallet address The address format is a list of two items [address, data structure from random_mss call] :param signature_tree_height: :param address_type: :param seed: :return: a wallet address """ # FIXME: This should be always using the extended seed instead if seed and signature_tree_height: xmss = XMSS(XmssFast(seed, signature_tree_height)) elif seed: xmss = XMSS.from_extended_seed(seed) else: xmss = XMSS.from_height(signature_tree_height) return AddressBundle(bin2hstr(xmss.address).encode(), xmss)
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 wallet_recover(ctx, seed_type): """ Recovers a wallet from a hexseed or mnemonic (32 words) """ if ctx.obj.remote: click.echo('This command is unsupported for remote wallets') return 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) walletObj = 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 walletObj.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...') walletObj.append_xmss(recovered_xmss) walletObj.save() click.echo('Done') _print_addresses(ctx, walletObj.address_items, config.user.wallet_dir)
def _read_wallet(self): self.address_bundle = [] if not os.path.isfile(self.wallet_dat_filename): return try: with open(self.wallet_dat_filename, "rb") as infile: wallet_store = qrl_pb2.WalletStore() wallet_store.ParseFromString(bytes(infile.read())) self.address_bundle = [] for a in wallet_store.wallets: tmpxmss = XMSS.from_extended_seed(mnemonic2bin(a.mnemonic.strip())) tmpxmss.set_ots_index(a.xmss_index) if a.address != bin2hstr(tmpxmss.address).encode(): logger.fatal("Mnemonic and address do not match.") exit(1) self.address_bundle.append(AddressBundle(a.address, tmpxmss)) except Exception as e: logger.warning("It was not possible to open the wallet: %s", e)
def test_multi_output_transaction_add_block(self): with set_data_dir('no_data'): with State() as state: state.get_measurement = MagicMock(return_value=10000000) alice_xmss = get_alice_xmss() bob_xmss = get_bob_xmss() extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) transfer_transaction = TransferTransaction.create( addrs_to=[alice_xmss.address, random_xmss.address], amounts=[ 40 * int(config.dev.shor_per_quanta), 59 * int(config.dev.shor_per_quanta) ], fee=1 * config.dev.shor_per_quanta, xmss_pk=bob_xmss.pk) transfer_transaction._data.nonce = 1 transfer_transaction.sign(bob_xmss) genesis_block = GenesisBlock() chain_manager = ChainManager(state) chain_manager.load(genesis_block) chain_manager._difficulty_tracker = Mock() dt = DifficultyTracker() tmp_difficulty = StringToUInt256('2') tmp_boundary = dt.get_target(tmp_difficulty) chain_manager._difficulty_tracker.get = MagicMock( return_value=(tmp_difficulty, tmp_boundary)) block = state.get_block(genesis_block.headerhash) self.assertIsNotNone(block) with mock.patch('qrl.core.misc.ntp.getTime') as time_mock: time_mock.return_value = 1615270948 # Very high to get an easy difficulty block_1 = Block.create( block_number=1, prevblock_headerhash=genesis_block.headerhash, transactions=[transfer_transaction], miner_address=alice_xmss.address) block_1.set_nonces(274, 0) # Uncomment only to determine the correct mining_nonce of above blocks # from qrl.core.PoWValidator import PoWValidator # while not PoWValidator().validate_mining_nonce(state, block_1.blockheader, False): # block_1.set_nonces(block_1.mining_nonce + 1) # print(block_1.mining_nonce) result = chain_manager.add_block(block_1) self.assertTrue(result) self.assertEqual(chain_manager.last_block, block_1) bob_addr_state = state.get_address(bob_xmss.address) alice_addr_state = state.get_address(alice_xmss.address) random_addr_state = state.get_address(random_xmss.address) self.assertEqual(bob_addr_state.balance, 0) self.assertEqual( alice_addr_state.balance, 140 * int(config.dev.shor_per_quanta) + block_1.block_reward + block_1.fee_reward) self.assertEqual(random_addr_state.balance, 159 * int(config.dev.shor_per_quanta))
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)) return transactions seed = bytes(hstr2bin(input('Enter extended hexseed: '))) dist_xmss = XMSS.from_extended_seed(seed) transactions = get_migration_transactions(signing_xmss=dist_xmss) block = Block.create(block_number=0, prevblock_headerhash=config.dev.genesis_prev_headerhash, transactions=transactions, miner_address=dist_xmss.address) block.set_nonces(0, 0) block._data.genesis_balance.MergeFrom([ qrl_pb2.GenesisBalance(address=config.dev.coinbase_address, balance=105000000000000000) ])