def wallet_showutxos(wallet, showprivkey): unsp = {} max_tries = jm_single().config.getint("POLICY", "taker_utxo_retries") for u, av in wallet.unspent.iteritems(): key = wallet.get_key_from_addr(av['address']) tries = podle.get_podle_tries(u, key, max_tries) tries_remaining = max(0, max_tries - tries) unsp[u] = { 'address': av['address'], 'value': av['value'], 'tries': tries, 'tries_remaining': tries_remaining, 'external': False } if showprivkey: wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2pk_vbyte()) unsp[u]['privkey'] = wifkey used_commitments, external_commitments = podle.get_podle_commitments() for u, ec in external_commitments.iteritems(): tries = podle.get_podle_tries(utxo=u, max_tries=max_tries, external=True) tries_remaining = max(0, max_tries - tries) unsp[u] = { 'tries': tries, 'tries_remaining': tries_remaining, 'external': True } return json.dumps(unsp, indent=4)
def wallet_showutxos(wallet, showprivkey): unsp = {} max_tries = jm_single().config.getint("POLICY", "taker_utxo_retries") utxos = wallet.get_utxos_by_mixdepth() for md in utxos: for u, av in utxos[md].items(): key = wallet.get_key_from_addr(av['address']) tries = podle.get_podle_tries(u, key, max_tries) tries_remaining = max(0, max_tries - tries) unsp[u] = { 'address': av['address'], 'value': av['value'], 'tries': tries, 'tries_remaining': tries_remaining, 'external': False } if showprivkey: unsp[u]['privkey'] = wallet.get_wif_path(av['path']) used_commitments, external_commitments = podle.get_podle_commitments() for u, ec in iteritems(external_commitments): tries = podle.get_podle_tries(utxo=u, max_tries=max_tries, external=True) tries_remaining = max(0, max_tries - tries) unsp[u] = { 'tries': tries, 'tries_remaining': tries_remaining, 'external': True } return json.dumps(unsp, indent=4)
def make_commitment(self): """The Taker default commitment function, which uses PoDLE. Alternative commitment types should use a different commit type byte. This will allow future upgrades to provide different style commitments by subclassing Taker and changing the commit_type_byte; existing makers will simply not accept this new type of commitment. In case of success, return the commitment and its opening. In case of failure returns (None, None) and constructs a detailed log for the user to read and discern the reason. """ def filter_by_coin_age_amt(utxos, age, amt): results = jm_single().bc_interface.query_utxo_set(utxos, includeconf=True) newresults = [] too_old = [] too_small = [] for i, r in enumerate(results): #results return "None" if txo is spent; drop this if not r: continue valid_age = r['confirms'] >= age valid_amt = r['value'] >= amt if not valid_age: too_old.append(utxos[i]) if not valid_amt: too_small.append(utxos[i]) if valid_age and valid_amt: newresults.append(utxos[i]) return newresults, too_old, too_small def priv_utxo_pairs_from_utxos(utxos, age, amt): #returns pairs list of (priv, utxo) for each valid utxo; #also returns lists "too_old" and "too_small" for any #utxos that did not satisfy the criteria for debugging. priv_utxo_pairs = [] new_utxos, too_old, too_small = filter_by_coin_age_amt( list(utxos.keys()), age, amt) new_utxos_dict = {k: v for k, v in utxos.items() if k in new_utxos} for k, v in new_utxos_dict.items(): addr = self.wallet_service.script_to_addr(v["script"]) priv = self.wallet_service.get_key_from_addr(addr) if priv: #can be null from create-unsigned priv_utxo_pairs.append((priv, k)) return priv_utxo_pairs, too_old, too_small commit_type_byte = "P" tries = jm_single().config.getint("POLICY", "taker_utxo_retries") age = jm_single().config.getint("POLICY", "taker_utxo_age") #Minor rounding errors don't matter here amt = int( self.cjamount * jm_single().config.getint("POLICY", "taker_utxo_amtpercent") / 100.0) priv_utxo_pairs, to, ts = priv_utxo_pairs_from_utxos( self.input_utxos, age, amt) #For podle data format see: podle.PoDLE.reveal() #In first round try, don't use external commitments podle_data = generate_podle(priv_utxo_pairs, tries) if not podle_data: #Pre-filter the set of external commitments that work for this #transaction according to its size and age. dummy, extdict = get_podle_commitments() if len(extdict) > 0: ext_valid, ext_to, ext_ts = filter_by_coin_age_amt( list(extdict.keys()), age, amt) else: ext_valid = None #We defer to a second round to try *all* utxos in spending mixdepth; #this is because it's much cleaner to use the utxos involved #in the transaction, about to be consumed, rather than use #random utxos that will persist after. At this step we also #allow use of external utxos in the json file. mixdepth_utxos = self.wallet_service.get_utxos_by_mixdepth()[ self.mixdepth] if len(self.input_utxos) == len(mixdepth_utxos): # Already tried the whole mixdepth podle_data = generate_podle([], tries, ext_valid) else: priv_utxo_pairs, to, ts = priv_utxo_pairs_from_utxos( mixdepth_utxos, age, amt) podle_data = generate_podle(priv_utxo_pairs, tries, ext_valid) if podle_data: jlog.debug("Generated PoDLE: " + repr(podle_data)) return (commit_type_byte + bintohex(podle_data.commitment), podle_data.serialize_revelation(), "Commitment sourced OK") else: errmsgheader, errmsg = generate_podle_error_string( priv_utxo_pairs, to, ts, self.wallet_service, self.cjamount, jm_single().config.get("POLICY", "taker_utxo_age"), jm_single().config.get("POLICY", "taker_utxo_amtpercent")) with open("commitments_debug.txt", "wb") as f: errmsgfileheader = (b"THIS IS A TEMPORARY FILE FOR DEBUGGING; " b"IT CAN BE SAFELY DELETED ANY TIME.\n") errmsgfileheader += (b"***\n") f.write(errmsgfileheader + errmsg.encode('utf-8')) return (None, (priv_utxo_pairs, to, ts), errmsgheader + errmsg)