def test_valid_sigs(setup_ecc): for v in vectors['vectors']: msg = v['msg'] sig = v['sig'] priv = v['privkey'] assert sig == btc.ecdsa_raw_sign(msg, priv, True, rawmsg=True) + '01' #check that the signature verifies against the key(pair) pubkey = btc.privtopub(priv) assert btc.ecdsa_raw_verify(msg, pubkey, sig[:-2], True, rawmsg=True) #check that it fails to verify against corrupted signatures for i in [0, 1, 2, 4, 7, 25, 55]: #corrupt one byte binsig = binascii.unhexlify(sig) checksig = binascii.hexlify(binsig[:i] + chr((ord(binsig[i]) + 1) % 256) + binsig[i + 1:-1]) #this kind of corruption will sometimes lead to an assert #failure (if the DER format is corrupted) and sometimes lead #to a signature verification failure. try: res = btc.ecdsa_raw_verify(msg, pubkey, checksig, True, rawmsg=True) except: continue assert res == False
def make_valid_nick(i=0): nick_priv = hashlib.sha256(chr(i) * 16).hexdigest() + '01' nick_pubkey = bitcoin.privtopub(nick_priv) nick_pkh_raw = hashlib.sha256(nick_pubkey).digest()[:NICK_HASH_LENGTH] nick_pkh = bitcoin.changebase(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. nick_pkh += 'O' * (NICK_MAX_ENCODED - len(nick_pkh)) #The constructed length will be 1 + 1 + NICK_MAX_ENCODED return JOINMARKET_NICK_HEADER + str(JM_VERSION) + nick_pkh
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)).decode('ascii') 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 set_nick(self): self.nick_pubkey = btc.privtopub(self.nick_priv) self.nick_pkh_raw = btc.bin_sha256( self.nick_pubkey)[:self.nick_hashlen] self.nick_pkh = btc.b58encode(self.nick_pkh_raw) #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 informuser = getattr(self.client, "inform_user_details", None) if callable(informuser): informuser()
def test_spend_p2sh_p2wpkh_multi(setup_segwit, wallet_structure, in_amt, amount, segwit_amt, segwit_ins, o_ins): """Creates a wallet from which non-segwit inputs/ outputs can be created, constructs one or more p2wpkh in p2sh spendable utxos (by paying into the corresponding address) and tests spending them in combination. wallet_structure is in accordance with commontest.make_wallets, see docs there in_amt is the amount to pay into each address into the wallet (non-segwit adds) amount (in satoshis) is how much we will pay to the output address segwit_amt in BTC is the amount we will fund each new segwit address with segwit_ins is a list of input indices (where to place the funding segwit utxos) other_ins is a list of input indices (where to place the funding non-sw utxos) """ wallet = make_wallets(1, wallet_structure, in_amt, walletclass=Wallet)[0]['wallet'] jm_single().bc_interface.sync_wallet(wallet) other_ins = {} ctr = 0 for k, v in wallet.unspent.iteritems(): #only extract as many non-segwit utxos as we need; #doesn't matter which they are if ctr == len(o_ins): break other_ins[k] = (v["value"], wallet.get_key_from_addr(v["address"]), o_ins[ctr]) ctr += 1 ins_sw = {} for i in range(len(segwit_ins)): #build segwit ins from "deterministic-random" keys; #intended to be the same for each run with the same parameters seed = json.dumps( [i, wallet_structure, in_amt, amount, segwit_ins, other_ins]) priv = btc.sha256(seed) + "01" pub = btc.privtopub(priv) #magicbyte is testnet p2sh addr1 = btc.pubkey_to_p2sh_p2wpkh_address(pub, magicbyte=196) print "got address for p2shp2wpkh: " + addr1 txid = jm_single().bc_interface.grab_coins(addr1, segwit_amt) #TODO - int cast, fix? ins_sw[get_utxo_from_txid(txid, addr1)] = (int(segwit_amt * 100000000), priv, segwit_ins[i]) #make_sign_and_push will sanity check the received amount is correct txid = make_sign_and_push(ins_sw, wallet, amount, other_ins) #will always be False if it didn't push. assert txid
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) """ #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, ) # deserialize the commitment revelation try: cr_dict = PoDLE.deserialize_revelation(cr) except PoDLEError as e: reason = repr(e) return reject(reason) 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) try: if not self.wallet.pubkey_has_script(unhexlify(cr_dict['P']), unhexlify(res[0]['script'])): raise EngineError() except EngineError: 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[list(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)