Example #1
0
    def auth_counterparty(self, nick, cr):
        #deserialize the commitment revelation
        cr_dict = btc.PoDLE.deserialize_revelation(cr)
        #check the validity of the proof of discrete log equivalence
        tries = jm_single().config.getint("POLICY", "taker_utxo_retries")
        def reject(msg):
            log.info("Counterparty commitment not accepted, reason: " + msg)
            return False
        if not btc.verify_podle(cr_dict['P'], cr_dict['P2'], cr_dict['sig'],
                                cr_dict['e'], self.maker.commit,
                                index_range=range(tries)):
            reason = "verify_podle failed"
            return reject(reason)
        #finally, check that the proffered utxo is real, old enough, large enough,
        #and corresponds to the pubkey
        res = jm_single().bc_interface.query_utxo_set([cr_dict['utxo']],
                                                      includeconf=True)
        if len(res) != 1 or not res[0]:
            reason = "authorizing utxo is not valid"
            return reject(reason)
        age = jm_single().config.getint("POLICY", "taker_utxo_age")
        if res[0]['confirms'] < age:
            reason = "commitment utxo not old enough: " + str(res[0]['confirms'])
            return reject(reason)
        reqd_amt = int(self.cj_amount * jm_single().config.getint(
            "POLICY", "taker_utxo_amtpercent") / 100.0)
        if res[0]['value'] < reqd_amt:
            reason = "commitment utxo too small: " + str(res[0]['value'])
            return reject(reason)
        if res[0]['address'] != btc.pubkey_to_address(cr_dict['P'],
                                                         get_p2pk_vbyte()):
            reason = "Invalid podle pubkey: " + str(cr_dict['P'])
            return reject(reason)

        # authorisation of taker passed

        # Send auth request to taker
        # Need to choose an input utxo pubkey to sign with
        # (no longer using the coinjoin pubkey from 0.2.0)
        # Just choose the first utxo in self.utxos and retrieve key from wallet.
        auth_address = self.utxos[self.utxos.keys()[0]]['address']
        auth_key = self.maker.wallet.get_key_from_addr(auth_address)
        auth_pub = btc.privtopub(auth_key)
        btc_sig = btc.ecdsa_sign(self.kp.hex_pk(), auth_key)
        self.maker.msgchan.send_ioauth(nick, self.utxos.keys(), auth_pub,
                                       self.cj_addr, self.change_addr, btc_sig)
        #In case of *blacklisted (ie already used) commitments, we already
        #broadcasted them on receipt; in case of valid, and now used commitments,
        #we broadcast them here, and not early - to avoid accidentally
        #blacklisting commitments that are broadcast between makers in real time
        #for the same transaction.
        self.maker.transfer_commitment(self.maker.commit)
        #now persist the fact that the commitment is actually used.
        check_utxo_blacklist(self.maker.commit, persist=True)
        return True
Example #2
0
 def on_order_fill(self, nick, oid, amount, taker_pubkey, commit):
     if nick in self.active_orders and self.active_orders[nick] is not None:
         self.active_orders[nick] = None
         log.info('had a partially filled order but starting over now')
     if not commit[0] == "P":
         self.msgchan.send_error(
             nick, "Unsupported commitment type: " + str(commit[0]))
         return
     #Strip the type byte before processing
     scommit = commit[1:]
     if not check_utxo_blacklist(scommit):
         log.info("Taker utxo commitment is blacklisted, rejecting.")
         self.msgchan.send_error(nick,
                             "Commitment is blacklisted: " + str(scommit))
         #Note that broadcast is happening here to reflect an already
         #consumed commitment; it can also be broadcast separately (earlier) on
         #valid usage in CoinjoinOrder.auth_counterparty().
         #Keep the type byte for communication so not scommit:
         self.transfer_commitment(commit)
         return
     self.commit = scommit
     self.wallet_unspent_lock.acquire()
     try:
         self.active_orders[nick] = CoinJoinOrder(self, nick, oid, amount,
                                                  taker_pubkey)
     finally:
         self.wallet_unspent_lock.release()
Example #3
0
 def on_order_fill(self, nick, oid, amount, taker_pubkey, commit):
     if nick in self.active_orders and self.active_orders[nick] is not None:
         self.active_orders[nick] = None
         log.debug('had a partially filled order but starting over now')
     if not commit[0] == "P":
         self.msgchan.send_error(
             nick, "Unsupported commitment type: " + str(commit[0]))
         return
     #Strip the type byte before processing
     scommit = commit[1:]
     if not check_utxo_blacklist(scommit):
         log.debug("Taker utxo commitment is blacklisted, rejecting.")
         self.msgchan.send_error(
             nick, "Commitment is blacklisted: " + str(scommit))
         #Note that broadcast is happening here to reflect an already
         #consumed commitment; it can also be broadcast separately (earlier) on
         #valid usage in CoinjoinOrder.auth_counterparty().
         #Keep the type byte for communication so not scommit:
         self.transfer_commitment(commit)
         return
     self.commit = scommit
     self.wallet_unspent_lock.acquire()
     try:
         self.active_orders[nick] = CoinJoinOrder(self, nick, oid, amount,
                                                  taker_pubkey)
     finally:
         self.wallet_unspent_lock.release()
