def _tx_pay_btc(txhex, privk, burn_price, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS):
        tx = virtualchain.btc_tx_deserialize(txhex)

        # up the burn amount 
        tx['outs'][3]['script'] = virtualchain.btc_make_payment_script(burn_addr)
        tx['outs'][3]['value'] = burn_price

        tx['outs'][4]['value'] -= burn_price

        # re-sign 
        for i in tx['ins']:
            i['script'] = ''

        txhex = virtualchain.btc_tx_serialize(tx)
        _addr = virtualchain.address_reencode(virtualchain.get_privkey_address(privk))
        txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(privk, testlib.get_utxos(_addr), txhex)

        # re-sign the last output with the payment key
        tx_signed = virtualchain.btc_tx_deserialize(txhex_signed)
        tx_signed['ins'][-1]['script'] = ''
        txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(testlib.get_default_payment_wallet().privkey, testlib.get_utxos(testlib.get_default_payment_wallet().addr), virtualchain.btc_tx_serialize(tx_signed))
        
        print txhex_signed

        res = testlib.broadcast_transaction(txhex_signed)
        assert 'error' not in res
        return res
Exemple #2
0
def convert_funds_to_segwit(payment_key, tx_fee):
    # convert payment key to bech32
    addr = virtualchain.address_reencode(
        virtualchain.get_privkey_address(payment_key))
    pubk = virtualchain.lib.ecdsalib.ecdsa_private_key(
        payment_key, compressed=True).public_key().to_hex()
    addrhash = virtualchain.lib.hashing.bin_hash160(
        pubk.decode('hex')).encode('hex')
    segwit_addr = virtualchain.segwit_addr_encode(addrhash.decode('hex'),
                                                  hrp='bcrt')

    # fund the segwit address, and then use the same payment key to send the transaction
    fund_inputs = testlib.get_utxos(addr)
    fund_outputs = [
        {
            "script": '0014' + addrhash,
            "value": sum(inp['value'] for inp in fund_inputs) - tx_fee
        },
    ]
    fund_prev_outputs = [{
        'out_script': inp['out_script'],
        'value': inp['value']
    } for inp in fund_inputs]
    fund_serialized_tx = testlib.serialize_tx(fund_inputs, fund_outputs)
    fund_signed_tx = virtualchain.tx_sign_all_unsigned_inputs(
        payment_key, fund_prev_outputs, fund_serialized_tx)

    print fund_signed_tx

    res = testlib.broadcast_transaction(fund_signed_tx)
    assert 'error' not in res, res

    res.update({'utxos': fund_outputs})
    return res
def scenario(wallets, **kw):

    global reveal_block
    global preorder_block

    res = testlib.blockstack_namespace_preorder("test",
                                                wallets[1].addr,
                                                wallets[0].privkey,
                                                tx_only=True,
                                                expect_fail=True)
    ns_preorder_txhex = res['transaction']

    # change the burn address
    ns_preorder_tx = virtualchain.btc_tx_deserialize(ns_preorder_txhex)
    ns_preorder_tx['outs'][2]['script'] = virtualchain.btc_make_payment_script(
        wallets[2].addr)

    for i in ns_preorder_tx['ins']:
        i['script'] = ''

    utxos = testlib.get_utxos(wallets[0].addr)
    ns_preorder_txhex = virtualchain.btc_tx_serialize(ns_preorder_tx)
    ns_preorder_txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        wallets[0].privkey, utxos, ns_preorder_txhex)

    print ns_preorder_txhex_signed

    res = testlib.broadcast_transaction(ns_preorder_txhex_signed)
    if 'error' in res:
        print res
        return False

    print res

    testlib.next_block(**kw)

    num_ops = virtualchain.lib.indexer.StateEngine.get_block_statistics(
        testlib.get_current_block(**kw))
    if num_ops['num_parsed_ops'] != 1:
        print 'processed ops: {}'.format(num_ops)
        return False

    # try again, but use the right burn address
    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    preorder_block = testlib.get_current_block(**kw) + 1
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    reveal_block = testlib.get_current_block(**kw) + 1

    testlib.next_block(**kw)
