mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 19:49:33 +00:00
add rules for blocks
TODO: the tests need re-ordering they are just all chucked in at the moment.
This commit is contained in:
parent
b727062e97
commit
2033a2d16c
11 changed files with 86 additions and 42 deletions
|
@ -57,5 +57,3 @@ dirs = {version="5.0", optional = true}
|
|||
# here to help cargo to pick a version - remove me
|
||||
syn = "2.0.37"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 3
|
||||
|
|
|
@ -132,7 +132,28 @@ where
|
|||
|
||||
if current_height % 500 == 0 {
|
||||
tracing::info!("Saving cache to: {}", save_file.display());
|
||||
cache.write().unwrap().save(&save_file)?;
|
||||
cache.read().unwrap().save(&save_file)?;
|
||||
|
||||
let DatabaseResponse::BlockExtendedHeader(header) = database
|
||||
.ready()
|
||||
.await?
|
||||
.call(DatabaseRequest::BlockExtendedHeader(
|
||||
verified_block_info.height.into(),
|
||||
))
|
||||
.await?
|
||||
else {
|
||||
panic!();
|
||||
};
|
||||
|
||||
assert_eq!(header.block_weight, verified_block_info.weight);
|
||||
assert_eq!(
|
||||
header.cumulative_difficulty,
|
||||
verified_block_info.cumulative_difficulty
|
||||
);
|
||||
assert_eq!(
|
||||
header.long_term_weight,
|
||||
verified_block_info.long_term_weight
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
|||
ConsensusError, HardFork,
|
||||
};
|
||||
|
||||
//mod checks;
|
||||
mod checks;
|
||||
mod hash_worker;
|
||||
mod miner_tx;
|
||||
|
||||
|
@ -127,6 +127,8 @@ where
|
|||
|
||||
tracing::debug!("got blockchain context: {:?}", context);
|
||||
|
||||
// TODO: reorder these tests so we do the cheap tests first.
|
||||
|
||||
let txs = if !txs.is_empty() {
|
||||
let VerifyTxResponse::BatchSetupOk(txs) = tx_verifier_svc
|
||||
.oneshot(VerifyTxRequest::BatchSetupVerifyBlock {
|
||||
|
@ -159,6 +161,17 @@ where
|
|||
|
||||
let hashing_blob = block.serialize_hashable();
|
||||
|
||||
checks::block_size_sanity_check(block.serialize().len(), context.effective_median_weight)?;
|
||||
checks::block_weight_check(block_weight, context.median_weight_for_block_reward)?;
|
||||
|
||||
checks::check_amount_txs(block.txs.len())?;
|
||||
checks::check_prev_id(&block, &context.top_hash)?;
|
||||
if let Some(median_timestamp) = context.median_block_timestamp {
|
||||
// will only be None for the first 60 blocks
|
||||
checks::check_timestamp(&block, median_timestamp)?;
|
||||
}
|
||||
|
||||
// do POW test last
|
||||
let pow_hash = tokio::task::spawn_blocking(move || {
|
||||
hash_worker::calculate_pow_hash(
|
||||
&hashing_blob,
|
||||
|
@ -169,6 +182,12 @@ where
|
|||
.await
|
||||
.unwrap()?;
|
||||
|
||||
checks::check_block_pow(&pow_hash, context.next_difficulty)?;
|
||||
|
||||
context
|
||||
.current_hard_fork
|
||||
.check_block_version_vote(&block.header)?;
|
||||
|
||||
Ok(VerifiedBlockInformation {
|
||||
block_hash: block.hash(),
|
||||
block,
|
||||
|
|
|
@ -15,18 +15,22 @@ const BLOCK_FUTURE_TIME_LIMIT: u64 = 60 * 60 * 2;
|
|||
/// Returns if the blocks POW hash is valid for the current difficulty.
|
||||
///
|
||||
/// See: https://cuprate.github.io/monero-book/consensus_rules/blocks/difficulty.html#checking-a-blocks-proof-of-work
|
||||
pub fn check_block_pow(hash: &[u8; 32], difficulty: u128) -> bool {
|
||||
pub fn check_block_pow(hash: &[u8; 32], difficulty: u128) -> Result<(), ConsensusError> {
|
||||
let int_hash = U256::from_le_slice(hash);
|
||||
|
||||
let difficulty = U256::from_u128(difficulty);
|
||||
|
||||
int_hash.checked_mul(&difficulty).is_some().unwrap_u8() == 1
|
||||
if int_hash.checked_mul(&difficulty).is_some().unwrap_u8() != 1 {
|
||||
Err(ConsensusError::BlockPOWInvalid)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sanity check on the block blob size.
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks.html#block-weight-and-size
|
||||
fn block_size_sanity_check(
|
||||
pub fn block_size_sanity_check(
|
||||
block_blob_len: usize,
|
||||
effective_median: usize,
|
||||
) -> Result<(), ConsensusError> {
|
||||
|
@ -37,10 +41,21 @@ fn block_size_sanity_check(
|
|||
}
|
||||
}
|
||||
|
||||
/// Sanity check on number of txs in the block.
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks.html#amount-of-transactions
|
||||
pub fn check_amount_txs(number_none_miner_txs: usize) -> Result<(), ConsensusError> {
|
||||
if number_none_miner_txs + 1 > 0x10000000 {
|
||||
Err(ConsensusError::BlockIsTooLarge)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sanity check on the block weight.
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks.html#block-weight-and-siz
|
||||
fn block_weight_check(
|
||||
pub fn block_weight_check(
|
||||
block_weight: usize,
|
||||
median_for_block_reward: usize,
|
||||
) -> Result<(), ConsensusError> {
|
||||
|
@ -54,7 +69,7 @@ fn block_weight_check(
|
|||
/// Verifies the previous id is the last blocks hash
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks.html#previous-id
|
||||
fn check_prev_id(block: &Block, top_hash: &[u8; 32]) -> Result<(), ConsensusError> {
|
||||
pub fn check_prev_id(block: &Block, top_hash: &[u8; 32]) -> Result<(), ConsensusError> {
|
||||
if &block.header.previous != top_hash {
|
||||
Err(ConsensusError::BlockIsNotApartOfChain)
|
||||
} else {
|
||||
|
@ -65,7 +80,7 @@ fn check_prev_id(block: &Block, top_hash: &[u8; 32]) -> Result<(), ConsensusErro
|
|||
/// Checks the blocks timestamp is in the valid range.
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks.html#timestamp
|
||||
fn check_timestamp(block: &Block, median_timestamp: u64) -> Result<(), ConsensusError> {
|
||||
pub fn check_timestamp(block: &Block, median_timestamp: u64) -> Result<(), ConsensusError> {
|
||||
if block.header.timestamp < median_timestamp
|
||||
|| block.header.timestamp > current_time() + BLOCK_FUTURE_TIME_LIMIT
|
||||
{
|
||||
|
|
|
@ -46,7 +46,8 @@ pub fn calculate_block_reward(
|
|||
/// Checks the miner transactions version.
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks/miner_tx.html#version
|
||||
fn check_tx_version(tx_version: &TxVersion, hf: &HardFork) -> Result<(), ConsensusError> {
|
||||
fn check_miner_tx_version(tx_version: &TxVersion, hf: &HardFork) -> Result<(), ConsensusError> {
|
||||
// The TxVersion enum checks if the version is not 1 or 2
|
||||
if hf >= &HardFork::V12 && tx_version != &TxVersion::RingCT {
|
||||
Err(ConsensusError::MinerTransaction("Version invalid"))
|
||||
} else {
|
||||
|
@ -162,7 +163,7 @@ pub fn check_miner_tx(
|
|||
hf: &HardFork,
|
||||
) -> Result<u64, ConsensusError> {
|
||||
let tx_version = TxVersion::from_raw(tx.prefix.version)?;
|
||||
check_tx_version(&tx_version, hf)?;
|
||||
check_miner_tx_version(&tx_version, hf)?;
|
||||
|
||||
if hf >= &HardFork::V12 && tx.rct_signatures.rct_type() != RctType::Null {
|
||||
return Err(ConsensusError::MinerTransaction("RctType is not null"));
|
||||
|
|
|
@ -137,7 +137,7 @@ pub struct BlockChainContext {
|
|||
/// The current cumulative difficulty.
|
||||
pub cumulative_difficulty: u128,
|
||||
/// The current effective median block weight.
|
||||
effective_median_weight: usize,
|
||||
pub effective_median_weight: usize,
|
||||
/// The median long term block weight.
|
||||
median_long_term_weight: usize,
|
||||
/// Median weight to use for block reward calculations.
|
||||
|
|
|
@ -18,28 +18,6 @@ const BLOCK_TIME_V2: Duration = Duration::from_secs(120);
|
|||
|
||||
const NUMB_OF_HARD_FORKS: usize = 16;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct BlockHFInfo {
|
||||
pub version: HardFork,
|
||||
pub vote: HardFork,
|
||||
}
|
||||
|
||||
impl BlockHFInfo {
|
||||
pub fn from_block_header(block_header: &BlockHeader) -> Result<BlockHFInfo, ConsensusError> {
|
||||
BlockHFInfo::from_major_minor(block_header.major_version, block_header.minor_version)
|
||||
}
|
||||
|
||||
pub fn from_major_minor(
|
||||
major_version: u8,
|
||||
minor_version: u8,
|
||||
) -> Result<BlockHFInfo, ConsensusError> {
|
||||
Ok(BlockHFInfo {
|
||||
version: HardFork::from_version(&major_version)?,
|
||||
vote: HardFork::from_vote(&minor_version),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a given hard-fork.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct HFInfo {
|
||||
|
@ -187,8 +165,20 @@ impl HardFork {
|
|||
/// Checks a blocks version and vote, assuming that `self` is the current hard-fork.
|
||||
///
|
||||
/// https://cuprate.github.io/monero-book/consensus_rules/blocks.html#version-and-vote
|
||||
pub fn check_block_version_vote(&self, block_hf_info: &BlockHFInfo) -> bool {
|
||||
self == &block_hf_info.version && &block_hf_info.vote >= self
|
||||
pub fn check_block_version_vote(
|
||||
&self,
|
||||
block_header: &BlockHeader,
|
||||
) -> Result<(), ConsensusError> {
|
||||
let version = HardFork::from_version(&block_header.major_version)?;
|
||||
let vote = HardFork::from_vote(&block_header.minor_version);
|
||||
|
||||
if self == &version && &vote >= self {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ConsensusError::InvalidHardForkVersion(
|
||||
"Block version or vote incorrect",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,9 @@ where
|
|||
spent_kis.clone(),
|
||||
)
|
||||
})
|
||||
});
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
|
||||
Ok(VerifyTxResponse::Ok)
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ fn output_unlocked(
|
|||
/// https://cuprate.github.io/monero-book/consensus_rules/transactions/unlock_time.html#block-height
|
||||
fn check_block_time_lock(unlock_height: u64, current_chain_height: u64) -> bool {
|
||||
// current_chain_height = 1 + top height
|
||||
unlock_height >= current_chain_height
|
||||
unlock_height <= current_chain_height
|
||||
}
|
||||
|
||||
/// ///
|
||||
|
|
|
@ -21,7 +21,7 @@ fn main() {
|
|||
.file("c/CryptonightR_JIT.c")
|
||||
.file("c/CryptonightR_template.S")
|
||||
.flag("-maes")
|
||||
.flag("-Ofast")
|
||||
.flag("-O2")
|
||||
.flag("-fexceptions")
|
||||
.compile("cryptonight")
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
pub(crate) fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue