Beispiel #1
0
def test_imported_privkey(setup_wallets):
    for n in ["mainnet", "testnet"]:
        privkey = "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb401"
        jm_single().config.set("BLOCKCHAIN", "network", n)
        password = "******"
        password_key = bitcoin.bin_dbl_sha256(password)
        wifprivkey = bitcoin.wif_compressed_privkey(privkey, get_p2pk_vbyte())
        #mainnet is "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi"
        #to verify use from_wif_privkey and privkey_to_address
        if n == "mainnet":
            iaddr = "1LDsjB43N2NAQ1Vbc2xyHca4iBBciN8iwC"
        else:
            iaddr = "mzjq2E92B3oRB7yDKbwM7XnPaAnKfRERw2"
        privkey_bin = bitcoin.from_wif_privkey(
            wifprivkey, vbyte=get_p2pk_vbyte()).decode('hex')[:-1]
        encrypted_privkey = encryptData(password_key, privkey_bin)
        encrypted_privkey_bad = encryptData(password_key, privkey_bin[:6])
        walletdir = "wallets"
        testwalletname = "test" + n
        pathtowallet = os.path.join(walletdir, testwalletname)
        seed = bitcoin.sha256("\xaa" * 64)[:32]
        encrypted_seed = encryptData(password_key, seed.decode('hex'))
        timestamp = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
        for ep in [encrypted_privkey, encrypted_privkey_bad]:
            walletfilejson = {
                'creator':
                'joinmarket project',
                'creation_time':
                timestamp,
                'encrypted_seed':
                encrypted_seed.encode('hex'),
                'network':
                n,
                'index_cache': [[0, 0]] * 5,
                'imported_keys': [{
                    'encrypted_privkey': ep.encode('hex'),
                    'mixdepth': 0
                }]
            }
            walletfile = json.dumps(walletfilejson)
            if not os.path.exists(walletdir):
                os.makedirs(walletdir)
            with open(pathtowallet, "wb") as f:
                f.write(walletfile)
            if ep == encrypted_privkey_bad:
                with pytest.raises(Exception) as e_info:
                    Wallet(testwalletname, password, 5, 6, False, False)
                continue
            newwallet = Wallet(testwalletname, password, 5, 6, False, False)
            assert newwallet.seed == seed
            #test accessing the key from the addr
            assert newwallet.get_key_from_addr(
                iaddr) == bitcoin.from_wif_privkey(wifprivkey,
                                                   vbyte=get_p2pk_vbyte())
            if n == "testnet":
                jm_single().bc_interface.sync_wallet(newwallet)
    load_program_config()
Beispiel #2
0
def cli_receive(filename):
    wif_privkey = raw_input("Enter private key in WIF compressed format: ")
    try:
        privkey = btc.from_wif_privkey(wif_privkey, vbyte=get_p2pk_vbyte())
    except:
        print("Could not parse WIF privkey, quitting.")
        return
    amount = raw_input("Enter amount of utxo being spent, in satoshis: ")
    valid_coinjoins = scan_for_coinjoins(privkey, int(amount), filename)
    if not valid_coinjoins:
        print("Found no valid coinjoins")
        return
    for vc in valid_coinjoins:
        addr, priv, tx = vc
        print("Found signable coinjoin with destination address: ", addr)
        #TODO find a more sensible file naming
        fn = btc.txhash(tx) + ".txt"
        with open(fn, "wb") as f:
            f.write("SNICKER output file for receiver\n"
                    "================================\n")
            f.write("The serialized transaction in hex:\n")
            f.write(tx + "\n")
            f.write("YOUR DESTINATION: " + addr + "\n")
            f.write("PRIVATE KEY FOR THIS DESTINATION ADDRESS:\n")
            f.write(
                btc.wif_compressed_privkey(priv, vbyte=get_p2pk_vbyte()) +
                "\n")
            f.write("The decoded transaction:\n")
            f.write(pformat(btc.deserialize(tx)) + "\n")
        print("The partially signed transaction and the private key for your "
              "output are stored in the file: " + fn)
        print(
            "Pass the transaction hex to `signrawtransaction` in Bitcoin Core "
            "or similar if you wish to broadcast the transaction.")
