2019-06-19 01:32:02 +02:00
|
|
|
#!/usr/bin/env python3
|
2023-04-25 13:51:26 +02:00
|
|
|
# Copyright (c) 2018-2020 The Bitcoin Core developers
|
2019-06-19 01:32:02 +02:00
|
|
|
# Distributed under the MIT software license, see the accompanying
|
|
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
"""Test the avoid_reuse and setwalletflag features."""
|
|
|
|
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
|
|
from test_framework.util import (
|
|
|
|
assert_equal,
|
|
|
|
assert_raises_rpc_error,
|
|
|
|
)
|
|
|
|
|
|
|
|
# TODO: Copied from wallet_groups.py -- should perhaps move into util.py
|
|
|
|
def assert_approx(v, vexp, vspan=0.00001):
|
|
|
|
if v < vexp - vspan:
|
|
|
|
raise AssertionError("%s < [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
|
|
|
|
if v > vexp + vspan:
|
|
|
|
raise AssertionError("%s > [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
|
|
|
|
|
|
|
|
def reset_balance(node, discardaddr):
|
|
|
|
'''Throw away all owned coins by the node so it gets a balance of 0.'''
|
|
|
|
balance = node.getbalance(avoid_reuse=False)
|
|
|
|
if balance > 0.5:
|
|
|
|
node.sendtoaddress(address=discardaddr, amount=balance, subtractfeefromamount=True, avoid_reuse=False)
|
|
|
|
|
|
|
|
def count_unspent(node):
|
|
|
|
'''Count the unspent outputs for the given node and return various statistics'''
|
|
|
|
r = {
|
|
|
|
"total": {
|
|
|
|
"count": 0,
|
|
|
|
"sum": 0,
|
|
|
|
},
|
|
|
|
"reused": {
|
|
|
|
"count": 0,
|
|
|
|
"sum": 0,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
supports_reused = True
|
|
|
|
for utxo in node.listunspent(minconf=0):
|
|
|
|
r["total"]["count"] += 1
|
|
|
|
r["total"]["sum"] += utxo["amount"]
|
|
|
|
if supports_reused and "reused" in utxo:
|
|
|
|
if utxo["reused"]:
|
|
|
|
r["reused"]["count"] += 1
|
|
|
|
r["reused"]["sum"] += utxo["amount"]
|
|
|
|
else:
|
|
|
|
supports_reused = False
|
|
|
|
r["reused"]["supported"] = supports_reused
|
|
|
|
return r
|
|
|
|
|
|
|
|
def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None, reused_count=None, reused_sum=None):
|
|
|
|
'''Make assertions about a node's unspent output statistics'''
|
|
|
|
stats = count_unspent(node)
|
|
|
|
if total_count is not None:
|
|
|
|
assert_equal(stats["total"]["count"], total_count)
|
|
|
|
if total_sum is not None:
|
|
|
|
assert_approx(stats["total"]["sum"], total_sum, 0.001)
|
|
|
|
if reused_supported is not None:
|
|
|
|
assert_equal(stats["reused"]["supported"], reused_supported)
|
|
|
|
if reused_count is not None:
|
|
|
|
assert_equal(stats["reused"]["count"], reused_count)
|
|
|
|
if reused_sum is not None:
|
|
|
|
assert_approx(stats["reused"]["sum"], reused_sum, 0.001)
|
|
|
|
|
2019-06-22 11:58:52 +02:00
|
|
|
def assert_balances(node, mine):
|
|
|
|
'''Make assertions about a node's getbalances output'''
|
|
|
|
got = node.getbalances()["mine"]
|
|
|
|
for k,v in mine.items():
|
|
|
|
assert_approx(got[k], v, 0.001)
|
|
|
|
|
2019-06-19 01:32:02 +02:00
|
|
|
class AvoidReuseTest(BitcoinTestFramework):
|
|
|
|
|
|
|
|
def set_test_params(self):
|
|
|
|
self.setup_clean_chain = False
|
|
|
|
self.num_nodes = 2
|
Merge #17362: test: speed up wallet_avoidreuse, add logging
0e7c90eb37a687158c261ddd1ff9f1028a1e7012 test: speed up wallet_avoidreuse.py (Jon Atack)
6d50b2606ea9249627556051637080c3587b1b04 test: add logging to wallet_avoidreuse.py (Jon Atack)
Pull request description:
Inspired by PRs #17340 and #15881.
- add logging
- pass -whitelist in `set_test_params` to speed up transaction relay
`wallet_avoidreuse.py` is not intended to test P2P transaction relay/timing, so it should be fine to do this here. This reduces test run time variability and speeds up the test by 2-3 times on average.
Test run times in seconds:
- before: 20, 24, 22, 17, 27, 40, 30
- after: 10, 10, 8, 9, 10, 7, 8
ACKs for top commit:
MarcoFalke:
ACK 0e7c90eb37a687158c261ddd1ff9f1028a1e7012 🐊
fanquake:
ACK 0e7c90eb37a687158c261ddd1ff9f1028a1e7012
Tree-SHA512: 6d954a0aaf402c9594201626b59d29263479059e68fa5155bb44ed973cd0c3347729dd78b78b4d5a2275e45da365dc1afb4cc7e3293dea33fcc2e3e83a39faf5
2019-11-07 17:34:23 +01:00
|
|
|
# This test isn't testing txn relay/timing, so set whitelist on the
|
|
|
|
# peers for instant txn relay. This speeds up the test run time 2-3x.
|
2020-02-28 05:18:57 +01:00
|
|
|
self.extra_args = [["-whitelist=noban@127.0.0.1"]] * self.num_nodes
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
def skip_test_if_missing_module(self):
|
|
|
|
self.skip_if_no_wallet()
|
|
|
|
|
|
|
|
def run_test(self):
|
|
|
|
'''Set up initial chain and run tests defined below'''
|
|
|
|
|
|
|
|
self.test_persistence()
|
|
|
|
self.test_immutable()
|
|
|
|
|
|
|
|
self.nodes[0].generate(110)
|
|
|
|
self.sync_all()
|
|
|
|
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
|
2020-04-17 13:05:31 +02:00
|
|
|
self.test_sending_from_reused_address_without_avoid_reuse()
|
2019-06-19 01:32:02 +02:00
|
|
|
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
|
2020-04-17 13:05:31 +02:00
|
|
|
self.test_sending_from_reused_address_fails()
|
2020-01-15 10:10:39 +01:00
|
|
|
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
|
|
|
|
self.test_getbalances_used()
|
2020-04-17 13:05:31 +02:00
|
|
|
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
|
|
|
|
self.test_full_destination_group_is_preferred()
|
|
|
|
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
|
|
|
|
self.test_all_destination_groups_are_used()
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
def test_persistence(self):
|
|
|
|
'''Test that wallet files persist the avoid_reuse flag.'''
|
Merge #17362: test: speed up wallet_avoidreuse, add logging
0e7c90eb37a687158c261ddd1ff9f1028a1e7012 test: speed up wallet_avoidreuse.py (Jon Atack)
6d50b2606ea9249627556051637080c3587b1b04 test: add logging to wallet_avoidreuse.py (Jon Atack)
Pull request description:
Inspired by PRs #17340 and #15881.
- add logging
- pass -whitelist in `set_test_params` to speed up transaction relay
`wallet_avoidreuse.py` is not intended to test P2P transaction relay/timing, so it should be fine to do this here. This reduces test run time variability and speeds up the test by 2-3 times on average.
Test run times in seconds:
- before: 20, 24, 22, 17, 27, 40, 30
- after: 10, 10, 8, 9, 10, 7, 8
ACKs for top commit:
MarcoFalke:
ACK 0e7c90eb37a687158c261ddd1ff9f1028a1e7012 🐊
fanquake:
ACK 0e7c90eb37a687158c261ddd1ff9f1028a1e7012
Tree-SHA512: 6d954a0aaf402c9594201626b59d29263479059e68fa5155bb44ed973cd0c3347729dd78b78b4d5a2275e45da365dc1afb4cc7e3293dea33fcc2e3e83a39faf5
2019-11-07 17:34:23 +01:00
|
|
|
self.log.info("Test wallet files persist avoid_reuse flag")
|
|
|
|
|
2019-06-19 01:32:02 +02:00
|
|
|
# Configure node 1 to use avoid_reuse
|
|
|
|
self.nodes[1].setwalletflag('avoid_reuse')
|
|
|
|
|
|
|
|
# Flags should be node1.avoid_reuse=false, node2.avoid_reuse=true
|
|
|
|
assert_equal(self.nodes[0].getwalletinfo()["avoid_reuse"], False)
|
|
|
|
assert_equal(self.nodes[1].getwalletinfo()["avoid_reuse"], True)
|
|
|
|
|
|
|
|
# Stop and restart node 1
|
2020-06-22 18:24:41 +02:00
|
|
|
self.restart_node(1)
|
2022-09-24 14:36:35 +02:00
|
|
|
self.connect_nodes(0, 1)
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
# Flags should still be node1.avoid_reuse=false, node2.avoid_reuse=true
|
|
|
|
assert_equal(self.nodes[0].getwalletinfo()["avoid_reuse"], False)
|
|
|
|
assert_equal(self.nodes[1].getwalletinfo()["avoid_reuse"], True)
|
|
|
|
|
|
|
|
# Attempting to set flag to its current state should throw
|
|
|
|
assert_raises_rpc_error(-8, "Wallet flag is already set to false", self.nodes[0].setwalletflag, 'avoid_reuse', False)
|
|
|
|
assert_raises_rpc_error(-8, "Wallet flag is already set to true", self.nodes[1].setwalletflag, 'avoid_reuse', True)
|
|
|
|
|
|
|
|
def test_immutable(self):
|
|
|
|
'''Test immutable wallet flags'''
|
Merge #17362: test: speed up wallet_avoidreuse, add logging
0e7c90eb37a687158c261ddd1ff9f1028a1e7012 test: speed up wallet_avoidreuse.py (Jon Atack)
6d50b2606ea9249627556051637080c3587b1b04 test: add logging to wallet_avoidreuse.py (Jon Atack)
Pull request description:
Inspired by PRs #17340 and #15881.
- add logging
- pass -whitelist in `set_test_params` to speed up transaction relay
`wallet_avoidreuse.py` is not intended to test P2P transaction relay/timing, so it should be fine to do this here. This reduces test run time variability and speeds up the test by 2-3 times on average.
Test run times in seconds:
- before: 20, 24, 22, 17, 27, 40, 30
- after: 10, 10, 8, 9, 10, 7, 8
ACKs for top commit:
MarcoFalke:
ACK 0e7c90eb37a687158c261ddd1ff9f1028a1e7012 🐊
fanquake:
ACK 0e7c90eb37a687158c261ddd1ff9f1028a1e7012
Tree-SHA512: 6d954a0aaf402c9594201626b59d29263479059e68fa5155bb44ed973cd0c3347729dd78b78b4d5a2275e45da365dc1afb4cc7e3293dea33fcc2e3e83a39faf5
2019-11-07 17:34:23 +01:00
|
|
|
self.log.info("Test immutable wallet flags")
|
|
|
|
|
2019-06-19 01:32:02 +02:00
|
|
|
# Attempt to set the disable_private_keys flag; this should not work
|
|
|
|
assert_raises_rpc_error(-8, "Wallet flag is immutable", self.nodes[1].setwalletflag, 'disable_private_keys')
|
|
|
|
|
|
|
|
tempwallet = ".wallet_avoidreuse.py_test_immutable_wallet.dat"
|
|
|
|
|
|
|
|
# Create a wallet with disable_private_keys set; this should work
|
|
|
|
self.nodes[1].createwallet(tempwallet, True)
|
|
|
|
w = self.nodes[1].get_wallet_rpc(tempwallet)
|
|
|
|
|
|
|
|
# Attempt to unset the disable_private_keys flag; this should not work
|
|
|
|
assert_raises_rpc_error(-8, "Wallet flag is immutable", w.setwalletflag, 'disable_private_keys', False)
|
|
|
|
|
|
|
|
# Unload temp wallet
|
|
|
|
self.nodes[1].unloadwallet(tempwallet)
|
|
|
|
|
2020-04-17 13:05:31 +02:00
|
|
|
def test_sending_from_reused_address_without_avoid_reuse(self):
|
2019-06-19 01:32:02 +02:00
|
|
|
'''
|
2020-04-17 13:05:31 +02:00
|
|
|
Test the same as test_sending_from_reused_address_fails, except send the 10 BTC with
|
2019-06-19 01:32:02 +02:00
|
|
|
the avoid_reuse flag set to false. This means the 10 BTC send should succeed,
|
2020-04-17 13:05:31 +02:00
|
|
|
where it fails in test_sending_from_reused_address_fails.
|
2019-06-19 01:32:02 +02:00
|
|
|
'''
|
2020-04-17 13:05:31 +02:00
|
|
|
self.log.info("Test sending from reused address with avoid_reuse=false")
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
fundaddr = self.nodes[1].getnewaddress()
|
|
|
|
retaddr = self.nodes[0].getnewaddress()
|
|
|
|
|
|
|
|
self.nodes[0].sendtoaddress(fundaddr, 10)
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# listunspent should show 1 single, unused 10 btc output
|
|
|
|
assert_unspent(self.nodes[1], total_count=1, total_sum=10, reused_supported=True, reused_count=0)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show no used, 10 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 0, "trusted": 10})
|
|
|
|
# node 0 should not show a used entry, as it does not enable avoid_reuse
|
|
|
|
assert("used" not in self.nodes[0].getbalances()["mine"])
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
self.nodes[1].sendtoaddress(retaddr, 5)
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# listunspent should show 1 single, unused 5 btc output
|
|
|
|
assert_unspent(self.nodes[1], total_count=1, total_sum=5, reused_supported=True, reused_count=0)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show no used, 5 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 0, "trusted": 5})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
self.nodes[0].sendtoaddress(fundaddr, 10)
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# listunspent should show 2 total outputs (5, 10 btc), one unused (5), one reused (10)
|
|
|
|
assert_unspent(self.nodes[1], total_count=2, total_sum=15, reused_count=1, reused_sum=10)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show 10 used, 5 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 10, "trusted": 5})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
self.nodes[1].sendtoaddress(address=retaddr, amount=10, avoid_reuse=False)
|
|
|
|
|
|
|
|
# listunspent should show 1 total outputs (5 btc), unused
|
|
|
|
assert_unspent(self.nodes[1], total_count=1, total_sum=5, reused_count=0)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show no used, 5 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 0, "trusted": 5})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
# node 1 should now have about 5 btc left (for both cases)
|
|
|
|
assert_approx(self.nodes[1].getbalance(), 5, 0.001)
|
|
|
|
assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 5, 0.001)
|
|
|
|
|
2020-04-17 13:05:31 +02:00
|
|
|
def test_sending_from_reused_address_fails(self):
|
2019-06-19 01:32:02 +02:00
|
|
|
'''
|
|
|
|
Test the simple case where [1] generates a new address A, then
|
|
|
|
[0] sends 10 BTC to A.
|
|
|
|
[1] spends 5 BTC from A. (leaving roughly 5 BTC useable)
|
|
|
|
[0] sends 10 BTC to A again.
|
|
|
|
[1] tries to spend 10 BTC (fails; dirty).
|
|
|
|
[1] tries to spend 4 BTC (succeeds; change address sufficient)
|
|
|
|
'''
|
2020-04-17 13:05:31 +02:00
|
|
|
self.log.info("Test sending from reused address fails")
|
2019-06-19 01:32:02 +02:00
|
|
|
|
2020-01-07 22:31:23 +01:00
|
|
|
fundaddr = self.nodes[1].getnewaddress(label="")
|
2019-06-19 01:32:02 +02:00
|
|
|
retaddr = self.nodes[0].getnewaddress()
|
|
|
|
|
|
|
|
self.nodes[0].sendtoaddress(fundaddr, 10)
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# listunspent should show 1 single, unused 10 btc output
|
|
|
|
assert_unspent(self.nodes[1], total_count=1, total_sum=10, reused_supported=True, reused_count=0)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show no used, 10 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 0, "trusted": 10})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
self.nodes[1].sendtoaddress(retaddr, 5)
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# listunspent should show 1 single, unused 5 btc output
|
|
|
|
assert_unspent(self.nodes[1], total_count=1, total_sum=5, reused_supported=True, reused_count=0)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show no used, 5 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 0, "trusted": 5})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
self.nodes[0].sendtoaddress(fundaddr, 10)
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# listunspent should show 2 total outputs (5, 10 btc), one unused (5), one reused (10)
|
|
|
|
assert_unspent(self.nodes[1], total_count=2, total_sum=15, reused_count=1, reused_sum=10)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show 10 used, 5 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 10, "trusted": 5})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
# node 1 should now have a balance of 5 (no dirty) or 15 (including dirty)
|
|
|
|
assert_approx(self.nodes[1].getbalance(), 5, 0.001)
|
|
|
|
assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 15, 0.001)
|
|
|
|
|
|
|
|
assert_raises_rpc_error(-6, "Insufficient funds", self.nodes[1].sendtoaddress, retaddr, 10)
|
|
|
|
|
|
|
|
self.nodes[1].sendtoaddress(retaddr, 4)
|
|
|
|
|
|
|
|
# listunspent should show 2 total outputs (1, 10 btc), one unused (1), one reused (10)
|
|
|
|
assert_unspent(self.nodes[1], total_count=2, total_sum=11, reused_count=1, reused_sum=10)
|
2019-06-22 11:58:52 +02:00
|
|
|
# getbalances should show 10 used, 1 btc trusted
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 10, "trusted": 1})
|
2019-06-19 01:32:02 +02:00
|
|
|
|
|
|
|
# node 1 should now have about 1 btc left (no dirty) and 11 (including dirty)
|
|
|
|
assert_approx(self.nodes[1].getbalance(), 1, 0.001)
|
|
|
|
assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 11, 0.001)
|
|
|
|
|
2020-01-15 10:10:39 +01:00
|
|
|
def test_getbalances_used(self):
|
|
|
|
'''
|
|
|
|
getbalances and listunspent should pick up on reused addresses
|
|
|
|
immediately, even for address reusing outputs created before the first
|
|
|
|
transaction was spending from that address
|
|
|
|
'''
|
|
|
|
self.log.info("Test getbalances used category")
|
|
|
|
|
|
|
|
# node under test should be completely empty
|
|
|
|
assert_equal(self.nodes[1].getbalance(avoid_reuse=False), 0)
|
|
|
|
|
|
|
|
new_addr = self.nodes[1].getnewaddress()
|
|
|
|
ret_addr = self.nodes[0].getnewaddress()
|
|
|
|
|
|
|
|
# send multiple transactions, reusing one address
|
|
|
|
for _ in range(11):
|
|
|
|
self.nodes[0].sendtoaddress(new_addr, 1)
|
|
|
|
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# send transaction that should not use all the available outputs
|
|
|
|
# per the current coin selection algorithm
|
|
|
|
self.nodes[1].sendtoaddress(ret_addr, 5)
|
|
|
|
|
|
|
|
# getbalances and listunspent should show the remaining outputs
|
|
|
|
# in the reused address as used/reused
|
|
|
|
assert_unspent(self.nodes[1], total_count=2, total_sum=6, reused_count=1, reused_sum=1)
|
|
|
|
assert_balances(self.nodes[1], mine={"used": 1, "trusted": 5})
|
|
|
|
|
2020-04-17 13:05:31 +02:00
|
|
|
def test_full_destination_group_is_preferred(self):
|
|
|
|
'''
|
|
|
|
Test the case where [1] only has 11 outputs of 1 BTC in the same reused
|
|
|
|
address and tries to send a small payment of 0.5 BTC. The wallet
|
|
|
|
should use 10 outputs from the reused address as inputs and not a
|
|
|
|
single 1 BTC input, in order to join several outputs from the reused
|
|
|
|
address.
|
|
|
|
'''
|
|
|
|
self.log.info("Test that full destination groups are preferred in coin selection")
|
|
|
|
|
|
|
|
# Node under test should be empty
|
|
|
|
assert_equal(self.nodes[1].getbalance(avoid_reuse=False), 0)
|
|
|
|
|
|
|
|
new_addr = self.nodes[1].getnewaddress()
|
|
|
|
ret_addr = self.nodes[0].getnewaddress()
|
|
|
|
|
|
|
|
# Send 11 outputs of 1 BTC to the same, reused address in the wallet
|
|
|
|
for _ in range(11):
|
|
|
|
self.nodes[0].sendtoaddress(new_addr, 1)
|
|
|
|
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# Sending a transaction that is smaller than each one of the
|
|
|
|
# available outputs
|
|
|
|
txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=0.5)
|
|
|
|
inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
|
|
|
|
|
|
|
|
# The transaction should use 10 inputs exactly
|
|
|
|
assert_equal(len(inputs), 10)
|
|
|
|
|
|
|
|
def test_all_destination_groups_are_used(self):
|
|
|
|
'''
|
|
|
|
Test the case where [1] only has 22 outputs of 1 BTC in the same reused
|
|
|
|
address and tries to send a payment of 20.5 BTC. The wallet
|
|
|
|
should use all 22 outputs from the reused address as inputs.
|
|
|
|
'''
|
|
|
|
self.log.info("Test that all destination groups are used")
|
|
|
|
|
|
|
|
# Node under test should be empty
|
|
|
|
assert_equal(self.nodes[1].getbalance(avoid_reuse=False), 0)
|
|
|
|
|
|
|
|
new_addr = self.nodes[1].getnewaddress()
|
|
|
|
ret_addr = self.nodes[0].getnewaddress()
|
|
|
|
|
|
|
|
# Send 22 outputs of 1 BTC to the same, reused address in the wallet
|
|
|
|
for _ in range(22):
|
|
|
|
self.nodes[0].sendtoaddress(new_addr, 1)
|
|
|
|
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.sync_all()
|
|
|
|
|
|
|
|
# Sending a transaction that needs to use the full groups
|
|
|
|
# of 10 inputs but also the incomplete group of 2 inputs.
|
|
|
|
txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=20.5)
|
|
|
|
inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
|
|
|
|
|
|
|
|
# The transaction should use 22 inputs exactly
|
|
|
|
assert_equal(len(inputs), 22)
|
|
|
|
|
|
|
|
|
2019-06-19 01:32:02 +02:00
|
|
|
if __name__ == '__main__':
|
|
|
|
AvoidReuseTest().main()
|