primeminer/src/main.h

365 lines
11 KiB
C
Raw Normal View History

// Copyright (c) 2009-2010 Satoshi Nakamoto
2012-02-07 16:28:30 +00:00
// 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"
2014-01-26 13:43:02 +00:00
#include "hash.h"
#include <list>
class CBlockIndex;
2012-11-11 02:53:32 +00:00
struct CBlockIndexWorkComparator;
2012-11-02 23:14:43 +00:00
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
2012-11-02 23:14:43 +00:00
/** 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;
2012-11-02 23:14:43 +00:00
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
2012-11-02 23:14:43 +00:00
/** The maximum number of orphan transactions kept in memory */
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
2012-11-02 23:14:43 +00:00
/** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000;
2012-11-02 23:14:43 +00:00
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
2012-11-02 23:14:43 +00:00
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
2012-11-02 23:14:43 +00:00
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
2012-11-02 23:14:43 +00:00
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
Ultraprune This switches bitcoin's transaction/block verification logic to use a "coin database", which contains all unredeemed transaction output scripts, amounts and heights. The name ultraprune comes from the fact that instead of a full transaction index, we only (need to) keep an index with unspent outputs. For now, the blocks themselves are kept as usual, although they are only necessary for serving, rescanning and reorganizing. The basic datastructures are CCoins (representing the coins of a single transaction), and CCoinsView (representing a state of the coins database). There are several implementations for CCoinsView. A dummy, one backed by the coins database (coins.dat), one backed by the memory pool, and one that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock, DisconnectBlock, ... now operate on a generic CCoinsView. The block switching logic now builds a single cached CCoinsView with changes to be committed to the database before any changes are made. This means no uncommitted changes are ever read from the database, and should ease the transition to another database layer which does not support transactions (but does support atomic writes), like LevelDB. For the getrawtransaction() RPC call, access to a txid-to-disk index would be preferable. As this index is not necessary or even useful for any other part of the implementation, it is not provided. Instead, getrawtransaction() uses the coin database to find the block height, and then scans that block to find the requested transaction. This is slow, but should suffice for debug purposes.
2012-07-01 16:54:00 +00:00
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
2012-11-02 23:14:43 +00:00
/** 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;
2014-01-26 13:43:02 +00:00
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;
}
2012-08-14 23:21:20 +00:00
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
{
2014-01-26 13:43:02 +00:00
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(),
2014-01-26 13:43:02 +00:00
nTime, nBits, nNonce);
printf("\n");
}
};
2014-01-26 13:43:02 +00:00
class CBlockIndex;
extern CBlockIndex *pindexBest;
2012-03-26 14:48:23 +00:00
/** 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;
Ultraprune This switches bitcoin's transaction/block verification logic to use a "coin database", which contains all unredeemed transaction output scripts, amounts and heights. The name ultraprune comes from the fact that instead of a full transaction index, we only (need to) keep an index with unspent outputs. For now, the blocks themselves are kept as usual, although they are only necessary for serving, rescanning and reorganizing. The basic datastructures are CCoins (representing the coins of a single transaction), and CCoinsView (representing a state of the coins database). There are several implementations for CCoinsView. A dummy, one backed by the coins database (coins.dat), one backed by the memory pool, and one that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock, DisconnectBlock, ... now operate on a generic CCoinsView. The block switching logic now builds a single cached CCoinsView with changes to be committed to the database before any changes are made. This means no uncommitted changes are ever read from the database, and should ease the transition to another database layer which does not support transactions (but does support atomic writes), like LevelDB. For the getrawtransaction() RPC call, access to a txid-to-disk index would be preferable. As this index is not necessary or even useful for any other part of the implementation, it is not provided. Instead, getrawtransaction() uses the coin database to find the block height, and then scans that block to find the requested transaction. This is slow, but should suffice for debug purposes.
2012-07-01 16:54:00 +00:00
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