def get_utxo_info(upriv):
    """Verify that the input string parses correctly as (utxo, priv)
    and return that.
    """
    try:
        u, priv = upriv.split(',')
        u = u.strip()
        priv = priv.strip()
        txid, n = u.split(':')
        assert len(txid) == 64
        assert len(n) in range(1, 4)
        n = int(n)
        assert n in range(256)
    except:
        #not sending data to stdout in case privkey info
        jmprint("Failed to parse utxo information for utxo", "error")
        raise
    try:
        hexpriv = btc.from_wif_privkey(priv, vbyte=get_p2pk_vbyte())
    except:
        jmprint(
            "failed to parse privkey, make sure it's WIF compressed format.",
            "error")
        raise
    return u, priv
Beispiel #4
0
def sign(utxo, priv, destaddrs, segwit=True):
    """Sign a tx sending the amount amt, from utxo utxo,
    equally to each of addresses in list destaddrs,
    after fees; the purpose is to create a large
    number of utxos. If segwit=True the (single) utxo is assumed to
    be of type segwit p2sh/p2wpkh.
    """
    results = validate_utxo_data([(utxo, priv)], retrieve=True, segwit=segwit)
    if not results:
        return False
    assert results[0][0] == utxo
    amt = results[0][1]
    ins = [utxo]
    # TODO extend to other utxo types
    txtype = 'p2sh-p2wpkh' if segwit else 'p2pkh'
    estfee = estimate_tx_fee(1, len(destaddrs), txtype=txtype)
    outs = []
    share = int((amt - estfee) / len(destaddrs))
    fee = amt - share * len(destaddrs)
    assert fee >= estfee
    log.info("Using fee: " + str(fee))
    for i, addr in enumerate(destaddrs):
        outs.append({'address': addr, 'value': share})
    unsigned_tx = btc.mktx(ins, outs)
    amtforsign = amt if segwit else None
    return btc.sign(unsigned_tx,
                    0,
                    btc.from_wif_privkey(priv, vbyte=get_p2pk_vbyte()),
                    amount=amtforsign)
