#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
+#include <algorithm>
+
+#include "timestamps.h"
#include "bignum.h"
#include "sync.h"
#include "net.h"
#include "script.h"
-#include "scrypt_mine.h"
+#include "scrypt.h"
#include <list>
+#include <map>
class CWallet;
class CBlock;
class CRequestTracker;
class CNode;
+//
+// Global state
+//
+
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
static const unsigned int MAX_INV_SZ = 50000;
-static const int64 MIN_TX_FEE = CENT;
-static const int64 MIN_RELAY_TX_FEE = CENT;
+
+static const int64 MIN_TX_FEE = CENT/10;
+static const int64 MIN_RELAY_TX_FEE = CENT/50;
+
static const int64 MAX_MONEY = 2000000000 * COIN;
static const int64 MAX_MINT_PROOF_OF_WORK = 100 * COIN;
static const int64 MAX_MINT_PROOF_OF_STAKE = 1 * COIN;
-static const int64 MIN_TXOUT_AMOUNT = MIN_TX_FEE;
-static const unsigned int STAKE_SWITCH_TIME = 1371686400; // 20 Jun 2013 00:00:00
-static const unsigned int TARGETS_SWITCH_TIME = 1374278400; // 20 Jul 2013 00:00:00
-static const unsigned int LOCKS_SWITCH_TIME = 1376956800; // 20 Aug 2013 00:00:00
+static const int64 MIN_TXOUT_AMOUNT = CENT/100;
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
// 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;
#ifdef USE_UPNP
static const int fHaveUPnP = true;
static const uint256 hashGenesisBlock("0x00000a060336cbb72fe969666d337b87198b1add2abaa59cca226820b32933a4");
static const uint256 hashGenesisBlockTestNet("0x000c763e402f2436da9ed36c7286f62c3f6e5dbafce9ff289bd43d7459327eb");
-static const int64 nMaxClockDrift = 2 * 60 * 60; // two hours
+inline int64 PastDrift(int64 nTime) { return nTime - 2 * 60 * 60; } // up to 2 hours from the past
+inline int64 FutureDrift(int64 nTime) { return nTime + 2 * 60 * 60; } // up to 2 hours from the future
extern CScript COINBASE_FLAGS;
-
-
extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
extern std::set<std::pair<COutPoint, unsigned int> > setStakeSeen;
extern CBlockIndex* pindexGenesisBlock;
+extern unsigned int nNodeLifespan;
extern unsigned int nStakeMinAge;
extern int nCoinbaseMaturity;
extern int nBestHeight;
-extern CBigNum bnBestChainTrust;
-extern CBigNum bnBestInvalidTrust;
+extern uint256 nBestChainTrust;
+extern uint256 nBestInvalidTrust;
extern uint256 hashBestChain;
extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
extern uint64 nLastBlockSize;
extern int64 nLastCoinStakeSearchInterval;
extern const std::string strMessageMagic;
-extern double dHashesPerSec;
-extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
// Settings
extern int64 nTransactionFee;
+extern int64 nMinimumInputValue;
+extern bool fUseFastIndex;
+extern unsigned int nDerivationMethodIndex;
+extern int nScriptCheckThreads;
// Minimum disk space required - used in CheckDiskSpace()
static const uint64 nMinDiskSpace = 52428800;
-
class CReserveKey;
class CTxDB;
class CTxIndex;
+class CScriptCheck;
void RegisterWallet(CWallet* pwalletIn);
void UnregisterWallet(CWallet* pwalletIn);
bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
bool LoadExternalBlockFile(FILE* fileIn);
-void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
-CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake=false);
-void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
-void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
-bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
+
+// Run an instance of the script checking thread
+void ThreadScriptCheck(void* parg);
+// Stop the script checking threads
+void ThreadScriptCheckQuit();
+
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
-int64 GetProofOfWorkReward(unsigned int nBits);
-int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime);
+unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake);
+int64 GetProofOfWorkReward(unsigned int nBits, int64 nFees=0);
+int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly=false);
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
+unsigned int ComputeMinStake(unsigned int nBase, int64 nTime, unsigned int nBlockTime);
int GetNumBlocksOfPeers();
bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);
uint256 WantedByOrphan(const CBlock* pblockOrphan);
const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake);
-void BitcoinMiner(CWallet *pwallet, bool fProofOfStake);
+void StakeMiner(CWallet *pwallet);
void ResendWalletTransactions();
-
-
+bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
return dPriority > COIN * 144 / 250;
}
- int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=false, enum GetMinFee_mode mode=GMF_BLOCK) const;
+ int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=false, enum GetMinFee_mode mode=GMF_BLOCK, unsigned int nBytes = 0) const;
bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
{
filein >> *this;
}
catch (std::exception &e) {
- return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ return error("%s() : deserialize or I/O error", BOOST_CURRENT_FUNCTION);
}
// Return file pointer
@param[in] pindexBlock
@param[in] fBlock true if called from ConnectBlock
@param[in] fMiner true if called from CreateNewBlock
- @param[in] fStrictPayToScriptHash true if fully validating p2sh transactions
+ @param[in] fScriptChecks enable scripts validation?
+ @param[in] flags STRICT_FLAGS script validation flags
+ @param[in] pvChecks NULL If pvChecks is not NULL, script checks are pushed onto it instead of being performed inline.
@return Returns true if all checks succeed
*/
- bool ConnectInputs(CTxDB& txdb, MapPrevTx inputs,
- std::map<uint256, CTxIndex>& mapTestPool, const CDiskTxPos& posThisTx,
- const CBlockIndex* pindexBlock, bool fBlock, bool fMiner, bool fStrictPayToScriptHash=true);
+ bool ConnectInputs(CTxDB& txdb, MapPrevTx inputs, std::map<uint256, CTxIndex>& mapTestPool, const CDiskTxPos& posThisTx, const CBlockIndex* pindexBlock,
+ bool fBlock, bool fMiner, bool fScriptChecks=true,
+ unsigned int flags=STRICT_FLAGS, std::vector<CScriptCheck> *pvChecks = NULL);
bool ClientConnectInputs();
bool CheckTransaction() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
};
+/** Closure representing one script verification
+ * Note that this stores references to the spending transaction */
+class CScriptCheck
+{
+private:
+ CScript scriptPubKey;
+ const CTransaction *ptxTo;
+ unsigned int nIn;
+ unsigned int nFlags;
+ int nHashType;
+
+public:
+ CScriptCheck() {}
+ CScriptCheck(const CTransaction& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, int nHashTypeIn) :
+ scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
+ ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), nHashType(nHashTypeIn) { }
+
+ bool operator()() const;
+
+ void swap(CScriptCheck &check) {
+ scriptPubKey.swap(check.scriptPubKey);
+ std::swap(ptxTo, check.ptxTo);
+ std::swap(nIn, check.nIn);
+ std::swap(nFlags, check.nFlags);
+ std::swap(nHashType, check.nHashType);
+ }
+};
{
public:
// header
- static const int CURRENT_VERSION=5;
+ static const int CURRENT_VERSION=6;
int nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
uint256 GetHash() const
{
- uint256 thash;
- void * scratchbuff = scrypt_buffer_alloc();
-
- scrypt_hash(CVOIDBEGIN(nVersion), sizeof(block_header), UINTBEGIN(thash), scratchbuff);
-
- scrypt_buffer_free(scratchbuff);
-
- return thash;
+ return scrypt_blockhash(CVOIDBEGIN(nVersion));
}
int64 GetBlockTime() const
void UpdateTime(const CBlockIndex* pindexPrev);
// ppcoin: entropy bit for stake modifier if chosen by modifier
- unsigned int GetStakeEntropyBit(unsigned int nHeight) const
+ unsigned int GetStakeEntropyBit(unsigned int nTime) const
{
// Protocol switch to support p2pool at novacoin block #9689
- if (nHeight >= 9689 || fTestNet)
+ if (nTime >= ENTROPY_SWITCH_TIME || fTestNet)
{
// Take last bit of block hash as entropy bit
- unsigned int nEntropyBit = ((GetHash().Get64()) & 1llu);
+ unsigned int nEntropyBit = ((GetHash().Get64()) & 1ULL);
+ //unsigned int nEntropyBit = 1;
if (fDebug && GetBoolArg("-printstakemodifier"))
- printf("GetStakeEntropyBit: nHeight=%u hashBlock=%s nEntropyBit=%u\n", nHeight, GetHash().ToString().c_str(), nEntropyBit);
+ printf("GetStakeEntropyBit: nTime=%u hashBlock=%s nEntropyBit=%u\n", nTime, GetHash().ToString().c_str(), nEntropyBit);
return nEntropyBit;
}
// Before novacoin block #9689 - old protocol
filein >> *this;
}
catch (std::exception &e) {
- return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ return error("%s() : deserialize or I/O error", BOOST_CURRENT_FUNCTION);
}
// Check the header
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
- bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true) const;
+ bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true, bool fCheckSig=true) const;
bool AcceptBlock();
bool GetCoinAge(uint64& nCoinAge) const; // ppcoin: calculate total coin age spent in block
- bool SignBlock(const CKeyStore& keystore);
- bool CheckBlockSignature() const;
+ bool SignBlock(CWallet& keystore);
+ bool CheckBlockSignature(bool fProofOfStake) const;
private:
bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew);
CBlockIndex* pnext;
unsigned int nFile;
unsigned int nBlockPos;
- CBigNum bnChainTrust; // ppcoin: trust score of block chain
+ uint256 nChainTrust; // ppcoin: trust score of block chain
int nHeight;
int64 nMint;
nFile = 0;
nBlockPos = 0;
nHeight = 0;
- bnChainTrust = 0;
+ nChainTrust = 0;
nMint = 0;
nMoneySupply = 0;
nFlags = 0;
nFile = nFileIn;
nBlockPos = nBlockPosIn;
nHeight = 0;
- bnChainTrust = 0;
+ nChainTrust = 0;
nMint = 0;
nMoneySupply = 0;
nFlags = 0;
return (int64)nTime;
}
- CBigNum GetBlockTrust() const
- {
- CBigNum bnTarget;
- bnTarget.SetCompact(nBits);
- if (bnTarget <= 0)
- return 0;
- return (IsProofOfStake()? (CBigNum(1)<<256) / (bnTarget+1) : 1);
- }
+ uint256 GetBlockTrust() const;
bool IsInMainChain() const
{
/** Used to marshal pointers into hashes for db storage. */
class CDiskBlockIndex : public CBlockIndex
{
+private:
+ uint256 blockHash;
+
public:
uint256 hashPrev;
uint256 hashNext;
{
hashPrev = 0;
hashNext = 0;
+ blockHash = 0;
}
explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
+ READWRITE(blockHash);
)
uint256 GetBlockHash() const
{
+ if (fUseFastIndex && (nTime < GetAdjustedTime() - 24 * 60 * 60) && blockHash != 0)
+ return blockHash;
+
CBlock block;
block.nVersion = nVersion;
block.hashPrevBlock = hashPrev;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
- return block.GetHash();
- }
+ const_cast<CDiskBlockIndex*>(this)->blockHash = block.GetHash();
+
+ return blockHash;
+ }
std::string ToString() const
{