Exemple #4
0
def replace_output_with_bech32(txhex, output_index, payment_key, addrhash):
    print 'txhex: {}'.format(txhex)
    tx = virtualchain.btc_tx_deserialize(txhex)

    new_tx = {
        'locktime': 0,
        'version': 1,
        'ins': tx['ins'],
        'outs': tx['outs'],
    }

    for inp in new_tx['ins']:
        inp['script'] = ''
        inp['witness_script'] = ''

    new_tx['outs'][output_index] = {
        'script': '0014' + addrhash,
        'value': tx['outs'][output_index]['value']
    }

    unsigned_txhex = virtualchain.btc_tx_serialize(new_tx)
    print 'unsigned: {}'.format(unsigned_txhex)

    addr = virtualchain.address_reencode(
        virtualchain.get_privkey_address(payment_key))
    utxos = testlib.get_utxos(addr)
    prev_outputs = [{
        'out_script': inp['out_script'],
        'value': inp['value']
    } for inp in utxos]

    signed_txhex = virtualchain.tx_sign_all_unsigned_inputs(
        payment_key, prev_outputs, unsigned_txhex)

    print 'signed: {}'.format(signed_txhex)

    res = testlib.broadcast_transaction(signed_txhex)
    assert 'error' not in res

    return res
    def _tx_pay_btc(txhex, privk, btc_paid, burn_addr):
        tx = virtualchain.btc_tx_deserialize(txhex)

        # up the burn amount 
        btc_price = blockstack.lib.scripts.price_name('baz', namespace, testlib.get_current_block(**kw))
        tx['outs'][2]['script'] = virtualchain.btc_make_payment_script(burn_addr)
        tx['outs'][2]['value'] = btc_paid

        tx['outs'][1]['value'] -= btc_paid

        # re-sign 
        for i in tx['ins']:
            i['script'] = ''

        txhex = virtualchain.btc_tx_serialize(tx)
        _addr = virtualchain.address_reencode(virtualchain.get_privkey_address(privk))
        txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(privk, testlib.get_utxos(_addr), txhex)
        
        print txhex_signed
        res = testlib.broadcast_transaction(txhex_signed)
        assert 'error' not in res, res['error']
        return res
