add references to monero protocol docs

+ skip genesis block in DifficultyCalculator
This commit is contained in:
Boog900 2023-09-06 19:50:49 +01:00
parent ab3c496bbd
commit b4711c7118
No known key found for this signature in database
GPG key ID: 5401367FB7302004
4 changed files with 36 additions and 18 deletions

View file

@ -39,7 +39,7 @@ impl<Req: Clone, Res, E> tower::retry::Policy<Req, Res, E> for Attempts {
type Future = futures::future::Ready<Self>; type Future = futures::future::Ready<Self>;
fn retry(&self, _: &Req, result: Result<&Res, &E>) -> Option<Self::Future> { fn retry(&self, _: &Req, result: Result<&Res, &E>) -> Option<Self::Future> {
if result.is_err() { if result.is_err() {
Some(futures::future::ready(Attempts(self.0 - 1))) Some(futures::future::ready(Attempts(self.0 )))
} else { } else {
None None
} }
@ -92,11 +92,13 @@ async fn main() {
println!("{pow_info:?}"); println!("{pow_info:?}");
let difficulty = DifficultyCalculator::init_from_chain_height(2968227, rpc.clone()) let difficulty = DifficultyCalculator::init_from_chain_height(578656, rpc.clone())
.await .await
.unwrap(); .unwrap();
println!("{:?}", difficulty.next_difficulty(&HardFork::V16)); //257344482654 println!("{:?}", difficulty);
println!("{:?}", difficulty.next_difficulty(&HardFork::V1)); //774466376
//let _hfs = HardForks::init_at_chain_height(HardForkConfig::default(), 1009827, rpc.clone()) //let _hfs = HardForks::init_at_chain_height(HardForkConfig::default(), 1009827, rpc.clone())
// .await // .await

View file

@ -25,7 +25,7 @@ fn genesis_miner_tx(network: &Network) -> Transaction {
/// Generates the Monero genesis block. /// Generates the Monero genesis block.
/// ///
/// ref: consensus-doc#Genesis /// ref: https://cuprate.github.io/monero-docs/consensus_rules/genesis_block.html
pub fn generate_genesis_block(network: &Network) -> Block { pub fn generate_genesis_block(network: &Network) -> Block {
Block { Block {
header: BlockHeader { header: BlockHeader {

View file

@ -11,7 +11,7 @@ use cuprate_common::{BlockID, Network};
use crate::{Database, DatabaseRequest, DatabaseResponse, Error}; use crate::{Database, DatabaseRequest, DatabaseResponse, Error};
//http://localhost:3000/consensus_rules/hardforks.html#window-size // https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#accepting-a-fork
const DEFAULT_WINDOW_SIZE: u64 = 10080; // supermajority window check length - a week const DEFAULT_WINDOW_SIZE: u64 = 10080; // supermajority window check length - a week
/// An identifier for every hard-fork Monero has had. /// An identifier for every hard-fork Monero has had.
@ -33,13 +33,14 @@ pub enum HardFork {
V13, V13,
V14, V14,
V15, V15,
// remember to update from_vote!
V16, V16,
} }
impl HardFork { impl HardFork {
/// Returns the hard-fork for a blocks `major_version` field. /// Returns the hard-fork for a blocks `major_version` field.
/// ///
/// http://**/consensus_rules/hardforks.html#blocks-version-and-vote /// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#blocks-version-and-vote
pub fn from_version(version: &u8) -> Result<HardFork, Error> { pub fn from_version(version: &u8) -> Result<HardFork, Error> {
Ok(match version { Ok(match version {
1 => HardFork::V1, 1 => HardFork::V1,
@ -68,7 +69,7 @@ impl HardFork {
/// Returns the hard-fork for a blocks `minor_version` (vote) field. /// Returns the hard-fork for a blocks `minor_version` (vote) field.
/// ///
/// http://**/consensus_rules/hardforks.html#blocks-version-and-vote /// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#blocks-version-and-vote
pub fn from_vote(vote: &u8) -> HardFork { pub fn from_vote(vote: &u8) -> HardFork {
if *vote == 0 { if *vote == 0 {
// A vote of 0 is interpreted as 1 as that's what Monero used to default to. // A vote of 0 is interpreted as 1 as that's what Monero used to default to.
@ -102,10 +103,13 @@ impl HardFork {
/// Returns the threshold of this fork. /// Returns the threshold of this fork.
pub fn fork_threshold(&self, _: &Network) -> u64 { pub fn fork_threshold(&self, _: &Network) -> u64 {
// No Monero hard forks actually use voting
0 0
} }
/// Returns the votes needed for this fork. /// Returns the votes needed for this fork.
///
/// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#accepting-a-fork
pub fn votes_needed(&self, network: &Network, window: u64) -> u64 { pub fn votes_needed(&self, network: &Network, window: u64) -> u64 {
(self.fork_threshold(network) * window + 99) / 100 (self.fork_threshold(network) * window + 99) / 100
} }
@ -119,14 +123,17 @@ impl HardFork {
} }
} }
/// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#Stagenet-Hard-Forks
fn stagenet_fork_height(&self) -> u64 { fn stagenet_fork_height(&self) -> u64 {
todo!() todo!()
} }
/// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#Testnet-Hard-Forks
fn testnet_fork_height(&self) -> u64 { fn testnet_fork_height(&self) -> u64 {
todo!() todo!()
} }
/// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#Mainnet-Hard-Forks
fn mainnet_fork_height(&self) -> u64 { fn mainnet_fork_height(&self) -> u64 {
match self { match self {
HardFork::V1 => 0, // Monero core has this as 1, which is strange HardFork::V1 => 0, // Monero core has this as 1, which is strange
@ -197,7 +204,7 @@ impl HFVotes {
/// Returns the total votes for a hard-fork. /// Returns the total votes for a hard-fork.
/// ///
/// http://localhost:3000/consensus_rules/hardforks.html#accepting-a-fork /// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#accepting-a-fork
pub fn votes_for_hf(&self, hf: &HardFork) -> u64 { pub fn votes_for_hf(&self, hf: &HardFork) -> u64 {
self.votes[*hf as usize - 1..].iter().sum() self.votes[*hf as usize - 1..].iter().sum()
} }
@ -402,6 +409,9 @@ impl HardForks {
self.check_set_new_hf() self.check_set_new_hf()
} }
/// Checks if the next hard-fork should be activated and sets it it it should.
///
/// https://cuprate.github.io/monero-docs/consensus_rules/hardforks.html#accepting-a-fork
fn check_set_new_hf(&mut self) { fn check_set_new_hf(&mut self) {
while let Some(new_hf) = self.next_hardfork { while let Some(new_hf) = self.next_hardfork {
if self.last_height + 1 >= new_hf.fork_height(&self.config.network) if self.last_height + 1 >= new_hf.fork_height(&self.config.network)
@ -415,6 +425,7 @@ impl HardForks {
} }
} }
/// Sets a new hard-fork.
fn set_hf(&mut self, new_hf: HardFork) { fn set_hf(&mut self, new_hf: HardFork) {
self.next_hardfork = new_hf.next_fork(); self.next_hardfork = new_hf.next_fork();
self.current_hardfork = new_hf; self.current_hardfork = new_hf;
@ -460,10 +471,3 @@ async fn get_block_header<D: Database>(
}; };
Ok(header) Ok(header)
} }
#[test]
fn to_from_hf() {
let hf = HardFork::V1 as u8;
assert_eq!(hf, 1)
}

View file

@ -51,7 +51,11 @@ impl DifficultyCalculator {
chain_height: u64, chain_height: u64,
mut database: D, mut database: D,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let block_start = chain_height.saturating_sub(DIFFICULTY_BLOCKS_COUNT); let mut block_start = chain_height.saturating_sub(DIFFICULTY_BLOCKS_COUNT);
if block_start == 0 {
block_start = 1;
}
let timestamps = let timestamps =
get_blocks_in_range_timestamps(database.clone(), block_start..chain_height).await?; get_blocks_in_range_timestamps(database.clone(), block_start..chain_height).await?;
@ -111,7 +115,12 @@ impl DifficultyCalculator {
} }
async fn update_windowed_work<D: Database>(&mut self, mut database: D) -> Result<(), Error> { async fn update_windowed_work<D: Database>(&mut self, mut database: D) -> Result<(), Error> {
let block_start = (self.last_accounted_height + 1).saturating_sub(DIFFICULTY_BLOCKS_COUNT); let mut block_start =
(self.last_accounted_height + 1).saturating_sub(DIFFICULTY_BLOCKS_COUNT);
if block_start == 0 {
block_start = 1;
}
let (start, end) = get_window_start_and_end(self.timestamps.len()); let (start, end) = get_window_start_and_end(self.timestamps.len());
@ -137,7 +146,9 @@ impl DifficultyCalculator {
} }
let mut sorted_timestamps = self.timestamps.clone(); let mut sorted_timestamps = self.timestamps.clone();
sorted_timestamps.drain(DIFFICULTY_WINDOW..); if sorted_timestamps.len() > DIFFICULTY_WINDOW {
sorted_timestamps.drain(DIFFICULTY_WINDOW..);
};
sorted_timestamps.sort_unstable(); sorted_timestamps.sort_unstable();
let (window_start, window_end) = get_window_start_and_end(sorted_timestamps.len()); let (window_start, window_end) = get_window_start_and_end(sorted_timestamps.len());
@ -194,6 +205,7 @@ async fn get_blocks_in_range_timestamps<D: Database + Clone>(
} }
async fn get_block_timestamp<D: Database>(database: D, height: u64) -> Result<u64, Error> { async fn get_block_timestamp<D: Database>(database: D, height: u64) -> Result<u64, Error> {
tracing::debug!("Getting block timestamp: {}", height);
let DatabaseResponse::BlockPOWInfo(pow) = database let DatabaseResponse::BlockPOWInfo(pow) = database
.oneshot(DatabaseRequest::BlockPOWInfo(height.into())) .oneshot(DatabaseRequest::BlockPOWInfo(height.into()))
.await? .await?