Skip to content

Commit

Permalink
Add SyncInvalid integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
eval-exec committed May 4, 2024
1 parent 629e882 commit 3a20c6e
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 5 deletions.
3 changes: 3 additions & 0 deletions test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ ckb-logger-config = { path = "../util/logger-config", version = "= 0.116.0-pre"
ckb-logger-service = { path = "../util/logger-service", version = "= 0.116.0-pre" }
ckb-error = { path = "../error", version = "= 0.116.0-pre" }
ckb-constant = { path = "../util/constant", version = "= 0.116.0-pre" }
ckb-db = { path = "../db", version = "= 0.116.0-pre" }
ckb-store = { path = "../store", version = "= 0.116.0-pre" }
ckb-shared = { path = "../shared", version = "= 0.116.0-pre" }
tempfile = "3"
reqwest = { version = "=0.11.20", features = ["blocking", "json"] }
rand = "0.7"
Expand Down
1 change: 1 addition & 0 deletions test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ fn all_specs() -> Vec<Box<dyn Spec>> {
Box::new(RequestUnverifiedBlocks),
Box::new(SyncTimeout),
Box::new(SyncChurn),
Box::new(SyncInvalid),
Box::new(GetBlockFilterCheckPoints),
Box::new(GetBlockFilterHashes),
Box::new(GetBlockFilters),
Expand Down
83 changes: 79 additions & 4 deletions test/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::global::binary;
use crate::rpc::RpcClient;
use crate::utils::{find_available_port, temp_path, wait_until};
use crate::{SYSTEM_CELL_ALWAYS_FAILURE_INDEX, SYSTEM_CELL_ALWAYS_SUCCESS_INDEX};
use ckb_app_config::CKBAppConfig;
use ckb_app_config::{AppConfig, CKBAppConfig, ExitCode};
use ckb_chain_spec::consensus::Consensus;
use ckb_chain_spec::ChainSpec;
use ckb_error::AnyError;
Expand All @@ -11,6 +11,8 @@ use ckb_jsonrpc_types::{PoolTxDetailInfo, TxStatus};
use ckb_logger::{debug, error, info};
use ckb_network::multiaddr::Multiaddr;
use ckb_resource::Resource;
use ckb_shared::shared_builder::open_or_create_db;
use ckb_store::ChainDB;
use ckb_types::{
bytes,
core::{
Expand All @@ -22,9 +24,8 @@ use ckb_types::{
};
use std::borrow::{Borrow, BorrowMut};
use std::collections::{HashMap, HashSet};
use std::convert::Into;
use std::fs;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use std::sync::{Arc, RwLock};
use std::thread::sleep;
Expand Down Expand Up @@ -722,6 +723,74 @@ impl Node {
drop(self.take_guard());
}

fn derive_options(
&self,
mut config: CKBAppConfig,
root_dir: &Path,
subcommand_name: &str,
) -> Result<CKBAppConfig, ExitCode> {
config.root_dir = root_dir.to_path_buf();

config.data_dir = root_dir.join(config.data_dir);

config.db.adjust(root_dir, &config.data_dir, "db");
config.ancient = config.data_dir.join("ancient");

config.network.path = config.data_dir.join("network");
if config.tmp_dir.is_none() {
config.tmp_dir = Some(config.data_dir.join("tmp"));
}
config.logger.log_dir = config.data_dir.join("logs");
config.logger.file = Path::new(&(subcommand_name.to_string() + ".log")).to_path_buf();

let tx_pool_path = config.data_dir.join("tx_pool");
config.tx_pool.adjust(root_dir, tx_pool_path);

let indexer_path = config.data_dir.join("indexer");
config.indexer.adjust(root_dir, indexer_path);

config.chain.spec.absolutize(root_dir);

Ok(config)
}

pub fn access_db<F>(&self, f: F)
where
F: Fn(&ChainDB),
{
info!("accessing db");
info!("AppConfig load_for_subcommand {:?}", self.working_dir());

let resource = Resource::ckb_config(self.working_dir());
let app_config =
CKBAppConfig::load_from_slice(&resource.get().expect("resource")).expect("app config");

let config = AppConfig::CKB(Box::new(
self.derive_options(app_config, self.working_dir().as_ref(), "run")
.expect("app config"),
));

let consensus = config
.chain_spec()
.expect("spec")
.build_consensus()
.expect("consensus");

let app_config = config.into_ckb().expect("app config");

let db = open_or_create_db(
"ckb",
&app_config.root_dir,
&app_config.db,
consensus.hardfork_switch().clone(),
)
.expect("open_or_create_db");
let chain_db = ChainDB::new(db, app_config.store);
f(&chain_db);

info!("accessed db done");
}

pub fn stop_gracefully(&mut self) {
let guard = self.take_guard();
if let Some(mut guard) = guard {
Expand Down Expand Up @@ -824,7 +893,13 @@ pub fn waiting_for_sync<N: Borrow<Node>>(nodes: &[N]) {
tip_headers.len() == 1
});
if !synced {
panic!("timeout to wait for sync, tip_headers: {tip_headers:?}");
panic!(
"timeout to wait for sync, tip_headers: {:?}",
tip_headers
.iter()
.map(|header| header.inner.number.value())
.collect::<Vec<BlockNumber>>()
);
}
for node in nodes {
node.borrow().wait_for_tx_pool();
Expand Down
7 changes: 6 additions & 1 deletion test/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use ckb_error::AnyError;
use ckb_jsonrpc_types::{
Alert, BannedAddr, Block, BlockEconomicState, BlockFilter, BlockNumber, BlockTemplate,
BlockView, Capacity, CellWithStatus, ChainInfo, EpochNumber, EpochView, EstimateCycles,
HeaderView, LocalNode, OutPoint, PoolTxDetailInfo, RawTxPool, RemoteNode, Timestamp,
HeaderView, LocalNode, OutPoint, PoolTxDetailInfo, RawTxPool, RemoteNode, SyncState, Timestamp,
Transaction, TransactionProof, TransactionWithStatusResponse, TxPoolInfo, Uint32, Uint64,
Version,
};
Expand Down Expand Up @@ -150,6 +150,10 @@ impl RpcClient {
.expect("rpc call get_banned_addresses")
}

pub fn sync_state(&self) -> SyncState {
self.inner.sync_state().expect("rpc call sync_state")
}

pub fn clear_banned_addresses(&self) {
self.inner
.clear_banned_addresses()
Expand Down Expand Up @@ -322,6 +326,7 @@ jsonrpc!(
pub fn get_current_epoch(&self) -> EpochView;
pub fn get_epoch_by_number(&self, number: EpochNumber) -> Option<EpochView>;

pub fn sync_state(&self) -> SyncState;
pub fn local_node_info(&self) -> LocalNode;
pub fn get_peers(&self) -> Vec<RemoteNode>;
pub fn get_banned_addresses(&self) -> Vec<BannedAddr>;
Expand Down
2 changes: 2 additions & 0 deletions test/src/specs/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod invalid_locator_size;
mod last_common_header;
mod sync_and_mine;
mod sync_churn;
mod sync_invalid;
mod sync_timeout;

pub use block_filter::*;
Expand All @@ -20,4 +21,5 @@ pub use invalid_locator_size::*;
pub use last_common_header::*;
pub use sync_and_mine::*;
pub use sync_churn::*;
pub use sync_invalid::*;
pub use sync_timeout::*;
114 changes: 114 additions & 0 deletions test/src/specs/sync/sync_invalid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use crate::{Node, Spec};
use ckb_app_config::CKBAppConfig;
use ckb_logger::info;
use ckb_store::{ChainDB, ChainStore};
use ckb_types::core;
use ckb_types::packed;
use ckb_types::prelude::{AsBlockBuilder, Builder, Entity, IntoUncleBlockView};
use std::thread::sleep;
use std::time::Duration;

pub struct SyncInvalid;

impl Spec for SyncInvalid {
crate::setup!(num_nodes: 2);

fn run(&self, nodes: &mut Vec<Node>) {
nodes[0].mine(20);
nodes[1].mine(1);

nodes[0].connect(&nodes[1]);

let info_nodes_tip = || {
info!(
"nodes tip_number: {:?}",
nodes
.iter()
.map(|node| node.get_tip_block_number())
.collect::<Vec<_>>()
);
};

let insert_invalid_block = || {
let template = nodes[0].rpc_client().get_block_template(None, None, None);

let block = packed::Block::from(template)
.as_advanced_builder()
.uncle(packed::UncleBlock::new_builder().build().into_view())
.build();
nodes[0]
.rpc_client()
.process_block_without_verify(block.data().into(), false);
};

info_nodes_tip();
insert_invalid_block();
insert_invalid_block();
info_nodes_tip();
assert_eq!(nodes[0].get_tip_block_number(), 22);

while nodes[1]
.rpc_client()
.sync_state()
.best_known_block_number
.value()
<= 20
{
sleep(Duration::from_secs(1));
}

let block_21_hash = core::BlockView::from(
nodes[0]
.rpc_client()
.get_block_by_number(21)
.expect("get block 21"),
)
.hash();
let block_22_hash = core::BlockView::from(
nodes[0]
.rpc_client()
.get_block_by_number(22)
.expect("get block 22"),
)
.hash();

assert!(!nodes[1].rpc_client().get_banned_addresses().is_empty());
assert!(nodes[1]
.rpc_client()
.get_banned_addresses()
.first()
.unwrap()
.ban_reason
.contains(&format!("{}", block_21_hash)));
info_nodes_tip();

nodes[0].stop();
nodes[1].stop();

nodes[0].access_db(|store: &ChainDB| {
{
assert!(store.get_block(&block_21_hash).is_some());
assert!(store.get_block(&block_22_hash).is_some());
let ext = store.get_block_ext(&block_21_hash).expect("block 21 ext");
assert_eq!(ext.verified, Some(true));
}
{
assert!(store.get_block(&block_22_hash).is_some());
assert!(store.get_block(&block_22_hash).is_some());
let ext = store.get_block_ext(&block_22_hash).expect("block 22 ext");
assert_eq!(ext.verified, Some(true));
}
});

nodes[1].access_db(|store: &ChainDB| {
assert!(store.get_block(&block_21_hash).is_none());
assert!(store.get_block_ext(&block_21_hash).is_none());
assert!(store.get_block(&block_22_hash).is_none());
assert!(store.get_block_ext(&block_22_hash).is_none());
});
}

fn modify_app_config(&self, config: &mut CKBAppConfig) {
config.logger.filter = Some("ckb=debug".to_string());
}
}

0 comments on commit 3a20c6e

Please sign in to comment.