Exemple #6
0
def scenario(wallets, **kw):
    global pk, pk2

    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    # pay for a name in a v1 namespace with Stacks
    addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk))
    addr2 = virtualchain.address_reencode(
        virtualchain.get_privkey_address(pk2))

    # calculate the cost of doing so
    namespace = testlib.get_state_engine().get_namespace('test')
    stacks_price = blockstack.lib.scripts.price_name_stacks(
        'baz', namespace, testlib.get_current_block(**kw))
    btc_price = blockstack.lib.scripts.price_name(
        'baz', namespace, testlib.get_current_block(**kw))

    print ''
    print 'price of {} in Stacks is {}'.format('baz.test', stacks_price)
    print 'price of {} in BTC is {}'.format('baz.test', btc_price)
    print ''

    testlib.blockstack_send_tokens(addr, "STACKS", stacks_price,
                                   wallets[0].privkey)
    testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price * 2,
                                   wallets[0].privkey)
    testlib.send_funds(wallets[0].privkey, 10 * btc_price, addr)
    testlib.send_funds(wallets[0].privkey, 10 * btc_price, addr2)
    testlib.next_block(**kw)

    # preorder/register using Stacks
    testlib.blockstack_name_preorder("baz.test",
                                     wallets[2].privkey,
                                     addr2,
                                     price={
                                         'units': 'STACKS',
                                         'amount': stacks_price
                                     })
    testlib.blockstack_name_preorder("goo.test",
                                     wallets[2].privkey,
                                     addr2,
                                     price={
                                         'units': 'STACKS',
                                         'amount': stacks_price
                                     })
    testlib.blockstack_name_preorder("nop.test",
                                     wallets[2].privkey,
                                     addr2,
                                     price={
                                         'units': 'STACKS',
                                         'amount': stacks_price
                                     })
    testlib.next_block(**kw)

    testlib.blockstack_name_register("baz.test", wallets[2].privkey, addr2)
    testlib.blockstack_name_register("goo.test", wallets[2].privkey, addr2)
    testlib.blockstack_name_register("nop.test", wallets[2].privkey, addr2)
    testlib.next_block(**kw)

    balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS']

    # pay with both Stacks and Bitcoin
    # should favor Stacks payment over Bitcoin payment if we pay enough stacks.
    # Stacks should have been burned, as well as BTC.
    res = testlib.blockstack_name_renew('baz.test',
                                        pk2,
                                        price={
                                            'units': 'STACKS',
                                            'amount': stacks_price
                                        },
                                        tx_only=True,
                                        expect_success=True)
    txhex = res['transaction']
    tx = virtualchain.btc_tx_deserialize(txhex)

    # up the burn amount
    btc_price = blockstack.lib.scripts.price_name(
        'baz', namespace, testlib.get_current_block(**kw))
    tx['outs'][3]['script'] = virtualchain.btc_make_payment_script(
        blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS)
    tx['outs'][3]['value'] = btc_price

    tx['outs'][4]['value'] -= btc_price

    # re-sign
    for i in tx['ins']:
        i['script'] = ''

    txhex = virtualchain.btc_tx_serialize(tx)
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        pk2, testlib.get_utxos(addr2), txhex)

    # re-sign the last output with the payment key
    tx_signed = virtualchain.btc_tx_deserialize(txhex_signed)
    tx_signed['ins'][-1]['script'] = ''
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        testlib.get_default_payment_wallet().privkey,
        testlib.get_utxos(testlib.get_default_payment_wallet().addr),
        virtualchain.btc_tx_serialize(tx_signed))

    print txhex_signed

    res = testlib.broadcast_transaction(txhex_signed)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    # should have paid in Stacks
    balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS']
    if balance_after != balance_before - stacks_price:
        print 'baz.test cost {}'.format(balance_before - balance_after)
        return False

    balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS']

    # try to renew a name where we pay not enough stacks, but enough bitcoin.
    # should be rejected.
    res = testlib.blockstack_name_renew('goo.test',
                                        pk2,
                                        price={
                                            'units': 'STACKS',
                                            'amount': stacks_price - 1
                                        },
                                        tx_only=True)
    txhex = res['transaction']
    tx = virtualchain.btc_tx_deserialize(txhex)

    # up the burn amount to the name price
    btc_price = blockstack.lib.scripts.price_name(
        'goo', namespace, testlib.get_current_block(**kw))
    tx['outs'][3]['script'] = virtualchain.btc_make_payment_script(
        blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS)
    tx['outs'][3]['value'] = btc_price

    tx['outs'][4]['value'] -= btc_price

    # re-sign
    for i in tx['ins']:
        i['script'] = ''

    txhex = virtualchain.btc_tx_serialize(tx)
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        pk2, testlib.get_utxos(addr2), txhex)

    # re-sign the last output with the payment key
    tx_signed = virtualchain.btc_tx_deserialize(txhex_signed)
    tx_signed['ins'][-1]['script'] = ''
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        testlib.get_default_payment_wallet().privkey,
        testlib.get_utxos(testlib.get_default_payment_wallet().addr),
        virtualchain.btc_tx_serialize(tx_signed))

    print txhex_signed

    res = testlib.broadcast_transaction(txhex_signed)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    # should NOT have paid in Stacks
    balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS']
    if balance_after != balance_before:
        print 'goo.test paid {}'.format(balance_before - balance_after)
        return False

    balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS']

    # underpay in both Stacks and Bitcoin.
    # only bitcoin will be burned; transaction will not be processed
    res = testlib.blockstack_name_renew('nop.test',
                                        pk2,
                                        price={
                                            'units': 'STACKS',
                                            'amount': stacks_price - 1
                                        },
                                        tx_only=True)
    txhex = res['transaction']
    tx = virtualchain.btc_tx_deserialize(txhex)

    # up the burn amount to the name price
    btc_price = blockstack.lib.scripts.price_name(
        'goo', namespace, testlib.get_current_block(**kw))
    tx['outs'][3]['script'] = virtualchain.btc_make_payment_script(
        blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS)
    tx['outs'][3]['value'] = btc_price - 1

    tx['outs'][4]['value'] -= btc_price + 1

    # re-sign
    for i in tx['ins']:
        i['script'] = ''

    txhex = virtualchain.btc_tx_serialize(tx)
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        pk2, testlib.get_utxos(addr2), txhex)

    # re-sign the last output with the payment key
    tx_signed = virtualchain.btc_tx_deserialize(txhex_signed)
    tx_signed['ins'][-1]['script'] = ''
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        testlib.get_default_payment_wallet().privkey,
        testlib.get_utxos(testlib.get_default_payment_wallet().addr),
        virtualchain.btc_tx_serialize(tx_signed))

    print txhex_signed

    res = testlib.broadcast_transaction(txhex_signed)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)
    testlib.expect_snv_fail_at('nop.test', testlib.get_current_block(**kw))

    balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS']
    if balance_after != balance_before:
        print 'paid {} for nop.test'.format(balance_before - balance_after)
        return False
