Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ea0b251
Fix new lints required by Rust 1.85 (#640)
michaelsutton Feb 23, 2025
430c8ad
Crescendo hardfork transitioning (#633)
michaelsutton Mar 4, 2025
01f6846
Crescendo TN10 node setup guide (#645)
michaelsutton Mar 4, 2025
6e84ac6
Start the pruning proof per level search at the lowest required depth…
coderofstuff Mar 10, 2025
036fa8c
Crescendo-related RAM optimizations & miscellaneous (#650)
michaelsutton Mar 11, 2025
8eb1f2a
Initial implementation of Mining Rule Engine
coderofstuff Jan 30, 2025
75d96ce
Add MiningRules and wire it up
coderofstuff Feb 9, 2025
dbdd9be
Apply NoTransactions rule
coderofstuff Feb 9, 2025
307b870
Apply BlueParentsOnly rule
coderofstuff Feb 11, 2025
3edcf8b
Implement MiningRule trait in a submodule
coderofstuff Feb 12, 2025
527035f
Refactor Sync Rate Rule
coderofstuff Feb 12, 2025
74284ee
Implement trigger and recovery for NoTransactionsRule
coderofstuff Feb 13, 2025
de7d1ad
Add merge depth check for BlueParentsOnlyRule recovery
coderofstuff Feb 13, 2025
c9e8302
Add documentation for rules
coderofstuff Feb 14, 2025
b59e332
Use virtual resolve count to calc processing average
coderofstuff Feb 14, 2025
ac677a0
Implement Retention Period Support (#592)
coderofstuff Mar 12, 2025
53269c5
Merge branch 'master' into rule-engine
coderofstuff Mar 16, 2025
ea3047a
BlueParentsOnlyRule comment fixes
coderofstuff Mar 17, 2025
a087772
Windowed sampling for sync rate rule
coderofstuff Mar 18, 2025
c3c950f
Update "no txs rule" to depend on submit blocks
coderofstuff Mar 18, 2025
de10c18
BlueParentOnlyRule: focus trigger and recovery on build block template
coderofstuff Mar 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 82 additions & 60 deletions Cargo.lock

Large diffs are not rendered by default.

113 changes: 57 additions & 56 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ members = [

[workspace.package]
rust-version = "1.82.0"
version = "0.16.1"
version = "0.17.1"
authors = ["Kaspa developers"]
license = "ISC"
repository = "https://github.com/kaspanet/rusty-kaspa"
Expand All @@ -80,61 +80,62 @@ include = [
]

[workspace.dependencies]
# kaspa-testing-integration = { version = "0.16.1", path = "testing/integration" }
kaspa-addresses = { version = "0.16.1", path = "crypto/addresses" }
kaspa-addressmanager = { version = "0.16.1", path = "components/addressmanager" }
kaspa-bip32 = { version = "0.16.1", path = "wallet/bip32" }
kaspa-cli = { version = "0.16.1", path = "cli" }
kaspa-connectionmanager = { version = "0.16.1", path = "components/connectionmanager" }
kaspa-consensus = { version = "0.16.1", path = "consensus" }
kaspa-consensus-core = { version = "0.16.1", path = "consensus/core" }
kaspa-consensus-client = { version = "0.16.1", path = "consensus/client" }
kaspa-consensus-notify = { version = "0.16.1", path = "consensus/notify" }
kaspa-consensus-wasm = { version = "0.16.1", path = "consensus/wasm" }
kaspa-consensusmanager = { version = "0.16.1", path = "components/consensusmanager" }
kaspa-core = { version = "0.16.1", path = "core" }
kaspa-daemon = { version = "0.16.1", path = "daemon" }
kaspa-database = { version = "0.16.1", path = "database" }
kaspa-grpc-client = { version = "0.16.1", path = "rpc/grpc/client" }
kaspa-grpc-core = { version = "0.16.1", path = "rpc/grpc/core" }
kaspa-grpc-server = { version = "0.16.1", path = "rpc/grpc/server" }
kaspa-hashes = { version = "0.16.1", path = "crypto/hashes" }
kaspa-index-core = { version = "0.16.1", path = "indexes/core" }
kaspa-index-processor = { version = "0.16.1", path = "indexes/processor" }
kaspa-math = { version = "0.16.1", path = "math" }
kaspa-merkle = { version = "0.16.1", path = "crypto/merkle" }
kaspa-metrics-core = { version = "0.16.1", path = "metrics/core" }
kaspa-mining = { version = "0.16.1", path = "mining" }
kaspa-mining-errors = { version = "0.16.1", path = "mining/errors" }
kaspa-muhash = { version = "0.16.1", path = "crypto/muhash" }
kaspa-notify = { version = "0.16.1", path = "notify" }
kaspa-p2p-flows = { version = "0.16.1", path = "protocol/flows" }
kaspa-p2p-lib = { version = "0.16.1", path = "protocol/p2p" }
kaspa-perf-monitor = { version = "0.16.1", path = "metrics/perf_monitor" }
kaspa-pow = { version = "0.16.1", path = "consensus/pow" }
kaspa-rpc-core = { version = "0.16.1", path = "rpc/core" }
kaspa-rpc-macros = { version = "0.16.1", path = "rpc/macros" }
kaspa-rpc-service = { version = "0.16.1", path = "rpc/service" }
kaspa-txscript = { version = "0.16.1", path = "crypto/txscript" }
kaspa-txscript-errors = { version = "0.16.1", path = "crypto/txscript/errors" }
kaspa-utils = { version = "0.16.1", path = "utils" }
kaspa-utils-tower = { version = "0.16.1", path = "utils/tower" }
kaspa-utxoindex = { version = "0.16.1", path = "indexes/utxoindex" }
kaspa-wallet = { version = "0.16.1", path = "wallet/native" }
kaspa-wallet-cli-wasm = { version = "0.16.1", path = "wallet/wasm" }
kaspa-wallet-keys = { version = "0.16.1", path = "wallet/keys" }
kaspa-wallet-pskt = { version = "0.16.1", path = "wallet/pskt" }
kaspa-wallet-core = { version = "0.16.1", path = "wallet/core" }
kaspa-wallet-macros = { version = "0.16.1", path = "wallet/macros" }
kaspa-wasm = { version = "0.16.1", path = "wasm" }
kaspa-wasm-core = { version = "0.16.1", path = "wasm/core" }
kaspa-wrpc-client = { version = "0.16.1", path = "rpc/wrpc/client" }
kaspa-wrpc-proxy = { version = "0.16.1", path = "rpc/wrpc/proxy" }
kaspa-wrpc-server = { version = "0.16.1", path = "rpc/wrpc/server" }
kaspa-wrpc-wasm = { version = "0.16.1", path = "rpc/wrpc/wasm" }
kaspa-wrpc-example-subscriber = { version = "0.16.1", path = "rpc/wrpc/examples/subscriber" }
kaspad = { version = "0.16.1", path = "kaspad" }
kaspa-alloc = { version = "0.16.1", path = "utils/alloc" }
# kaspa-testing-integration = { version = "0.17.1", path = "testing/integration" }
kaspa-addresses = { version = "0.17.1", path = "crypto/addresses" }
kaspa-addressmanager = { version = "0.17.1", path = "components/addressmanager" }
kaspa-bip32 = { version = "0.17.1", path = "wallet/bip32" }
kaspa-cli = { version = "0.17.1", path = "cli" }
kaspa-connectionmanager = { version = "0.17.1", path = "components/connectionmanager" }
kaspa-consensus = { version = "0.17.1", path = "consensus" }
kaspa-consensus-core = { version = "0.17.1", path = "consensus/core" }
kaspa-consensus-client = { version = "0.17.1", path = "consensus/client" }
kaspa-consensus-notify = { version = "0.17.1", path = "consensus/notify" }
kaspa-consensus-wasm = { version = "0.17.1", path = "consensus/wasm" }
kaspa-consensusmanager = { version = "0.17.1", path = "components/consensusmanager" }
kaspa-core = { version = "0.17.1", path = "core" }
kaspa-daemon = { version = "0.17.1", path = "daemon" }
kaspa-database = { version = "0.17.1", path = "database" }
kaspa-grpc-client = { version = "0.17.1", path = "rpc/grpc/client" }
kaspa-grpc-core = { version = "0.17.1", path = "rpc/grpc/core" }
kaspa-grpc-server = { version = "0.17.1", path = "rpc/grpc/server" }
kaspa-hashes = { version = "0.17.1", path = "crypto/hashes" }
kaspa-index-core = { version = "0.17.1", path = "indexes/core" }
kaspa-index-processor = { version = "0.17.1", path = "indexes/processor" }
kaspa-math = { version = "0.17.1", path = "math" }
kaspa-merkle = { version = "0.17.1", path = "crypto/merkle" }
kaspa-metrics-core = { version = "0.17.1", path = "metrics/core" }
kaspa-mining = { version = "0.17.1", path = "mining" }
kaspa-mining-errors = { version = "0.17.1", path = "mining/errors" }
kaspa-muhash = { version = "0.17.1", path = "crypto/muhash" }
kaspa-notify = { version = "0.17.1", path = "notify" }
kaspa-p2p-flows = { version = "0.17.1", path = "protocol/flows" }
kaspa-p2p-lib = { version = "0.17.1", path = "protocol/p2p" }
kaspa-p2p-mining = { version = "0.17.1", path = "protocol/mining" }
kaspa-perf-monitor = { version = "0.17.1", path = "metrics/perf_monitor" }
kaspa-pow = { version = "0.17.1", path = "consensus/pow" }
kaspa-rpc-core = { version = "0.17.1", path = "rpc/core" }
kaspa-rpc-macros = { version = "0.17.1", path = "rpc/macros" }
kaspa-rpc-service = { version = "0.17.1", path = "rpc/service" }
kaspa-txscript = { version = "0.17.1", path = "crypto/txscript" }
kaspa-txscript-errors = { version = "0.17.1", path = "crypto/txscript/errors" }
kaspa-utils = { version = "0.17.1", path = "utils" }
kaspa-utils-tower = { version = "0.17.1", path = "utils/tower" }
kaspa-utxoindex = { version = "0.17.1", path = "indexes/utxoindex" }
kaspa-wallet = { version = "0.17.1", path = "wallet/native" }
kaspa-wallet-cli-wasm = { version = "0.17.1", path = "wallet/wasm" }
kaspa-wallet-keys = { version = "0.17.1", path = "wallet/keys" }
kaspa-wallet-pskt = { version = "0.17.1", path = "wallet/pskt" }
kaspa-wallet-core = { version = "0.17.1", path = "wallet/core" }
kaspa-wallet-macros = { version = "0.17.1", path = "wallet/macros" }
kaspa-wasm = { version = "0.17.1", path = "wasm" }
kaspa-wasm-core = { version = "0.17.1", path = "wasm/core" }
kaspa-wrpc-client = { version = "0.17.1", path = "rpc/wrpc/client" }
kaspa-wrpc-proxy = { version = "0.17.1", path = "rpc/wrpc/proxy" }
kaspa-wrpc-server = { version = "0.17.1", path = "rpc/wrpc/server" }
kaspa-wrpc-wasm = { version = "0.17.1", path = "rpc/wrpc/wasm" }
kaspa-wrpc-example-subscriber = { version = "0.17.1", path = "rpc/wrpc/examples/subscriber" }
kaspad = { version = "0.17.1", path = "kaspad" }
kaspa-alloc = { version = "0.17.1", path = "utils/alloc" }

# external
aes = "0.8.3"
Expand Down
30 changes: 14 additions & 16 deletions components/consensusmanager/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use kaspa_consensus_core::{
daa_score_timestamp::DaaScoreTimestamp,
errors::consensus::ConsensusResult,
header::Header,
mass::{ContextualMasses, NonContextualMasses},
pruning::{PruningPointProof, PruningPointTrustedData, PruningPointsList},
trusted::{ExternalGhostdagData, TrustedBlock},
tx::{MutableTransaction, SignableTransaction, Transaction, TransactionOutpoint, UtxoEntry},
Expand Down Expand Up @@ -191,14 +192,14 @@ impl ConsensusSessionOwned {
self.consensus.validate_and_insert_trusted_block(tb)
}

pub fn calculate_transaction_compute_mass(&self, transaction: &Transaction) -> u64 {
pub fn calculate_transaction_non_contextual_masses(&self, transaction: &Transaction) -> NonContextualMasses {
// This method performs pure calculations so no need for an async wrapper
self.consensus.calculate_transaction_compute_mass(transaction)
self.consensus.calculate_transaction_non_contextual_masses(transaction)
}

pub fn calculate_transaction_storage_mass(&self, transaction: &MutableTransaction) -> Option<u64> {
pub fn calculate_transaction_contextual_masses(&self, transaction: &MutableTransaction) -> Option<ContextualMasses> {
// This method performs pure calculations so no need for an async wrapper
self.consensus.calculate_transaction_storage_mass(transaction)
self.consensus.calculate_transaction_contextual_masses(transaction)
}

pub fn get_virtual_daa_score(&self) -> u64 {
Expand Down Expand Up @@ -249,26 +250,23 @@ impl ConsensusSessionOwned {
self.clone().spawn_blocking(|c| c.get_sink_timestamp()).await
}

pub async fn async_get_sink_daa_score_timestamp(&self) -> DaaScoreTimestamp {
self.clone().spawn_blocking(|c| c.get_sink_daa_score_timestamp()).await
}

pub async fn async_get_current_block_color(&self, hash: Hash) -> Option<bool> {
self.clone().spawn_blocking(move |c| c.get_current_block_color(hash)).await
}

/// source refers to the earliest block from which the current node has full header & block data
pub async fn async_get_source(&self) -> Hash {
self.clone().spawn_blocking(|c| c.get_source()).await
/// retention period root refers to the earliest block from which the current node has full header & block data
pub async fn async_get_retention_period_root(&self) -> Hash {
self.clone().spawn_blocking(|c| c.get_retention_period_root()).await
}

pub async fn async_estimate_block_count(&self) -> BlockCount {
self.clone().spawn_blocking(|c| c.estimate_block_count()).await
}

/// Returns whether this consensus is considered synced or close to being synced.
///
/// This info is used to determine if it's ok to use a block template from this node for mining purposes.
pub async fn async_is_nearly_synced(&self) -> bool {
self.clone().spawn_blocking(|c| c.is_nearly_synced()).await
}

pub async fn async_get_virtual_chain_from_block(
&self,
low: Hash,
Expand Down Expand Up @@ -442,8 +440,8 @@ impl ConsensusSessionOwned {
self.clone().spawn_blocking(move |c| c.estimate_network_hashes_per_second(start_hash, window_size)).await
}

pub async fn async_validate_pruning_points(&self) -> ConsensusResult<()> {
self.clone().spawn_blocking(move |c| c.validate_pruning_points()).await
pub async fn async_validate_pruning_points(&self, syncer_virtual_selected_parent: Hash) -> ConsensusResult<()> {
self.clone().spawn_blocking(move |c| c.validate_pruning_points(syncer_virtual_selected_parent)).await
}

pub async fn async_are_pruning_points_violating_finality(&self, pp_list: PruningPointsList) -> bool {
Expand Down
7 changes: 7 additions & 0 deletions consensus/client/src/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::imports::*;
use crate::outpoint::{TransactionOutpoint, TransactionOutpointInner};
use crate::result::Result;
use kaspa_addresses::Address;
use kaspa_consensus_core::mass::{UtxoCell, UtxoPlurality};

#[wasm_bindgen(typescript_custom_section)]
const TS_UTXO_ENTRY: &'static str = r#"
Expand Down Expand Up @@ -249,6 +250,12 @@ impl From<UtxoEntry> for UtxoEntryReference {
}
}

impl From<&UtxoEntryReference> for UtxoCell {
fn from(entry: &UtxoEntryReference) -> Self {
Self::new(entry.utxo.script_public_key.plurality(), entry.amount())
}
}

impl Eq for UtxoEntryReference {}

impl PartialEq for UtxoEntryReference {
Expand Down
22 changes: 22 additions & 0 deletions consensus/core/src/api/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub struct ProcessingCounters {
pub chain_block_counts: AtomicU64,
pub chain_disqualified_counts: AtomicU64,
pub mass_counts: AtomicU64,
pub build_block_template_above_threshold: AtomicU64,
pub build_block_template_within_threshold: AtomicU64,
pub submit_block_bad_merkle_root_count: AtomicU64,
pub submit_block_success_count: AtomicU64,
}

impl ProcessingCounters {
Expand All @@ -25,6 +29,10 @@ impl ProcessingCounters {
chain_block_counts: self.chain_block_counts.load(Ordering::Relaxed),
chain_disqualified_counts: self.chain_disqualified_counts.load(Ordering::Relaxed),
mass_counts: self.mass_counts.load(Ordering::Relaxed),
build_block_template_above_threshold: self.build_block_template_above_threshold.load(Ordering::Relaxed),
build_block_template_within_threshold: self.build_block_template_within_threshold.load(Ordering::Relaxed),
submit_block_bad_merkle_root_count: self.submit_block_bad_merkle_root_count.load(Ordering::Relaxed),
submit_block_success_count: self.submit_block_success_count.load(Ordering::Relaxed),
}
}
}
Expand All @@ -40,6 +48,10 @@ pub struct ProcessingCountersSnapshot {
pub chain_block_counts: u64,
pub chain_disqualified_counts: u64,
pub mass_counts: u64,
pub build_block_template_above_threshold: u64,
pub build_block_template_within_threshold: u64,
pub submit_block_bad_merkle_root_count: u64,
pub submit_block_success_count: u64,
}

impl core::ops::Sub for &ProcessingCountersSnapshot {
Expand All @@ -56,6 +68,16 @@ impl core::ops::Sub for &ProcessingCountersSnapshot {
chain_block_counts: self.chain_block_counts.saturating_sub(rhs.chain_block_counts),
chain_disqualified_counts: self.chain_disqualified_counts.saturating_sub(rhs.chain_disqualified_counts),
mass_counts: self.mass_counts.saturating_sub(rhs.mass_counts),
build_block_template_above_threshold: self
.build_block_template_above_threshold
.saturating_sub(rhs.build_block_template_above_threshold),
build_block_template_within_threshold: self
.build_block_template_within_threshold
.saturating_sub(rhs.build_block_template_within_threshold),
submit_block_bad_merkle_root_count: self
.submit_block_bad_merkle_root_count
.saturating_sub(rhs.submit_block_bad_merkle_root_count),
submit_block_success_count: self.submit_block_success_count.saturating_sub(rhs.submit_block_success_count),
}
}
}
24 changes: 11 additions & 13 deletions consensus/core/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::{
tx::TxResult,
},
header::Header,
mass::{ContextualMasses, NonContextualMasses},
pruning::{PruningPointProof, PruningPointTrustedData, PruningPointsList, PruningProofMetadata},
trusted::{ExternalGhostdagData, TrustedBlock},
tx::{MutableTransaction, SignableTransaction, Transaction, TransactionOutpoint, UtxoEntry},
Expand Down Expand Up @@ -90,11 +91,11 @@ pub trait ConsensusApi: Send + Sync {
unimplemented!()
}

fn calculate_transaction_compute_mass(&self, transaction: &Transaction) -> u64 {
fn calculate_transaction_non_contextual_masses(&self, transaction: &Transaction) -> NonContextualMasses {
unimplemented!()
}

fn calculate_transaction_storage_mass(&self, transaction: &MutableTransaction) -> Option<u64> {
fn calculate_transaction_contextual_masses(&self, transaction: &MutableTransaction) -> Option<ContextualMasses> {
unimplemented!()
}

Expand Down Expand Up @@ -134,27 +135,24 @@ pub trait ConsensusApi: Send + Sync {
unimplemented!()
}

fn get_current_block_color(&self, hash: Hash) -> Option<bool> {
fn get_sink_daa_score_timestamp(&self) -> DaaScoreTimestamp {
unimplemented!()
}

fn get_virtual_state_approx_id(&self) -> VirtualStateApproxId {
fn get_current_block_color(&self, hash: Hash) -> Option<bool> {
unimplemented!()
}

/// source refers to the earliest block from which the current node has full header & block data
fn get_source(&self) -> Hash {
fn get_virtual_state_approx_id(&self) -> VirtualStateApproxId {
unimplemented!()
}

fn estimate_block_count(&self) -> BlockCount {
/// retention period root refers to the earliest block from which the current node has full header & block data
fn get_retention_period_root(&self) -> Hash {
unimplemented!()
}

/// Returns whether this consensus is considered synced or close to being synced.
///
/// This info is used to determine if it's ok to use a block template from this node for mining purposes.
fn is_nearly_synced(&self) -> bool {
fn estimate_block_count(&self) -> BlockCount {
unimplemented!()
}

Expand Down Expand Up @@ -218,7 +216,7 @@ pub trait ConsensusApi: Send + Sync {
unimplemented!()
}

fn import_pruning_points(&self, pruning_points: PruningPointsList) {
fn import_pruning_points(&self, pruning_points: PruningPointsList) -> PruningImportResult<()> {
unimplemented!()
}

Expand Down Expand Up @@ -354,7 +352,7 @@ pub trait ConsensusApi: Send + Sync {
unimplemented!()
}

fn validate_pruning_points(&self) -> ConsensusResult<()> {
fn validate_pruning_points(&self, syncer_virtual_selected_parent: Hash) -> ConsensusResult<()> {
unimplemented!()
}

Expand Down
28 changes: 10 additions & 18 deletions consensus/core/src/config/bps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ pub fn calculate_ghostdag_k(x: f64, delta: f64) -> u64 {
}
}

/// Bps-related constants generator for testnet 11
pub type Testnet11Bps = Bps<10>;
/// Bps-related constants generator for 10-bps networks
pub type TenBps = Bps<10>;

/// Struct representing network blocks-per-second. Provides a bunch of const functions
/// computing various constants which are functions of the BPS value
Expand Down Expand Up @@ -93,29 +93,21 @@ impl<const BPS: u64> Bps<BPS> {
BPS * NEW_FINALITY_DURATION
}

/// Limit used to previously calculate the pruning depth.
const fn prev_mergeset_size_limit() -> u64 {
Self::ghostdag_k() as u64 * 10
}

pub const fn pruning_depth() -> u64 {
// Based on the analysis at https://github.com/kaspanet/docs/blob/main/Reference/prunality/Prunality.pdf
// and on the decomposition of merge depth (rule R-I therein) from finality depth (φ)
// We add an additional merge depth unit as a safety margin for anticone finalization
Self::finality_depth()
let lower_bound = Self::finality_depth()
+ Self::merge_depth_bound() * 2
+ 4 * Self::prev_mergeset_size_limit() * Self::ghostdag_k() as u64
+ 4 * Self::mergeset_size_limit() * Self::ghostdag_k() as u64
+ 2 * Self::ghostdag_k() as u64
+ 2

// TODO (HF or restart of TN11):
// Return `Self::finality_depth() * 3` and assert that this value is equal or larger than the above expression.
// This will give us a round easy number to track which is not sensitive to minor changes in other related params.
}
+ 2;

pub const fn pruning_proof_m() -> u64 {
// No need to scale this constant with BPS since the important block levels (higher) remain logarithmically short
PRUNING_PROOF_M
if lower_bound > BPS * NEW_PRUNING_DURATION {
lower_bound
} else {
BPS * NEW_PRUNING_DURATION
}
}

/// Sample rate for sampling blocks to the median time window (in block units, hence dependent on BPS)
Expand Down
Loading
Loading