diff --git a/Cargo.lock b/Cargo.lock index c28817994..d1ebf9cfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2393,7 +2393,7 @@ dependencies = [ [[package]] name = "kaspa-addresses" -version = "0.14.3" +version = "0.14.5" dependencies = [ "borsh", "criterion", @@ -2410,7 +2410,7 @@ dependencies = [ [[package]] name = "kaspa-addressmanager" -version = "0.14.3" +version = "0.14.5" dependencies = [ "borsh", "igd-next", @@ -2433,14 +2433,14 @@ dependencies = [ [[package]] name = "kaspa-alloc" -version = "0.14.3" +version = "0.14.5" dependencies = [ "mimalloc", ] [[package]] name = "kaspa-bip32" -version = "0.14.3" +version = "0.14.5" dependencies = [ "borsh", "bs58", @@ -2467,7 +2467,7 @@ dependencies = [ [[package]] name = "kaspa-cli" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "borsh", @@ -2514,7 +2514,7 @@ dependencies = [ [[package]] name = "kaspa-connectionmanager" -version = "0.14.3" +version = "0.14.5" dependencies = [ "duration-string", "futures-util", @@ -2531,7 +2531,7 @@ dependencies = [ [[package]] name = "kaspa-consensus" -version = "0.14.3" +version = "0.14.5" dependencies = [ "arc-swap", "async-channel 2.3.1", @@ -2574,7 +2574,7 @@ dependencies = [ [[package]] name = "kaspa-consensus-client" -version = "0.14.3" +version = "0.14.5" dependencies = [ "ahash", "cfg-if 1.0.0", @@ -2602,7 +2602,7 @@ dependencies = [ [[package]] name = "kaspa-consensus-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "bincode", @@ -2640,7 +2640,7 @@ dependencies = [ [[package]] name = "kaspa-consensus-notify" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "cfg-if 1.0.0", @@ -2659,7 +2659,7 @@ dependencies = [ [[package]] name = "kaspa-consensus-wasm" -version = "0.14.3" +version = "0.14.5" dependencies = [ "cfg-if 1.0.0", "faster-hex", @@ -2683,7 +2683,7 @@ dependencies = [ [[package]] name = "kaspa-consensusmanager" -version = "0.14.3" +version = "0.14.5" dependencies = [ "duration-string", "futures", @@ -2701,7 +2701,7 @@ dependencies = [ [[package]] name = "kaspa-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "cfg-if 1.0.0", "ctrlc", @@ -2719,7 +2719,7 @@ dependencies = [ [[package]] name = "kaspa-daemon" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "borsh", @@ -2741,7 +2741,7 @@ dependencies = [ [[package]] name = "kaspa-database" -version = "0.14.3" +version = "0.14.5" dependencies = [ "bincode", "enum-primitive-derive", @@ -2763,7 +2763,7 @@ dependencies = [ [[package]] name = "kaspa-grpc-client" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-stream", @@ -2794,7 +2794,7 @@ dependencies = [ [[package]] name = "kaspa-grpc-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-stream", @@ -2823,7 +2823,7 @@ dependencies = [ [[package]] name = "kaspa-grpc-server" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-stream", @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "kaspa-hashes" -version = "0.14.3" +version = "0.14.5" dependencies = [ "blake2b_simd", "borsh", @@ -2879,7 +2879,7 @@ dependencies = [ [[package]] name = "kaspa-index-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-trait", @@ -2898,7 +2898,7 @@ dependencies = [ [[package]] name = "kaspa-index-processor" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-trait", @@ -2926,7 +2926,7 @@ dependencies = [ [[package]] name = "kaspa-math" -version = "0.14.3" +version = "0.14.5" dependencies = [ "borsh", "criterion", @@ -2947,14 +2947,14 @@ dependencies = [ [[package]] name = "kaspa-merkle" -version = "0.14.3" +version = "0.14.5" dependencies = [ "kaspa-hashes", ] [[package]] name = "kaspa-metrics-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "borsh", @@ -2970,7 +2970,7 @@ dependencies = [ [[package]] name = "kaspa-mining" -version = "0.14.3" +version = "0.14.5" dependencies = [ "criterion", "futures-util", @@ -2997,7 +2997,7 @@ dependencies = [ [[package]] name = "kaspa-mining-errors" -version = "0.14.3" +version = "0.14.5" dependencies = [ "kaspa-consensus-core", "thiserror", @@ -3005,7 +3005,7 @@ dependencies = [ [[package]] name = "kaspa-muhash" -version = "0.14.3" +version = "0.14.5" dependencies = [ "criterion", "kaspa-hashes", @@ -3018,7 +3018,7 @@ dependencies = [ [[package]] name = "kaspa-notify" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-trait", @@ -3054,7 +3054,7 @@ dependencies = [ [[package]] name = "kaspa-p2p-flows" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "chrono", @@ -3085,7 +3085,7 @@ dependencies = [ [[package]] name = "kaspa-p2p-lib" -version = "0.14.3" +version = "0.14.5" dependencies = [ "borsh", "ctrlc", @@ -3116,7 +3116,7 @@ dependencies = [ [[package]] name = "kaspa-perf-monitor" -version = "0.14.3" +version = "0.14.5" dependencies = [ "kaspa-core", "log", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "kaspa-pow" -version = "0.14.3" +version = "0.14.5" dependencies = [ "criterion", "js-sys", @@ -3144,7 +3144,7 @@ dependencies = [ [[package]] name = "kaspa-rpc-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-trait", @@ -3186,7 +3186,7 @@ dependencies = [ [[package]] name = "kaspa-rpc-macros" -version = "0.14.3" +version = "0.14.5" dependencies = [ "convert_case 0.6.0", "proc-macro-error", @@ -3198,7 +3198,7 @@ dependencies = [ [[package]] name = "kaspa-rpc-service" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "kaspa-addresses", @@ -3227,7 +3227,7 @@ dependencies = [ [[package]] name = "kaspa-testing-integration" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "async-trait", @@ -3287,7 +3287,7 @@ dependencies = [ [[package]] name = "kaspa-txscript" -version = "0.14.3" +version = "0.14.5" dependencies = [ "blake2b_simd", "borsh", @@ -3319,7 +3319,7 @@ dependencies = [ [[package]] name = "kaspa-txscript-errors" -version = "0.14.3" +version = "0.14.5" dependencies = [ "secp256k1", "thiserror", @@ -3327,7 +3327,7 @@ dependencies = [ [[package]] name = "kaspa-utils" -version = "0.14.3" +version = "0.14.5" dependencies = [ "arc-swap", "async-channel 2.3.1", @@ -3363,7 +3363,7 @@ dependencies = [ [[package]] name = "kaspa-utils-tower" -version = "0.14.3" +version = "0.14.5" dependencies = [ "cfg-if 1.0.0", "futures", @@ -3377,7 +3377,7 @@ dependencies = [ [[package]] name = "kaspa-utxoindex" -version = "0.14.3" +version = "0.14.5" dependencies = [ "futures", "kaspa-consensus", @@ -3398,7 +3398,7 @@ dependencies = [ [[package]] name = "kaspa-wallet" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-std", "async-trait", @@ -3410,7 +3410,7 @@ dependencies = [ [[package]] name = "kaspa-wallet-cli-wasm" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "js-sys", @@ -3424,7 +3424,7 @@ dependencies = [ [[package]] name = "kaspa-wallet-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "aes", "ahash", @@ -3505,7 +3505,7 @@ dependencies = [ [[package]] name = "kaspa-wallet-keys" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "borsh", @@ -3538,7 +3538,7 @@ dependencies = [ [[package]] name = "kaspa-wallet-macros" -version = "0.14.3" +version = "0.14.5" dependencies = [ "convert_case 0.5.0", "proc-macro-error", @@ -3551,7 +3551,7 @@ dependencies = [ [[package]] name = "kaspa-wallet-pskt" -version = "0.14.3" +version = "0.14.5" dependencies = [ "bincode", "derive_builder", @@ -3578,7 +3578,7 @@ dependencies = [ [[package]] name = "kaspa-wasm" -version = "0.14.3" +version = "0.14.5" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3606,7 +3606,7 @@ dependencies = [ [[package]] name = "kaspa-wasm-core" -version = "0.14.3" +version = "0.14.5" dependencies = [ "faster-hex", "hexplay", @@ -3617,7 +3617,7 @@ dependencies = [ [[package]] name = "kaspa-wrpc-client" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-std", "async-trait", @@ -3652,7 +3652,7 @@ dependencies = [ [[package]] name = "kaspa-wrpc-example-subscriber" -version = "0.14.3" +version = "0.14.5" dependencies = [ "ctrlc", "futures", @@ -3667,7 +3667,7 @@ dependencies = [ [[package]] name = "kaspa-wrpc-proxy" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "clap 4.5.16", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "kaspa-wrpc-server" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-trait", "borsh", @@ -3714,7 +3714,7 @@ dependencies = [ [[package]] name = "kaspa-wrpc-wasm" -version = "0.14.3" +version = "0.14.5" dependencies = [ "ahash", "async-std", @@ -3743,7 +3743,7 @@ dependencies = [ [[package]] name = "kaspad" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "cfg-if 1.0.0", @@ -5188,7 +5188,7 @@ dependencies = [ [[package]] name = "rothschild" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "clap 4.5.16", @@ -5665,7 +5665,7 @@ dependencies = [ [[package]] name = "simpa" -version = "0.14.3" +version = "0.14.5" dependencies = [ "async-channel 2.3.1", "cfg-if 1.0.0", diff --git a/Cargo.toml b/Cargo.toml index 0a6799e43..0fdc4a499 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ members = [ [workspace.package] rust-version = "1.80.0" -version = "0.14.3" +version = "0.14.5" authors = ["Kaspa developers"] license = "ISC" repository = "https://github.com/kaspanet/rusty-kaspa" @@ -79,61 +79,61 @@ include = [ ] [workspace.dependencies] -# kaspa-testing-integration = { version = "0.14.3", path = "testing/integration" } -kaspa-addresses = { version = "0.14.3", path = "crypto/addresses" } -kaspa-addressmanager = { version = "0.14.3", path = "components/addressmanager" } -kaspa-bip32 = { version = "0.14.3", path = "wallet/bip32" } -kaspa-cli = { version = "0.14.3", path = "cli" } -kaspa-connectionmanager = { version = "0.14.3", path = "components/connectionmanager" } -kaspa-consensus = { version = "0.14.3", path = "consensus" } -kaspa-consensus-core = { version = "0.14.3", path = "consensus/core" } -kaspa-consensus-client = { version = "0.14.3", path = "consensus/client" } -kaspa-consensus-notify = { version = "0.14.3", path = "consensus/notify" } -kaspa-consensus-wasm = { version = "0.14.3", path = "consensus/wasm" } -kaspa-consensusmanager = { version = "0.14.3", path = "components/consensusmanager" } -kaspa-core = { version = "0.14.3", path = "core" } -kaspa-daemon = { version = "0.14.3", path = "daemon" } -kaspa-database = { version = "0.14.3", path = "database" } -kaspa-grpc-client = { version = "0.14.3", path = "rpc/grpc/client" } -kaspa-grpc-core = { version = "0.14.3", path = "rpc/grpc/core" } -kaspa-grpc-server = { version = "0.14.3", path = "rpc/grpc/server" } -kaspa-hashes = { version = "0.14.3", path = "crypto/hashes" } -kaspa-index-core = { version = "0.14.3", path = "indexes/core" } -kaspa-index-processor = { version = "0.14.3", path = "indexes/processor" } -kaspa-math = { version = "0.14.3", path = "math" } -kaspa-merkle = { version = "0.14.3", path = "crypto/merkle" } -kaspa-metrics-core = { version = "0.14.3", path = "metrics/core" } -kaspa-mining = { version = "0.14.3", path = "mining" } -kaspa-mining-errors = { version = "0.14.3", path = "mining/errors" } -kaspa-muhash = { version = "0.14.3", path = "crypto/muhash" } -kaspa-notify = { version = "0.14.3", path = "notify" } -kaspa-p2p-flows = { version = "0.14.3", path = "protocol/flows" } -kaspa-p2p-lib = { version = "0.14.3", path = "protocol/p2p" } -kaspa-perf-monitor = { version = "0.14.3", path = "metrics/perf_monitor" } -kaspa-pow = { version = "0.14.3", path = "consensus/pow" } -kaspa-rpc-core = { version = "0.14.3", path = "rpc/core" } -kaspa-rpc-macros = { version = "0.14.3", path = "rpc/macros" } -kaspa-rpc-service = { version = "0.14.3", path = "rpc/service" } -kaspa-txscript = { version = "0.14.3", path = "crypto/txscript" } -kaspa-txscript-errors = { version = "0.14.3", path = "crypto/txscript/errors" } -kaspa-utils = { version = "0.14.3", path = "utils" } -kaspa-utils-tower = { version = "0.14.3", path = "utils/tower" } -kaspa-utxoindex = { version = "0.14.3", path = "indexes/utxoindex" } -kaspa-wallet = { version = "0.14.3", path = "wallet/native" } -kaspa-wallet-cli-wasm = { version = "0.14.3", path = "wallet/wasm" } -kaspa-wallet-keys = { version = "0.14.3", path = "wallet/keys" } -kaspa-wallet-pskt = { version = "0.14.3", path = "wallet/pskt" } -kaspa-wallet-core = { version = "0.14.3", path = "wallet/core" } -kaspa-wallet-macros = { version = "0.14.3", path = "wallet/macros" } -kaspa-wasm = { version = "0.14.3", path = "wasm" } -kaspa-wasm-core = { version = "0.14.3", path = "wasm/core" } -kaspa-wrpc-client = { version = "0.14.3", path = "rpc/wrpc/client" } -kaspa-wrpc-proxy = { version = "0.14.3", path = "rpc/wrpc/proxy" } -kaspa-wrpc-server = { version = "0.14.3", path = "rpc/wrpc/server" } -kaspa-wrpc-wasm = { version = "0.14.3", path = "rpc/wrpc/wasm" } -kaspa-wrpc-example-subscriber = { version = "0.14.3", path = "rpc/wrpc/examples/subscriber" } -kaspad = { version = "0.14.3", path = "kaspad" } -kaspa-alloc = { version = "0.14.3", path = "utils/alloc" } +# kaspa-testing-integration = { version = "0.14.5", path = "testing/integration" } +kaspa-addresses = { version = "0.14.5", path = "crypto/addresses" } +kaspa-addressmanager = { version = "0.14.5", path = "components/addressmanager" } +kaspa-bip32 = { version = "0.14.5", path = "wallet/bip32" } +kaspa-cli = { version = "0.14.5", path = "cli" } +kaspa-connectionmanager = { version = "0.14.5", path = "components/connectionmanager" } +kaspa-consensus = { version = "0.14.5", path = "consensus" } +kaspa-consensus-core = { version = "0.14.5", path = "consensus/core" } +kaspa-consensus-client = { version = "0.14.5", path = "consensus/client" } +kaspa-consensus-notify = { version = "0.14.5", path = "consensus/notify" } +kaspa-consensus-wasm = { version = "0.14.5", path = "consensus/wasm" } +kaspa-consensusmanager = { version = "0.14.5", path = "components/consensusmanager" } +kaspa-core = { version = "0.14.5", path = "core" } +kaspa-daemon = { version = "0.14.5", path = "daemon" } +kaspa-database = { version = "0.14.5", path = "database" } +kaspa-grpc-client = { version = "0.14.5", path = "rpc/grpc/client" } +kaspa-grpc-core = { version = "0.14.5", path = "rpc/grpc/core" } +kaspa-grpc-server = { version = "0.14.5", path = "rpc/grpc/server" } +kaspa-hashes = { version = "0.14.5", path = "crypto/hashes" } +kaspa-index-core = { version = "0.14.5", path = "indexes/core" } +kaspa-index-processor = { version = "0.14.5", path = "indexes/processor" } +kaspa-math = { version = "0.14.5", path = "math" } +kaspa-merkle = { version = "0.14.5", path = "crypto/merkle" } +kaspa-metrics-core = { version = "0.14.5", path = "metrics/core" } +kaspa-mining = { version = "0.14.5", path = "mining" } +kaspa-mining-errors = { version = "0.14.5", path = "mining/errors" } +kaspa-muhash = { version = "0.14.5", path = "crypto/muhash" } +kaspa-notify = { version = "0.14.5", path = "notify" } +kaspa-p2p-flows = { version = "0.14.5", path = "protocol/flows" } +kaspa-p2p-lib = { version = "0.14.5", path = "protocol/p2p" } +kaspa-perf-monitor = { version = "0.14.5", path = "metrics/perf_monitor" } +kaspa-pow = { version = "0.14.5", path = "consensus/pow" } +kaspa-rpc-core = { version = "0.14.5", path = "rpc/core" } +kaspa-rpc-macros = { version = "0.14.5", path = "rpc/macros" } +kaspa-rpc-service = { version = "0.14.5", path = "rpc/service" } +kaspa-txscript = { version = "0.14.5", path = "crypto/txscript" } +kaspa-txscript-errors = { version = "0.14.5", path = "crypto/txscript/errors" } +kaspa-utils = { version = "0.14.5", path = "utils" } +kaspa-utils-tower = { version = "0.14.5", path = "utils/tower" } +kaspa-utxoindex = { version = "0.14.5", path = "indexes/utxoindex" } +kaspa-wallet = { version = "0.14.5", path = "wallet/native" } +kaspa-wallet-cli-wasm = { version = "0.14.5", path = "wallet/wasm" } +kaspa-wallet-keys = { version = "0.14.5", path = "wallet/keys" } +kaspa-wallet-pskt = { version = "0.14.5", path = "wallet/pskt" } +kaspa-wallet-core = { version = "0.14.5", path = "wallet/core" } +kaspa-wallet-macros = { version = "0.14.5", path = "wallet/macros" } +kaspa-wasm = { version = "0.14.5", path = "wasm" } +kaspa-wasm-core = { version = "0.14.5", path = "wasm/core" } +kaspa-wrpc-client = { version = "0.14.5", path = "rpc/wrpc/client" } +kaspa-wrpc-proxy = { version = "0.14.5", path = "rpc/wrpc/proxy" } +kaspa-wrpc-server = { version = "0.14.5", path = "rpc/wrpc/server" } +kaspa-wrpc-wasm = { version = "0.14.5", path = "rpc/wrpc/wasm" } +kaspa-wrpc-example-subscriber = { version = "0.14.5", path = "rpc/wrpc/examples/subscriber" } +kaspad = { version = "0.14.5", path = "kaspad" } +kaspa-alloc = { version = "0.14.5", path = "utils/alloc" } # external aes = "0.8.3" diff --git a/consensus/core/src/api/counters.rs b/consensus/core/src/api/counters.rs index 5faee5bc3..0297dab26 100644 --- a/consensus/core/src/api/counters.rs +++ b/consensus/core/src/api/counters.rs @@ -9,6 +9,7 @@ pub struct ProcessingCounters { pub body_counts: AtomicU64, pub txs_counts: AtomicU64, pub chain_block_counts: AtomicU64, + pub chain_disqualified_counts: AtomicU64, pub mass_counts: AtomicU64, } @@ -22,6 +23,7 @@ impl ProcessingCounters { body_counts: self.body_counts.load(Ordering::Relaxed), txs_counts: self.txs_counts.load(Ordering::Relaxed), 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), } } @@ -36,6 +38,7 @@ pub struct ProcessingCountersSnapshot { pub body_counts: u64, pub txs_counts: u64, pub chain_block_counts: u64, + pub chain_disqualified_counts: u64, pub mass_counts: u64, } @@ -51,6 +54,7 @@ impl core::ops::Sub for &ProcessingCountersSnapshot { body_counts: self.body_counts.saturating_sub(rhs.body_counts), txs_counts: self.txs_counts.saturating_sub(rhs.txs_counts), 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), } } diff --git a/consensus/core/src/errors/block.rs b/consensus/core/src/errors/block.rs index 9aab18905..f5c235476 100644 --- a/consensus/core/src/errors/block.rs +++ b/consensus/core/src/errors/block.rs @@ -147,6 +147,10 @@ pub enum RuleError { #[error("DAA window data has only {0} entries")] InsufficientDaaWindowSize(usize), + + /// Currently this error is never created because it is impossible to submit such a block + #[error("cannot add block body to a pruned block")] + PrunedBlock, } pub type BlockProcessResult = std::result::Result; diff --git a/consensus/src/pipeline/body_processor/body_validation_in_context.rs b/consensus/src/pipeline/body_processor/body_validation_in_context.rs index 042410fa8..aa2f345b3 100644 --- a/consensus/src/pipeline/body_processor/body_validation_in_context.rs +++ b/consensus/src/pipeline/body_processor/body_validation_in_context.rs @@ -14,14 +14,7 @@ impl BlockBodyProcessor { pub fn validate_body_in_context(self: &Arc, block: &Block) -> BlockProcessResult<()> { self.check_parent_bodies_exist(block)?; self.check_coinbase_blue_score_and_subsidy(block)?; - self.check_block_transactions_in_context(block)?; - self.check_block_is_not_pruned(block) - } - - fn check_block_is_not_pruned(self: &Arc, _block: &Block) -> BlockProcessResult<()> { - // TODO: In kaspad code it checks that the block is not in the past of the current tips. - // We should decide what's the best indication that a block was pruned. - Ok(()) + self.check_block_transactions_in_context(block) } fn check_block_transactions_in_context(self: &Arc, block: &Block) -> BlockProcessResult<()> { @@ -36,12 +29,6 @@ impl BlockBodyProcessor { } fn check_parent_bodies_exist(self: &Arc, block: &Block) -> BlockProcessResult<()> { - // TODO: Skip this check for blocks in PP anticone that comes as part of the pruning proof. - - if block.header.direct_parents().len() == 1 && block.header.direct_parents()[0] == self.genesis.hash { - return Ok(()); - } - let statuses_read_guard = self.statuses_store.read(); let missing: Vec = block .header diff --git a/consensus/src/pipeline/body_processor/processor.rs b/consensus/src/pipeline/body_processor/processor.rs index ae9c07b8a..4191a01ce 100644 --- a/consensus/src/pipeline/body_processor/processor.rs +++ b/consensus/src/pipeline/body_processor/processor.rs @@ -201,8 +201,7 @@ impl BlockBodyProcessor { // transactions that fits the merkle root. // PrunedBlock - PrunedBlock is an error that rejects a block body and // not the block as a whole, so we shouldn't mark it as invalid. - // TODO: implement the last part. - if !matches!(e, RuleError::BadMerkleRoot(_, _) | RuleError::MissingParents(_)) { + if !matches!(e, RuleError::BadMerkleRoot(_, _) | RuleError::MissingParents(_) | RuleError::PrunedBlock) { self.statuses_store.write().set(block.hash(), BlockStatus::StatusInvalid).unwrap(); } return Err(e); @@ -226,7 +225,6 @@ impl BlockBodyProcessor { fn validate_body(self: &Arc, block: &Block, is_trusted: bool) -> BlockProcessResult { let mass = self.validate_body_in_isolation(block)?; if !is_trusted { - // TODO: Check that it's safe to skip this check if the block is trusted. self.validate_body_in_context(block)?; } Ok(mass) diff --git a/consensus/src/pipeline/header_processor/processor.rs b/consensus/src/pipeline/header_processor/processor.rs index d1b74aeb5..6c93b91d9 100644 --- a/consensus/src/pipeline/header_processor/processor.rs +++ b/consensus/src/pipeline/header_processor/processor.rs @@ -308,8 +308,6 @@ impl HeaderProcessor { // Runs partial header validation for trusted blocks (currently validates only header-in-isolation and computes GHOSTDAG). fn validate_trusted_header(&self, header: &Arc
) -> BlockProcessResult { - // TODO: For now we skip most validations for trusted blocks, but in the future we should - // employ some validations to avoid spam etc. let block_level = self.validate_header_in_isolation(header)?; let mut ctx = self.build_processing_context(header, block_level); self.ghostdag(&mut ctx); @@ -407,7 +405,6 @@ impl HeaderProcessor { && reachability::is_chain_ancestor_of(&staging, pp, ctx.hash).unwrap() { // Hint reachability about the new tip. - // TODO: identify a disqualified hst and make sure to use sink instead reachability::hint_virtual_selected_parent(&mut staging, ctx.hash).unwrap(); hst_write.set_batch(&mut batch, SortableBlock::new(ctx.hash, header.blue_work)).unwrap(); } diff --git a/consensus/src/pipeline/monitor.rs b/consensus/src/pipeline/monitor.rs index 600059f0a..ca370a2f8 100644 --- a/consensus/src/pipeline/monitor.rs +++ b/consensus/src/pipeline/monitor.rs @@ -5,7 +5,7 @@ use kaspa_core::{ service::{AsyncService, AsyncServiceFuture}, tick::{TickReason, TickService}, }, - trace, + trace, warn, }; use std::{ sync::Arc, @@ -62,6 +62,13 @@ impl ConsensusMonitor { if delta.body_counts != 0 { delta.mass_counts as f64 / delta.body_counts as f64 } else{ 0f64 }, ); + if delta.chain_disqualified_counts > 0 { + warn!( + "Consensus detected UTXO-invalid blocks which are disqualified from the virtual selected chain (possibly due to inheritance): {} disqualified vs. {} valid chain blocks", + delta.chain_disqualified_counts, delta.chain_block_counts + ); + } + last_snapshot = snapshot; last_log_time = now; } diff --git a/consensus/src/pipeline/virtual_processor/processor.rs b/consensus/src/pipeline/virtual_processor/processor.rs index 163e88893..dfb7394b8 100644 --- a/consensus/src/pipeline/virtual_processor/processor.rs +++ b/consensus/src/pipeline/virtual_processor/processor.rs @@ -383,10 +383,12 @@ impl VirtualStateProcessor { // Walk back up to the new virtual selected parent candidate let mut chain_block_counter = 0; + let mut chain_disqualified_counter = 0; for (selected_parent, current) in self.reachability_service.forward_chain_iterator(split_point, to, true).tuple_windows() { if selected_parent != diff_point { // This indicates that the selected parent is disqualified, propagate up and continue self.statuses_store.write().set(current, StatusDisqualifiedFromChain).unwrap(); + chain_disqualified_counter += 1; continue; } @@ -416,6 +418,7 @@ impl VirtualStateProcessor { if let Err(rule_error) = res { info!("Block {} is disqualified from virtual chain: {}", current, rule_error); self.statuses_store.write().set(current, StatusDisqualifiedFromChain).unwrap(); + chain_disqualified_counter += 1; } else { debug!("VIRTUAL PROCESSOR, UTXO validated for {current}"); @@ -434,6 +437,9 @@ impl VirtualStateProcessor { } // Report counters self.counters.chain_block_counts.fetch_add(chain_block_counter, Ordering::Relaxed); + if chain_disqualified_counter > 0 { + self.counters.chain_disqualified_counts.fetch_add(chain_disqualified_counter, Ordering::Relaxed); + } diff_point } @@ -559,7 +565,7 @@ impl VirtualStateProcessor { finality_point: Hash, pruning_point: Hash, ) -> (Hash, VecDeque) { - // TODO: tests + // TODO (relaxed): additional tests let mut heap = tips .into_iter() @@ -621,7 +627,7 @@ impl VirtualStateProcessor { mut candidates: VecDeque, pruning_point: Hash, ) -> (Vec, GhostdagData) { - // TODO: tests + // TODO (relaxed): additional tests // Mergeset increasing might traverse DAG areas which are below the finality point and which theoretically // can borderline with pruned data, hence we acquire the prune lock to ensure data consistency. Note that @@ -670,7 +676,7 @@ impl VirtualStateProcessor { MergesetIncreaseResult::Rejected { new_candidate } => { // If we already have a candidate in the past of new candidate then skip. if self.reachability_service.is_any_dag_ancestor(&mut candidates.iter().copied(), new_candidate) { - continue; // TODO: not sure this test is needed if candidates invariant as antichain is kept + continue; // TODO (optimization): not sure this check is needed if candidates invariant as antichain is kept } // Remove all candidates which are in the future of the new candidate candidates.retain(|&h| !self.reachability_service.is_dag_ancestor_of(new_candidate, h)); @@ -860,7 +866,7 @@ impl VirtualStateProcessor { build_mode: TemplateBuildMode, ) -> Result { // - // TODO: tests + // TODO (relaxed): additional tests // // We call for the initial tx batch before acquiring the virtual read lock, @@ -1048,7 +1054,7 @@ impl VirtualStateProcessor { ); } - // TODO: rename to reflect finalizing pruning point utxoset state and importing *to* virtual utxoset + /// Finalizes the pruning point utxoset state and imports the pruning point utxoset *to* virtual utxoset pub fn import_pruning_point_utxo_set( &self, new_pruning_point: Hash, diff --git a/consensus/src/pipeline/virtual_processor/utxo_validation.rs b/consensus/src/pipeline/virtual_processor/utxo_validation.rs index 999cd1c54..306f81446 100644 --- a/consensus/src/pipeline/virtual_processor/utxo_validation.rs +++ b/consensus/src/pipeline/virtual_processor/utxo_validation.rs @@ -267,7 +267,6 @@ impl VirtualStateProcessor { for i in 0..mutable_tx.tx.inputs.len() { if mutable_tx.entries[i].is_some() { // We prefer a previously populated entry if such exists - // TODO: consider re-checking the utxo view to get the most up-to-date entry (since DAA score can change) continue; } if let Some(entry) = utxo_view.get(&mutable_tx.tx.inputs[i].previous_outpoint) { diff --git a/crypto/txscript/src/caches.rs b/crypto/txscript/src/caches.rs index 3f76b2575..b3911fcf4 100644 --- a/crypto/txscript/src/caches.rs +++ b/crypto/txscript/src/caches.rs @@ -87,8 +87,8 @@ impl core::ops::Sub for &TxScriptCacheCountersSnapshot { fn sub(self, rhs: Self) -> Self::Output { Self::Output { - insert_counts: self.insert_counts.checked_sub(rhs.insert_counts).unwrap_or_default(), - get_counts: self.get_counts.checked_sub(rhs.get_counts).unwrap_or_default(), + insert_counts: self.insert_counts.saturating_sub(rhs.insert_counts), + get_counts: self.get_counts.saturating_sub(rhs.get_counts), } } } diff --git a/kaspad/src/daemon.rs b/kaspad/src/daemon.rs index c13ed1c38..4175206eb 100644 --- a/kaspad/src/daemon.rs +++ b/kaspad/src/daemon.rs @@ -6,7 +6,7 @@ use kaspa_consensus_core::{ errors::config::{ConfigError, ConfigResult}, }; use kaspa_consensus_notify::{root::ConsensusNotificationRoot, service::NotifyService}; -use kaspa_core::{core::Core, info, trace}; +use kaspa_core::{core::Core, debug, info}; use kaspa_core::{kaspad_env::version, task::tick::TickService}; use kaspa_database::prelude::CachePolicy; use kaspa_grpc_server::service::GrpcService; @@ -400,10 +400,10 @@ do you confirm? (answer y/n or pass --yes to the Kaspad command line to confirm .with_tick_service(tick_service.clone()); let perf_monitor = if args.perf_metrics { let cb = move |counters: CountersSnapshot| { - trace!("[{}] {}", kaspa_perf_monitor::SERVICE_NAME, counters.to_process_metrics_display()); - trace!("[{}] {}", kaspa_perf_monitor::SERVICE_NAME, counters.to_io_metrics_display()); + debug!("[{}] {}", kaspa_perf_monitor::SERVICE_NAME, counters.to_process_metrics_display()); + debug!("[{}] {}", kaspa_perf_monitor::SERVICE_NAME, counters.to_io_metrics_display()); #[cfg(feature = "heap")] - trace!("[{}] heap stats: {:?}", kaspa_perf_monitor::SERVICE_NAME, dhat::HeapStats::get()); + debug!("[{}] heap stats: {:?}", kaspa_perf_monitor::SERVICE_NAME, dhat::HeapStats::get()); }; Arc::new(perf_monitor_builder.with_fetch_cb(cb).build()) } else { diff --git a/mining/src/lib.rs b/mining/src/lib.rs index 745fb63f9..141d9d283 100644 --- a/mining/src/lib.rs +++ b/mining/src/lib.rs @@ -30,6 +30,7 @@ pub struct MiningCounters { pub low_priority_tx_counts: AtomicU64, pub block_tx_counts: AtomicU64, pub tx_accepted_counts: AtomicU64, + pub tx_evicted_counts: AtomicU64, pub input_counts: AtomicU64, pub output_counts: AtomicU64, @@ -48,6 +49,7 @@ impl Default for MiningCounters { low_priority_tx_counts: Default::default(), block_tx_counts: Default::default(), tx_accepted_counts: Default::default(), + tx_evicted_counts: Default::default(), input_counts: Default::default(), output_counts: Default::default(), ready_txs_sample: Default::default(), @@ -66,6 +68,7 @@ impl MiningCounters { low_priority_tx_counts: self.low_priority_tx_counts.load(Ordering::Relaxed), block_tx_counts: self.block_tx_counts.load(Ordering::Relaxed), tx_accepted_counts: self.tx_accepted_counts.load(Ordering::Relaxed), + tx_evicted_counts: self.tx_evicted_counts.load(Ordering::Relaxed), input_counts: self.input_counts.load(Ordering::Relaxed), output_counts: self.output_counts.load(Ordering::Relaxed), ready_txs_sample: self.ready_txs_sample.load(Ordering::Relaxed), @@ -101,6 +104,7 @@ pub struct MempoolCountersSnapshot { pub low_priority_tx_counts: u64, pub block_tx_counts: u64, pub tx_accepted_counts: u64, + pub tx_evicted_counts: u64, pub input_counts: u64, pub output_counts: u64, pub ready_txs_sample: u64, @@ -151,13 +155,14 @@ impl core::ops::Sub for &MempoolCountersSnapshot { fn sub(self, rhs: Self) -> Self::Output { Self::Output { - elapsed_time: self.elapsed_time.checked_sub(rhs.elapsed_time).unwrap_or_default(), - high_priority_tx_counts: self.high_priority_tx_counts.checked_sub(rhs.high_priority_tx_counts).unwrap_or_default(), - low_priority_tx_counts: self.low_priority_tx_counts.checked_sub(rhs.low_priority_tx_counts).unwrap_or_default(), - block_tx_counts: self.block_tx_counts.checked_sub(rhs.block_tx_counts).unwrap_or_default(), - tx_accepted_counts: self.tx_accepted_counts.checked_sub(rhs.tx_accepted_counts).unwrap_or_default(), - input_counts: self.input_counts.checked_sub(rhs.input_counts).unwrap_or_default(), - output_counts: self.output_counts.checked_sub(rhs.output_counts).unwrap_or_default(), + elapsed_time: self.elapsed_time.saturating_sub(rhs.elapsed_time), + high_priority_tx_counts: self.high_priority_tx_counts.saturating_sub(rhs.high_priority_tx_counts), + low_priority_tx_counts: self.low_priority_tx_counts.saturating_sub(rhs.low_priority_tx_counts), + block_tx_counts: self.block_tx_counts.saturating_sub(rhs.block_tx_counts), + tx_accepted_counts: self.tx_accepted_counts.saturating_sub(rhs.tx_accepted_counts), + tx_evicted_counts: self.tx_evicted_counts.saturating_sub(rhs.tx_evicted_counts), + input_counts: self.input_counts.saturating_sub(rhs.input_counts), + output_counts: self.output_counts.saturating_sub(rhs.output_counts), ready_txs_sample: (self.ready_txs_sample + rhs.ready_txs_sample) / 2, txs_sample: (self.txs_sample + rhs.txs_sample) / 2, orphans_sample: (self.orphans_sample + rhs.orphans_sample) / 2, @@ -177,8 +182,8 @@ impl core::ops::Sub for &P2pTxCountSample { fn sub(self, rhs: Self) -> Self::Output { Self::Output { - elapsed_time: self.elapsed_time.checked_sub(rhs.elapsed_time).unwrap_or_default(), - low_priority_tx_counts: self.low_priority_tx_counts.checked_sub(rhs.low_priority_tx_counts).unwrap_or_default(), + elapsed_time: self.elapsed_time.saturating_sub(rhs.elapsed_time), + low_priority_tx_counts: self.low_priority_tx_counts.saturating_sub(rhs.low_priority_tx_counts), } } } diff --git a/mining/src/mempool/validate_and_insert_transaction.rs b/mining/src/mempool/validate_and_insert_transaction.rs index 3eddac459..69e08019b 100644 --- a/mining/src/mempool/validate_and_insert_transaction.rs +++ b/mining/src/mempool/validate_and_insert_transaction.rs @@ -1,3 +1,5 @@ +use std::sync::atomic::Ordering; + use crate::mempool::{ errors::{RuleError, RuleResult}, model::{ @@ -84,21 +86,27 @@ impl Mempool { // Before adding the transaction, check if there is room in the pool let transaction_size = transaction.mempool_estimated_bytes(); let txs_to_remove = self.transaction_pool.limit_transaction_count(&transaction, transaction_size)?; - for x in txs_to_remove.iter() { - self.remove_transaction(x, true, TxRemovalReason::MakingRoom, format!(" for {}", transaction_id).as_str())?; - // self.transaction_pool.limit_transaction_count(&transaction) returns the - // smallest prefix of `ready_transactions` (sorted by ascending fee-rate) - // that makes enough room for `transaction`, but since each call to `self.remove_transaction` - // also removes all transactions dependant on `x` we might already have sufficient space, so - // we constantly check the break condition. - // - // Note that self.transaction_pool.len() < self.config.maximum_transaction_count means we have - // at least one available slot in terms of the count limit - if self.transaction_pool.len() < self.config.maximum_transaction_count - && self.transaction_pool.get_estimated_size() + transaction_size <= self.config.mempool_size_limit - { - break; + if !txs_to_remove.is_empty() { + let transaction_pool_len_before = self.transaction_pool.len(); + for x in txs_to_remove.iter() { + self.remove_transaction(x, true, TxRemovalReason::MakingRoom, format!(" for {}", transaction_id).as_str())?; + // self.transaction_pool.limit_transaction_count(&transaction) returns the + // smallest prefix of `ready_transactions` (sorted by ascending fee-rate) + // that makes enough room for `transaction`, but since each call to `self.remove_transaction` + // also removes all transactions dependant on `x` we might already have sufficient space, so + // we constantly check the break condition. + // + // Note that self.transaction_pool.len() < self.config.maximum_transaction_count means we have + // at least one available slot in terms of the count limit + if self.transaction_pool.len() < self.config.maximum_transaction_count + && self.transaction_pool.get_estimated_size() + transaction_size <= self.config.mempool_size_limit + { + break; + } } + self.counters + .tx_evicted_counts + .fetch_add(transaction_pool_len_before.saturating_sub(self.transaction_pool.len()) as u64, Ordering::Relaxed); } assert!( diff --git a/mining/src/monitor.rs b/mining/src/monitor.rs index 876ce9b7a..74449424c 100644 --- a/mining/src/monitor.rs +++ b/mining/src/monitor.rs @@ -69,6 +69,12 @@ impl MiningMonitor { let feerate_estimations = self.mining_manager.clone().get_realtime_feerate_estimations().await; debug!("Realtime feerate estimations: {}", feerate_estimations); } + if delta.tx_evicted_counts > 0 { + info!( + "Mempool stats: {} transactions were evicted from the mempool in favor of incoming higher feerate transactions", + delta.tx_evicted_counts + ); + } if tx_script_cache_snapshot != last_tx_script_cache_snapshot { debug!( "UTXO set stats: {} spent, {} created ({} signatures validated, {} cache hits, {:.2} hit ratio)",