def scenario(wallets, **kw):

    # pass 100 stacks around in a circle.
    new_keys = [wallets[0].privkey] + [
        virtualchain.lib.ecdsalib.ecdsa_private_key().to_hex()
        for i in range(0, 4)
    ]
    for k in range(0, 4):
        for j in range(0, len(new_keys)):
            i = j

            new_addr = virtualchain.get_privkey_address(
                new_keys[(i + 1) % len(new_keys)])
            cur_addr = virtualchain.get_privkey_address(
                new_keys[i % len(new_keys)])

            initial_new_balance_info = json.loads(
                testlib.nodejs_cli('balance', new_addr))
            initial_cur_balance_info = json.loads(
                testlib.nodejs_cli('balance', cur_addr))

            print '\n initial new balance info: {} \n'.format(
                initial_new_balance_info)

            if 'STACKS' not in initial_new_balance_info:
                initial_new_balance_info['STACKS'] = 0

            if i > 0:
                testlib.send_funds(wallets[0].privkey, 500000, cur_addr)

            testlib.send_funds(wallets[0].privkey, 500000, new_addr)

            testlib.blockstack_send_tokens(new_addr,
                                           'STACKS',
                                           100,
                                           new_keys[i % len(new_keys)],
                                           safety_checks=False)

            # consolidate
            utxos = testlib.get_utxos(wallets[0].addr)
            if len(utxos) > 1:
                balance = testlib.get_balance(wallets[0].addr)
                testlib.send_funds(wallets[0].privkey,
                                   balance - 5500,
                                   wallets[0].addr,
                                   change=False)

            utxos = testlib.get_utxos(new_addr)
            if len(utxos) > 1:
                balance = testlib.get_balance(new_addr)
                testlib.send_funds(new_keys[(i + 1) % len(new_keys)],
                                   balance - 5500,
                                   new_addr,
                                   change=False)

        testlib.next_block(**kw)

        for j in range(0, len(new_keys)):
            i = j

            new_addr = virtualchain.get_privkey_address(
                new_keys[(i + 1) % len(new_keys)])
            cur_addr = virtualchain.get_privkey_address(
                new_keys[i % len(new_keys)])

            if j == len(new_keys) - 1:
                if (i + 1) % len(new_keys) != 0:
                    # last address should have 100 stacks, unless new_addr is wallets[0]
                    balance_info = json.loads(
                        testlib.nodejs_cli('balance', new_addr))
                    assert int(balance_info['STACKS']) == 100

            else:
                if i % len(new_keys) != 0:
                    # every other address, except wallets[0], should have 0 balance
                    balance_info = json.loads(
                        testlib.nodejs_cli('balance', cur_addr))
                    assert int(balance_info['STACKS']) == 0

        # consolidate
        for j in range(0, len(new_keys)):
            cur_addr = virtualchain.get_privkey_address(
                new_keys[i % len(new_keys)])
            utxos = testlib.get_utxos(cur_addr)
            if len(utxos) > 1:
                balance = testlib.get_balance(cur_addr)
                testlib.send_funds(new_keys[i % len(new_keys)],
                                   balance - 5500,
                                   cur_addr,
                                   change=False)

        testlib.next_block(**kw)

    # each *new* address has 4 history items -- four spends, four receives
    for new_key in new_keys[1:]:
        new_addr = virtualchain.get_privkey_address(new_key)
        history = requests.get(
            'http://localhost:16268/v1/accounts/{}/history?page=0'.format(
                new_addr)).json()

        # should have gotten 4 debits for 100, and 4 credits for 100
        assert int(history[0]['credit_value']) == 400, history
        assert int(history[0]['debit_value']) == 400, history

        assert len(history) == 8, history
