def test_hr_psbt(setup_psbt_wallet):
    bitcoin.select_chain_params("bitcoin")
    for k, v in hr_test_vectors.items():
        print(
            PSBTWalletMixin.human_readable_psbt(
                bitcoin.PartiallySignedTransaction.from_binary(hextobin(v))))
    bitcoin.select_chain_params("bitcoin/regtest")
def setup_sync():
    load_test_config(bs="bitcoin-rpc-no-history")
    # a special case needed for the bitcoin core
    # no history interface: it does not use
    # 'blockchain_source' to distinguish regtest,
    # so it must be set specifically for the test
    # here:
    select_chain_params("bitcoin/regtest")
def test_get_utxo_info():
    load_test_config()
    # this test tests mainnet keys, so temporarily switch network
    select_chain_params("bitcoin")
    jm_single().config.set("BLOCKCHAIN", "network", "mainnet")

    dbci = DummyBlockchainInterface()
    privkey = "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi"
    #to verify use from_wif_privkey and privkey_to_address
    iaddr = "bc1q6tvmnmetj8vfz98vuetpvtuplqtj4uvvwjgxxc"
    fakeutxo = "aa" * 32 + ":08"
    success, fakeutxo_bin = utxostr_to_utxo(fakeutxo)
    assert success
    fake_query_results = [{
        'value': 200000000,
        'script': BTC_P2WPKH.address_to_script(iaddr),
        'utxo': fakeutxo_bin,
        'confirms': 20
    }]
    dbci.insert_fake_query_results(fake_query_results)
    jm_single().bc_interface = dbci
    u, priv = get_utxo_info(fakeutxo + "," + privkey)
    assert u == fakeutxo
    assert priv == privkey
    #invalid format
    with pytest.raises(Exception):
        u, priv = get_utxo_info(fakeutxo + privkey)
    #invalid index
    fu2 = "ab" * 32 + ":-1"
    with pytest.raises(Exception):
        u, priv = get_utxo_info(fu2 + "," + privkey)
    #invalid privkey
    p2 = privkey[:-1] + 'j'
    with pytest.raises(Exception):
        u, priv = get_utxo_info(fakeutxo + "," + p2)

    utxodatas = [(fakeutxo_bin, privkey)]
    retval = validate_utxo_data(utxodatas, False)
    assert retval
    #try to retrieve
    retval = validate_utxo_data(utxodatas, True)
    assert retval[0] == (fakeutxo_bin, 200000000)
    fake_query_results[0]['script'] = hextobin(
        "76a91479b000887626b294a914501a4cd226b58b23598388ac")
    dbci.insert_fake_query_results(fake_query_results)
    #validate should fail for wrong address
    retval = validate_utxo_data(utxodatas, False)
    assert not retval
    #remove fake query result and trigger not found
    dbci.fake_query_results = None
    dbci.setQUSFail(True)
    retval = validate_utxo_data(utxodatas, False)
    assert not retval
    dbci.setQUSFail(False)
    select_chain_params("bitcoin/regtest")
    jm_single().config.set("BLOCKCHAIN", "network", "regtest")
Exemple #4
0
def get_blockchain_interface_instance(_config):
    # todo: refactor joinmarket module to get rid of loops
    # importing here is necessary to avoid import loops
    from jmclient.blockchaininterface import BitcoinCoreInterface, \
        RegtestBitcoinCoreInterface, ElectrumWalletInterface, \
        BitcoinCoreNoHistoryInterface
    source = _config.get("BLOCKCHAIN", "blockchain_source")
    network = get_network()
    testnet = (network == 'testnet' or network == 'signet')

    if source in ('bitcoin-rpc', 'regtest', 'bitcoin-rpc-no-history'):
        rpc_host = _config.get("BLOCKCHAIN", "rpc_host")
        rpc_port = _config.get("BLOCKCHAIN", "rpc_port")
        if rpc_port == '':
            if network == 'mainnet':
                rpc_port = 8332
            elif network == 'regtest':
                rpc_port = 18443
            elif network == 'testnet':
                rpc_port = 18332
            elif network == 'signet':
                rpc_port = 38332
            else:
                raise ValueError('wrong network configured: ' + network)
        rpc_user, rpc_password = get_bitcoin_rpc_credentials(_config)
        rpc_wallet_file = _config.get("BLOCKCHAIN", "rpc_wallet_file")
        rpc = JsonRpc(rpc_host, rpc_port, rpc_user, rpc_password)
        if source == 'bitcoin-rpc': #pragma: no cover
            bc_interface = BitcoinCoreInterface(rpc, network,
                rpc_wallet_file)
            if testnet:
                btc.select_chain_params("bitcoin/testnet")
            else:
                btc.select_chain_params("bitcoin")
        elif source == 'regtest':
            bc_interface = RegtestBitcoinCoreInterface(rpc,
                rpc_wallet_file)
            btc.select_chain_params("bitcoin/regtest")
        elif source == "bitcoin-rpc-no-history":
            bc_interface = BitcoinCoreNoHistoryInterface(rpc, network,
                rpc_wallet_file)
            if testnet or network == "regtest":
                # in tests, for bech32 regtest addresses, for bc-no-history,
                # this will have to be reset manually:
                btc.select_chain_params("bitcoin/testnet")
            else:
                btc.select_chain_params("bitcoin")
        else:
            assert 0
    elif source == 'electrum':
        bc_interface = ElectrumWalletInterface(testnet)
    elif source == 'no-blockchain':
        bc_interface = None
    else:
        raise ValueError("Invalid blockchain source")
    return bc_interface
