Checks the first line in the checkpoint list instead of the first item in the BTreeMap

This commit is contained in:
Arya 2024-04-19 16:32:05 -04:00
parent c30537d946
commit 5690d4e2f4
1 changed files with 28 additions and 20 deletions

View File

@ -64,29 +64,42 @@ impl ParameterCheckpoint for Network {
} }
fn checkpoint_list(&self) -> CheckpointList { fn checkpoint_list(&self) -> CheckpointList {
// parse calls CheckpointList::from_list let checkpoints_for_network = match self {
let checkpoint_list: CheckpointList = match self { Network::Mainnet => MAINNET_CHECKPOINTS,
Network::Mainnet => MAINNET_CHECKPOINTS Network::Testnet(_) => TESTNET_CHECKPOINTS,
.parse()
.expect("Hard-coded Mainnet checkpoint list parses and validates"),
Network::Testnet(_params) => TESTNET_CHECKPOINTS
.parse()
.expect("Hard-coded Testnet checkpoint list parses and validates"),
}; };
// Check that the list starts with the correct genesis block // Check that the list starts with the correct genesis block and parses checkpoint list.
let first_checkpoint_height = checkpoint_list.iter().next(); let first_checkpoint_height = checkpoints_for_network
.lines()
.next()
.map(checkpoint_height_and_hash)
.expect("there must be at least one checkpoint, for the genesis block");
match first_checkpoint_height { match first_checkpoint_height {
Some((block::Height(0), &hash)) if hash == self.genesis_hash() => checkpoint_list, // parse calls CheckpointList::from_list
Some((block::Height(0), _)) => { Ok((block::Height(0), hash)) if hash == self.genesis_hash() => checkpoints_for_network
.parse()
.expect("Hard-coded checkpoint list parses and validates"),
Ok((block::Height(0), _)) => {
panic!("the genesis checkpoint does not match the Mainnet or Testnet genesis hash") panic!("the genesis checkpoint does not match the Mainnet or Testnet genesis hash")
} }
Some(_) => panic!("checkpoints must start at the genesis block height 0"), Ok(_) => panic!("checkpoints must start at the genesis block height 0"),
None => panic!("there must be at least one checkpoint, for the genesis block"), Err(err) => panic!("{err}"),
} }
} }
} }
/// Parses a checkpoint to a [`block::Height`] and [`block::Hash`].
fn checkpoint_height_and_hash(checkpoint: &str) -> Result<(block::Height, block::Hash), BoxError> {
let fields = checkpoint.split(' ').collect::<Vec<_>>();
if let [height, hash] = fields[..] {
Ok((height.parse()?, hash.parse()?))
} else {
Err(format!("Invalid checkpoint format: expected 2 space-separated fields but found {}: '{checkpoint}'", fields.len()).into())
}
}
/// A list of block height and hash checkpoints. /// A list of block height and hash checkpoints.
/// ///
/// Checkpoints should be chosen to avoid forks or chain reorganizations, /// Checkpoints should be chosen to avoid forks or chain reorganizations,
@ -112,12 +125,7 @@ impl FromStr for CheckpointList {
let mut checkpoint_list: Vec<(block::Height, block::Hash)> = Vec::new(); let mut checkpoint_list: Vec<(block::Height, block::Hash)> = Vec::new();
for checkpoint in s.lines() { for checkpoint in s.lines() {
let fields = checkpoint.split(' ').collect::<Vec<_>>(); checkpoint_list.push(checkpoint_height_and_hash(checkpoint)?);
if let [height, hash] = fields[..] {
checkpoint_list.push((height.parse()?, hash.parse()?));
} else {
Err(format!("Invalid checkpoint format: expected 2 space-separated fields but found {}: '{checkpoint}'", fields.len()))?;
};
} }
CheckpointList::from_list(checkpoint_list) CheckpointList::from_list(checkpoint_list)