Exemple #8
0
def check_utxo_consumption(name_or_ns, payment_wallet, owner_wallet,
                           data_wallet, operations, recipient_address, **kw):

    global small_unspents

    wallet = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", payment_wallet.privkey, owner_wallet.privkey,
        data_wallet.privkey)
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    # estimate the fee for the operation sequence
    fees = testlib.blockstack_cli_price(name_or_ns,
                                        "0123456789abcdef",
                                        recipient_address=recipient_address,
                                        operations=operations)
    if 'error' in fees:
        return fees

    print "without UTXOs:"
    print simplejson.dumps(fees, indent=4, sort_keys=True)

    # make a few small UTXOs for the payment address
    # count up the number of UTXOs that exist for this payment address
    payment_utxos = testlib.get_utxos(payment_wallet.addr)
    expected_utxo_count = len(payment_utxos)
    for i in xrange(0, 1):
        senders = wallets
        for sender in senders:
            if sender.privkey == payment_wallet.privkey:
                continue

            res = testlib.send_funds(sender.privkey, 10000,
                                     payment_wallet.addr)
            if 'error' in res:
                print simplejson.dumps(res, indent=4, sort_keys=True)
                return res

            expected_utxo_count += 1
            small_unspents.append(res['transaction_hash'])

        testlib.next_block(**kw)

    # estimate the fee with all the UTXOs
    fees_utxos = testlib.blockstack_cli_price(
        name_or_ns,
        "0123456789abcdef",
        recipient_address=recipient_address,
        operations=operations)
    if 'error' in fees_utxos:
        return fees_utxos

    print "with UTXOs:"
    print simplejson.dumps(fees_utxos, indent=4, sort_keys=True)

    # all our operations should have similar fees, regardless of the UTXO set
    for tx_fee_key in ['{}_tx_fee'.format(op) for op in operations]:
        fee_diff = abs(fees[tx_fee_key]['satoshis'] -
                       fees_utxos[tx_fee_key]['satoshis'])
        if fee_diff > 5500:
            print 'tx fees for {} disagree by {}'.format(tx_fee_key, fee_diff)
            return {'error': 'No appreciable fee change'}

    return {'status': True, 'expected_utxo_count': expected_utxo_count}
