Skip to content

Commit

Permalink
Add 'disable_checkpoints' config setting, refactor checkpoint code
Browse files Browse the repository at this point in the history
- This commit adds a config file option in server settings 'disable_checkpoints'
- If a user sets 'skip_pow_validation' they will skip pow validation on all blocks up to last checkpoint
- If a user sets 'disable_checkpoints' in addition to 'skip_pow_validation', they will fast sync all the way to chaintip
- This also required a relocation BlockchainCheckpoints code, and resolves an omission i made in original addition of this functionality (not sure it would have made a difference, but its resolved here also)
  • Loading branch information
who-biz committed Sep 1, 2023
1 parent 3c6b12e commit bcf0ecc
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 128 deletions.
22 changes: 2 additions & 20 deletions chain/src/pipe.rs
Expand Up @@ -27,7 +27,7 @@ use crate::error::{Error, ErrorKind};
use crate::store;
use crate::store::BottleIter;
use crate::txhashset;
use crate::types::{BlockchainCheckpoints, CommitPos, Options, Tip};
use crate::types::{CommitPos, Options, Tip};
use chrono::prelude::Utc;
use chrono::Duration;
use epic_store;
Expand Down Expand Up @@ -353,25 +353,7 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext<'_>) -> Result<(

check_bad_header(header)?;

let checkpoints = BlockchainCheckpoints::new().checkpoints;

for c in &checkpoints {
if header.height == c.height {
if header.hash() == c.block_hash {
info!(
"Checkpoint successfully passed at height({})! Hashes: header({:?}), checkpoint({:?})",
c.height,
header.hash(),
c.block_hash
);
} else {
return Err(ErrorKind::CheckpointFailure.into());
}
}
}

