config to enable full chain validation per block (#839)

* default to full chain validation on processing each block (except during sync)
* add sample config for chain_validation_mode
* document chain_validation_mode
This commit is contained in:
Antioch Peverell 2018-03-21 16:50:08 -04:00 committed by Ignotus Peverell
parent fc01a33d15
commit ff4d68d2be
4 changed files with 63 additions and 1 deletions

View file

@ -42,6 +42,12 @@ db_root = ".grin"
#
chain_type = "Testnet2"
#The chain validation mode, defines how often (if at all) we
#want to run a full chain validation. Can be:
#EveryBlock - run full chain validation when processing each block (except during sync)
#Disabled - disable full chain validation (just run regular block validation)
#chain_validation_mode=EveryBlock
#run the node in "full archive" mode (default is fast-sync, pruned node)
#archive_mode = false

View file

@ -17,6 +17,7 @@ use std::net::SocketAddr;
use std::ops::Deref;
use std::sync::{Arc, RwLock, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Instant;
use rand;
use rand::Rng;
@ -30,6 +31,7 @@ use p2p;
use pool;
use util::OneTime;
use store;
use types::{ChainValidationMode, ServerConfig};
use util::LOGGER;
// All adapters use `Weak` references instead of `Arc` to avoid cycles that
@ -51,6 +53,7 @@ pub struct NetToChainAdapter {
chain: Weak<chain::Chain>,
tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
peers: OneTime<Weak<p2p::Peers>>,
config: ServerConfig,
}
impl p2p::ChainAdapter for NetToChainAdapter {
@ -334,12 +337,14 @@ impl NetToChainAdapter {
currently_syncing: Arc<AtomicBool>,
chain_ref: Weak<chain::Chain>,
tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
config: ServerConfig,
) -> NetToChainAdapter {
NetToChainAdapter {
currently_syncing: currently_syncing,
chain: chain_ref,
tx_pool: tx_pool,
peers: OneTime::new(),
config: config,
}
}
@ -388,7 +393,7 @@ impl NetToChainAdapter {
let prev_hash = b.header.previous;
let bhash = b.hash();
let chain = w(&self.chain);
match chain.process_block(b, self.chain_opts()) {
let result = match chain.process_block(b, self.chain_opts()) {
Ok(_) => true,
Err(chain::Error::Orphan) => {
// make sure we did not miss the parent block
@ -415,7 +420,36 @@ impl NetToChainAdapter {
);
true
}
};
// If we are running in "validate the full chain every block" then
// panic here if validation fails for any reason.
// We are out of consensus at this point and want to track the problem
// down as soon as possible.
// Skip this if we are currently syncing (too slow).
if !self.currently_syncing.load(Ordering::Relaxed)
&& self.config.chain_validation_mode == ChainValidationMode::EveryBlock
{
let now = Instant::now();
debug!(
LOGGER,
"adapter: process_block: ***** validating full chain state at {}", bhash,
);
let chain = w(&self.chain);
chain
.validate(true)
.expect("chain validation failed, hard stop");
debug!(
LOGGER,
"adapter: process_block: ***** done validating full chain state, took {}s",
now.elapsed().as_secs(),
);
}
result
}
// After receiving a compact block if we cannot successfully hydrate

View file

@ -120,6 +120,7 @@ impl Server {
currently_syncing.clone(),
Arc::downgrade(&shared_chain),
tx_pool.clone(),
config.clone(),
));
let p2p_config = config.p2p_config.clone();

View file

@ -86,6 +86,22 @@ impl From<wallet::Error> for Error {
}
}
/// Type of seeding the server will use to find other peers on the network.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ChainValidationMode {
/// Run full chain validation after processing every block.
EveryBlock,
/// Do not automatically run chain validation during normal block
/// processing.
Disabled,
}
impl Default for ChainValidationMode {
fn default() -> ChainValidationMode {
ChainValidationMode::EveryBlock
}
}
/// Type of seeding the server will use to find other peers on the network.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Seeding {
@ -122,6 +138,10 @@ pub struct ServerConfig {
/// Whether this node is a full archival node or a fast-sync, pruned node
pub archive_mode: Option<bool>,
/// Automatically run full chain validation during normal block processing?
#[serde(default)]
pub chain_validation_mode: ChainValidationMode,
/// Method used to get the list of seed nodes for initial bootstrap.
#[serde(default)]
pub seeding_type: Seeding,
@ -169,6 +189,7 @@ impl Default for ServerConfig {
mining_config: Some(pow::types::MinerConfig::default()),
chain_type: ChainTypes::default(),
archive_mode: None,
chain_validation_mode: ChainValidationMode::default(),
pool_config: pool::PoolConfig::default(),
skip_sync_wait: None,
run_tui: None,