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
示例#4
0
 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
示例#6
0
    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)