Beispiel #1
0
def create_wallet_for_sync(wallet_file, password, wallet_structure, a):
    #Prepare a testnet wallet file for this wallet
    password_key = bitcoin.bin_dbl_sha256(password)
    #We need a distinct seed for each run so as not to step over each other;
    #make it through a deterministic hash
    seedh = bitcoin.sha256("".join([str(x) for x in a]))[:32]
    encrypted_seed = encryptData(password_key, seedh.decode('hex'))
    timestamp = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
    walletfilejson = {
        'creator': 'joinmarket project',
        'creation_time': timestamp,
        'encrypted_seed': encrypted_seed.encode('hex'),
        'network': get_network()
    }
    walletfile = json.dumps(walletfilejson)
    if not os.path.exists('wallets'):
        os.makedirs('wallets')
    with open(os.path.join('wallets', wallet_file), "wb") as f:
        f.write(walletfile)
    #The call to Wallet() in make_wallets should now find the file
    #and read from it:
    return make_wallets(1, [wallet_structure],
                        fixed_seeds=[wallet_file],
                        test_wallet=True,
                        passwords=[password])[0]['wallet']
Beispiel #2
0
def generate_single_podle_sig(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.
    """
    dummy_utxo = bitcoin.sha256(priv) + ":3"
    podle = PoDLE(dummy_utxo, binascii.hexlify(priv).decode('ascii'))
    r = podle.generate_podle(i)
    return (r['P'], r['P2'], r['sig'], r['e'], r['commit'])
Beispiel #3
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()
def test_commitment_retries(setup_podle):
    """Assumes no external commitments available.
    Generate pretend priv/utxo pairs and check that they can be used
    taker_utxo_retries times.
    """
    allowed = jm_single().config.getint("POLICY", "taker_utxo_retries")
    #make some pretend commitments
    dummy_priv_utxo_pairs = [(bitcoin.sha256(os.urandom(10)),
           bitcoin.sha256(os.urandom(10))+":0") for _ in range(10)]
    #test a single commitment request of all 10
    for x in dummy_priv_utxo_pairs:
        p = generate_podle([x], allowed)
        assert p
    #At this point slot 0 has been taken by all 10.
    for i in range(allowed-1):
        p = generate_podle(dummy_priv_utxo_pairs[:1], allowed)
        assert p
    p = generate_podle(dummy_priv_utxo_pairs[:1], allowed)
    assert p is None
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 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 create_wallet_for_sync(wallet_structure, a, **kwargs):
    #We need a distinct seed for each run so as not to step over each other;
    #make it through a deterministic hash
    seedh = btc.sha256("".join([str(x) for x in a]))[:32]
    return make_wallets(1, [wallet_structure], fixed_seeds=[seedh],
                        **kwargs)[0]['wallet']
Beispiel #8
0
def test_external_commitments(setup_podle):
    """Add this generated commitment to the external list
    {txid:N:{'P':pubkey, 'reveal':{1:{'P2':P2,'s':s,'e':e}, 2:{..},..}}}
    Note we do this *after* the sendpayment test so that the external
    commitments will not erroneously used (they are fake).
    """
    #ensure the file exists even if empty
    update_commitments()
    ecs = {}
    tries = jm_single().config.getint("POLICY", "taker_utxo_retries")
    for i in range(10):
        priv = os.urandom(32)
        dummy_utxo = bitcoin.sha256(priv) + ":2"
        ecs[dummy_utxo] = {}
        ecs[dummy_utxo]['reveal'] = {}
        for j in range(tries):
            P, P2, s, e, commit = generate_single_podle_sig(priv, j)
            if 'P' not in ecs[dummy_utxo]:
                ecs[dummy_utxo]['P'] = P
            ecs[dummy_utxo]['reveal'][j] = {'P2': P2, 's': s, 'e': e}
    add_external_commitments(ecs)
    used, external = get_podle_commitments()
    for u in external:
        assert external[u]['P'] == ecs[u]['P']
        for i in range(tries):
            for x in ['P2', 's', 'e']:
                assert external[u]['reveal'][str(
                    i)][x] == ecs[u]['reveal'][i][x]

    #add a dummy used commitment, then try again
    update_commitments(commitment="ab" * 32)
    ecs = {}
    known_commits = []
    known_utxos = []
    tries = 3
    for i in range(1, 6):
        u = binascii.hexlify(struct.pack(b'B', i) * 32).decode('ascii')
        known_utxos.append(u)
        priv = struct.pack(b'B', i) * 32 + b"\x01"
        ecs[u] = {}
        ecs[u]['reveal'] = {}
        for j in range(tries):
            P, P2, s, e, commit = generate_single_podle_sig(priv, j)
            known_commits.append(commit)
            if 'P' not in ecs[u]:
                ecs[u]['P'] = P
            ecs[u]['reveal'][j] = {'P2': P2, 's': s, 'e': e}
    add_external_commitments(ecs)
    #simulate most of those external being already used
    for c in known_commits[:-1]:
        update_commitments(commitment=c)
    #this should find the remaining one utxo and return from it
    assert generate_podle([], max_tries=tries, allow_external=known_utxos)
    #test commitment removal
    to_remove = ecs[binascii.hexlify(struct.pack(b'B', 3) *
                                     32).decode('ascii')]
    update_commitments(external_to_remove={
        binascii.hexlify(struct.pack(b'B', 3) * 32).decode('ascii'):
        to_remove
    })
    #test that an incorrectly formatted file raises
    with open(get_commitment_file(), "rb") as f:
        validjson = json.loads(f.read().decode('utf-8'))
    corruptjson = copy.deepcopy(validjson)
    del corruptjson['used']
    with open(get_commitment_file(), "wb") as f:
        f.write(json.dumps(corruptjson, indent=4).encode('utf-8'))
    with pytest.raises(PoDLEError) as e_info:
        get_podle_commitments()
    #clean up
    with open(get_commitment_file(), "wb") as f:
        f.write(json.dumps(validjson, indent=4).encode('utf-8'))
def test_wallet_create(setup_wallets, includecache, wrongnet, storepwd,
                       extendmd, pwdnumtries):
    walletdir, pathtowallet, testwalletname, wallet = create_default_testnet_wallet(
    )
    assert wallet.get_key(
        4, 1,
        17) == "1289ca322f96673acef83f396a9735840e3ab69f0459cf9bfa8d9985a876534401"
    assert wallet.get_addr(2, 0, 5) == "myWPu9QJWHGE79XAmuKkwKgNk8vsr5evpk"
    jm_single().bc_interface.wallet_synced = True
    assert wallet.get_new_addr(1, 0) == "mi88ZgDGPmarzcsU6S437h9CY9BLmgH5M6"
    assert wallet.get_external_addr(3) == "mvChQuChnXVhqvH67wfMxrodPQ7xccdVJU"
    addr3internal = wallet.get_internal_addr(3)
    assert addr3internal == "mv26o79Bauf2miJMoxoSu1vXmfXnk85YPQ"
    assert wallet.get_key_from_addr(
        addr3internal) == "2a283c9a2168a25509e2fb944939637228c50c8b4fecd9024650316c4584246501"
    dummyaddr = "mvw1NazKDRbeNufFANqpYNAANafsMC2zVU"
    assert not wallet.get_key_from_addr(dummyaddr)
    #Make a new Wallet(), and prepare a testnet wallet file for this wallet

    password = "******"
    password_key = bitcoin.bin_dbl_sha256(password)
    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")
    net = get_network() if not wrongnet else 'mainnnet'
    walletfilejson = {'creator': 'joinmarket project',
                      'creation_time': timestamp,
                      'encrypted_seed': encrypted_seed.encode('hex'),
                      'network': net}
    if includecache:
        mmd = wallet.max_mix_depth if not extendmd else wallet.max_mix_depth + 5
        print("using mmd: " + str(mmd))
        walletfilejson.update({'index_cache': [[0, 0]] * mmd})
    walletfile = json.dumps(walletfilejson)
    if not os.path.exists(walletdir):
        os.makedirs(walletdir)
    with open(pathtowallet, "wb") as f:
        f.write(walletfile)
    if wrongnet:
        with pytest.raises(ValueError) as e_info:
            Wallet(testwalletname,
                   password,
                   5,
                   6,
                   extend_mixdepth=extendmd,
                   storepassword=storepwd)
        return
    from string import ascii_letters
    for i in range(
            pwdnumtries):  #multiple tries to ensure pkcs7 error is triggered
        with pytest.raises(WalletError) as e_info:
            wrongpwd = "".join([random.choice(ascii_letters) for _ in range(20)
                               ])
            Wallet(testwalletname,
                   wrongpwd,
                   5,
                   6,
                   extend_mixdepth=extendmd,
                   storepassword=storepwd)

    with pytest.raises(WalletError) as e_info:
        Wallet(testwalletname,
               None,
               5,
               6,
               extend_mixdepth=extendmd,
               storepassword=storepwd)
    newwallet = Wallet(testwalletname,
                       password,
                       5,
                       6,
                       extend_mixdepth=extendmd,
                       storepassword=storepwd)
    assert newwallet.seed == seed
    #now we have a functional wallet + file, update the cache; first try
    #with failed paths
    oldpath = newwallet.path
    newwallet.path = None
    newwallet.update_cache_index()
    newwallet.path = "fake-path-definitely-doesnt-exist"
    newwallet.update_cache_index()
    #with real path
    newwallet.path = oldpath
    newwallet.index = [[1, 1]] * 5
    newwallet.update_cache_index()

    #ensure we cannot find a mainnet wallet from seed
    seed = "goodbye"
    jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
    with pytest.raises(IOError) as e_info:
        Wallet(seed, 5, 6, False, False)
    load_program_config()
def test_wallet_create(setup_wallets, includecache, wrongnet, storepwd,
                       extendmd, pwdnumtries):
    walletdir, pathtowallet, testwalletname, wallet = create_default_testnet_wallet(
    )
    assert wallet.get_key(
        4, 1,
        17) == "96095d7542e4e832c476b9df7e49ca9e5be61ad3bb8c8a3bdd8e141e2f4caf9101"
    assert wallet.get_addr(2, 0, 5) == "2NBUxbEQrGPKrYCV6d4o7Y4AtJ34Uy6gZZg"
    jm_single().bc_interface.wallet_synced = True
    assert wallet.get_new_addr(1, 0) == "2Mz817RE6zqywgkG2h9cATUoiXwnFSxufk2"
    assert wallet.get_external_addr(3) == "2N3gn65WXEzbLnjk5FLDZPc1pL6ebvZAmoA"
    addr3internal = wallet.get_internal_addr(3)
    assert addr3internal == "2N5NMTYogAyrGhDtWBnVQUp1kgwwFzcf7UM"
    assert wallet.get_key_from_addr(
        addr3internal) == "089a7173314d29f99e02a37e36da517ce41537a317c83284db1f33dda0af0cc201"
    dummyaddr = "mvw1NazKDRbeNufFANqpYNAANafsMC2zVU"
    assert not wallet.get_key_from_addr(dummyaddr)
    #Make a new Wallet(), and prepare a testnet wallet file for this wallet

    password = "******"
    password_key = bitcoin.bin_dbl_sha256(password)
    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")
    net = get_network() if not wrongnet else 'mainnnet'
    walletfilejson = {'creator': 'joinmarket project',
                      'creation_time': timestamp,
                      'encrypted_seed': encrypted_seed.encode('hex'),
                      'network': net}
    if includecache:
        mmd = wallet.max_mix_depth if not extendmd else wallet.max_mix_depth + 5
        print("using mmd: " + str(mmd))
        walletfilejson.update({'index_cache': [[0, 0]] * mmd})
    walletfile = json.dumps(walletfilejson)
    if not os.path.exists(walletdir):
        os.makedirs(walletdir)
    with open(pathtowallet, "wb") as f:
        f.write(walletfile)
    if wrongnet:
        with pytest.raises(ValueError) as e_info:
            SegwitWallet(testwalletname,
                   password,
                   5,
                   6,
                   extend_mixdepth=extendmd,
                   storepassword=storepwd)
        return
    from string import ascii_letters
    for i in range(
            pwdnumtries):  #multiple tries to ensure pkcs7 error is triggered
        with pytest.raises(WalletError) as e_info:
            wrongpwd = "".join([random.choice(ascii_letters) for _ in range(20)
                               ])
            SegwitWallet(testwalletname,
                   wrongpwd,
                   5,
                   6,
                   extend_mixdepth=extendmd,
                   storepassword=storepwd)

    with pytest.raises(WalletError) as e_info:
        SegwitWallet(testwalletname,
               None,
               5,
               6,
               extend_mixdepth=extendmd,
               storepassword=storepwd)
    newwallet = SegwitWallet(testwalletname,
                       password,
                       5,
                       6,
                       extend_mixdepth=extendmd,
                       storepassword=storepwd)
    assert newwallet.seed == wallet.wallet_data_to_seed(seed)
    #now we have a functional wallet + file, update the cache; first try
    #with failed paths
    oldpath = newwallet.path
    newwallet.path = None
    newwallet.update_cache_index()
    newwallet.path = "fake-path-definitely-doesnt-exist"
    newwallet.update_cache_index()
    #with real path
    newwallet.path = oldpath
    newwallet.index = [[1, 1]] * 5
    newwallet.update_cache_index()

    #ensure we cannot find a mainnet wallet from seed
    seed = "goodbye"
    jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
    with pytest.raises(IOError) as e_info:
        Wallet(seed, 5, 6, False, False)
    load_program_config()
Beispiel #11
0
                        balance += addrvalue['value']
                used = (' used' if balance > 0.0 else 'empty')
                balance_depth += balance
                if options.showprivkey:
                    wip_privkey = btc.wif_compressed_privkey(
                    privkey, get_p2pk_vbyte())
                else:
                    wip_privkey = ''
                cus_print(' ' * 13 + '%-35s%s %.8f btc %s' % (
                    addr, used, balance / 1e8, wip_privkey))
        total_balance += balance_depth
        print('for mixdepth=%d balance=%.8fbtc' % (m, balance_depth / 1e8))
    print('total balance = %.8fbtc' % (total_balance / 1e8))
elif method == 'generate' or method == 'recover':
    if method == 'generate':
        seed = btc.sha256(os.urandom(64))[:32]
        words = mn_encode(seed)
        print('Write down this wallet recovery seed\n\n' + ' '.join(words) +
              '\n')
    elif method == 'recover':
        words = raw_input('Input 12 word recovery seed: ')
        words = words.split()  # default for split is 1 or more whitespace chars
        if len(words) != 12:
            print('ERROR: Recovery seed phrase must be exactly 12 words.')
            sys.exit(0)
        seed = mn_decode(words)
        print(seed)
    password = getpass.getpass('Enter wallet encryption passphrase: ')
    password2 = getpass.getpass('Reenter wallet encryption passphrase: ')
    if password != password2:
        print('ERROR. Passwords did not match')