Skip to content

Commit e7b0004

Browse files
committed
Merge bitcoin/bitcoin#27596: assumeutxo (2)
edbed31 chainparams: add signet assumeutxo param at height 160_000 (Sjors Provoost) b8cafe3 chainparams: add testnet assumeutxo param at height 2_500_000 (Sjors Provoost) 99839bb doc: add note about confusing HaveTxsDownloaded name (James O'Beirne) 7ee46a7 contrib: add script to demo/test assumeutxo (James O'Beirne) 42cae39 test: add feature_assumeutxo functional test (James O'Beirne) 0f64bac rpc: add getchainstates (James O'Beirne) bb05857 refuse to activate a UTXO snapshot if mempool not empty (James O'Beirne) ce585a9 rpc: add loadtxoutset (James O'Beirne) 62ac519 validation: do not activate snapshot if behind active chain (James O'Beirne) 9511fb3 validation: assumeutxo: swap m_mempool on snapshot activation (James O'Beirne) 7fcd215 blockstorage: segment normal/assumedvalid blockfiles (James O'Beirne) 4c3b8ca validation: populate nChainTx value for assumedvalid chainstates (James O'Beirne) 49ef778 test: adjust chainstate tests to use recognized snapshot base (James O'Beirne) 1019c39 validation: pruning for multiple chainstates (James O'Beirne) 373cf91 validation: indexing changes for assumeutxo (James O'Beirne) 1fffdd7 net_processing: validationinterface: ignore some events for bg chain (James O'Beirne) fbe0a7d wallet: validationinterface: only handle active chain notifications (James O'Beirne) f073917 validationinterface: only send zmq notifications for active (James O'Beirne) 4d8f4dc validation: pass ChainstateRole for validationinterface calls (James O'Beirne) 1e59acd validation: only call UpdatedBlockTip for active chainstate (James O'Beirne) c6af23c validation: add ChainstateRole (James O'Beirne) 9f2318c validation: MaybeRebalanceCaches when chain leaves IBD (James O'Beirne) 434495a chainparams: add blockhash to AssumeutxoData (James O'Beirne) c711ca1 assumeutxo: remove snapshot during -reindex{-chainstate} (James O'Beirne) c93ef43 bugfix: correct is_snapshot_cs in VerifyDB (James O'Beirne) b73d3bb net_processing: Request assumeutxo background chain blocks (Suhas Daftuar) Pull request description: - Background and FAQ: https://github.com/jamesob/assumeutxo-docs/tree/2019-04-proposal/proposal - Prior progress/project: https://github.com/bitcoin/bitcoin/projects/11 - Replaces bitcoin/bitcoin#15606, which was closed due to Github slowness. Original description and commentary can be found there. --- This changeset finishes the first phase of the assumeutxo project. It makes UTXO snapshots loadable via RPC (`loadtxoutset`) and adds `assumeutxo` parameters to chainparams. It contains all the remaining changes necessary to both use an assumedvalid snapshot chainstate and do a full validation sync in the background. This may look like a lot to review, but note that - ~200 lines are a (non-essential) demo shell script - Many lines are functional test, documentation, and relatively dilute RPC code. So it shouldn't be as burdensome to review as the linecount might suggest. - **P2P**: minor changes are made to `init.cpp` and `net_processing.cpp` to make simultaneous IBD across multiple chainstates work. - **Pruning**: implement correct pruning behavior when using a background chainstate - **Blockfile separation**: to prevent "fragmentation" in blockfile storage, have background chainstates use separate blockfiles from active snapshot chainstates to avoid interleaving heights and impairing pruning. - **Indexing**: some `CValidationInterface` events are given with an additional parameter, ChainstateRole, and all indexers ignore events from ChainstateRole::ASSUMEDVALID so that indexation only happens sequentially. - Have `-reindex` properly wipe snapshot chainstates. - **RPC**: introduce RPC commands `loadtxoutset` and (hidden) `getchainstates`. - **Release docs & first assumeutxo commitment**: add notes and a particular assumeutxo hash value for first AU-enabled release. - This will complete the project and allow use of UTXO snapshots for faster node bootstrap. The next phase, if it were to be pursued, would be coming up with a way to distribute the UTXO snapshots over the P2P network. --- ### UTXO snapshots Create your own with `./contrib/devtools/utxo_snapshot.sh`, e.g. ```shell ./contrib/devtools/utxo_snapshot.sh 788000 utxo.dat ./src/bitcoin-cli -datadir=$(pwd)/testdata`) ``` or use the pre-generated ones listed below. - Testnet: **2'500'000** (Sjors): - torrent: `magnet:?xt=urn:btih:511e09f4bf853aefab00de5c070b1e031f0ecbe9&dn=utxo-testnet-2500000.dat&tr=udp%3A%2F%2Ftracker.bitcoin.sprovoost.nl%3A6969` - sha256: `79db4b025448cc0ac388d8589a28eab02de53055d181e34eb47391717aa16388` - Signet: **160'000** (Sjors): - torrent: `magnet:?xt=urn:btih:9da986cb27b3980ea7fd06b21e199b148d486880&dn=utxo-signet-160000.dat&tr=udp%3A%2F%2Ftracker.bitcoin.sprovoost.nl%3A6969` - sha256: `eeeca845385ba91e84ef58c09d38f98f246a24feadaad57fe1e5874f3f92ef8c` - Mainnet: **800'000** (Sjors): - Note: this needs the following commit cherry-picked in: Sjors/bitcoin@24deb20 - torrent: `magnet:?xt=urn:btih:50ee955bef37f5ec3e5b0df4cf0288af3d715a2e&dn=utxo-800000.dat&tr=udp%3A%2F%2Ftracker.bitcoin.sprovoost.nl%3A6969` ### Testing #### For fun (~5min) If you want to do a quick test, you can run `./contrib/devtools/test_utxo_snapshots.sh` and follow the instructions. This is mostly obviated by the functional tests, though. #### For real (longer) If you'd like to experience a real usage of assumeutxo, you can do that too. I've cut a new snapshot at height 788'000 (http://img.jameso.be/utxo-788000.dat - but you can do it yourself with `./contrib/devtools/utxo_snapshot.sh` if you want). Download that, and then create a datadir for testing: ```sh $ cd ~/src/bitcoin # or whatever # get the snapshot $ curl http://img.jameso.be/utxo-788000.dat > utxo-788000.dat # you'll want to do this if you like copy/pasting $ export AU_DATADIR=/home/${USER}/au-test # or wherever $ mkdir ${AU_DATADIR} $ vim ${AU_DATADIR}/bitcoin.conf dbcache=8000 # or, you know, something high blockfilterindex=1 coinstatsindex=1 prune=3000 logthreadnames=1 ``` Obtain this branch, build it, and then start bitcoind: ```sh $ git remote add jamesob https://github.com/jamesob/bitcoin $ git fetch jamesob assumeutxo $ git checkout jamesob/assumeutxo $ ./configure $conf_args && make # (whatever you like to do here) # start 'er up and watch the logs $ ./src/bitcoind -datadir=${AU_DATADIR} ``` Then, in some other window, load the snapshot ```sh $ ./src/bitcoin-cli -datadir=${AU_DATADIR} loadtxoutset $(pwd)/utxo-788000.dat ``` You'll see some log messages about headers retrieval and waiting to see the snapshot in the headers chain. Once you get the full headers chain, you'll spend a decent amount of time (~10min) loading the snapshot, checking it, and flushing it to disk. After all that happens, you should be syncing to tip in pretty short order, and you'll see the occasional `[background validation]` log message go by. In yet another window, you can check out chainstate status with ```sh $ ./src/bitcoin-cli -datadir=${AU_DATADIR} getchainstates ``` as well as usual favorites like `getblockchaininfo`. ACKs for top commit: achow101: ACK edbed31 Tree-SHA512: 6086fb9a38dc7df85fedc76b30084dd8154617a2a91e89a84fb41326d34ef8e7d7ea593107afba01369093bf8cc91770621d98f0ea42a5b3b99db868d2f14dc2
2 parents fd8ab08 + edbed31 commit e7b0004

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1597
-289
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#!/usr/bin/env bash
2+
# Demonstrate the creation and usage of UTXO snapshots.
3+
#
4+
# A server node starts up, IBDs up to a certain height, then generates a UTXO
5+
# snapshot at that point.
6+
#
7+
# The server then downloads more blocks (to create a diff from the snapshot).
8+
#
9+
# We bring a client up, load the UTXO snapshot, and we show the client sync to
10+
# the "network tip" and then start a background validation of the snapshot it
11+
# loaded. We see the background validation chainstate removed after validation
12+
# completes.
13+
#
14+
15+
export LC_ALL=C
16+
set -e
17+
18+
BASE_HEIGHT=${1:-30000}
19+
INCREMENTAL_HEIGHT=20000
20+
FINAL_HEIGHT=$(($BASE_HEIGHT + $INCREMENTAL_HEIGHT))
21+
22+
SERVER_DATADIR="$(pwd)/utxodemo-data-server-$BASE_HEIGHT"
23+
CLIENT_DATADIR="$(pwd)/utxodemo-data-client-$BASE_HEIGHT"
24+
UTXO_DAT_FILE="$(pwd)/utxo.$BASE_HEIGHT.dat"
25+
26+
# Chosen to try to not interfere with any running bitcoind processes.
27+
SERVER_PORT=8633
28+
SERVER_RPC_PORT=8632
29+
30+
CLIENT_PORT=8733
31+
CLIENT_RPC_PORT=8732
32+
33+
SERVER_PORTS="-port=${SERVER_PORT} -rpcport=${SERVER_RPC_PORT}"
34+
CLIENT_PORTS="-port=${CLIENT_PORT} -rpcport=${CLIENT_RPC_PORT}"
35+
36+
# Ensure the client exercises all indexes to test that snapshot use works
37+
# properly with indexes.
38+
ALL_INDEXES="-txindex -coinstatsindex -blockfilterindex=1"
39+
40+
if ! command -v jq >/dev/null ; then
41+
echo "This script requires jq to parse JSON RPC output. Please install it."
42+
echo "(e.g. sudo apt install jq)"
43+
exit 1
44+
fi
45+
46+
DUMP_OUTPUT="dumptxoutset-output-$BASE_HEIGHT.json"
47+
48+
finish() {
49+
echo
50+
echo "Killing server and client PIDs ($SERVER_PID, $CLIENT_PID) and cleaning up datadirs"
51+
echo
52+
rm -f "$UTXO_DAT_FILE" "$DUMP_OUTPUT"
53+
rm -rf "$SERVER_DATADIR" "$CLIENT_DATADIR"
54+
kill -9 "$SERVER_PID" "$CLIENT_PID"
55+
}
56+
57+
trap finish EXIT
58+
59+
# Need to specify these to trick client into accepting server as a peer
60+
# it can IBD from, otherwise the default values prevent IBD from the server node.
61+
EARLY_IBD_FLAGS="-maxtipage=9223372036854775207 -minimumchainwork=0x00"
62+
63+
server_rpc() {
64+
./src/bitcoin-cli -rpcport=$SERVER_RPC_PORT -datadir="$SERVER_DATADIR" "$@"
65+
}
66+
client_rpc() {
67+
./src/bitcoin-cli -rpcport=$CLIENT_RPC_PORT -datadir="$CLIENT_DATADIR" "$@"
68+
}
69+
server_sleep_til_boot() {
70+
while ! server_rpc ping >/dev/null 2>&1; do sleep 0.1; done
71+
}
72+
client_sleep_til_boot() {
73+
while ! client_rpc ping >/dev/null 2>&1; do sleep 0.1; done
74+
}
75+
76+
mkdir -p "$SERVER_DATADIR" "$CLIENT_DATADIR"
77+
78+
echo "Hi, welcome to the assumeutxo demo/test"
79+
echo
80+
echo "We're going to"
81+
echo
82+
echo " - start up a 'server' node, sync it via mainnet IBD to height ${BASE_HEIGHT}"
83+
echo " - create a UTXO snapshot at that height"
84+
echo " - IBD ${INCREMENTAL_HEIGHT} more blocks on top of that"
85+
echo
86+
echo "then we'll demonstrate assumeutxo by "
87+
echo
88+
echo " - starting another node (the 'client') and loading the snapshot in"
89+
echo " * first you'll have to modify the code slightly (chainparams) and recompile"
90+
echo " * don't worry, we'll make it easy"
91+
echo " - observing the client sync ${INCREMENTAL_HEIGHT} blocks on top of the snapshot from the server"
92+
echo " - observing the client validate the snapshot chain via background IBD"
93+
echo
94+
read -p "Press [enter] to continue" _
95+
96+
echo
97+
echo "-- Starting the demo. You might want to run the two following commands in"
98+
echo " separate terminal windows:"
99+
echo
100+
echo " watch -n0.1 tail -n 30 $SERVER_DATADIR/debug.log"
101+
echo " watch -n0.1 tail -n 30 $CLIENT_DATADIR/debug.log"
102+
echo
103+
read -p "Press [enter] to continue" _
104+
105+
echo
106+
echo "-- IBDing the blocks (height=$BASE_HEIGHT) required to the server node..."
107+
./src/bitcoind -logthreadnames=1 $SERVER_PORTS \
108+
-datadir="$SERVER_DATADIR" $EARLY_IBD_FLAGS -stopatheight="$BASE_HEIGHT" >/dev/null
109+
110+
echo
111+
echo "-- Creating snapshot at ~ height $BASE_HEIGHT ($UTXO_DAT_FILE)..."
112+
sleep 2
113+
./src/bitcoind -logthreadnames=1 $SERVER_PORTS \
114+
-datadir="$SERVER_DATADIR" $EARLY_IBD_FLAGS -connect=0 -listen=0 >/dev/null &
115+
SERVER_PID="$!"
116+
117+
server_sleep_til_boot
118+
server_rpc dumptxoutset "$UTXO_DAT_FILE" > "$DUMP_OUTPUT"
119+
cat "$DUMP_OUTPUT"
120+
kill -9 "$SERVER_PID"
121+
122+
RPC_BASE_HEIGHT=$(jq -r .base_height < "$DUMP_OUTPUT")
123+
RPC_AU=$(jq -r .txoutset_hash < "$DUMP_OUTPUT")
124+
RPC_NCHAINTX=$(jq -r .nchaintx < "$DUMP_OUTPUT")
125+
RPC_BLOCKHASH=$(jq -r .base_hash < "$DUMP_OUTPUT")
126+
127+
# Wait for server to shutdown...
128+
while server_rpc ping >/dev/null 2>&1; do sleep 0.1; done
129+
130+
echo
131+
echo "-- Now: add the following to CMainParams::m_assumeutxo_data"
132+
echo " in src/kernel/chainparams.cpp, and recompile:"
133+
echo
134+
echo " {${RPC_BASE_HEIGHT}, AssumeutxoHash{uint256S(\"0x${RPC_AU}\")}, ${RPC_NCHAINTX}, uint256S(\"0x${RPC_BLOCKHASH}\")},"
135+
echo
136+
echo
137+
echo "-- IBDing more blocks to the server node (height=$FINAL_HEIGHT) so there is a diff between snapshot and tip..."
138+
./src/bitcoind $SERVER_PORTS -logthreadnames=1 -datadir="$SERVER_DATADIR" \
139+
$EARLY_IBD_FLAGS -stopatheight="$FINAL_HEIGHT" >/dev/null
140+
141+
echo
142+
echo "-- Starting the server node to provide blocks to the client node..."
143+
./src/bitcoind $SERVER_PORTS -logthreadnames=1 -debug=net -datadir="$SERVER_DATADIR" \
144+
$EARLY_IBD_FLAGS -connect=0 -listen=1 >/dev/null &
145+
SERVER_PID="$!"
146+
server_sleep_til_boot
147+
148+
echo
149+
echo "-- Okay, what you're about to see is the client starting up and activating the snapshot."
150+
echo " I'm going to display the top 14 log lines from the client on top of an RPC called"
151+
echo " getchainstates, which is like getblockchaininfo but for both the snapshot and "
152+
echo " background validation chainstates."
153+
echo
154+
echo " You're going to first see the snapshot chainstate sync to the server's tip, then"
155+
echo " the background IBD chain kicks in to validate up to the base of the snapshot."
156+
echo
157+
echo " Once validation of the snapshot is done, you should see log lines indicating"
158+
echo " that we've deleted the background validation chainstate."
159+
echo
160+
echo " Once everything completes, exit the watch command with CTRL+C."
161+
echo
162+
read -p "When you're ready for all this, hit [enter]" _
163+
164+
echo
165+
echo "-- Starting the client node to get headers from the server, then load the snapshot..."
166+
./src/bitcoind $CLIENT_PORTS $ALL_INDEXES -logthreadnames=1 -datadir="$CLIENT_DATADIR" \
167+
-connect=0 -addnode=127.0.0.1:$SERVER_PORT -debug=net $EARLY_IBD_FLAGS >/dev/null &
168+
CLIENT_PID="$!"
169+
client_sleep_til_boot
170+
171+
echo
172+
echo "-- Initial state of the client:"
173+
client_rpc getchainstates
174+
175+
echo
176+
echo "-- Loading UTXO snapshot into client..."
177+
client_rpc loadtxoutset "$UTXO_DAT_FILE"
178+
179+
watch -n 0.3 "( tail -n 14 $CLIENT_DATADIR/debug.log ; echo ; ./src/bitcoin-cli -rpcport=$CLIENT_RPC_PORT -datadir=$CLIENT_DATADIR getchainstates) | cat"
180+
181+
echo
182+
echo "-- Okay, now I'm going to restart the client to make sure that the snapshot chain reloads "
183+
echo " as the main chain properly..."
184+
echo
185+
echo " Press CTRL+C after you're satisfied to exit the demo"
186+
echo
187+
read -p "Press [enter] to continue"
188+
189+
while kill -0 "$CLIENT_PID"; do
190+
sleep 1
191+
done
192+
./src/bitcoind $CLIENT_PORTS $ALL_INDEXES -logthreadnames=1 -datadir="$CLIENT_DATADIR" -connect=0 \
193+
-addnode=127.0.0.1:$SERVER_PORT "$EARLY_IBD_FLAGS" >/dev/null &
194+
CLIENT_PID="$!"
195+
client_sleep_til_boot
196+
197+
watch -n 0.3 "( tail -n 14 $CLIENT_DATADIR/debug.log ; echo ; ./src/bitcoin-cli -rpcport=$CLIENT_RPC_PORT -datadir=$CLIENT_DATADIR getchainstates) | cat"
198+
199+
echo
200+
echo "-- Done!"

doc/design/assumeutxo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Assumeutxo is a feature that allows fast bootstrapping of a validating bitcoind
44
instance with a very similar security model to assumevalid.
55

6-
The RPC commands `dumptxoutset` and `loadtxoutset` (yet to be merged) are used to
6+
The RPC commands `dumptxoutset` and `loadtxoutset` are used to
77
respectively generate and load UTXO snapshots. The utility script
88
`./contrib/devtools/utxo_snapshot.sh` may be of use.
99

doc/release-notes-27596.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Pruning
2+
-------
3+
4+
When using assumeutxo with `-prune`, the prune budget may be exceeded if it is set
5+
lower than 1100MB (i.e. `MIN_DISK_SPACE_FOR_BLOCK_FILES * 2`). Prune budget is normally
6+
split evenly across each chainstate, unless the resulting prune budget per chainstate
7+
is beneath `MIN_DISK_SPACE_FOR_BLOCK_FILES` in which case that value will be used.
8+
9+
RPC
10+
---
11+
12+
`loadtxoutset` has been added, which allows loading a UTXO snapshot of the format
13+
generated by `dumptxoutset`. Once this snapshot is loaded, its contents will be
14+
deserialized into a second chainstate data structure, which is then used to sync to
15+
the network's tip under a security model very much like `assumevalid`.
16+
17+
Meanwhile, the original chainstate will complete the initial block download process in
18+
the background, eventually validating up to the block that the snapshot is based upon.
19+
20+
The result is a usable bitcoind instance that is current with the network tip in a
21+
matter of minutes rather than hours. UTXO snapshot are typically obtained via
22+
third-party sources (HTTP, torrent, etc.) which is reasonable since their contents
23+
are always checked by hash.
24+
25+
You can find more information on this process in the `assumeutxo` design
26+
document (<https://github.com/bitcoin/bitcoin/blob/master/doc/design/assumeutxo.md>).
27+
28+
`getchainstates` has been added to aid in monitoring the assumeutxo sync process.

doc/zmq.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ Where the 8-byte uints correspond to the mempool sequence number.
113113
| hashtx | <32-byte transaction hash in Little Endian> | <uint32 sequence number in Little Endian>
114114

115115

116-
`rawblock`: Notifies when the chain tip is updated. Messages are ZMQ multipart messages with three parts. The first part is the topic (`rawblock`), the second part is the serialized block, and the last part is a sequence number (representing the message count to detect lost messages).
116+
`rawblock`: Notifies when the chain tip is updated. When assumeutxo is in use, this notification will not be issued for historical blocks connected to the background validation chainstate. Messages are ZMQ multipart messages with three parts. The first part is the topic (`rawblock`), the second part is the serialized block, and the last part is a sequence number (representing the message count to detect lost messages).
117117

118118
| rawblock | <serialized block> | <uint32 sequence number in Little Endian>
119119

120-
`hashblock`: Notifies when the chain tip is updated. Messages are ZMQ multipart messages with three parts. The first part is the topic (`hashblock`), the second part is the 32-byte block hash, and the last part is a sequence number (representing the message count to detect lost messages).
120+
`hashblock`: Notifies when the chain tip is updated. When assumeutxo is in use, this notification will not be issued for historical blocks connected to the background validation chainstate. Messages are ZMQ multipart messages with three parts. The first part is the topic (`hashblock`), the second part is the 32-byte block hash, and the last part is a sequence number (representing the message count to detect lost messages).
121121

122122
| hashblock | <32-byte block hash in Little Endian> | <uint32 sequence number in Little Endian>
123123

src/bench/wallet_create_tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void generateFakeBlock(const CChainParams& params,
7070

7171
// notify wallet
7272
const auto& pindex = WITH_LOCK(::cs_main, return context.chainman->ActiveChain().Tip());
73-
wallet.blockConnected(kernel::MakeBlockInfo(pindex, &block));
73+
wallet.blockConnected(ChainstateRole::NORMAL, kernel::MakeBlockInfo(pindex, &block));
7474
}
7575

7676
struct PreSelectInputs {

src/chain.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,12 @@ class CBlockIndex
276276
*
277277
* Does not imply the transactions are consensus-valid (ConnectTip might fail)
278278
* Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
279+
*
280+
* Note that this will be true for the snapshot base block, if one is loaded (and
281+
* all subsequent assumed-valid blocks) since its nChainTx value will have been set
282+
* manually based on the related AssumeutxoData entry.
283+
*
284+
* TODO: potentially change the name of this based on the fact above.
279285
*/
280286
bool HaveTxsDownloaded() const { return nChainTx != 0; }
281287

src/index/base.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,15 @@ BaseIndex::~BaseIndex()
7979

8080
bool BaseIndex::Init()
8181
{
82+
AssertLockNotHeld(cs_main);
83+
84+
// May need reset if index is being restarted.
85+
m_interrupt.reset();
86+
8287
// m_chainstate member gives indexing code access to node internals. It is
8388
// removed in followup https://github.com/bitcoin/bitcoin/pull/24230
84-
m_chainstate = &m_chain->context()->chainman->ActiveChainstate();
89+
m_chainstate = WITH_LOCK(::cs_main,
90+
return &m_chain->context()->chainman->GetChainstateForIndexing());
8591
// Register to validation interface before setting the 'm_synced' flag, so that
8692
// callbacks are not missed once m_synced is true.
8793
RegisterValidationInterface(this);
@@ -92,7 +98,8 @@ bool BaseIndex::Init()
9298
}
9399

94100
LOCK(cs_main);
95-
CChain& active_chain = m_chainstate->m_chain;
101+
CChain& index_chain = m_chainstate->m_chain;
102+
96103
if (locator.IsNull()) {
97104
SetBestBlockIndex(nullptr);
98105
} else {
@@ -114,7 +121,7 @@ bool BaseIndex::Init()
114121
// Note: this will latch to true immediately if the user starts up with an empty
115122
// datadir and an index enabled. If this is the case, indexation will happen solely
116123
// via `BlockConnected` signals until, possibly, the next restart.
117-
m_synced = start_block == active_chain.Tip();
124+
m_synced = start_block == index_chain.Tip();
118125
m_init = true;
119126
return true;
120127
}
@@ -143,6 +150,8 @@ void BaseIndex::ThreadSync()
143150
std::chrono::steady_clock::time_point last_locator_write_time{0s};
144151
while (true) {
145152
if (m_interrupt) {
153+
LogPrintf("%s: m_interrupt set; exiting ThreadSync\n", GetName());
154+
146155
SetBestBlockIndex(pindex);
147156
// No need to handle errors in Commit. If it fails, the error will be already be
148157
// logged. The best way to recover is to continue, as index cannot be corrupted by
@@ -250,8 +259,19 @@ bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_ti
250259
return true;
251260
}
252261

253-
void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
262+
void BaseIndex::BlockConnected(ChainstateRole role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
254263
{
264+
// Ignore events from the assumed-valid chain; we will process its blocks
265+
// (sequentially) after it is fully verified by the background chainstate. This
266+
// is to avoid any out-of-order indexing.
267+
//
268+
// TODO at some point we could parameterize whether a particular index can be
269+
// built out of order, but for now just do the conservative simple thing.
270+
if (role == ChainstateRole::ASSUMEDVALID) {
271+
return;
272+
}
273+
274+
// Ignore BlockConnected signals until we have fully indexed the chain.
255275
if (!m_synced) {
256276
return;
257277
}
@@ -296,8 +316,14 @@ void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const
296316
}
297317
}
298318

299-
void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
319+
void BaseIndex::ChainStateFlushed(ChainstateRole role, const CBlockLocator& locator)
300320
{
321+
// Ignore events from the assumed-valid chain; we will process its blocks
322+
// (sequentially) after it is fully verified by the background chainstate.
323+
if (role == ChainstateRole::ASSUMEDVALID) {
324+
return;
325+
}
326+
301327
if (!m_synced) {
302328
return;
303329
}

0 commit comments

Comments
 (0)