1111#include < chainparams.h>
1212#include < coins.h>
1313#include < consensus/validation.h>
14+ #include < crypto/muhash.h>
1415#include < core_io.h>
1516#include < hash.h>
1617#include < index/blockfilterindex.h>
3536#include < warnings.h>
3637
3738#include < assert.h>
39+
3840#include < stdint.h>
3941
4042#include < univalue.h>
@@ -916,29 +918,28 @@ struct CCoinsStats
916918 uint64_t nTransactions;
917919 uint64_t nTransactionOutputs;
918920 uint64_t nBogoSize;
919- uint256 hashSerialized ;
921+ uint256 muhash ;
920922 uint64_t nDiskSize;
921923 CAmount nTotalAmount;
922924
923925 CCoinsStats () : nHeight(0 ), nTransactions(0 ), nTransactionOutputs(0 ), nBogoSize(0 ), nDiskSize(0 ), nTotalAmount(0 ) {}
924926};
925927
926- static void ApplyStats (CCoinsStats &stats, CHashWriter& ss , const uint256& hash, const std::map<uint32_t , Coin>& outputs)
928+ static void ApplyStats (CCoinsStats &stats, MuHash3072& acc , const uint256& hash, const std::map<uint32_t , Coin>& outputs)
927929{
928930 assert (!outputs.empty ());
929- ss << hash;
930- ss << VARINT (outputs.begin ()->second .nHeight * 2 + outputs.begin ()->second .fCoinBase ? 1u : 0u );
931931 stats.nTransactions ++;
932- for (const auto & output : outputs) {
933- ss << VARINT (output.first + 1 );
934- ss << output.second .out .scriptPubKey ;
935- ss << VARINT (output.second .out .nValue , VarIntMode::NONNEGATIVE_SIGNED);
932+ for (const auto output : outputs) {
933+ TruncatedSHA512Writer ss (SER_DISK, 0 );
934+ ss << COutPoint (hash, output.first );
935+ ss << (uint32_t )(output.second .nHeight * 2 + output.second .fCoinBase );
936+ ss << output.second .out ;
937+ acc *= MuHash3072 (ss.GetHash ().begin ());
936938 stats.nTransactionOutputs ++;
937939 stats.nTotalAmount += output.second .out .nValue ;
938940 stats.nBogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ +
939941 2 /* scriptPubKey len */ + output.second .out .scriptPubKey .size () /* scriptPubKey */ ;
940942 }
941- ss << VARINT (0u );
942943}
943944
944945// ! Calculate statistics about the unspent transaction output set
@@ -947,22 +948,21 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
947948 std::unique_ptr<CCoinsViewCursor> pcursor (view->Cursor ());
948949 assert (pcursor);
949950
950- CHashWriter ss (SER_GETHASH, PROTOCOL_VERSION);
951951 stats.hashBlock = pcursor->GetBestBlock ();
952952 {
953953 LOCK (cs_main);
954954 stats.nHeight = LookupBlockIndex (stats.hashBlock )->nHeight ;
955955 }
956- ss << stats.hashBlock ;
957- uint256 prevkey;
956+ MuHash3072 acc;
958957 std::map<uint32_t , Coin> outputs;
958+ uint256 prevkey;
959959 while (pcursor->Valid ()) {
960960 boost::this_thread::interruption_point ();
961961 COutPoint key;
962962 Coin coin;
963963 if (pcursor->GetKey (key) && pcursor->GetValue (coin)) {
964964 if (!outputs.empty () && key.hash != prevkey) {
965- ApplyStats (stats, ss , prevkey, outputs);
965+ ApplyStats (stats, acc , prevkey, outputs);
966966 outputs.clear ();
967967 }
968968 prevkey = key.hash ;
@@ -973,9 +973,13 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
973973 pcursor->Next ();
974974 }
975975 if (!outputs.empty ()) {
976- ApplyStats (stats, ss , prevkey, outputs);
976+ ApplyStats (stats, acc , prevkey, outputs);
977977 }
978- stats.hashSerialized = ss.GetHash ();
978+ unsigned char data[384 ];
979+ acc.Finalize (data);
980+ TruncatedSHA512Writer ss (SER_DISK, 0 );
981+ ss << FLATDATA (data);
982+ stats.muhash = ss.GetHash ();
979983 stats.nDiskSize = view->EstimateSize ();
980984 return true ;
981985}
@@ -1049,7 +1053,7 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
10491053 " \" transactions\" : n, (numeric) The number of transactions with unspent outputs\n "
10501054 " \" txouts\" : n, (numeric) The number of unspent transaction outputs\n "
10511055 " \" bogosize\" : n, (numeric) A meaningless metric for UTXO set size\n "
1052- " \" hash_serialized_2 \" : \" hash\" , (string) The serialized hash\n "
1056+ " \" muhash \" : \" hash\" , (string) Rolling UTXO set hash\n "
10531057 " \" disk_size\" : n, (numeric) The estimated size of the chainstate on disk\n "
10541058 " \" total_amount\" : x.xxx (numeric) The total amount\n "
10551059 " }\n "
@@ -1072,7 +1076,7 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
10721076 ret.pushKV (" transactions" , (int64_t )stats.nTransactions );
10731077 ret.pushKV (" txouts" , (int64_t )stats.nTransactionOutputs );
10741078 ret.pushKV (" bogosize" , (int64_t )stats.nBogoSize );
1075- ret.pushKV (" hash_serialized_2 " , stats.hashSerialized .GetHex ());
1079+ ret.pushKV (" muhash " , stats.muhash .GetHex ());
10761080 ret.pushKV (" disk_size" , stats.nDiskSize );
10771081 ret.pushKV (" total_amount" , ValueFromAmount (stats.nTotalAmount ));
10781082 } else {
0 commit comments