From 19ef5883912d85b3df003ba8e26a923dc9eeec98 Mon Sep 17 00:00:00 2001 From: Martin Stefcek Date: Mon, 23 Aug 2021 11:35:11 +0200 Subject: [PATCH] test: cucumber forced sync --- .../sync/header_sync/synchronizer.rs | 4 +-- common/src/configuration/global.rs | 12 ++++---- integration_tests/features/Sync.feature | 29 ++++++++++++++++--- integration_tests/features/support/steps.js | 20 +++++++++++++ integration_tests/features/support/world.js | 2 +- integration_tests/helpers/baseNodeProcess.js | 8 ++++- integration_tests/helpers/config.js | 10 +++++-- 7 files changed, 69 insertions(+), 16 deletions(-) diff --git a/base_layer/core/src/base_node/sync/header_sync/synchronizer.rs b/base_layer/core/src/base_node/sync/header_sync/synchronizer.rs index 426e564a42a..8ff487a8e5a 100644 --- a/base_layer/core/src/base_node/sync/header_sync/synchronizer.rs +++ b/base_layer/core/src/base_node/sync/header_sync/synchronizer.rs @@ -480,8 +480,8 @@ impl<'a, B: BlockchainBackend + 'static> HeaderSynchronizer<'a, B> { ) -> Result<(), BlockHeaderSyncError> { const COMMIT_EVERY_N_HEADERS: usize = 1000; - // Peer returned less than the max headers. This indicates that there are no further headers to request. - if self.header_validator.valid_headers().len() < NUM_INITIAL_HEADERS_TO_REQUEST as usize { + // Peer returned no more than the max headers. This indicates that there are no further headers to request. + if self.header_validator.valid_headers().len() <= NUM_INITIAL_HEADERS_TO_REQUEST as usize { debug!(target: LOG_TARGET, "No further headers to download"); if !self.pending_chain_has_higher_pow(&split_info.local_tip_header)? { return Err(BlockHeaderSyncError::WeakerChain); diff --git a/common/src/configuration/global.rs b/common/src/configuration/global.rs index 7d1b8c7f98a..f6e2e159f62 100644 --- a/common/src/configuration/global.rs +++ b/common/src/configuration/global.rs @@ -401,11 +401,13 @@ fn convert_node_config( // block sync let key = config_string("base_node", &net_str, "force_sync_peers"); - let force_sync_peers = optional( - cfg.get_array(&key) - .map(|values| values.into_iter().map(|v| v.into_str().unwrap()).collect()), - )? - .unwrap_or_default(); + let force_sync_peers = match cfg.get_array(&key) { + Ok(peers) => peers.into_iter().map(|v| v.into_str().unwrap()).collect(), + Err(..) => match cfg.get_str(&key) { + Ok(s) => s.split(',').map(|v| v.to_string()).collect(), + Err(..) => vec![], + }, + }; // Liveness auto ping interval let key = config_string("base_node", &net_str, "auto_ping_interval"); diff --git a/integration_tests/features/Sync.feature b/integration_tests/features/Sync.feature index 497a59e6f68..396daad1cf3 100644 --- a/integration_tests/features/Sync.feature +++ b/integration_tests/features/Sync.feature @@ -25,7 +25,7 @@ Feature: Block Sync # All nodes should sync to tip Then all nodes are at height 20 - @critical + @critical Scenario: Pruned mode simple sync Given I have 1 seed nodes Given I have a SHA3 miner NODE1 connected to all seed nodes @@ -36,7 +36,7 @@ Feature: Block Sync Given I have a pruned node PNODE1 connected to node NODE1 with pruning horizon set to 5 Then all nodes are at height 20 -@critical + @critical Scenario: When a new node joins the network, it should receive all peers Given I have 10 seed nodes And I have a base node NODE1 connected to all seed nodes @@ -103,7 +103,7 @@ Feature: Block Sync When I mine 15 blocks on PNODE2 Then all nodes are at height 23 - Scenario: Node should not sync from pruned node + Scenario: Node should not sync from pruned node Given I have a base node NODE1 connected to all seed nodes Given I have a pruned node PNODE1 connected to node NODE1 with pruning horizon set to 5 When I mine 40 blocks on NODE1 @@ -152,7 +152,7 @@ Feature: Block Sync | X1 | Y1 | SYNC_TIME | | 1000 | 50 | 60 | -Scenario: Pruned mode network only + Scenario: Pruned mode network only Given I have a base node NODE1 connected to all seed nodes Given I have a pruned node PNODE1 connected to node NODE1 with pruning horizon set to 5 Given I have a pruned node PNODE2 connected to node PNODE1 with pruning horizon set to 5 @@ -167,3 +167,24 @@ Scenario: Pruned mode network only Then node PNODE2 is at height 20 Given I have a pruned node PNODE3 connected to node PNODE1 with pruning horizon set to 5 Then node PNODE3 is at height 20 + + Scenario Outline: Force sync many nodes agains one peer + Given I have a base node BASE + And I have a SHA3 miner MINER connected to node BASE + And mining node MINER mines blocks + And I have base nodes with pruning horizon force syncing on node BASE + When I wait seconds + Then all nodes are at height + + @critical @long-running + Examples: + | NODES | BLOCKS | PRUNE_HORIZON | SYNC_TIME | + | 5 | 100 | 0 | 30 | + | 10 | 100 | 0 | 30 | + | 20 | 100 | 0 | 30 | + | 5 | 1001 | 0 | 60 | + | 10 | 1001 | 0 | 60 | + | 20 | 1001 | 0 | 60 | + | 5 | 1001 | 100 | 90 | + | 10 | 1001 | 100 | 90 | + | 20 | 1001 | 100 | 90 | diff --git a/integration_tests/features/support/steps.js b/integration_tests/features/support/steps.js index 2d13f664b67..d7af185e852 100644 --- a/integration_tests/features/support/steps.js +++ b/integration_tests/features/support/steps.js @@ -3609,3 +3609,23 @@ Then( wallet.clearCallbackCounters(); } ); + +When( + "I have {int} base nodes with pruning horizon {int} force syncing on node {word}", + { timeout: 190 * 1000 }, + async function (nodes_count, horizon, force_sync_to) { + const promises = []; + const force_sync_address = this.getNode(force_sync_to).peerAddress(); + for (let i = 0; i < nodes_count; i++) { + const base_node = this.createNode(`BaseNode${i}`, { + pruningHorizon: horizon, + }); + base_node.setPeerSeeds([force_sync_address]); + base_node.setForceSyncPeers([force_sync_address]); + promises.push( + base_node.startNew().then(() => this.addNode(`BaseNode${i}`, base_node)) + ); + } + await Promise.all(promises); + } +); diff --git a/integration_tests/features/support/world.js b/integration_tests/features/support/world.js index 1bf8283768d..a0fd19dd1aa 100644 --- a/integration_tests/features/support/world.js +++ b/integration_tests/features/support/world.js @@ -280,7 +280,7 @@ class CustomWorld { console.error(err); failed += 1; if (failed > canFail) - reject(`Too many failed. Expected less than ${canFail} failures`); + reject(`Too many failed. Expected at most ${canFail} failures`); }); } }); diff --git a/integration_tests/helpers/baseNodeProcess.js b/integration_tests/helpers/baseNodeProcess.js index a4a74ab41c8..d35edb06862 100644 --- a/integration_tests/helpers/baseNodeProcess.js +++ b/integration_tests/helpers/baseNodeProcess.js @@ -85,6 +85,10 @@ class BaseNodeProcess { this.peerSeeds = addresses.join(","); } + setForceSyncPeers(addresses) { + this.forceSyncPeers = addresses.join(","); + } + getGrpcAddress() { const address = "127.0.0.1:" + this.grpcPort; // console.log("Base Node GRPC Address:",address); @@ -113,7 +117,9 @@ class BaseNodeProcess { "127.0.0.1:8080", "127.0.0.1:8085", this.options, - this.peerSeeds + this.peerSeeds, + "DirectAndStoreAndForward", + this.forceSyncPeers ); } diff --git a/integration_tests/helpers/config.js b/integration_tests/helpers/config.js index 14e75995675..ef06a754495 100644 --- a/integration_tests/helpers/config.js +++ b/integration_tests/helpers/config.js @@ -57,7 +57,7 @@ function mapEnvs(options) { return res; } -function baseEnvs(peerSeeds = []) { +function baseEnvs(peerSeeds = [], forceSyncPeers = []) { const envs = { RUST_BACKTRACE: 1, TARI_BASE_NODE__NETWORK: "localnet", @@ -101,6 +101,9 @@ function baseEnvs(peerSeeds = []) { TARI_MINING_NODE__VALIDATE_TIP_TIMEOUT_SEC: 2, TARI_WALLET__SCAN_FOR_UTXO_INTERVAL: 5, }; + if (forceSyncPeers.length != 0) { + envs.TARI_BASE_NODE__LOCALNET__FORCE_SYNC_PEERS = forceSyncPeers; + } if (peerSeeds.length != 0) { envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = peerSeeds; } else { @@ -127,9 +130,10 @@ function createEnv( transcoderFullAddress = "127.0.0.1:8085", options, peerSeeds = [], - _txnSendingMechanism = "DirectAndStoreAndForward" + _txnSendingMechanism = "DirectAndStoreAndForward", + forceSyncPeers = [] ) { - const envs = baseEnvs(peerSeeds); + const envs = baseEnvs(peerSeeds, forceSyncPeers); const network = options && options.network ? options.network.toUpperCase() : "LOCALNET";