mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
cc38451955
beee49b [tests] Allow stderr to be tested against specified string (John Newbery) e503671 [Tests] Use LIBC_FATAL_STDERR_=1 in tests (John Newbery) c22ce8a [Tests] Write stdout/stderr to datadir instead of temp file. (John Newbery) Pull request description: **Due to a merge conflict, this is now based on #10267. Please review that PR first!** Subset of #12379 now that parts of that PR have been merged. #12362 was only observed when running the functional tests locally because: - by defatul libc logs to `/dev/tty` instead of stderr - the functional tests only check for substring inclusion in stderr when we're expecting bitcoind to fail. This PR tightens our checking of stderr and will cause tests to fail if there is any unexpected message in stderr: - commit *Write stdout/stderr to datadir instead of temp file* writes stderr to a file in the datadir instead of a temporary file. This helps with debugging in the case of failure. - commit *Use LIBC_FATAL_STDERR=1 in tests* ensures that libc failures are logged to stderr instead of the terminal. commit *Assert that bitcoind stdout is empty on shutdown* asserts that stderr is empty on bitcoind shutdown. Tree-SHA512: 21111030e667b3b686f2a7625c2b625ebcfb6998e1cccb4f3932e8b5d21fb514b19a73ac971595d049343430e9a63155986a7f5648cad55b8f36f3c58b1c7048
481 lines
23 KiB
Python
Executable File
481 lines
23 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
"""Test the wallet."""
|
|
from decimal import Decimal
|
|
import time
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
from test_framework.util import (
|
|
assert_array_result,
|
|
assert_equal,
|
|
assert_fee_amount,
|
|
assert_raises_rpc_error,
|
|
connect_nodes_bi,
|
|
count_bytes,
|
|
wait_until,
|
|
)
|
|
|
|
class WalletTest(BitcoinTestFramework):
|
|
def set_test_params(self):
|
|
self.num_nodes = 4
|
|
self.setup_clean_chain = True
|
|
self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)]
|
|
|
|
def setup_network(self):
|
|
self.add_nodes(4, self.extra_args)
|
|
self.start_node(0)
|
|
self.start_node(1)
|
|
self.start_node(2)
|
|
connect_nodes_bi(self.nodes, 0, 1)
|
|
connect_nodes_bi(self.nodes, 1, 2)
|
|
connect_nodes_bi(self.nodes, 0, 2)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
|
|
"""Return curr_balance after asserting the fee was in range"""
|
|
fee = balance_with_fee - curr_balance
|
|
assert_fee_amount(fee, tx_size, fee_per_byte * 1000)
|
|
return curr_balance
|
|
|
|
def run_test(self):
|
|
# Check that there's no UTXO on none of the nodes
|
|
assert_equal(len(self.nodes[0].listunspent()), 0)
|
|
assert_equal(len(self.nodes[1].listunspent()), 0)
|
|
assert_equal(len(self.nodes[2].listunspent()), 0)
|
|
|
|
self.log.info("Mining blocks...")
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
walletinfo = self.nodes[0].getwalletinfo()
|
|
assert_equal(walletinfo['immature_balance'], 500)
|
|
assert_equal(walletinfo['balance'], 0)
|
|
|
|
self.sync_all(self.nodes[0:3])
|
|
self.nodes[1].generate(101)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
assert_equal(self.nodes[0].getbalance(), 500)
|
|
assert_equal(self.nodes[1].getbalance(), 500)
|
|
assert_equal(self.nodes[2].getbalance(), 0)
|
|
|
|
# Check getbalance with different arguments
|
|
assert_equal(self.nodes[0].getbalance("*"), 500)
|
|
assert_equal(self.nodes[0].getbalance("*", 1), 500)
|
|
assert_equal(self.nodes[0].getbalance("*", 1, True), 500)
|
|
assert_equal(self.nodes[0].getbalance(minconf=1), 500)
|
|
|
|
# first argument of getbalance must be excluded or set to "*"
|
|
assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[0].getbalance, "")
|
|
|
|
# Check that only first and second nodes have UTXOs
|
|
utxos = self.nodes[0].listunspent()
|
|
assert_equal(len(utxos), 1)
|
|
assert_equal(len(self.nodes[1].listunspent()), 1)
|
|
assert_equal(len(self.nodes[2].listunspent()), 0)
|
|
|
|
self.log.info("test gettxout")
|
|
confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"]
|
|
# First, outputs that are unspent both in the chain and in the
|
|
# mempool should appear with or without include_mempool
|
|
txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=False)
|
|
assert_equal(txout['value'], 500)
|
|
txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
|
|
assert_equal(txout['value'], 500)
|
|
|
|
# Send 210 DASH from 0 to 2 using sendtoaddress call.
|
|
# Second transaction will be child of first, and will require a fee
|
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 110)
|
|
mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 100)
|
|
|
|
self.log.info("test gettxout (second part)")
|
|
# utxo spent in mempool should be visible if you exclude mempool
|
|
# but invisible if you include mempool
|
|
txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False)
|
|
assert_equal(txout['value'], 500)
|
|
txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True)
|
|
assert txout is None
|
|
# new utxo from mempool should be invisible if you exclude mempool
|
|
# but visible if you include mempool
|
|
txout = self.nodes[0].gettxout(mempool_txid, 0, False)
|
|
assert txout is None
|
|
txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
|
|
txout2 = self.nodes[0].gettxout(mempool_txid, 1, True)
|
|
# note the mempool tx will have randomly assigned indices
|
|
# but 10 will go to node2 and the rest will go to node0
|
|
balance = self.nodes[0].getbalance()
|
|
assert_equal(set([txout1['value'], txout2['value']]), set([100, balance]))
|
|
|
|
walletinfo = self.nodes[0].getwalletinfo()
|
|
assert_equal(walletinfo['immature_balance'], 0)
|
|
|
|
# Have node0 mine a block, thus it will collect its own fee.
|
|
self.nodes[0].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
# Exercise locking of unspent outputs
|
|
unspent_0 = self.nodes[2].listunspent()[0]
|
|
unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
|
|
assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", self.nodes[2].lockunspent, True, [unspent_0])
|
|
self.nodes[2].lockunspent(False, [unspent_0])
|
|
assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])
|
|
assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 200)
|
|
assert_equal([unspent_0], self.nodes[2].listlockunspent())
|
|
self.nodes[2].lockunspent(True, [unspent_0])
|
|
assert_equal(len(self.nodes[2].listlockunspent()), 0)
|
|
assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
|
|
self.nodes[2].lockunspent, False,
|
|
[{"txid": "0000000000000000000000000000000000", "vout": 0}])
|
|
assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
|
|
self.nodes[2].lockunspent, False,
|
|
[{"txid": unspent_0["txid"], "vout": 999}])
|
|
|
|
# An output should be unlocked when spent
|
|
unspent_0 = self.nodes[1].listunspent()[0]
|
|
self.nodes[1].lockunspent(False, [unspent_0])
|
|
tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
|
|
tx = self.nodes[1].fundrawtransaction(tx)['hex']
|
|
tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
|
|
self.nodes[1].sendrawtransaction(tx)
|
|
assert_equal(len(self.nodes[1].listlockunspent()), 0)
|
|
|
|
# Have node1 generate 100 blocks (so node0 can recover the fee)
|
|
self.nodes[1].generate(100)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
# node0 should end up with 1000 DASH in block rewards plus fees, but
|
|
# minus the 210 plus fees sent to node2
|
|
assert_equal(self.nodes[0].getbalance(), 1000 - 210)
|
|
assert_equal(self.nodes[2].getbalance(), 210)
|
|
|
|
# Node0 should have two unspent outputs.
|
|
# Create a couple of transactions to send them to node2, submit them through
|
|
# node1, and make sure both node0 and node2 pick them up properly:
|
|
node0utxos = self.nodes[0].listunspent(1)
|
|
assert_equal(len(node0utxos), 2)
|
|
|
|
fee_per_input = Decimal('0.00001')
|
|
totalfee = 0
|
|
# create both transactions
|
|
txns_to_send = []
|
|
for utxo in node0utxos:
|
|
inputs = []
|
|
outputs = {}
|
|
inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
|
|
outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - fee_per_input
|
|
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
|
txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx))
|
|
totalfee += fee_per_input
|
|
|
|
# Have node 1 (miner) send the transactions
|
|
self.nodes[1].sendrawtransaction(txns_to_send[0]["hex"])
|
|
self.nodes[1].sendrawtransaction(txns_to_send[1]["hex"])
|
|
|
|
# Have node1 mine a block to confirm transactions:
|
|
self.nodes[1].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
assert_equal(self.nodes[0].getbalance(), 0)
|
|
assert_equal(self.nodes[2].getbalance(), 1000 - totalfee)
|
|
|
|
# Verify that a spent output cannot be locked anymore
|
|
spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]}
|
|
assert_raises_rpc_error(-8, "Invalid parameter, expected unspent output", self.nodes[0].lockunspent, False, [spent_0])
|
|
|
|
# Send 100 DASH normal
|
|
address = self.nodes[0].getnewaddress("test")
|
|
fee_per_byte = Decimal('0.00001') / 1000
|
|
self.nodes[2].settxfee(fee_per_byte * 1000)
|
|
txid = self.nodes[2].sendtoaddress(address, 100, "", "", False)
|
|
self.nodes[2].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('900') - totalfee, fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
|
|
assert_equal(self.nodes[0].getbalance(), Decimal('100'))
|
|
|
|
# Send 100 DASH with subtract fee from amount
|
|
txid = self.nodes[2].sendtoaddress(address, 100, "", "", True)
|
|
self.nodes[2].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
node_2_bal -= Decimal('100')
|
|
assert_equal(self.nodes[2].getbalance(), node_2_bal)
|
|
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('200'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
|
|
|
|
# Sendmany 100 DASH
|
|
txid = self.nodes[2].sendmany('', {address: 100}, 0, False, "", [])
|
|
self.nodes[2].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
node_0_bal += Decimal('100')
|
|
node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('100'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
|
|
assert_equal(self.nodes[0].getbalance(), node_0_bal)
|
|
|
|
# Sendmany 100 DASH with subtract fee from amount
|
|
txid = self.nodes[2].sendmany('', {address: 100}, 0, False, "", [address])
|
|
self.nodes[2].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
node_2_bal -= Decimal('100')
|
|
assert_equal(self.nodes[2].getbalance(), node_2_bal)
|
|
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('100'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
|
|
|
|
# Test ResendWalletTransactions:
|
|
# Create a couple of transactions, then start up a fourth
|
|
# node (nodes[3]) and ask nodes[0] to rebroadcast.
|
|
# EXPECT: nodes[3] should have those transactions in its mempool.
|
|
txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
|
|
txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
|
self.sync_mempools(self.nodes[0:2])
|
|
|
|
self.start_node(3)
|
|
connect_nodes_bi(self.nodes, 0, 3)
|
|
self.sync_blocks()
|
|
|
|
relayed = self.nodes[0].resendwallettransactions()
|
|
assert_equal(set(relayed), {txid1, txid2})
|
|
self.sync_mempools()
|
|
|
|
assert(txid1 in self.nodes[3].getrawmempool())
|
|
|
|
# Exercise balance rpcs
|
|
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1)
|
|
assert_equal(self.nodes[0].getunconfirmedbalance(), 1)
|
|
|
|
# check if we can list zero value tx as available coins
|
|
# 1. create raw_tx
|
|
# 2. hex-changed one output to 0.0
|
|
# 3. sign and send
|
|
# 4. check if recipient (node0) can list the zero value tx
|
|
usp = self.nodes[1].listunspent(query_options={'minimumAmount': '499.998'})[0]
|
|
inputs = [{"txid": usp['txid'], "vout": usp['vout']}]
|
|
outputs = {self.nodes[1].getnewaddress(): 499.998, self.nodes[0].getnewaddress(): 11.11}
|
|
|
|
raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") # replace 11.11 with 0.0 (int32)
|
|
signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx)
|
|
decoded_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
|
|
zero_value_txid = decoded_raw_tx['txid']
|
|
self.nodes[1].sendrawtransaction(signed_raw_tx['hex'])
|
|
|
|
self.sync_all()
|
|
self.nodes[1].generate(1) # mine a block
|
|
self.sync_all()
|
|
|
|
unspent_txs = self.nodes[0].listunspent() # zero value tx must be in listunspents output
|
|
found = False
|
|
for uTx in unspent_txs:
|
|
if uTx['txid'] == zero_value_txid:
|
|
found = True
|
|
assert_equal(uTx['amount'], Decimal('0'))
|
|
assert(found)
|
|
|
|
# do some -walletbroadcast tests
|
|
self.stop_nodes()
|
|
self.start_node(0, ["-walletbroadcast=0"])
|
|
self.start_node(1, ["-walletbroadcast=0"])
|
|
self.start_node(2, ["-walletbroadcast=0"])
|
|
connect_nodes_bi(self.nodes, 0, 1)
|
|
connect_nodes_bi(self.nodes, 1, 2)
|
|
connect_nodes_bi(self.nodes, 0, 2)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
|
|
tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
|
|
self.nodes[1].generate(1) # mine a block, tx should not be in there
|
|
self.sync_all(self.nodes[0:3])
|
|
assert_equal(self.nodes[2].getbalance(), node_2_bal) # should not be changed because tx was not broadcasted
|
|
|
|
# now broadcast from another node, mine a block, sync, and check the balance
|
|
self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex'])
|
|
self.nodes[1].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
node_2_bal += 2
|
|
tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
|
|
assert_equal(self.nodes[2].getbalance(), node_2_bal)
|
|
|
|
# create another tx
|
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
|
|
|
|
# restart the nodes with -walletbroadcast=1
|
|
self.stop_nodes()
|
|
self.start_node(0)
|
|
self.start_node(1)
|
|
self.start_node(2)
|
|
connect_nodes_bi(self.nodes, 0, 1)
|
|
connect_nodes_bi(self.nodes, 1, 2)
|
|
connect_nodes_bi(self.nodes, 0, 2)
|
|
self.sync_blocks(self.nodes[0:3])
|
|
|
|
self.nodes[0].generate(1)
|
|
self.sync_blocks(self.nodes[0:3])
|
|
node_2_bal += 2
|
|
|
|
# tx should be added to balance because after restarting the nodes tx should be broadcast
|
|
assert_equal(self.nodes[2].getbalance(), node_2_bal)
|
|
|
|
# send a tx with value in a string (PR#6380 +)
|
|
txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
|
|
tx_obj = self.nodes[0].gettransaction(txid)
|
|
assert_equal(tx_obj['amount'], Decimal('-2'))
|
|
|
|
txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
|
|
tx_obj = self.nodes[0].gettransaction(txid)
|
|
assert_equal(tx_obj['amount'], Decimal('-0.0001'))
|
|
|
|
# check if JSON parser can handle scientific notation in strings
|
|
txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
|
|
tx_obj = self.nodes[0].gettransaction(txid)
|
|
assert_equal(tx_obj['amount'], Decimal('-0.0001'))
|
|
|
|
# This will raise an exception because the amount type is wrong
|
|
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")
|
|
|
|
# This will raise an exception since generate does not accept a string
|
|
assert_raises_rpc_error(-1, "not an integer", self.nodes[0].generate, "2")
|
|
|
|
# Import address and private key to check correct behavior of spendable unspents
|
|
# 1. Send some coins to generate new UTXO
|
|
address_to_import = self.nodes[2].getnewaddress()
|
|
txid = self.nodes[0].sendtoaddress(address_to_import, 1)
|
|
self.nodes[0].generate(1)
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
# 2. Import address from node2 to node1
|
|
self.nodes[1].importaddress(address_to_import)
|
|
|
|
# 3. Validate that the imported address is watch-only on node1
|
|
assert(self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"])
|
|
|
|
# 4. Check that the unspents after import are not spendable
|
|
assert_array_result(self.nodes[1].listunspent(),
|
|
{"address": address_to_import},
|
|
{"spendable": False})
|
|
|
|
# 5. Import private key of the previously imported address on node1
|
|
priv_key = self.nodes[2].dumpprivkey(address_to_import)
|
|
self.nodes[1].importprivkey(priv_key)
|
|
|
|
# 6. Check that the unspents are now spendable on node1
|
|
assert_array_result(self.nodes[1].listunspent(),
|
|
{"address": address_to_import},
|
|
{"spendable": True})
|
|
|
|
# Mine a block from node0 to an address from node1
|
|
coinbase_addr = self.nodes[1].getnewaddress()
|
|
block_hash = self.nodes[0].generatetoaddress(1, coinbase_addr)[0]
|
|
coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]
|
|
self.sync_all(self.nodes[0:3])
|
|
|
|
# Check that the txid and balance is found by node1
|
|
self.nodes[1].gettransaction(coinbase_txid)
|
|
|
|
# check if wallet or blockchain maintenance changes the balance
|
|
self.sync_all(self.nodes[0:3])
|
|
blocks = self.nodes[0].generate(2)
|
|
self.sync_all(self.nodes[0:3])
|
|
balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
|
|
block_count = self.nodes[0].getblockcount()
|
|
|
|
# Check modes:
|
|
# - True: unicode escaped as \u....
|
|
# - False: unicode directly as UTF-8
|
|
for mode in [True, False]:
|
|
self.nodes[0].rpc.ensure_ascii = mode
|
|
# unicode check: Basic Multilingual Plane, Supplementary Plane respectively
|
|
for label in [u'рыба', u'𝅘𝅥𝅯']:
|
|
addr = self.nodes[0].getnewaddress()
|
|
self.nodes[0].setlabel(addr, label)
|
|
assert_equal(self.nodes[0].getaddressinfo(addr)['label'], label)
|
|
assert(label in self.nodes[0].listlabels())
|
|
self.nodes[0].rpc.ensure_ascii = True # restore to default
|
|
|
|
# maintenance tests
|
|
maintenance = [
|
|
'-rescan',
|
|
'-reindex',
|
|
'-zapwallettxes=1',
|
|
'-zapwallettxes=2',
|
|
# disabled until issue is fixed: https://github.com/bitcoin/bitcoin/issues/7463
|
|
# '-salvagewallet',
|
|
]
|
|
chainlimit = 6
|
|
for m in maintenance:
|
|
self.log.info("check " + m)
|
|
self.stop_nodes()
|
|
# set lower ancestor limit for later
|
|
self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)])
|
|
self.start_node(1, [m, "-limitancestorcount=" + str(chainlimit)])
|
|
self.start_node(2, [m, "-limitancestorcount=" + str(chainlimit)])
|
|
if m == '-reindex':
|
|
# reindex will leave rpc warm up "early"; Wait for it to finish
|
|
wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
|
|
assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])
|
|
|
|
# Exercise listsinceblock with the last two blocks
|
|
coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0])
|
|
assert_equal(coinbase_tx_1["lastblock"], blocks[1])
|
|
assert_equal(len(coinbase_tx_1["transactions"]), 1)
|
|
assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1])
|
|
assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0)
|
|
|
|
# ==Check that wallet prefers to use coins that don't exceed mempool limits =====
|
|
|
|
# Get all non-zero utxos together
|
|
chain_addrs = [self.nodes[0].getnewaddress(), self.nodes[0].getnewaddress()]
|
|
singletxid = self.nodes[0].sendtoaddress(chain_addrs[0], self.nodes[0].getbalance(), "", "", True)
|
|
self.nodes[0].generate(1)
|
|
node0_balance = self.nodes[0].getbalance()
|
|
# Split into two chains
|
|
rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')})
|
|
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx)
|
|
singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
|
|
self.nodes[0].generate(1)
|
|
|
|
# Make a long chain of unconfirmed payments without hitting mempool limit
|
|
# Each tx we make leaves only one output of change on a chain 1 longer
|
|
# Since the amount to send is always much less than the outputs, we only ever need one output
|
|
# So we should be able to generate exactly chainlimit txs for each original output
|
|
sending_addr = self.nodes[1].getnewaddress()
|
|
txid_list = []
|
|
for i in range(chainlimit * 2):
|
|
txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
|
|
assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
|
|
assert_equal(len(txid_list), chainlimit * 2)
|
|
|
|
# Without walletrejectlongchains, we will still generate a txid
|
|
# The tx will be stored in the wallet but not accepted to the mempool
|
|
extra_txid = self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001'))
|
|
assert(extra_txid not in self.nodes[0].getrawmempool())
|
|
assert(extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()])
|
|
self.nodes[0].abandontransaction(extra_txid)
|
|
total_txs = len(self.nodes[0].listtransactions("*", 99999))
|
|
|
|
# Try with walletrejectlongchains
|
|
# Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
|
|
self.stop_node(0)
|
|
self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])
|
|
|
|
# wait for loadmempool
|
|
timeout = 10
|
|
while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit * 2):
|
|
time.sleep(0.5)
|
|
timeout -= 0.5
|
|
assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2)
|
|
|
|
node0_balance = self.nodes[0].getbalance()
|
|
# With walletrejectlongchains we will not create the tx and store it in our wallet.
|
|
assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))
|
|
|
|
# Verify nothing new in wallet
|
|
assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))
|
|
|
|
# Test getaddressinfo. Note that these addresses are taken from disablewallet.py
|
|
assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
|
|
address_info = self.nodes[0].getaddressinfo("yjQ5gLvGRtmq1cwc4kePLCrzQ8GVCh9Gaz")
|
|
assert_equal(address_info['address'], "yjQ5gLvGRtmq1cwc4kePLCrzQ8GVCh9Gaz")
|
|
assert_equal(address_info["scriptPubKey"], "76a914fd2b4d101724a76374fccbc5b6df7670a75d7cd088ac")
|
|
assert not address_info["ismine"]
|
|
assert not address_info["iswatchonly"]
|
|
assert not address_info["isscript"]
|
|
|
|
if __name__ == '__main__':
|
|
WalletTest().main()
|