hash_type
option muhash
to gettxoutsetinfo
through which the user can calculate the serialized muhash of the utxo set. This PR does not use the index yet.
hash_type
option muhash
to gettxoutsetinfo
through which the user can calculate the serialized muhash of the utxo set. This PR does not use the index yet.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
muhash
. And that muhash
and none
will be more responsive than the default (or just change the default, and note that as a breaking change to anyone who uses the legacy hash).
P2PDataStore
in other tests. But the data it returns on each UTXO is kind of specific to my test.
396@@ -397,6 +397,8 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
397 crypto/hmac_sha512.h \
398 crypto/poly1305.h \
399 crypto/poly1305.cpp \
400+ crypto/muhash.h \
401+ crypto/muhash.cpp \
54+ height += 1
55+ block_time += 1
56+
57+ # Save first block because we want to spend its coinbase.
58+ if i == 0:
59+ block1 = block
Isn’t this sort of a roundabout way to setup what seems to be the actual test, at lines 74-87? I’m not seeing why conn = node.add_p2p_connection(P2PDataStore())
is necessary for what’s being tested here, and if the method added in this PR def estimate_utxo_set(self):
is needed.
Would something like this do what you need:
0coinbase_blocks = list(map(lambda block: node.getblock(block), node.generate(100)))
1spending = next(filter(lambda block: block["confirmations"] == 100, coinbase_blocks))
2coinbase_blocks.remove(spending)
3
4tx = node.gettransaction(spending["tx"][0])
5vtx = FromHex(CTransaction(), tx["hex"])
6vtx.rehash()
7tx1 = create_tx_with_script(vtx, 0, script_sig=b'\x51', amount=25 * COIN)
8tx2 = create_tx_with_script(tx1, 0, script_sig=b'\x51', amount=25 * COIN)
9
10tx1id = node.sendrawtransaction(hexstring=tx1.serialize().hex(), maxfeerate=0)['hex']
11tx2id = node.sendrawtransaction(hexstring=tx2.serialize().hex(), maxfeerate=0)['hex']
12node.generateblock(output=node.getnewaddress(), transactions=[tx1id, tx2id])
and then you form utxo_set
here from coinbase_blocks
, and tx
, tx1
, tx2
to calculate the MuHash of the set
70+ block2.solve()
71+
72+ conn.send_blocks_and_test([block2], node, success=True)
73+
74+ # Calculate the MuHash of the UTXO set estimate
75+ muhash = MuHash3072()
tx1
, tx2
?
24@@ -24,31 +25,47 @@ static uint64_t GetBogoSize(const CScript& scriptPubKey)
25 scriptPubKey.size() /* scriptPubKey */;
26 }
27
28-static void ApplyStats(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
29+static void ApplyHash(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
CCoinsStats& stats
There is a deterministic regtest blockchain for the test
rpc_getblockstats.py
which could (additionally) test the finalized hash against constants, especially in the future when one tests for correct rolling behaviour between blocks.
Thanks, that’s a good point but I think this will be even more interesting when we get to the actual index when the RPC can give hashes for specific heights so I think I will leave this for one of the follow-ups of this one.
274@@ -276,18 +275,33 @@ void Num3072::Divide(const Num3072& a)
275 if (this->IsOverflow()) this->FullReduce();
276 }
277
278-Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
279- Num3072 out{};
280- uint256 hashed_in = (CHashWriter(SER_DISK, 0) << in).GetSHA256();
281- unsigned char tmp[BYTE_SIZE];
282- ChaCha20(hashed_in.data(), hashed_in.size()).Keystream(tmp, BYTE_SIZE);
283+Num3072::Num3072(const unsigned char data[BYTE_SIZE]) {
In commit " refactor: Improve encapsulation between MuHash3072 and Num3072"
I recommend against passing C-style arrays, as despite its notation, it’s not passing an array but a pointer. For example, this works with no warning: https://godbolt.org/z/YrMvfE
An alternative is using a C++ reference-to-array:
0 Num3072::Num3072(const unsigned char (&data)[BYTE_SIZE]) {
50+
51+ CDataStream ss(SER_DISK, PROTOCOL_VERSION);
52+ ss << outpoint;
53+ ss << (uint32_t)(coin.nHeight * 2 + coin.fCoinBase);
54+ ss << coin.out;
55+ muhash.Insert(MakeUCharSpan(ss.str()));
In commit “rpc: Add hash_type MUHASH to gettxoutsetinfo”
I think extracting an std::string
here is unnecessary.
0muhash.Insert(MakeUCharSpan(ss));
should work just as well, and avoid the copy.
23@@ -24,31 +24,35 @@ static uint64_t GetBogoSize(const CScript& scriptPubKey)
24 scriptPubKey.size() /* scriptPubKey */;
25 }
26
27-static void ApplyStats(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
28+static void ApplyHash(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
In commit “refactor: Seperate hash and stats calculation in coinstats”
Nit: seperate -> separate in commit title
93@@ -91,8 +94,6 @@ class Num3072
94 class MuHash3072
f8e4e369 nit, this is the only occurrence in the codebase documentation where MuHash is written Muhash
0 * efficiently combined later.
1 *
2- * Muhash does not support checking if an element is already part of the
3+ * MuHash does not support checking if an element is already part of the
4 * set. That is why this class does not enforce the use of a set as the
5 * data it represents because there is no efficient way to do so.
(the other place is in the python code)
0test/functional/test_framework/muhash.py:95:class TestFrameworkMuhash(unittest.TestCase):
266@@ -267,6 +267,13 @@ def _test_gettxoutsetinfo(self):
267 # hash_type none should not return a UTXO set hash.
268 res5 = node.gettxoutsetinfo(hash_type='none')
269 assert 'hash_serialized_2' not in res5
270+ assert 'muhash' not in res5
assert 'muhash' not in
be added to any of res-res4
135+ } else if (hash_type_input == "none") {
136+ return CoinStatsHashType::NONE;
137+ } else if (hash_type_input == "muhash") {
138+ return CoinStatsHashType::MUHASH;
139+ } else {
140+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%d is not a valid hash_type", hash_type_input));
bde3febaf this could perhaps be a bit simpler
0diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
1index 576dabc349..3a07e5620d 100644
2--- a/src/rpc/blockchain.cpp
3+++ b/src/rpc/blockchain.cpp
4@@ -1079,7 +1079,7 @@ static RPCHelpMan gettxoutsetinfo()
5 CCoinsStats stats;
6 ::ChainstateActive().ForceFlushStateToDisk();
7
8- const CoinStatsHashType hash_type = ParseHashType(request.params[0], CoinStatsHashType::HASH_SERIALIZED);
9+ const CoinStatsHashType hash_type{request.params[0].isNull() ? CoinStatsHashType::HASH_SERIALIZED : ParseHashType(request.params[0].get_str())};
10
11 CCoinsView* coins_view = WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB());
12 NodeContext& node = EnsureNodeContext(request.context);
13diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
14index 30e09a9aac..d8dadf41f7 100644
15--- a/src/rpc/util.cpp
16+++ b/src/rpc/util.cpp
17@@ -113,14 +113,8 @@ std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
18 return ParseHexV(find_value(o, strKey), strKey);
19 }
20
21-CoinStatsHashType ParseHashType(const UniValue& param, const CoinStatsHashType default_type)
22+CoinStatsHashType ParseHashType(const std::string& hash_type_input)
23 {
24- if (param.isNull()) {
25- return default_type;
26- }
27-
28- std::string hash_type_input = param.get_str();
29-
30 if (hash_type_input == "hash_serialized_2") {
31 return CoinStatsHashType::HASH_SERIALIZED;
32 } else if (hash_type_input == "none") {
33diff --git a/src/rpc/util.h b/src/rpc/util.h
34index 942c243718..611d281014 100644
35--- a/src/rpc/util.h
36+++ b/src/rpc/util.h
37@@ -77,7 +77,7 @@ extern uint256 ParseHashO(const UniValue& o, std::string strKey);
38 extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
39 extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
40
41-CoinStatsHashType ParseHashType(const UniValue& param, const CoinStatsHashType default_type);
42+CoinStatsHashType ParseHashType(const std::string& hash_type_input);
43
44 extern CAmount AmountFromValue(const UniValue& value);
45 extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
rpc/blockchain.cpp
.
1062@@ -1063,6 +1063,7 @@ static RPCHelpMan gettxoutsetinfo()
1063 {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
1064 {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
1065 {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
1066+ {RPCResult::Type::STR_HEX, "muhash", "The serialized hash (only present if 'muhash' hash_type is chosen)"},
1067 {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
bde3febaf pass as optional results
0- {RPCResult::Type::STR_HEX, "muhash", "The serialized hash (only present if 'muhash' hash_type is chosen)"},
1- {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
2+ {RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
3+ {RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
62+ COutPoint outpoint = COutPoint(hash, it->first);
63+ Coin coin = it->second;
64+
65+ CDataStream ss(SER_DISK, PROTOCOL_VERSION);
66+ ss << outpoint;
67+ ss << (uint32_t)(coin.nHeight * 2 + coin.fCoinBase);
bde3feba named cast
0 ss << static_cast<uint32_t>(coin.nHeight * 2 + coin.fCoinBase);
9+
10+from test_framework.blocktools import create_transaction
11+from test_framework.messages import (
12+ COutPoint,
13+ FromHex,
14+ CBlock,
15+)
16+from test_framework.muhash import MuHash3072
17+from test_framework.test_framework import BitcoinTestFramework
18+from test_framework.util import assert_equal
19+
20+import struct
Also fixes a typo.
1065 return RPCHelpMan{"gettxoutsetinfo",
1066 "\nReturns statistics about the unspent transaction output set.\n"
1067 "Note this call may take some time.\n",
1068 {
1069- {"hash_type", RPCArg::Type::STR, /* default */ "hash_serialized_2", "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'none'."},
1070+ {"hash_type", RPCArg::Type::STR, /* default */ "hash_serialized_2", "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."},
good catch in the latest push
0- Options: 'hash_serialized_2' (the legacy algorithm), 'none'."},
1+ Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."},
1054+ } else if (hash_type_input == "none") {
1055+ return CoinStatsHashType::NONE;
1056+ } else if (hash_type_input == "muhash") {
1057+ return CoinStatsHashType::MUHASH;
1058+ } else {
1059+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%d is not a valid hash_type", hash_type_input));
726c9504 I overlooked this in my first review, perhaps add a functional test assertion on this output
0 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s is not a valid hash_type", hash_type_input));
Oh, maybe it works anyway
0./src/bitcoin-cli -signet gettxoutsetinfo MuHash
1error code: -8
2error message:
3MuHash is not a valid hash_type
137@@ -117,9 +138,17 @@ static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
138 ss << stats.hashBlock;
139 }
140 static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
141+// Muhash does not need the prepare step
ACK 2e5617f7f4bcece4834852cc925068e47ceeffa3 code review, reviewed diff last review per git diff 7a96f77 2e5617f
, tested rebased on current master
Happy to re-ACK for the changes above.
0# bsi is an alias for ./src/bitcoin-cli -signet
1
2((HEAD detached at origin/pr/19145))$ bsi help gettxoutsetinfo
3gettxoutsetinfo ( "hash_type" )
4
5Returns statistics about the unspent transaction output set.
6Note this call may take some time.
7
8Arguments:
91. hash_type (string, optional, default=hash_serialized_2) Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'.
10
11Result:
12{ (json object)
13 "height" : n, (numeric) The current block height (index)
14 "bestblock" : "hex", (string) The hash of the block at the tip of the chain
15 "transactions" : n, (numeric) The number of transactions with unspent outputs
16 "txouts" : n, (numeric) The number of unspent transaction outputs
17 "bogosize" : n, (numeric) A meaningless metric for UTXO set size
18 "muhash" : "hex", (string, optional) The serialized hash (only present if 'muhash' hash_type is chosen)
19 "hash_serialized_2" : "hex", (string, optional) The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)
20 "disk_size" : n, (numeric) The estimated size of the chainstate on disk
21 "total_amount" : n (numeric) The total amount
22}
23
24Examples:
25> bitcoin-cli gettxoutsetinfo
26> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "gettxoutsetinfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
27
28((HEAD detached at origin/pr/19145))$ bsi gettxoutsetinfo
29{
30 "height": 21927,
31 "bestblock": "0000000d69e0c1800fd7103a7f1aaf24ec7b8c1db92257bda1035dcfd8e71c30",
32 "transactions": 17430,
33 "txouts": 17550,
34 "bogosize": 1263989,
35 "hash_serialized_2": "c8dbf6ab5094c36935ca89fc8e347b65ab17320f0937c5ac942274a1a0027892",
36 "disk_size": 1264123,
37 "total_amount": 1096350.00000000
38}
39
40((HEAD detached at origin/pr/19145))$ bsi gettxoutsetinfo hash_serialized_2
41{
42 "height": 21928,
43 "bestblock": "000000c3c7e614717b8cdf6c33de7a8a7d97a856eba6640b481a0029fc774249",
44 "transactions": 17431,
45 "txouts": 17551,
46 "bogosize": 1264061,
47 "hash_serialized_2": "3e31af57df9dac6bf8924560b647fc81f01bdac1c0fe4af2bc12b61c81d87d61",
48 "disk_size": 1264123,
49 "total_amount": 1096400.00000000
50}
51
52((HEAD detached at origin/pr/19145))$ bsi gettxoutsetinfo muhash
53{
54 "height": 21927,
55 "bestblock": "0000000d69e0c1800fd7103a7f1aaf24ec7b8c1db92257bda1035dcfd8e71c30",
56 "transactions": 17430,
57 "txouts": 17550,
58 "bogosize": 1263989,
59 "muhash": "cd74b9cfe35dfee561ed730953ed15085e83c096db30d5c03a8ab1a6a137077a",
60 "disk_size": 1264123,
61 "total_amount": 1096350.00000000
62}
63
64((HEAD detached at origin/pr/19145))$ bsi gettxoutsetinfo none
65{
66 "height": 21927,
67 "bestblock": "0000000d69e0c1800fd7103a7f1aaf24ec7b8c1db92257bda1035dcfd8e71c30",
68 "transactions": 17430,
69 "txouts": 17550,
70 "bogosize": 1263989,
71 "disk_size": 1264123,
72 "total_amount": 1096350.00000000
73}
74
75((HEAD detached at origin/pr/19145))$ bsi gettxoutsetinfo non
76error code: -8
77error message:
78non is not a valid hash_type
79
80((HEAD detached at origin/pr/19145))$ bsi gettxoutsetinfo MuHash
81error code: -8
82error message:
83MuHash is not a valid hash_type
re-ACK 3506d9080166bc250e941d791e3e8a2b85d5bd6b per git diff 2e5617f 3506d90
Thanks for updating.
c263d20036cc983510e9b347cb88e947168dd5665ed00b0e6118d07a7704f810
24@@ -24,7 +25,7 @@ static uint64_t GetBogoSize(const CScript& scriptPubKey)
25 scriptPubKey.size() /* scriptPubKey */;
26 }
27
28-static void ApplyHash(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
29+static void ApplyHash(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
&
in the previous commit
123@@ -111,6 +124,10 @@ bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, CoinStatsHashType hash_t
124 case(CoinStatsHashType::NONE): {
125 return GetUTXOStats(view, stats, nullptr, interruption_point);
126 }
127+ case(CoinStatsHashType::MUHASH): {
MUHASH
before NONE
? (same with PrepareHash
and ParseHashType
)
1075@@ -1063,7 +1076,8 @@ static RPCHelpMan gettxoutsetinfo()
1076 {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
1077 {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
1078 {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
1079- {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
1080+ {RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
142+static void PrepareHash(MuHash3072& muhash, CCoinsStats& stats) {}
143
144 static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
145 {
146- stats.hashSerialized = ss.GetHash();
147+ stats.hashSerialized = ss.GetSHA256();
gettxoutsetinfo hash_serialized_2
(probably something else)
Reviewed 3506d9080166bc250e941d791e3e8a2b85d5bd6b, almost happy…
Muhash at height 668,212: d0192e6604c3dc9a78f47bfc5ae84b8c0f6baf960d7ba9305664bbb9f65ef092
.
hash_serialized_2
is 63fa057a656168ed832d8abbec8008948fc17aecde9f346d69043871a746941f
on master, but 15d3629db2fcbed27a1fd9d35c15b5ac6f0a70f5723ebf9cf87e3df0b0feb061
here (efe73b1f89e82d65100c73c06d9a01ec19cc7e029d93caaa8bfded4d1723d484
if I revert GetHash()
)
You may want to hardcode a hash_serialized_2
example in the test suite.
Also small style fix in rpc/util.cpp
Reviewed 3506d90, almost happy…
Muhash at height 668,212:
d0192e6604c3dc9a78f47bfc5ae84b8c0f6baf960d7ba9305664bbb9f65ef092
.
hash_serialized_2
is63fa057a656168ed832d8abbec8008948fc17aecde9f346d69043871a746941f
on master, but15d3629db2fcbed27a1fd9d35c15b5ac6f0a70f5723ebf9cf87e3df0b0feb061
here (efe73b1f89e82d65100c73c06d9a01ec19cc7e029d93caaa8bfded4d1723d484
if I revertGetHash()
)You may want to hardcode a
hash_serialized_2
example in the test suite.
Thanks a lot for testing @Sjors ! I should have addressed all your comments.
The difference in that hash was caused by using outputs.end()
where I should have used std::prev(outputs.end())
in ApplyHash()
. I was actually sure we had some deterministic tests in place for that hash already but obviously, we didn’t. So I added a new commit with a small test calculating the hash based on the cached chain to add such coverage.
1075@@ -1063,7 +1076,8 @@ static RPCHelpMan gettxoutsetinfo()
1076 {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
1077 {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
1078 {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
1079- {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
1080+ {RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
1081+ {RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
s/'/\"/
Good catch and nice improvements.
Tested re-ACK e987ae5a554c9952812746c29f2766bacea4b727 per git diff 3506d90 e987ae5
, reviewed diff, debug built, ran gettxoutsetinfo -signet and help on this branch vs master, at height 23127 both returned hash_serialized_2
of 2b72d65f3b6efb2311f58374ea2b939abf49684d44f4bafda45faa3b5452a454
and this branch returned muhash
of c9f1ff12d345ccf9939c6bbf087e6f7399b6115adee1569287e9c5c43dbb475c
Only if you have to retouch and if you agree, one nit below (and maybe use single/double quotes consistently in the functional tests).
tACK e987ae5
I get the same MuHash as before for block 668,212 and hash_serialized_2
now matches what I found on master.
ACK e987ae5a554c9952812746c29f2766bacea4b727
It would be nice if the test used MiniWallet or otherwise didn’t rely on the wallet, but it’s fine for now.
274@@ -276,18 +275,33 @@ void Num3072::Divide(const Num3072& a)
275 if (this->IsOverflow()) this->FullReduce();
276 }
277
278-Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
279- Num3072 out{};
280- uint256 hashed_in = (CHashWriter(SER_DISK, 0) << in).GetSHA256();
281- unsigned char tmp[BYTE_SIZE];
282- ChaCha20(hashed_in.data(), hashed_in.size()).Keystream(tmp, BYTE_SIZE);
283+Num3072::Num3072(const unsigned char (&data)[BYTE_SIZE]) {
In commit “refactor: Improve encapsulation between MuHash3072 and Num3072” (a1fcceac69097a8e6540a6fd8121a5d53022528f)
Note in case it helps other reviewers: I found this commit easier to review rearranging the method order to ToNum3072
Num3072
ToBytes
instead of Num3072
ToBytes
ToNum3072
so diff was smaller with code moving around less.
23@@ -24,31 +24,35 @@ static uint64_t GetBogoSize(const CScript& scriptPubKey)
24 scriptPubKey.size() /* scriptPubKey */;
25 }
26
27-static void ApplyStats(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
28+static void ApplyHash(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
In commit “refactor: Separate hash and stats calculation in coinstats” (2474645f3b15687e7f196b89eb935d6e6a98a9da)
stats
arguments in unused in all three overloads and could be dropped.
Also, passing iterators around like this seems unnecessarily elaborate. It makes sense to separate stats and hash computations, but is there a reason both computations need to share the a single for
loop over the output map? I would think you could make all the functions separate like:
static void ApplyHash(CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs); static void ApplyHash(MuHash3072& muhash, const uint256& hash, const std::map<uint32_t, Coin>& outputs); static void ApplyHash(std::nullptr_t, const uint256& hash, const std::map<uint32_t, Coin>& outputs); static void ApplyStats(CCoinsStats& stats, const uint256& hash, const std::map<uint32_t, Coin>& outputs);
25+ self.skip_if_no_wallet()
26+
27+ def test_deterministic_hash_results(self):
28+ self.log.info("Test deterministic UTXO set hash results")
29+
30+ # These depend on the setup_clean_chain option, the chain loaded from the cache
there is no loaded chain and the utxo set is empty. Which is also useful to check, but doesn’t check if the hash is deterministic?
Did you forget to load the chain from ./test/functional/data/rpc_getblockstats.json
?