365 lines
11 KiB
C++
365 lines
11 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2012 The Bitcoin developers
|
|
// Copyright (c) 2011-2013 PPCoin developers
|
|
// Copyright (c) 2013 Primecoin developers
|
|
// Distributed under conditional MIT/X11 software license,
|
|
// see the accompanying file COPYING
|
|
#ifndef BITCOIN_MAIN_H
|
|
#define BITCOIN_MAIN_H
|
|
|
|
#include "bignum.h"
|
|
#include "sync.h"
|
|
#include "hash.h"
|
|
|
|
#include <list>
|
|
|
|
class CBlockIndex;
|
|
struct CBlockIndexWorkComparator;
|
|
|
|
/** The maximum allowed size for a serialized block, in bytes (network rule) */
|
|
static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
|
/** The maximum size for mined blocks */
|
|
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
|
|
/** The maximum size for transactions we're willing to relay/mine */
|
|
static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5;
|
|
/** The maximum allowed number of signature check operations in a block (network rule) */
|
|
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
|
|
/** The maximum number of orphan transactions kept in memory */
|
|
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
|
|
/** The maximum number of entries in an 'inv' protocol message */
|
|
static const unsigned int MAX_INV_SZ = 50000;
|
|
/** The maximum size of a blk?????.dat file (since 0.8) */
|
|
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
|
|
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
|
|
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
|
|
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
|
|
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
|
|
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
|
|
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
|
|
/** No amount larger than this (in satoshi) is valid */
|
|
static const int64 MAX_MONEY = 2000000000u * COIN;
|
|
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
|
static const int64 MIN_TX_FEE = CENT;
|
|
static const int64 MIN_RELAY_TX_FEE = MIN_TX_FEE;
|
|
static const int64 MIN_TXOUT_AMOUNT = MIN_TX_FEE;
|
|
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
|
|
static const int COINBASE_MATURITY = 3000;
|
|
/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */
|
|
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
|
/** Maximum number of script-checking threads allowed */
|
|
static const int MAX_SCRIPTCHECK_THREADS = 16;
|
|
// Settings
|
|
|
|
class CBlockHeader
|
|
{
|
|
public:
|
|
// header
|
|
static const int CURRENT_VERSION=2;
|
|
int nVersion;
|
|
uint256 hashPrevBlock;
|
|
uint256 hashMerkleRoot;
|
|
unsigned int nTime;
|
|
unsigned int nBits; // Primecoin: prime chain target, see prime.cpp
|
|
unsigned int nNonce;
|
|
|
|
// Primecoin: proof-of-work certificate
|
|
// Multiplier to block hash to derive the probable prime chain (k=0, 1, ...)
|
|
// Cunningham Chain of first kind: hash * multiplier * 2**k - 1
|
|
// Cunningham Chain of second kind: hash * multiplier * 2**k + 1
|
|
// BiTwin Chain: hash * multiplier * 2**k +/- 1
|
|
CBigNum bnPrimeChainMultiplier;
|
|
|
|
CBlockHeader()
|
|
{
|
|
SetNull();
|
|
}
|
|
|
|
void SetNull()
|
|
{
|
|
nVersion = CBlockHeader::CURRENT_VERSION;
|
|
hashPrevBlock = 0;
|
|
hashMerkleRoot = 0;
|
|
nTime = 0;
|
|
nBits = 0;
|
|
nNonce = 0;
|
|
bnPrimeChainMultiplier = 0;
|
|
}
|
|
|
|
bool IsNull() const
|
|
{
|
|
return (nBits == 0);
|
|
}
|
|
|
|
// Primecoin: header hash does not include prime certificate
|
|
uint256 GetHeaderHash() const
|
|
{
|
|
return Hash(BEGIN(nVersion), END(nNonce));
|
|
}
|
|
|
|
int64 GetBlockTime() const
|
|
{
|
|
return (int64)nTime;
|
|
}
|
|
|
|
void UpdateTime(const CBlockIndex* pindexPrev);
|
|
};
|
|
|
|
class CBlock : public CBlockHeader
|
|
{
|
|
public:
|
|
unsigned int nPrimeChainType; // primecoin: chain type (memory-only)
|
|
unsigned int nPrimeChainLength; // primecoin: chain length (memory-only)
|
|
|
|
CBlock()
|
|
{
|
|
SetNull();
|
|
}
|
|
|
|
CBlock(const CBlockHeader &header)
|
|
{
|
|
SetNull();
|
|
*((CBlockHeader*)this) = header;
|
|
}
|
|
|
|
void SetNull()
|
|
{
|
|
CBlockHeader::SetNull();
|
|
nPrimeChainType = 0;
|
|
nPrimeChainLength = 0;
|
|
}
|
|
|
|
CBlockHeader GetBlockHeader() const
|
|
{
|
|
CBlockHeader block;
|
|
block.nVersion = nVersion;
|
|
block.hashPrevBlock = hashPrevBlock;
|
|
block.hashMerkleRoot = hashMerkleRoot;
|
|
block.nTime = nTime;
|
|
block.nBits = nBits;
|
|
block.nNonce = nNonce;
|
|
return block;
|
|
}
|
|
|
|
void print() const
|
|
{
|
|
printf("CBlock(hashBlockHeader=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u)\n",
|
|
GetHeaderHash().ToString().c_str(),
|
|
nVersion,
|
|
hashPrevBlock.ToString().c_str(),
|
|
hashMerkleRoot.ToString().c_str(),
|
|
nTime, nBits, nNonce);
|
|
printf("\n");
|
|
}
|
|
};
|
|
|
|
class CBlockIndex;
|
|
extern CBlockIndex *pindexBest;
|
|
|
|
/** 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. pprev and pnext link a path through the
|
|
* main/longest chain. A blockindex may have multiple pprev pointing back
|
|
* to it, but pnext will only point forward to the longest branch, or will
|
|
* be null if the block is not part of the longest chain.
|
|
*/
|
|
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;
|
|
|
|
// (memory only) pointer to the index of the *active* successor of this block
|
|
CBlockIndex* pnext;
|
|
|
|
// 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
|
|
uint256 nChainWork;
|
|
unsigned int nWorkTransition; // primecoin: work transition ratio (memory-only)
|
|
|
|
unsigned int nPrimeChainType; // primecoin: chain type
|
|
unsigned int nPrimeChainLength; // primecoin: chain length
|
|
int64 nMoneySupply; // primecoin: money supply
|
|
|
|
// 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
|
|
unsigned int nChainTx; // change to 64-bit type when necessary; won't happen before 2030
|
|
|
|
// Verification status of this block. See enum BlockStatus
|
|
unsigned int nStatus;
|
|
|
|
// block header
|
|
int nVersion;
|
|
uint256 hashMerkleRoot;
|
|
unsigned int nTime;
|
|
unsigned int nBits;
|
|
unsigned int nNonce;
|
|
|
|
|
|
CBlockIndex()
|
|
{
|
|
phashBlock = NULL;
|
|
pprev = NULL;
|
|
pnext = NULL;
|
|
nHeight = 0;
|
|
nFile = 0;
|
|
nDataPos = 0;
|
|
nUndoPos = 0;
|
|
nChainWork = 0;
|
|
nWorkTransition = 0;
|
|
nPrimeChainType = 0;
|
|
nPrimeChainLength = 0;
|
|
nMoneySupply = 0;
|
|
nTx = 0;
|
|
nChainTx = 0;
|
|
nStatus = 0;
|
|
|
|
nVersion = 0;
|
|
hashMerkleRoot = 0;
|
|
nTime = 0;
|
|
nBits = 0;
|
|
nNonce = 0;
|
|
}
|
|
|
|
CBlockIndex(CBlockHeader& block)
|
|
{
|
|
phashBlock = NULL;
|
|
pprev = NULL;
|
|
pnext = NULL;
|
|
nHeight = 0;
|
|
nFile = 0;
|
|
nDataPos = 0;
|
|
nUndoPos = 0;
|
|
nChainWork = 0;
|
|
nWorkTransition = 0;
|
|
nPrimeChainType = 0;
|
|
nPrimeChainLength = 0;
|
|
nMoneySupply = 0;
|
|
nTx = 0;
|
|
nChainTx = 0;
|
|
nStatus = 0;
|
|
|
|
nVersion = block.nVersion;
|
|
hashMerkleRoot = block.hashMerkleRoot;
|
|
nTime = block.nTime;
|
|
nBits = block.nBits;
|
|
nNonce = block.nNonce;
|
|
}
|
|
|
|
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 GetBlockTime() const
|
|
{
|
|
return (int64)nTime;
|
|
}
|
|
|
|
CBigNum GetBlockWork() const;
|
|
|
|
bool IsInMainChain() const
|
|
{
|
|
return (pnext || this == pindexBest);
|
|
}
|
|
|
|
bool CheckIndex() const
|
|
{
|
|
// Primecoin: disabled proof-of-work check for loading block index
|
|
// return CheckProofOfWork(GetBlockHash(), nBits);
|
|
return true;
|
|
}
|
|
|
|
enum { nMedianTimeSpan=99 };
|
|
|
|
int64 GetMedianTimePast() const
|
|
{
|
|
int64 pmedian[nMedianTimeSpan];
|
|
int64* pbegin = &pmedian[nMedianTimeSpan];
|
|
int64* 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];
|
|
}
|
|
|
|
int64 GetMedianTime() const
|
|
{
|
|
const CBlockIndex* pindex = this;
|
|
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
|
{
|
|
if (!pindex->pnext)
|
|
return GetBlockTime();
|
|
pindex = pindex->pnext;
|
|
}
|
|
return pindex->GetMedianTimePast();
|
|
}
|
|
|
|
/**
|
|
* Returns true if there are nRequired or more blocks of minVersion or above
|
|
* in the last nToCheck blocks, starting at pstart and going backwards.
|
|
*/
|
|
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart,
|
|
unsigned int nRequired, unsigned int nToCheck);
|
|
|
|
std::string ToString() const
|
|
{
|
|
return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
|
pprev, pnext, nHeight,
|
|
hashMerkleRoot.ToString().c_str(),
|
|
GetBlockHash().ToString().c_str());
|
|
}
|
|
|
|
void print() const
|
|
{
|
|
printf("%s\n", ToString().c_str());
|
|
}
|
|
};
|
|
|
|
struct CBlockIndexWorkComparator
|
|
{
|
|
bool operator()(CBlockIndex *pa, CBlockIndex *pb) {
|
|
if (pa->nChainWork > pb->nChainWork) return false;
|
|
if (pa->nChainWork < pb->nChainWork) return true;
|
|
|
|
if (pa->GetBlockHash() < pb->GetBlockHash()) return false;
|
|
if (pa->GetBlockHash() > pb->GetBlockHash()) return true;
|
|
|
|
return false; // identical blocks
|
|
}
|
|
};
|
|
|
|
#endif
|