Skip to content

Commit ff4d68d

Browse files
antiochpignopeverell
authored andcommitted
config to enable full chain validation per block (mimblewimble#839)
* default to full chain validation on processing each block (except during sync) * add sample config for chain_validation_mode * document chain_validation_mode
1 parent fc01a33 commit ff4d68d

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

grin.toml

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ db_root = ".grin"
4242
#
4343
chain_type = "Testnet2"
4444

45+
#The chain validation mode, defines how often (if at all) we
46+
#want to run a full chain validation. Can be:
47+
#EveryBlock - run full chain validation when processing each block (except during sync)
48+
#Disabled - disable full chain validation (just run regular block validation)
49+
#chain_validation_mode=EveryBlock
50+
4551
#run the node in "full archive" mode (default is fast-sync, pruned node)
4652
#archive_mode = false
4753

grin/src/adapters.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::net::SocketAddr;
1717
use std::ops::Deref;
1818
use std::sync::{Arc, RwLock, Weak};
1919
use std::sync::atomic::{AtomicBool, Ordering};
20+
use std::time::Instant;
2021
use rand;
2122
use rand::Rng;
2223

@@ -30,6 +31,7 @@ use p2p;
3031
use pool;
3132
use util::OneTime;
3233
use store;
34+
use types::{ChainValidationMode, ServerConfig};
3335
use util::LOGGER;
3436

3537
// All adapters use `Weak` references instead of `Arc` to avoid cycles that
@@ -51,6 +53,7 @@ pub struct NetToChainAdapter {
5153
chain: Weak<chain::Chain>,
5254
tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
5355
peers: OneTime<Weak<p2p::Peers>>,
56+
config: ServerConfig,
5457
}
5558

5659
impl p2p::ChainAdapter for NetToChainAdapter {
@@ -334,12 +337,14 @@ impl NetToChainAdapter {
334337
currently_syncing: Arc<AtomicBool>,
335338
chain_ref: Weak<chain::Chain>,
336339
tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
340+
config: ServerConfig,
337341
) -> NetToChainAdapter {
338342
NetToChainAdapter {
339343
currently_syncing: currently_syncing,
340344
chain: chain_ref,
341345
tx_pool: tx_pool,
342346
peers: OneTime::new(),
347+
config: config,
343348
}
344349
}
345350

@@ -388,7 +393,7 @@ impl NetToChainAdapter {
388393
let prev_hash = b.header.previous;
389394
let bhash = b.hash();
390395
let chain = w(&self.chain);
391-
match chain.process_block(b, self.chain_opts()) {
396+
let result = match chain.process_block(b, self.chain_opts()) {
392397
Ok(_) => true,
393398
Err(chain::Error::Orphan) => {
394399
// make sure we did not miss the parent block
@@ -415,7 +420,36 @@ impl NetToChainAdapter {
415420
);
416421
true
417422
}
423+
};
424+
425+
// If we are running in "validate the full chain every block" then
426+
// panic here if validation fails for any reason.
427+
// We are out of consensus at this point and want to track the problem
428+
// down as soon as possible.
429+
// Skip this if we are currently syncing (too slow).
430+
if !self.currently_syncing.load(Ordering::Relaxed)
431+
&& self.config.chain_validation_mode == ChainValidationMode::EveryBlock
432+
{
433+
let now = Instant::now();
434+
435+
debug!(
436+
LOGGER,
437+
"adapter: process_block: ***** validating full chain state at {}", bhash,
438+
);
439+
440+
let chain = w(&self.chain);
441+
chain
442+
.validate(true)
443+
.expect("chain validation failed, hard stop");
444+
445+
debug!(
446+
LOGGER,
447+
"adapter: process_block: ***** done validating full chain state, took {}s",
448+
now.elapsed().as_secs(),
449+
);
418450
}
451+
452+
result
419453
}
420454

421455
// After receiving a compact block if we cannot successfully hydrate

grin/src/server.rs

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ impl Server {
120120
currently_syncing.clone(),
121121
Arc::downgrade(&shared_chain),
122122
tx_pool.clone(),
123+
config.clone(),
123124
));
124125

125126
let p2p_config = config.p2p_config.clone();

grin/src/types.rs

+21
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ impl From<wallet::Error> for Error {
8686
}
8787
}
8888

89+
/// Type of seeding the server will use to find other peers on the network.
90+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
91+
pub enum ChainValidationMode {
92+
/// Run full chain validation after processing every block.
93+
EveryBlock,
94+
/// Do not automatically run chain validation during normal block
95+
/// processing.
96+
Disabled,
97+
}
98+
99+
impl Default for ChainValidationMode {
100+
fn default() -> ChainValidationMode {
101+
ChainValidationMode::EveryBlock
102+
}
103+
}
104+
89105
/// Type of seeding the server will use to find other peers on the network.
90106
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
91107
pub enum Seeding {
@@ -122,6 +138,10 @@ pub struct ServerConfig {
122138
/// Whether this node is a full archival node or a fast-sync, pruned node
123139
pub archive_mode: Option<bool>,
124140

141+
/// Automatically run full chain validation during normal block processing?
142+
#[serde(default)]
143+
pub chain_validation_mode: ChainValidationMode,
144+
125145
/// Method used to get the list of seed nodes for initial bootstrap.
126146
#[serde(default)]
127147
pub seeding_type: Seeding,
@@ -169,6 +189,7 @@ impl Default for ServerConfig {
169189
mining_config: Some(pow::types::MinerConfig::default()),
170190
chain_type: ChainTypes::default(),
171191
archive_mode: None,
192+
chain_validation_mode: ChainValidationMode::default(),
172193
pool_config: pool::PoolConfig::default(),
173194
skip_sync_wait: None,
174195
run_tui: None,

0 commit comments

Comments
 (0)