Beispiel #5
0
def validate_utxo_data(utxo_datas, retrieve=False, segwit=False):
    """For each txid: N, 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:
        jmprint('validating this utxo: ' + str(u), "info")
        hexpriv = btc.from_wif_privkey(priv, vbyte=get_p2pk_vbyte())
        if segwit:
            addr = btc.pubkey_to_p2sh_p2wpkh_address(
                btc.privkey_to_pubkey(hexpriv), get_p2sh_vbyte())
        else:
            addr = btc.privkey_to_address(hexpriv, magicbyte=get_p2pk_vbyte())
        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: " + str(u), "error")
            return False
        if res[0]['address'] != addr:
            jmprint("privkey corresponds to the wrong address for utxo: " + str(u), "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
 def generate_single_podle_sig(u, priv, i):
     """Make a podle entry for key priv at index i, using a dummy utxo value.
     This calls the underlying 'raw' code based on the class PoDLE, not the
     library 'generate_podle' which intelligently searches and updates commitments.
     """
     #Convert priv to hex
     hexpriv = btc.from_wif_privkey(priv, vbyte=get_p2pk_vbyte())
     podle = PoDLE(u, hexpriv)
     r = podle.generate_podle(i)
     return (r['P'], r['P2'], r['sig'], r['e'], r['commit'])
def test_wif_privkeys_invalid():
    #first try to create wif privkey from key of wrong length
    bad_privs = [b'\x01\x02' * 17]  #some silly private key but > 33 bytes

    #next try to create wif with correct length but wrong compression byte
    bad_privs.append(b'\x07' * 32 + b'\x02')

    for priv in bad_privs:
        with pytest.raises(Exception) as e_info:
            fake_wif = btc.wif_compressed_privkey(
                binascii.hexlify(priv).decode('ascii'))

    #Create a wif with wrong length
    bad_wif1 = btc.bin_to_b58check(b'\x01\x02' * 34, b'\x80')
    #Create a wif with wrong compression byte
    bad_wif2 = btc.bin_to_b58check(b'\x07' * 33, b'\x80')
    for bw in [bad_wif1, bad_wif2]:
        with pytest.raises(Exception) as e_info:
            fake_priv = btc.from_wif_privkey(bw)

    #Some invalid b58 from bitcoin repo;
    #none of these are valid as any kind of key or address
    with open(os.path.join(testdir, "base58_keys_invalid.json"), "r") as f:
        json_data = f.read()
    invalid_key_list = json.loads(json_data)
    for k in invalid_key_list:
        bad_key = k[0]
        for netval in ["mainnet", "testnet"]:
            #if using pytest -s ; sanity check to see what's actually being tested
            print('testing this key: ' + bad_key)
            #should throw exception
            with pytest.raises(Exception) as e_info:
                from_wif_key = btc.from_wif_privkey(
                    bad_key, btc.get_version_byte(bad_key))
                #in case the b58 check encoding is valid, we should
                #also check if the leading version byte is in the
                #expected set, and throw an error if not.
                if chr(btc.get_version_byte(bad_key)) not in b'\x80\xef':
                    raise Exception("Invalid version byte")
Beispiel #8
0
def test_wif_privkeys_valid():
    with open(os.path.join(testdir, "base58_keys_valid.json"), "r") as f:
        json_data = f.read()
    valid_keys_list = json.loads(json_data)
    for a in valid_keys_list:
        key, hex_key, prop_dict = a
        if prop_dict["isPrivkey"]:
            netval = "testnet" if prop_dict["isTestnet"] else "mainnet"
            print 'testing this key: ' + key
            assert chr(btc.get_version_byte(
                key)) in '\x80\xef', "not valid network byte"
            comp = prop_dict["isCompressed"]
            from_wif_key = btc.from_wif_privkey(
                key, compressed=comp, vbyte=btc.get_version_byte(key) - 128)
            expected_key = hex_key
            if comp: expected_key += '01'
            assert from_wif_key == expected_key, "Incorrect key decoding: " + \
                   str(from_wif_key) + ", should be: " + str(expected_key)
Beispiel #9
0
    print('hexseed = ' + hexseed)
    words = mn_encode(hexseed)
    print('Wallet recovery seed\n\n' + ' '.join(words) + '\n')
elif method == 'importprivkey':
    print('WARNING: This imported key will not be recoverable with your 12 ' +
          'word mnemonic seed. Make sure you have backups.')
    print('WARNING: Handling of raw ECDSA bitcoin private keys can lead to '
          'non-intuitive behaviour and loss of funds.\n  Recommended instead '
          'is to use the \'sweep\' feature of sendpayment.py ')
    privkeys = raw_input('Enter private key(s) to import: ')
    privkeys = privkeys.split(',') if ',' in privkeys else privkeys.split()
    # TODO read also one key for each line
    for privkey in privkeys:
        # TODO is there any point in only accepting wif format? check what
        # other wallets do
        privkey_bin = btc.from_wif_privkey(privkey,
                                        vbyte=get_p2pk_vbyte()).decode('hex')[:-1]
        encrypted_privkey = encryptData(wallet.password_key, privkey_bin)
        if 'imported_keys' not in wallet.walletdata:
            wallet.walletdata['imported_keys'] = []
        wallet.walletdata['imported_keys'].append(
            {'encrypted_privkey': encrypted_privkey.encode('hex'),
             'mixdepth': options.mixdepth})
    if wallet.walletdata['imported_keys']:
        fd = open(wallet.path, 'w')
        fd.write(json.dumps(wallet.walletdata))
        fd.close()
        print('Private key(s) successfully imported')
elif method == 'dumpprivkey':
    if options.hd_path.startswith('m/0/'):
        m, forchange, k = [int(y) for y in options.hd_path[4:].split('/')]
        key = wallet.get_key(m, forchange, k)