mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-02 03:31:09 +00:00
There are only a few uses of `insecure_random` outside the tests. This PR replaces uses of insecure_random (and its accompanying global state) in the core code with an FastRandomContext that is automatically seeded on creation. This is meant to be used for inner loops. The FastRandomContext can be in the outer scope, or the class itself, then rand32() is used inside the loop. Useful e.g. for pushing addresses in CNode or the fee rounding, or randomization for coin selection. As a context is created per purpose, thus it gets rid of cross-thread unprotected shared usage of a single set of globals, this should also get rid of the potential race conditions. - I'd say TxMempool::check is not called enough to warrant using a special fast random context, this is switched to GetRand() (open for discussion...) - The use of `insecure_rand` in ConnectThroughProxy has been replaced by an atomic integer counter. The only goal here is to have a different credentials pair for each connection to go on a different Tor circuit, it does not need to be random nor unpredictable. - To avoid having a FastRandomContext on every CNode, the context is passed into PushAddress as appropriate. There remains an insecure_random for test usage in `test_random.h`.
168 lines
5.1 KiB
C++
168 lines
5.1 KiB
C++
// Copyright (c) 2011-2015 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#define BOOST_TEST_MODULE Bitcoin Test Suite
|
|
|
|
#include "test_bitcoin.h"
|
|
|
|
#include "chainparams.h"
|
|
#include "consensus/consensus.h"
|
|
#include "consensus/validation.h"
|
|
#include "key.h"
|
|
#include "main.h"
|
|
#include "miner.h"
|
|
#include "pubkey.h"
|
|
#include "random.h"
|
|
#include "txdb.h"
|
|
#include "txmempool.h"
|
|
#include "ui_interface.h"
|
|
#include "rpc/server.h"
|
|
#include "rpc/register.h"
|
|
|
|
#include "test/testutil.h"
|
|
|
|
#include <boost/filesystem.hpp>
|
|
#include <boost/test/unit_test.hpp>
|
|
#include <boost/thread.hpp>
|
|
|
|
std::unique_ptr<CConnman> g_connman;
|
|
FastRandomContext insecure_rand_ctx(true);
|
|
|
|
extern bool fPrintToConsole;
|
|
extern void noui_connect();
|
|
|
|
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
|
{
|
|
ECC_Start();
|
|
SetupEnvironment();
|
|
SetupNetworking();
|
|
fPrintToDebugLog = false; // don't want to write to debug.log file
|
|
fCheckBlockIndex = true;
|
|
SelectParams(chainName);
|
|
noui_connect();
|
|
}
|
|
|
|
BasicTestingSetup::~BasicTestingSetup()
|
|
{
|
|
ECC_Stop();
|
|
g_connman.reset();
|
|
}
|
|
|
|
TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
|
|
{
|
|
const CChainParams& chainparams = Params();
|
|
// Ideally we'd move all the RPC tests to the functional testing framework
|
|
// instead of unit tests, but for now we need these here.
|
|
|
|
RegisterAllCoreRPCCommands(tableRPC);
|
|
ClearDatadirCache();
|
|
pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
|
|
boost::filesystem::create_directories(pathTemp);
|
|
mapArgs["-datadir"] = pathTemp.string();
|
|
mempool.setSanityCheck(1.0);
|
|
pblocktree = new CBlockTreeDB(1 << 20, true);
|
|
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
|
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
|
InitBlockIndex(chainparams);
|
|
{
|
|
CValidationState state;
|
|
bool ok = ActivateBestChain(state, chainparams);
|
|
BOOST_CHECK(ok);
|
|
}
|
|
nScriptCheckThreads = 3;
|
|
for (int i=0; i < nScriptCheckThreads-1; i++)
|
|
threadGroup.create_thread(&ThreadScriptCheck);
|
|
g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
|
|
connman = g_connman.get();
|
|
RegisterNodeSignals(GetNodeSignals());
|
|
}
|
|
|
|
TestingSetup::~TestingSetup()
|
|
{
|
|
UnregisterNodeSignals(GetNodeSignals());
|
|
threadGroup.interrupt_all();
|
|
threadGroup.join_all();
|
|
UnloadBlockIndex();
|
|
delete pcoinsTip;
|
|
delete pcoinsdbview;
|
|
delete pblocktree;
|
|
boost::filesystem::remove_all(pathTemp);
|
|
}
|
|
|
|
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
|
|
{
|
|
// Generate a 100-block chain:
|
|
coinbaseKey.MakeNewKey(true);
|
|
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
|
|
for (int i = 0; i < COINBASE_MATURITY; i++)
|
|
{
|
|
std::vector<CMutableTransaction> noTxns;
|
|
CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
|
|
coinbaseTxns.push_back(b.vtx[0]);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a new block with just given transactions, coinbase paying to
|
|
// scriptPubKey, and try to add it to the current chain.
|
|
//
|
|
CBlock
|
|
TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
|
|
{
|
|
const CChainParams& chainparams = Params();
|
|
CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
|
|
CBlock& block = pblocktemplate->block;
|
|
|
|
// Replace mempool-selected txns with just coinbase plus passed-in txns:
|
|
block.vtx.resize(1);
|
|
BOOST_FOREACH(const CMutableTransaction& tx, txns)
|
|
block.vtx.push_back(tx);
|
|
// IncrementExtraNonce creates a valid coinbase and merkleRoot
|
|
unsigned int extraNonce = 0;
|
|
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
|
|
|
|
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
|
|
|
|
CValidationState state;
|
|
ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, connman);
|
|
|
|
CBlock result = block;
|
|
delete pblocktemplate;
|
|
return result;
|
|
}
|
|
|
|
TestChain100Setup::~TestChain100Setup()
|
|
{
|
|
}
|
|
|
|
|
|
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
|
|
CTransaction txn(tx);
|
|
return FromTx(txn, pool);
|
|
}
|
|
|
|
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CTransaction &txn, CTxMemPool *pool) {
|
|
bool hasNoDependencies = pool ? pool->HasNoInputsOf(txn) : hadNoDependencies;
|
|
// Hack to assume either its completely dependent on other mempool txs or not at all
|
|
CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0;
|
|
|
|
return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
|
|
hasNoDependencies, inChainValue, spendsCoinbase, sigOpCost, lp);
|
|
}
|
|
|
|
void Shutdown(void* parg)
|
|
{
|
|
exit(0);
|
|
}
|
|
|
|
void StartShutdown()
|
|
{
|
|
exit(0);
|
|
}
|
|
|
|
bool ShutdownRequested()
|
|
{
|
|
return false;
|
|
}
|