0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-03-05 14:06:27 -05:00

wallet: Increase OUTPUT_GROUP_MAX_ENTRIES to 100

This commit is contained in:
Fabian Jahr 2020-03-24 15:04:36 +01:00
parent 13d27b452d
commit 8f073076b1
No known key found for this signature in database
GPG key ID: F13D1E9D890798CD
2 changed files with 25 additions and 25 deletions

View file

@ -53,7 +53,7 @@ const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
}, },
}; };
static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10; static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};
RecursiveMutex cs_wallets; RecursiveMutex cs_wallets;
static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets); static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
@ -2497,7 +2497,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// form groups from remaining coins; note that preset coins will not // form groups from remaining coins; note that preset coins will not
// automatically have their associated (same address) coins included // automatically have their associated (same address) coins included
if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) { if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
// Cases where we have 11+ outputs all pointing to the same destination may result in // Cases where we have 101+ outputs all pointing to the same destination may result in
// privacy leaks as they will potentially be deterministically sorted. We solve that by // privacy leaks as they will potentially be deterministically sorted. We solve that by
// explicitly shuffling the outputs before processing // explicitly shuffling the outputs before processing
Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext()); Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());

View file

@ -42,25 +42,25 @@ def count_unspent(node):
r["reused"]["supported"] = supports_reused r["reused"]["supported"] = supports_reused
return r return r
def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None, reused_count=None, reused_sum=None): def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None, reused_count=None, reused_sum=None, margin=0.001):
'''Make assertions about a node's unspent output statistics''' '''Make assertions about a node's unspent output statistics'''
stats = count_unspent(node) stats = count_unspent(node)
if total_count is not None: if total_count is not None:
assert_equal(stats["total"]["count"], total_count) assert_equal(stats["total"]["count"], total_count)
if total_sum is not None: if total_sum is not None:
assert_approx(stats["total"]["sum"], total_sum, 0.001) assert_approx(stats["total"]["sum"], total_sum, margin)
if reused_supported is not None: if reused_supported is not None:
assert_equal(stats["reused"]["supported"], reused_supported) assert_equal(stats["reused"]["supported"], reused_supported)
if reused_count is not None: if reused_count is not None:
assert_equal(stats["reused"]["count"], reused_count) assert_equal(stats["reused"]["count"], reused_count)
if reused_sum is not None: if reused_sum is not None:
assert_approx(stats["reused"]["sum"], reused_sum, 0.001) assert_approx(stats["reused"]["sum"], reused_sum, margin)
def assert_balances(node, mine): def assert_balances(node, mine, margin=0.001):
'''Make assertions about a node's getbalances output''' '''Make assertions about a node's getbalances output'''
got = node.getbalances()["mine"] got = node.getbalances()["mine"]
for k,v in mine.items(): for k,v in mine.items():
assert_approx(got[k], v, 0.001) assert_approx(got[k], v, margin)
class AvoidReuseTest(BitcoinTestFramework): class AvoidReuseTest(BitcoinTestFramework):
@ -299,7 +299,7 @@ class AvoidReuseTest(BitcoinTestFramework):
ret_addr = self.nodes[0].getnewaddress() ret_addr = self.nodes[0].getnewaddress()
# send multiple transactions, reusing one address # send multiple transactions, reusing one address
for _ in range(11): for _ in range(101):
self.nodes[0].sendtoaddress(new_addr, 1) self.nodes[0].sendtoaddress(new_addr, 1)
self.nodes[0].generate(1) self.nodes[0].generate(1)
@ -311,14 +311,14 @@ class AvoidReuseTest(BitcoinTestFramework):
# getbalances and listunspent should show the remaining outputs # getbalances and listunspent should show the remaining outputs
# in the reused address as used/reused # 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_unspent(self.nodes[1], total_count=2, total_sum=96, reused_count=1, reused_sum=1, margin=0.01)
assert_balances(self.nodes[1], mine={"used": 1, "trusted": 5}) assert_balances(self.nodes[1], mine={"used": 1, "trusted": 95}, margin=0.01)
def test_full_destination_group_is_preferred(self): def test_full_destination_group_is_preferred(self):
''' '''
Test the case where [1] only has 11 outputs of 1 BTC in the same reused Test the case where [1] only has 101 outputs of 1 BTC in the same reused
address and tries to send a small payment of 0.5 BTC. The wallet 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 should use 100 outputs from the reused address as inputs and not a
single 1 BTC input, in order to join several outputs from the reused single 1 BTC input, in order to join several outputs from the reused
address. address.
''' '''
@ -330,8 +330,8 @@ class AvoidReuseTest(BitcoinTestFramework):
new_addr = self.nodes[1].getnewaddress() new_addr = self.nodes[1].getnewaddress()
ret_addr = self.nodes[0].getnewaddress() ret_addr = self.nodes[0].getnewaddress()
# Send 11 outputs of 1 BTC to the same, reused address in the wallet # Send 101 outputs of 1 BTC to the same, reused address in the wallet
for _ in range(11): for _ in range(101):
self.nodes[0].sendtoaddress(new_addr, 1) self.nodes[0].sendtoaddress(new_addr, 1)
self.nodes[0].generate(1) self.nodes[0].generate(1)
@ -342,14 +342,14 @@ class AvoidReuseTest(BitcoinTestFramework):
txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=0.5) txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=0.5)
inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"] inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
# The transaction should use 10 inputs exactly # The transaction should use 100 inputs exactly
assert_equal(len(inputs), 10) assert_equal(len(inputs), 100)
def test_all_destination_groups_are_used(self): def test_all_destination_groups_are_used(self):
''' '''
Test the case where [1] only has 22 outputs of 1 BTC in the same reused Test the case where [1] only has 202 outputs of 1 BTC in the same reused
address and tries to send a payment of 20.5 BTC. The wallet address and tries to send a payment of 200.5 BTC. The wallet
should use all 22 outputs from the reused address as inputs. should use all 202 outputs from the reused address as inputs.
''' '''
self.log.info("Test that all destination groups are used") self.log.info("Test that all destination groups are used")
@ -359,20 +359,20 @@ class AvoidReuseTest(BitcoinTestFramework):
new_addr = self.nodes[1].getnewaddress() new_addr = self.nodes[1].getnewaddress()
ret_addr = self.nodes[0].getnewaddress() ret_addr = self.nodes[0].getnewaddress()
# Send 22 outputs of 1 BTC to the same, reused address in the wallet # Send 202 outputs of 1 BTC to the same, reused address in the wallet
for _ in range(22): for _ in range(202):
self.nodes[0].sendtoaddress(new_addr, 1) self.nodes[0].sendtoaddress(new_addr, 1)
self.nodes[0].generate(1) self.nodes[0].generate(1)
self.sync_all() self.sync_all()
# Sending a transaction that needs to use the full groups # Sending a transaction that needs to use the full groups
# of 10 inputs but also the incomplete group of 2 inputs. # of 100 inputs but also the incomplete group of 2 inputs.
txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=20.5) txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=200.5)
inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"] inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
# The transaction should use 22 inputs exactly # The transaction should use 202 inputs exactly
assert_equal(len(inputs), 22) assert_equal(len(inputs), 202)
if __name__ == '__main__': if __name__ == '__main__':