Exemple #5
0
def setup_wallet(request):
    load_test_config()
    btc.select_chain_params("bitcoin/regtest")
    #see note in cryptoengine.py:
    cryptoengine.BTC_P2WPKH.VBYTE = 100
    jm_single().bc_interface.tick_forward_chain_interval = 2
    def teardown():
        if os.path.exists(test_create_wallet_filename):
            os.remove(test_create_wallet_filename)
    request.addfinalizer(teardown)
Exemple #6
0
def test_get_utxo_info():
    load_test_config()
    # this test tests mainnet keys, so temporarily switch network
    select_chain_params("bitcoin")
    jm_single().config.set("BLOCKCHAIN", "network", "mainnet")

    dbci = DummyBlockchainInterface()
    privkey = "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi"
    #to verify use from_wif_privkey and privkey_to_address
    iaddr = "1LDsjB43N2NAQ1Vbc2xyHca4iBBciN8iwC"
    fakeutxo = "aa" * 32 + ":08"

    fake_query_results = [{
        'value': 200000000,
        'address': iaddr,
        'utxo': fakeutxo,
        'confirms': 20
    }]
    dbci.insert_fake_query_results(fake_query_results)
    jm_single().bc_interface = dbci
    u, priv = get_utxo_info(fakeutxo + "," + privkey)
    assert u == fakeutxo
    assert priv == privkey
    #invalid format
    with pytest.raises(Exception) as e_info:
        u, priv = get_utxo_info(fakeutxo + privkey)
    #invalid index
    fu2 = "ab" * 32 + ":-1"
    with pytest.raises(Exception) as e_info:
        u, priv = get_utxo_info(fu2 + "," + privkey)
    #invalid privkey
    p2 = privkey[:-1] + 'j'
    with pytest.raises(Exception) as e_info:
        u, priv = get_utxo_info(fakeutxo + "," + p2)

    utxodatas = [(fakeutxo, privkey)]
    retval = validate_utxo_data(utxodatas, False)
    assert retval
    #try to retrieve
    retval = validate_utxo_data(utxodatas, True)
    assert retval[0] == (fakeutxo, 200000000)
    fake_query_results[0]['address'] = "fakeaddress"
    dbci.insert_fake_query_results(fake_query_results)
    #validate should fail for wrong address
    retval = validate_utxo_data(utxodatas, False)
    assert not retval
    #remove fake query result and trigger not found
    dbci.fake_query_results = None
    dbci.setQUSFail(True)
    retval = validate_utxo_data(utxodatas, False)
    assert not retval
    dbci.setQUSFail(False)
    select_chain_params("bitcoin/regtest")
    jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
Exemple #7
0
def test_signmessage(seed, hdpath, walletcls, message, sig, addr):
    load_test_config()
    jm_single().config.set('BLOCKCHAIN', 'network', 'mainnet')
    select_chain_params("bitcoin/mainnet")
    storage = VolatileStorage()
    walletcls.initialize(
        storage, get_network(), entropy=seed, max_mixdepth=3)
    wallet = walletcls(storage)
    s, m, a = wallet_signmessage(wallet, hdpath, message,
                                        out_str=False)
    assert (s, m, a) == (sig, message, addr)
    jm_single().config.set("BLOCKCHAIN", "network", "testnet")
    select_chain_params("bitcoin/regtest")
