diff --git a/src/chain.h b/src/chain.h --- a/src/chain.h +++ b/src/chain.h @@ -93,8 +93,11 @@ //! blocks are received. int32_t nSequenceId; + //! (memory only) block metadata + uint64_t nTimeBlockReceived; + //! (memory only) block header metadata - uint64_t nTimeReceived; + uint64_t nTimeHeaderReceived; //! (memory only) Maximum nTime in the chain upto and including this block. unsigned int nTimeMax; @@ -117,7 +120,8 @@ nVersion = 0; hashMerkleRoot = uint256(); nTime = 0; - nTimeReceived = 0; + nTimeBlockReceived = 0; + nTimeHeaderReceived = 0; nBits = 0; nNonce = 0; } @@ -130,11 +134,13 @@ nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; nTime = block.nTime; - // Default to block time if nTimeReceived is never set, which + // Default to block time if nTime(Block/Header)Received is never set, + // which // in effect assumes that this block is honestly mined. // Note that nTimeReceived isn't written to disk, so blocks read from // disk will be assumed to be honestly mined. - nTimeReceived = block.nTime; + nTimeBlockReceived = block.nTime; + nTimeHeaderReceived = block.nTime; nBits = block.nBits; nNonce = block.nNonce; } @@ -176,7 +182,9 @@ int64_t GetBlockTimeMax() const { return int64_t(nTimeMax); } - int64_t GetHeaderReceivedTime() const { return nTimeReceived; } + int64_t GetBlockReceivedTime() const { return nTimeBlockReceived; } + + int64_t GetHeaderReceivedTime() const { return nTimeHeaderReceived; } int64_t GetReceivedTimeDiff() const { return GetHeaderReceivedTime() - GetBlockTime(); diff --git a/src/test/blockindex_tests.cpp b/src/test/blockindex_tests.cpp --- a/src/test/blockindex_tests.cpp +++ b/src/test/blockindex_tests.cpp @@ -6,6 +6,7 @@ #include "chain.h" #include "diskblockpos.h" #include "uint256.h" +#include "validation.h" #include "test/test_bitcoin.h" @@ -108,7 +109,7 @@ BOOST_CHECK(hash == randomHash); } -BOOST_AUTO_TEST_CASE(received_time) { +BOOST_AUTO_TEST_CASE(header_received_time) { // Set to UINT32_MAX because that's the maximum value header.nTime can hold const int64_t expectedBlockTime = std::numeric_limits::max(); @@ -118,14 +119,14 @@ CBlockIndex index = CBlockIndex(header); // nTimeReceived defaults to block time - BOOST_CHECK(index.nTimeReceived == expectedBlockTime); + BOOST_CHECK(index.nTimeHeaderReceived == expectedBlockTime); // nTimeReceived can be updated to the actual received time, which may // be before or after the miner's time. for (int64_t receivedTime = expectedBlockTime - 10; // Make sure that receivedTime is tested beyond 32-bit values. receivedTime <= expectedBlockTime + 10; receivedTime++) { - index.nTimeReceived = receivedTime; + index.nTimeHeaderReceived = receivedTime; BOOST_CHECK(index.GetBlockTime() == expectedBlockTime); BOOST_CHECK(index.GetHeaderReceivedTime() == receivedTime); BOOST_CHECK(index.GetReceivedTimeDiff() == @@ -133,6 +134,24 @@ } } +BOOST_FIXTURE_TEST_CASE(block_received_time, TestChain100Setup) { + // The time in the BlockHeader is the max of the MTP-11 and GetTime(). + // So we rewind the time, and check the received time before the blocktime.s + time_t mockedTime = GetTime() - 600; + SetMockTime(mockedTime); + + CBlock block = CreateAndProcessBlock({}, CScript() << OP_TRUE); + BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); + CBlockIndex *pindex = nullptr; + BOOST_CHECK(mapBlockIndex.count(block.GetHash()) == 1); + pindex = mapBlockIndex[block.GetHash()]; + + BOOST_CHECK(pindex->GetBlockReceivedTime() == mockedTime); + // We don't know the exact MTP-11, but it should be AT LEAST 590 seconds + // ahead. + BOOST_CHECK(pindex->GetBlockTime() > mockedTime + 590); +} + BOOST_AUTO_TEST_CASE(median_time_past) { std::array indices; diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3066,7 +3066,7 @@ pindexNew->nHeight = pindexNew->pprev->nHeight + 1; pindexNew->BuildSkip(); } - pindexNew->nTimeReceived = GetTime(); + pindexNew->nTimeHeaderReceived = GetTime(); pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) @@ -3098,6 +3098,7 @@ pindexNew->nUndoPos = 0; pindexNew->nStatus = pindexNew->nStatus.withData(); pindexNew->RaiseValidity(BlockValidity::TRANSACTIONS); + pindexNew->nTimeBlockReceived = GetTime(); setDirtyBlockIndex.insert(pindexNew); if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) {