diff --git a/Cargo.lock b/Cargo.lock index 7af0535e56..32c34816cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3877,9 +3877,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff55dc09d460954e9ef2fa8a7ced735a964be9981fd50e870b2b3b0705e14964" +checksum = "d9512ffd81e3a3503ed401f79c33168b9148c75038956039166cd750eaa037c3" dependencies = [ "secp256k1-sys", ] diff --git a/devtools/doc/rpc.py b/devtools/doc/rpc.py index 04b55de882..04ceb9822d 100755 --- a/devtools/doc/rpc.py +++ b/devtools/doc/rpc.py @@ -256,8 +256,6 @@ def handle_starttag(self, tag, attrs): self.ty = '`null`' if self.ty == RUST_DOC_PREFIX + '/std/primitive.bool.html': self.ty = '`boolean`' - if self.ty == RUST_DOC_PREFIX + '/std/primitive.f64.html': - self.ty = '`64-bit floating point`' if self.ty == RUST_DOC_PREFIX + '/alloc/string/struct.String.html': self.ty = '`string`' elif self.ty == RUST_DOC_PREFIX + '/core/option/enum.Option.html': diff --git a/rpc/README.md b/rpc/README.md index 63ba548371..451b519f6f 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -1827,7 +1827,7 @@ Returns the fee_rate statistics of confirmed blocks on the chain ###### Returns -If the query has data records, it returns statistics, if not, it returns null. +If the query finds the corresponding historical data, the corresponding statistics are returned, containing the mean and median, in shannons per kilo-weight. If not, it returns null. ###### Examples @@ -1852,8 +1852,8 @@ Response "id": 42, "jsonrpc": "2.0", "result": { - "mean":59.29387293275573, - "median":5.288207297726071 + "mean": "0xe79d", + "median": "0x14a8" } } ``` @@ -5779,15 +5779,15 @@ Response result of the RPC method `estimate_cycles`. ### Type `FeeRateStatics` -The fee_rate statistics information, includes mean and median +The fee_rate statistics information, includes mean and median, unit: shannons per kilo-weight #### Fields `FeeRateStatics` is a JSON object with the following fields. -* `mean`: `64-bit floating point` - mean +* `mean`: [`Uint64`](#type-uint64) - mean -* `median`: `64-bit floating point` - median +* `median`: [`Uint64`](#type-uint64) - median ### Type `H256` diff --git a/rpc/src/module/chain.rs b/rpc/src/module/chain.rs index a9f3400c29..7a06d15765 100644 --- a/rpc/src/module/chain.rs +++ b/rpc/src/module/chain.rs @@ -1498,7 +1498,10 @@ pub trait ChainRpc { /// /// ## Returns /// - /// If the query has data records, it returns statistics, if not, it returns null. + /// If the query finds the corresponding historical data, + /// the corresponding statistics are returned, + /// containing the mean and median, in shannons per kilo-weight. + /// If not, it returns null. /// /// ## Examples /// @@ -1520,8 +1523,8 @@ pub trait ChainRpc { /// "id": 42, /// "jsonrpc": "2.0", /// "result": { - /// "mean":59.29387293275573, - /// "median":5.288207297726071 + /// "mean": "0xe79d", + /// "median": "0x14a8" /// } /// } /// ``` diff --git a/rpc/src/tests/fee_rate.rs b/rpc/src/tests/fee_rate.rs index ff289f5e1a..062c55bd7d 100644 --- a/rpc/src/tests/fee_rate.rs +++ b/rpc/src/tests/fee_rate.rs @@ -54,8 +54,8 @@ fn test_fee_rate_statics() { assert_eq!( statistics, Some(FeeRateStatics { - mean: 11.0, - median: 11.0 + mean: 11_000.into(), + median: 11_000.into(), }) ); @@ -63,8 +63,8 @@ fn test_fee_rate_statics() { assert_eq!( statistics, Some(FeeRateStatics { - mean: 17.0, - median: 17.0 + mean: 17_000.into(), + median: 17_000.into() }) ); @@ -72,8 +72,8 @@ fn test_fee_rate_statics() { assert_eq!( statistics, Some(FeeRateStatics { - mean: 11.0, - median: 11.0 + mean: 11_000.into(), + median: 11_000.into(), }) ); @@ -81,8 +81,8 @@ fn test_fee_rate_statics() { assert_eq!( statistics, Some(FeeRateStatics { - mean: 21.0, - median: 21.0 + mean: 21_000.into(), + median: 21_000.into(), }) ); } diff --git a/rpc/src/util/fee_rate.rs b/rpc/src/util/fee_rate.rs index dc6d07177b..d5ff490ae5 100644 --- a/rpc/src/util/fee_rate.rs +++ b/rpc/src/util/fee_rate.rs @@ -1,7 +1,7 @@ use ckb_jsonrpc_types::FeeRateStatics; use ckb_shared::Snapshot; use ckb_store::ChainStore; -use ckb_types::core::{tx_pool::get_transaction_weight, BlockExt, BlockNumber}; +use ckb_types::core::{tx_pool::get_transaction_weight, BlockExt, BlockNumber, FeeRate}; const DEFAULT_TARGET: u64 = 21; const MIN_TARGET: u64 = 1; @@ -11,16 +11,16 @@ fn is_even(n: u64) -> bool { n & 1 == 0 } -fn mean(numbers: &[f64]) -> f64 { - let sum: f64 = numbers.iter().sum(); - sum / numbers.len() as f64 +fn mean(numbers: &[u64]) -> u64 { + let sum: u64 = numbers.iter().sum(); + sum / numbers.len() as u64 } -fn median(numbers: &mut [f64]) -> f64 { - numbers.sort_unstable_by(|a, b| a.partial_cmp(b).expect("slice does not contain NaN")); +fn median(numbers: &mut [u64]) -> u64 { + numbers.sort_unstable(); let mid = numbers.len() / 2; if numbers.len() % 2 == 0 { - mean(&[numbers[mid - 1], numbers[mid]]) as f64 + mean(&[numbers[mid - 1], numbers[mid]]) } else { numbers[mid] } @@ -30,9 +30,9 @@ pub(crate) trait FeeRateProvider { fn get_tip_number(&self) -> BlockNumber; fn get_block_ext_by_number(&self, number: BlockNumber) -> Option; - fn collect(&self, target: u64, f: F) -> Vec + fn collect(&self, target: u64, f: F) -> Vec where - F: FnMut(Vec, BlockExt) -> Vec, + F: FnMut(Vec, BlockExt) -> Vec, { let tip_number = self.get_tip_number(); let start = std::cmp::max( @@ -88,7 +88,7 @@ where ) { let weight = get_transaction_weight(size as usize, cycles); if weight > 0 { - fee_rates.push(fee.as_u64() as f64 / weight as f64); + fee_rates.push(FeeRate::calculate(fee, weight).as_u64()); } } } @@ -99,8 +99,8 @@ where None } else { Some(FeeRateStatics { - mean: mean(&fee_rates), - median: median(&mut fee_rates), + mean: mean(&fee_rates).into(), + median: median(&mut fee_rates).into(), }) } } diff --git a/tx-pool/src/util.rs b/tx-pool/src/util.rs index 4e60d76062..7b4172d068 100644 --- a/tx-pool/src/util.rs +++ b/tx-pool/src/util.rs @@ -46,7 +46,10 @@ pub(crate) fn check_tx_fee( let fee = DaoCalculator::new(snapshot.consensus(), &snapshot.as_data_provider()) .transaction_fee(rtx) .map_err(|err| Reject::Malformed(format!("{}", err)))?; - let min_fee = tx_pool.config.min_fee_rate.fee(tx_size); + // Theoretically we cannot use size as weight directly to calculate fee_rate, + // here min fee rate is used as a cheap check, + // so we will use size to calculate fee_rate directly + let min_fee = tx_pool.config.min_fee_rate.fee(tx_size as u64); // reject txs which fee lower than min fee rate if fee < min_fee { let reject = diff --git a/util/jsonrpc-types/src/blockchain.rs b/util/jsonrpc-types/src/blockchain.rs index c62a833cff..0faf151f84 100644 --- a/util/jsonrpc-types/src/blockchain.rs +++ b/util/jsonrpc-types/src/blockchain.rs @@ -1398,11 +1398,11 @@ impl HardForkFeature { } } -/// The fee_rate statistics information, includes mean and median +/// The fee_rate statistics information, includes mean and median, unit: shannons per kilo-weight #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct FeeRateStatics { /// mean - pub mean: f64, + pub mean: Uint64, /// median - pub median: f64, + pub median: Uint64, } diff --git a/util/types/src/core/fee_rate.rs b/util/types/src/core/fee_rate.rs index 2b5ca25f6a..8bb2caee30 100644 --- a/util/types/src/core/fee_rate.rs +++ b/util/types/src/core/fee_rate.rs @@ -1,23 +1,23 @@ use crate::core::Capacity; -/// shannons per kilobytes +/// shannons per kilo-weight #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct FeeRate(pub u64); -const KB: u64 = 1000; +const KW: u64 = 1000; impl FeeRate { /// TODO(doc): @doitian - pub fn calculate(fee: Capacity, weight: usize) -> Self { + pub fn calculate(fee: Capacity, weight: u64) -> Self { if weight == 0 { return FeeRate::zero(); } - FeeRate::from_u64(fee.as_u64().saturating_mul(KB) / (weight as u64)) + FeeRate::from_u64(fee.as_u64().saturating_mul(KW) / weight) } /// TODO(doc): @doitian - pub const fn from_u64(fee_per_kb: u64) -> Self { - FeeRate(fee_per_kb) + pub const fn from_u64(fee_per_kw: u64) -> Self { + FeeRate(fee_per_kw) } /// TODO(doc): @doitian @@ -31,8 +31,8 @@ impl FeeRate { } /// TODO(doc): @doitian - pub fn fee(self, size: usize) -> Capacity { - let fee = self.0.saturating_mul(size as u64) / KB; + pub fn fee(self, weight: u64) -> Capacity { + let fee = self.0.saturating_mul(weight) / KW; Capacity::shannons(fee) } }