if !ctx.opts.contains(Options::SKIP_POW) || (header.height > checkpoints.last().unwrap().height)
{
if !ctx.opts.contains(Options::SKIP_POW) {
if !header.pow.is_primary() && !header.pow.is_secondary() {
return Err(ErrorKind::LowEdgebits.into());
}
Expand Down
104 changes: 0 additions & 104 deletions chain/src/types.rs
Expand Up @@ -411,107 +411,3 @@ pub enum BlockStatus {
/// Previous block was not our previous chain head.
Reorg(u64),
}

// Elements in checkpoint data vector
#[derive(Debug)]
pub struct Checkpoint {
pub height: u64,
pub block_hash: Hash,
}

#[derive(Debug)]
pub struct BlockchainCheckpoints {
pub checkpoints: Vec<Checkpoint>,
}

impl BlockchainCheckpoints {
pub fn new() -> BlockchainCheckpoints {
let checkpoints = vec![
Checkpoint {
height: 100000,
block_hash: Hash::from_hex(
"e835eb9ebc9f2e13b11061691cb268f44b20001f081003169b634497eb730848",
)
.unwrap(),
},
Checkpoint {
height: 200000,
block_hash: Hash::from_hex(
"b2365a8c9719a709f11d450bbddfd012011e21c862239bdc8590aba00815e84c",
)
.unwrap(),
},
Checkpoint {
height: 400000,
block_hash: Hash::from_hex(
"6578f1cdf5504d29fc757424e75ac60494e0f6d24b7553d124c8bea6ef99b5d8",
)
.unwrap(),
},
Checkpoint {
height: 600000,
block_hash: Hash::from_hex(
"de483eafb2141d66bf541a94d8e41858f01ffc517b9fa61d8781483c34c2a6f7",
)
.unwrap(),
},
Checkpoint {
height: 800000,
block_hash: Hash::from_hex(
"1465e7c094376e781b1e80ebd6b7a0c6350ec4d6554f9acdd843802162831003",
)
.unwrap(),
},
Checkpoint {
height: 1000000,
block_hash: Hash::from_hex(
"00e4a404130ac192face23fd25f2c46a99a38a31d8cf2d3cc79ea7a518830686",
)
.unwrap(),
},
Checkpoint {
height: 1200000,
block_hash: Hash::from_hex(
"8d69282df5579d32346ad0f6d3f4e03a43b1e00e741b1f3ba71c2934d81e5e1a",
)
.unwrap(),
},
Checkpoint {
height: 1400000,
block_hash: Hash::from_hex(
"e7e34e50e8a5c9bcf3fe7b7ad99e62a848cda37171ce8d37f21bc334035df4d2",
)
.unwrap(),
},
Checkpoint {
height: 1600000,
block_hash: Hash::from_hex(
"ba44beaf37776c3e7da3f4a1b906ae238e1178794cbaa90685e3945d2662d7a2",
)
.unwrap(),
},
Checkpoint {
height: 1800000,
block_hash: Hash::from_hex(
"4f23aaf2e83e4041cac670226d3024f4468e3b9bb6ffa2548ebc59489bd09b63",
)
.unwrap(),
},
Checkpoint {
height: 2000000,
block_hash: Hash::from_hex(
"eaf5d7a4b6f07ccb8bdbe5db2f39e10eea3ee1c28f8333907d91c9ccc21ce99d",
)
.unwrap(),
},
Checkpoint {
height: 2050000,
block_hash: Hash::from_hex(
"1a51bb18562e120f33783e53a70c449fd14197ac77082dc23d664c7f47a744c9",
)
.unwrap(),
},
];
return BlockchainCheckpoints { checkpoints };
}
}
11 changes: 10 additions & 1 deletion config/src/comments.rs
Expand Up @@ -107,7 +107,16 @@ fn comments() -> HashMap<String, String> {
"skip_pow_validation".to_string(),
"
#Whether or not to skip pow validation when syncing headers
#Only applies to blocks within checkpointed history range (default is false)
#Only applies to blocks in checkpointed range, unless disable_checkpoints is set to true
"
.to_string(),
);

retval.insert(
"disable_checkpoints".to_string(),
"
#Disables checkpoint-based pow_validation, no proof of work will be validated whatsoever
#while syncing. Has no effect unless 'skip_pow_validation' is set to true
"
.to_string(),
);
Expand Down
41 changes: 39 additions & 2 deletions servers/src/common/adapters.rs
Expand Up @@ -25,7 +25,9 @@ use std::time::Instant;

use crate::chain::{self, BlockStatus, ChainAdapter, Options, SyncState, SyncStatus};
use crate::common::hooks::{ChainEvents, NetEvents};
use crate::common::types::{ChainValidationMode, DandelionEpoch, ServerConfig};
use crate::common::types::{
BlockchainCheckpoints, ChainValidationMode, DandelionEpoch, ServerConfig,
};
use crate::core::core::hash::{Hash, Hashed};
use crate::core::core::transaction::Transaction;
use crate::core::core::{BlockHeader, BlockSums, CompactBlock};
Expand Down Expand Up @@ -306,12 +308,47 @@ impl p2p::ChainAdapter for NetToChainAdapter {
);

let mut ctx_option = Options::SYNC;
let mut within_checkpointed_range = true;
let mut disable_checkpoints = false;

let checkpoints = BlockchainCheckpoints::new().checkpoints;

for header in bhs {
for c in &checkpoints {
if header.height == c.height {
if header.hash() == c.block_hash {
info!("Checkpoint successfully passed at height({})! Hashes: header({:?}), checkpoint({:?})",
c.height,
header.hash(),
c.block_hash
);
} else {
return Err(chain::ErrorKind::CheckpointFailure.into());
}
}
}
if header.height > checkpoints.last().unwrap().height {
within_checkpointed_range = false;
}
}

if self.config.disable_checkpoints.is_some() {
if self.config.disable_checkpoints.unwrap() {
disable_checkpoints = true;
}
}

if self.config.skip_pow_validation.is_some() {
if self.config.skip_pow_validation.unwrap() {
ctx_option = Options::SKIP_POW;
if within_checkpointed_range || disable_checkpoints {
// only skip pow validation if setting is toggled AND we are within checkpointed range
// OR if we have 'skip_pow_validation' AND 'disable_checkpoints' toggled
// fully validate pow for all other cases
ctx_option = Options::SKIP_POW;
}
}
}

match self.chain().sync_block_headers(bhs, ctx_option) {
Ok(_) => {
info!(
Expand Down
113 changes: 112 additions & 1 deletion servers/src/common/types.rs
Expand Up @@ -21,6 +21,7 @@ use rand::prelude::*;

use crate::api;
use crate::chain;
use crate::core::core::hash::Hash;
use crate::core::global;
use crate::core::global::ChainTypes;
use crate::core::{consensus, core, libtx, pow};
Expand Down Expand Up @@ -172,9 +173,14 @@ pub struct ServerConfig {
/// Whether this node is a full archival node or a fast-sync, pruned node
pub archive_mode: Option<bool>,

// How to validate new block headers
/// Disable pow validation in checkpointed range, fully validate all blocks
/// Outside of checkpointed range
pub skip_pow_validation: Option<bool>,

/// Disable pow validation all the way to chaintip, only has effect when
/// skip_pow_validation is also set to 'true'
pub disable_checkpoints: Option<bool>,

/// Whether to skip the sync timeout on startup
/// (To assist testing on solo chains)
pub skip_sync_wait: Option<bool>,
Expand Down Expand Up @@ -240,6 +246,7 @@ impl Default for ServerConfig {
chain_type: ChainTypes::default(),
archive_mode: Some(false),
skip_pow_validation: Some(false),
disable_checkpoints: Some(false),
chain_validation_mode: ChainValidationMode::default(),
pool_config: pool::PoolConfig::default(),
skip_sync_wait: Some(false),
Expand Down Expand Up @@ -446,3 +453,107 @@ impl DandelionEpoch {
self.relay_peer.clone()
}
}

// Elements in checkpoint data vector
#[derive(Debug)]
pub struct Checkpoint {
pub height: u64,
pub block_hash: Hash,
}

#[derive(Debug)]
pub struct BlockchainCheckpoints {
pub checkpoints: Vec<Checkpoint>,
}

impl BlockchainCheckpoints {
pub fn new() -> BlockchainCheckpoints {
let checkpoints = vec![
Checkpoint {
height: 100000,
block_hash: Hash::from_hex(
"e835eb9ebc9f2e13b11061691cb268f44b20001f081003169b634497eb730848",
)
.unwrap(),
},
Checkpoint {
height: 200000,
block_hash: Hash::from_hex(
"b2365a8c9719a709f11d450bbddfd012011e21c862239bdc8590aba00815e84c",
)
.unwrap(),
},
Checkpoint {
height: 400000,
block_hash: Hash::from_hex(
"6578f1cdf5504d29fc757424e75ac60494e0f6d24b7553d124c8bea6ef99b5d8",
)
.unwrap(),
},
Checkpoint {
height: 600000,
block_hash: Hash::from_hex(
"de483eafb2141d66bf541a94d8e41858f01ffc517b9fa61d8781483c34c2a6f7",
)
.unwrap(),
},
Checkpoint {
height: 800000,
block_hash: Hash::from_hex(
"1465e7c094376e781b1e80ebd6b7a0c6350ec4d6554f9acdd843802162831003",
)
.unwrap(),
},
Checkpoint {
height: 1000000,
block_hash: Hash::from_hex(
"00e4a404130ac192face23fd25f2c46a99a38a31d8cf2d3cc79ea7a518830686",
)
.unwrap(),
},
Checkpoint {
height: 1200000,
block_hash: Hash::from_hex(
"8d69282df5579d32346ad0f6d3f4e03a43b1e00e741b1f3ba71c2934d81e5e1a",
)
.unwrap(),
},
Checkpoint {
height: 1400000,
block_hash: Hash::from_hex(
"e7e34e50e8a5c9bcf3fe7b7ad99e62a848cda37171ce8d37f21bc334035df4d2",
)
.unwrap(),
},
Checkpoint {
height: 1600000,
block_hash: Hash::from_hex(
"ba44beaf37776c3e7da3f4a1b906ae238e1178794cbaa90685e3945d2662d7a2",
)
.unwrap(),
},
Checkpoint {
height: 1800000,
block_hash: Hash::from_hex(
"4f23aaf2e83e4041cac670226d3024f4468e3b9bb6ffa2548ebc59489bd09b63",
)
.unwrap(),
},
Checkpoint {
height: 2000000,
block_hash: Hash::from_hex(
"eaf5d7a4b6f07ccb8bdbe5db2f39e10eea3ee1c28f8333907d91c9ccc21ce99d",
)
.unwrap(),
},
Checkpoint {
height: 2050000,
block_hash: Hash::from_hex(
"1a51bb18562e120f33783e53a70c449fd14197ac77082dc23d664c7f47a744c9",
)
.unwrap(),
},
];
return BlockchainCheckpoints { checkpoints };
}
}

0 comments on commit bcf0ecc

Please sign in to comment.