diff --git a/ckb-bin/src/subcommand/run.rs b/ckb-bin/src/subcommand/run.rs index 4c9178a889..827999fa5a 100644 --- a/ckb-bin/src/subcommand/run.rs +++ b/ckb-bin/src/subcommand/run.rs @@ -17,7 +17,7 @@ pub fn run(args: RunArgs, version: Version, async_handle: Handle) -> Result<(), info!("ckb version: {}", version); info!("run rpc server with {} threads", rpc_threads_num); let (mut rpc_handle, _rpc_stop_rx, _runtime) = new_global_runtime(Some(rpc_threads_num)); - let mut launcher = Launcher::new(args, version, async_handle, rpc_handle.clone()); + let launcher = Launcher::new(args, version, async_handle, rpc_handle.clone()); let block_assembler_config = launcher.sanitize_block_assembler_config()?; let miner_enable = block_assembler_config.is_some(); @@ -45,8 +45,6 @@ pub fn run(args: RunArgs, version: Version, async_handle: Handle) -> Result<(), Some(shared.store().db().inner()), ); - launcher.check_assume_valid_target(&shared); - let chain_controller = launcher.start_chain_service(&shared, pack.take_proposal_table()); launcher.start_block_filter(&shared); diff --git a/rpc/README.md b/rpc/README.md index ade3cd07d0..f2a27d8172 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -4138,12 +4138,16 @@ Response "id": 42, "jsonrpc": "2.0", "result": { + "assume_valid_target": "0x0000000000000000000000000000000000000000000000000000000000000000", + "assume_valid_target_reached": true, "best_known_block_number": "0x400", "best_known_block_timestamp": "0x5cd2b117", "fast_time": "0x3e8", "ibd": true, "inflight_blocks_count": "0x0", "low_time": "0x5dc", + "min_chain_work": "0x0", + "min_chain_work_reached": true, "normal_time": "0x4e2", "orphan_blocks_count": "0x0", "orphan_blocks_size": "0x0" @@ -6833,6 +6837,10 @@ The overall chain synchronization state of this local node. `SyncState` is a JSON object with the following fields. +* `assume_valid_target`: [`Byte32`](#type-byte32) - The assume_valid_target specified by ckb, if no assume_valid_target, this will be all zero. + +* `assume_valid_target_reached`: `boolean` - Is ckb reached the assume_valid_target? If no assume_valid_target, this will be true. + * `best_known_block_number`: [`Uint64`](#type-uint64) - This is the best known block number observed by the local node from the P2P network. The best here means that the block leads a chain which has the best known accumulated difficulty. @@ -6853,6 +6861,10 @@ The overall chain synchronization state of this local node. * `low_time`: [`Uint64`](#type-uint64) - The download scheduler's time analysis data, the low is the 9/10 of the cut-off point, unit ms +* `min_chain_work`: [`Uint128`](#type-uint128) - This field acts as a security measure to ensure that a node only synchronizes with other nodes that have a significant amount of computational work invested in them, thereby preventing certain types of attacks and ensuring network integrity. Only the mainnet uses a hardcoded value for this field. + +* `min_chain_work_reached`: `boolean` - Is ckb reached the min_chain_work? + * `normal_time`: [`Uint64`](#type-uint64) - The download scheduler's time analysis data, the normal is the 4/5 of the cut-off point, unit ms * `orphan_blocks_count`: [`Uint64`](#type-uint64) - Count of orphan blocks the local node has downloaded. diff --git a/rpc/src/module/net.rs b/rpc/src/module/net.rs index 658011f80e..0513b126ab 100644 --- a/rpc/src/module/net.rs +++ b/rpc/src/module/net.rs @@ -7,6 +7,7 @@ use ckb_jsonrpc_types::{ use ckb_network::{extract_peer_id, multiaddr::Multiaddr, NetworkController}; use ckb_sync::SyncShared; use ckb_systemtime::unix_time_as_millis; +use ckb_types::prelude::Pack; use jsonrpc_core::Result; use jsonrpc_utils::rpc; use std::sync::Arc; @@ -361,12 +362,16 @@ pub trait NetRpc { /// "id": 42, /// "jsonrpc": "2.0", /// "result": { + /// "assume_valid_target": "0x0000000000000000000000000000000000000000000000000000000000000000", + /// "assume_valid_target_reached": true, /// "best_known_block_number": "0x400", /// "best_known_block_timestamp": "0x5cd2b117", /// "fast_time": "0x3e8", /// "ibd": true, /// "inflight_blocks_count": "0x0", /// "low_time": "0x5dc", + /// "min_chain_work": "0x0", + /// "min_chain_work_reached": true, /// "normal_time": "0x4e2", /// "orphan_blocks_count": "0x0", /// "orphan_blocks_size": "0x0" @@ -719,8 +724,22 @@ impl NetRpc for NetRpcImpl { let state = chain.shared().state(); let (fast_time, normal_time, low_time) = state.read_inflight_blocks().division_point(); let best_known = state.shared_best_header(); + let min_chain_work = { + let mut min_chain_work_500k_u128: [u8; 16] = [0; 16]; + min_chain_work_500k_u128 + .copy_from_slice(&self.sync_shared.state().min_chain_work().to_le_bytes()[..16]); + u128::from_le_bytes(min_chain_work_500k_u128) + }; let sync_state = SyncState { ibd: chain.is_initial_block_download(), + assume_valid_target_reached: state.assume_valid_target().is_none(), + assume_valid_target: state + .assume_valid_target_specified() + .unwrap_or_default() + .pack() + .into(), + min_chain_work: min_chain_work.into(), + min_chain_work_reached: state.min_chain_work_ready(), best_known_block_number: best_known.number().into(), best_known_block_timestamp: best_known.timestamp().into(), orphan_blocks_count: (state.orphan_pool().len() as u64).into(), diff --git a/sync/src/types/mod.rs b/sync/src/types/mod.rs index e634c5f838..a98431de21 100644 --- a/sync/src/types/mod.rs +++ b/sync/src/types/mod.rs @@ -1244,6 +1244,17 @@ impl SyncShared { Self::with_tmpdir::(shared, sync_config, None, tx_relay_receiver) } + /// Check whether the data already exists in the database before starting + fn check_assume_valid_target_already_exists(sync_config: &SyncConfig, shared: &Shared) -> bool { + if let Some(ref target) = sync_config.assume_valid_target { + if shared.snapshot().block_exists(&target.pack()) { + info!("assume valid target is already in db, CKB will do full verification from now on"); + return true; + } + } + false + } + /// Generate a global sync state through configuration pub fn with_tmpdir

( shared: Shared, @@ -1286,7 +1297,14 @@ impl SyncShared { inflight_blocks: RwLock::new(InflightBlocks::default()), pending_get_headers: RwLock::new(LruCache::new(GET_HEADERS_CACHE_SIZE)), tx_relay_receiver, - assume_valid_target: Mutex::new(sync_config.assume_valid_target), + assume_valid_target: Mutex::new({ + if Self::check_assume_valid_target_already_exists(&sync_config, &shared) { + None + } else { + sync_config.assume_valid_target.clone() + } + }), + assume_valid_target_specified: sync_config.assume_valid_target, min_chain_work: sync_config.min_chain_work, }; @@ -1647,6 +1665,7 @@ pub struct SyncState { /* cached for sending bulk */ tx_relay_receiver: Receiver, assume_valid_target: Mutex>, + assume_valid_target_specified: Option, min_chain_work: U256, } @@ -1655,6 +1674,10 @@ impl SyncState { self.assume_valid_target.lock() } + pub fn assume_valid_target_specified(&self) -> Option { + self.assume_valid_target_specified.clone() + } + pub fn min_chain_work(&self) -> &U256 { &self.min_chain_work } diff --git a/util/jsonrpc-types/src/net.rs b/util/jsonrpc-types/src/net.rs index 502ee0f753..11de4b7038 100644 --- a/util/jsonrpc-types/src/net.rs +++ b/util/jsonrpc-types/src/net.rs @@ -1,4 +1,4 @@ -use crate::{BlockNumber, Byte32, Timestamp, Uint64}; +use crate::{BlockNumber, Byte32, Timestamp, Uint128, Uint64}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -258,6 +258,18 @@ pub struct SyncState { /// During IBD, the local node only synchronizes the chain with one selected remote node and /// stops responding to most P2P requests. pub ibd: bool, + /// Is ckb reached the assume_valid_target? If no assume_valid_target, this will be true. + pub assume_valid_target_reached: bool, + /// The assume_valid_target specified by ckb, if no assume_valid_target, this will be all zero. + pub assume_valid_target: Byte32, + /// Is ckb reached the min_chain_work? + pub min_chain_work_reached: bool, + /// This field acts as a security measure to ensure that a node only + /// synchronizes with other nodes that have a significant amount of + /// computational work invested in them, thereby preventing certain types + /// of attacks and ensuring network integrity. Only the mainnet uses a + /// hardcoded value for this field. + pub min_chain_work: Uint128, /// This is the best known block number observed by the local node from the P2P network. /// /// The best here means that the block leads a chain which has the best known accumulated diff --git a/util/launcher/src/lib.rs b/util/launcher/src/lib.rs index 7b0c041036..b13bc0249e 100644 --- a/util/launcher/src/lib.rs +++ b/util/launcher/src/lib.rs @@ -26,7 +26,7 @@ use ckb_rpc::ServiceBuilder; use ckb_shared::Shared; use ckb_shared::shared_builder::{SharedBuilder, SharedPackage}; -use ckb_store::{ChainDB, ChainStore}; +use ckb_store::ChainDB; use ckb_sync::{BlockFilter, NetTimeProtocol, Relayer, SyncShared, Synchronizer}; use ckb_tx_pool::service::TxVerificationResult; use ckb_types::prelude::*; @@ -219,16 +219,6 @@ impl Launcher { Ok((shared, pack)) } - /// Check whether the data already exists in the database before starting - pub fn check_assume_valid_target(&mut self, shared: &Shared) { - if let Some(ref target) = self.args.config.network.sync.assume_valid_target { - if shared.snapshot().block_exists(&target.pack()) { - info!("assume valid target is already in db, CKB will do full verification from now on"); - self.args.config.network.sync.assume_valid_target.take(); - } - } - } - /// Start chain service, return ChainController pub fn start_chain_service(&self, shared: &Shared, table: ProposalTable) -> ChainController { let chain_service = ChainService::new(shared.clone(), table);