Exemple #8
0
def test_sign_external_psbt(setup_psbt_wallet, walletseed, xpub,
                            spktype_wallet, spktype_destn, partial, psbt):
    bitcoin.select_chain_params("bitcoin")
    wallet_cls = SegwitWallet if spktype_wallet == "p2wpkh" else SegwitLegacyWallet
    wallet = create_volatile_wallet(walletseed, wallet_cls=wallet_cls)

    # if we want to actually sign, our wallet has to recognize the fake utxos
    # as being in the wallet, so we inject them:
    class DummyUtxoManager(object):
        _utxo = {0: {}}

        def add_utxo(self, utxo, path, value, height):
            self._utxo[0][utxo] = (path, value, height)

    wallet._index_cache[0][0] = 1000
    wallet._utxos = DummyUtxoManager()
    p0, p1, p2 = (wallet.get_path(0, 0, i) for i in range(3))
    if not partial:
        wallet._utxos.add_utxo(
            utxostr_to_utxo(
                "0b7468282e0c5fd82ee6b006ed5057199a7b3a1c4422e58ddfb35c5e269684bb:0"
            ), p0, 10000, 1)
    wallet._utxos.add_utxo(
        utxostr_to_utxo(
            "442d551b314efd28f49c89e06b9495efd0fbc8c64fd06f398a73ad47c6447df9:0"
        ), p1, 10000, 1)
    wallet._utxos.add_utxo(
        utxostr_to_utxo(
            "4bda19e193781fb899511a052717fa38cd4d341a4f6dc29b6cb10c854c29e76b:0"
        ), p2, 10000, 1)
    signresult_and_signedpsbt, err = wallet.sign_psbt(base64.b64decode(
        psbt.encode("ascii")),
                                                      with_sign_result=True)
    assert not err
    signresult, signedpsbt = signresult_and_signedpsbt
    if partial:
        assert not signresult.is_final
        assert signresult.num_inputs_signed == 2
        assert signresult.num_inputs_final == 2
    else:
        assert signresult.is_final
        assert signresult.num_inputs_signed == 3
        assert signresult.num_inputs_final == 3
    print(PSBTWalletMixin.human_readable_psbt(signedpsbt))
    bitcoin.select_chain_params("bitcoin/regtest")
Exemple #9
0
def test_create_wallet(setup_wallet, password, wallet_cls):
    wallet_name = test_create_wallet_filename
    password = password.encode("utf-8")
    # test mainnet (we are not transacting)
    btc.select_chain_params("bitcoin")
    wallet = create_wallet(wallet_name, password, 4, wallet_cls)
    mnemonic = wallet.get_mnemonic_words()[0]
    firstkey = wallet.get_key_from_addr(wallet.get_addr(0,0,0))
    print("Created mnemonic, firstkey: ", mnemonic, firstkey)
    wallet.close()
    # ensure that the wallet file created is openable with the password,
    # and has the parameters that were claimed on creation:
    new_wallet = open_test_wallet_maybe(wallet_name, "", 4,
                        password=password, ask_for_password=False)
    assert new_wallet.get_mnemonic_words()[0] == mnemonic
    assert new_wallet.get_key_from_addr(
        new_wallet.get_addr(0,0,0)) == firstkey
    os.remove(wallet_name)
    btc.select_chain_params("bitcoin/regtest")
def test_b58_valid_addresses():
    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:
        addr, pubkey, prop_dict = a
        if not prop_dict["isPrivkey"]:
            if prop_dict["isTestnet"]:
                jm_single().config.set("BLOCKCHAIN", "network", "testnet")
                btc.select_chain_params("bitcoin/testnet")
            else:
                jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
                btc.select_chain_params("bitcoin")
            #if using pytest -s ; sanity check to see what's actually being tested
            res, message = validate_address(addr)
            assert res == True, "Incorrectly failed to validate address: " + addr + " with message: " + message
    jm_single().config.set("BLOCKCHAIN", "network", "testnet")
    btc.select_chain_params("bitcoin/regtest")
def test_valid_bech32_addresses():
    valids = ["BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
    "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
    # TODO these are valid bech32 addresses but rejected by bitcointx
    # because they are not witness version 0; add others.
    #"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
    #"BC1SW50QA3JX3S",
    #"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
    "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy"]
    for va in valids:
        if va.lower()[:2] == "bc":
            jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
            btc.select_chain_params("bitcoin")
        else:
            jm_single().config.set("BLOCKCHAIN", "network", "testnet")
            btc.select_chain_params("bitcoin/testnet")
        res, message = validate_address(va)
        assert res == True, "Incorrect failed to validate address: " + va + " with message: " + message
    jm_single().config.set("BLOCKCHAIN", "network", "testnet")
    btc.select_chain_params("bitcoin/regtest")
Exemple #12
0
def setup_env_nodeps(monkeypatch):
    monkeypatch.setattr(jmclient.configure,
                        'get_blockchain_interface_instance',
                        lambda x: DummyBlockchainInterface())
    btc.select_chain_params("bitcoin/regtest")
    load_test_config()
Exemple #13
0
def setup_wallet():
    load_test_config()
    btc.select_chain_params("bitcoin/regtest")
    #see note in cryptoengine.py:
    cryptoengine.BTC_P2WPKH.VBYTE = 100
    jm_single().bc_interface.tick_forward_chain_interval = 2
def address_valid_somewhere(addr):
    for x in ["bitcoin", "bitcoin/testnet", "bitcoin/regtest"]:
        btc.select_chain_params(x)
        if validate_address(addr)[0]:
            return True
    return False