def on_auth_received(self, nick, offer, commitment, cr, amount, kphex): """Receives data on proposed transaction offer from daemon, verifies commitment, returns necessary data to send ioauth message (utxos etc) """ #deserialize the commitment revelation cr_dict = 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): jlog.info("Counterparty commitment not accepted, reason: " + msg) return (False, ) if not verify_podle(str(cr_dict['P']), str(cr_dict['P2']), str(cr_dict['sig']), str(cr_dict['e']), str(commitment), 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( 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'] != self.wallet.pubkey_to_address(cr_dict['P']): reason = "Invalid podle pubkey: " + str(cr_dict['P']) return reject(reason) # authorisation of taker passed #Find utxos for the transaction now: utxos, cj_addr, change_addr = self.oid_to_order(offer, amount) if not utxos: #could not find funds return (False, ) self.wallet.update_cache_index() # Construct data for auth request back 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 = utxos[utxos.keys()[0]]['address'] auth_key = self.wallet.get_key_from_addr(auth_address) auth_pub = btc.privtopub(auth_key) btc_sig = btc.ecdsa_sign(kphex, auth_key) return (True, utxos, auth_pub, cj_addr, change_addr, btc_sig)
def start_encryption(self, nick, maker_pk): if nick not in self.active_orders.keys(): log.debug("Counterparty not part of this transaction. Ignoring") return try: self.crypto_boxes[nick] = [ maker_pk, as_init_encryption(self.kp, init_pubkey(maker_pk)) ] except NaclError as e: log.debug("Unable to setup crypto box with " + nick + ": " + repr(e)) self.msgchan.send_error(nick, "invalid nacl pubkey: " + maker_pk) return # send authorisation request log.debug("Starting auth, utxos: " + pprint.pformat(self.input_utxos)) if self.auth_addr: my_btc_addr = self.auth_addr else: my_btc_addr = self.input_utxos.itervalues().next()['address'] log.debug("Trying to get privkey") my_btc_priv = self.wallet.get_key_from_addr(my_btc_addr) log.debug("Trying to get pubkey") my_btc_pub = btc.privtopub(my_btc_priv) log.debug("Got pubkey: " + str(my_btc_pub)) my_btc_sig = btc.ecdsa_sign(self.kp.hex_pk(), my_btc_priv) self.msgchan.send_auth(nick, my_btc_pub, my_btc_sig)
def get_addr(self, mixing_depth, forchange, i): """Construct a p2sh-p2wpkh style address for the keypair corresponding to mixing depth mixing_depth, branch forchange and index i """ pub = btc.privtopub(self.get_key(mixing_depth, forchange, i)) return btc.pubkey_to_p2sh_p2wpkh_address(pub, magicbyte=self.get_vbyte())
def set_nick(self): self.nick_pubkey = btc.privtopub(self.nick_priv) self.nick_pkh_raw = hashlib.sha256(self.nick_pubkey).digest()[ :self.nick_hashlen] self.nick_pkh = btc.changebase(self.nick_pkh_raw, 256, 58) #right pad to maximum possible; b58 is not fixed length. #Use 'O' as one of the 4 not included chars in base58. self.nick_pkh += 'O' * (self.nick_maxencoded - len(self.nick_pkh)) #The constructed length will be 1 + 1 + NICK_MAX_ENCODED self.nick = self.nick_header + str(self.jm_version) + self.nick_pkh jm_single().nickname = self.nick
def donation_address(reusable_donation_pubkey=None): #pragma: no cover #Donation code currently disabled, so not tested. if not reusable_donation_pubkey: reusable_donation_pubkey = ('02be838257fbfddabaea03afbb9f16e852' '9dfe2de921260a5c46036d97b5eacf2a') sign_k = binascii.hexlify(os.urandom(32)) c = btc.sha256(btc.multiply(sign_k, reusable_donation_pubkey, True)) sender_pubkey = btc.add_pubkeys( [reusable_donation_pubkey, btc.privtopub(c + '01', True)], True) sender_address = btc.pubtoaddr(sender_pubkey, get_p2pk_vbyte()) log.debug('sending coins to ' + sender_address) return sender_address, sign_k
def auth_counterparty(self, nick, i_utxo_pubkey, btc_sig): self.i_utxo_pubkey = i_utxo_pubkey if not btc.ecdsa_verify(self.taker_pk, btc_sig, self.i_utxo_pubkey): print('signature didnt match pubkey and message') return False # authorisation of taker passed # (but input utxo pubkey is checked in verify_unsigned_tx). # Send auth request to taker # TODO the next 2 lines are a little inefficient. btc_key = self.maker.wallet.get_key_from_addr(self.cj_addr) btc_pub = btc.privtopub(btc_key) btc_sig = btc.ecdsa_sign(self.kp.hex_pk(), btc_key) self.maker.msgchan.send_ioauth(nick, self.utxos.keys(), btc_pub, self.change_addr, btc_sig) return True
def start_encryption(self, nick, maker_pk): if nick not in self.active_orders.keys(): log.debug("Counterparty not part of this transaction. Ignoring") return try: self.crypto_boxes[nick] = [maker_pk, as_init_encryption( self.kp, init_pubkey(maker_pk))] except NaclError as e: log.debug("Unable to setup crypto box with " + nick + ": " + repr(e)) self.msgchan.send_error(nick, "invalid nacl pubkey: " + maker_pk) return # send authorisation request log.debug("Starting auth, utxos: " + pprint.pformat(self.input_utxos)) if self.auth_addr: my_btc_addr = self.auth_addr else: my_btc_addr = self.input_utxos.itervalues().next()['address'] log.debug("Trying to get privkey") my_btc_priv = self.wallet.get_key_from_addr(my_btc_addr) log.debug("Trying to get pubkey") my_btc_pub = btc.privtopub(my_btc_priv) log.debug("Got pubkey: " + str(my_btc_pub)) my_btc_sig = btc.ecdsa_sign(self.kp.hex_pk(), my_btc_priv) self.msgchan.send_auth(nick, my_btc_pub, my_btc_sig)