X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fmain.cpp;h=c41f43ad3b963d6f422ff109cfb62737bbabdf55;hp=f6adb17281915fa33f81bb4c93fdadaee6a65b72;hb=8e064484abe4d65e15e3ec1bcdbb2b91f97dd726;hpb=47bb141bf2d589db630ac1a917189b05b75b80d0 diff --git a/src/main.cpp b/src/main.cpp index f6adb17..c41f43a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,6 @@ #include "checkpoints.h" #include "db.h" #include "txdb.h" -#include "net.h" #include "init.h" #include "ui_interface.h" #include "checkqueue.h" @@ -81,7 +80,6 @@ int64_t nMinimumInputValue = MIN_TXOUT_AMOUNT; // Ping and address broadcast intervals int64_t nPingInterval = 30 * 60; -int64_t nBroadcastInterval = nOneDay; extern enum Checkpoints::CPMode CheckpointsMode; @@ -182,10 +180,10 @@ void static Inventory(const uint256& hash) } // ask wallets to resend their transactions -void ResendWalletTransactions() +void ResendWalletTransactions(bool fForceResend) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) - pwallet->ResendWalletTransactions(); + pwallet->ResendWalletTransactions(fForceResend); } @@ -430,7 +428,7 @@ unsigned int 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. @@ -511,10 +509,6 @@ bool CTransaction::CheckTransaction() const 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")); @@ -623,6 +617,10 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, 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"); @@ -1190,10 +1188,10 @@ const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfSta 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) @@ -1759,8 +1757,16 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) 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 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); } @@ -1831,11 +1837,11 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) 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"); } @@ -2138,7 +2144,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) 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; @@ -2340,9 +2346,9 @@ bool CBlock::AcceptBlock() 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()) @@ -2501,7 +2507,7 @@ bool static ReserealizeBlockSignature(CBlock* pblock) return true; } - return CKey::ReserealizeSignature(pblock->vchBlockSig); + return CPubKey::ReserealizeSignature(pblock->vchBlockSig); } bool static IsCanonicalBlockSignature(CBlock* pblock) @@ -2521,6 +2527,13 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) 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 @@ -2653,8 +2666,8 @@ bool CBlock::CheckBlockSignature() const if (whichType == TX_PUBKEY) { valtype& vchPubKey = vSolutions[0]; - CKey key; - if (!key.SetPubKey(vchPubKey)) + CPubKey key(vchPubKey); + if (!key.IsValid()) return false; return key.Verify(GetHash(), vchBlockSig); } @@ -2709,7 +2722,7 @@ static unsigned int nCurrentBlockFile = 1; FILE* AppendBlockFile(unsigned int& nFileRet) { nFileRet = 0; - while (true) + for ( ; ; ) { FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab"); if (!file) @@ -2960,7 +2973,7 @@ bool LoadExternalBlockFile(FILE* fileIn) unsigned char pchData[65536]; do { fseek(blkdat, nPos, SEEK_SET); - int nRead = fread(pchData, 1, sizeof(pchData), blkdat); + size_t nRead = fread(pchData, 1, sizeof(pchData), blkdat); if (nRead <= 8) { nPos = std::numeric_limits::max(); @@ -3023,7 +3036,7 @@ string GetWarnings(string strFor) strRPC = "test"; // Misc warnings like out of disk space and clock is wrong - if (strMiscWarning != "") + if (!strMiscWarning.empty()) { nPriority = 1000; strStatusBar = strMiscWarning; @@ -3348,15 +3361,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } // find last block in inv vector - unsigned int nLastBlock = std::numeric_limits::max(); - for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { + size_t nLastBlock = std::numeric_limits::max(); + for (size_t nInv = 0; nInv < vInv.size(); nInv++) { if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) { nLastBlock = 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]; @@ -3672,7 +3685,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (!GetBoolArg("-allowreceivebyip")) { - pfrom->PushMessage("reply", hashReply, (int)2, string("")); + pfrom->PushMessage("reply", hashReply, 2, string("")); return true; } @@ -3688,7 +3701,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // Send back approval of order and pubkey to use CScript scriptPubKey; scriptPubKey << mapReuseKey[pfrom->addr] << OP_CHECKSIG; - pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey); + pfrom->PushMessage("reply", hashReply, 0, scriptPubKey); } @@ -3714,23 +3727,20 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) 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); } @@ -3797,7 +3807,7 @@ bool ProcessMessages(CNode* pfrom) // (x) data // - while (true) + for ( ; ; ) { // Don't bother if send buffer is too full to respond anyway if (pfrom->vSend.size() >= SendBufferSize()) @@ -3906,6 +3916,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle) { TRY_LOCK(cs_main, lockMain); if (lockMain) { + // Current time in microseconds + int64_t nNow = GetTimeMicros(); + // Don't send anything until we get their version message if (pto->nVersion == 0) return true; @@ -3914,10 +3927,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // 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 @@ -3930,39 +3940,20 @@ bool SendMessages(CNode* pto, bool fSendTrickle) 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 vAddr; vAddr.reserve(pto->vAddrToSend.size()); BOOST_FOREACH(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); @@ -3979,13 +3970,17 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->PushMessage("addr", vAddr); } - // // Message: inventory // vector vInv; vector 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()); @@ -4005,15 +4000,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle) hashRand = Hash(BEGIN(hashRand), END(hashRand)); 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); @@ -4042,7 +4028,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Message: getdata // vector vGetData; - int64_t nNow = GetTime() * 1000000; CTxDB txdb("r"); while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow) {