primeminer/src/main.h

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