Line data Source code
1 : // Copyright (c) 2011-2013 The Bitcoin Core developers
2 : // Copyright (c) 2017-2022 The PIVX Core developers
3 : // Distributed under the MIT/X11 software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #define BOOST_TEST_MODULE Pivx Test Suite
7 :
8 : #include "test/test_pivx.h"
9 :
10 : #include "blockassembler.h"
11 : #include "consensus/merkle.h"
12 : #include "bls/bls_wrapper.h"
13 : #include "guiinterface.h"
14 : #include "evo/deterministicmns.h"
15 : #include "evo/evodb.h"
16 : #include "evo/evonotificationinterface.h"
17 : #include "llmq/quorums_init.h"
18 : #include "miner.h"
19 : #include "net_processing.h"
20 : #include "rpc/server.h"
21 : #include "rpc/register.h"
22 : #include "pow.h"
23 : #include "script/sigcache.h"
24 : #include "sporkdb.h"
25 : #include "streams.h"
26 : #include "txmempool.h"
27 : #include "validation.h"
28 :
29 : #include <boost/test/unit_test.hpp>
30 :
31 : std::unique_ptr<CConnman> g_connman;
32 :
33 : CClientUIInterface uiInterface; // Declared but not defined in guiinterface.h
34 :
35 : FastRandomContext g_insecure_rand_ctx;
36 : /** Random context to get unique temp data dirs. Separate from g_insecure_rand_ctx, which can be seeded from a const env var */
37 : static FastRandomContext g_insecure_rand_ctx_temp_path;
38 :
39 : /** Return the unsigned from the environment var if available, otherwise 0 */
40 84 : static uint256 GetUintFromEnv(const std::string& env_name)
41 : {
42 84 : const char* num = std::getenv(env_name.c_str());
43 84 : if (!num) return {};
44 0 : return uint256S(num);
45 : }
46 :
47 479 : void Seed(FastRandomContext& ctx)
48 : {
49 : // Should be enough to get the seed once for the process
50 563 : static uint256 seed{};
51 479 : static const std::string RANDOM_CTX_SEED{"RANDOM_CTX_SEED"};
52 958 : if (seed.IsNull()) seed = GetUintFromEnv(RANDOM_CTX_SEED);
53 958 : if (seed.IsNull()) seed = GetRandHash();
54 479 : LogPrintf("%s: Setting random seed for current tests to %s=%s\n", __func__, RANDOM_CTX_SEED, seed.GetHex());
55 479 : ctx = FastRandomContext(seed);
56 479 : }
57 :
58 : extern bool fPrintToConsole;
59 : extern void noui_connect();
60 :
61 0 : std::ostream& operator<<(std::ostream& os, const uint256& num)
62 : {
63 0 : os << num.ToString();
64 0 : return os;
65 : }
66 :
67 415 : BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
68 1660 : : m_path_root{fs::temp_directory_path() / "test_pivx" / std::to_string(g_insecure_rand_ctx_temp_path.rand32())}
69 : {
70 415 : ECC_Start();
71 415 : BLSInit();
72 415 : SetupEnvironment();
73 415 : InitSignatureCache();
74 415 : fCheckBlockIndex = true;
75 415 : SelectParams(chainName);
76 415 : SeedInsecureRand();
77 415 : evoDb.reset(new CEvoDB(1 << 20, true, true));
78 415 : deterministicMNManager.reset(new CDeterministicMNManager(*evoDb));
79 415 : }
80 :
81 828 : BasicTestingSetup::~BasicTestingSetup()
82 : {
83 414 : fs::remove_all(m_path_root);
84 414 : ECC_Stop();
85 414 : deterministicMNManager.reset();
86 414 : evoDb.reset();
87 414 : }
88 :
89 130 : fs::path BasicTestingSetup::SetDataDir(const std::string& name)
90 : {
91 130 : fs::path ret = m_path_root / name;
92 130 : fs::create_directories(ret);
93 130 : gArgs.ForceSetArg("-datadir", ret.string());
94 130 : return ret;
95 : }
96 :
97 118 : TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
98 : {
99 236 : SetDataDir("tempdir");
100 118 : ClearDatadirCache();
101 :
102 : // Start the lightweight task scheduler thread
103 118 : CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
104 118 : threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
105 :
106 : // Note that because we don't bother running a scheduler thread here,
107 : // callbacks via CValidationInterface are unreliable, but that's OK,
108 : // our unit tests aren't testing multiple parts of the code at once.
109 118 : GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
110 :
111 236 : g_connman = std::make_unique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
112 118 : connman = g_connman.get();
113 :
114 : // Register EvoNotificationInterface
115 118 : pEvoNotificationInterface = new EvoNotificationInterface();
116 118 : RegisterValidationInterface(pEvoNotificationInterface);
117 :
118 : // Ideally we'd move all the RPC tests to the functional testing framework
119 : // instead of unit tests, but for now we need these here.
120 118 : RegisterAllCoreRPCCommands(tableRPC);
121 118 : zerocoinDB.reset(new CZerocoinDB(0, true));
122 118 : pSporkDB.reset(new CSporkDB(0, true));
123 118 : pblocktree.reset(new CBlockTreeDB(1 << 20, true));
124 118 : pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
125 118 : pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
126 118 : llmq::InitLLMQSystem(*evoDb, &scheduler, true);
127 118 : if (!LoadGenesisBlock()) {
128 0 : throw std::runtime_error("Error initializing block database");
129 : }
130 118 : {
131 236 : CValidationState state;
132 118 : bool ok = ActivateBestChain(state);
133 236 : BOOST_CHECK(ok);
134 : }
135 118 : nScriptCheckThreads = 3;
136 354 : for (int i=0; i < nScriptCheckThreads-1; i++)
137 236 : threadGroup.create_thread(&ThreadScriptCheck);
138 236 : peerLogic.reset(new PeerLogicValidation(connman));
139 118 : }
140 :
141 118 : TestingSetup::~TestingSetup()
142 : {
143 118 : scheduler.stop();
144 118 : llmq::InterruptLLMQSystem();
145 118 : threadGroup.interrupt_all();
146 118 : threadGroup.join_all();
147 118 : GetMainSignals().FlushBackgroundCallbacks();
148 118 : UnregisterAllValidationInterfaces();
149 118 : GetMainSignals().UnregisterBackgroundSignalScheduler();
150 118 : g_connman.reset();
151 118 : peerLogic.reset();
152 118 : UnloadBlockIndex();
153 118 : delete pEvoNotificationInterface;
154 118 : pcoinsTip.reset();
155 118 : pcoinsdbview.reset();
156 118 : pblocktree.reset();
157 118 : zerocoinDB.reset();
158 118 : pSporkDB.reset();
159 118 : llmq::DestroyLLMQSystem();
160 118 : }
161 :
162 : // Test chain only available on regtest
163 11 : TestChainSetup::TestChainSetup(int blockCount) : TestingSetup(CBaseChainParams::REGTEST)
164 : {
165 : // if blockCount is over PoS start, delay it to 100 blocks after.
166 11 : if (blockCount > Params().GetConsensus().vUpgrades[Consensus::UPGRADE_POS].nActivationHeight) {
167 2 : UpdateNetworkUpgradeParameters(Consensus::UPGRADE_POS, blockCount + 100);
168 2 : UpdateNetworkUpgradeParameters(Consensus::UPGRADE_V3_4, blockCount + 101);
169 : }
170 :
171 : // Generate a blockCount-block chain:
172 11 : coinbaseKey.MakeNewKey(true);
173 22 : CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
174 1511 : for (int i = 0; i < blockCount; i++)
175 : {
176 3000 : std::vector<CMutableTransaction> noTxns;
177 3000 : CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
178 1500 : coinbaseTxns.push_back(*b.vtx[0]);
179 : }
180 11 : }
181 :
182 : // Create a new block with coinbase paying to scriptPubKey, and try to add it to the current chain.
183 : // Include given transactions, and, if fNoMempoolTx=true, remove transactions coming from the mempool.
184 2407 : CBlock TestChainSetup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey, bool fNoMempoolTx)
185 : {
186 2407 : CBlock block = CreateBlock(txns, scriptPubKey, fNoMempoolTx);
187 2407 : ProcessNewBlock(std::make_shared<const CBlock>(block), nullptr);
188 2407 : return block;
189 : }
190 :
191 884 : CBlock TestChainSetup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)
192 : {
193 1768 : CScript scriptPubKey = CScript() << ToByteVector(scriptKey.GetPubKey()) << OP_CHECKSIG;
194 1768 : return CreateAndProcessBlock(txns, scriptPubKey);
195 : }
196 :
197 2435 : CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns,
198 : const CScript& scriptPubKey,
199 : bool fNoMempoolTx,
200 : bool fTestBlockValidity,
201 : bool fIncludeQfc,
202 : CBlockIndex* customPrevBlock)
203 : {
204 2435 : std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
205 : Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey,
206 : nullptr, // wallet
207 : false, // fProofOfStake
208 : nullptr, // availableCoins
209 : fNoMempoolTx,
210 : fTestBlockValidity,
211 : customPrevBlock,
212 : true,
213 2435 : fIncludeQfc);
214 4870 : std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
215 :
216 : // Add passed-in txns:
217 2498 : for (const CMutableTransaction& tx : txns) {
218 63 : pblock->vtx.push_back(MakeTransactionRef(tx));
219 : }
220 :
221 4869 : const int nHeight = (customPrevBlock != nullptr ? customPrevBlock->nHeight + 1
222 4868 : : WITH_LOCK(cs_main, return chainActive.Height()) + 1);
223 :
224 : // Re-compute sapling root
225 2435 : pblock->hashFinalSaplingRoot = CalculateSaplingTreeRoot(pblock.get(), nHeight, Params());
226 :
227 : // Find valid PoW
228 2435 : assert(SolveBlock(pblock, nHeight));
229 4870 : return *pblock;
230 : }
231 :
232 11 : CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey,
233 : bool fTestBlockValidity)
234 : {
235 22 : CScript scriptPubKey = CScript() << ToByteVector(scriptKey.GetPubKey()) << OP_CHECKSIG;
236 22 : return CreateBlock(txns, scriptPubKey, fTestBlockValidity);
237 : }
238 :
239 241 : std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock)
240 : {
241 241 : pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
242 522 : while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits)) { ++(pblock->nNonce); }
243 241 : return pblock;
244 : }
245 :
246 22 : TestChainSetup::~TestChainSetup()
247 : {
248 11 : }
249 :
250 19882 : CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction& tx)
251 : {
252 39764 : CTransaction txn(tx);
253 39764 : return FromTx(txn);
254 : }
255 :
256 19882 : CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction& txn)
257 : {
258 59646 : return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight,
259 39764 : spendsCoinbaseOrCoinstake, sigOpCount);
260 : }
261 :
262 0 : [[noreturn]] void Shutdown(void* parg)
263 : {
264 0 : std::exit(0);
265 : }
266 :
267 0 : [[noreturn]] void StartShutdown()
268 : {
269 0 : std::exit(0);
270 : }
271 :
272 3159 : bool ShutdownRequested()
273 : {
274 3159 : return false;
275 : }
|