diff --git a/Cargo.lock b/Cargo.lock index d517d8d08d..2f903a7fbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1508,6 +1508,7 @@ dependencies = [ "ckb-hash", "ckb-jsonrpc-types", "ckb-logger", + "ckb-metrics", "ckb-network", "ckb-reward-calculator", "ckb-snapshot", diff --git a/Makefile b/Makefile index 13f5f15557..32b03bbc36 100644 --- a/Makefile +++ b/Makefile @@ -180,6 +180,13 @@ clippy: setup-ckb-test ## Run linter to examine Rust source codes. cargo clippy ${VERBOSE} --all --all-targets --features ${ALL_FEATURES} -- ${CLIPPY_OPTS} -D missing_docs cd test && cargo clippy ${VERBOSE} --all --all-targets --all-features -- ${CLIPPY_OPTS} +.PHONY: bless +bless: setup-ckb-test + cargo clippy --fix --allow-dirty ${VERBOSE} --all --all-targets --features ${ALL_FEATURES} -- ${CLIPPY_OPTS} -D missing_docs + cd test && cargo clippy --fix --allow-dirty ${VERBOSE} --all --all-targets --all-features -- ${CLIPPY_OPTS} + cargo fmt ${VERBOSE} --all + cd test && cargo fmt ${VERBOSE} --all + .PHONY: security-audit security-audit: ## Use cargo-deny to audit Cargo.lock for crates with security vulnerabilities. cargo deny check --hide-inclusion-graph --show-stats advisories sources diff --git a/rpc/README.md b/rpc/README.md index 05789b79e9..ef19194fcd 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -4698,11 +4698,11 @@ Response "result": { "ancestors_count": "0x0", "descendants_count": "0x0", - "entry_status": "Pending", + "entry_status": "pending", "pending_count": "0x1", "proposed_count": "0x0", "rank_in_pending": "0x1", - "score_sortkey": "AncestorsScoreSortKey { fee: Capacity(96942915023), weight: 274, ancestors_fee: Capacity(96942915023), ancestors_weight: 274 }", + "score_sortkey": "fee: 0x16923F7DCF, ancestors_fee: 0x16923F7DCF, weight: 0x112, ancestors_weight: 0x112", "timestamp": "0x18aa1baa54c" }, "id": 42 @@ -6567,11 +6567,11 @@ A Tx details info in tx-pool. * `timestamp`: [`Uint64`](#type-uint64) - The time added into tx-pool -* `entry_status`: `string` - The detailed status in tx-pool, `Pending`, `Gap`, `Proposed` +* `entry_status`: `string` - The detailed status in tx-pool, `pending`, `gap`, `proposed` * `rank_in_pending`: [`Uint64`](#type-uint64) - The rank in pending, starting from 0 -* `pending_count`: [`Uint64`](#type-uint64) - The pending(`Pending` and `Gap`) count +* `pending_count`: [`Uint64`](#type-uint64) - The pending(`pending` and `gap`) count * `proposed_count`: [`Uint64`](#type-uint64) - The proposed count diff --git a/rpc/src/module/pool.rs b/rpc/src/module/pool.rs index 533b582441..9fb1c0555b 100644 --- a/rpc/src/module/pool.rs +++ b/rpc/src/module/pool.rs @@ -283,11 +283,11 @@ pub trait PoolRpc { /// "result": { /// "ancestors_count": "0x0", /// "descendants_count": "0x0", - /// "entry_status": "Pending", + /// "entry_status": "pending", /// "pending_count": "0x1", /// "proposed_count": "0x0", /// "rank_in_pending": "0x1", - /// "score_sortkey": "AncestorsScoreSortKey { fee: Capacity(96942915023), weight: 274, ancestors_fee: Capacity(96942915023), ancestors_weight: 274 }", + /// "score_sortkey": "fee: 0x16923F7DCF, ancestors_fee: 0x16923F7DCF, weight: 0x112, ancestors_weight: 0x112", /// "timestamp": "0x18aa1baa54c" /// }, /// "id": 42 diff --git a/rpc/src/tests/mod.rs b/rpc/src/tests/mod.rs index f13d26c5af..8551cd706a 100644 --- a/rpc/src/tests/mod.rs +++ b/rpc/src/tests/mod.rs @@ -89,7 +89,7 @@ struct RpcTestSuite { impl RpcTestSuite { fn rpc(&self, request: &RpcTestRequest) -> RpcTestResponse { - self.rpc_client + self.rpc_client .post(&self.rpc_uri) .json(&request) .send() diff --git a/test/src/specs/rpc/get_pool.rs b/test/src/specs/rpc/get_pool.rs index c227a92601..39953c9158 100644 --- a/test/src/specs/rpc/get_pool.rs +++ b/test/src/specs/rpc/get_pool.rs @@ -11,10 +11,10 @@ impl Spec for TxPoolEntryStatus { let tx_hash_0 = node0.generate_transaction(); let tx = node0.new_transaction(tx_hash_0.clone()); node0.rpc_client().send_transaction(tx.data().into()); - node0.assert_pool_entry_status(tx_hash_0.clone(), "Pending"); + node0.assert_pool_entry_status(tx_hash_0.clone(), "pending"); node0.mine(1); - node0.assert_pool_entry_status(tx_hash_0.clone(), "Gap"); + node0.assert_pool_entry_status(tx_hash_0.clone(), "gap"); node0.mine(1); - node0.assert_pool_entry_status(tx_hash_0, "Proposed"); + node0.assert_pool_entry_status(tx_hash_0, "proposed"); } } diff --git a/tx-pool/Cargo.toml b/tx-pool/Cargo.toml index 4a08cced80..2a52d27484 100644 --- a/tx-pool/Cargo.toml +++ b/tx-pool/Cargo.toml @@ -16,6 +16,7 @@ ckb-logger = { path = "../util/logger", version = "= 0.113.0-pre" } ckb-verification = { path = "../verification", version = "= 0.113.0-pre" } ckb-systemtime = { path = "../util/systemtime", version = "= 0.113.0-pre" } lru = "0.7.1" + ckb-dao = { path = "../util/dao", version = "= 0.113.0-pre" } ckb-reward-calculator = { path = "../util/reward-calculator", version = "= 0.113.0-pre" } ckb-store = { path = "../store", version = "= 0.113.0-pre" } @@ -23,6 +24,7 @@ ckb-util = { path = "../util", version = "= 0.113.0-pre" } ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.113.0-pre" } ckb-chain-spec = { path = "../spec", version = "= 0.113.0-pre" } ckb-snapshot = { path = "../util/snapshot", version = "= 0.113.0-pre" } +ckb-metrics = {path = "../util/metrics", version = "= 0.113.0-pre"} ckb-error = { path = "../error", version = "= 0.113.0-pre" } tokio = { version = "1", features = ["sync", "process"] } ckb-async-runtime = { path = "../util/runtime", version = "= 0.113.0-pre" } diff --git a/tx-pool/src/component/pool_map.rs b/tx-pool/src/component/pool_map.rs index d3e3e9062b..58b73b1815 100644 --- a/tx-pool/src/component/pool_map.rs +++ b/tx-pool/src/component/pool_map.rs @@ -28,6 +28,16 @@ pub enum Status { Proposed, } +impl ToString for Status { + fn to_string(&self) -> String { + match self { + Status::Pending => "pending".to_string(), + Status::Gap => "gap".to_string(), + Status::Proposed => "proposed".to_string(), + } + } +} + #[derive(Copy, Clone)] enum EntryOp { Add, @@ -182,6 +192,7 @@ impl PoolMap { self.insert_entry(&entry, status); self.record_entry_edges(&entry); self.record_entry_descendants(&entry); + self.track_entry_statics(); Ok(true) } @@ -192,6 +203,7 @@ impl PoolMap { e.status = status; }) .expect("unconsistent pool"); + self.track_entry_statics(); } pub(crate) fn remove_entry(&mut self, id: &ProposalShortId) -> Option { @@ -509,4 +521,21 @@ impl PoolMap { evict_key, }); } + + fn track_entry_statics(&self) { + if let Some(metrics) = ckb_metrics::handle() { + metrics + .ckb_tx_pool_entry + .pending + .set(self.entries.get_by_status(&Status::Pending).len() as i64); + metrics + .ckb_tx_pool_entry + .gap + .set(self.entries.get_by_status(&Status::Gap).len() as i64); + metrics + .ckb_tx_pool_entry + .proposed + .set(self.proposed_size() as i64); + } + } } diff --git a/tx-pool/src/component/sort_key.rs b/tx-pool/src/component/sort_key.rs index ceeab649bc..2c1797d9d7 100644 --- a/tx-pool/src/component/sort_key.rs +++ b/tx-pool/src/component/sort_key.rs @@ -47,6 +47,18 @@ impl Ord for AncestorsScoreSortKey { } } +impl ToString for AncestorsScoreSortKey { + fn to_string(&self) -> String { + format!( + "fee: {:#02X}, ancestors_fee: {:#02X}, weight: {:#02X}, ancestors_weight: {:#02X}", + self.fee.as_u64(), + self.ancestors_fee.as_u64(), + self.weight, + self.ancestors_weight + ) + } +} + /// First compare fee_rate, select the smallest fee_rate, /// and then select the latest timestamp, for eviction, /// the latest timestamp which also means that the fewer descendants may exist. diff --git a/tx-pool/src/pool.rs b/tx-pool/src/pool.rs index f8f8ded3a3..732cf996af 100644 --- a/tx-pool/src/pool.rs +++ b/tx-pool/src/pool.rs @@ -645,13 +645,13 @@ impl TxPool { }; let res = PoolTxDetailInfo { timestamp: entry.inner.timestamp, - entry_status: format!("{:?}", entry.status), + entry_status: entry.status.to_string(), pending_count: self.pool_map.pending_size(), rank_in_pending, proposed_count: ids.proposed.len(), descendants_count: self.pool_map.calc_descendants(id).len(), ancestors_count: self.pool_map.calc_ancestors(id).len(), - score_sortkey: format!("{:?}", entry.inner.as_score_key()), + score_sortkey: entry.inner.as_score_key().to_string(), }; Some(res) } else { diff --git a/util/jsonrpc-types/src/pool.rs b/util/jsonrpc-types/src/pool.rs index e70ad34647..48806c7bc4 100644 --- a/util/jsonrpc-types/src/pool.rs +++ b/util/jsonrpc-types/src/pool.rs @@ -220,11 +220,11 @@ pub enum RawTxPool { pub struct PoolTxDetailInfo { /// The time added into tx-pool pub timestamp: Uint64, - /// The detailed status in tx-pool, `Pending`, `Gap`, `Proposed` + /// The detailed status in tx-pool, `pending`, `gap`, `proposed` pub entry_status: String, /// The rank in pending, starting from 0 pub rank_in_pending: Uint64, - /// The pending(`Pending` and `Gap`) count + /// The pending(`pending` and `gap`) count pub pending_count: Uint64, /// The proposed count pub proposed_count: Uint64, diff --git a/util/metrics/src/lib.rs b/util/metrics/src/lib.rs index 96f55b4069..e67718827f 100644 --- a/util/metrics/src/lib.rs +++ b/util/metrics/src/lib.rs @@ -37,6 +37,15 @@ make_static_metric! { metadata, }, } + + // Struct for CKB tx-pool entry status statistics type label + struct CkbTxPoolEntryStatistics: IntGauge{ + "type" => { + pending, + gap, + proposed, + }, + } } pub struct Metrics { @@ -64,6 +73,8 @@ pub struct Metrics { pub ckb_sys_mem_process: CkbSysMemProcessStatistics, // GaugeVec for CKB system memory jemalloc statistics pub ckb_sys_mem_jemalloc: CkbSysMemJemallocStatistics, + // GaugeVec for CKB tx-pool tx entry status statistics + pub ckb_tx_pool_entry: CkbTxPoolEntryStatistics, /// Histogram for CKB network connections pub ckb_message_bytes: HistogramVec, /// Gauge for CKB rocksdb statistics @@ -127,6 +138,14 @@ static METRICS: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| M ) .unwrap(), ), + ckb_tx_pool_entry: CkbTxPoolEntryStatistics::from( + ®ister_int_gauge_vec!( + "ckb_tx_pool_entry", + "CKB tx-pool entry status statistics", + &["type"] + ) + .unwrap(), + ), ckb_message_bytes: register_histogram_vec!( "ckb_message_bytes", "The CKB message bytes",