Skip to content

Commit 7a6c46b

Browse files
committed
chainparams: add allowed assumeutxo values
Values for mainnet and testnet will be specified in a follow-up PR that can be scrutinized accordingly. This structure is required for use in snapshot activation logic.
1 parent e9c037b commit 7a6c46b

File tree

6 files changed

+110
-1
lines changed

6 files changed

+110
-1
lines changed

src/chainparams.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <chainparamsseeds.h>
99
#include <consensus/merkle.h>
1010
#include <hash.h> // for signet block challenge hash
11-
#include <tinyformat.h>
1211
#include <util/system.h>
1312
#include <util/strencodings.h>
1413
#include <versionbitsinfo.h>
@@ -161,6 +160,10 @@ class CMainParams : public CChainParams {
161160
}
162161
};
163162

163+
m_assumeutxo_data = MapAssumeutxo{
164+
// TODO to be specified in a future patch.
165+
};
166+
164167
chainTxData = ChainTxData{
165168
// Data from RPC: getchaintxstats 4096 0000000000000000000b9d2ec5a352ecba0592946514a92f14319dc2b367fc72
166169
/* nTime */ 1603995752,
@@ -250,6 +253,10 @@ class CTestNetParams : public CChainParams {
250253
}
251254
};
252255

256+
m_assumeutxo_data = MapAssumeutxo{
257+
// TODO to be specified in a future patch.
258+
};
259+
253260
chainTxData = ChainTxData{
254261
// Data from RPC: getchaintxstats 4096 000000000000006433d1efec504c53ca332b64963c425395515b01977bd7b3b0
255262
/* nTime */ 1603359686,
@@ -431,6 +438,17 @@ class CRegTestParams : public CChainParams {
431438
}
432439
};
433440

441+
m_assumeutxo_data = MapAssumeutxo{
442+
{
443+
110,
444+
{uint256S("0x76fd7334ac7c1baf57ddc0c626f073a655a35d98a4258cd1382c8cc2b8392e10"), 110},
445+
},
446+
{
447+
210,
448+
{uint256S("0x9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2"), 210},
449+
},
450+
};
451+
434452
chainTxData = ChainTxData{
435453
0,
436454
0,
@@ -526,3 +544,9 @@ void SelectParams(const std::string& network)
526544
SelectBaseParams(network);
527545
globalChainParams = CreateChainParams(gArgs, network);
528546
}
547+
548+
std::ostream& operator<<(std::ostream& o, const AssumeutxoData& aud)
549+
{
550+
o << strprintf("AssumeutxoData(%s, %s)", aud.hash_serialized.ToString(), aud.nChainTx);
551+
return o;
552+
}

src/chainparams.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,26 @@ struct CCheckpointData {
3030
}
3131
};
3232

