|
2 | 2 | // Distributed under the MIT software license, see the accompanying
|
3 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
4 | 4 | //
|
| 5 | +#include <chainparams.h> |
5 | 6 | #include <random.h>
|
6 | 7 | #include <uint256.h>
|
7 | 8 | #include <consensus/validation.h>
|
8 | 9 | #include <sync.h>
|
| 10 | +#include <rpc/blockchain.h> |
| 11 | +#include <test/util/chainstate.h> |
9 | 12 | #include <test/util/setup_common.h>
|
10 | 13 | #include <validation.h>
|
11 | 14 |
|
@@ -72,4 +75,77 @@ BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
|
72 | 75 | WITH_LOCK(::cs_main, manager.Unload());
|
73 | 76 | }
|
74 | 77 |
|
| 78 | +//! Test UpdateTip behavior for both active and background chainstates. |
| 79 | +//! |
| 80 | +//! When run on the background chainstate, UpdateTip should do a subset |
| 81 | +//! of what it does for the active chainstate. |
| 82 | +BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup) |
| 83 | +{ |
| 84 | + ChainstateManager& chainman = *Assert(m_node.chainman); |
| 85 | + uint256 curr_tip = ::g_best_block; |
| 86 | + |
| 87 | + // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can |
| 88 | + // be found. |
| 89 | + mineBlocks(10); |
| 90 | + |
| 91 | + // After adding some blocks to the tip, best block should have changed. |
| 92 | + BOOST_CHECK(::g_best_block != curr_tip); |
| 93 | + |
| 94 | + BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root)); |
| 95 | + |
| 96 | + // Ensure our active chain is the snapshot chainstate. |
| 97 | + BOOST_CHECK(chainman.IsSnapshotActive()); |
| 98 | + |
| 99 | + curr_tip = ::g_best_block; |
| 100 | + |
| 101 | + // Mine a new block on top of the activated snapshot chainstate. |
| 102 | + mineBlocks(1); // Defined in TestChain100Setup. |
| 103 | + |
| 104 | + // After adding some blocks to the snapshot tip, best block should have changed. |
| 105 | + BOOST_CHECK(::g_best_block != curr_tip); |
| 106 | + |
| 107 | + curr_tip = ::g_best_block; |
| 108 | + |
| 109 | + CChainState* background_cs; |
| 110 | + |
| 111 | + BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2); |
| 112 | + for (CChainState* cs : chainman.GetAll()) { |
| 113 | + if (cs != &chainman.ActiveChainstate()) { |
| 114 | + background_cs = cs; |
| 115 | + } |
| 116 | + } |
| 117 | + BOOST_CHECK(background_cs); |
| 118 | + |
| 119 | + // Create a block to append to the validation chain. |
| 120 | + std::vector<CMutableTransaction> noTxns; |
| 121 | + CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; |
| 122 | + CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, *background_cs); |
| 123 | + auto pblock = std::make_shared<const CBlock>(validation_block); |
| 124 | + BlockValidationState state; |
| 125 | + CBlockIndex* pindex = nullptr; |
| 126 | + const CChainParams& chainparams = Params(); |
| 127 | + bool newblock = false; |
| 128 | + |
| 129 | + // TODO: much of this is inlined from ProcessNewBlock(); just reuse PNB() |
| 130 | + // once it is changed to support multiple chainstates. |
| 131 | + { |
| 132 | + LOCK(::cs_main); |
| 133 | + bool checked = CheckBlock(*pblock, state, chainparams.GetConsensus()); |
| 134 | + BOOST_CHECK(checked); |
| 135 | + bool accepted = background_cs->AcceptBlock( |
| 136 | + pblock, state, &pindex, true, nullptr, &newblock); |
| 137 | + BOOST_CHECK(accepted); |
| 138 | + } |
| 139 | + // UpdateTip is called here |
| 140 | + bool block_added = background_cs->ActivateBestChain(state, pblock); |
| 141 | + |
| 142 | + // Ensure tip is as expected |
| 143 | + BOOST_CHECK_EQUAL(background_cs->m_chain.Tip()->GetBlockHash(), validation_block.GetHash()); |
| 144 | + |
| 145 | + // g_best_block should be unchanged after adding a block to the background |
| 146 | + // validation chain. |
| 147 | + BOOST_CHECK(block_added); |
| 148 | + BOOST_CHECK_EQUAL(curr_tip, ::g_best_block); |
| 149 | +} |
| 150 | + |
75 | 151 | BOOST_AUTO_TEST_SUITE_END()
|
0 commit comments