// Ping and address broadcast intervals
int64_t nPingInterval = 30 * 60;
-int64_t nBroadcastInterval = nOneDay;
extern enum Checkpoints::CPMode CheckpointsMode;
// check whether the passed transaction is from us
bool static IsFromMe(CTransaction& tx)
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
if (pwallet->IsFromMe(tx))
return true;
return false;
}
-// get the wallet transaction with the given hash (if it exists)
-bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
-{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- if (pwallet->GetTransaction(hashTx,wtx))
- return true;
- return false;
-}
-
-// erases transaction with the given hash from all wallets
-void static EraseFromWallets(uint256 hash)
-{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->EraseFromWallet(hash);
-}
-
// make sure all wallets know about the given transaction, in the given block
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fConnect)
{
// wallets need to refund inputs when disconnecting coinstake
if (tx.IsCoinStake())
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
if (pwallet->IsFromMe(tx))
pwallet->DisableTransaction(tx);
}
return;
}
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
}
// notify wallets about a new best chain
void static SetBestChain(const CBlockLocator& loc)
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
pwallet->SetBestChain(loc);
}
// notify wallets about an updated transaction
void static UpdatedTransaction(const uint256& hashTx)
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
pwallet->UpdatedTransaction(hashTx);
}
// dump all wallets
void static PrintWallets(const CBlock& block)
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
pwallet->PrintWallet(block);
}
// notify wallets about an incoming inventory (for request counts)
void static Inventory(const uint256& hash)
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ for(CWallet* pwallet : setpwalletRegistered)
pwallet->Inventory(hash);
}
// ask wallets to resend their transactions
-void ResendWalletTransactions()
+void ResendWalletTransactions(bool fForceResend)
{
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->ResendWalletTransactions();
+ for(CWallet* pwallet : setpwalletRegistered)
+ pwallet->ResendWalletTransactions(fForceResend);
}
bool AddOrphanTx(const CTransaction& tx)
{
- uint256 hash = tx.GetHash();
+ auto hash = tx.GetHash();
if (mapOrphanTransactions.count(hash))
return false;
}
mapOrphanTransactions[hash] = tx;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for(const CTxIn& txin : tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
printf("stored orphan tx %s (mapsz %" PRIszu ")\n", hash.ToString().substr(0,10).c_str(),
{
if (!mapOrphanTransactions.count(hash))
return;
- const CTransaction& tx = mapOrphanTransactions[hash];
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ const auto& tx = mapOrphanTransactions[hash];
+ for(const auto& txin : tx.vin)
{
mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash);
if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty())
while (mapOrphanTransactions.size() > nMaxOrphans)
{
// Evict a random orphan:
- uint256 randomhash = GetRandHash();
- map<uint256, CTransaction>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
+ auto randomhash = GetRandHash();
+ auto it = mapOrphanTransactions.lower_bound(randomhash);
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
EraseOrphanTx(it->first);
unsigned int nDataOut = 0;
txnouttype whichType;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ for(const CTxIn& txin : vin)
{
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
// keys. (remember the 520 byte limit on redeemScript size) That works
return false;
}
}
- BOOST_FOREACH(const CTxOut& txout, vout) {
+ for(const CTxOut& txout : vout) {
if (!::IsStandard(txout.scriptPubKey, whichType)) {
strReason = "scriptpubkey";
return false;
if (IsCoinBase())
return true; // Coinbases don't use vin normally
- for (unsigned int i = 0; i < vin.size(); i++)
+ for (uint32_t i = 0; i < vin.size(); i++)
{
const CTxOut& prev = GetOutputFor(vin[i], mapInputs);
CTransaction::GetLegacySigOpCount() const
{
unsigned int nSigOps = 0;
- if (!IsCoinBase() || nTime < COINBASE_SIGOPS_SWITCH_TIME)
+ if (!IsCoinBase())
{
// Coinbase scriptsigs are never executed, so there is
// no sense in calculation of sigops.
- BOOST_FOREACH(const CTxIn& txin, vin)
+ for(const CTxIn& txin : vin)
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
}
- BOOST_FOREACH(const CTxOut& txout, vout)
+ for(const CTxOut& txout : vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
return nSigOps;
}
-
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
{
if (fClient)
else
{
CBlock blockTmp;
+
if (pblock == NULL)
{
// Load the block this tx is in
}
// Is the tx in a block that's in the main chain
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ auto mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
- CBlockIndex* pindex = (*mi).second;
+ const CBlockIndex* pindex = (*mi).second;
if (!pindex || !pindex->IsInMainChain())
return 0;
return pindexBest->nHeight - pindex->nHeight + 1;
}
-
-
-
-
-
-
bool CTransaction::CheckTransaction() const
{
// Basic checks that don't depend on any context
return DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
if (vout.empty())
return DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
- // Time (prevent mempool memory exhaustion attack)
- // Comes into force since 20 December 2015.
- if (nTime > 1450569600 && nTime > FutureDrift(GetAdjustedTime()))
- return DoS(10, error("CTransaction::CheckTransaction() : timestamp is too far into the future"));
// Size limits
if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
// Check for negative or overflow output values
- int64_t nValueOut = 0;
- for (unsigned int i = 0; i < vout.size(); i++)
+ CBigNum nValueOut = 0;
+ for (uint32_t i = 0; i < vout.size(); i++)
{
- const CTxOut& txout = vout[i];
+ const auto& txout = vout[i];
if (txout.IsEmpty() && !IsCoinBase() && !IsCoinStake())
return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));
-
- if (txout.nValue < 0)
- return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue is negative"));
- if (txout.nValue > MAX_MONEY)
- return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
+ if (!MoneyRange(txout.nValue))
+ return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue is out of range"));
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
return DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
// Check for duplicate inputs
set<COutPoint> vInOutPoints;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ for(const CTxIn& txin : vin)
{
if (vInOutPoints.count(txin.prevout))
return false;
}
else
{
- BOOST_FOREACH(const CTxIn& txin, vin)
+ for(const CTxIn& txin : vin)
if (txin.prevout.IsNull())
return DoS(10, error("CTransaction::CheckTransaction() : prevout is null"));
}
}
// Base fee is either nMinTxFee or nMinRelayTxFee
- int64_t nBaseFee = (mode == GMF_RELAY) ? nMinRelayTxFee : nMinTxFee;
+ auto nBaseFee = (mode == GMF_RELAY) ? nMinRelayTxFee : nMinTxFee;
unsigned int nNewBlockSize = nBlockSize + nBytes;
int64_t nMinFee = (1 + (int64_t)nBytes / 1000) * nBaseFee;
//
// It's safe to ignore empty outputs here, because these inputs are allowed
// only for coinbase and coinstake transactions.
- BOOST_FOREACH(const CTxOut& txout, vout)
+ for(const CTxOut& txout : vout)
if (txout.nValue < CENT && !txout.IsEmpty())
nMinFee += nBaseFee;
if (pfMissingInputs)
*pfMissingInputs = false;
+ // Time (prevent mempool memory exhaustion attack)
+ if (tx.nTime > FutureDrift(GetAdjustedTime()))
+ return tx.DoS(10, error("CTxMemPool::accept() : transaction timestamp is too far in the future"));
+
if (!tx.CheckTransaction())
return error("CTxMemPool::accept() : CheckTransaction failed");
return error("CTxMemPool::accept() : nonstandard transaction (%s)", strNonStd.c_str());
// Do we already have it?
- uint256 hash = tx.GetHash();
+ auto hash = tx.GetHash();
{
LOCK(cs);
if (mapTx.count(hash))
return false;
// Check for conflicts with in-memory transactions
- CTransaction* ptxOld = NULL;
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
- COutPoint outpoint = tx.vin[i].prevout;
+ auto outpoint = tx.vin[i].prevout;
if (mapNextTx.count(outpoint))
{
- // Disable replacement feature for now
+ // Replacement feature isn't supported by Novacoin.
return false;
-
- // Allow replacing with a newer version of the same transaction
- if (i != 0)
- return false;
- ptxOld = mapNextTx[outpoint].ptx;
- if (ptxOld->IsFinal())
- return false;
- if (!tx.IsNewerThan(*ptxOld))
- return false;
- for (unsigned int i = 0; i < tx.vin.size(); i++)
- {
- COutPoint outpoint = tx.vin[i].prevout;
- if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
- return false;
- }
- break;
}
}
// you should add code here to check that the transaction does a
// reasonable number of ECDSA signature verifications.
- int64_t nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
+ auto nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Don't accept it if it can't get into a block
- int64_t txMinFee = tx.GetMinFee(1000, true, GMF_RELAY, nSize);
+ auto txMinFee = tx.GetMinFee(1000, true, GMF_RELAY, nSize);
if (nFees < txMinFee)
return error("CTxMemPool::accept() : not enough fees %s, %" PRId64 " < %" PRId64,
hash.ToString().c_str(),
static CCriticalSection cs;
static double dFreeCount;
static int64_t nLastTime;
- int64_t nNow = GetTime();
+ auto nNow = GetTime();
{
LOCK(cs);
// Store transaction in memory
{
LOCK(cs);
- if (ptxOld)
- {
- printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
- remove(*ptxOld);
- }
addUnchecked(hash, tx);
}
- ///// are we sure this is ok when loading transactions or restoring block txes
- // If updated, erase old tx from wallet
- if (ptxOld)
- EraseFromWallets(ptxOld->GetHash());
-
printf("CTxMemPool::accept() : accepted %s (poolsz %" PRIszu ")\n",
hash.ToString().substr(0,10).c_str(),
mapTx.size());
// Remove transaction from memory pool
{
LOCK(cs);
- uint256 hash = tx.GetHash();
+ auto hash = tx.GetHash();
if (mapTx.count(hash))
{
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for(const CTxIn& txin : tx.vin)
mapNextTx.erase(txin.prevout);
mapTx.erase(hash);
nTransactionsUpdated++;
LOCK(cs);
vtxid.reserve(mapTx.size());
- for (map<uint256, CTransaction>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
+ for (auto mi = mapTx.begin(); mi != mapTx.end(); ++mi)
vtxid.push_back((*mi).first);
}
return 0;
// Find the block it claims to be in
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ auto mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
{
LOCK(mempool.cs);
// Add previous supporting transactions first
- BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
+ for(CMerkleTx& tx : vtxPrev)
{
if (!(tx.IsCoinBase() || tx.IsCoinStake()))
{
- uint256 hash = tx.GetHash();
+ auto hash = tx.GetHash();
if (!mempool.exists(hash) && !txdb.ContainsTx(hash))
tx.AcceptToMemoryPool(txdb, fCheckInputs);
}
if (!block.ReadFromDisk(pos.nFile, pos.nBlockPos, false))
return 0;
// Find the block in the index
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.GetHash());
+ auto mi = mapBlockIndex.find(block.GetHash());
if (mi == mapBlockIndex.end())
return 0;
- CBlockIndex* pindex = (*mi).second;
+ auto pindex = (*mi).second;
if (!pindex || !pindex->IsInMainChain())
return 0;
return 1 + nBestHeight - pindex->nHeight;
while (bnLowerBound + CENT <= bnUpperBound)
{
- CBigNum bnMidValue = (bnLowerBound + bnUpperBound) / 2;
+ auto bnMidValue = (bnLowerBound + bnUpperBound) / 2;
//
// Reward for coin-year is cut in half every 8x multiply of PoS difficulty
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
- CBigNum bnTargetLimit = !fProofOfStake ? bnProofOfWorkLimit : GetProofOfStakeLimit(pindexLast->nHeight, pindexLast->nTime);
-
if (pindexLast == NULL)
- return bnTargetLimit.GetCompact(); // genesis block
+ return bnProofOfWorkLimit.GetCompact(); // genesis block
+
+ CBigNum bnTargetLimit = !fProofOfStake ? bnProofOfWorkLimit : GetProofOfStakeLimit(pindexLast->nHeight, pindexLast->nTime);
const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
if (pindexPrev->pprev == NULL)
return true;
static int64_t nLastUpdate;
static CBlockIndex* pindexLastBest;
- int64_t nCurrentTime = GetTime();
+ auto nCurrentTime = GetTime();
if (pindexBest != pindexLastBest)
{
pindexLastBest = pindexBest;
uiInterface.NotifyBlocksChanged();
}
- uint256 nBestInvalidBlockTrust = pindexNew->nChainTrust - pindexNew->pprev->nChainTrust;
- uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
+ auto nBestInvalidBlockTrust = pindexNew->nChainTrust - pindexNew->pprev->nChainTrust;
+ auto nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
printf("InvalidChainFound: invalid block=%s height=%d trust=%s blocktrust=%" PRId64 " date=%s\n",
pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight,
// Relinquish previous transactions' spent pointers
if (!IsCoinBase())
{
- BOOST_FOREACH(const CTxIn& txin, vin)
+ for(const CTxIn& txin : vin)
{
- COutPoint prevout = txin.prevout;
+ auto prevout = txin.prevout;
// Get prev txindex from disk
CTxIndex txindex;
for (unsigned int i = 0; i < vin.size(); i++)
{
- COutPoint prevout = vin[i].prevout;
+ auto prevout = vin[i].prevout;
if (inputsRet.count(prevout.hash))
continue; // Got it already
const CTxOut& CTransaction::GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const
{
- MapPrevTx::const_iterator mi = inputs.find(input.prevout.hash);
+ auto mi = inputs.find(input.prevout.hash);
if (mi == inputs.end())
throw std::runtime_error("CTransaction::GetOutputFor() : prevout.hash not found");
- const CTransaction& txPrev = (mi->second).second;
+ const auto& txPrev = (mi->second).second;
if (input.prevout.n >= txPrev.vout.size())
throw std::runtime_error("CTransaction::GetOutputFor() : prevout.n out of range");
if (IsCoinBase())
return 0;
- int64_t nResult = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
+ CBigNum nResult = 0;
+ for (uint32_t i = 0; i < vin.size(); i++)
{
- nResult += GetOutputFor(vin[i], inputs).nValue;
+ const auto& txOut = GetOutputFor(vin[i], inputs);
+ nResult += txOut.nValue;
+ if (!MoneyRange(txOut.nValue) || !MoneyRange(nResult))
+ throw runtime_error("CTransaction::GetValueIn() : value out of range");
}
- return nResult;
+ return nResult.getint64();
}
if (!IsCoinBase())
{
int64_t nValueIn = 0;
- int64_t nFees = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
{
- COutPoint prevout = vin[i].prevout;
- assert(inputs.count(prevout.hash) > 0);
- CTxIndex& txindex = inputs[prevout.hash].first;
- CTransaction& txPrev = inputs[prevout.hash].second;
-
- if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
- return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %" PRIszu " %" PRIszu " prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
-
- // If prev is coinbase or coinstake, check that it's matured
- if (txPrev.IsCoinBase() || txPrev.IsCoinStake())
- for (const CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < nCoinbaseMaturity; pindex = pindex->pprev)
- if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
- return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", pindexBlock->nHeight - pindex->nHeight);
-
- // ppcoin: check transaction timestamp
- if (txPrev.nTime > nTime)
- return DoS(100, error("ConnectInputs() : transaction timestamp earlier than input transaction"));
-
- // Check for negative or overflow input values
- nValueIn += txPrev.vout[prevout.n].nValue;
- if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
- return DoS(100, error("ConnectInputs() : txin values out of range"));
-
+ CBigNum bnValueIn = 0;
+ for (uint32_t i = 0; i < vin.size(); i++)
+ {
+ auto prevout = vin[i].prevout;
+ assert(inputs.count(prevout.hash) > 0);
+ CTxIndex& txindex = inputs[prevout.hash].first;
+ CTransaction& txPrev = inputs[prevout.hash].second;
+
+ if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
+ return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %" PRIszu " %" PRIszu " prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
+
+ // If prev is coinbase or coinstake, check that it's matured
+ if (txPrev.IsCoinBase() || txPrev.IsCoinStake())
+ for (const CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < nCoinbaseMaturity; pindex = pindex->pprev)
+ if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
+ return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", pindexBlock->nHeight - pindex->nHeight);
+
+ // ppcoin: check transaction timestamp
+ if (txPrev.nTime > nTime)
+ return DoS(100, error("ConnectInputs() : transaction timestamp earlier than input transaction"));
+
+ // Check for negative or overflow input values
+ bnValueIn += txPrev.vout[prevout.n].nValue;
+ if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(bnValueIn))
+ return DoS(100, error("ConnectInputs() : txin values out of range"));
+ }
+ nValueIn = bnValueIn.getint64();
}
if (pvChecks)
// Helps prevent CPU exhaustion attacks.
for (unsigned int i = 0; i < vin.size(); i++)
{
- COutPoint prevout = vin[i].prevout;
+ auto prevout = vin[i].prevout;
assert(inputs.count(prevout.hash) > 0);
CTxIndex& txindex = inputs[prevout.hash].first;
CTransaction& txPrev = inputs[prevout.hash].second;
if (!GetCoinAge(txdb, nCoinAge))
return error("ConnectInputs() : %s unable to get coin age for coinstake", GetHash().ToString().substr(0,10).c_str());
- int64_t nReward = GetValueOut() - nValueIn;
- int64_t nCalculatedReward = GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime) - GetMinFee(1, false, GMF_BLOCK, nTxSize) + CENT;
+ auto nReward = GetValueOut() - nValueIn;
+ auto nCalculatedReward = GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime) - GetMinFee(1, false, GMF_BLOCK, nTxSize) + CENT;
if (nReward > nCalculatedReward)
return DoS(100, error("ConnectInputs() : coinstake pays too much(actual=%" PRId64 " vs calculated=%" PRId64 ")", nReward, nCalculatedReward));
return DoS(100, error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,10).c_str()));
// Tally transaction fees
- int64_t nTxFee = nValueIn - GetValueOut();
- if (nTxFee < 0)
- return DoS(100, error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,10).c_str()));
-
- nFees += nTxFee;
- if (!MoneyRange(nFees))
+ auto nTxFee = nValueIn - GetValueOut();
+ if (!MoneyRange(nTxFee))
return DoS(100, error("ConnectInputs() : nFees out of range"));
}
}
// Take over previous transactions' spent pointers
{
LOCK(mempool.cs);
- int64_t nValueIn = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
+ CBigNum bnValueIn = 0;
+ for (uint32_t i = 0; i < vin.size(); i++)
{
// Get prev tx from single transactions in memory
- COutPoint prevout = vin[i].prevout;
+ auto prevout = vin[i].prevout;
if (!mempool.exists(prevout.hash))
return false;
CTransaction& txPrev = mempool.lookup(prevout.hash);
// // Flag outpoints as used
// txPrev.vout[prevout.n].posNext = posThisTx;
- nValueIn += txPrev.vout[prevout.n].nValue;
+ bnValueIn += txPrev.vout[prevout.n].nValue;
- if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
+ if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(bnValueIn))
return error("ClientConnectInputs() : txin values out of range");
}
- if (GetValueOut() > nValueIn)
+ if (GetValueOut() > bnValueIn.getint64())
return false;
}
}
// ppcoin: clean up wallet after disconnecting coinstake
- BOOST_FOREACH(CTransaction& tx, vtx)
+ for(CTransaction& tx : vtx)
SyncWithWallets(tx, this, false, false);
return true;
int64_t nValueIn = 0;
int64_t nValueOut = 0;
unsigned int nSigOps = 0;
- BOOST_FOREACH(CTransaction& tx, vtx)
+ for(auto& tx : vtx)
{
- uint256 hashTx = tx.GetHash();
+ auto hashTx = tx.GetHash();
if (fEnforceBIP30) {
CTxIndex txindexOld;
if (txdb.ReadTxIndex(hashTx, txindexOld)) {
- BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent)
+ for(CDiskTxPos &pos : txindexOld.vSpent)
if (pos.IsNull())
return false;
}
if (nSigOps > MAX_BLOCK_SIGOPS)
return DoS(100, error("ConnectBlock() : too many sigops"));
- int64_t nTxValueIn = tx.GetValueIn(mapInputs);
- int64_t nTxValueOut = tx.GetValueOut();
+ auto nTxValueIn = tx.GetValueIn(mapInputs);
+ auto nTxValueOut = tx.GetValueOut();
nValueIn += nTxValueIn;
nValueOut += nTxValueOut;
if (!tx.IsCoinStake())
nFees += nTxValueIn - nTxValueOut;
+ unsigned int nFlags = SCRIPT_VERIFY_NOCACHE | SCRIPT_VERIFY_P2SH;
+
+ if (tx.nTime >= CHECKLOCKTIMEVERIFY_SWITCH_TIME) {
+ nFlags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
+ // OP_CHECKSEQUENCEVERIFY is senseless without BIP68, so we're going disable it for now.
+ // nFlags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
+ }
+
std::vector<CScriptCheck> vChecks;
- if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false, fScriptChecks, SCRIPT_VERIFY_NOCACHE | SCRIPT_VERIFY_P2SH, nScriptCheckThreads ? &vChecks : NULL))
+ if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false, fScriptChecks, nFlags, nScriptCheckThreads ? &vChecks : NULL))
return false;
control.Add(vChecks);
}
if (IsProofOfWork())
{
- int64_t nBlockReward = GetProofOfWorkReward(nBits, nFees);
+ auto nBlockReward = GetProofOfWorkReward(nBits, nFees);
// Check coinbase reward
if (vtx[0].GetValueOut() > nBlockReward)
return true;
// Write queued txindex changes
- for (map<uint256, CTxIndex>::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi)
+ for (auto mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi)
{
if (!txdb.UpdateTxIndex((*mi).first, (*mi).second))
return error("ConnectBlock() : UpdateTxIndex failed");
}
// Watch for transactions paying to me
- BOOST_FOREACH(CTransaction& tx, vtx)
+ for(CTransaction& tx : vtx)
SyncWithWallets(tx, this, true);
while (pfork != plonger)
{
while (plonger->nHeight > pfork->nHeight)
- if (!(plonger = plonger->pprev))
+ if ((plonger = plonger->pprev) == NULL)
return error("Reorganize() : plonger->pprev is null");
if (pfork == plonger)
break;
- if (!(pfork = pfork->pprev))
+ if ((pfork = pfork->pprev) == NULL)
return error("Reorganize() : pfork->pprev is null");
}
// Disconnect shorter branch
vector<CTransaction> vResurrect;
- BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
+ for(CBlockIndex* pindex : vDisconnect)
{
CBlock block;
if (!block.ReadFromDisk(pindex))
return error("Reorganize() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str());
// Queue memory transactions to resurrect
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ for(const CTransaction& tx : block.vtx)
if (!(tx.IsCoinBase() || tx.IsCoinStake()))
vResurrect.push_back(tx);
}
}
// Queue memory transactions to delete
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ for(const CTransaction& tx : block.vtx)
vDelete.push_back(tx);
}
if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
return error("Reorganize() : TxnCommit failed");
// Disconnect shorter branch
- BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
+ for(CBlockIndex* pindex : vDisconnect)
if (pindex->pprev)
pindex->pprev->pnext = NULL;
// Connect longer branch
- BOOST_FOREACH(CBlockIndex* pindex, vConnect)
+ for(CBlockIndex* pindex : vConnect)
if (pindex->pprev)
pindex->pprev->pnext = pindex;
// Resurrect memory transactions that were in the disconnected branch
- BOOST_FOREACH(CTransaction& tx, vResurrect)
+ for(CTransaction& tx : vResurrect)
tx.AcceptToMemoryPool(txdb, false);
// Delete redundant memory transactions that are in the connected branch
- BOOST_FOREACH(CTransaction& tx, vDelete)
+ for(CTransaction& tx : vDelete)
mempool.remove(tx);
printf("REORGANIZE: done\n");
// Called from inside SetBestChain: attaches a block to the new best chain being built
bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew)
{
- uint256 hash = GetHash();
+ auto hash = GetHash();
// Adding to current best branch
if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
pindexNew->pprev->pnext = pindexNew;
// Delete redundant memory transactions
- BOOST_FOREACH(CTransaction& tx, vtx)
+ for(CTransaction& tx : vtx)
mempool.remove(tx);
return true;
bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
{
- uint256 hash = GetHash();
+ auto hash = GetHash();
if (!txdb.TxnBegin())
return error("SetBestChain() : TxnBegin failed");
}
// Connect further blocks
- BOOST_REVERSE_FOREACH(CBlockIndex *pindex, vpindexSecondary)
+ for (std::vector<CBlockIndex*>::reverse_iterator rit = vpindexSecondary.rbegin(); rit != vpindexSecondary.rend(); ++rit)
{
CBlock block;
- if (!block.ReadFromDisk(pindex))
+ if (!block.ReadFromDisk(*rit))
{
printf("SetBestChain() : ReadFromDisk failed\n");
break;
break;
}
// errors now are not fatal, we still did a reorganisation to a new chain in a valid way
- if (!block.SetBestChainInner(txdb, pindex))
+ if (!block.SetBestChainInner(txdb, *rit))
break;
}
}
strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
}
- std::string strCmd = GetArg("-blocknotify", "");
+ auto strCmd = GetArg("-blocknotify", "");
if (!fIsInitialDownload && !strCmd.empty())
{
if (IsCoinBase())
return true;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ for(const CTxIn& txin : vin)
{
// First try finding the previous transaction in database
CTransaction txPrev;
if (block.GetBlockTime() + nStakeMinAge > nTime)
continue; // only count coins meeting min age requirement
- int64_t nValueIn = txPrev.vout[txin.prevout.n].nValue;
+ auto nValueIn = txPrev.vout[txin.prevout.n].nValue;
bnCentSecond += CBigNum(nValueIn) * (nTime-txPrev.nTime) / CENT;
if (fDebug && GetBoolArg("-printcoinage"))
printf("coin age nValueIn=%" PRId64 " nTimeDiff=%d bnCentSecond=%s\n", nValueIn, nTime - txPrev.nTime, bnCentSecond.ToString().c_str());
}
- CBigNum bnCoinDay = bnCentSecond * CENT / COIN / nOneDay;
+ auto bnCoinDay = bnCentSecond * CENT / COIN / nOneDay;
if (fDebug && GetBoolArg("-printcoinage"))
printf("coin age bnCoinDay=%s\n", bnCoinDay.ToString().c_str());
nCoinAge = bnCoinDay.getuint64();
nCoinAge = 0;
CTxDB txdb("r");
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ for(const CTransaction& tx : vtx)
{
uint64_t nTxCoinAge;
if (tx.GetCoinAge(txdb, nTxCoinAge))
bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
{
// Check for duplicate
- uint256 hash = GetHash();
+ auto hash = GetHash();
if (mapBlockIndex.count(hash))
return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,20).c_str());
// Construct new block index object
- CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
+ CBlockIndex* pindexNew = new(nothrow) CBlockIndex(nFile, nBlockPos, *this);
if (!pindexNew)
return error("AddToBlockIndex() : new CBlockIndex failed");
pindexNew->phashBlock = &hash;
- map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
+ auto miPrev = mapBlockIndex.find(hashPrevBlock);
if (miPrev != mapBlockIndex.end())
{
pindexNew->pprev = (*miPrev).second;
return error("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=0x%016" PRIx64, pindexNew->nHeight, nStakeModifier);
// Add to mapBlockIndex
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
+ auto mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
if (pindexNew->IsProofOfStake())
setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
pindexNew->phashBlock = &((*mi).first);
bool CBlock::AcceptBlock()
{
// Check for duplicate
- uint256 hash = GetHash();
+ auto hash = GetHash();
if (mapBlockIndex.count(hash))
return error("AcceptBlock() : block already in mapBlockIndex");
// Get prev block index
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
+ auto mi = mapBlockIndex.find(hashPrevBlock);
if (mi == mapBlockIndex.end())
return DoS(10, error("AcceptBlock() : prev block not found"));
CBlockIndex* pindexPrev = (*mi).second;
return DoS(100, error("AcceptBlock() : incorrect %s", IsProofOfWork() ? "proof-of-work" : "proof-of-stake"));
int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
- int nMaxOffset = 12 * 3600; // 12 hours
- if (pindexPrev->nTime < 1450569600)
- nMaxOffset = 7 * 86400; // One week until 20 Dec, 2015
+ int nMaxOffset = 12 * nOneHour; // 12 hours
+ if (fTestNet || pindexPrev->nTime < 1450569600)
+ nMaxOffset = 7 * nOneWeek; // One week (permanently on testNet or until 20 Dec, 2015 on mainNet)
// Check timestamp against prev
if (GetBlockTime() <= nMedianTimePast || FutureDrift(GetBlockTime()) < pindexPrev->GetBlockTime())
return error("AcceptBlock() : block's timestamp is too far in the future");
// Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ for(const CTransaction& tx : vtx)
if (!tx.IsFinal(nHeight, GetBlockTime()))
return DoS(10, error("AcceptBlock() : contains a non-final transaction"));
bool cpSatisfies = Checkpoints::CheckSync(hash, pindexPrev);
// Check that the block satisfies synchronized checkpoint
- if (CheckpointsMode == Checkpoints::STRICT && !cpSatisfies)
+ if (CheckpointsMode == Checkpoints::CP_STRICT && !cpSatisfies)
return error("AcceptBlock() : rejected by synchronized checkpoint");
- if (CheckpointsMode == Checkpoints::ADVISORY && !cpSatisfies)
+ if (CheckpointsMode == Checkpoints::CP_ADVISORY && !cpSatisfies)
strMiscWarning = _("WARNING: syncronized checkpoint violation detected, but skipped!");
// Enforce rule that the coinbase starts with serialized block height
- CScript expect = CScript() << nHeight;
+ auto expect = CScript() << nHeight;
if (vtx[0].vin[0].scriptSig.size() < expect.size() ||
!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
return DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
if (hashBestChain == hash)
{
LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
+ for(CNode* pnode : vNodes)
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
pnode->PushInventory(CInv(MSG_BLOCK, hash));
}
return true;
}
- return CKey::ReserealizeSignature(pblock->vchBlockSig);
+ return CPubKey::ReserealizeSignature(pblock->vchBlockSig);
}
bool static IsCanonicalBlockSignature(CBlock* pblock)
bool ProcessBlock(CNode* pfrom, CBlock* pblock)
{
// Check for duplicate
- uint256 hash = pblock->GetHash();
+ auto hash = pblock->GetHash();
if (mapBlockIndex.count(hash))
return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,20).c_str());
if (mapOrphanBlocks.count(hash))
return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,20).c_str());
+ // Check that block isn't listed as unconditionally banned.
+ if (!Checkpoints::CheckBanned(hash)) {
+ if (pfrom)
+ pfrom->Misbehaving(100);
+ return error("ProcessBlock() : block %s is rejected by hard-coded banlist", hash.GetHex().substr(0,20).c_str());
+ }
+
// Check proof-of-stake
// Limited duplicity on stake: prevents block flood attack
// Duplicate stake allowed only when there is orphan child block
if (pcheckpoint && pblock->hashPrevBlock != hashBestChain && !Checkpoints::WantedByPendingSyncCheckpoint(hash))
{
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
- int64_t deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
+ auto deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
CBigNum bnNewBlock;
bnNewBlock.SetCompact(pblock->nBits);
CBigNum bnRequired;
vWorkQueue.push_back(hash);
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
{
- uint256 hashPrev = vWorkQueue[i];
- for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
+ auto hashPrev = vWorkQueue[i];
+ for (auto mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
++mi)
{
if (whichType == TX_PUBKEY)
{
- valtype& vchPubKey = vSolutions[0];
- CKey key;
- if (!key.SetPubKey(vchPubKey))
+ auto& vchPubKey = vSolutions[0];
+ CPubKey key(vchPubKey);
+ if (!key.IsValid())
return false;
return key.Verify(GetHash(), vchBlockSig);
}
FILE* AppendBlockFile(unsigned int& nFileRet)
{
nFileRet = 0;
- while (true)
+ for ( ; ; )
{
FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab");
if (!file)
return NULL;
if (fseek(file, 0, SEEK_END) != 0)
+ {
+ fclose(file);
return NULL;
+ }
// FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB
if (ftell(file) < (long)(0x7F000000 - MAX_SIZE))
{
{
if (fTestNet)
{
- pchMessageStart[0] = 0xcd;
- pchMessageStart[1] = 0xf2;
- pchMessageStart[2] = 0xc0;
- pchMessageStart[3] = 0xef;
+ nNetworkID = 0xefc0f2cd;
bnProofOfWorkLimit = bnProofOfWorkLimitTestNet; // 16 bits PoW target limit for testnet
nStakeMinAge = 2 * nOneHour; // test net min age is 2 hours
// CTxOut(empty)
// vMerkleTree: 4cb33b3b6a
- const char* pszTimestamp = "https://bitcointalk.org/index.php?topic=134179.msg1502196#msg1502196";
+ const string strTimestamp = "https://bitcointalk.org/index.php?topic=134179.msg1502196#msg1502196";
CTransaction txNew;
txNew.nTime = 1360105017;
txNew.vin.resize(1);
txNew.vout.resize(1);
- txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(9999) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
+ txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(9999) << vector<unsigned char>(strTimestamp.begin(), strTimestamp.end());
txNew.vout[0].SetEmpty();
CBlock block;
block.vtx.push_back(txNew);
{
// pre-compute tree structure
map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
- for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
+ for (auto mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
CBlockIndex* pindex = (*mi).second;
mapNext[pindex->pprev].push_back(pindex);
}
}
-bool LoadExternalBlockFile(FILE* fileIn)
+bool LoadExternalBlockFile(FILE* fileIn, CClientUIInterface& uiInterface)
{
- int64_t nStart = GetTimeMillis();
-
- int nLoaded = 0;
+ auto nStart = GetTimeMillis();
+ vector<uint8_t> pchData(10 * (8+MAX_BLOCK_SIZE));
+ int32_t nLoaded = 0;
{
LOCK(cs_main);
try {
CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION);
- unsigned int nPos = 0;
+ uint32_t nPos = 0;
while (nPos != std::numeric_limits<uint32_t>::max() && blkdat.good() && !fRequestShutdown)
{
- unsigned char pchData[65536];
- do {
+ do
+ {
fseek(blkdat, nPos, SEEK_SET);
- int nRead = fread(pchData, 1, sizeof(pchData), blkdat);
+ auto nRead = fread(&pchData[0], 1, pchData.size(), blkdat);
if (nRead <= 8)
{
- nPos = std::numeric_limits<uint32_t>::max();
+ nPos = numeric_limits<uint32_t>::max();
break;
}
- void* nFind = memchr(pchData, pchMessageStart[0], nRead+1-sizeof(pchMessageStart));
- if (nFind)
+ auto it = pchData.begin();
+ while(it != pchData.end() && !fRequestShutdown)
{
- if (memcmp(nFind, pchMessageStart, sizeof(pchMessageStart))==0)
+ auto nBlockLength = *reinterpret_cast<const uint32_t*>(&(*(it+4)));
+ auto SeekToNext = [&pchData, &it, &nPos, &nBlockLength]() {
+ auto previt = it;
+ it = search(it+8, pchData.end(), BEGIN(nNetworkID), END(nNetworkID));
+ if (it != pchData.end())
+ nPos += (it - previt);
+ };
+ if (nBlockLength > 0)
{
- nPos += ((unsigned char*)nFind - pchData) + sizeof(pchMessageStart);
- break;
+ if (nBlockLength > (uint32_t)distance(it, pchData.end()))
+ {
+ SeekToNext();
+ break; // We've reached the end of buffer
+ }
+ else
+ {
+ CBlock block;
+ try
+ {
+ vector<unsigned char> vchBlockBytes(it+8, it+8+nBlockLength);
+ CDataStream blockData(vchBlockBytes, SER_NETWORK, PROTOCOL_VERSION);
+ blockData >> block;
+ }
+ catch (const std::exception&)
+ {
+ printf("LoadExternalBlockFile() : Deserialize error caught at the position %" PRIu32 ", this block may be truncated.", nPos);
+ SeekToNext();
+ break;
+ }
+ if (ProcessBlock(NULL, &block))
+ nLoaded++;
+ advance(it, 8 + nBlockLength);
+ nPos += (8 + nBlockLength);
+ {
+ static int64_t nLastUpdate = 0;
+ if (GetTimeMillis() - nLastUpdate > 1000)
+ {
+ uiInterface.InitMessage(strprintf(_("%" PRId32 " blocks were read."), nLoaded));
+ nLastUpdate = GetTimeMillis();
+ }
+ }
+ }
+ }
+ else
+ {
+ SeekToNext();
}
- nPos += ((unsigned char*)nFind - pchData) + 1;
- }
- else
- nPos += sizeof(pchData) - sizeof(pchMessageStart) + 1;
- } while(!fRequestShutdown);
- if (nPos == std::numeric_limits<uint32_t>::max())
- break;
- fseek(blkdat, nPos, SEEK_SET);
- unsigned int nSize;
- blkdat >> nSize;
- if (nSize > 0 && nSize <= MAX_BLOCK_SIZE)
- {
- CBlock block;
- blkdat >> block;
- if (ProcessBlock(NULL,&block))
- {
- nLoaded++;
- nPos += 4 + nSize;
}
}
+ while(!fRequestShutdown);
}
}
catch (const std::exception&) {
- printf("%s() : Deserialize or I/O error caught during load\n",
+ printf("%s() : I/O error caught during load\n",
BOOST_CURRENT_FUNCTION);
}
}
strRPC = "test";
// Misc warnings like out of disk space and clock is wrong
- if (strMiscWarning != "")
+ if (!strMiscWarning.empty())
{
nPriority = 1000;
strStatusBar = strMiscWarning;
// Alerts
{
LOCK(cs_mapAlerts);
- BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
+ for(auto& item : mapAlerts)
{
const CAlert& alert = item.second;
if (alert.AppliesToMe() && alert.nPriority > nPriority)
bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
{
- switch (inv.type)
+ int nType = inv.GetType();
+ auto nHash = inv.GetHash();
+
+ switch (nType)
{
case MSG_TX:
{
bool txInMap = false;
{
LOCK(mempool.cs);
- txInMap = (mempool.exists(inv.hash));
+ txInMap = (mempool.exists(nHash));
}
return txInMap ||
- mapOrphanTransactions.count(inv.hash) ||
- txdb.ContainsTx(inv.hash);
+ mapOrphanTransactions.count(nHash) ||
+ txdb.ContainsTx(nHash);
}
case MSG_BLOCK:
- return mapBlockIndex.count(inv.hash) ||
- mapOrphanBlocks.count(inv.hash);
+ return mapBlockIndex.count(nHash) ||
+ mapOrphanBlocks.count(nHash);
}
// Don't know what it is, just say we already got one
return true;
}
-
-
-
-// The message start string is designed to be unlikely to occur in normal data.
-// The characters are rarely used upper ASCII, not valid as UTF-8, and produce
-// a large 4-byte int at any alignment.
-unsigned char pchMessageStart[4] = { 0xe4, 0xe8, 0xe9, 0xe5 };
-
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
static map<CService, CPubKey> mapReuseKey;
// Advertise our address
if (!fNoListen && !IsInitialBlockDownload())
{
- CAddress addr = GetLocalAddress(&pfrom->addr);
+ auto addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable())
pfrom->PushAddress(addr);
}
// Relay alerts
{
LOCK(cs_mapAlerts);
- BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
+ for(auto& item : mapAlerts)
item.second.RelayTo(pfrom);
}
// Store the new addresses
vector<CAddress> vAddrOk;
- int64_t nNow = GetAdjustedTime();
- int64_t nSince = nNow - 10 * 60;
- BOOST_FOREACH(CAddress& addr, vAddr)
+ auto nNow = GetAdjustedTime();
+ auto nSince = nNow - 10 * 60;
+ for(CAddress& addr : vAddr)
{
if (fShutdown)
return true;
hashSalt = GetRandHash();
uint64_t hashAddr = addr.GetHash();
uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/nOneDay);
- hashRand = Hash(BEGIN(hashRand), END(hashRand));
+ hashRand = Hash(hashRand.begin(), hashRand.end());
multimap<uint256, CNode*> mapMix;
- BOOST_FOREACH(CNode* pnode, vNodes)
+ for(CNode* pnode : vNodes)
{
if (pnode->nVersion < CADDR_TIME_VERSION)
continue;
unsigned int nPointer;
memcpy(&nPointer, &pnode, sizeof(nPointer));
uint256 hashKey = hashRand ^ nPointer;
- hashKey = Hash(BEGIN(hashKey), END(hashKey));
+ hashKey = Hash(hashKey.begin(), hashKey.end());
mapMix.insert(make_pair(hashKey, pnode));
}
int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
- for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
+ for (auto mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
((*mi).second)->PushAddress(addr);
}
}
}
// find last block in inv vector
- unsigned int nLastBlock = std::numeric_limits<uint32_t>::max();
- for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
- if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) {
- nLastBlock = vInv.size() - 1 - nInv;
+ int nLastBlock = -1;
+ for (size_t nInv = 0; nInv < vInv.size(); nInv++) {
+ if (vInv[vInv.size() - 1 - nInv].GetType() == MSG_BLOCK) {
+ nLastBlock = (int) (vInv.size() - 1 - nInv);
break;
}
}
CTxDB txdb("r");
- for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
+ for (size_t nInv = 0; nInv < vInv.size(); nInv++)
{
const CInv &inv = vInv[nInv];
+ int nType = inv.GetType();
+ auto nHash = inv.GetHash();
if (fShutdown)
return true;
if (!fAlreadyHave)
pfrom->AskFor(inv);
- else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
- pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
- } else if (nInv == nLastBlock) {
+ else if (nType == MSG_BLOCK && mapOrphanBlocks.count(nHash)) {
+ pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[nHash]));
+ } else if (nType == nLastBlock) {
// In case we are on a very long side-chain, it is possible that we already have
// the last block in an inv bundle sent in response to getblocks. Try to detect
// this situation and push another getblocks to continue.
- pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0));
+ pfrom->PushGetBlocks(mapBlockIndex[nHash], uint256(0));
if (fDebug)
printf("force request: %s\n", inv.ToString().c_str());
}
// Track requests for our stuff
- Inventory(inv.hash);
+ Inventory(nHash);
}
}
if (fDebugNet || (vInv.size() != 1))
printf("received getdata (%" PRIszu " invsz)\n", vInv.size());
- BOOST_FOREACH(const CInv& inv, vInv)
+ for(const CInv& inv : vInv)
{
if (fShutdown)
return true;
if (fDebugNet || (vInv.size() == 1))
printf("received getdata for: %s\n", inv.ToString().c_str());
- if (inv.type == MSG_BLOCK)
+ int nType = inv.GetType();
+ auto nHash = inv.GetHash();
+
+ if (nType == MSG_BLOCK)
{
// Send block from disk
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
+ auto mi = mapBlockIndex.find(nHash);
if (mi != mapBlockIndex.end())
{
CBlock block;
pfrom->PushMessage("block", block);
// Trigger them to send a getblocks request for the next batch of inventory
- if (inv.hash == pfrom->hashContinue)
+ if (nHash == pfrom->hashContinue)
{
// ppcoin: send latest proof-of-work block to allow the
// download node to accept as orphan (proof-of-stake
bool pushed = false;
{
LOCK(cs_mapRelay);
- map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
+ auto mi = mapRelay.find(inv);
if (mi != mapRelay.end()) {
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
pushed = true;
}
}
- if (!pushed && inv.type == MSG_TX) {
+ if (!pushed && nType == MSG_TX) {
LOCK(mempool.cs);
- if (mempool.exists(inv.hash)) {
- CTransaction tx = mempool.lookup(inv.hash);
+ if (mempool.exists(nHash)) {
+ CTransaction tx = mempool.lookup(nHash);
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << tx;
}
// Track requests for our stuff
- Inventory(inv.hash);
+ Inventory(nHash);
}
}
// Relay
pfrom->hashCheckpointKnown = checkpoint.hashCheckpoint;
LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
+ for(CNode* pnode : vNodes)
checkpoint.RelayTo(pnode);
}
}
if (locator.IsNull())
{
// If locator is null, return the hashStop block
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashStop);
+ auto mi = mapBlockIndex.find(hashStop);
if (mi == mapBlockIndex.end())
return true;
pindex = (*mi).second;
bool fMissingInputs = false;
if (tx.AcceptToMemoryPool(txdb, true, &fMissingInputs))
{
+ auto nHash = inv.GetHash();
+
SyncWithWallets(tx, NULL, true);
- RelayTransaction(tx, inv.hash);
+ RelayTransaction(tx, nHash);
mapAlreadyAskedFor.erase(inv);
- vWorkQueue.push_back(inv.hash);
- vEraseQueue.push_back(inv.hash);
+ vWorkQueue.push_back(nHash);
+ vEraseQueue.push_back(nHash);
// Recursively process any orphan transactions that depended on this one
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
{
- uint256 hashPrev = vWorkQueue[i];
- for (set<uint256>::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin();
+ auto hashPrev = vWorkQueue[i];
+ for (auto mi = mapOrphanTransactionsByPrev[hashPrev].begin();
mi != mapOrphanTransactionsByPrev[hashPrev].end();
++mi)
{
const uint256& orphanTxHash = *mi;
- CTransaction& orphanTx = mapOrphanTransactions[orphanTxHash];
+ auto& orphanTx = mapOrphanTransactions[orphanTxHash];
bool fMissingInputs2 = false;
if (orphanTx.AcceptToMemoryPool(txdb, true, &fMissingInputs2))
}
}
- BOOST_FOREACH(uint256 hash, vEraseQueue)
+ for(uint256 hash : vEraseQueue)
EraseOrphanTx(hash);
}
else if (fMissingInputs)
{
CBlock block;
vRecv >> block;
- uint256 hashBlock = block.GetHash();
+ auto hashBlock = block.GetHash();
printf("received block %s\n", hashBlock.ToString().substr(0,20).c_str());
// block.print();
int64_t nCutOff = GetTime() - (nNodeLifespan * nOneDay);
pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = addrman.GetAddr();
- BOOST_FOREACH(const CAddress &addr, vAddr)
+ for(const CAddress &addr : vAddr)
if(addr.nTime > nCutOff)
pfrom->PushAddress(addr);
}
CRequestTracker tracker;
{
LOCK(pfrom->cs_mapRequests);
- map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
+ auto mi = pfrom->mapRequests.find(hashReply);
if (mi != pfrom->mapRequests.end())
{
tracker = (*mi).second;
else if (strCommand == "ping")
{
- if (pfrom->nVersion > BIP0031_VERSION)
- {
- uint64_t nonce = 0;
- vRecv >> nonce;
- // Echo the message back with the nonce. This allows for two useful features:
- //
- // 1) A remote node can quickly check if the connection is operational
- // 2) Remote nodes can measure the latency of the network thread. If this node
- // is overloaded it won't respond to pings quickly and the remote node can
- // avoid sending us more work, like chain download requests.
- //
- // The nonce stops the remote getting confused between different pings: without
- // it, if the remote node sends a ping once per second and this node takes 5
- // seconds to respond to each, the 5th ping the remote sends would appear to
- // return very quickly.
- pfrom->PushMessage("pong", nonce);
- }
+ uint64_t nonce = 0;
+ vRecv >> nonce;
+ // Echo the message back with the nonce. This allows for two useful features:
+ //
+ // 1) A remote node can quickly check if the connection is operational
+ // 2) Remote nodes can measure the latency of the network thread. If this node
+ // is overloaded it won't respond to pings quickly and the remote node can
+ // avoid sending us more work, like chain download requests.
+ //
+ // The nonce stops the remote getting confused between different pings: without
+ // it, if the remote node sends a ping once per second and this node takes 5
+ // seconds to respond to each, the 5th ping the remote sends would appear to
+ // return very quickly.
+ pfrom->PushMessage("pong", nonce);
}
CAlert alert;
vRecv >> alert;
- uint256 alertHash = alert.GetHash();
+ auto alertHash = alert.GetHash();
if (pfrom->setKnown.count(alertHash) == 0)
{
if (alert.ProcessAlert())
pfrom->setKnown.insert(alertHash);
{
LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
+ for(CNode* pnode : vNodes)
alert.RelayTo(pnode);
}
}
// (x) data
//
- while (true)
+ for ( ; ; )
{
// Don't bother if send buffer is too full to respond anyway
if (pfrom->vSend.size() >= SendBufferSize())
break;
// Scan for message start
- CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
+ CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(nNetworkID), END(nNetworkID));
int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
if (vRecv.end() - pstart < nHeaderSize)
{
}
// Checksum
- uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
+ auto hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
unsigned int nChecksum = 0;
memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum)
}
-bool SendMessages(CNode* pto, bool fSendTrickle)
+bool SendMessages(CNode* pto)
{
TRY_LOCK(cs_main, lockMain);
if (lockMain) {
+ // Current time in microseconds
+ auto nNow = GetTimeMicros();
+
// Don't send anything until we get their version message
if (pto->nVersion == 0)
return true;
// right now.
if (pto->nLastSend && GetTime() - pto->nLastSend > nPingInterval && pto->vSend.empty()) {
uint64_t nonce = 0;
- if (pto->nVersion > BIP0031_VERSION)
- pto->PushMessage("ping", nonce);
- else
- pto->PushMessage("ping");
+ pto->PushMessage("ping", nonce);
}
// Start block sync
ResendWalletTransactions();
// Address refresh broadcast
- static int64_t nLastRebroadcast;
- if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > nBroadcastInterval))
- {
- {
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- {
- // Periodically clear setAddrKnown to allow refresh broadcasts
- if (nLastRebroadcast)
- pnode->setAddrKnown.clear();
-
- // Rebroadcast our address
- if (!fNoListen)
- {
- CAddress addr = GetLocalAddress(&pnode->addr);
- if (addr.IsRoutable())
- pnode->PushAddress(addr);
- }
- }
- }
- nLastRebroadcast = GetTime();
+ if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
+ AdvertiseLocal(pto);
+ pto->nNextLocalAddrSend = PoissonNextSend(nNow, nOneDay);
}
//
// Message: addr
//
- if (fSendTrickle)
- {
+ if (pto->nNextAddrSend < nNow) {
+ pto->nNextAddrSend = PoissonNextSend(nNow, 30);
vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
- BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
+ for(const CAddress& addr : pto->vAddrToSend)
{
- // returns true if wasn't already contained in the set
if (pto->setAddrKnown.insert(addr).second)
{
vAddr.push_back(addr);
pto->PushMessage("addr", vAddr);
}
-
//
// Message: inventory
//
vector<CInv> vInv;
vector<CInv> vInvWait;
{
+ bool fSendTrickle = false;
+ if (pto->nNextInvSend < nNow) {
+ fSendTrickle = true;
+ pto->nNextInvSend = PoissonNextSend(nNow, 5);
+ }
LOCK(pto->cs_inventory);
vInv.reserve(pto->vInventoryToSend.size());
vInvWait.reserve(pto->vInventoryToSend.size());
- BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
+ for(const CInv& inv : pto->vInventoryToSend)
{
if (pto->setInventoryKnown.count(inv))
continue;
// trickle out tx inv to protect privacy
- if (inv.type == MSG_TX && !fSendTrickle)
+ if (inv.GetType() == MSG_TX && !fSendTrickle)
{
// 1/4 of tx invs blast to all immediately
static uint256 hashSalt;
if (hashSalt == 0)
hashSalt = GetRandHash();
- uint256 hashRand = inv.hash ^ hashSalt;
- hashRand = Hash(BEGIN(hashRand), END(hashRand));
+ uint256 hashRand = inv.GetHash() ^ hashSalt;
+ hashRand = Hash(hashRand.begin(), hashRand.end());
bool fTrickleWait = ((hashRand & 3) != 0);
- // always trickle our own transactions
- if (!fTrickleWait)
- {
- CWalletTx wtx;
- if (GetTransaction(inv.hash, wtx))
- if (wtx.fFromMe)
- fTrickleWait = true;
- }
-
if (fTrickleWait)
{
vInvWait.push_back(inv);
// Message: getdata
//
vector<CInv> vGetData;
- int64_t nNow = GetTime() * 1000000;
CTxDB txdb("r");
while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
{
CMainCleanup() {}
~CMainCleanup() {
// block headers
- std::map<uint256, CBlockIndex*>::iterator it1 = mapBlockIndex.begin();
+ auto it1 = mapBlockIndex.begin();
for (; it1 != mapBlockIndex.end(); it1++)
delete (*it1).second;
mapBlockIndex.clear();
// orphan blocks
- std::map<uint256, CBlock*>::iterator it2 = mapOrphanBlocks.begin();
+ auto it2 = mapOrphanBlocks.begin();
for (; it2 != mapOrphanBlocks.end(); it2++)
delete (*it2).second;
mapOrphanBlocks.clear();