Example #4
0
    def on_commitment_seen(self, nick, commitment):
        """Triggered when we see a commitment for blacklisting
	appear in the public pit channel. If the policy is set,
	we blacklist this commitment.
	"""
        if jm_single().config.has_option("POLICY", "accept_commitment_broadcasts"):
            blacklist_add = jm_single().config.getint("POLICY",
                                                    "accept_commitment_broadcasts")
        else:
            blacklist_add = 0
        if blacklist_add > 0:
            #just add if necessary, ignore return value.
            check_utxo_blacklist(commitment, persist=True)
            log.debug("Received commitment broadcast by other maker: " + str(
                commitment) + ", now blacklisted.")
        else:
            log.debug("Received commitment broadcast by other maker: " + str(
                commitment) + ", ignored.")
Example #5
0
    def on_commitment_seen(self, nick, commitment):
        """Triggered when we see a commitment for blacklisting
	appear in the public pit channel. If the policy is set,
	we blacklist this commitment.
	"""
        if jm_single().config.has_option("POLICY",
                                         "accept_commitment_broadcasts"):
            blacklist_add = jm_single().config.getint(
                "POLICY", "accept_commitment_broadcasts")
        else:
            blacklist_add = 0
        if blacklist_add > 0:
            #just add if necessary, ignore return value.
            check_utxo_blacklist(commitment, persist=True)
            log.debug("Received commitment broadcast by other maker: " +
                      str(commitment) + ", now blacklisted.")
        else:
            log.debug("Received commitment broadcast by other maker: " +
                      str(commitment) + ", ignored.")
Example #6
0
    def auth_counterparty(self, nick, cr):
        #deserialize the commitment revelation
        cr_dict = btc.PoDLE.deserialize_revelation(cr)
        #check the validity of the proof of discrete log equivalence
        tries = jm_single().config.getint("POLICY", "taker_utxo_retries")

        def reject(msg):
            log.debug("Counterparty commitment not accepted, reason: " + msg)
            return False

        if not btc.verify_podle(cr_dict['P'],
                                cr_dict['P2'],
                                cr_dict['sig'],
                                cr_dict['e'],
                                self.maker.commit,
                                index_range=range(tries)):
            reason = "verify_podle failed"
            return reject(reason)
        #finally, check that the proffered utxo is real, old enough, large enough,
        #and corresponds to the pubkey
        res = jm_single().bc_interface.query_utxo_set([cr_dict['utxo']],
                                                      includeconf=True)
        if len(res) != 1 or not res[0]:
            reason = "authorizing utxo is not valid"
            return reject(reason)
        age = jm_single().config.getint("POLICY", "taker_utxo_age")
        if res[0]['confirms'] < age:
            reason = "commitment utxo not old enough: " + str(
                res[0]['confirms'])
            return reject(reason)
        reqd_amt = int(
            self.cj_amount *
            jm_single().config.getint("POLICY", "taker_utxo_amtpercent") /
            100.0)
        if res[0]['value'] < reqd_amt:
            reason = "commitment utxo too small: " + str(res[0]['value'])
            return reject(reason)
        if res[0]['address'] != btc.pubkey_to_address(cr_dict['P'],
                                                      get_p2pk_vbyte()):
            reason = "Invalid podle pubkey: " + str(cr_dict['P'])
            return reject(reason)

        # authorisation of taker passed

        # Send auth request to taker
        # Need to choose an input utxo pubkey to sign with
        # (no longer using the coinjoin pubkey from 0.2.0)
        # Just choose the first utxo in self.utxos and retrieve key from wallet.
        auth_address = self.utxos[self.utxos.keys()[0]]['address']
        auth_key = self.maker.wallet.get_key_from_addr(auth_address)
        auth_pub = btc.privtopub(auth_key)
        btc_sig = btc.ecdsa_sign(self.kp.hex_pk(), auth_key)
        self.maker.msgchan.send_ioauth(nick, self.utxos.keys(), auth_pub,
                                       self.cj_addr, self.change_addr, btc_sig)
        #In case of *blacklisted (ie already used) commitments, we already
        #broadcasted them on receipt; in case of valid, and now used commitments,
        #we broadcast them here, and not early - to avoid accidentally
        #blacklisting commitments that are broadcast between makers in real time
        #for the same transaction.
        self.maker.transfer_commitment(self.maker.commit)
        #now persist the fact that the commitment is actually used.
        check_utxo_blacklist(self.maker.commit, persist=True)
        return True