def default_acceptance_callback(self, our_ins, their_ins, our_outs,
                                    their_outs):
        """ Accepts lists of inputs as CTXIns,
        a single output (belonging to us) as a CTxOut,
        and a list of other outputs (belonging not to us) in same
        format, and must return only True or False representing acceptance.

        Note that this code is relying on the calling function to give
        accurate information about the outputs.
        """
        # we must find the utxo in our wallet to get its amount.
        # this serves as a sanity check that the input is indeed
        # ours.
        # we use get_all* because for these purposes mixdepth
        # is irrelevant.
        utxos = self.wallet_service.get_all_utxos()
        our_in_amts = []
        our_out_amts = []
        for i in our_ins:
            utxo_for_i = (i.prevout.hash[::-1], i.prevout.n)
            if utxo_for_i not in utxos.keys():
                success, utxostr = utxo_to_utxostr(utxo_for_i)
                if not success:
                    jlog.error("Code error: input utxo in wrong format.")
                jlog.debug("The input utxo was not found: " + utxostr)
                jlog.debug(
                    "NB: This can simply mean the coin is already spent.")
                return False
            our_in_amts.append(utxos[utxo_for_i]["value"])
        for o in our_outs:
            our_out_amts.append(o.nValue)
        if sum(our_out_amts) - sum(our_in_amts) < self.income_threshold:
            return False
        return True
Esempio n. 2
0
 def on_JM_AUTH_RECEIVED(self, nick, offer, commitment, revelation, amount,
                         kphex):
     offer = json.loads(offer)
     revelation = json.loads(revelation)
     retval = self.client.on_auth_received(nick, offer, commitment,
                                           revelation, amount, kphex)
     if not retval[0]:
         jlog.info("Maker refuses to continue on receiving auth.")
     else:
         utxos, auth_pub, cj_addr, change_addr, btc_sig = retval[1:]
         # json does not allow non-string keys:
         utxos_strkeyed = {}
         for k in utxos:
             success, u = utxo_to_utxostr(k)
             assert success
             utxos_strkeyed[u] = {
                 "value": utxos[k]["value"],
                 "address": utxos[k]["address"]
             }
         auth_pub_hex = bintohex(auth_pub)
         d = self.callRemote(commands.JMIOAuth,
                             nick=nick,
                             utxolist=json.dumps(utxos_strkeyed),
                             pubkey=auth_pub_hex,
                             cjaddr=cj_addr,
                             changeaddr=change_addr,
                             pubkeysig=btc_sig)
         self.defaultCallbacks(d)
     return {"accepted": True}
Esempio n. 3
0
 def default_autofreeze_warning_cb(self, utxo):
     success, utxostr = utxo_to_utxostr(utxo)
     assert success, "Autofreeze warning cb called with invalid utxo."
     jlog.warning("WARNING: new utxo has been automatically "
                  "frozen to prevent forced address reuse: ")
     jlog.warning(utxostr)
     jlog.warning("You can unfreeze this utxo with the method "
                  "'freeze' of wallet-tool.py or the Coins tab "
                  "of Joinmarket-Qt.")
Esempio n. 4
0
 def serialize_revelation(self, separator='|'):
     """ Outputs the over-the-wire format as used in
     Joinmarket communication protocol.
     """
     state_dict = self.reveal()
     success, utxo = utxo_to_utxostr(state_dict["utxo"])
     assert success, "invalid utxo in PoDLE"
     ser_list = [utxo]
     ser_list += [bintohex(state_dict[x]) for x in ["P", "P2", "sig", "e"]]
     ser_string = separator.join(ser_list)
     return ser_string
