This commit is contained in:
Ross Nicoll 2021-10-18 13:28:56 +06:00 committed by GitHub
commit c2380ec5c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 66 deletions

View file

@ -116,7 +116,7 @@ static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
/** Maximum number of unconnecting headers announcements before DoS score */
static const int MAX_UNCONNECTING_HEADERS = 10;
/** Minimum blocks required to signal NODE_NETWORK_LIMITED */
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 1440;
/** Average delay between local address broadcasts */
static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24};
/** Average delay between peer address broadcasts */

View file

@ -288,7 +288,7 @@ enum ServiceFlags : uint64_t {
// See BIP157 and BIP158 for details on how this is implemented.
NODE_COMPACT_FILTERS = (1 << 6),
// NODE_NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only
// serving the last 288 (2 day) blocks
// serving the last 1,440 (1 day) blocks
// See BIP159 for details on how this is implemented.
NODE_NETWORK_LIMITED = (1 << 10),

View file

@ -1364,12 +1364,12 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
if (::ChainstateActive().IsInitialBlockDownload())
return;
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
// If our best fork is no longer within 360 blocks (+/- 6 hours if no one mines it)
// of our head, drop it
if (pindexBestForkTip && ::ChainActive().Height() - pindexBestForkTip->nHeight >= 72)
if (pindexBestForkTip && ::ChainActive().Height() - pindexBestForkTip->nHeight >= 360)
pindexBestForkTip = nullptr;
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6)))
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 30)))
{
if (!GetfLargeWorkForkFound() && pindexBestForkBase)
{
@ -2056,8 +2056,8 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the
// two in the chain that violate it. This prevents exploiting the issue against nodes during their
// initial block download.
bool fEnforceBIP30 = !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
// Dogecoin: BIP30 has been active since inception
bool fEnforceBIP30 = true;
// Once BIP34 activated it was not possible to create new duplicate coinbases and thus other than starting
// with the 2 existing duplicate coinbase pairs, not possible to create overwriting txs. But by the

View file

@ -81,18 +81,18 @@ static const bool DEFAULT_FEEFILTER = true;
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
static const unsigned int MIN_BLOCKS_TO_KEEP = 1440;
static const signed int DEFAULT_CHECKBLOCKS = 6;
static const unsigned int DEFAULT_CHECKLEVEL = 3;
// Require that user allocate at least 550 MiB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 288 blocks = 288MB.
// Add 15% for Undo data = 331MB
// Add 20% for Orphan block rate = 397MB
// We want the low water mark after pruning to be at least 397 MB and since we prune in
// Require that user allocate at least 2,200 MiB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 1,440 blocks = 1,440MB.
// Add 15% for Undo data = 1,656MB
// Add 20% for Orphan block rate = 1,987MB
// We want the low water mark after pruning to be at least 1,987 MB and since we prune in
// full block file chunks, we need the high water mark which triggers the prune to be
// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
// Setting the target to >= 550 MiB will make it likely we can respect the target.
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
// one 128MB block file + added 15% undo data = 2,134MB greater for a total of 545MB
// Setting the target to >= 2,200 MiB will make it likely we can respect the target.
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 2200ULL * 1024 * 1024;
struct BlockHasher
{
@ -370,7 +370,7 @@ private:
* Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set.
* Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)
* Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest).
* Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.
* Pruning will never delete a block within a defined distance (currently 1,440) from the active chain's tip.
* The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.
* A db flag records the fact that at least some block files have been pruned.
*

View file

@ -4,9 +4,9 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Tests NODE_NETWORK_LIMITED.
Tests that a node configured with -prune=550 signals NODE_NETWORK_LIMITED correctly
Tests that a node configured with -prune=2250 signals NODE_NETWORK_LIMITED correctly
and that it responds to getdata requests for blocks correctly:
- send a block within 288 + 2 of the tip
- send a block within 1440 + 2 of the tip
- disconnect peers who request blocks older than that."""
from test_framework.messages import CInv, MSG_BLOCK, msg_getdata, msg_verack, NODE_NETWORK_LIMITED, NODE_WITNESS
from test_framework.p2p import P2PInterface
@ -35,7 +35,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
self.extra_args = [['-prune=550', '-addrmantest'], [], []]
self.extra_args = [['-prune=2250', '-addrmantest'], [], []]
def disconnect_all(self):
self.disconnect_nodes(0, 1)
@ -59,15 +59,15 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
self.connect_nodes(0, 1)
blocks = self.nodes[1].generatetoaddress(292, self.nodes[1].get_deterministic_priv_key().address)
blocks = self.nodes[1].generatetoaddress(1444, self.nodes[1].get_deterministic_priv_key().address)
self.sync_blocks([self.nodes[0], self.nodes[1]])
self.log.info("Make sure we can max retrieve block at tip-288.")
self.log.info("Make sure we can max retrieve block at tip-1440.")
node.send_getdata_for_block(blocks[1]) # last block in valid range
node.wait_for_block(int(blocks[1], 16), timeout=3)
self.log.info("Requesting block at height 2 (tip-289) must fail (ignored).")
node.send_getdata_for_block(blocks[0]) # first block outside of the 288+2 limit
self.log.info("Requesting block at height 2 (tip-1440) must fail (ignored).")
node.send_getdata_for_block(blocks[0]) # first block outside of the 1440+2 limit
node.wait_for_disconnect(5)
self.log.info("Check local address relay, do a fresh connection.")

View file

@ -27,7 +27,7 @@ Node1 is unused in tests 3-7:
Node0 should process the second block but be stuck on the shorter chain,
because it's missing an intermediate block.
4c.Send 288 more blocks on the longer chain (the number of blocks ahead
4c.Send 1440 more blocks on the longer chain (the number of blocks ahead
we currently store).
Node0 should process all but the last block (too far ahead in height).
@ -147,12 +147,12 @@ class AcceptBlockTest(BitcoinTestFramework):
self.nodes[0].getblock(block_h3.hash)
self.log.info("Unrequested more-work block accepted")
# 4c. Now mine 288 more blocks and deliver; all should be processed but
# 4c. Now mine 1440 more blocks and deliver; all should be processed but
# the last (height-too-high) on node (as long as it is not missing any headers)
tip = block_h3
all_blocks = []
for i in range(288):
next_block = create_block(tip.sha256, create_coinbase(i + 4), tip.nTime+1)
for i in range(1440):
next_block = create_block(tip.sha256, create_coinbase(i + 4), tip.nTime+1, version=4)
next_block.solve()
all_blocks.append(next_block)
tip = next_block
@ -170,11 +170,11 @@ class AcceptBlockTest(BitcoinTestFramework):
self.nodes[0].getblock(all_blocks[1].hash)
# Now send the blocks in all_blocks
for i in range(288):
for i in range(1440):
test_node.send_message(msg_block(all_blocks[i]))
test_node.sync_with_ping()
# Blocks 1-287 should be accepted, block 288 should be ignored because it's too far ahead
# Blocks 1-1439 should be accepted, block 1440 should be ignored because it's too far ahead
for x in all_blocks[:-1]:
self.nodes[0].getblock(x.hash)
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, all_blocks[-1].hash)
@ -213,49 +213,49 @@ class AcceptBlockTest(BitcoinTestFramework):
# 7. Send the missing block for the third time (now it is requested)
test_node.send_and_ping(msg_block(block_h1f))
assert_equal(self.nodes[0].getblockcount(), 290)
self.nodes[0].getblock(all_blocks[286].hash)
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, all_blocks[287].hash)
assert_equal(self.nodes[0].getblockcount(), 1442)
self.nodes[0].getblock(all_blocks[1438].hash)
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[1438].hash)
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, all_blocks[1439].hash)
self.log.info("Successfully reorged to longer chain")
# 8. Create a chain which is invalid at a height longer than the
# current chain, but which has more blocks on top of that
block_289f = create_block(all_blocks[284].sha256, create_coinbase(289), all_blocks[284].nTime+1)
block_289f.solve()
block_290f = create_block(block_289f.sha256, create_coinbase(290), block_289f.nTime+1)
block_290f.solve()
block_291 = create_block(block_290f.sha256, create_coinbase(291), block_290f.nTime+1)
# block_291 spends a coinbase below maturity!
block_291.vtx.append(create_tx_with_script(block_290f.vtx[0], 0, script_sig=b"42", amount=1))
block_291.hashMerkleRoot = block_291.calc_merkle_root()
block_291.solve()
block_292 = create_block(block_291.sha256, create_coinbase(292), block_291.nTime+1)
block_292.solve()
block_1441f = create_block(all_blocks[1436].sha256, create_coinbase(1441), all_blocks[1436].nTime+1, version=4)
block_1441f.solve()
block_1442f = create_block(block_1441f.sha256, create_coinbase(1442), block_1441f.nTime+1, version=4)
block_1442f.solve()
block_1443 = create_block(block_1442f.sha256, create_coinbase(1443), block_1442f.nTime+1, version=4)
# block_1443 spends a coinbase below maturity!
block_1443.vtx.append(create_tx_with_script(block_1442f.vtx[0], 0, script_sig=b"42", amount=1))
block_1443.hashMerkleRoot = block_1443.calc_merkle_root()
block_1443.solve()
block_1444 = create_block(block_1443.sha256, create_coinbase(1444), block_1443.nTime+1, version=4)
block_1444.solve()
# Now send all the headers on the chain and enough blocks to trigger reorg
headers_message = msg_headers()
headers_message.headers.append(CBlockHeader(block_289f))
headers_message.headers.append(CBlockHeader(block_290f))
headers_message.headers.append(CBlockHeader(block_291))
headers_message.headers.append(CBlockHeader(block_292))
headers_message.headers.append(CBlockHeader(block_1441f))
headers_message.headers.append(CBlockHeader(block_1442f))
headers_message.headers.append(CBlockHeader(block_1443))
headers_message.headers.append(CBlockHeader(block_1444))
test_node.send_and_ping(headers_message)
tip_entry_found = False
for x in self.nodes[0].getchaintips():
if x['hash'] == block_292.hash:
if x['hash'] == block_1444.hash:
assert_equal(x['status'], "headers-only")
tip_entry_found = True
assert tip_entry_found
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, block_292.hash)
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, block_1444.hash)
test_node.send_message(msg_block(block_289f))
test_node.send_and_ping(msg_block(block_290f))
test_node.send_message(msg_block(block_1441f))
test_node.send_and_ping(msg_block(block_1442f))
self.nodes[0].getblock(block_289f.hash)
self.nodes[0].getblock(block_290f.hash)
self.nodes[0].getblock(block_1441f.hash)
self.nodes[0].getblock(block_1442f.hash)
test_node.send_message(msg_block(block_291))
test_node.send_message(msg_block(block_1443))
# At this point we've sent an obviously-bogus block, wait for full processing
# without assuming whether we will be disconnected or not
@ -269,16 +269,16 @@ class AcceptBlockTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
# We should have failed reorg and switched back to 290 (but have block 291)
assert_equal(self.nodes[0].getblockcount(), 290)
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
assert_equal(self.nodes[0].getblock(block_291.hash)["confirmations"], -1)
# We should have failed reorg and switched back to 1442 (but have block 1443)
assert_equal(self.nodes[0].getblockcount(), 1442)
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[1438].hash)
assert_equal(self.nodes[0].getblock(block_1443.hash)["confirmations"], -1)
# Now send a new header on the invalid chain, indicating we're forked off, and expect to get disconnected
block_293 = create_block(block_292.sha256, create_coinbase(293), block_292.nTime+1)
block_293.solve()
block_1445 = create_block(block_1444.sha256, create_coinbase(1445), block_1444.nTime+1)
block_1445.solve()
headers_message = msg_headers()
headers_message.headers.append(CBlockHeader(block_293))
headers_message.headers.append(CBlockHeader(block_1445))
test_node.send_message(headers_message)
test_node.wait_for_disconnect()

View file

@ -112,16 +112,16 @@ class BlockchainTest(BitcoinTestFramework):
# should have exact keys
assert_equal(sorted(res.keys()), keys)
self.restart_node(0, ['-stopatheight=207', '-prune=550'])
self.restart_node(0, ['-stopatheight=207', '-prune=2200'])
res = self.nodes[0].getblockchaininfo()
# result should have these additional pruning keys if prune=550
# result should have these additional pruning keys if prune=2200
assert_equal(sorted(res.keys()), sorted(['pruneheight', 'automatic_pruning', 'prune_target_size'] + keys))
# check related fields
assert res['pruned']
assert_equal(res['pruneheight'], 0)
assert res['automatic_pruning']
assert_equal(res['prune_target_size'], 576716800)
assert_equal(res['prune_target_size'], 2306867200)
assert_greater_than(res['size_on_disk'], 0)
assert_equal(res['softforks'], {