def slave_tx_generate(ctx, src, master, number_of_slaves, access_type, fee, pk, ots_key_index): """ Generates Slave Transaction for the wallet """ try: _, src_xmss = _select_wallet(ctx, src) ots_key_index = validate_ots_index(ots_key_index, src_xmss) src_xmss.set_ots_index(ots_key_index) if src_xmss: address_src_pk = src_xmss.pk else: address_src_pk = pk.encode() master_addr = None if master: master_addr = parse_qaddress(master) fee_shor = _quanta_to_shor(fee) except Exception as e: click.echo("Error validating arguments: {}".format(e)) quit(1) slave_xmss = [] slave_pks = [] access_types = [] slave_xmss_seed = [] if number_of_slaves > 100: click.echo("Error: Max Limit for the number of slaves is 100") quit(1) for i in range(number_of_slaves): print("Generating Slave #" + str(i + 1)) xmss = XMSS.from_height(config.dev.xmss_tree_height) slave_xmss.append(xmss) slave_xmss_seed.append(xmss.extended_seed) slave_pks.append(xmss.pk) access_types.append(access_type) print("Successfully Generated Slave %s/%s" % (str(i + 1), number_of_slaves)) try: tx = SlaveTransaction.create(slave_pks=slave_pks, access_types=access_types, fee=fee_shor, xmss_pk=address_src_pk, master_addr=master_addr) tx.sign(src_xmss) with open('slaves.json', 'w') as f: json.dump( [bin2hstr(src_xmss.address), slave_xmss_seed, tx.to_json()], f) click.echo('Successfully created slaves.json') click.echo( 'Move slaves.json file from current directory to the mining node inside ~/.qrl/' ) except Exception as e: click.echo("Unhandled error: {}".format(str(e))) quit(1)
def slave_tx_generate(ctx, src, addr_from, number_of_slaves, access_type, fee, pk, otsidx): """ Generates Slave Transaction for the wallet """ try: address_src, src_xmss = _select_wallet(ctx, src) src_xmss.set_ots_index(otsidx) if len(addr_from.strip()) == 0: addr_from = address_src if src_xmss: address_src_pk = src_xmss.pk else: address_src_pk = pk.encode() fee_shor = int(fee * 1.e9) except Exception as e: click.echo("Error validating arguments") quit(1) slave_xmss = [] slave_pks = [] access_types = [] slave_xmss_seed = [] if number_of_slaves > 100: click.echo("Error: Max Limit for the number of slaves is 100") quit(1) for i in range(number_of_slaves): print("Generating Slave #" + str(i + 1)) xmss = XMSS.from_height(config.dev.xmss_tree_height) slave_xmss.append(xmss) slave_xmss_seed.append(xmss.extended_seed) slave_pks.append(xmss.pk) access_types.append(access_type) print("Successfully Generated Slave %s/%s" % (str(i + 1), number_of_slaves)) channel = grpc.insecure_channel(ctx.obj.node_public_address) stub = qrl_pb2_grpc.PublicAPIStub(channel) # FIXME: This could be problematic. Check slaveTxnReq = qrl_pb2.SlaveTxnReq(address_from=addr_from, slave_pks=slave_pks, access_types=access_types, fee=fee_shor, xmss_pk=address_src_pk, ) try: slaveTxnResp = stub.GetSlaveTxn(slaveTxnReq, timeout=5) tx = Transaction.from_pbdata(slaveTxnResp.transaction_unsigned) tx.sign(src_xmss) with open('slaves.json', 'w') as f: json.dump([bin2hstr(src_xmss.address), slave_xmss_seed, tx.to_json()], f) click.echo('Successfully created slaves.json') click.echo('Move slaves.json file from current directory to the mining node inside ~/.qrl/') except grpc.RpcError as e: click.echo(e.details()) quit(1) except Exception as e: click.echo("Unhandled error: {}".format(str(e))) quit(1)
def add_new_address(self, height, hash_function="shake128"): if self.encrypted or self.encrypted_partially: raise WalletEncryptionError("Please decrypt all addresses in this wallet before adding a new address!") tmp_xmss = XMSS.from_height(height, hash_function) self.append_xmss(tmp_xmss) return tmp_xmss
def add_slave(self, index, height, number_of_slaves=1, passphrase: str=None, hash_function="shake128", force=False): if not force: if self.encrypted or self.encrypted_partially: raise WalletEncryptionError("Please decrypt all addresses in this wallet before adding a new address!") slaves_xmss = [] for i in range(number_of_slaves): tmp_xmss = XMSS.from_height(height, hash_function) if i == number_of_slaves - 1: tmp_xmss.set_ots_index(UNRESERVED_OTS_INDEX_START) # Start from unreserved ots index slaves_xmss.append(tmp_xmss) self.append_slave(slaves_xmss, passphrase, index) return slaves_xmss
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 get_mining_slave_addresses(args): slaves_filename = os.path.join(config.user.wallet_dir, config.user.slaves_filename) if args.randomizeSlaveXMSS: xmss = XMSS.from_height(config.dev.slave_xmss_height) slaves = [bin2hstr(xmss.address), [xmss.extended_seed], None] write_slaves(slaves_filename, slaves) if not os.path.isfile(slaves_filename): generate_slave_from_input(slaves_filename) slaves = None try: slaves = read_slaves(slaves_filename) except KeyboardInterrupt: quit(1) except Exception as e: logger.error('Exception %s', e) quit(1) return slaves
def add_new_address(self, height): tmp_xmss = XMSS.from_height(height) self.append_xmss(tmp_xmss) return tmp_xmss
def get_random_xmss(xmss_height=6) -> XMSS: return XMSS.from_height(xmss_height)
def test_from_height_custom_hash(self): xmss_height = 4 xmss = XMSS.from_height(xmss_height, "shake128") self.assertEqual('shake128', xmss.hash_function)
def create_block(self, last_block, mining_nonce, tx_pool, signing_xmss, master_address) -> Optional[Block]: # TODO: Persistence will move to rocksdb # FIXME: Difference between this and create block????????????? # FIXME: Break encapsulation if not self._dummy_xmss: self._dummy_xmss = XMSS.from_height(signing_xmss.height) dummy_block = Block.create(block_number=last_block.block_number + 1, prevblock_headerhash=last_block.headerhash, transactions=[], signing_xmss=self._dummy_xmss, master_address=master_address, nonce=0) dummy_block.set_mining_nonce(mining_nonce) t_pool2 = copy.deepcopy(tx_pool.transaction_pool) del tx_pool.transaction_pool[:] ###### # recreate the transaction pool as in the tx_hash_list, ordered by txhash.. total_txn = len(t_pool2) txnum = 0 addresses_set = set() while txnum < total_txn: tx = t_pool2[txnum] tx.set_effected_address(addresses_set) txnum += 1 addresses_state = dict() for address in addresses_set: addresses_state[address] = self.state.get_address(address) block_size = dummy_block.size block_size_limit = self.state.get_block_size_limit(last_block) txnum = 0 while txnum < total_txn: tx = t_pool2[txnum] # Skip Transactions for later, which doesn't fit into block if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit: txnum += 1 continue addr_from_pk_state = addresses_state[tx.addr_from] addr_from_pk = Transaction.get_slave(tx) if addr_from_pk: addr_from_pk_state = addresses_state[addr_from_pk] if addr_from_pk_state.ots_key_reuse(tx.ots_key): del t_pool2[txnum] total_txn -= 1 continue if isinstance(tx, TransferTransaction): if addresses_state[ tx.addr_from].balance < tx.total_amount + tx.fee: logger.warning('%s %s exceeds balance, invalid tx', tx, tx.addr_from) logger.warning('type: %s', tx.type) logger.warning( 'Buffer State Balance: %s Transfer Amount %s', addresses_state[tx.addr_from].balance, tx.total_amount) del t_pool2[txnum] total_txn -= 1 continue if isinstance(tx, MessageTransaction): if addresses_state[tx.addr_from].balance < tx.fee: logger.warning('%s %s exceeds balance, invalid message tx', tx, tx.addr_from) logger.warning('type: %s', tx.type) logger.warning('Buffer State Balance: %s Free %s', addresses_state[tx.addr_from].balance, tx.fee) total_txn -= 1 continue if isinstance(tx, TokenTransaction): if addresses_state[tx.addr_from].balance < tx.fee: logger.warning('%s %s exceeds balance, invalid tx', tx, tx.addr_from) logger.warning('type: %s', tx.type) logger.warning('Buffer State Balance: %s Fee %s', addresses_state[tx.addr_from].balance, tx.fee) del t_pool2[txnum] total_txn -= 1 continue if isinstance(tx, TransferTokenTransaction): if addresses_state[tx.addr_from].balance < tx.fee: logger.warning('%s %s exceeds balance, invalid tx', tx, tx.addr_from) logger.warning('type: %s', tx.type) logger.warning( 'Buffer State Balance: %s Transfer Amount %s', addresses_state[tx.addr_from].balance, tx.fee) del t_pool2[txnum] total_txn -= 1 continue if bin2hstr(tx.token_txhash).encode() not in addresses_state[ tx.addr_from].tokens: logger.warning( '%s doesnt own any token with token_txnhash %s', tx.addr_from, bin2hstr(tx.token_txhash).encode()) del t_pool2[txnum] total_txn -= 1 continue if addresses_state[tx.addr_from].tokens[bin2hstr( tx.token_txhash).encode()] < tx.total_amount: logger.warning( 'Token Transfer amount exceeds available token') logger.warning('Token Txhash %s', bin2hstr(tx.token_txhash).encode()) logger.warning( 'Available Token Amount %s', addresses_state[tx.addr_from].tokens[bin2hstr( tx.token_txhash).encode()]) logger.warning('Transaction Amount %s', tx.total_amount) del t_pool2[txnum] total_txn -= 1 continue if isinstance(tx, LatticePublicKey): if addresses_state[tx.addr_from].balance < tx.fee: logger.warning( 'Lattice TXN %s %s exceeds balance, invalid tx', tx, tx.addr_from) logger.warning('type: %s', tx.type) logger.warning( 'Buffer State Balance: %s Transfer Amount %s', addresses_state[tx.addr_from].balance, tx.fee) del t_pool2[txnum] total_txn -= 1 continue if isinstance(tx, SlaveTransaction): if addresses_state[tx.addr_from].balance < tx.fee: logger.warning( 'Slave TXN %s %s exceeds balance, invalid tx', tx, tx.addr_from) logger.warning('type: %s', tx.type) logger.warning( 'Buffer State Balance: %s Transfer Amount %s', addresses_state[tx.addr_from].balance, tx.fee) del t_pool2[txnum] total_txn -= 1 continue tx.apply_on_state(addresses_state) tx_pool.add_tx_to_pool(tx) tx._data.nonce = addresses_state[tx.addr_from].nonce txnum += 1 block_size += tx.size + config.dev.tx_extra_overhead coinbase_nonce = self.state.get_address(signing_xmss.address).nonce if signing_xmss.address in addresses_state: coinbase_nonce = addresses_state[signing_xmss.address].nonce + 1 block = Block.create(block_number=last_block.block_number + 1, prevblock_headerhash=last_block.headerhash, transactions=t_pool2, signing_xmss=signing_xmss, master_address=master_address, nonce=coinbase_nonce) return block