#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
+#include "timestamps.h"
#include "bignum.h"
#include "sync.h"
#include "net.h"
#include "scrypt.h"
#include <list>
+#include <map>
class CWallet;
class CBlock;
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 ENTROPY_SWITCH_TIME = 1362791041; // Sat, 09 Mar 2013 01:04:01 GMT
-static const unsigned int STAKE_SWITCH_TIME = 1371686400; // Thu, 20 Jun 2013 00:00:00 GMT
-static const unsigned int TARGETS_SWITCH_TIME = 1374278400; // Sat, 20 Jul 2013 00:00:00 GMT
-static const unsigned int CHAINCHECKS_SWITCH_TIME = 1379635200; // Fri, 20 Sep 2013 00:00:00 GMT
-static const unsigned int STAKECURVE_SWITCH_TIME = 1382227200; // Sun, 20 Oct 2013 00:00:00 GMT
-static const unsigned int STAKEWEIGHT_SWITCH_TIME = 1388534400; // Wed, 01 Jan 2014 00:00:00 GMT
-
+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;
// Settings
extern int64 nTransactionFee;
-extern bool fStakeUsePooledKeys;
+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);
+
+// 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);
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake);
-int64 GetProofOfWorkReward(unsigned int nBits);
+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);
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)
{
@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);
+ }
+};
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 SignBlock(CWallet& keystore);
bool CheckBlockSignature(bool fProofOfStake) const;
private:
/** 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
{