Page MenuHomePhabricator

No OneTemporary

diff --git a/src/chain.h b/src/chain.h
index 81b4fc20c9..df3f7ad640 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,427 +1,426 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CHAIN_H
#define BITCOIN_CHAIN_H
#include <arith_uint256.h>
#include <blockstatus.h>
#include <blockvalidity.h>
#include <consensus/params.h>
#include <flatfile.h>
-#include <pow.h>
#include <primitives/block.h>
#include <sync.h>
#include <tinyformat.h>
#include <uint256.h>
#include <unordered_map>
#include <vector>
/**
* Maximum amount of time that a block timestamp is allowed to exceed the
* current network-adjusted time before the block will be accepted.
*/
static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
/**
* Timestamp window used as a grace period by code that compares external
* timestamps (such as timestamps passed to RPCs, or wallet key creation times)
* to block timestamps. This should be set at least as high as
* MAX_FUTURE_BLOCK_TIME.
*/
static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
/**
* Maximum gap between node time and block time used
* for the "Catching up..." mode in GUI.
*
* Ref: https://github.com/bitcoin/bitcoin/pull/1026
*/
static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
/**
* The block chain is a tree shaped structure starting with the genesis block at
* the root, with each block potentially having multiple candidates to be the
* next block. A blockindex may have multiple pprev pointing to it, but at most
* one of them can be part of the currently active branch.
*/
class CBlockIndex {
public:
//! pointer to the hash of the block, if any. Memory is owned by this
//! CBlockIndex
const uint256 *phashBlock;
//! pointer to the index of the predecessor of this block
CBlockIndex *pprev;
//! pointer to the index of some further predecessor of this block
CBlockIndex *pskip;
//! height of the entry in the chain. The genesis block has height 0
int nHeight;
//! Which # file this block is stored in (blk?????.dat)
int nFile;
//! Byte offset within blk?????.dat where this block's data is stored
unsigned int nDataPos;
//! Byte offset within rev?????.dat where this block's undo data is stored
unsigned int nUndoPos;
//! (memory only) Total amount of work (expected number of hashes) in the
//! chain up to and including this block
arith_uint256 nChainWork;
//! Number of transactions in this block.
//! Note: in a potential headers-first mode, this number cannot be relied
//! upon
unsigned int nTx;
//! (memory only) Number of transactions in the chain up to and including
//! this block.
//! This value will be non-zero only if and only if transactions for this
//! block and all its parents are available. Change to 64-bit type when
//! necessary; won't happen before 2030
unsigned int nChainTx;
//! Verification status of this block. See enum BlockStatus
BlockStatus nStatus;
//! block header
int32_t nVersion;
uint256 hashMerkleRoot;
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
//! (memory only) Sequential id assigned to distinguish order in which
//! blocks are received.
int32_t nSequenceId;
//! (memory only) block header metadata
uint64_t nTimeReceived;
//! (memory only) Maximum nTime in the chain up to and including this block.
unsigned int nTimeMax;
void SetNull() {
phashBlock = nullptr;
pprev = nullptr;
pskip = nullptr;
nHeight = 0;
nFile = 0;
nDataPos = 0;
nUndoPos = 0;
nChainWork = arith_uint256();
nTx = 0;
nChainTx = 0;
nStatus = BlockStatus();
nSequenceId = 0;
nTimeMax = 0;
nVersion = 0;
hashMerkleRoot = uint256();
nTime = 0;
nTimeReceived = 0;
nBits = 0;
nNonce = 0;
}
CBlockIndex() { SetNull(); }
explicit CBlockIndex(const CBlockHeader &block) {
SetNull();
nVersion = block.nVersion;
hashMerkleRoot = block.hashMerkleRoot;
nTime = block.nTime;
nTimeReceived = 0;
nBits = block.nBits;
nNonce = block.nNonce;
}
FlatFilePos GetBlockPos() const {
FlatFilePos ret;
if (nStatus.hasData()) {
ret.nFile = nFile;
ret.nPos = nDataPos;
}
return ret;
}
FlatFilePos GetUndoPos() const {
FlatFilePos ret;
if (nStatus.hasUndo()) {
ret.nFile = nFile;
ret.nPos = nUndoPos;
}
return ret;
}
CBlockHeader GetBlockHeader() const {
CBlockHeader block;
block.nVersion = nVersion;
if (pprev) {
block.hashPrevBlock = pprev->GetBlockHash();
}
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
uint256 GetBlockHash() const { return *phashBlock; }
int64_t GetBlockTime() const { return int64_t(nTime); }
int64_t GetBlockTimeMax() const { return int64_t(nTimeMax); }
int64_t GetHeaderReceivedTime() const { return nTimeReceived; }
int64_t GetReceivedTimeDiff() const {
return GetHeaderReceivedTime() - GetBlockTime();
}
static constexpr int nMedianTimeSpan = 11;
int64_t GetMedianTimePast() const {
int64_t pmedian[nMedianTimeSpan];
int64_t *pbegin = &pmedian[nMedianTimeSpan];
int64_t *pend = &pmedian[nMedianTimeSpan];
const CBlockIndex *pindex = this;
for (int i = 0; i < nMedianTimeSpan && pindex;
i++, pindex = pindex->pprev) {
*(--pbegin) = pindex->GetBlockTime();
}
std::sort(pbegin, pend);
return pbegin[(pend - pbegin) / 2];
}
std::string ToString() const {
return strprintf(
"CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev,
nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString());
}
//! Check whether this block index entry is valid up to the passed validity
//! level.
bool IsValid(enum BlockValidity nUpTo = BlockValidity::TRANSACTIONS) const {
return nStatus.isValid(nUpTo);
}
//! Raise the validity level of this block index entry.
//! Returns true if the validity was changed.
bool RaiseValidity(enum BlockValidity nUpTo) {
// Only validity flags allowed.
if (nStatus.isInvalid()) {
return false;
}
if (nStatus.getValidity() >= nUpTo) {
return false;
}
nStatus = nStatus.withValidity(nUpTo);
return true;
}
//! Build the skiplist pointer for this entry.
void BuildSkip();
//! Efficiently find an ancestor of this block.
CBlockIndex *GetAncestor(int height);
const CBlockIndex *GetAncestor(int height) const;
};
/**
* Maintain a map of CBlockIndex for all known headers.
*/
struct BlockHasher {
size_t operator()(const uint256 &hash) const { return hash.GetCheapHash(); }
};
typedef std::unordered_map<uint256, CBlockIndex *, BlockHasher> BlockMap;
extern BlockMap &mapBlockIndex;
extern CCriticalSection cs_main;
inline CBlockIndex *LookupBlockIndex(const uint256 &hash) {
AssertLockHeld(cs_main);
BlockMap::const_iterator it = mapBlockIndex.find(hash);
return it == mapBlockIndex.end() ? nullptr : it->second;
}
arith_uint256 GetBlockProof(const CBlockIndex &block);
/**
* Return the time it would take to redo the work difference between from and
* to, assuming the current hashrate corresponds to the difficulty at tip, in
* seconds.
*/
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to,
const CBlockIndex &from,
const CBlockIndex &tip,
const Consensus::Params &);
/**
* Find the forking point between two chain tips.
*/
const CBlockIndex *LastCommonAncestor(const CBlockIndex *pa,
const CBlockIndex *pb);
/**
* Check if two block index are on the same fork.
*/
bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb);
/** Used to marshal pointers into hashes for db storage. */
class CDiskBlockIndex : public CBlockIndex {
public:
uint256 hashPrev;
CDiskBlockIndex() { hashPrev = uint256(); }
explicit CDiskBlockIndex(const CBlockIndex *pindex) : CBlockIndex(*pindex) {
hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream &s, Operation ser_action) {
int _nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(VARINT(_nVersion));
}
READWRITE(VARINT(nHeight));
READWRITE(nStatus);
READWRITE(VARINT(nTx));
if (nStatus.hasData() || nStatus.hasUndo()) {
READWRITE(VARINT(nFile));
}
if (nStatus.hasData()) {
READWRITE(VARINT(nDataPos));
}
if (nStatus.hasUndo()) {
READWRITE(VARINT(nUndoPos));
}
// block header
READWRITE(this->nVersion);
READWRITE(hashPrev);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
}
uint256 GetBlockHash() const {
CBlockHeader block;
block.nVersion = nVersion;
block.hashPrevBlock = hashPrev;
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block.GetHash();
}
std::string ToString() const {
std::string str = "CDiskBlockIndex(";
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s)",
GetBlockHash().ToString(), hashPrev.ToString());
return str;
}
};
/**
* An in-memory indexed chain of blocks.
*/
class CChain {
private:
std::vector<CBlockIndex *> vChain;
public:
/**
* Returns the index entry for the genesis block of this chain, or nullptr
* if none.
*/
CBlockIndex *Genesis() const {
return vChain.size() > 0 ? vChain[0] : nullptr;
}
/**
* Returns the index entry for the tip of this chain, or nullptr if none.
*/
CBlockIndex *Tip() const {
return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;
}
/**
* Returns the index entry at a particular height in this chain, or nullptr
* if no such height exists.
*/
CBlockIndex *operator[](int nHeight) const {
if (nHeight < 0 || nHeight >= (int)vChain.size()) {
return nullptr;
}
return vChain[nHeight];
}
/** Compare two chains efficiently. */
friend bool operator==(const CChain &a, const CChain &b) {
return a.vChain.size() == b.vChain.size() &&
a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
}
/** Efficiently check whether a block is present in this chain. */
bool Contains(const CBlockIndex *pindex) const {
return (*this)[pindex->nHeight] == pindex;
}
/**
* Find the successor of a block in this chain, or nullptr if the given
* index is not found or is the tip.
*/
CBlockIndex *Next(const CBlockIndex *pindex) const {
if (!Contains(pindex)) {
return nullptr;
}
return (*this)[pindex->nHeight + 1];
}
/**
* Return the maximal height in the chain. Is equal to chain.Tip() ?
* chain.Tip()->nHeight : -1.
*/
int Height() const { return vChain.size() - 1; }
/** Set/initialize a chain with a given tip. */
void SetTip(CBlockIndex *pindex);
/**
* Return a CBlockLocator that refers to a block in this chain (by default
* the tip).
*/
CBlockLocator GetLocator(const CBlockIndex *pindex = nullptr) const;
/**
* Find the last common block between this chain and a block index entry.
*/
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
/**
* Find the earliest block with timestamp equal or greater than the given.
*/
CBlockIndex *FindEarliestAtLeast(int64_t nTime) const;
};
#endif // BITCOIN_CHAIN_H
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 4c4c08865d..a9068ba531 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -1,207 +1,208 @@
// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/test_bitcoin.h>
#include <chain.h>
#include <chainparams.h>
#include <config.h>
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <crypto/sha256.h>
#include <fs.h>
#include <key.h>
#include <logging.h>
#include <miner.h>
#include <net_processing.h>
#include <noui.h>
+#include <pow.h>
#include <pubkey.h>
#include <random.h>
#include <rpc/register.h>
#include <rpc/server.h>
#include <script/scriptcache.h>
#include <script/sigcache.h>
#include <txdb.h>
#include <txmempool.h>
#include <ui_interface.h>
#include <validation.h>
#include <memory>
FastRandomContext g_insecure_rand_ctx;
std::ostream &operator<<(std::ostream &os, const uint256 &num) {
os << num.ToString();
return os;
}
BasicTestingSetup::BasicTestingSetup(const std::string &chainName)
: m_path_root(fs::temp_directory_path() / "test_bitcoin" /
strprintf("%lu_%i", static_cast<unsigned long>(GetTime()),
int(InsecureRandRange(1 << 30)))) {
SHA256AutoDetect();
RandomInit();
ECC_Start();
SetupEnvironment();
SetupNetworking();
InitSignatureCache();
InitScriptExecutionCache();
// Don't want to write to debug.log file.
GetLogger().m_print_to_file = false;
fCheckBlockIndex = true;
SelectParams(chainName);
noui_connect();
}
BasicTestingSetup::~BasicTestingSetup() {
fs::remove_all(m_path_root);
ECC_Stop();
}
fs::path BasicTestingSetup::SetDataDir(const std::string &name) {
fs::path ret = m_path_root / name;
fs::create_directories(ret);
gArgs.ForceSetArg("-datadir", ret.string());
return ret;
}
TestingSetup::TestingSetup(const std::string &chainName)
: BasicTestingSetup(chainName) {
SetDataDir("tempdir");
const Config &config = GetConfig();
const CChainParams &chainparams = config.GetChainParams();
// Ideally we'd move all the RPC tests to the functional testing framework
// instead of unit tests, but for now we need these here.
RPCServer rpcServer;
RegisterAllRPCCommands(config, rpcServer, tableRPC);
/**
* RPC does not come out of the warmup state on its own. Normally, this is
* handled in bitcoind's init path, but unit tests do not trigger this
* codepath, so we call it explicitly as part of setup.
*/
std::string rpcWarmupStatus;
if (RPCIsInWarmup(&rpcWarmupStatus)) {
SetRPCWarmupFinished();
}
ClearDatadirCache();
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
threadGroup.create_thread(
boost::bind(&CScheduler::serviceQueue, &scheduler));
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
g_mempool.setSanityCheck(1.0);
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
if (!LoadGenesisBlock(chainparams)) {
throw std::runtime_error("LoadGenesisBlock failed.");
}
{
CValidationState state;
if (!ActivateBestChain(config, state)) {
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)",
FormatStateMessage(state)));
}
}
nScriptCheckThreads = 3;
for (int i = 0; i < nScriptCheckThreads - 1; i++) {
threadGroup.create_thread(&ThreadScriptCheck);
}
// Deterministic randomness for tests.
g_connman = std::make_unique<CConnman>(config, 0x1337, 0x1337);
}
TestingSetup::~TestingSetup() {
threadGroup.interrupt_all();
threadGroup.join_all();
GetMainSignals().FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler();
g_connman.reset();
UnloadBlockIndex();
pcoinsTip.reset();
pcoinsdbview.reset();
pblocktree.reset();
}
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);
m_coinbase_txns.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 Config &config = GetConfig();
std::unique_ptr<CBlockTemplate> pblocktemplate =
BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey);
CBlock &block = pblocktemplate->block;
// Replace mempool-selected txns with just coinbase plus passed-in txns:
block.vtx.resize(1);
for (const CMutableTransaction &tx : txns) {
block.vtx.push_back(MakeTransactionRef(tx));
}
// Order transactions by canonical order
std::sort(std::begin(block.vtx) + 1, std::end(block.vtx),
[](const std::shared_ptr<const CTransaction> &txa,
const std::shared_ptr<const CTransaction> &txb) -> bool {
return txa->GetId() < txb->GetId();
});
// IncrementExtraNonce creates a valid coinbase and merkleRoot
{
LOCK(cs_main);
unsigned int extraNonce = 0;
IncrementExtraNonce(config, &block, chainActive.Tip(), extraNonce);
}
const Consensus::Params &params = config.GetChainParams().GetConsensus();
while (!CheckProofOfWork(block.GetHash(), block.nBits, params)) {
++block.nNonce;
}
std::shared_ptr<const CBlock> shared_pblock =
std::make_shared<const CBlock>(block);
ProcessNewBlock(config, shared_pblock, true, nullptr);
CBlock result = block;
return result;
}
TestChain100Setup::~TestChain100Setup() {}
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction &tx,
CTxMemPool *pool) {
return FromTx(MakeTransactionRef(tx), pool);
}
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef &tx,
CTxMemPool *pool) {
// Hack to assume either it's completely dependent on other mempool txs or
// not at all.
Amount inChainValue =
pool && pool->HasNoInputsOf(*tx) ? tx->GetValueOut() : Amount::zero();
return CTxMemPoolEntry(tx, nFee, nTime, dPriority, nHeight, inChainValue,
spendsCoinbase, sigOpCost, lp);
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, May 13, 01:47 (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5777067
Default Alt Text
(19 KB)

Event Timeline