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")
Ejemplo n.º 2
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")
def test_on_sig(createcmtdata, dummyaddr, signmethod, schedule):
    #plan: create a new transaction with known inputs and dummy outputs;
    #then, create a signature with various inputs, pass in in b64 to on_sig.
    #in order for it to verify, the DummyBlockchainInterface will have to
    #return the right values in query_utxo_set

    #create 2 privkey + utxos that are to be ours
    privs = [x * 32 + "\x01" for x in [chr(y) for y in range(1, 6)]]
    utxos = [str(x) * 64 + ":1" for x in range(5)]
    fake_query_results = [{
        'value':
        200000000,
        'utxo':
        utxos[x],
        'address':
        bitcoin.privkey_to_address(privs[x], False, magicbyte=0x6f),
        'script':
        bitcoin.mk_pubkey_script(
            bitcoin.privkey_to_address(privs[x], False, magicbyte=0x6f)),
        'confirms':
        20
    } for x in range(5)]

    dbci = DummyBlockchainInterface()
    dbci.insert_fake_query_results(fake_query_results)
    jm_single().bc_interface = dbci
    #make a transaction with all the fake results above, and some outputs
    outs = [{
        'value': 100000000,
        'address': dummyaddr
    }, {
        'value': 899990000,
        'address': dummyaddr
    }]
    tx = bitcoin.mktx(utxos, outs)

    de_tx = bitcoin.deserialize(tx)
    #prepare the Taker with the right intermediate data
    taker = get_taker(schedule=schedule, sign_method=signmethod)
    taker.nonrespondants = ["cp1", "cp2", "cp3"]
    taker.latest_tx = de_tx
    #my inputs are the first 2 utxos
    taker.input_utxos = {
        utxos[0]: {
            'address': bitcoin.privkey_to_address(privs[0],
                                                  False,
                                                  magicbyte=0x6f),
            'value': 200000000
        },
        utxos[1]: {
            'address': bitcoin.privkey_to_address(privs[1],
                                                  False,
                                                  magicbyte=0x6f),
            'value': 200000000
        }
    }
    taker.utxos = {
        None: utxos[:2],
        "cp1": [utxos[2]],
        "cp2": [utxos[3]],
        "cp3": [utxos[4]]
    }
    for i in range(2):
        # placeholders required for my inputs
        taker.latest_tx['ins'][i]['script'] = 'deadbeef'
    #to prepare for my signing, need to mark cjaddr:
    taker.my_cj_addr = dummyaddr
    #make signatures for the last 3 fake utxos, considered as "not ours":
    tx3 = bitcoin.sign(tx, 2, privs[2])
    sig3 = b64encode(
        bitcoin.deserialize(tx3)['ins'][2]['script'].decode('hex'))
    taker.on_sig("cp1", sig3)
    tx4 = bitcoin.sign(tx, 3, privs[3])
    sig4 = b64encode(
        bitcoin.deserialize(tx4)['ins'][3]['script'].decode('hex'))
    taker.on_sig("cp2", sig4)
    tx5 = bitcoin.sign(tx, 4, privs[4])
    #Before completing with the final signature, which will trigger our own
    #signing, try with an injected failure of query utxo set, which should
    #prevent this signature being accepted.
    dbci.setQUSFail(True)
    sig5 = b64encode(
        bitcoin.deserialize(tx5)['ins'][4]['script'].decode('hex'))
    taker.on_sig("cp3", sig5)
    #allow it to succeed, and try again
    dbci.setQUSFail(False)
    #this should succeed and trigger the we-sign code
    taker.on_sig("cp3", sig5)
def test_on_sig(setup_taker, dummyaddr, schedule):
    #plan: create a new transaction with known inputs and dummy outputs;
    #then, create a signature with various inputs, pass in in b64 to on_sig.
    #in order for it to verify, the DummyBlockchainInterface will have to 
    #return the right values in query_utxo_set
    utxos = [(struct.pack(b"B", x) * 32, 1) for x in range(5)]
    #create 2 privkey + utxos that are to be ours
    privs = [x*32 + b"\x01" for x in [struct.pack(b'B', y) for y in range(1,6)]]
    scripts = [BTC_P2PKH.key_to_script(privs[x]) for x in range(5)]
    addrs = [BTC_P2PKH.privkey_to_address(privs[x]) for x in range(5)]
    fake_query_results = [{'value': 200000000, 'utxo': utxos[x], 'address': addrs[x],
                           'script': scripts[x], 'confirms': 20} for x in range(5)]

    dbci = DummyBlockchainInterface()
    dbci.insert_fake_query_results(fake_query_results)
    jm_single().bc_interface = dbci
    #make a transaction with all the fake results above, and some outputs
    outs = [{'value': 100000000, 'address': dummyaddr},
            {'value': 899990000, 'address': dummyaddr}]
    tx = bitcoin.mktx(utxos, outs)
    # since tx will be updated as it is signed, unlike in real life
    # (where maker signing operation doesn't happen here), we'll create
    # a second copy without the signatures:
    tx2 = bitcoin.mktx(utxos, outs)

    #prepare the Taker with the right intermediate data
    taker = get_taker(schedule=schedule)
    taker.nonrespondants=["cp1", "cp2", "cp3"]
    taker.latest_tx = tx
    #my inputs are the first 2 utxos
    taker.input_utxos = {utxos[0]:
                        {'address': addrs[0],
                         'script': scripts[0],
                         'value': 200000000},
                        utxos[1]:
                        {'address': addrs[1],
                         'script': scripts[1],
                         'value': 200000000}}    
    taker.utxos = {None: utxos[:2], "cp1": [utxos[2]], "cp2": [utxos[3]], "cp3":[utxos[4]]}
    for i in range(2):
        # placeholders required for my inputs
        taker.latest_tx.vin[i].scriptSig = bitcoin.CScript(hextobin('deadbeef'))
        tx2.vin[i].scriptSig = bitcoin.CScript(hextobin('deadbeef'))
    #to prepare for my signing, need to mark cjaddr:
    taker.my_cj_addr = dummyaddr
    #make signatures for the last 3 fake utxos, considered as "not ours":
    sig, msg = bitcoin.sign(tx2, 2, privs[2])
    assert sig, "Failed to sign: " + msg
    sig3 = b64encode(tx2.vin[2].scriptSig)
    taker.on_sig("cp1", sig3)
    #try sending the same sig again; should be ignored
    taker.on_sig("cp1", sig3)
    sig, msg = bitcoin.sign(tx2, 3, privs[3])
    assert sig, "Failed to sign: " + msg
    sig4 = b64encode(tx2.vin[3].scriptSig)
    #try sending junk instead of cp2's correct sig
    assert not taker.on_sig("cp2", str("junk")), "incorrectly accepted junk signature"
    taker.on_sig("cp2", sig4)
    sig, msg = bitcoin.sign(tx2, 4, privs[4])
    assert sig, "Failed to sign: " + msg
    #Before completing with the final signature, which will trigger our own
    #signing, try with an injected failure of query utxo set, which should
    #prevent this signature being accepted.
    dbci.setQUSFail(True)
    sig5 = b64encode(tx2.vin[4].scriptSig)
    assert not taker.on_sig("cp3", sig5), "incorrectly accepted sig5"
    #allow it to succeed, and try again
    dbci.setQUSFail(False)
    #this should succeed and trigger the we-sign code
    taker.on_sig("cp3", sig5)