33+
/**
34+
* Holds configuration for use during UTXO snapshot load and validation. The contents
35+
* here are security critical, since they dictate which UTXO snapshots are recognized
36+
* as valid.
37+
*/
38+
struct AssumeutxoData {
39+
//! The expected hash of the deserialized UTXO set.
40+
const uint256 hash_serialized;
41+
42+
//! Used to populate the nChainTx value, which is used during BlockManager::LoadBlockIndex().
43+
//!
44+
//! We need to hardcode the value here because this is computed cumulatively using block data,
45+
//! which we do not necessarily have at the time of snapshot load.
46+
const unsigned int nChainTx;
47+
};
48+
49+
std::ostream& operator<<(std::ostream& o, const AssumeutxoData& aud);
50+
51+
using MapAssumeutxo = std::map<int, const AssumeutxoData>;
52+
3353
/**
3454
* Holds various statistics on transactions within a chain. Used to estimate
3555
* verification progress during chain sync.
@@ -90,6 +110,11 @@ class CChainParams
90110
const std::string& Bech32HRP() const { return bech32_hrp; }
91111
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
92112
const CCheckpointData& Checkpoints() const { return checkpointData; }
113+
114+
//! Get allowed assumeutxo configuration.
115+
//! @see ChainstateManager
116+
const MapAssumeutxo& Assumeutxo() const { return m_assumeutxo_data; }
117+
93118
const ChainTxData& TxData() const { return chainTxData; }
94119
protected:
95120
CChainParams() {}
@@ -111,6 +136,7 @@ class CChainParams
111136
bool m_is_test_chain;
112137
bool m_is_mockable_chain;
113138
CCheckpointData checkpointData;
139+
MapAssumeutxo m_assumeutxo_data;
114140
ChainTxData chainTxData;
115141
};
116142

src/node/coinstats.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ static void ApplyHash(CCoinsStats& stats, MuHash3072& muhash, const uint256& has
5555
muhash.Insert(MakeUCharSpan(ss));
5656
}
5757

58+
//! Warning: be very careful when changing this! assumeutxo and UTXO snapshot
59+
//! validation commitments are reliant on the hash constructed by this
60+
//! function.
61+
//!
62+
//! If the construction of this hash is changed, it will invalidate
63+
//! existing UTXO snapshots. This will not result in any kind of consensus
64+
//! failure, but it will force clients that were expecting to make use of
65+
//! assumeutxo to do traditional IBD instead.
66+
//!
67+
//! It is also possible, though very unlikely, that a change in this
68+
//! construction could cause a previously invalid (and potentially malicious)
69+
//! UTXO snapshot to be considered valid.
5870
template <typename T>
5971
static void ApplyStats(CCoinsStats& stats, T& hash_obj, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
6072
{

src/test/validation_tests.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <chainparams.h>
66
#include <net.h>
77
#include <signet.h>
8+
#include <uint256.h>
89
#include <validation.h>
910

1011
#include <test/util/setup_common.h>
@@ -119,4 +120,27 @@ BOOST_AUTO_TEST_CASE(signet_parse_tests)
119120
BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus()));
120121
}
121122

123+
//! Test retrieval of valid assumeutxo values.
124+
BOOST_AUTO_TEST_CASE(test_assumeutxo)
125+
{
126+
const auto params = CreateChainParams(*m_node.args, CBaseChainParams::REGTEST);
127+
128+
// These heights don't have assumeutxo configurations associated, per the contents
129+
// of chainparams.cpp.
130+
std::vector<int> bad_heights{0, 100, 111, 115, 209, 211};
131+
132+
for (auto empty : bad_heights) {
133+
const auto out = ExpectedAssumeutxo(empty, *params);
134+
BOOST_CHECK(!out);
135+
}
136+
137+
const auto out110 = *ExpectedAssumeutxo(110, *params);
138+
BOOST_CHECK_EQUAL(out110.hash_serialized, uint256S("76fd7334ac7c1baf57ddc0c626f073a655a35d98a4258cd1382c8cc2b8392e10"));
139+
BOOST_CHECK_EQUAL(out110.nChainTx, (unsigned int)110);
140+
141+
const auto out210 = *ExpectedAssumeutxo(210, *params);
142+
BOOST_CHECK_EQUAL(out210.hash_serialized, uint256S("9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2"));
143+
BOOST_CHECK_EQUAL(out210.nChainTx, (unsigned int)210);
144+
}
145+
122146
BOOST_AUTO_TEST_SUITE_END()

src/validation.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <logging/timer.h>
2323
#include <node/ui_interface.h>
2424
#include <optional.h>
25+
#include <node/coinstats.h>
2526
#include <policy/policy.h>
2627
#include <policy/settings.h>
2728
#include <pow.h>
@@ -5192,6 +5193,18 @@ CChainState& ChainstateManager::InitializeChainstate(CTxMemPool& mempool, const
51925193
return *to_modify;
51935194
}
51945195

5196+
const AssumeutxoData* ExpectedAssumeutxo(
5197+
const int height, const CChainParams& chainparams)
5198+
{
5199+
const MapAssumeutxo& valid_assumeutxos_map = chainparams.Assumeutxo();
5200+
const auto assumeutxo_found = valid_assumeutxos_map.find(height);
5201+
5202+
if (assumeutxo_found != valid_assumeutxos_map.end()) {
5203+
return &assumeutxo_found->second;
5204+
}
5205+
return nullptr;
5206+
}
5207+
51955208
CChainState& ChainstateManager::ActiveChainstate() const
51965209
{
51975210
LOCK(::cs_main);

src/validation.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct ChainTxData;
5353
struct DisconnectedBlockTransactions;
5454
struct PrecomputedTransactionData;
5555
struct LockPoints;
56+
struct AssumeutxoData;
5657

5758
/** Default for -minrelaytxfee, minimum relay fee for transactions */
5859
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
@@ -1013,4 +1014,13 @@ inline bool IsBlockPruned(const CBlockIndex* pblockindex)
10131014
return (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0);
10141015
}
10151016

1017+
/**
1018+
* Return the expected assumeutxo value for a given height, if one exists.
1019+
*
1020+
* @param height[in] Get the assumeutxo value for this height.
1021+
*
1022+
* @returns empty if no assumeutxo configuration exists for the given height.
1023+
*/
1024+
const AssumeutxoData* ExpectedAssumeutxo(const int height, const CChainParams& params);
1025+
10161026
#endif // BITCOIN_VALIDATION_H

0 commit comments

Comments
 (0)