X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=bf91707e591a94340deb8107966104a52ae377cd;hb=40a76f11c7056c53f71bfc60419ba7354016f55f;hp=d96af0a28610ab9f77e2ecb237c0804dc6485207;hpb=e1fc548ff893f35d24565b381eca454ba6319ef4;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index d96af0a..bf91707 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,10 +42,10 @@ uint256 nPoWBase = uint256("0x00000000ffff00000000000000000000000000000000000000 CBigNum bnProofOfWorkLimitTestNet(~uint256(0) >> 16); -unsigned int nStakeMinAge = 60 * 60 * 24 * 30; // 30 days as zero time weight -unsigned int nStakeMaxAge = 60 * 60 * 24 * 90; // 90 days as full weight +unsigned int nStakeMinAge = 30 * nOneDay; // 30 days as zero time weight +unsigned int nStakeMaxAge = 90 * nOneDay; // 90 days as full weight unsigned int nStakeTargetSpacing = 10 * 60; // 10-minute stakes spacing -unsigned int nModifierInterval = 6 * 60 * 60; // time to elapse before new modifier is computed +unsigned int nModifierInterval = 6 * nOneHour; // time to elapse before new modifier is computed int nCoinbaseMaturity = 500; @@ -511,6 +511,10 @@ 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")); @@ -2335,10 +2339,19 @@ bool CBlock::AcceptBlock() if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake())) 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 + // Check timestamp against prev - if (GetBlockTime() <= pindexPrev->GetMedianTimePast() || FutureDrift(GetBlockTime()) < pindexPrev->GetBlockTime()) + if (GetBlockTime() <= nMedianTimePast || FutureDrift(GetBlockTime()) < pindexPrev->GetBlockTime()) return error("AcceptBlock() : block's timestamp is too early"); + // Don't accept blocks with future timestamps + if (pindexPrev->nHeight > 1 && nMedianTimePast + nMaxOffset < 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) if (!tx.IsFinal(nHeight, GetBlockTime())) @@ -2675,7 +2688,7 @@ static filesystem::path BlockFilePath(unsigned int nFile) FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode) { - if ((nFile < 1) || (nFile == (unsigned int) -1)) + if ((nFile < 1) || (nFile == std::numeric_limits::max())) return NULL; FILE* file = fopen(BlockFilePath(nFile).string().c_str(), pszMode); if (!file) @@ -2736,7 +2749,7 @@ bool LoadBlockIndex(bool fAllowNew) pchMessageStart[3] = 0xef; bnProofOfWorkLimit = bnProofOfWorkLimitTestNet; // 16 bits PoW target limit for testnet - nStakeMinAge = 2 * 60 * 60; // test net min age is 2 hours + nStakeMinAge = 2 * nOneHour; // test net min age is 2 hours nModifierInterval = 20 * 60; // test modifier interval is 20 minutes nCoinbaseMaturity = 10; // test maturity is 10 blocks nStakeTargetSpacing = 5 * 60; // test block spacing is 5 minutes @@ -2942,7 +2955,7 @@ bool LoadExternalBlockFile(FILE* fileIn) try { CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION); unsigned int nPos = 0; - while (nPos != (unsigned int)-1 && blkdat.good() && !fRequestShutdown) + while (nPos != std::numeric_limits::max() && blkdat.good() && !fRequestShutdown) { unsigned char pchData[65536]; do { @@ -2950,7 +2963,7 @@ bool LoadExternalBlockFile(FILE* fileIn) int nRead = fread(pchData, 1, sizeof(pchData), blkdat); if (nRead <= 8) { - nPos = (unsigned int)-1; + nPos = std::numeric_limits::max(); break; } void* nFind = memchr(pchData, pchMessageStart[0], nRead+1-sizeof(pchMessageStart)); @@ -2966,7 +2979,7 @@ bool LoadExternalBlockFile(FILE* fileIn) else nPos += sizeof(pchData) - sizeof(pchMessageStart) + 1; } while(!fRequestShutdown); - if (nPos == (unsigned int)-1) + if (nPos == std::numeric_limits::max()) break; fseek(blkdat, nPos, SEEK_SET); unsigned int nSize; @@ -3018,7 +3031,7 @@ string GetWarnings(string strFor) // if detected unmet upgrade requirement enter safe mode // Note: Modifier upgrade requires blockchain redownload if past protocol switch - if (IsFixedModifierInterval(nModifierUpgradeTime + 60*60*24)) // 1 day margin + if (IsFixedModifierInterval(nModifierUpgradeTime + nOneDay)) // 1 day margin { nPriority = 5000; strStatusBar = strRPC = "WARNING: Blockchain redownload required approaching or past v.0.4.4.6u4 upgrade deadline."; @@ -3295,7 +3308,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (hashSalt == 0) hashSalt = GetRandHash(); uint64_t hashAddr = addr.GetHash(); - uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60)); + uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/nOneDay); hashRand = Hash(BEGIN(hashRand), END(hashRand)); multimap mapMix; BOOST_FOREACH(CNode* pnode, vNodes) @@ -3317,7 +3330,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (fReachable) vAddrOk.push_back(addr); } - addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); + addrman.Add(vAddrOk, pfrom->addr, 2 * nOneHour); if (vAddr.size() < 1000) pfrom->fGetAddr = false; if (pfrom->fOneShot) @@ -3335,7 +3348,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } // find last block in inv vector - unsigned int nLastBlock = (unsigned int)(-1); + unsigned int nLastBlock = std::numeric_limits::max(); for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) { nLastBlock = vInv.size() - 1 - nInv; @@ -3619,7 +3632,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } - else if (strCommand == "getaddr") + // This asymmetric behavior for inbound and outbound connections was introduced + // to prevent a fingerprinting attack: an attacker can send specific fake addresses + // to users' AddrMan and later request them by sending getaddr messages. + // Making users (which are behind NAT and can only make outgoing connections) ignore + // getaddr message mitigates the attack. + else if ((strCommand == "getaddr") && (pfrom->fInbound)) { // Don't return addresses older than nCutOff timestamp int64_t nCutOff = GetTime() - (nNodeLifespan * nOneDay); @@ -3654,7 +3672,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; } @@ -3670,7 +3688,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); } @@ -4070,4 +4088,4 @@ public: // orphan transactions } -} instance_of_cmaincleanup; \ No newline at end of file +} instance_of_cmaincleanup;