Esempio n. 5
0
def validate_utxo_data(utxo_datas, retrieve=False, utxo_address_type="p2wpkh"):
    """For each (utxo, privkey), first
    convert the privkey and convert to address,
    then use the blockchain instance to look up
    the utxo and check that its address field matches.
    If retrieve is True, return the set of utxos and their values.
    If segwit is true, assumes a p2sh wrapped p2wpkh, i.e.
    native segwit is NOT currently supported here. If segwit
    is false, p2pkh is assumed.
    """
    results = []
    for u, priv in utxo_datas:
        success, utxostr = utxo_to_utxostr(u)
        if not success:
            jmprint("Invalid utxo format: " + str(u), "error")
            sys.exit(EXIT_FAILURE)
        jmprint('validating this utxo: ' + utxostr, "info")
        # as noted in `ImportWalletMixin` code comments, there is not
        # yet a functional auto-detection of key type from WIF, so the
        # second argument is ignored; we assume p2sh-p2wpkh if segwit=True,
        # p2pkh if segwit=False, and p2wpkh if segwit="native" (slightly
        # ugly, just done for backwards compat.).
        if utxo_address_type == "p2wpkh":
            engine = BTC_P2WPKH
        elif utxo_address_type == "p2sh-p2wpkh":
            engine = BTC_P2SH_P2WPKH
        elif utxo_address_type == "p2pkh":
            engine = BTC_P2PKH
        else:
            raise Exception("Invalid argument: " + str(utxo_address_type))
        rawpriv, _ = BTCEngine.wif_to_privkey(priv)
        addr = engine.privkey_to_address(rawpriv)
        jmprint('claimed address: ' + addr, "info")
        res = jm_single().bc_interface.query_utxo_set([u])
        if len(res) != 1 or None in res:
            jmprint("utxo not found on blockchain: " + utxostr, "error")
            return False
        if res[0]['address'] != addr:
            jmprint(
                "privkey corresponds to the wrong address for utxo: " +
                utxostr, "error")
            jmprint(
                "blockchain returned address: {}".format(res[0]['address']),
                "error")
            jmprint("your privkey gave this address: " + addr, "error")
            return False
        if retrieve:
            results.append((u, res[0]['value']))
    jmprint('all utxos validated OK', "success")
    if retrieve:
        return results
    return True
Esempio n. 6
0
 def __repr__(self):
     """ Specified here to allow logging.
     """
     # note: will throw if not fully initalised
     r = self.reveal()
     success, utxo = utxo_to_utxostr(r["utxo"])
     assert success, "invalid utxo in PoDLE."
     return pformat({'used': r["used"],
             'utxo': utxo,
             'P': bintohex(r["P"]),
             'P2': bintohex(r["P2"]),
             'commit': bintohex(r["commit"]),
             'sig': bintohex(r["sig"]),
             'e': bintohex(r["e"])})
Esempio n. 7
0
def human_readable_input(txinput, txinput_witness):
    """ Pass objects of type CTxIn and CTxInWitness (or None)
    and a dict of human-readable entries for this input
    is returned.
    """
    assert isinstance(txinput, CTxIn)
    outdict = {}
    success, u = utxo_to_utxostr(
        (txinput.prevout.hash[::-1], txinput.prevout.n))
    assert success
    outdict["outpoint"] = u
    outdict["scriptSig"] = bintohex(txinput.scriptSig)
    outdict["nSequence"] = txinput.nSequence

    if txinput_witness:
        outdict["witness"] = bintohex(
            txinput_witness.scriptWitness.serialize())
    return outdict
Esempio n. 8
0
def validate_utxo_data(utxo_datas, retrieve=False, utxo_address_type="p2wpkh"):
    """For each (utxo, privkey), first
    convert the privkey and convert to address,
    then use the blockchain instance to look up
    the utxo and check that its address field matches.
    If retrieve is True, return the set of utxos and their values.
    """
    results = []
    for u, priv in utxo_datas:
        success, utxostr = utxo_to_utxostr(u)
        if not success:
            jmprint("Invalid utxo format: " + str(u), "error")
            sys.exit(EXIT_FAILURE)
        jmprint('validating this utxo: ' + utxostr, "info")
        # as noted in `ImportWalletMixin` code comments, there is not
        # yet a functional auto-detection of key type from WIF, hence
        # the need for this additional switch:
        if utxo_address_type == "p2wpkh":
            engine = BTC_P2WPKH
        elif utxo_address_type == "p2sh-p2wpkh":
            engine = BTC_P2SH_P2WPKH
        elif utxo_address_type == "p2pkh":
            engine = BTC_P2PKH
        else:
            raise Exception("Invalid argument: " + str(utxo_address_type))
        rawpriv, _ = BTCEngine.wif_to_privkey(priv)
        addr = engine.privkey_to_address(rawpriv)
        jmprint('claimed address: ' + addr, "info")
        res = jm_single().bc_interface.query_utxo_set([u])
        if len(res) != 1 or None in res:
            jmprint("utxo not found on blockchain: " + utxostr, "error")
            return False
        returned_addr = engine.script_to_address(res[0]['script'])
        if returned_addr != addr:
            return print_failed_addr_match(utxostr, addr, returned_addr)
        if retrieve:
            results.append((u, res[0]['value']))
    jmprint('all utxos validated OK', "success")
    if retrieve:
        return results
    return True
Esempio n. 9
0
 def report_changed(x, utxos):
     if len(utxos.keys()) > 0:
         jlog.info(x + ' utxos=\n{}'.format('\n'.join(
             '{} - {}'.format(
                 utxo_to_utxostr(u)[1], fmt_tx_data(tx_data, self))
             for u, tx_data in utxos.items())))
Esempio n. 10
0
def fmt_utxo(utxo):
    success, utxostr = utxo_to_utxostr(utxo)
    assert success
    return utxostr