Exemple #9
0
def scenario(wallets, **kw):

    global debug, consensus, small_unspents

    res = check_utxo_consumption(
        "test", wallets[0], wallets[1], wallets[2],
        ['namespace_preorder', 'namespace_reveal', 'namespace_ready'],
        wallets[1].addr, **kw)
    if 'error' in res:
        return False

    expected_utxo_count = res['expected_utxo_count']

    # do the preorder
    resp = testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                                 wallets[0].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    testlib.next_block(**kw)

    # verify that all the small UTXOs are NOT consumed
    bitcoind = testlib.connect_bitcoind()
    bitcoind.ping()

    txdata = bitcoind.getrawtransaction(resp['transaction_hash'], 1)
    if len(txdata['vin']) != 1:
        print simplejson.dumps(txdata, indent=4)
        print "wrong number of inputs: {} != 1".format(len(txdata['vin']))
        return False

    if spent_small_transaction(resp['transaction_hash']):
        return False

    # finish ordering the namespace
    resp = testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)

    resp = testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)

    res = check_utxo_consumption(
        "foo.test", wallets[2], wallets[3], wallets[4],
        ['preorder', 'register', 'update', 'transfer'], wallets[4].addr, **kw)
    if 'error' in res:
        return False

    expected_utxo_count = res['expected_utxo_count']

    resp = testlib.blockstack_name_preorder("foo.test", wallets[2].privkey,
                                            wallets[3].addr)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)

    # verify that all the small UTXOs are NOT consumed
    bitcoind = testlib.connect_bitcoind()
    bitcoind.ping()

    txdata = bitcoind.getrawtransaction(resp['transaction_hash'], 1)
    if len(txdata['vin']) != 1:
        print simplejson.dumps(txdata, indent=4)
        print "wrong number of inputs: {} != {}".format(
            len(txdata['vin']), expected_utxo_count)
        return False

    # proceed to register
    resp = testlib.blockstack_name_register("foo.test", wallets[2].privkey,
                                            wallets[3].addr)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)

    # verify that all the UTXOs are consumed
    bitcoind = testlib.connect_bitcoind()
    bitcoind.ping()

    txdata = bitcoind.getrawtransaction(resp['transaction_hash'], 1)
    if len(txdata['vin']) != 1:
        print simplejson.dumps(txdata, indent=4)
        print "wrong number of inputs: {} != {}".format(
            len(txdata['vin']), expected_utxo_count)
        return False

    # make a few small UTXOs for the preorder payment addr
    for i in xrange(0, 3):
        res = testlib.send_funds(wallets[1].privkey, 10000,
                                 testlib.get_default_payment_wallet().addr)
        if 'error' in res:
            print simplejson.dumps(res, indent=4, sort_keys=True)
            return False

        testlib.next_block(**kw)
        small_unspents.append(res['transaction_hash'])

    utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr)
    assert len(utxos) > 3

    resp = testlib.blockstack_name_update("foo.test", "11" * 20,
                                          wallets[3].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    if spent_small_transaction(resp['transaction_hash']):
        return False

    consensus = testlib.get_consensus_at(testlib.get_current_block(**kw), **kw)
    testlib.next_block(**kw)

    # inspect the transaction: only 3 UTXOs should have been consumed (2 owner UTXOs and 1 payment UTXO)
    txdata = testlib.connect_bitcoind().getrawtransaction(
        resp['transaction_hash'], 1)
    if len(txdata['vin']) != 3:
        print simplejson.dumps(txdata, indent=4)
        print "too many inputs"
        return False

    # make a few more small UTXOs for the preorder payment addr
    for i in xrange(0, 3):
        res = testlib.send_funds(wallets[1].privkey, 10000,
                                 testlib.get_default_payment_wallet().addr)
        if 'error' in res:
            print simplejson.dumps(res, indent=4, sort_keys=True)
            return False

        testlib.next_block(**kw)
        small_unspents.append(res['transaction_hash'])

    utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr)
    assert len(utxos) > 3

    resp = testlib.blockstack_name_transfer("foo.test", wallets[4].addr, True,
                                            wallets[3].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    # inspect the transaction: only 2 UTXOs should have been consumed (1 owner UTXO and 1 payment UTXO)
    txdata = testlib.connect_bitcoind().getrawtransaction(
        resp['transaction_hash'], 1)
    if len(txdata['vin']) != 2:
        print simplejson.dumps(txdata, indent=4)
        print "too many inputs"
        return False

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)

    # make a few more small UTXOs for the preorder payment addr
    for i in xrange(0, 3):
        res = testlib.send_funds(wallets[1].privkey, 10000,
                                 testlib.get_default_payment_wallet().addr)
        if 'error' in res:
            print simplejson.dumps(res, indent=4, sort_keys=True)
            return False

        testlib.next_block(**kw)
        small_unspents.append(res['transaction_hash'])

    utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr)
    assert len(utxos) > 3

    resp = testlib.blockstack_name_renew("foo.test", wallets[4].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    # inspect the transaction: only 3 UTXOs should have been consumed (2 owner UTXO and 1 payment UTXO)
    # NOTE: produces two UTXOs: an "owner" utxo and the change for the owner address
    txdata = testlib.connect_bitcoind().getrawtransaction(
        resp['transaction_hash'], 1)
    if len(txdata['vin']) != 3:
        print simplejson.dumps(txdata, indent=4)
        print "too many inputs"
        return False

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)

    # make a few more small UTXOs for the preorder payment addr
    for i in xrange(0, 3):
        res = testlib.send_funds(wallets[1].privkey, 10000,
                                 testlib.get_default_payment_wallet().addr)
        if 'error' in res:
            print simplejson.dumps(res, indent=4, sort_keys=True)
            return False

        testlib.next_block(**kw)
        small_unspents.append(res['transaction_hash'])

    utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr)
    assert len(utxos) > 3

    resp = testlib.blockstack_name_revoke("foo.test", wallets[4].privkey)
    if debug or 'error' in resp:
        print simplejson.dumps(resp, indent=4)

    # inspect the transaction: only 3 UTXOs should have been consumed (2 owner UTXO and 1 payment UTXO)
    txdata = testlib.connect_bitcoind().getrawtransaction(
        resp['transaction_hash'], 1)
    if len(txdata['vin']) != 3:
        print simplejson.dumps(txdata, indent=4)
        print "too many inputs"
        return False

    if spent_small_transaction(resp['transaction_hash']):
        return False

    testlib.next_block(**kw)
    '''
def scenario(wallets, **kw):
    segwit_addr_1 = get_segwit_address(wallets[1].privkey)
    segwit_addr_1_tb = get_segwit_address(wallets[1].privkey, hrp='tb')
    segwit_addr_0_tb = get_segwit_address(wallets[0].privkey, hrp='tb')

    print segwit_addr_0_tb
    print segwit_addr_1_tb

    pubk = virtualchain.lib.ecdsalib.ecdsa_private_key(
        wallets[1].privkey, compressed=True).public_key().to_hex()
    addrhash = virtualchain.lib.hashing.bin_hash160(
        pubk.decode('hex')).encode('hex')

    a = 'tb1pzjpqjwmz5d5e9qkey6vphmtkvh5rsn9225xsgg79'
    namespace_preorder_name_hash = blockstack.lib.hashing.hash_name(
        'test', virtualchain.make_payment_script(wallets[0].addr), a)
    print 'hash of {} + {} + {} = {}'.format(
        'test', virtualchain.make_payment_script(wallets[0].addr), a,
        namespace_preorder_name_hash)

    resp = testlib.blockstack_namespace_preorder("test",
                                                 wallets[1].addr,
                                                 wallets[0].privkey,
                                                 tx_only=True)
    tx = virtualchain.btc_tx_deserialize(resp['transaction'])

    new_tx = {
        'locktime': 0,
        'version': 1,
        'ins': tx['ins'],
        'outs': tx['outs'],
    }

    for inp in new_tx['ins']:
        inp['script'] = ''
        inp['witness_script'] = ''

    print 'script before: {}'.format(tx['outs'][0]['script'])

    patched_script = virtualchain.make_data_script(
        'id*'.encode('hex') + namespace_preorder_name_hash +
        tx['outs'][0]['script'].decode('hex')[25:].encode('hex'))

    print 'script after : {}'.format(patched_script)

    new_tx['outs'][0] = {'script': patched_script, 'value': 0}

    unsigned_txhex = virtualchain.btc_tx_serialize(new_tx)
    print 'unsigned: {}'.format(unsigned_txhex)

    addr = virtualchain.address_reencode(
        virtualchain.get_privkey_address(wallets[0].privkey))
    utxos = testlib.get_utxos(addr)
    prev_outputs = [{
        'out_script': inp['out_script'],
        'value': inp['value']
    } for inp in utxos]

    signed_txhex = virtualchain.tx_sign_all_unsigned_inputs(
        wallets[0].privkey, prev_outputs, unsigned_txhex)

    print 'signed: {}'.format(signed_txhex)

    res = testlib.broadcast_transaction(signed_txhex)
    assert 'error' not in res

    testlib.next_block(**kw)

    # should fail
    resp = testlib.blockstack_namespace_reveal(
        "test",
        wallets[1].addr,
        52595,
        250,
        4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        10,
        10,
        wallets[0].privkey,
        tx_only=True)
    resp = replace_output_with_bech32(resp['transaction'], 1,
                                      wallets[0].privkey, addrhash)

    testlib.next_block(**kw)
def scenario(wallets, **kw):
    global pk

    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    # pay for a name in a v1 namespace with Stacks
    addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk))

    # calculate the cost of doing so
    namespace = testlib.get_state_engine().get_namespace('test')
    stacks_price = blockstack.lib.scripts.price_name_stacks(
        'foo', namespace, testlib.get_current_block(**kw))
    btc_price = blockstack.lib.scripts.price_name(
        'foo', namespace, testlib.get_current_block(**kw))

    print ''
    print 'price of {} in Stacks is {}'.format('foo.test', stacks_price)
    print ''

    testlib.blockstack_send_tokens(addr, "STACKS", stacks_price * 4,
                                   wallets[0].privkey)
    testlib.send_funds(wallets[0].privkey, btc_price * 10,
                       addr)  # fund with enough bitcoin
    testlib.next_block(**kw)

    # preorder/register using Stacks---Stacks should still be used since that's what the transaction indicates
    testlib.blockstack_name_preorder("foo.test",
                                     pk,
                                     wallets[3].addr,
                                     price={
                                         'units': 'STACKS',
                                         'amount': stacks_price
                                     })
    testlib.next_block(**kw)

    testlib.send_funds(wallets[0].privkey, btc_price * 10, addr)
    testlib.blockstack_name_register("foo.test", pk, wallets[3].addr)
    testlib.next_block(**kw)

    # preorder/register using Bitcoin--Stacks should NOT be used since that's what the transaction indicates
    testlib.blockstack_name_preorder("bar.test",
                                     pk,
                                     wallets[3].addr,
                                     price={
                                         'units': 'BTC',
                                         'amount': btc_price
                                     })
    testlib.next_block(**kw)

    testlib.blockstack_name_register('bar.test', pk, wallets[3].addr)
    testlib.next_block(**kw)

    balance_before = testlib.get_addr_balances(addr)[addr]['STACKS']

    # pay with Stacks and Bitcoin.  Preorder should succeed, and register should also succeed since we're paying enough stacks.  Underpay bitcoin
    res = testlib.blockstack_name_preorder('baz.test',
                                           pk,
                                           wallets[3].addr,
                                           price={
                                               'units': 'STACKS',
                                               'amount': stacks_price
                                           },
                                           tx_only=True,
                                           expect_success=True)
    txhex = res['transaction']
    tx = virtualchain.btc_tx_deserialize(txhex)

    # up the burn amount
    btc_price = blockstack.lib.scripts.price_name(
        'baz', namespace, testlib.get_current_block(**kw))
    tx['outs'][2]['script'] = virtualchain.btc_make_payment_script(
        blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS)
    tx['outs'][2]['value'] = btc_price - 1

    tx['outs'][1]['value'] -= btc_price - 1

    # re-sign
    for i in tx['ins']:
        i['script'] = ''

    txhex = virtualchain.btc_tx_serialize(tx)
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        pk, testlib.get_utxos(addr), txhex)

    print txhex_signed

    res = testlib.broadcast_transaction(txhex_signed)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    # should have paid in Stacks
    balance_after = testlib.get_addr_balances(addr)[addr]['STACKS']
    if balance_after != balance_before - stacks_price:
        print 'baz.test cost {}'.format(balance_before - balance_after)
        return False

    # should succeed, since we paid enough stacks (Bitcoin is not considered)
    testlib.blockstack_name_register('baz.test', pk, wallets[3].addr)
    testlib.next_block(**kw)

    balance_before = testlib.get_addr_balances(addr)[addr]['STACKS']

    # register a name where we pay not enough stacks, but enough bitcoin.  preorder should succeed, but register should fail since we tried to use stacks
    res = testlib.blockstack_name_preorder('goo.test',
                                           pk,
                                           wallets[3].addr,
                                           price={
                                               'units': 'STACKS',
                                               'amount': stacks_price - 1
                                           },
                                           tx_only=True,
                                           expect_success=True)
    txhex = res['transaction']
    tx = virtualchain.btc_tx_deserialize(txhex)

    # up the burn amount to the name price
    btc_price = blockstack.lib.scripts.price_name(
        'goo', namespace, testlib.get_current_block(**kw))
    tx['outs'][2]['script'] = virtualchain.btc_make_payment_script(
        blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS)
    tx['outs'][2]['value'] = btc_price

    tx['outs'][1]['value'] -= btc_price

    # re-sign
    for i in tx['ins']:
        i['script'] = ''

    txhex = virtualchain.btc_tx_serialize(tx)
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        pk, testlib.get_utxos(addr), txhex)

    print txhex_signed

    res = testlib.broadcast_transaction(txhex_signed)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    # should have paid in Stacks
    balance_after = testlib.get_addr_balances(addr)[addr]['STACKS']
    if balance_after != balance_before - stacks_price + 1:
        print 'goo.test paid {}'.format(balance_before - balance_after)
        return False

    # should fail, since we tried to pay in stacks and didn't pay enough
    testlib.blockstack_name_register('goo.test', pk, wallets[3].addr)
    testlib.next_block(**kw)
    testlib.expect_snv_fail_at('goo.test', testlib.get_current_block(**kw))

    if testlib.get_state_engine().get_name('goo.test') is not None:
        print 'registered goo.test'
        return False

    balance_before = testlib.get_addr_balances(addr)[addr]['STACKS']

    # underpay in both Stacks and Bitcoin.
    # both stacks and bitcoin will be burned.
    # preorder should succeed, but register should fail.
    res = testlib.blockstack_name_preorder('nop.test',
                                           pk,
                                           wallets[3].addr,
                                           price={
                                               'units': 'STACKS',
                                               'amount': stacks_price - 1
                                           },
                                           safety_checks=False,
                                           tx_only=True,
                                           expect_success=True)
    txhex = res['transaction']
    tx = virtualchain.btc_tx_deserialize(txhex)

    # up the burn amount to the name price, but just under
    btc_price = blockstack.lib.scripts.price_name(
        'nop', namespace, testlib.get_current_block(**kw))
    tx['outs'][2]['script'] = virtualchain.btc_make_payment_script(
        blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS)
    tx['outs'][2]['value'] = btc_price - 1

    tx['outs'][1]['value'] -= btc_price - 1

    # re-sign
    for i in tx['ins']:
        i['script'] = ''

    txhex = virtualchain.btc_tx_serialize(tx)
    txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(
        pk, testlib.get_utxos(addr), txhex)

    print txhex_signed

    res = testlib.broadcast_transaction(txhex_signed)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    # should fail, since we didn't pay enough stacks and tried to pay in stacks
    res = testlib.blockstack_name_register('nop.test', pk, wallets[3].addr)
    testlib.next_block(**kw)
    testlib.expect_snv_fail_at('nop.test', testlib.get_current_block(**kw))

    # preorder should still have debited
    balance_after = testlib.get_addr_balances(addr)[addr]['STACKS']
    if balance_after != balance_before - stacks_price + 1:
        print 'paid {} for nop.test'.format(balance_before - balance_after)
        return False