From d6b5eb9614df0d244c95d66f479413934d9b0098 Mon Sep 17 00:00:00 2001 From: quake Date: Mon, 20 May 2024 13:21:25 +0900 Subject: [PATCH 1/7] feat: add estimate_fee_rate rpc --- rpc/README.md | 48 ++++++++++++++++++ rpc/src/module/pool.rs | 65 ++++++++++++++++++++++++- tx-pool/src/component/pool_map.rs | 29 ++++++++++- tx-pool/src/component/tests/estimate.rs | 56 +++++++++++++++++++++ tx-pool/src/component/tests/mod.rs | 1 + tx-pool/src/pool.rs | 12 ++++- tx-pool/src/process.rs | 6 +++ tx-pool/src/service.rs | 19 ++++++++ 8 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 tx-pool/src/component/tests/estimate.rs diff --git a/rpc/README.md b/rpc/README.md index 016b32b8b8..6dddc8d57a 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -104,6 +104,7 @@ The crate `ckb-rpc`'s minimum supported rustc version is 1.71.1. * [Module Pool](#module-pool) [👉 OpenRPC spec](http://playground.open-rpc.org/?uiSchema[appBar][ui:title]=CKB-Pool&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:logoUrl]=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/ckb-logo.jpg&schemaUrl=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/json/pool_rpc_doc.json) * [Method `send_transaction`](#pool-send_transaction) + * [Method `estimate_fee_rate`](#pool-estimate_fee_rate) * [Method `test_tx_pool_accept`](#pool-test_tx_pool_accept) * [Method `remove_transaction`](#pool-remove_transaction) * [Method `tx_pool_info`](#pool-tx_pool_info) @@ -4422,6 +4423,53 @@ Response } ``` + +#### Method `estimate_fee_rate` +* `estimate_fee_rate(target_to_be_committed)` + * `target_to_be_committed`: [`Uint64`](#type-uint64) +* result: [`Uint64`](#type-uint64) + +Estimate fee rate for a transaction to be committed within target block number by using a simple strategy. + +Since CKB transaction confirmation involves a two-step process—1) propose and 2) commit, it is complex to +predict the transaction fee accurately with the expectation that it will be included within a certain block height. + +This method relies on two assumptions and uses a simple strategy to estimate the transaction fee: 1) all transactions +in the pool are waiting to be proposed, and 2) no new transactions will be added to the pool. + +In practice, this simple method should achieve good accuracy fee rate and running performance. + +###### Params + +* `target_to_be_committed` - The target block number to be committed, minimum value is 3 and maximum value is 131. + +###### Returns + +The estimated fee rate in shannons per kilobyte. + +###### Examples + +```json +{ + "id": 42, + "jsonrpc": "2.0", + "method": "estimate_fee_rate", + "params": [ + "0x4" + ] +} +``` + +Response + +```json +{ + "id": 42, + "jsonrpc": "2.0", + "result": "0x3e8" +} +``` + #### Method `test_tx_pool_accept` * `test_tx_pool_accept(tx, outputs_validator)` diff --git a/rpc/src/module/pool.rs b/rpc/src/module/pool.rs index aab1071e0d..0551f9de78 100644 --- a/rpc/src/module/pool.rs +++ b/rpc/src/module/pool.rs @@ -3,7 +3,8 @@ use async_trait::async_trait; use ckb_chain_spec::consensus::Consensus; use ckb_constant::hardfork::{mainnet, testnet}; use ckb_jsonrpc_types::{ - EntryCompleted, OutputsValidator, PoolTxDetailInfo, RawTxPool, Script, Transaction, TxPoolInfo, + BlockNumber, EntryCompleted, OutputsValidator, PoolTxDetailInfo, RawTxPool, Script, + Transaction, TxPoolInfo, Uint64, }; use ckb_logger::error; use ckb_shared::shared::Shared; @@ -110,6 +111,50 @@ pub trait PoolRpc { outputs_validator: Option, ) -> Result; + /// Estimate fee rate for a transaction to be committed within target block number by using a simple strategy. + /// + /// Since CKB transaction confirmation involves a two-step process—1) propose and 2) commit, it is complex to + /// predict the transaction fee accurately with the expectation that it will be included within a certain block height. + /// + /// This method relies on two assumptions and uses a simple strategy to estimate the transaction fee: 1) all transactions + /// in the pool are waiting to be proposed, and 2) no new transactions will be added to the pool. + /// + /// In practice, this simple method should achieve good accuracy fee rate and running performance. + /// + /// ## Params + /// + /// * `target_to_be_committed` - The target block number to be committed, minimum value is 3 and maximum value is 131. + /// + /// ## Returns + /// + /// The estimated fee rate in shannons per kilobyte. + /// + /// ## Examples + /// + /// ```json + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "method": "estimate_fee_rate", + /// "params": [ + /// "0x4" + /// ] + /// } + /// ``` + /// + /// Response + /// + /// ```json + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "result": "0x3e8" + /// } + /// ``` + /// + #[rpc(name = "estimate_fee_rate")] + fn estimate_fee_rate(&self, target_to_be_committed: BlockNumber) -> Result; + /// Test if a transaction can be accepted by the transaction pool without inserting it into the pool or rebroadcasting it to peers. /// The parameters and errors of this method are the same as `send_transaction`. /// @@ -604,6 +649,24 @@ impl PoolRpc for PoolRpcImpl { } } + fn estimate_fee_rate(&self, target_to_be_committed: BlockNumber) -> Result { + let target_to_be_committed = target_to_be_committed.value(); + if !(3..=131).contains(&target_to_be_committed) { + return Err(RPCError::invalid_params( + "target to be committed block number must be in range [3, 131]", + )); + } + let fee_rate = self + .shared + .tx_pool_controller() + .estimate_fee_rate(target_to_be_committed) + .map_err(|e| { + error!("Send estimate_fee_rate request error {}", e); + RPCError::ckb_internal_error(e) + })?; + Ok(fee_rate.as_u64().into()) + } + fn test_tx_pool_accept( &self, tx: Transaction, diff --git a/tx-pool/src/component/pool_map.rs b/tx-pool/src/component/pool_map.rs index a421f10e04..ba31c1fb5a 100644 --- a/tx-pool/src/component/pool_map.rs +++ b/tx-pool/src/component/pool_map.rs @@ -9,7 +9,7 @@ use crate::error::Reject; use crate::TxEntry; use ckb_logger::{debug, error, trace}; use ckb_types::core::error::OutPointError; -use ckb_types::core::Cycle; +use ckb_types::core::{Cycle, FeeRate}; use ckb_types::packed::OutPoint; use ckb_types::prelude::*; use ckb_types::{ @@ -329,6 +329,33 @@ impl PoolMap { conflicts } + pub(crate) fn estimate_fee_rate( + &self, + mut target_blocks: usize, + max_block_bytes: usize, + max_block_cycles: Cycle, + min_fee_rate: FeeRate, + ) -> FeeRate { + debug_assert!(target_blocks > 0); + let iter = self.entries.iter_by_score().rev(); + let mut current_block_bytes = 0; + let mut current_block_cycles = 0; + for entry in iter { + current_block_bytes += entry.inner.size; + current_block_cycles += entry.inner.cycles; + if current_block_bytes >= max_block_bytes || current_block_cycles >= max_block_cycles { + target_blocks -= 1; + if target_blocks == 0 { + return entry.inner.fee_rate(); + } + current_block_bytes = entry.inner.size; + current_block_cycles = entry.inner.cycles; + } + } + + min_fee_rate + } + // find the pending txs sorted by score, and return their proposal short ids pub(crate) fn get_proposals( &self, diff --git a/tx-pool/src/component/tests/estimate.rs b/tx-pool/src/component/tests/estimate.rs new file mode 100644 index 0000000000..fa222fd91a --- /dev/null +++ b/tx-pool/src/component/tests/estimate.rs @@ -0,0 +1,56 @@ +use crate::component::tests::util::build_tx; +use crate::component::{ + entry::TxEntry, + pool_map::{PoolMap, Status}, +}; +use ckb_types::core::{Capacity, Cycle, FeeRate}; + +#[test] +fn test_estimate_fee_rate() { + let mut pool = PoolMap::new(1000); + for i in 0..1024 { + let tx = build_tx(vec![(&Default::default(), i as u32)], 1); + let entry = TxEntry::dummy_resolve(tx, i + 1, Capacity::shannons(i + 1), 1000); + pool.add_entry(entry, Status::Pending).unwrap(); + } + + assert_eq!( + FeeRate::from_u64(42), + pool.estimate_fee_rate(1, usize::MAX, Cycle::MAX, FeeRate::from_u64(42)) + ); + + assert_eq!( + FeeRate::from_u64(1024), + pool.estimate_fee_rate(1, 1000, Cycle::MAX, FeeRate::from_u64(1)) + ); + assert_eq!( + FeeRate::from_u64(1023), + pool.estimate_fee_rate(1, 2000, Cycle::MAX, FeeRate::from_u64(1)) + ); + assert_eq!( + FeeRate::from_u64(1016), + pool.estimate_fee_rate(2, 5000, Cycle::MAX, FeeRate::from_u64(1)) + ); + + assert_eq!( + FeeRate::from_u64(1024), + pool.estimate_fee_rate(1, usize::MAX, 1, FeeRate::from_u64(1)) + ); + assert_eq!( + FeeRate::from_u64(1023), + pool.estimate_fee_rate(1, usize::MAX, 2047, FeeRate::from_u64(1)) + ); + assert_eq!( + FeeRate::from_u64(1015), + pool.estimate_fee_rate(2, usize::MAX, 5110, FeeRate::from_u64(1)) + ); + + assert_eq!( + FeeRate::from_u64(624), + pool.estimate_fee_rate(100, 5000, 5110, FeeRate::from_u64(1)) + ); + assert_eq!( + FeeRate::from_u64(1), + pool.estimate_fee_rate(1000, 5000, 5110, FeeRate::from_u64(1)) + ); +} diff --git a/tx-pool/src/component/tests/mod.rs b/tx-pool/src/component/tests/mod.rs index ac625eede3..4f344ce443 100644 --- a/tx-pool/src/component/tests/mod.rs +++ b/tx-pool/src/component/tests/mod.rs @@ -1,5 +1,6 @@ mod chunk; mod entry; +mod estimate; mod links; mod orphan; mod pending; diff --git a/tx-pool/src/pool.rs b/tx-pool/src/pool.rs index 54b2395e4c..1780f20a5f 100644 --- a/tx-pool/src/pool.rs +++ b/tx-pool/src/pool.rs @@ -12,7 +12,7 @@ use ckb_logger::{debug, error, warn}; use ckb_snapshot::Snapshot; use ckb_store::ChainStore; use ckb_types::core::tx_pool::PoolTxDetailInfo; -use ckb_types::core::CapacityError; +use ckb_types::core::{BlockNumber, CapacityError, FeeRate}; use ckb_types::packed::OutPoint; use ckb_types::{ core::{ @@ -528,6 +528,16 @@ impl TxPool { (entries, size, cycles) } + pub(crate) fn estimate_fee_rate(&self, target_to_be_committed: BlockNumber) -> FeeRate { + self.pool_map.estimate_fee_rate( + (target_to_be_committed - self.snapshot.consensus().tx_proposal_window().closest()) + as usize, + self.snapshot.consensus().max_block_bytes() as usize, + self.snapshot.consensus().max_block_cycles(), + self.config.min_fee_rate, + ) + } + pub(crate) fn check_rbf( &self, snapshot: &Snapshot, diff --git a/tx-pool/src/process.rs b/tx-pool/src/process.rs index 39627ccf9a..f898309255 100644 --- a/tx-pool/src/process.rs +++ b/tx-pool/src/process.rs @@ -20,6 +20,7 @@ use ckb_snapshot::Snapshot; use ckb_store::data_loader_wrapper::AsDataLoader; use ckb_store::ChainStore; use ckb_types::core::error::OutPointError; +use ckb_types::core::{BlockNumber, FeeRate}; use ckb_types::{ core::{cell::ResolvedTransaction, BlockView, Capacity, Cycle, HeaderView, TransactionView}, packed::{Byte32, ProposalShortId}, @@ -339,6 +340,11 @@ impl TxPoolService { } } + pub(crate) async fn estimate_fee_rate(&self, target_to_be_committed: BlockNumber) -> FeeRate { + let pool = self.tx_pool.read().await; + pool.estimate_fee_rate(target_to_be_committed) + } + pub(crate) async fn test_accept_tx(&self, tx: TransactionView) -> Result { // non contextual verify first self.non_contextual_verify(&tx, None)?; diff --git a/tx-pool/src/service.rs b/tx-pool/src/service.rs index 64f17f4aa9..db48fc48d6 100644 --- a/tx-pool/src/service.rs +++ b/tx-pool/src/service.rs @@ -19,6 +19,7 @@ use ckb_network::{NetworkController, PeerIndex}; use ckb_snapshot::Snapshot; use ckb_stop_handler::new_tokio_exit_rx; use ckb_types::core::tx_pool::{EntryCompleted, PoolTxDetailInfo, TransactionWithStatus, TxStatus}; +use ckb_types::core::{BlockNumber, FeeRate}; use ckb_types::{ core::{ tx_pool::{Reject, TxPoolEntryInfo, TxPoolIds, TxPoolInfo, TRANSACTION_SIZE_LIMIT}, @@ -91,6 +92,7 @@ pub(crate) enum Message { BlockTemplate(Request), SubmitLocalTx(Request), RemoveLocalTx(Request), + EstimateFeeRate(Request), TestAcceptTx(Request), SubmitRemoteTx(Request<(TransactionView, Cycle, PeerIndex), ()>), NotifyTxs(Notify>), @@ -228,6 +230,14 @@ impl TxPoolController { send_message!(self, SubmitLocalTx, tx) } + /// Estimate fee rate for a transaction to be committed within target block number by using a simple strategy + pub fn estimate_fee_rate( + &self, + target_to_be_committed: BlockNumber, + ) -> Result { + send_message!(self, EstimateFeeRate, target_to_be_committed) + } + /// test if a tx can be accepted by tx-pool /// Won't be broadcasted to network /// won't be insert to tx-pool @@ -706,6 +716,15 @@ async fn process(mut service: TxPoolService, message: Message) { error!("Responder sending remove_tx result failed {:?}", e); }; } + Message::EstimateFeeRate(Request { + responder, + arguments: target_to_be_committed, + }) => { + let fee_rate = service.estimate_fee_rate(target_to_be_committed).await; + if let Err(e) = responder.send(fee_rate) { + error!("Responder sending estimate_fee_rate failed {:?}", e); + }; + } Message::TestAcceptTx(Request { responder, arguments: tx, From d3fa3196d57de0aab741be4948157b414f5077ec Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Mon, 20 May 2024 18:51:32 +0800 Subject: [PATCH 2/7] feat: (experimental) optional fee estimator with different algorithms --- Cargo.lock | 13 + Cargo.toml | 1 + chain/src/chain.rs | 7 + resource/ckb.toml | 4 + rpc/README.md | 61 ++ rpc/src/module/experiment.rs | 58 +- rpc/src/tests/examples.rs | 2 + shared/Cargo.toml | 1 + shared/src/shared_builder.rs | 50 +- spec/src/consensus.rs | 9 +- tx-pool/Cargo.toml | 1 + tx-pool/src/process.rs | 15 +- tx-pool/src/service.rs | 38 +- util/app-config/src/app_config.rs | 3 + util/app-config/src/configs/fee_estimator.rs | 18 + util/app-config/src/configs/mod.rs | 2 + util/app-config/src/legacy/mod.rs | 4 + util/fee-estimator/Cargo.toml | 16 + util/fee-estimator/src/constants.rs | 24 + util/fee-estimator/src/error.rs | 14 + .../src/estimator/confirmation_fraction.rs | 600 ++++++++++++++++++ util/fee-estimator/src/estimator/mod.rs | 92 +++ .../src/estimator/weight_units_flow.rs | 463 ++++++++++++++ util/fee-estimator/src/lib.rs | 8 + util/jsonrpc-types/src/fee_estimator.rs | 43 ++ util/jsonrpc-types/src/lib.rs | 2 + util/launcher/Cargo.toml | 1 - util/launcher/src/lib.rs | 1 + util/types/src/core/fee_estimator.rs | 14 + util/types/src/core/mod.rs | 2 + 30 files changed, 1555 insertions(+), 12 deletions(-) create mode 100644 util/app-config/src/configs/fee_estimator.rs create mode 100644 util/fee-estimator/Cargo.toml create mode 100644 util/fee-estimator/src/constants.rs create mode 100644 util/fee-estimator/src/error.rs create mode 100644 util/fee-estimator/src/estimator/confirmation_fraction.rs create mode 100644 util/fee-estimator/src/estimator/mod.rs create mode 100644 util/fee-estimator/src/estimator/weight_units_flow.rs create mode 100644 util/fee-estimator/src/lib.rs create mode 100644 util/jsonrpc-types/src/fee_estimator.rs create mode 100644 util/types/src/core/fee_estimator.rs diff --git a/Cargo.lock b/Cargo.lock index 96aa488a20..775ac7bba0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -864,6 +864,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ckb-fee-estimator" +version = "0.117.0-pre" +dependencies = [ + "ckb-chain-spec", + "ckb-logger", + "ckb-types", + "ckb-util", + "thiserror", +] + [[package]] name = "ckb-fixed-hash" version = "0.117.0-pre" @@ -1505,6 +1516,7 @@ dependencies = [ "ckb-db", "ckb-db-schema", "ckb-error", + "ckb-fee-estimator", "ckb-logger", "ckb-migrate", "ckb-notify", @@ -1673,6 +1685,7 @@ dependencies = [ "ckb-dao", "ckb-db", "ckb-error", + "ckb-fee-estimator", "ckb-hash", "ckb-jsonrpc-types", "ckb-logger", diff --git a/Cargo.toml b/Cargo.toml index 3361e53e1d..5c35229b42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,6 +91,7 @@ members = [ "util/instrument", "rpc", "util/light-client-protocol-server", + "util/fee-estimator", "util/launcher", "devtools/doc/rpc-gen", "ckb-bin" diff --git a/chain/src/chain.rs b/chain/src/chain.rs index c1915ed48e..1851ae50b0 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -460,6 +460,7 @@ impl ChainService { // is_better_than let new_best_block = cannon_total_difficulty > current_total_difficulty; + let in_ibd = self.shared.is_initial_block_download(); if new_best_block { debug!( "Newly found best block : {} => {:#x}, difficulty diff = {:#x}", @@ -517,6 +518,9 @@ impl ChainService { ) { error!("Notify update_tx_pool_for_reorg error {}", e); } + if let Err(e) = tx_pool_controller.update_ibd_state(in_ibd) { + error!("Notify update_ibd_state error {}", e); + } } let block_ref: &BlockView = █ @@ -546,6 +550,9 @@ impl ChainService { if let Err(e) = tx_pool_controller.notify_new_uncle(block_ref.as_uncle()) { error!("Notify new_uncle error {}", e); } + if let Err(e) = tx_pool_controller.update_ibd_state(in_ibd) { + error!("Notify update_ibd_state error {}", e); + } } } diff --git a/resource/ckb.toml b/resource/ckb.toml index 1ccd93b623..22438aefc9 100644 --- a/resource/ckb.toml +++ b/resource/ckb.toml @@ -218,3 +218,7 @@ block_uncles_cache_size = 30 # db_port = 5432 # db_user = "postgres" # db_password = "123456" +# +# # [fee_estimator] +# # Specifies the fee estimates algorithm. Current algorithms: ConfirmationFraction, WeightUnitsFlow. +# # algorithm = "WeightUnitsFlow" diff --git a/rpc/README.md b/rpc/README.md index 016b32b8b8..d6318f070c 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -70,6 +70,7 @@ The crate `ckb-rpc`'s minimum supported rustc version is 1.71.1. * [Method `dry_run_transaction`](#experiment-dry_run_transaction) * [Method `calculate_dao_maximum_withdraw`](#experiment-calculate_dao_maximum_withdraw) + * [Method `get_fee_estimates`](#experiment-get_fee_estimates) * [Module Indexer](#module-indexer) [👉 OpenRPC spec](http://playground.open-rpc.org/?uiSchema[appBar][ui:title]=CKB-Indexer&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:logoUrl]=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/ckb-logo.jpg&schemaUrl=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/json/indexer_rpc_doc.json) * [Method `get_indexer_tip`](#indexer-get_indexer_tip) @@ -208,6 +209,7 @@ The crate `ckb-rpc`'s minimum supported rustc version is 1.71.1. * [Type `Ratio`](#type-ratio) * [Type `RationalU256`](#type-rationalu256) * [Type `RawTxPool`](#type-rawtxpool) + * [Type `RecommendedFeeRates`](#type-recommendedfeerates) * [Type `RemoteNode`](#type-remotenode) * [Type `RemoteNodeProtocol`](#type-remotenodeprotocol) * [Type `ResponseFormat`](#type-responseformat_for_blockview) @@ -2162,6 +2164,50 @@ Response } ``` + +#### Method `get_fee_estimates` +* `get_fee_estimates()` + +* result: [`RecommendedFeeRates`](#type-recommendedfeerates) + +Get fee estimates. + +###### Returns + +Recommended fee rates in 4 levels of priorities: +- No priority (about 2 hours). +- Low priority (about 1 hour). +- Medium priority (about 10 minutes). +- High priority (as soon as possible). + +###### Examples + +Request + +```json +{ + "id": 42, + "jsonrpc": "2.0", + "method": "get_fee_estimates", + "params": [] +} +``` + +Response + +```json +{ + "id": 42, + "jsonrpc": "2.0", + "result": { + "no_priority": 1000, + "low_priority": 1000, + "medium_priority": 1000, + "high_priority": 1000 + } +} +``` + ### Module `Indexer` - [👉 OpenRPC spec](http://playground.open-rpc.org/?uiSchema[appBar][ui:title]=CKB-Indexer&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:logoUrl]=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/ckb-logo.jpg&schemaUrl=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/json/indexer_rpc_doc.json) @@ -6606,6 +6652,21 @@ All transactions in tx-pool. [`TxPoolIds`]: struct.TxPoolIds.html [`TxPoolEntries`]: struct.TxPoolEntries.html +### Type `RecommendedFeeRates` +Recommended fee rates. + +#### Fields + +`RecommendedFeeRates` is a JSON object with the following fields. + +* `high_priority`: `integer` - High-priority fee rate. + +* `low_priority`: `integer` - Low-priority fee rate. + +* `medium_priority`: `integer` - Medium-priority fee rate. + +* `no_priority`: `integer` - Default fee rate. + ### Type `RemoteNode` Information of a remote node. diff --git a/rpc/src/module/experiment.rs b/rpc/src/module/experiment.rs index 90e910dc1a..6a0f8fec06 100644 --- a/rpc/src/module/experiment.rs +++ b/rpc/src/module/experiment.rs @@ -3,7 +3,8 @@ use crate::module::chain::CyclesEstimator; use async_trait::async_trait; use ckb_dao::DaoCalculator; use ckb_jsonrpc_types::{ - Capacity, DaoWithdrawingCalculationKind, EstimateCycles, OutPoint, Transaction, + Capacity, DaoWithdrawingCalculationKind, EstimateCycles, OutPoint, RecommendedFeeRates, + Transaction, }; use ckb_shared::{shared::Shared, Snapshot}; use ckb_store::ChainStore; @@ -162,6 +163,46 @@ pub trait ExperimentRpc { out_point: OutPoint, kind: DaoWithdrawingCalculationKind, ) -> Result; + + /// Get fee estimates. + /// + /// ## Returns + /// + /// Recommended fee rates in 4 levels of priorities: + /// - No priority (about 2 hours). + /// - Low priority (about 1 hour). + /// - Medium priority (about 10 minutes). + /// - High priority (as soon as possible). + /// + /// ## Examples + /// + /// Request + /// + /// ```json + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "method": "get_fee_estimates", + /// "params": [] + /// } + /// ``` + /// + /// Response + /// + /// ```json + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "result": { + /// "no_priority": 1000, + /// "low_priority": 1000, + /// "medium_priority": 1000, + /// "high_priority": 1000 + /// } + /// } + /// ``` + #[rpc(name = "get_fee_estimates")] + fn get_fee_estimates(&self) -> Result; } #[derive(Clone)] @@ -241,4 +282,19 @@ impl ExperimentRpc for ExperimentRpcImpl { } } } + + fn get_fee_estimates(&self) -> Result { + let tx_pool = self.shared.tx_pool_controller(); + let fee_rates_res = tx_pool + .get_fee_estimates() + .map_err(|err| RPCError::custom(RPCError::CKBInternalError, err.to_string()))?; + if let Ok(Some(fee_rates)) = fee_rates_res { + Ok(fee_rates) + } else { + // TODO merge code from PR#4465 + let msg = "fallback fee estimates algorithm is unfinished"; + let err = RPCError::custom(RPCError::CKBInternalError, msg.to_owned()); + Err(err) + } + } } diff --git a/rpc/src/tests/examples.rs b/rpc/src/tests/examples.rs index 03afbb9d3c..d9dfa030fc 100644 --- a/rpc/src/tests/examples.rs +++ b/rpc/src/tests/examples.rs @@ -15,6 +15,7 @@ use std::hash; use std::io::{self, BufRead}; use std::path::PathBuf; +use ckb_jsonrpc_types::RecommendedFeeRates; use ckb_types::{ core::{capacity_bytes, Capacity, TransactionBuilder, TransactionView}, h256, @@ -389,6 +390,7 @@ fn mock_rpc_response(example: &RpcTestExample, response: &mut RpcTestResponse) { "get_pool_tx_detail_info" => { response.result["timestamp"] = example.response.result["timestamp"].clone() } + "get_fee_estimates" => replace_rpc_response::(example, response), _ => {} } } diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 794f800946..96ae061663 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -29,6 +29,7 @@ ckb-systemtime = { path = "../util/systemtime", version = "= 0.117.0-pre" } ckb-channel = { path = "../util/channel", version = "= 0.117.0-pre" } ckb-app-config = {path = "../util/app-config", version = "= 0.117.0-pre"} ckb-migrate = { path = "../util/migrate", version = "= 0.117.0-pre" } +ckb-fee-estimator = {path = "../util/fee-estimator", version = "= 0.117.0-pre"} once_cell = "1.8.0" tempfile.workspace = true diff --git a/shared/src/shared_builder.rs b/shared/src/shared_builder.rs index 985add3ba0..4a47f858da 100644 --- a/shared/src/shared_builder.rs +++ b/shared/src/shared_builder.rs @@ -13,12 +13,14 @@ use ckb_proposal_table::ProposalView; use ckb_snapshot::{Snapshot, SnapshotMgr}; use ckb_app_config::{ - BlockAssemblerConfig, DBConfig, ExitCode, NotifyConfig, StoreConfig, TxPoolConfig, + BlockAssemblerConfig, DBConfig, ExitCode, FeeEstimatorAlgo, FeeEstimatorConfig, NotifyConfig, + StoreConfig, TxPoolConfig, }; use ckb_async_runtime::{new_background_runtime, Handle}; use ckb_db::RocksDB; use ckb_db_schema::COLUMNS; use ckb_error::{Error, InternalErrorKind}; +use ckb_fee_estimator::FeeEstimator; use ckb_logger::{error, info}; use ckb_migrate::migrate::Migrate; use ckb_notify::{NotifyController, NotifyService}; @@ -45,6 +47,7 @@ pub struct SharedBuilder { block_assembler_config: Option, notify_config: Option, async_handle: Handle, + fee_estimator_config: Option, } /// Open or create a rocksdb @@ -148,6 +151,7 @@ impl SharedBuilder { store_config: None, block_assembler_config: None, async_handle, + fee_estimator_config: None, }) } @@ -193,6 +197,7 @@ impl SharedBuilder { store_config: None, block_assembler_config: None, async_handle: runtime.get_or_init(new_background_runtime).clone(), + fee_estimator_config: None, }) } } @@ -228,6 +233,12 @@ impl SharedBuilder { self } + /// Sets the configuration for the fee estimator. + pub fn fee_estimator_config(mut self, config: FeeEstimatorConfig) -> Self { + self.fee_estimator_config = Some(config); + self + } + /// specifies the async_handle for the shared pub fn async_handle(mut self, async_handle: Handle) -> Self { self.async_handle = async_handle; @@ -328,6 +339,7 @@ impl SharedBuilder { block_assembler_config, notify_config, async_handle, + fee_estimator_config, } = self; let tx_pool_config = tx_pool_config.unwrap_or_default(); @@ -354,6 +366,17 @@ impl SharedBuilder { let (sender, receiver) = ckb_channel::unbounded(); + let fee_estimator_algo = fee_estimator_config + .map(|config| config.algorithm) + .unwrap_or(None); + let fee_estimator = match fee_estimator_algo { + Some(FeeEstimatorAlgo::WeightUnitsFlow) => FeeEstimator::new_weight_units_flow(), + Some(FeeEstimatorAlgo::ConfirmationFraction) => { + FeeEstimator::new_confirmation_fraction() + } + None => FeeEstimator::new_dummy(), + }; + let (mut tx_pool_builder, tx_pool_controller) = TxPoolServiceBuilder::new( tx_pool_config, Arc::clone(&snapshot), @@ -361,9 +384,14 @@ impl SharedBuilder { Arc::clone(&txs_verify_cache), &async_handle, sender, + fee_estimator.clone(), ); - register_tx_pool_callback(&mut tx_pool_builder, notify_controller.clone()); + register_tx_pool_callback( + &mut tx_pool_builder, + notify_controller.clone(), + fee_estimator, + ); let ibd_finished = Arc::new(AtomicBool::new(false)); let shared = Shared::new( @@ -387,7 +415,11 @@ impl SharedBuilder { } } -fn register_tx_pool_callback(tx_pool_builder: &mut TxPoolServiceBuilder, notify: NotifyController) { +fn register_tx_pool_callback( + tx_pool_builder: &mut TxPoolServiceBuilder, + notify: NotifyController, + fee_estimator: FeeEstimator, +) { let notify_pending = notify.clone(); let tx_relay_sender = tx_pool_builder.tx_relay_sender(); @@ -398,10 +430,15 @@ fn register_tx_pool_callback(tx_pool_builder: &mut TxPoolServiceBuilder, notify: fee: entry.fee, timestamp: entry.timestamp, }; + + let fee_estimator_clone = fee_estimator.clone(); tx_pool_builder.register_pending(Box::new(move |entry: &TxEntry| { // notify let notify_tx_entry = create_notify_entry(entry); notify_pending.notify_new_transaction(notify_tx_entry); + let tx_hash = entry.transaction().hash(); + let entry_info = entry.to_info(); + fee_estimator_clone.accept_tx(tx_hash, entry_info); })); let notify_proposed = notify.clone(); @@ -428,7 +465,9 @@ fn register_tx_pool_callback(tx_pool_builder: &mut TxPoolServiceBuilder, notify: } if reject.is_allowed_relay() { - if let Err(e) = tx_relay_sender.send(TxVerificationResult::Reject { tx_hash }) { + if let Err(e) = tx_relay_sender.send(TxVerificationResult::Reject { + tx_hash: tx_hash.clone(), + }) { error!("tx-pool tx_relay_sender internal error {}", e); } } @@ -436,6 +475,9 @@ fn register_tx_pool_callback(tx_pool_builder: &mut TxPoolServiceBuilder, notify: // notify let notify_tx_entry = create_notify_entry(entry); notify_reject.notify_reject_transaction(notify_tx_entry, reject); + + // fee estimator + fee_estimator.reject_tx(&tx_hash); }, )); } diff --git a/spec/src/consensus.rs b/spec/src/consensus.rs index 2d8a16c481..3d312a9a8b 100644 --- a/spec/src/consensus.rs +++ b/spec/src/consensus.rs @@ -45,7 +45,8 @@ pub(crate) const DEFAULT_SECONDARY_EPOCH_REWARD: Capacity = Capacity::shannons(6 // 4.2 billion per year pub(crate) const INITIAL_PRIMARY_EPOCH_REWARD: Capacity = Capacity::shannons(1_917_808_21917808); const MAX_UNCLE_NUM: usize = 2; -pub(crate) const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10); +/// Default transaction proposal window. +pub const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10); // Cellbase outputs are "locked" and require 4 epoch confirmations (approximately 16 hours) before // they mature sufficiently to be spendable, // This is to reduce the risk of later txs being reversed if a chain reorganization occurs. @@ -138,17 +139,17 @@ pub const TYPE_ID_CODE_HASH: H256 = h256!("0x545950455f4944"); /// impl ProposalWindow { /// The w_close parameter - pub fn closest(&self) -> BlockNumber { + pub const fn closest(&self) -> BlockNumber { self.0 } /// The w_far parameter - pub fn farthest(&self) -> BlockNumber { + pub const fn farthest(&self) -> BlockNumber { self.1 } /// The proposal window length - pub fn length(&self) -> BlockNumber { + pub const fn length(&self) -> BlockNumber { self.1 - self.0 + 1 } } diff --git a/tx-pool/Cargo.toml b/tx-pool/Cargo.toml index 7ced816523..308fe4a770 100644 --- a/tx-pool/Cargo.toml +++ b/tx-pool/Cargo.toml @@ -42,6 +42,7 @@ multi_index_map = "0.6.0" slab = "0.4" rustc-hash = "1.1" tokio-util = "0.7.8" +ckb-fee-estimator = { path = "../util/fee-estimator", version = "= 0.117.0-pre" } [dev-dependencies] tempfile.workspace = true diff --git a/tx-pool/src/process.rs b/tx-pool/src/process.rs index 39627ccf9a..3436409fa7 100644 --- a/tx-pool/src/process.rs +++ b/tx-pool/src/process.rs @@ -12,7 +12,7 @@ use crate::util::{ }; use ckb_chain_spec::consensus::MAX_BLOCK_PROPOSALS_LIMIT; use ckb_error::{AnyError, InternalErrorKind}; -use ckb_jsonrpc_types::BlockTemplate; +use ckb_jsonrpc_types::{BlockTemplate, RecommendedFeeRates}; use ckb_logger::Level::Trace; use ckb_logger::{debug, error, info, log_enabled_target, trace_target}; use ckb_network::PeerIndex; @@ -924,6 +924,7 @@ impl TxPoolService { } for blk in attached_blocks { + self.fee_estimator.commit_block(&blk); attached.extend(blk.transactions().into_iter().skip(1)); } let retain: Vec = detached.difference(&attached).cloned().collect(); @@ -1089,6 +1090,18 @@ impl TxPoolService { } } + pub(crate) async fn update_ibd_state(&self, in_ibd: bool) { + self.fee_estimator.update_ibd_state(in_ibd); + } + + pub(crate) async fn get_fee_estimates(&self) -> Result, AnyError> { + let all_entry_info = self.tx_pool.read().await.get_all_entry_info(); + self.fee_estimator + .get_fee_estimates(all_entry_info) + .map(|inner| inner.map(Into::into)) + .map_err(Into::into) + } + // # Notice // // This method assumes that the inputs transactions are sorted. diff --git a/tx-pool/src/service.rs b/tx-pool/src/service.rs index 64f17f4aa9..28510f55c7 100644 --- a/tx-pool/src/service.rs +++ b/tx-pool/src/service.rs @@ -13,7 +13,8 @@ use ckb_async_runtime::Handle; use ckb_chain_spec::consensus::Consensus; use ckb_channel::oneshot; use ckb_error::AnyError; -use ckb_jsonrpc_types::BlockTemplate; +use ckb_fee_estimator::FeeEstimator; +use ckb_jsonrpc_types::{BlockTemplate, RecommendedFeeRates}; use ckb_logger::{error, info}; use ckb_network::{NetworkController, PeerIndex}; use ckb_snapshot::Snapshot; @@ -87,6 +88,8 @@ pub(crate) type ChainReorgArgs = ( Arc, ); +pub(crate) type FeeEstimatesResult = Result, AnyError>; + pub(crate) enum Message { BlockTemplate(Request), SubmitLocalTx(Request), @@ -107,6 +110,9 @@ pub(crate) enum Message { SavePool(Request<(), ()>), GetPoolTxDetails(Request), + UpdateIBDState(Request), + GetFeeEstimates(Request<(), FeeEstimatesResult>), + // test #[cfg(feature = "internal")] PlugEntry(Request<(Vec, PlugTarget), ()>), @@ -323,6 +329,16 @@ impl TxPoolController { send_message!(self, SavePool, ()) } + /// Updates IBD state. + pub fn update_ibd_state(&self, in_ibd: bool) -> Result<(), AnyError> { + send_message!(self, UpdateIBDState, in_ibd) + } + + /// Gets fee estimates. + pub fn get_fee_estimates(&self) -> Result { + send_message!(self, GetFeeEstimates, ()) + } + /// Sends suspend chunk process cmd pub fn suspend_chunk_process(&self) -> Result<(), AnyError> { self.chunk_tx @@ -394,6 +410,7 @@ pub struct TxPoolServiceBuilder { mpsc::Sender, mpsc::Receiver, ), + pub(crate) fee_estimator: FeeEstimator, } impl TxPoolServiceBuilder { @@ -405,6 +422,7 @@ impl TxPoolServiceBuilder { txs_verify_cache: Arc>, handle: &Handle, tx_relay_sender: ckb_channel::Sender, + fee_estimator: FeeEstimator, ) -> (TxPoolServiceBuilder, TxPoolController) { let (sender, receiver) = mpsc::channel(DEFAULT_CHANNEL_SIZE); let block_assembler_channel = mpsc::channel(BLOCK_ASSEMBLER_CHANNEL_SIZE); @@ -440,6 +458,7 @@ impl TxPoolServiceBuilder { chunk, started, block_assembler_channel, + fee_estimator, }; (builder, controller) @@ -495,6 +514,7 @@ impl TxPoolServiceBuilder { consensus, delay: Arc::new(RwLock::new(LinkedHashMap::new())), after_delay: Arc::new(AtomicBool::new(after_delay_window)), + fee_estimator: self.fee_estimator, }; let signal_receiver = self.signal_receiver.clone(); @@ -650,6 +670,7 @@ pub(crate) struct TxPoolService { pub(crate) block_assembler_sender: mpsc::Sender, pub(crate) delay: Arc>>, pub(crate) after_delay: Arc, + pub(crate) fee_estimator: FeeEstimator, } /// tx verification result @@ -903,6 +924,21 @@ async fn process(mut service: TxPoolService, message: Message) { error!("Responder sending save_pool failed {:?}", e) }; } + Message::UpdateIBDState(Request { + responder, + arguments: in_ibd, + }) => { + service.update_ibd_state(in_ibd).await; + if let Err(e) = responder.send(()) { + error!("Responder sending update_ibd_state failed {:?}", e) + }; + } + Message::GetFeeEstimates(Request { responder, .. }) => { + let fee_estimates_result = service.get_fee_estimates().await; + if let Err(e) = responder.send(fee_estimates_result) { + error!("Responder sending fee_estimates_result failed {:?}", e) + }; + } #[cfg(feature = "internal")] Message::PlugEntry(Request { responder, diff --git a/util/app-config/src/app_config.rs b/util/app-config/src/app_config.rs index 963bd7ef18..d10819c876 100644 --- a/util/app-config/src/app_config.rs +++ b/util/app-config/src/app_config.rs @@ -92,6 +92,9 @@ pub struct CKBAppConfig { /// Indexer config options. #[serde(default)] pub indexer: IndexerConfig, + /// Fee estimator config options. + #[serde(default)] + pub fee_estimator: FeeEstimatorConfig, } /// The miner config file for `ckb miner`. Usually it is the `ckb-miner.toml` in the CKB root diff --git a/util/app-config/src/configs/fee_estimator.rs b/util/app-config/src/configs/fee_estimator.rs new file mode 100644 index 0000000000..5ca05d46d8 --- /dev/null +++ b/util/app-config/src/configs/fee_estimator.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Serialize}; + +/// Fee estimator config options. +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Config { + /// The algorithm for fee estimator. + pub algorithm: Option, +} + +/// Specifies the fee estimates algorithm. +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq)] +pub enum Algorithm { + /// Confirmation Fraction Fee Estimator + ConfirmationFraction, + /// Weight-Units Flow Fee Estimator + WeightUnitsFlow, +} diff --git a/util/app-config/src/configs/mod.rs b/util/app-config/src/configs/mod.rs index 95b0c79508..5a20d1ea16 100644 --- a/util/app-config/src/configs/mod.rs +++ b/util/app-config/src/configs/mod.rs @@ -1,4 +1,5 @@ mod db; +mod fee_estimator; mod indexer; mod memory_tracker; mod miner; @@ -11,6 +12,7 @@ mod store; mod tx_pool; pub use db::Config as DBConfig; +pub use fee_estimator::{Algorithm as FeeEstimatorAlgo, Config as FeeEstimatorConfig}; pub use indexer::{IndexerConfig, IndexerSyncConfig}; pub use memory_tracker::Config as MemoryTrackerConfig; pub use miner::{ diff --git a/util/app-config/src/legacy/mod.rs b/util/app-config/src/legacy/mod.rs index 79d8c29b27..77084810d3 100644 --- a/util/app-config/src/legacy/mod.rs +++ b/util/app-config/src/legacy/mod.rs @@ -59,6 +59,8 @@ pub(crate) struct CKBAppConfig { notify: crate::NotifyConfig, #[serde(default)] indexer_v2: crate::IndexerConfig, + #[serde(default)] + fee_estimator: crate::FeeEstimatorConfig, } #[derive(Clone, Debug, Deserialize)] @@ -106,6 +108,7 @@ impl From for crate::CKBAppConfig { alert_signature, notify, indexer_v2, + fee_estimator, } = input; #[cfg(not(feature = "with_sentry"))] let _ = sentry; @@ -131,6 +134,7 @@ impl From for crate::CKBAppConfig { alert_signature, notify, indexer: indexer_v2, + fee_estimator, } } } diff --git a/util/fee-estimator/Cargo.toml b/util/fee-estimator/Cargo.toml new file mode 100644 index 0000000000..4cdc57c484 --- /dev/null +++ b/util/fee-estimator/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ckb-fee-estimator" +version = "0.117.0-pre" +license = "MIT" +authors = ["Nervos Core Dev "] +edition = "2021" +description = "The ckb fee estimator" +homepage = "https://github.com/nervosnetwork/ckb" +repository = "https://github.com/nervosnetwork/ckb" + +[dependencies] +ckb-logger = { path = "../logger", version = "= 0.117.0-pre" } +ckb-types = { path = "../types", version = "= 0.117.0-pre" } +ckb-util = { path = "../../util", version = "= 0.117.0-pre" } +ckb-chain-spec = { path = "../../spec", version = "= 0.117.0-pre" } +thiserror = "1.0" diff --git a/util/fee-estimator/src/constants.rs b/util/fee-estimator/src/constants.rs new file mode 100644 index 0000000000..fcfc934f81 --- /dev/null +++ b/util/fee-estimator/src/constants.rs @@ -0,0 +1,24 @@ +//! The constants for the fee estimator. + +use ckb_chain_spec::consensus::{MAX_BLOCK_INTERVAL, MIN_BLOCK_INTERVAL, TX_PROPOSAL_WINDOW}; +use ckb_types::core::{BlockNumber, FeeRate}; + +/// Average block interval. +pub(crate) const AVG_BLOCK_INTERVAL: u64 = (MAX_BLOCK_INTERVAL + MIN_BLOCK_INTERVAL) / 2; + +/// Max target blocks, about 2 hours. +pub(crate) const MAX_TARGET: BlockNumber = (60 * 2 * 60) / AVG_BLOCK_INTERVAL; +/// Min target blocks, in next block. +pub(crate) const MIN_TARGET: BlockNumber = TX_PROPOSAL_WINDOW.closest() + 1; + +/// Lowest fee rate. +pub(crate) const LOWEST_FEE_RATE: FeeRate = FeeRate::from_u64(1000); + +/// Target blocks for default priority (lowest priority, about 2 hours). +pub(crate) const DEFAULT_TARGET: BlockNumber = MAX_TARGET; +/// Target blocks for low priority (about 1 hour). +pub(crate) const LOW_TARGET: BlockNumber = DEFAULT_TARGET / 2; +/// Target blocks for medium priority (about 10 minutes). +pub(crate) const MEDIUM_TARGET: BlockNumber = LOW_TARGET / 6; +/// Target blocks for high priority. +pub(crate) const HIGH_TARGET: BlockNumber = MIN_TARGET; diff --git a/util/fee-estimator/src/error.rs b/util/fee-estimator/src/error.rs new file mode 100644 index 0000000000..66702a59ae --- /dev/null +++ b/util/fee-estimator/src/error.rs @@ -0,0 +1,14 @@ +//! The error type for the fee estimator. + +use thiserror::Error; + +/// A list specifying general categories of fee estimator errors. +#[derive(Error, Debug)] +pub enum Error { + /// Not ready for do estimate. + #[error("not ready")] + NotReady, + /// Lack of empirical data. + #[error("lack of empirical data")] + LackData, +} diff --git a/util/fee-estimator/src/estimator/confirmation_fraction.rs b/util/fee-estimator/src/estimator/confirmation_fraction.rs new file mode 100644 index 0000000000..10edbb131f --- /dev/null +++ b/util/fee-estimator/src/estimator/confirmation_fraction.rs @@ -0,0 +1,600 @@ +//! Confirmation Fraction Fee Estimator +//! +//! Copy from https://github.com/nervosnetwork/ckb/tree/v0.39.1/util/fee-estimator +//! Ref: https://github.com/nervosnetwork/ckb/pull/1659 + +use std::{ + cmp, + collections::{BTreeMap, HashMap}, +}; + +use ckb_types::{ + core::{ + tx_pool::{get_transaction_weight, TxEntryInfo}, + BlockNumber, BlockView, FeeRate, RecommendedFeeRates, + }, + packed::Byte32, +}; + +use crate::{constants, Error}; + +const DEFAULT_MIN_CONFIRM_RATE: f64 = 0.9; + +#[derive(Default, Debug, Clone)] +struct BucketStat { + total_fee_rate: FeeRate, + txs_count: f64, + old_unconfirmed_txs: usize, +} + +/// TxConfirmStat is a struct to help to estimate txs fee rate, +/// This struct record txs fee_rate and blocks that txs to be committed. +/// +/// We start from track unconfirmed txs, +/// When tx added to txpool, we increase the count of unconfirmed tx, we do opposite tx removed. +/// When a tx get committed, put it into bucket by tx fee_rate and confirmed blocks, +/// then decrease the count of unconfirmed txs. +/// +/// So we get a group of samples which includes txs count, average fee rate and confirmed blocks, etc. +/// For estimate, we loop through each bucket, calculate the confirmed txs rate, until meet the required_confirm_rate. +#[derive(Clone)] +struct TxConfirmStat { + min_fee_rate: FeeRate, + /// per bucket stat + bucket_stats: Vec, + /// bucket upper bound fee_rate => bucket index + fee_rate_to_bucket: BTreeMap, + /// confirm_blocks => bucket index => confirmed txs count + confirm_blocks_to_confirmed_txs: Vec>, + /// confirm_blocks => bucket index => failed txs count + confirm_blocks_to_failed_txs: Vec>, + /// Track recent N blocks unconfirmed txs + /// tracked block index => bucket index => TxTracker + block_unconfirmed_txs: Vec>, + decay_factor: f64, +} + +#[derive(Clone)] +struct TxRecord { + height: u64, + bucket_index: usize, + fee_rate: FeeRate, +} + +/// Estimator track new block and tx_pool to collect data +/// we track every new tx enter txpool and record the tip height and fee_rate, +/// when tx is packed into a new block or dropped by txpool, +/// we get a sample about how long a tx with X fee_rate can get confirmed or get dropped. +/// +/// In inner, we group samples by predefined fee_rate buckets. +/// To estimator fee_rate for a confirm target(how many blocks that a tx can get committed), +/// we travel through fee_rate buckets, try to find a fee_rate X to let a tx get committed +/// with high probilities within confirm target blocks. +/// +#[derive(Clone)] +pub struct Algorithm { + best_height: u64, + start_height: u64, + /// a data struct to track tx confirm status + tx_confirm_stat: TxConfirmStat, + tracked_txs: HashMap, + + current_tip: BlockNumber, + is_ready: bool, +} + +impl BucketStat { + // add a new fee rate to this bucket + fn new_fee_rate_sample(&mut self, fee_rate: FeeRate) { + self.txs_count += 1f64; + let total_fee_rate = self + .total_fee_rate + .as_u64() + .saturating_add(fee_rate.as_u64()); + self.total_fee_rate = FeeRate::from_u64(total_fee_rate); + } + + // get average fee rate from a bucket + fn avg_fee_rate(&self) -> Option { + if self.txs_count > 0f64 { + Some(FeeRate::from_u64( + ((self.total_fee_rate.as_u64() as f64) / self.txs_count) as u64, + )) + } else { + None + } + } +} + +impl Default for TxConfirmStat { + fn default() -> Self { + let max_confirm_blocks = constants::MAX_TARGET as usize; + let min_bucket_feerate = f64::from(constants::LOWEST_FEE_RATE.as_u64() as u32); + let max_bucket_feerate = min_bucket_feerate * 1000.0; + let fee_spacing = min_bucket_feerate; + // half life each 100 blocks, math.exp(math.log(0.5) / 100) + let decay_factor: f64 = (0.5f64.ln() / 100.0).exp(); + + let mut buckets = Vec::new(); + let mut bucket_fee_boundary = min_bucket_feerate; + // initialize fee_rate buckets + while bucket_fee_boundary <= max_bucket_feerate { + buckets.push(FeeRate::from_u64(bucket_fee_boundary as u64)); + bucket_fee_boundary *= fee_spacing; + } + Self::new(buckets, max_confirm_blocks, decay_factor) + } +} + +impl TxConfirmStat { + fn new(buckets: Vec, max_confirm_blocks: usize, decay_factor: f64) -> Self { + // max_confirm_blocsk: The number of blocks that the esitmator will trace the statistics. + let min_fee_rate = buckets[0]; + let bucket_stats = vec![BucketStat::default(); buckets.len()]; + let confirm_blocks_to_confirmed_txs = vec![vec![0f64; buckets.len()]; max_confirm_blocks]; + let confirm_blocks_to_failed_txs = vec![vec![0f64; buckets.len()]; max_confirm_blocks]; + let block_unconfirmed_txs = vec![vec![0; buckets.len()]; max_confirm_blocks]; + let fee_rate_to_bucket = buckets + .into_iter() + .enumerate() + .map(|(i, fee_rate)| (fee_rate, i)) + .collect(); + TxConfirmStat { + min_fee_rate, + bucket_stats, + fee_rate_to_bucket, + block_unconfirmed_txs, + confirm_blocks_to_confirmed_txs, + confirm_blocks_to_failed_txs, + decay_factor, + } + } + + /// Return upper bound fee_rate bucket + /// assume we have three buckets with fee_rate [1.0, 2.0, 3.0], we return index 1 for fee_rate 1.5 + fn bucket_index_by_fee_rate(&self, fee_rate: FeeRate) -> Option { + self.fee_rate_to_bucket + .range(fee_rate..) + .next() + .map(|(_fee_rate, index)| *index) + } + + fn max_confirms(&self) -> usize { + self.confirm_blocks_to_confirmed_txs.len() + } + + // add confirmed sample + fn add_confirmed_tx(&mut self, blocks_to_confirm: usize, fee_rate: FeeRate) { + if blocks_to_confirm < 1 { + return; + } + let bucket_index = match self.bucket_index_by_fee_rate(fee_rate) { + Some(index) => index, + None => return, + }; + // increase txs_count in buckets + for i in (blocks_to_confirm - 1)..self.max_confirms() { + self.confirm_blocks_to_confirmed_txs[i][bucket_index] += 1f64; + } + let stat = &mut self.bucket_stats[bucket_index]; + stat.new_fee_rate_sample(fee_rate); + } + + // track an unconfirmed tx + // entry_height - tip number when tx enter txpool + fn add_unconfirmed_tx(&mut self, entry_height: u64, fee_rate: FeeRate) -> Option { + let bucket_index = match self.bucket_index_by_fee_rate(fee_rate) { + Some(index) => index, + None => return None, + }; + let block_index = (entry_height % (self.block_unconfirmed_txs.len() as u64)) as usize; + self.block_unconfirmed_txs[block_index][bucket_index] += 1; + Some(bucket_index) + } + + fn remove_unconfirmed_tx( + &mut self, + entry_height: u64, + tip_height: u64, + bucket_index: usize, + count_failure: bool, + ) { + let tx_age = tip_height.saturating_sub(entry_height) as usize; + if tx_age < 1 { + return; + } + if tx_age >= self.block_unconfirmed_txs.len() { + self.bucket_stats[bucket_index].old_unconfirmed_txs -= 1; + } else { + let block_index = (entry_height % self.block_unconfirmed_txs.len() as u64) as usize; + self.block_unconfirmed_txs[block_index][bucket_index] -= 1; + } + if count_failure { + self.confirm_blocks_to_failed_txs[tx_age - 1][bucket_index] += 1f64; + } + } + + fn move_track_window(&mut self, height: u64) { + let block_index = (height % (self.block_unconfirmed_txs.len() as u64)) as usize; + for bucket_index in 0..self.bucket_stats.len() { + // mark unconfirmed txs as old_unconfirmed_txs + self.bucket_stats[bucket_index].old_unconfirmed_txs += + self.block_unconfirmed_txs[block_index][bucket_index]; + self.block_unconfirmed_txs[block_index][bucket_index] = 0; + } + } + + /// apply decay factor on stats, smoothly reduce the effects of old samples. + fn decay(&mut self) { + let decay_factor = self.decay_factor; + for (bucket_index, bucket) in self.bucket_stats.iter_mut().enumerate() { + self.confirm_blocks_to_confirmed_txs + .iter_mut() + .for_each(|buckets| { + buckets[bucket_index] *= decay_factor; + }); + + self.confirm_blocks_to_failed_txs + .iter_mut() + .for_each(|buckets| { + buckets[bucket_index] *= decay_factor; + }); + bucket.total_fee_rate = + FeeRate::from_u64((bucket.total_fee_rate.as_u64() as f64 * decay_factor) as u64); + bucket.txs_count *= decay_factor; + // TODO do we need decay the old unconfirmed? + } + } + + /// The naive estimate implementation + /// 1. find best range of buckets satisfy the given condition + /// 2. get median fee_rate from best range bucekts + fn estimate_median( + &self, + confirm_blocks: usize, + required_samples: usize, + required_confirm_rate: f64, + ) -> Option { + // A tx need 1 block to propose, then 2 block to get confirmed + // so at least confirm blocks is 3 blocks. + if confirm_blocks < 3 || required_samples == 0 { + ckb_logger::debug!( + "confirm_blocks(={}) < 3 || required_samples(={}) == 0", + confirm_blocks, + required_samples + ); + return None; + } + let mut confirmed_txs = 0f64; + let mut txs_count = 0f64; + let mut failure_count = 0f64; + let mut extra_count = 0; + let mut best_bucket_start = 0; + let mut best_bucket_end = 0; + let mut start_bucket_index = 0; + let mut find_best = false; + // try find enough sample data from buckets + for (bucket_index, stat) in self.bucket_stats.iter().enumerate() { + confirmed_txs += self.confirm_blocks_to_confirmed_txs[confirm_blocks - 1][bucket_index]; + failure_count += self.confirm_blocks_to_failed_txs[confirm_blocks - 1][bucket_index]; + extra_count += &self.block_unconfirmed_txs[confirm_blocks - 1][bucket_index]; + txs_count += stat.txs_count; + // we have enough data + while txs_count as usize >= required_samples { + let confirm_rate = confirmed_txs / (txs_count + failure_count + extra_count as f64); + // satisfied required_confirm_rate, find the best buckets range + if confirm_rate >= required_confirm_rate { + best_bucket_start = start_bucket_index; + best_bucket_end = bucket_index; + find_best = true; + break; + } else { + // remove sample data of the first bucket in the range, then retry + let stat = &self.bucket_stats[start_bucket_index]; + confirmed_txs -= self.confirm_blocks_to_confirmed_txs[confirm_blocks - 1] + [start_bucket_index]; + failure_count -= + self.confirm_blocks_to_failed_txs[confirm_blocks - 1][start_bucket_index]; + extra_count -= + &self.block_unconfirmed_txs[confirm_blocks - 1][start_bucket_index]; + txs_count -= stat.txs_count; + start_bucket_index += 1; + continue; + } + } + + // end loop if we found the best buckets + if find_best { + break; + } + } + + if find_best { + let best_range_txs_count: f64 = self.bucket_stats[best_bucket_start..=best_bucket_end] + .iter() + .map(|b| b.txs_count) + .sum(); + + // find median bucket + if best_range_txs_count != 0f64 { + let mut half_count = best_range_txs_count / 2f64; + for bucket in &self.bucket_stats[best_bucket_start..=best_bucket_end] { + // find the median bucket + if bucket.txs_count >= half_count { + return bucket + .avg_fee_rate() + .map(|fee_rate| cmp::max(fee_rate, self.min_fee_rate)); + } else { + half_count -= bucket.txs_count; + } + } + } + ckb_logger::trace!("no best fee rate"); + } else { + ckb_logger::trace!("no best bucket"); + } + + None + } +} + +impl Default for Algorithm { + fn default() -> Self { + Self::new() + } +} + +impl Algorithm { + /// Creates a new estimator. + pub fn new() -> Self { + Self { + best_height: 0, + start_height: 0, + tx_confirm_stat: Default::default(), + tracked_txs: Default::default(), + current_tip: 0, + is_ready: false, + } + } + + fn process_block_tx(&mut self, height: u64, tx_hash: &Byte32) -> bool { + if let Some(tx) = self.drop_tx_inner(tx_hash, false) { + let blocks_to_confirm = height.saturating_sub(tx.height) as usize; + self.tx_confirm_stat + .add_confirmed_tx(blocks_to_confirm, tx.fee_rate); + true + } else { + // tx is not tracked + false + } + } + + /// process new block + /// record confirm blocks for txs which we tracked before. + fn process_block(&mut self, height: u64, txs: impl Iterator) { + // For simpfy, we assume chain reorg will not effect tx fee. + if height <= self.best_height { + return; + } + self.best_height = height; + // update tx confirm stat + self.tx_confirm_stat.move_track_window(height); + self.tx_confirm_stat.decay(); + let processed_txs = txs.filter(|tx| self.process_block_tx(height, tx)).count(); + if self.start_height == 0 && processed_txs > 0 { + // start record + self.start_height = self.best_height; + ckb_logger::debug!("start recording at {}", self.start_height); + } + } + + /// track a tx that entered txpool + fn track_tx(&mut self, tx_hash: Byte32, fee_rate: FeeRate, height: u64) { + if self.tracked_txs.contains_key(&tx_hash) { + // already in track + return; + } + if height != self.best_height { + // ignore wrong height txs + return; + } + if let Some(bucket_index) = self.tx_confirm_stat.add_unconfirmed_tx(height, fee_rate) { + self.tracked_txs.insert( + tx_hash, + TxRecord { + height, + bucket_index, + fee_rate, + }, + ); + } + } + + fn drop_tx_inner(&mut self, tx_hash: &Byte32, count_failure: bool) -> Option { + self.tracked_txs.remove(tx_hash).map(|tx_record| { + self.tx_confirm_stat.remove_unconfirmed_tx( + tx_record.height, + self.best_height, + tx_record.bucket_index, + count_failure, + ); + tx_record + }) + } + + /// tx removed from txpool + fn drop_tx(&mut self, tx_hash: &Byte32) -> bool { + self.drop_tx_inner(tx_hash, true).is_some() + } + + /// estimate a fee rate for confirm target + fn estimate(&self, expect_confirm_blocks: BlockNumber) -> Option { + let min_estimate_samples = constants::MIN_TARGET as usize * 2; + self.tx_confirm_stat.estimate_median( + expect_confirm_blocks as usize, + min_estimate_samples, + DEFAULT_MIN_CONFIRM_RATE, + ) + } +} + +impl Algorithm { + pub fn update_ibd_state(&mut self, in_ibd: bool) { + if self.is_ready { + if in_ibd { + self.clear(); + self.is_ready = false; + } + } else if !in_ibd { + self.clear(); + self.is_ready = true; + } + } + + fn clear(&mut self) { + self.best_height = 0; + self.start_height = 0; + self.tx_confirm_stat = Default::default(); + self.tracked_txs.clear(); + self.current_tip = 0; + } + + pub fn commit_block(&mut self, block: &BlockView) { + let tip_number = block.number(); + self.current_tip = tip_number; + self.process_block(tip_number, block.tx_hashes().iter().map(ToOwned::to_owned)); + } + + pub fn accept_tx(&mut self, tx_hash: Byte32, info: TxEntryInfo) { + let weight = get_transaction_weight(info.size as usize, info.cycles); + let fee_rate = FeeRate::calculate(info.fee, weight); + self.track_tx(tx_hash, fee_rate, self.current_tip) + } + + pub fn reject_tx(&mut self, tx_hash: &Byte32) { + let _ = self.drop_tx(tx_hash); + } + + pub fn get_fee_estimates(&self) -> Result, Error> { + if !self.is_ready { + return Err(Error::NotReady); + } + + let high = if let Some(fee_rate) = self.estimate(constants::HIGH_TARGET) { + fee_rate + } else { + return Ok(None); + }; + + let medium = if let Some(fee_rate) = self.estimate(constants::MEDIUM_TARGET) { + fee_rate + } else { + let rates = RecommendedFeeRates { + default: high, + low: high, + medium: high, + high, + }; + return Ok(Some(rates)); + }; + + let low = if let Some(fee_rate) = self.estimate(constants::LOW_TARGET) { + fee_rate + } else { + let rates = RecommendedFeeRates { + default: medium, + low: medium, + medium, + high, + }; + return Ok(Some(rates)); + }; + + let default = if let Some(fee_rate) = self.estimate(constants::DEFAULT_TARGET) { + fee_rate + } else { + let rates = RecommendedFeeRates { + default: low, + low, + medium, + high, + }; + return Ok(Some(rates)); + }; + + let rates = RecommendedFeeRates { + default, + low, + medium, + high, + }; + Ok(Some(rates)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_estimate_median() { + let mut bucket_fee_rate = 1000; + let bucket_end_fee_rate = 5000; + let rate = 1.1f64; + // decay = exp(ln(0.5) / 100), so decay.pow(100) =~ 0.5 + let decay = 0.993f64; + let max_confirm_blocks = 1000; + // prepare fee rate buckets + let mut buckets = vec![]; + while bucket_fee_rate < bucket_end_fee_rate { + buckets.push(FeeRate::from_u64(bucket_fee_rate)); + bucket_fee_rate = (rate * bucket_fee_rate as f64) as u64; + } + let mut stat = TxConfirmStat::new(buckets, max_confirm_blocks, decay); + // txs data + let fee_rate_and_confirms = vec![ + (2500, 5), + (3000, 5), + (3500, 5), + (1500, 10), + (2000, 10), + (2100, 10), + (2200, 10), + (1200, 15), + (1000, 15), + ]; + for (fee_rate, blocks_to_confirm) in fee_rate_and_confirms { + stat.add_confirmed_tx(blocks_to_confirm, FeeRate::from_u64(fee_rate)); + } + // test basic median fee rate + assert_eq!( + stat.estimate_median(5, 3, 1f64), + Some(FeeRate::from_u64(3000)) + ); + // test different required samples + assert_eq!( + stat.estimate_median(10, 1, 1f64), + Some(FeeRate::from_u64(1500)) + ); + assert_eq!( + stat.estimate_median(10, 3, 1f64), + Some(FeeRate::from_u64(2050)) + ); + assert_eq!( + stat.estimate_median(10, 4, 1f64), + Some(FeeRate::from_u64(2050)) + ); + assert_eq!( + stat.estimate_median(15, 2, 1f64), + Some(FeeRate::from_u64(1000)) + ); + assert_eq!( + stat.estimate_median(15, 3, 1f64), + Some(FeeRate::from_u64(1200)) + ); + // test return zero if confirm_blocks or required_samples is zero + assert_eq!(stat.estimate_median(0, 4, 1f64), None); + assert_eq!(stat.estimate_median(15, 0, 1f64), None); + assert_eq!(stat.estimate_median(0, 3, 1f64), None); + } +} diff --git a/util/fee-estimator/src/estimator/mod.rs b/util/fee-estimator/src/estimator/mod.rs new file mode 100644 index 0000000000..1d71bfeecf --- /dev/null +++ b/util/fee-estimator/src/estimator/mod.rs @@ -0,0 +1,92 @@ +use std::sync::Arc; + +use ckb_types::{ + core::{ + tx_pool::{TxEntryInfo, TxPoolEntryInfo}, + BlockView, RecommendedFeeRates, + }, + packed::Byte32, +}; +use ckb_util::RwLock; + +use crate::Error; + +mod confirmation_fraction; +mod weight_units_flow; + +/// The fee estimator with a chosen algorithm. +#[derive(Clone)] +pub enum FeeEstimator { + /// Dummy fee estimate algorithm; just do nothing. + Dummy, + /// Confirmation fraction fee estimator algorithm. + ConfirmationFraction(Arc>), + /// Weight-Units flow fee estimator algorithm. + WeightUnitsFlow(Arc>), +} + +impl FeeEstimator { + /// Creates a new dummy fee estimator. + pub fn new_dummy() -> Self { + FeeEstimator::Dummy + } + + /// Creates a new confirmation fraction fee estimator. + pub fn new_confirmation_fraction() -> Self { + let algo = confirmation_fraction::Algorithm::new(); + FeeEstimator::ConfirmationFraction(Arc::new(RwLock::new(algo))) + } + + /// Creates a new weight-units flow fee estimator. + pub fn new_weight_units_flow() -> Self { + let algo = weight_units_flow::Algorithm::new(); + FeeEstimator::WeightUnitsFlow(Arc::new(RwLock::new(algo))) + } + + /// Updates the IBD state. + pub fn update_ibd_state(&self, in_ibd: bool) { + match self { + Self::Dummy => {} + Self::ConfirmationFraction(algo) => algo.write().update_ibd_state(in_ibd), + Self::WeightUnitsFlow(algo) => algo.write().update_ibd_state(in_ibd), + } + } + + /// Commits a block. + pub fn commit_block(&self, block: &BlockView) { + match self { + Self::Dummy => {} + Self::ConfirmationFraction(algo) => algo.write().commit_block(block), + Self::WeightUnitsFlow(algo) => algo.write().commit_block(block), + } + } + + /// Accepts a tx. + pub fn accept_tx(&self, tx_hash: Byte32, info: TxEntryInfo) { + match self { + Self::Dummy => {} + Self::ConfirmationFraction(algo) => algo.write().accept_tx(tx_hash, info), + Self::WeightUnitsFlow(algo) => algo.write().accept_tx(info), + } + } + + /// Rejects a tx. + pub fn reject_tx(&self, tx_hash: &Byte32) { + match self { + Self::Dummy | Self::WeightUnitsFlow(_) => {} + Self::ConfirmationFraction(algo) => algo.write().reject_tx(tx_hash), + } + } + + /// Gets fee estimates. + pub fn get_fee_estimates( + &self, + all_entry_info: TxPoolEntryInfo, + ) -> Result, Error> { + match self { + Self::Dummy => Ok(None), + Self::ConfirmationFraction(algo) => algo.read().get_fee_estimates(), + Self::WeightUnitsFlow(algo) => algo.read().get_fee_estimates(all_entry_info), + } + } +} diff --git a/util/fee-estimator/src/estimator/weight_units_flow.rs b/util/fee-estimator/src/estimator/weight_units_flow.rs new file mode 100644 index 0000000000..16d209bd4b --- /dev/null +++ b/util/fee-estimator/src/estimator/weight_units_flow.rs @@ -0,0 +1,463 @@ +//! Weight-Units Flow Fee Estimator +//! +//! ### Summary +//! +//! This algorithm is migrated from a Bitcoin fee estimates algorithm. +//! +//! The original algorithm could be found in . +//! +//! ### Details +//! +//! #### Inputs +//! +//! The mempool is categorized into "fee buckets". +//! A bucket represents data about all transactions with a fee greater than or +//! equal to some amount (in `weight`). +//! +//! Each bucket contains 2 numeric values: +//! +//! - `current_weight`, represents the transactions currently sitting in the +//! mempool. +//! +//! - `flow`, represents the speed at which new transactions are entering the +//! mempool. +//! +//! It's sampled by observing the flow of transactions during twice the blocks +//! count of each target interval (ex: last 60 blocks for the 30 blocks target +//! interval). +//! +//! For simplicity, transactions are not looked at individually. +//! Focus is on the weight, like a fluid flowing from bucket to bucket. +//! +//! #### Computations +//! +//! Let's simulate what's going to happen during each timespan lasting blocks: +//! +//! - New transactions entering the mempool. +//! +//! While it's impossible to predict sudden changes to the speed at which new +//! weight is added to the mempool, for simplicty's sake we're going to assume +//! the flow we measured remains constant: `added_weight = flow * blocks`. +//! +//! - Transactions leaving the mempool due to mined blocks. Each block removes +//! up to `MAX_BLOCK_BYTES` weight from a bucket. +//! +//! Once we know the minimum expected number of blocks we can compute how that +//! would affect the bucket's weight: +//! `removed_weight = MAX_BLOCK_BYTES * blocks`. +//! +//! - Finally we can compute the expected final weight of the bucket: +//! `final_weight = current_weight + added_weight - removed_weight`. +//! +//! The cheapest bucket whose `final_weight` is less than or equal to 0 is going +//! to be the one selected as the estimate. + +use std::collections::HashMap; + +use ckb_chain_spec::consensus::MAX_BLOCK_BYTES; +use ckb_types::core::{ + tx_pool::{get_transaction_weight, TxEntryInfo, TxPoolEntryInfo}, + BlockNumber, BlockView, FeeRate, RecommendedFeeRates, +}; + +use crate::{constants, Error}; + +const FEE_RATE_UNIT: u64 = 1000; + +#[derive(Clone)] +pub struct Algorithm { + boot_tip: BlockNumber, + current_tip: BlockNumber, + txs: HashMap>, + + is_ready: bool, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +struct TxStatus { + weight: u64, + fee_rate: FeeRate, +} + +impl PartialOrd for TxStatus { + fn partial_cmp(&self, other: &TxStatus) -> Option<::std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for TxStatus { + fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { + self.fee_rate + .cmp(&other.fee_rate) + .then_with(|| other.weight.cmp(&self.weight)) + } +} + +impl TxStatus { + fn new_from_entry_info(info: TxEntryInfo) -> Self { + let weight = get_transaction_weight(info.size as usize, info.cycles); + let fee_rate = FeeRate::calculate(info.fee, weight); + Self { weight, fee_rate } + } +} + +impl Default for Algorithm { + fn default() -> Self { + Self::new() + } +} + +impl Algorithm { + pub fn new() -> Self { + Self { + boot_tip: 0, + current_tip: 0, + txs: Default::default(), + is_ready: false, + } + } + + pub fn update_ibd_state(&mut self, in_ibd: bool) { + if self.is_ready { + if in_ibd { + self.clear(); + self.is_ready = false; + } + } else if !in_ibd { + self.clear(); + self.is_ready = true; + } + } + + fn clear(&mut self) { + self.boot_tip = 0; + self.current_tip = 0; + self.txs.clear(); + } + + pub fn commit_block(&mut self, block: &BlockView) { + let tip_number = block.number(); + if self.boot_tip == 0 { + self.boot_tip = tip_number; + } + self.current_tip = tip_number; + self.expire(); + } + + fn expire(&mut self) { + let historical_blocks = Self::historical_blocks(constants::MAX_TARGET); + let expired_tip = self.current_tip.saturating_sub(historical_blocks); + self.txs.retain(|&num, _| num >= expired_tip); + } + + pub fn accept_tx(&mut self, info: TxEntryInfo) { + if self.current_tip == 0 { + return; + } + let item = TxStatus::new_from_entry_info(info); + self.txs + .entry(self.current_tip) + .and_modify(|items| items.push(item)) + .or_insert_with(|| vec![item]); + } + + pub fn get_fee_estimates( + &self, + all_entry_info: TxPoolEntryInfo, + ) -> Result, Error> { + if !self.is_ready { + return Err(Error::NotReady); + } + + let sorted_current_txs = { + let mut current_txs: Vec<_> = all_entry_info + .pending + .into_values() + .chain(all_entry_info.proposed.into_values()) + .map(TxStatus::new_from_entry_info) + .collect(); + current_txs.sort_unstable_by(|a, b| b.cmp(a)); + current_txs + }; + + let high = if let Some(fee_rate) = + self.do_estimate(constants::HIGH_TARGET, &sorted_current_txs)? + { + fee_rate + } else { + return Ok(None); + }; + + let medium = if let Ok(Some(fee_rate)) = + self.do_estimate(constants::MEDIUM_TARGET, &sorted_current_txs) + { + fee_rate + } else { + let rates = RecommendedFeeRates { + default: high, + low: high, + medium: high, + high, + }; + return Ok(Some(rates)); + }; + + let low = if let Ok(Some(fee_rate)) = + self.do_estimate(constants::LOW_TARGET, &sorted_current_txs) + { + fee_rate + } else { + let rates = RecommendedFeeRates { + default: medium, + low: medium, + medium, + high, + }; + return Ok(Some(rates)); + }; + + let default = if let Ok(Some(fee_rate)) = + self.do_estimate(constants::DEFAULT_TARGET, &sorted_current_txs) + { + fee_rate + } else { + let rates = RecommendedFeeRates { + default: low, + low, + medium, + high, + }; + return Ok(Some(rates)); + }; + + let rates = RecommendedFeeRates { + default, + low, + medium, + high, + }; + Ok(Some(rates)) + } +} + +impl Algorithm { + fn do_estimate( + &self, + target_blocks: BlockNumber, + sorted_current_txs: &[TxStatus], + ) -> Result, Error> { + ckb_logger::debug!( + "boot: {}, current: {}, target: {target_blocks} blocks", + self.boot_tip, + self.current_tip, + ); + let historical_blocks = Self::historical_blocks(target_blocks); + ckb_logger::debug!("required: {historical_blocks} blocks"); + if historical_blocks > self.current_tip.saturating_sub(self.boot_tip) { + return Err(Error::LackData); + } + + let max_fee_rate = if let Some(fee_rate) = sorted_current_txs.first().map(|tx| tx.fee_rate) + { + fee_rate + } else { + return Ok(Some(constants::LOWEST_FEE_RATE)); + }; + + ckb_logger::debug!("max fee rate of current transactions: {max_fee_rate}"); + + let max_bucket_index = Self::max_bucket_index_by_fee_rate(max_fee_rate); + ckb_logger::debug!("current weight buckets size: {}", max_bucket_index + 1); + + // Create weight buckets. + let current_weight_buckets = { + let mut buckets = vec![0u64; max_bucket_index + 1]; + let mut index_curr = max_bucket_index; + for tx in sorted_current_txs { + let index = Self::max_bucket_index_by_fee_rate(tx.fee_rate); + if index < index_curr { + let weight_curr = buckets[index_curr]; + for i in buckets.iter_mut().take(index_curr).skip(index) { + *i = weight_curr; + } + } + buckets[index] += tx.weight; + index_curr = index; + } + buckets + }; + for (index, weight) in current_weight_buckets.iter().enumerate() { + if *weight != 0 { + ckb_logger::trace!(">>> current_weight[{index}]: {weight}"); + } + } + + // Calculate flow speeds for buckets. + let flow_speed_buckets = { + let historical_tip = self.current_tip - historical_blocks; + let sorted_flowed = self.sorted_flowed(historical_tip); + let mut buckets = vec![0u64; max_bucket_index + 1]; + let mut index_curr = max_bucket_index; + for tx in &sorted_flowed { + let index = Self::max_bucket_index_by_fee_rate(tx.fee_rate); + if index > max_bucket_index { + continue; + } + if index < index_curr { + let flowed_curr = buckets[index_curr]; + for i in buckets.iter_mut().take(index_curr).skip(index) { + *i = flowed_curr; + } + } + buckets[index] += tx.weight; + index_curr = index; + } + buckets + .into_iter() + .map(|value| value / historical_blocks) + .collect::>() + }; + for (index, speed) in flow_speed_buckets.iter().enumerate() { + if *speed != 0 { + ckb_logger::trace!(">>> flow_speed[{index}]: {speed}"); + } + } + + for bucket_index in 1..=max_bucket_index { + let current_weight = current_weight_buckets[bucket_index]; + let added_weight = flow_speed_buckets[bucket_index] * target_blocks; + let removed_weight = MAX_BLOCK_BYTES * target_blocks; + let passed = current_weight + added_weight <= removed_weight; + ckb_logger::trace!( + ">>> bucket[{}]: {}; {} + {} - {}", + bucket_index, + passed, + current_weight, + added_weight, + removed_weight + ); + if passed { + let fee_rate = Self::lowest_fee_rate_by_bucket_index(bucket_index); + return Ok(Some(fee_rate)); + } + } + + Ok(None) + } + + fn sorted_flowed(&self, historical_tip: BlockNumber) -> Vec { + let mut statuses: Vec<_> = self + .txs + .iter() + .filter(|(&num, _)| num >= historical_tip) + .flat_map(|(_, statuses)| statuses.to_owned()) + .collect(); + statuses.sort_unstable_by(|a, b| b.cmp(a)); + statuses + } +} + +impl Algorithm { + fn historical_blocks(target_blocks: BlockNumber) -> BlockNumber { + if target_blocks < constants::MIN_TARGET { + constants::MIN_TARGET * 2 + } else { + target_blocks * 2 + } + } + + fn lowest_fee_rate_by_bucket_index(index: usize) -> FeeRate { + let t = FEE_RATE_UNIT; + let value = match index as u64 { + // 0->0 + 0 => 0, + // 1->1000, 2->2000, .., 10->10000 + x if x <= 10 => t * x, + // 11->12000, 12->14000, .., 30->50000 + x if x <= 30 => t * (10 + (x - 10) * 2), + // 31->55000, 32->60000, ..., 60->200000 + x if x <= 60 => t * (10 + 20 * 2 + (x - 30) * 5), + // 61->210000, 62->220000, ..., 90->500000 + x if x <= 90 => t * (10 + 20 * 2 + 30 * 5 + (x - 60) * 10), + // 91->520000, 92->540000, ..., 115 -> 1000000 + x if x <= 115 => t * (10 + 20 * 2 + 30 * 5 + 30 * 10 + (x - 90) * 20), + // 116->1050000, 117->1100000, ..., 135->2000000 + x if x <= 135 => t * (10 + 20 * 2 + 30 * 5 + 30 * 10 + 25 * 20 + (x - 115) * 50), + // 136->2100000, 137->2200000, ... + x => t * (10 + 20 * 2 + 30 * 5 + 30 * 10 + 25 * 20 + 20 * 50 + (x - 135) * 100), + }; + FeeRate::from_u64(value) + } + + fn max_bucket_index_by_fee_rate(fee_rate: FeeRate) -> usize { + let t = FEE_RATE_UNIT; + let index = match fee_rate.as_u64() { + x if x <= 10_000 => x / t, + x if x <= 50_000 => (x + t * 10) / (2 * t), + x if x <= 200_000 => (x + t * 100) / (5 * t), + x if x <= 500_000 => (x + t * 400) / (10 * t), + x if x <= 1_000_000 => (x + t * 1_300) / (20 * t), + x if x <= 2_000_000 => (x + t * 4_750) / (50 * t), + x => (x + t * 11_500) / (100 * t), + }; + index as usize + } +} + +#[cfg(test)] +mod tests { + use super::Algorithm; + use ckb_types::core::FeeRate; + + #[test] + fn test_bucket_index_and_fee_rate_expected() { + let testdata = [ + (0, 0), + (1, 1_000), + (2, 2_000), + (10, 10_000), + (11, 12_000), + (12, 14_000), + (30, 50_000), + (31, 55_000), + (32, 60_000), + (60, 200_000), + (61, 210_000), + (62, 220_000), + (90, 500_000), + (91, 520_000), + (92, 540_000), + (115, 1_000_000), + (116, 1_050_000), + (117, 1_100_000), + (135, 2_000_000), + (136, 2_100_000), + (137, 2_200_000), + ]; + for (bucket_index, fee_rate) in &testdata[..] { + let expected_fee_rate = + Algorithm::lowest_fee_rate_by_bucket_index(*bucket_index).as_u64(); + assert_eq!(expected_fee_rate, *fee_rate); + let actual_bucket_index = + Algorithm::max_bucket_index_by_fee_rate(FeeRate::from_u64(*fee_rate)); + assert_eq!(actual_bucket_index, *bucket_index); + } + } + + #[test] + fn test_bucket_index_and_fee_rate_continuous() { + for fee_rate in 0..3_000_000 { + let bucket_index = Algorithm::max_bucket_index_by_fee_rate(FeeRate::from_u64(fee_rate)); + let fee_rate_le = Algorithm::lowest_fee_rate_by_bucket_index(bucket_index).as_u64(); + let fee_rate_gt = Algorithm::lowest_fee_rate_by_bucket_index(bucket_index + 1).as_u64(); + assert!( + fee_rate_le <= fee_rate && fee_rate < fee_rate_gt, + "Error for bucket[{}]: {} <= {} < {}", + bucket_index, + fee_rate_le, + fee_rate, + fee_rate_gt, + ); + } + } +} diff --git a/util/fee-estimator/src/lib.rs b/util/fee-estimator/src/lib.rs new file mode 100644 index 0000000000..e2c444e35b --- /dev/null +++ b/util/fee-estimator/src/lib.rs @@ -0,0 +1,8 @@ +//! CKB's built-in fee estimator, which shares data with the ckb node through the tx-pool service. + +pub mod constants; +pub(crate) mod error; +pub(crate) mod estimator; + +pub use error::Error; +pub use estimator::FeeEstimator; diff --git a/util/jsonrpc-types/src/fee_estimator.rs b/util/jsonrpc-types/src/fee_estimator.rs new file mode 100644 index 0000000000..d46db1882d --- /dev/null +++ b/util/jsonrpc-types/src/fee_estimator.rs @@ -0,0 +1,43 @@ +use ckb_types::core; +use serde::{Deserialize, Serialize}; + +use schemars::JsonSchema; + +/// Recommended fee rates. +#[derive(Clone, Copy, Default, Debug, Serialize, Deserialize, JsonSchema)] +pub struct RecommendedFeeRates { + /// Default fee rate. + #[serde(rename = "no_priority")] + pub default: u64, + /// Low-priority fee rate. + #[serde(rename = "low_priority")] + pub low: u64, + /// Medium-priority fee rate. + #[serde(rename = "medium_priority")] + pub medium: u64, + /// High-priority fee rate. + #[serde(rename = "high_priority")] + pub high: u64, +} + +impl From for core::RecommendedFeeRates { + fn from(json: RecommendedFeeRates) -> Self { + core::RecommendedFeeRates { + default: core::FeeRate::from_u64(json.default), + low: core::FeeRate::from_u64(json.low), + medium: core::FeeRate::from_u64(json.medium), + high: core::FeeRate::from_u64(json.high), + } + } +} + +impl From for RecommendedFeeRates { + fn from(data: core::RecommendedFeeRates) -> Self { + RecommendedFeeRates { + default: data.default.as_u64(), + low: data.low.as_u64(), + medium: data.medium.as_u64(), + high: data.high.as_u64(), + } + } +} diff --git a/util/jsonrpc-types/src/lib.rs b/util/jsonrpc-types/src/lib.rs index ac70de3ec3..be965af45e 100644 --- a/util/jsonrpc-types/src/lib.rs +++ b/util/jsonrpc-types/src/lib.rs @@ -6,6 +6,7 @@ mod bytes; mod cell; mod debug; mod experiment; +mod fee_estimator; mod fee_rate; mod fixed_bytes; mod indexer; @@ -37,6 +38,7 @@ pub use self::bytes::JsonBytes; pub use self::cell::{CellData, CellInfo, CellWithStatus}; pub use self::debug::{ExtraLoggerConfig, MainLoggerConfig}; pub use self::experiment::{DaoWithdrawingCalculationKind, EstimateCycles}; +pub use self::fee_estimator::RecommendedFeeRates; pub use self::fee_rate::FeeRateDef; pub use self::fixed_bytes::Byte32; pub use self::info::{ChainInfo, DeploymentInfo, DeploymentPos, DeploymentState, DeploymentsInfo}; diff --git a/util/launcher/Cargo.toml b/util/launcher/Cargo.toml index e9d04dc543..fe089d6f69 100644 --- a/util/launcher/Cargo.toml +++ b/util/launcher/Cargo.toml @@ -33,7 +33,6 @@ ckb-tx-pool = { path = "../../tx-pool", version = "= 0.117.0-pre" } ckb-light-client-protocol-server = { path = "../light-client-protocol-server", version = "= 0.117.0-pre" } ckb-block-filter = { path = "../../block-filter", version = "= 0.117.0-pre" } - [features] with_sentry = [ "ckb-sync/with_sentry", "ckb-network/with_sentry", "ckb-app-config/with_sentry" ] portable = ["ckb-shared/portable"] diff --git a/util/launcher/src/lib.rs b/util/launcher/src/lib.rs index 0370339a54..776b0ef4af 100644 --- a/util/launcher/src/lib.rs +++ b/util/launcher/src/lib.rs @@ -203,6 +203,7 @@ impl Launcher { .notify_config(self.args.config.notify.clone()) .store_config(self.args.config.store) .block_assembler_config(block_assembler_config) + .fee_estimator_config(self.args.config.fee_estimator.clone()) .build()?; // internal check migrate_version diff --git a/util/types/src/core/fee_estimator.rs b/util/types/src/core/fee_estimator.rs new file mode 100644 index 0000000000..ef31bbbdcb --- /dev/null +++ b/util/types/src/core/fee_estimator.rs @@ -0,0 +1,14 @@ +use crate::core::FeeRate; + +/// Recommended fee rates. +#[derive(Clone, Copy, Debug)] +pub struct RecommendedFeeRates { + /// Default fee rate. + pub default: FeeRate, + /// Low-priority fee rate. + pub low: FeeRate, + /// Medium-priority fee rate. + pub medium: FeeRate, + /// High-priority fee rate. + pub high: FeeRate, +} diff --git a/util/types/src/core/mod.rs b/util/types/src/core/mod.rs index 5b0cbdb5b3..ace2a15ec6 100644 --- a/util/types/src/core/mod.rs +++ b/util/types/src/core/mod.rs @@ -23,6 +23,7 @@ mod tests; mod advanced_builders; mod blockchain; mod extras; +mod fee_estimator; mod fee_rate; mod reward; mod transaction_meta; @@ -31,6 +32,7 @@ mod views; pub use advanced_builders::{BlockBuilder, HeaderBuilder, TransactionBuilder}; pub use blockchain::DepType; pub use extras::{BlockExt, EpochExt, EpochNumberWithFraction, TransactionInfo}; +pub use fee_estimator::RecommendedFeeRates; pub use fee_rate::FeeRate; pub use reward::{BlockEconomicState, BlockIssuance, BlockReward, MinerReward}; pub use transaction_meta::{TransactionMeta, TransactionMetaBuilder}; From a6c1a8656d51042fb43a71c11c26e0e91b004cf6 Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Fri, 18 Oct 2024 12:16:06 +0800 Subject: [PATCH 3/7] fix(fee-estimator): adjusting parameters based on tests --- util/fee-estimator/src/constants.rs | 17 +++++++++-------- .../src/estimator/confirmation_fraction.rs | 18 +++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/util/fee-estimator/src/constants.rs b/util/fee-estimator/src/constants.rs index 5cf781de80..ca08d9fa0e 100644 --- a/util/fee-estimator/src/constants.rs +++ b/util/fee-estimator/src/constants.rs @@ -3,22 +3,23 @@ use ckb_chain_spec::consensus::{MAX_BLOCK_INTERVAL, MIN_BLOCK_INTERVAL, TX_PROPOSAL_WINDOW}; use ckb_types::core::{BlockNumber, FeeRate}; -/// Average block interval. +/// Average block interval (28). pub(crate) const AVG_BLOCK_INTERVAL: u64 = (MAX_BLOCK_INTERVAL + MIN_BLOCK_INTERVAL) / 2; -/// Max target blocks, about 1 hour. +/// Max target blocks, about 1 hour (128). pub(crate) const MAX_TARGET: BlockNumber = (60 * 60) / AVG_BLOCK_INTERVAL; -/// Min target blocks, in next block. -pub(crate) const MIN_TARGET: BlockNumber = TX_PROPOSAL_WINDOW.closest() + 1; +/// Min target blocks, in next block (5). +/// NOTE After tests, 3 blocks are too strict; so to adjust larger: 5. +pub(crate) const MIN_TARGET: BlockNumber = (TX_PROPOSAL_WINDOW.closest() + 1) + 2; /// Lowest fee rate. pub(crate) const LOWEST_FEE_RATE: FeeRate = FeeRate::from_u64(1000); -/// Target blocks for no priority (lowest priority, about 1 hour). +/// Target blocks for no priority (lowest priority, about 1 hour, 128). pub const DEFAULT_TARGET: BlockNumber = MAX_TARGET; -/// Target blocks for low priority (about 30 minutes). +/// Target blocks for low priority (about 30 minutes, 64). pub const LOW_TARGET: BlockNumber = DEFAULT_TARGET / 2; -/// Target blocks for medium priority (about 10 minutes). +/// Target blocks for medium priority (about 10 minutes, 42). pub const MEDIUM_TARGET: BlockNumber = LOW_TARGET / 3; -/// Target blocks for high priority. +/// Target blocks for high priority (3). pub const HIGH_TARGET: BlockNumber = MIN_TARGET; diff --git a/util/fee-estimator/src/estimator/confirmation_fraction.rs b/util/fee-estimator/src/estimator/confirmation_fraction.rs index 5514078c8a..cc21d07c7d 100644 --- a/util/fee-estimator/src/estimator/confirmation_fraction.rs +++ b/util/fee-estimator/src/estimator/confirmation_fraction.rs @@ -18,7 +18,10 @@ use ckb_types::{ use crate::{constants, Error}; -const DEFAULT_MIN_CONFIRM_RATE: f64 = 0.9; +/// The number of blocks that the esitmator will trace the statistics. +const MAX_CONFIRM_BLOCKS: usize = 1000; +const DEFAULT_MIN_SAMPLES: usize = 20; +const DEFAULT_MIN_CONFIRM_RATE: f64 = 0.85; #[derive(Default, Debug, Clone)] struct BucketStat { @@ -108,10 +111,12 @@ impl BucketStat { impl Default for TxConfirmStat { fn default() -> Self { - let max_confirm_blocks = constants::MAX_TARGET as usize; let min_bucket_feerate = f64::from(constants::LOWEST_FEE_RATE.as_u64() as u32); - let max_bucket_feerate = min_bucket_feerate * 1000.0; - let fee_spacing = min_bucket_feerate; + // MULTIPLE = max_bucket_feerate / min_bucket_feerate + const MULTIPLE: f64 = 10000.0; + let max_bucket_feerate = min_bucket_feerate * MULTIPLE; + // expect 200 buckets + let fee_spacing = (MULTIPLE.ln() / 200.0f64).exp(); // half life each 100 blocks, math.exp(math.log(0.5) / 100) let decay_factor: f64 = (0.5f64.ln() / 100.0).exp(); @@ -122,7 +127,7 @@ impl Default for TxConfirmStat { buckets.push(FeeRate::from_u64(bucket_fee_boundary as u64)); bucket_fee_boundary *= fee_spacing; } - Self::new(buckets, max_confirm_blocks, decay_factor) + Self::new(buckets, MAX_CONFIRM_BLOCKS, decay_factor) } } @@ -430,10 +435,9 @@ impl Algorithm { /// estimate a fee rate for confirm target fn estimate(&self, expect_confirm_blocks: BlockNumber) -> Result { - let min_estimate_samples = constants::MIN_TARGET as usize * 2; self.tx_confirm_stat.estimate_median( expect_confirm_blocks as usize, - min_estimate_samples, + DEFAULT_MIN_SAMPLES, DEFAULT_MIN_CONFIRM_RATE, ) } From 7528cf50d954c82e97f58e71f12947f2032ac321 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:27:01 +0000 Subject: [PATCH 4/7] chore(deps): bump tokio from 1.40.0 to 1.41.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.40.0 to 1.41.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.40.0...tokio-1.41.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd09682ce5..a5afa8ca99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5916,9 +5916,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", From 4cd7dce2b2e5e457131079fa9073cb3d8ab06594 Mon Sep 17 00:00:00 2001 From: driftluo Date: Wed, 23 Oct 2024 15:23:01 +0800 Subject: [PATCH 5/7] chore: upgrade deps --- Cargo.lock | 544 +++++++++++++----- benches/Cargo.toml | 1 - benches/benches/benchmarks/util.rs | 28 +- chain/Cargo.toml | 9 +- chain/src/tests/block_assembler.rs | 15 - ckb-bin/Cargo.toml | 2 +- db-migration/Cargo.toml | 1 - db-migration/src/lib.rs | 4 +- error/Cargo.toml | 4 +- error/src/lib.rs | 2 +- miner/Cargo.toml | 10 +- miner/src/client.rs | 94 +-- network/Cargo.toml | 18 +- network/src/protocols/tests/mod.rs | 3 +- .../src/services/dns_seeding/seed_record.rs | 8 +- rpc/Cargo.toml | 2 +- shared/Cargo.toml | 19 +- shared/src/shared_builder.rs | 8 +- spec/Cargo.toml | 8 +- sync/Cargo.toml | 3 +- sync/src/tests/net_time_checker.rs | 3 +- test/Cargo.toml | 9 +- test/src/global.rs | 21 +- test/src/main.rs | 98 ++-- test/src/rpc.rs | 14 +- tx-pool/Cargo.toml | 18 +- tx-pool/src/block_assembler/mod.rs | 14 +- util/Cargo.toml | 3 +- util/app-config/Cargo.toml | 2 +- util/crypto/Cargo.toml | 1 - util/crypto/src/secp/mod.rs | 8 +- util/jsonrpc-types/Cargo.toml | 1 - util/jsonrpc-types/src/tests/blockchain.rs | 8 +- util/logger-service/Cargo.toml | 3 +- util/logger-service/src/lib.rs | 8 +- util/memory-tracker/Cargo.toml | 1 - util/memory-tracker/src/process.rs | 4 +- util/metrics-service/Cargo.toml | 5 +- util/metrics-service/src/lib.rs | 66 ++- util/metrics/Cargo.toml | 1 - util/metrics/src/lib.rs | 5 +- util/network-alert/Cargo.toml | 9 +- util/network-alert/src/tests/test_notifier.rs | 3 +- util/rich-indexer/Cargo.toml | 1 - util/rich-indexer/src/store.rs | 4 +- util/src/strings.rs | 2 +- util/stop-handler/Cargo.toml | 1 - util/stop-handler/src/stop_register.rs | 16 +- util/test-chain-utils/Cargo.toml | 7 +- util/test-chain-utils/src/chain.rs | 31 +- util/types/Cargo.toml | 3 +- util/types/src/core/cell.rs | 4 +- util/types/src/global.rs | 4 +- verification/Cargo.toml | 8 +- 54 files changed, 729 insertions(+), 440 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd09682ce5..437005b03e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,13 +197,19 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "attohttpc" version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247" dependencies = [ - "http", + "http 0.2.12", "log", "url", "wildmatch", @@ -227,9 +233,9 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.31", "itoa", "matchit", "memchr", @@ -242,7 +248,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper", + "sync_wrapper 0.1.2", "tokio", "tokio-tungstenite", "tower", @@ -259,8 +265,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "mime", "rustversion", "tower-layer", @@ -387,12 +393,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bs58" version = "0.5.1" @@ -435,13 +435,12 @@ dependencies = [ [[package]] name = "cacache" -version = "12.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142316461ed3a3dfcba10417317472da5bfd0461e4d276bf7c07b330766d9490" +checksum = "a61ff12b19d89c752c213316b87fdb4a587f073d219b893cc56974b8c9f39bf7" dependencies = [ "digest", "either", - "futures", "hex", "libc", "memmap2", @@ -455,8 +454,6 @@ dependencies = [ "ssri", "tempfile", "thiserror", - "tokio", - "tokio-stream", "walkdir", ] @@ -662,7 +659,6 @@ dependencies = [ "ckb-verification", "ckb-verification-traits", "criterion", - "lazy_static", "rand 0.8.5", "tempfile", ] @@ -765,7 +761,6 @@ dependencies = [ "dashmap", "faux", "is_sorted", - "lazy_static", "minstant", "tempfile", ] @@ -817,7 +812,6 @@ version = "0.119.0-pre" dependencies = [ "ckb-fixed-hash", "faster-hex", - "lazy_static", "rand 0.8.5", "secp256k1", "thiserror", @@ -873,7 +867,6 @@ dependencies = [ "ckb-stop-handler", "console", "indicatif", - "once_cell", "tempfile", ] @@ -887,7 +880,7 @@ version = "0.119.0-pre" dependencies = [ "anyhow", "ckb-occupied-capacity", - "derive_more", + "derive_more 1.0.0", "thiserror", ] @@ -1014,7 +1007,6 @@ dependencies = [ "ckb-types", "ckb_schemars", "faster-hex", - "lazy_static", "proptest", "regex", "serde", @@ -1109,7 +1101,6 @@ dependencies = [ "ckb-util", "env_logger", "log", - "once_cell", "regex", "sentry", "tempfile", @@ -1125,7 +1116,6 @@ dependencies = [ "ckb-logger", "ckb-metrics", "libc", - "once_cell", "tikv-jemalloc-ctl", "tikv-jemalloc-sys", ] @@ -1143,7 +1133,6 @@ dependencies = [ name = "ckb-metrics" version = "0.119.0-pre" dependencies = [ - "once_cell", "prometheus", "prometheus-static-metric", ] @@ -1165,8 +1154,11 @@ dependencies = [ "ckb-metrics-config", "ckb-stop-handler", "ckb-util", - "hyper", + "http-body-util", + "hyper 1.5.0", + "hyper-util", "prometheus", + "tokio", ] [[package]] @@ -1213,8 +1205,10 @@ dependencies = [ "console", "eaglesong", "futures", - "hyper", + "http-body-util", + "hyper 1.5.0", "hyper-tls", + "hyper-util", "indicatif", "jsonrpc-core", "lru", @@ -1241,7 +1235,7 @@ version = "0.119.0-pre" dependencies = [ "bitflags 1.3.2", "bloom-filters", - "bs58 0.4.0", + "bs58", "ckb-app-config", "ckb-hash", "ckb-logger", @@ -1255,9 +1249,7 @@ dependencies = [ "faster-hex", "futures", "ipnetwork", - "lazy_static", "num_cpus", - "once_cell", "proptest", "rand 0.8.5", "secp256k1", @@ -1265,7 +1257,7 @@ dependencies = [ "serde", "serde_json", "snap", - "socket2 0.5.7", + "socket2", "tempfile", "tentacle", "tokio", @@ -1291,7 +1283,6 @@ dependencies = [ "ckb-util", "faster-hex", "lru", - "once_cell", "semver", "serde_json", ] @@ -1408,7 +1399,6 @@ dependencies = [ "include_dir", "log", "num-bigint", - "once_cell", "rand 0.8.5", "serde_json", "sql-builder", @@ -1551,7 +1541,6 @@ dependencies = [ "ckb-util", "ckb-verification", "dashmap", - "once_cell", "sled", "tempfile", "tokio", @@ -1587,7 +1576,6 @@ dependencies = [ "ckb-util", "ctrlc", "libc", - "once_cell", "rand 0.8.5", "tokio", "tokio-util", @@ -1647,7 +1635,6 @@ dependencies = [ "itertools 0.11.0", "keyed_priority_queue", "lru", - "once_cell", "rand 0.8.5", "sentry", "tempfile", @@ -1686,7 +1673,6 @@ dependencies = [ "ckb-traits", "ckb-types", "ckb-util", - "lazy_static", "tempfile", ] @@ -1723,7 +1709,9 @@ dependencies = [ "ckb-types", "ckb-util", "ckb-verification", - "hyper", + "http-body-util", + "hyper 1.5.0", + "hyper-util", "lru", "multi_index_map", "num_cpus", @@ -1752,12 +1740,11 @@ dependencies = [ "ckb-merkle-mountain-range", "ckb-occupied-capacity", "ckb-rational", - "derive_more", + "derive_more 1.0.0", "golomb-coded-set", "merkle-cbt", "molecule", "numext-fixed-uint", - "once_cell", "paste", "proptest", ] @@ -1768,7 +1755,6 @@ version = "0.119.0-pre" dependencies = [ "ckb-fixed-hash", "linked-hash-map", - "once_cell", "parking_lot 0.12.3", "regex", ] @@ -1789,7 +1775,7 @@ dependencies = [ "ckb-traits", "ckb-types", "ckb-verification-traits", - "derive_more", + "derive_more 1.0.0", "lru", "tokio", ] @@ -1838,7 +1824,7 @@ dependencies = [ "bytes", "cc", "ckb-vm-definitions", - "derive_more", + "derive_more 0.99.18", "goblin 0.2.3", "goblin 0.4.0", "rand 0.7.3", @@ -2356,6 +2342,27 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "unicode-xid", +] + [[package]] name = "deunicode" version = "1.6.0" @@ -2433,14 +2440,14 @@ dependencies = [ [[package]] name = "enum-as-inner" -version = "0.3.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] @@ -2555,6 +2562,18 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -2866,7 +2885,26 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", "indexmap 2.6.0", "slab", "tokio", @@ -2956,12 +2994,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -3024,6 +3056,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows 0.52.0", +] + [[package]] name = "http" version = "0.2.12" @@ -3035,6 +3078,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -3042,7 +3096,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -3089,27 +3166,65 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.5.0", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-timeout" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.31", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -3117,15 +3232,37 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", - "hyper", + "http-body-util", + "hyper 1.5.0", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.5.0", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] @@ -3159,11 +3296,10 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -3299,14 +3435,14 @@ dependencies = [ [[package]] name = "ipconfig" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.3.19", + "socket2", "widestring", - "winapi", - "winreg 0.6.2", + "windows-sys 0.48.0", + "winreg", ] [[package]] @@ -3317,9 +3453,9 @@ checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "ipnetwork" -version = "0.18.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4088d739b183546b239688ddbc79891831df421773df95e236daf7867866d355" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" dependencies = [ "serde", ] @@ -3564,12 +3700,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.7.3" @@ -3998,6 +4128,17 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "os_info" +version = "3.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +dependencies = [ + "log", + "serde", + "windows-sys 0.52.0", +] + [[package]] name = "parking" version = "2.2.1" @@ -4656,7 +4797,7 @@ checksum = "dc31414597d1cd7fdd2422798b7652a6329dda0fe0219e6335a13d5bcaa9aeb6" dependencies = [ "cfg-if", "rustix", - "windows", + "windows 0.58.0", ] [[package]] @@ -4705,20 +4846,24 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.11.20" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.5.0", + "hyper-rustls", "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", @@ -4727,9 +4872,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -4737,7 +4885,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.50.0", + "windows-registry", ] [[package]] @@ -4746,7 +4894,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ - "hostname", + "hostname 0.3.1", "quick-error", ] @@ -5014,40 +5162,45 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "sentry" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904eca4fb30c6112a1dae60c0a9e29cfb42f42129da4260f1ee20e94151b62e3" +checksum = "5484316556650182f03b43d4c746ce0e3e48074a21e2f51244b648b6542e1066" dependencies = [ "httpdate", + "native-tls", "reqwest", "sentry-backtrace", "sentry-contexts", "sentry-core", + "sentry-debug-images", "sentry-log", "sentry-panic", + "sentry-tracing", "tokio", + "ureq", ] [[package]] name = "sentry-backtrace" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1671189d1b759879fa4bdde46c50a499abb14332ed81f84fc6f60658f41b2fdb" +checksum = "40aa225bb41e2ec9d7c90886834367f560efc1af028f1c5478a6cce6a59c463a" dependencies = [ "backtrace", - "lazy_static", + "once_cell", "regex", "sentry-core", ] [[package]] name = "sentry-contexts" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db80ceff16bb1a4b2689b8758e5e61e405fc4d8ff9f2d1b5b845b76ce37fa34e" +checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" dependencies = [ - "hostname", + "hostname 0.4.0", "libc", + "os_info", "rustc_version", "sentry-core", "uname", @@ -5055,22 +5208,33 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c9f509d3959ed4dbbd80ca42572caad682aaa1cdd92c719e0815d0e87f82c96" +checksum = "161283cfe8e99c8f6f236a402b9ccf726b201f365988b5bb637ebca0abbd4a30" dependencies = [ - "lazy_static", + "once_cell", "rand 0.8.5", "sentry-types", "serde", "serde_json", ] +[[package]] +name = "sentry-debug-images" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc6b25e945fcaa5e97c43faee0267eebda9f18d4b09a251775d8fef1086238a" +dependencies = [ + "findshlibs", + "once_cell", + "sentry-core", +] + [[package]] name = "sentry-log" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e00357035f6af5404870048167affaa551e15e0bee6efa2157e4b9bec6a453" +checksum = "75bbcc61886955045a1dd4bdb173412a80bb2571be3c5bfcf7eb8f55a442bbf5" dependencies = [ "log", "sentry-core", @@ -5078,23 +5242,35 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b442769cc34115f64393f7bfe4f863c3c38749e0c0b9613a7ae25b37c7ba53" +checksum = "bc74f229c7186dd971a9491ffcbe7883544aa064d1589bd30b83fb856cd22d63" dependencies = [ "sentry-backtrace", "sentry-core", ] +[[package]] +name = "sentry-tracing" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c5faf2103cd01eeda779ea439b68c4ee15adcdb16600836e97feafab362ec" +dependencies = [ + "sentry-backtrace", + "sentry-core", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "sentry-types" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254b600e93e9ef00a48382c9f1e86d27884bd9a5489efa4eb9210c20c72e88a6" +checksum = "5d68cdf6bc41b8ff3ae2a9c4671e97426dcdd154cc1d4b6b72813f285d6b163f" dependencies = [ "debugid", - "getrandom 0.2.15", "hex", + "rand 0.8.5", "serde", "serde_json", "thiserror", @@ -5311,17 +5487,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if", - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.7" @@ -5447,7 +5612,7 @@ checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" dependencies = [ "dotenvy", "either", - "heck 0.5.0", + "heck", "hex", "once_cell", "proc-macro2", @@ -5648,6 +5813,36 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.13.0" @@ -5679,7 +5874,7 @@ dependencies = [ "once_cell", "parking_lot 0.12.3", "rand 0.8.5", - "socket2 0.5.7", + "socket2", "tentacle-multiaddr", "tentacle-secio", "thiserror", @@ -5697,7 +5892,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9e71b28bf0bbf274b92f47cb2c5b42755d84a11e2246cf7bcb7b65c89483b9" dependencies = [ - "bs58 0.5.1", + "bs58", "bytes", "serde", "sha2", @@ -5710,7 +5905,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cac8b23a7879426a4961acea6ae66287f7fe9a934d131a722cbb88f145e97fea" dependencies = [ - "bs58 0.5.1", + "bs58", "bytes", "chacha20poly1305", "futures", @@ -5927,7 +6122,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", "tracing", "windows-sys 0.52.0", @@ -5964,6 +6159,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.16" @@ -6034,10 +6240,10 @@ dependencies = [ "axum", "base64 0.21.7", "bytes", - "h2", - "http", - "http-body", - "hyper", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.31", "hyper-timeout", "percent-encoding", "pin-project", @@ -6080,8 +6286,8 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "http-range-header", "pin-project-lite", "tokio", @@ -6151,9 +6357,9 @@ dependencies = [ [[package]] name = "trust-dns-proto" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" +checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" dependencies = [ "async-trait", "cfg-if", @@ -6162,35 +6368,36 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna 0.2.3", + "idna 0.4.0", "ipnet", - "lazy_static", - "log", + "once_cell", "rand 0.8.5", "smallvec", "thiserror", "tinyvec", "tokio", + "tracing", "url", ] [[package]] name = "trust-dns-resolver" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" +checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" dependencies = [ "cfg-if", "futures-util", "ipconfig", - "lazy_static", - "log", "lru-cache", - "parking_lot 0.11.2", + "once_cell", + "parking_lot 0.12.3", + "rand 0.8.5", "resolv-conf", "smallvec", "thiserror", "tokio", + "tracing", "trust-dns-proto", ] @@ -6209,7 +6416,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 0.2.12", "httparse", "log", "rand 0.8.5", @@ -6344,6 +6551,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -6372,6 +6585,19 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +dependencies = [ + "base64 0.22.1", + "log", + "native-tls", + "once_cell", + "url", +] + [[package]] name = "url" version = "2.5.2" @@ -6590,9 +6816,9 @@ dependencies = [ [[package]] name = "widestring" -version = "0.4.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "wildmatch" @@ -6631,6 +6857,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.58.0" @@ -6685,6 +6921,17 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -6852,15 +7099,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winreg" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -dependencies = [ - "winapi", -] - [[package]] name = "winreg" version = "0.50.0" diff --git a/benches/Cargo.toml b/benches/Cargo.toml index 91858206ef..c5f5037f95 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -24,7 +24,6 @@ ckb-test-chain-utils = { path = "../util/test-chain-utils", version = "= 0.119.0 ckb-dao-utils = { path = "../util/dao/utils", version = "= 0.119.0-pre" } ckb-dao = { path = "../util/dao", version = "= 0.119.0-pre" } ckb-system-scripts = { version = "= 0.5.4" } -lazy_static = "1.3.0" ckb-crypto = { path = "../util/crypto", version = "= 0.119.0-pre" } ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } ckb-verification = { path = "../verification", version = "= 0.119.0-pre" } diff --git a/benches/benches/benchmarks/util.rs b/benches/benches/benchmarks/util.rs index a9f64d0a50..e64401c975 100644 --- a/benches/benches/benchmarks/util.rs +++ b/benches/benches/benchmarks/util.rs @@ -23,7 +23,6 @@ use ckb_types::{ utilities::difficulty_to_compact, H160, H256, U256, }; -use lazy_static::lazy_static; use rand::random; use std::collections::HashSet; @@ -200,19 +199,19 @@ pub fn gen_always_success_block( const PRIVKEY: H256 = h256!("0xb2b3324cece882bca684eaf202667bb56ed8e8c2fd4b4dc71f615ebd6d9055a5"); const PUBKEY_HASH: H160 = h160!("0x779e5930892a0a9bf2fedfe048f685466c7d0396"); -lazy_static! { - static ref SECP_DATA_CELL: (CellOutput, Bytes) = { - let raw_data = BUNDLED_CELL - .get("specs/cells/secp256k1_data") - .expect("load secp256k1_blake160_sighash_all"); - let data: Bytes = raw_data.to_vec().into(); +static SECP_DATA_CELL: std::sync::LazyLock<(CellOutput, Bytes)> = std::sync::LazyLock::new(|| { + let raw_data = BUNDLED_CELL + .get("specs/cells/secp256k1_data") + .expect("load secp256k1_blake160_sighash_all"); + let data: Bytes = raw_data.to_vec().into(); - let cell = CellOutput::new_builder() - .capacity(Capacity::bytes(data.len()).unwrap().pack()) - .build(); - (cell, data) - }; - static ref SECP_CELL: (CellOutput, Bytes, Script) = { + let cell = CellOutput::new_builder() + .capacity(Capacity::bytes(data.len()).unwrap().pack()) + .build(); + (cell, data) +}); +static SECP_CELL: std::sync::LazyLock<(CellOutput, Bytes, Script)> = + std::sync::LazyLock::new(|| { let raw_data = BUNDLED_CELL .get("specs/cells/secp256k1_blake160_sighash_all") .expect("load secp256k1_blake160_sighash_all"); @@ -229,8 +228,7 @@ lazy_static! { .build(); (cell, data, script) - }; -} + }); pub fn secp_cell() -> &'static (CellOutput, Bytes, Script) { &SECP_CELL diff --git a/chain/Cargo.toml b/chain/Cargo.toml index ba04ed20b3..3218f54327 100644 --- a/chain/Cargo.toml +++ b/chain/Cargo.toml @@ -41,12 +41,15 @@ dashmap = "4.0" ckb-test-chain-utils = { path = "../util/test-chain-utils", version = "= 0.119.0-pre" } ckb-dao-utils = { path = "../util/dao/utils", version = "= 0.119.0-pre" } ckb-reward-calculator = { path = "../util/reward-calculator", version = "= 0.119.0-pre" } -ckb-tx-pool = { path = "../tx-pool", version = "= 0.119.0-pre", features = ["internal"] } +ckb-tx-pool = { path = "../tx-pool", version = "= 0.119.0-pre", features = [ + "internal", +] } ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } ckb-network = { path = "../network", version = "= 0.119.0-pre" } -lazy_static = "1.4" tempfile.workspace = true -ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre" ,features = ["enable_faketime"]} +ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = [ + "enable_faketime", +] } ckb-logger-service = { path = "../util/logger-service", version = "= 0.119.0-pre" } [features] diff --git a/chain/src/tests/block_assembler.rs b/chain/src/tests/block_assembler.rs index caf0eb84ca..6e8a71e516 100644 --- a/chain/src/tests/block_assembler.rs +++ b/chain/src/tests/block_assembler.rs @@ -19,7 +19,6 @@ use ckb_types::{ }; use ckb_verification::{BlockVerifier, HeaderVerifier}; use ckb_verification_traits::{Switch, Verifier}; -use lazy_static::lazy_static; use std::sync::Arc; fn start_chain(consensus: Option) -> (ChainController, Shared) { @@ -57,20 +56,6 @@ fn start_chain(consensus: Option) -> (ChainController, Shared) { (chain_controller, shared) } -lazy_static! { - static ref BASIC_BLOCK_SIZE: u64 = { - let (_chain_controller, shared) = start_chain(None); - - let block_template = shared - .get_block_template(None, None, None) - .unwrap() - .unwrap(); - - let block: Block = block_template.into(); - block.serialized_size_without_uncle_proposals() as u64 - }; -} - #[test] fn test_get_block_template() { let (_chain_controller, shared) = start_chain(None); diff --git a/ckb-bin/Cargo.toml b/ckb-bin/Cargo.toml index c6be0d57c7..b4087ae4cc 100644 --- a/ckb-bin/Cargo.toml +++ b/ckb-bin/Cargo.toml @@ -44,7 +44,7 @@ ckb-constant = { path = "../util/constant", version = "= 0.119.0-pre" } base64 = "0.21.0" tempfile.workspace = true rayon = "1.0" -sentry = { version = "0.26.0", optional = true } +sentry = { version = "0.34.0", optional = true } is-terminal = "0.4.7" fdlimit = "0.2.1" ckb-stop-handler = { path = "../util/stop-handler", version = "= 0.119.0-pre" } diff --git a/db-migration/Cargo.toml b/db-migration/Cargo.toml index 9e2d55a08d..facbfa1997 100644 --- a/db-migration/Cargo.toml +++ b/db-migration/Cargo.toml @@ -17,7 +17,6 @@ ckb-error = { path = "../error", version = "= 0.119.0-pre" } ckb-db-schema = { path = "../db-schema", version = "= 0.119.0-pre" } ckb-channel = { path = "../util/channel", version = "= 0.119.0-pre" } ckb-stop-handler = { path = "../util/stop-handler", version = "= 0.119.0-pre" } -once_cell = "1.8.0" indicatif = "0.16" console = ">=0.9.1, <1.0.0" diff --git a/db-migration/src/lib.rs b/db-migration/src/lib.rs index fa2ba321dc..d3aa913325 100644 --- a/db-migration/src/lib.rs +++ b/db-migration/src/lib.rs @@ -9,17 +9,17 @@ use ckb_logger::{debug, error, info}; use ckb_stop_handler::register_thread; use console::Term; pub use indicatif::{HumanDuration, MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle}; -use once_cell::sync::OnceCell; use std::cmp::Ordering; use std::collections::BTreeMap; use std::collections::VecDeque; use std::sync::Arc; use std::sync::Mutex; +use std::sync::OnceLock; use std::thread; use std::thread::JoinHandle; /// Shutdown flag for background migration. -pub static SHUTDOWN_BACKGROUND_MIGRATION: OnceCell = OnceCell::new(); +pub static SHUTDOWN_BACKGROUND_MIGRATION: OnceLock = OnceLock::new(); #[cfg(test)] mod tests; diff --git a/error/Cargo.toml b/error/Cargo.toml index b9b90d8faa..03fb94d9a7 100644 --- a/error/Cargo.toml +++ b/error/Cargo.toml @@ -12,4 +12,6 @@ repository = "https://github.com/nervosnetwork/ckb" thiserror = "1.0.22" anyhow = "1.0.34" ckb-occupied-capacity = { path = "../util/occupied-capacity", version = "= 0.119.0-pre" } -derive_more = { version = "0.99.0", default-features = false, features = ["display"] } +derive_more = { version = "1", default-features = false, features = [ + "display", +] } diff --git a/error/src/lib.rs b/error/src/lib.rs index 2c2dfa575e..528c1ad513 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -89,7 +89,7 @@ impl fmt::Display for AnyError { impl fmt::Debug for AnyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) + derive_more::Display::fmt(self, f) } } /// Return whether the error's kind is `InternalErrorKind::Database` diff --git a/miner/Cargo.toml b/miner/Cargo.toml index 29e4fcbc77..dda397ed0b 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -20,8 +20,14 @@ rand_distr = "0.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } -hyper = { version = "0.14", features = ["client", "http2", "http1", "server"] } -hyper-tls = "0.5" +hyper = { version = "1", features = ["client", "http2", "http1", "server"] } +hyper-util = { version = "0.1", features = [ + "server-auto", + "server-graceful", + "client-legacy", +] } +http-body-util = "0.1" +hyper-tls = "0.6" futures = "0.3" lru = "0.7.1" ckb-stop-handler = { path = "../util/stop-handler", version = "= 0.119.0-pre" } diff --git a/miner/src/client.rs b/miner/src/client.rs index 1cea7e2ae0..e5f53360aa 100644 --- a/miner/src/client.rs +++ b/miner/src/client.rs @@ -11,11 +11,17 @@ use ckb_types::{ H256, }; use futures::prelude::*; +use http_body_util::{BodyExt, Empty, Full}; use hyper::{ - body::{to_bytes, Buf, Bytes}, + body::{Buf, Bytes}, header::{HeaderValue, CONTENT_TYPE}, - service::{make_service_fn, service_fn}, - Body, Client as HttpClient, Error as HyperError, Method, Request, Response, Server, Uri, + service::service_fn, + Error as HyperError, Request, Response, Uri, +}; +use hyper_util::{ + client::legacy::{Client as HttpClient, Error as ClientError}, + rt::TokioExecutor, + server::{conn::auto, graceful::GracefulShutdown}, }; use jsonrpc_core::{ error::Error as RpcFail, error::ErrorCode as RpcFailCode, id::Id, params::Params, @@ -23,18 +29,21 @@ use jsonrpc_core::{ }; use serde_json::error::Error as JsonError; use serde_json::{self, json, Value}; -use std::convert::Infallible; use std::net::SocketAddr; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use std::{convert::Into, time}; -use tokio::sync::{mpsc, oneshot}; +use tokio::{ + net::TcpListener, + sync::{mpsc, oneshot}, +}; type RpcRequest = (oneshot::Sender>, MethodCall); #[derive(Debug)] pub enum RpcError { Http(HyperError), + Client(ClientError), Canceled, //oneshot canceled Json(JsonError), Fail(RpcFail), @@ -53,7 +62,7 @@ impl Rpc { let stop_rx: CancellationToken = new_tokio_exit_rx(); let https = hyper_tls::HttpsConnector::new(); - let client = HttpClient::builder().build(https); + let client = HttpClient::builder(TokioExecutor::new()).build::<_, Full>(https); let loop_handle = handle.clone(); handle.spawn(async move { loop { @@ -62,15 +71,14 @@ impl Rpc { let (sender, call): RpcRequest = item; let req_url = url.clone(); let request_json = serde_json::to_vec(&call).expect("valid rpc call"); - let mut req = Request::new(Body::from(request_json)); - *req.method_mut() = Method::POST; - *req.uri_mut() = req_url; - req.headers_mut() - .insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); + + let mut req = Request::builder().uri(req_url).method("POST").header(CONTENT_TYPE, "application/json"); + if let Some(value) = parse_authorization(&url) { - req.headers_mut() - .append(hyper::header::AUTHORIZATION, value); + req = req + .header(hyper::header::AUTHORIZATION, value); } + let req = req.body(Full::new(Bytes::from(request_json))).unwrap(); let client = client.clone(); loop_handle.spawn(async move { let request = match client @@ -78,8 +86,8 @@ impl Rpc { .await .map(|res|res.into_body()) { - Ok(body) => to_bytes(body).await.map_err(RpcError::Http), - Err(err) => Err(RpcError::Http(err)), + Ok(body) => BodyExt::collect(body).await.map_err(RpcError::Http).map(|t| t.to_bytes()), + Err(err) => Err(RpcError::Client(err)), }; if sender.send(request).is_err() { error!("rpc response send back error") @@ -224,23 +232,42 @@ Otherwise ckb-miner will malfunction and stop submitting valid blocks after a ce } async fn listen_block_template_notify(&self, addr: SocketAddr) { - let client = self.clone(); - let make_service = make_service_fn(move |_conn| { - let client = client.clone(); - let service = service_fn(move |req| handle(client.clone(), req)); - async move { Ok::<_, Infallible>(service) } - }); - - let server = Server::bind(&addr).serve(make_service); + let listener = TcpListener::bind(addr).await.unwrap(); + let server = auto::Builder::new(TokioExecutor::new()); + let graceful = GracefulShutdown::new(); let stop_rx: CancellationToken = new_tokio_exit_rx(); - let graceful = server.with_graceful_shutdown(async move { - stop_rx.cancelled().await; - info!("Miner client received exit signal. Exit now"); - }); - if let Err(e) = graceful.await { - error!("server error: {}", e); + loop { + let client = self.clone(); + let handle = service_fn(move |req| handle(client.clone(), req)); + tokio::select! { + conn = listener.accept() => { + let (stream, _) = match conn { + Ok(conn) => conn, + Err(e) => { + info!("accept error: {}", e); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + continue; + } + }; + let stream = hyper_util::rt::TokioIo::new(Box::pin(stream)); + let conn = server.serve_connection_with_upgrades(stream, handle); + + let conn = graceful.watch(conn.into_owned()); + tokio::spawn(async move { + if let Err(err) = conn.await { + info!("connection error: {}", err); + } + }); + }, + _ = stop_rx.cancelled() => { + info!("Miner client received exit signal. Exit now"); + break; + } + } } + drop(listener); + graceful.shutdown().await; } async fn poll_block_template(&self) { @@ -327,14 +354,17 @@ Otherwise ckb-miner will malfunction and stop submitting valid blocks after a ce type Error = Box; -async fn handle(client: Client, req: Request) -> Result, Error> { - let body = hyper::body::aggregate(req).await?; +async fn handle( + client: Client, + req: Request, +) -> Result>, Error> { + let body = BodyExt::collect(req).await?.aggregate(); if let Ok(template) = serde_json::from_reader(body.reader()) { client.update_block_template(template); } - Ok(Response::new(Body::empty())) + Ok(Response::new(Empty::new())) } async fn parse_response(output: Output) -> Result { diff --git a/network/Cargo.toml b/network/Cargo.toml index 8818bd3fd2..90cf548193 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -21,16 +21,15 @@ tokio = { version = "1", features = ["sync", "macros"] } tokio-util = { version = "0.7", features = ["codec"] } futures = "0.3" ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre" } -lazy_static = { version = "1.3.0", optional = true } -bs58 = { version = "0.4.0", optional = true } -sentry = { version = "0.26.0", optional = true } +bs58 = { version = "0.5.0", optional = true } +sentry = { version = "0.34.0", optional = true } faster-hex = { version = "0.6", optional = true } ckb-hash = { path = "../util/hash", version = "= 0.119.0-pre" } secp256k1 = { version = "0.29", features = ["recovery"], optional = true } -trust-dns-resolver = { version = "0.20", optional = true } +trust-dns-resolver = { version = "0.23", optional = true } snap = "1" ckb-types = { path = "../util/types", version = "= 0.119.0-pre" } -ipnetwork = "0.18" +ipnetwork = "0.20" serde_json = "1.0" bloom-filters = "0.1" ckb-spawn = { path = "../util/spawn", version = "= 0.119.0-pre" } @@ -45,13 +44,7 @@ p2p = { version = "0.6.1", package = "tentacle", features = [ [features] with_sentry = ["sentry"] -with_dns_seeding = [ - "lazy_static", - "bs58", - "faster-hex", - "trust-dns-resolver", - "secp256k1", -] +with_dns_seeding = ["bs58", "faster-hex", "trust-dns-resolver", "secp256k1"] fuzz = [] [dev-dependencies] @@ -59,7 +52,6 @@ tempfile.workspace = true criterion = "0.5" proptest = "1.0" num_cpus = "1.10" -once_cell = "1.8.0" ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = [ "enable_faketime", ] } diff --git a/network/src/protocols/tests/mod.rs b/network/src/protocols/tests/mod.rs index d30eba3d20..663ebf1dad 100644 --- a/network/src/protocols/tests/mod.rs +++ b/network/src/protocols/tests/mod.rs @@ -230,8 +230,7 @@ fn net_service_start( let control = p2p_service.control().clone().into(); let (addr_sender, addr_receiver) = ::std::sync::mpsc::channel(); - static RT: once_cell::sync::OnceCell = - once_cell::sync::OnceCell::new(); + static RT: std::sync::OnceLock = std::sync::OnceLock::new(); let rt = RT.get_or_init(|| { let num_threads = ::std::cmp::max(num_cpus::get(), 4); diff --git a/network/src/services/dns_seeding/seed_record.rs b/network/src/services/dns_seeding/seed_record.rs index 80abd6e271..20ec1affcc 100644 --- a/network/src/services/dns_seeding/seed_record.rs +++ b/network/src/services/dns_seeding/seed_record.rs @@ -6,7 +6,6 @@ use std::{ }; use ckb_hash::blake2b_256; -use lazy_static::lazy_static; use p2p::{ multiaddr::{Multiaddr, Protocol}, secio::PeerId, @@ -17,10 +16,9 @@ use secp256k1::{ Message, PublicKey, }; -lazy_static! { - pub(crate) static ref SECP256K1: secp256k1::Secp256k1 = - secp256k1::Secp256k1::new(); -} +pub(crate) static SECP256K1: std::sync::LazyLock> = + std::sync::LazyLock::new(secp256k1::Secp256k1::new); + pub(crate) const SEP: char = ';'; // Format: diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 0249d1e746..7d1675b21e 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -53,7 +53,7 @@ ckb-async-runtime = { path = "../util/runtime", version = "= 0.119.0-pre" } # issue tracking: https://github.com/GREsau/schemars/pull/251 schemars = { version = "0.8.19", package = "ckb_schemars" } [dev-dependencies] -reqwest = { version = "=0.11.20", features = ["blocking", "json"] } +reqwest = { version = "0.12", features = ["blocking", "json"] } serde = { version = "1.0", features = ["derive"] } ckb-shared = { path = "../shared", version = "= 0.119.0-pre" } ckb-test-chain-utils = { path = "../util/test-chain-utils", version = "= 0.119.0-pre" } diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 58f96716c8..26698b6d50 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -29,7 +29,6 @@ ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre" } ckb-channel = { path = "../util/channel", version = "= 0.119.0-pre" } ckb-app-config = { path = "../util/app-config", version = "= 0.119.0-pre" } ckb-migrate = { path = "../util/migrate", version = "= 0.119.0-pre" } -once_cell = "1.8.0" ckb-util = { path = "../util", version = "= 0.119.0-pre" } ckb-metrics = { path = "../util/metrics", version = "= 0.119.0-pre" } bitflags = "1.0" @@ -39,9 +38,21 @@ sled = "0.34.7" dashmap = "4.0" [dev-dependencies] -ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = ["enable_faketime"] } +ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = [ + "enable_faketime", +] } [features] -portable = ["ckb-db/portable", "ckb-store/portable", "ckb-tx-pool/portable", "ckb-migrate/portable"] -march-native = ["ckb-db/march-native", "ckb-store/march-native", "ckb-tx-pool/march-native", "ckb-migrate/march-native"] +portable = [ + "ckb-db/portable", + "ckb-store/portable", + "ckb-tx-pool/portable", + "ckb-migrate/portable", +] +march-native = [ + "ckb-db/march-native", + "ckb-store/march-native", + "ckb-tx-pool/march-native", + "ckb-migrate/march-native", +] stats = [] diff --git a/shared/src/shared_builder.rs b/shared/src/shared_builder.rs index 444ef4fe9e..d5644cacb5 100644 --- a/shared/src/shared_builder.rs +++ b/shared/src/shared_builder.rs @@ -160,7 +160,6 @@ impl SharedBuilder { /// Generates the SharedBuilder with temp db /// NOTICE: this is only used in testing pub fn with_temp_db() -> Self { - use once_cell::{sync, unsync}; use std::{ borrow::Borrow, sync::atomic::{AtomicUsize, Ordering}, @@ -172,18 +171,17 @@ impl SharedBuilder { thread_local! { // NOTICE:we can't put the runtime directly into thread_local here, // on windows the runtime in thread_local will get stuck when dropping - static RUNTIME_HANDLE: unsync::OnceCell = const { unsync::OnceCell::new() }; + static RUNTIME_HANDLE: std::cell::OnceCell = const { std::cell::OnceCell::new() }; } static DB_COUNT: AtomicUsize = AtomicUsize::new(0); - static TMP_DIR: sync::OnceCell = sync::OnceCell::new(); + static TMP_DIR: std::sync::OnceLock = std::sync::OnceLock::new(); let db = { let db_id = DB_COUNT.fetch_add(1, Ordering::SeqCst); let db_base_dir = TMP_DIR .borrow() - .get_or_try_init(TempDir::new) - .unwrap() + .get_or_init(|| TempDir::new().unwrap()) .path() .to_path_buf(); let db_dir = db_base_dir.join(format!("db_{db_id}")); diff --git a/spec/Cargo.toml b/spec/Cargo.toml index d25714b549..157e9b140c 100644 --- a/spec/Cargo.toml +++ b/spec/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/nervosnetwork/ckb" [dependencies] serde = { version = "1.0", features = ["derive"] } toml = "0.5" -cacache = { version = "12.0.0", default-features = false, features = ["tokio-runtime", "mmap"] } +cacache = { version = "13.0.0", default-features = false, features = ["mmap"] } ckb-constant = { path = "../util/constant", version = "= 0.119.0-pre" } ckb-types = { path = "../util/types", version = "= 0.119.0-pre" } ckb-pow = { path = "../pow", version = "= 0.119.0-pre" } @@ -19,11 +19,11 @@ ckb-resource = { path = "../resource", version = "= 0.119.0-pre" } ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } ckb-dao-utils = { path = "../util/dao/utils", version = "= 0.119.0-pre" } ckb-rational = { path = "../util/rational", version = "= 0.119.0-pre" } -ckb-crypto = { path = "../util/crypto", version = "= 0.119.0-pre"} -ckb-hash = { path = "../util/hash", version = "= 0.119.0-pre"} +ckb-crypto = { path = "../util/crypto", version = "= 0.119.0-pre" } +ckb-hash = { path = "../util/hash", version = "= 0.119.0-pre" } ckb-error = { path = "../error", version = "= 0.119.0-pre" } ckb-traits = { path = "../traits", version = "= 0.119.0-pre" } -ckb-logger = {path = "../util/logger", version = "= 0.119.0-pre"} +ckb-logger = { path = "../util/logger", version = "= 0.119.0-pre" } [dev-dependencies] diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 9aa237cfcb..7115dacd98 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -25,7 +25,7 @@ ckb-channel = { path = "../util/channel", version = "= 0.119.0-pre" } ckb-traits = { path = "../traits", version = "= 0.119.0-pre" } ckb-error = { path = "../error", version = "= 0.119.0-pre" } ckb-tx-pool = { path = "../tx-pool", version = "= 0.119.0-pre" } -sentry = { version = "0.26.0", optional = true } +sentry = { version = "0.34.0", optional = true } ckb-constant = { path = "../util/constant", version = "= 0.119.0-pre" } ckb-stop-handler = { path = "../util/stop-handler", version = "= 0.119.0-pre" } tokio = { version = "1", features = ["sync"] } @@ -48,7 +48,6 @@ ckb-chain = { path = "../chain", version = "= 0.119.0-pre", features = [ "mock", ] } faux = "^0.1" -once_cell = "1.8.0" ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = [ "enable_faketime", ] } diff --git a/sync/src/tests/net_time_checker.rs b/sync/src/tests/net_time_checker.rs index 846e07d796..89d631d5ee 100644 --- a/sync/src/tests/net_time_checker.rs +++ b/sync/src/tests/net_time_checker.rs @@ -109,8 +109,7 @@ fn net_service_start() -> Node { let control = p2p_service.control().clone().into(); let (addr_sender, addr_receiver) = ::std::sync::mpsc::channel(); - static RT: once_cell::sync::OnceCell = - once_cell::sync::OnceCell::new(); + static RT: std::sync::OnceLock = std::sync::OnceLock::new(); let rt = RT.get_or_init(|| { tokio::runtime::Builder::new_multi_thread() diff --git a/test/Cargo.toml b/test/Cargo.toml index 3ea017891c..0e8cde775e 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://github.com/nervosnetwork/ckb" repository = "https://github.com/nervosnetwork/ckb" [dependencies] -clap = { version = "=3.2.21" } +clap = { version = "4" } toml = "0.5.0" ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } ckb-app-config = { path = "../util/app-config", version = "= 0.119.0-pre" } @@ -33,21 +33,20 @@ ckb-db = { path = "../db", version = "= 0.119.0-pre" } ckb-store = { path = "../store", version = "= 0.119.0-pre" } ckb-shared = { path = "../shared", version = "= 0.119.0-pre" } tempfile = "3" -reqwest = { version = "=0.11.20", features = ["blocking", "json"] } +reqwest = { version = "0.12", features = ["blocking", "json"] } rand = "0.8" ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre" } serde_json = "1.0" -lazy_static = "1.4.0" byteorder = "1.3.1" jsonrpc-core = "18.0" ctrlc = { version = "3.1", features = ["termination"] } log = "0.4" [target.'cfg(not(target_os="windows"))'.dependencies] -nix = { version = "0.24.0", default-features = false, features = ["signal"] } +nix = { version = "0.29.0", default-features = false, features = ["signal"] } [target.'cfg(target_os="windows")'.dependencies] -windows-sys = { version = "0.52", features = [ +windows-sys = { version = "0.59", features = [ "Win32_Foundation", "Win32_System_Threading", "Win32_Security", diff --git a/test/src/global.rs b/test/src/global.rs index ee453eb6c7..07619ac5dd 100644 --- a/test/src/global.rs +++ b/test/src/global.rs @@ -1,18 +1,17 @@ use ckb_util::Mutex; -use lazy_static::lazy_static; use std::path::PathBuf; use std::sync::atomic::AtomicU16; -lazy_static! { - pub static ref BINARY_PATH: Mutex = Mutex::new(PathBuf::new()); - pub static ref VENDOR_PATH: Mutex = { - let default = ::std::env::current_dir() - .expect("can't get current_dir") - .join("vendor"); - Mutex::new(default) - }; - pub static ref PORT_COUNTER: AtomicU16 = AtomicU16::new(9000); -} +pub static BINARY_PATH: std::sync::LazyLock> = + std::sync::LazyLock::new(|| Mutex::new(PathBuf::new())); +pub static VENDOR_PATH: std::sync::LazyLock> = std::sync::LazyLock::new(|| { + let default = ::std::env::current_dir() + .expect("can't get current_dir") + .join("vendor"); + Mutex::new(default) +}); +pub static PORT_COUNTER: std::sync::LazyLock = + std::sync::LazyLock::new(|| AtomicU16::new(9000)); pub fn binary() -> PathBuf { (*BINARY_PATH.lock()).clone() diff --git a/test/src/main.rs b/test/src/main.rs index 038b947452..d03e672e59 100644 --- a/test/src/main.rs +++ b/test/src/main.rs @@ -8,7 +8,7 @@ use ckb_test::{ }; use ckb_types::core::ScriptHashType; use ckb_util::Mutex; -use clap::{App, Arg}; +use clap::{Arg, Command}; use rand::{seq::SliceRandom, thread_rng}; use std::any::Any; use std::cmp::min; @@ -17,7 +17,6 @@ use std::env; use std::fs::{self, read_to_string, File}; use std::io::{self, BufRead, BufReader, Write}; use std::path::{Path, PathBuf}; -use std::str::FromStr; use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::{Duration, Instant}; @@ -42,27 +41,24 @@ fn main() { let clap_app = clap_app(); let matches = clap_app.get_matches(); - let binary = matches.value_of_t_or_exit::("binary"); - let start_port = matches.value_of_t_or_exit::("port"); - let spec_names_to_run: Vec<_> = matches.values_of("specs").unwrap_or_default().collect(); - let max_time = if matches.is_present("max-time") { - matches.value_of_t_or_exit::("max-time") - } else { - 0 - }; - let worker_count = matches.value_of_t_or_exit::("concurrent"); + let binary = matches.get_one::("binary").cloned().unwrap(); + let start_port = matches.get_one::("port").cloned().unwrap(); + let spec_names_to_run: Vec<_> = matches + .get_many::("specs") + .unwrap_or_default() + .map(|v| v.as_str()) + .collect(); + let max_time = matches.get_one::("max-time").cloned().unwrap(); + let worker_count = matches.get_one::("concurrent").cloned().unwrap(); let vendor = matches - .value_of_t::("vendor") - .unwrap_or_else(|_| current_dir().join("vendor")); - let log_file_opt = matches - .value_of("log-file") - .map(PathBuf::from_str) - .transpose() - .unwrap_or_else(|err| panic!("failed to parse the log file path since {err}")); - let fail_fast = !matches.is_present("no-fail-fast"); - let report = !matches.is_present("no-report"); - let clean_tmp = !matches.is_present("keep-tmp-data"); - let verbose = matches.is_present("verbose"); + .get_one::("vendor") + .cloned() + .unwrap_or_else(|| current_dir().join("vendor")); + let log_file_opt = matches.get_one::("log-file").cloned(); + let fail_fast = !matches.get_flag("no-fail-fast"); + let report = !matches.get_flag("no-report"); + let clean_tmp = !matches.get_flag("keep-tmp-data"); + let verbose = matches.get_flag("verbose"); let logger_guard = { let filter = if !verbose { @@ -100,7 +96,7 @@ fn main() { .unwrap_or_else(|err| panic!("failed to init the logger service since {err}")) }; - if matches.is_present("list-specs") { + if matches.get_flag("list-specs") { list_specs(); return; } @@ -298,71 +294,83 @@ fn main() { drop(logger_guard); } -fn clap_app() -> App<'static> { - App::new("ckb-test") +fn clap_app() -> Command { + Command::new("ckb-test") .arg( - Arg::with_name("binary") + Arg::new("binary") .short('b') .long("bin") - .takes_value(true) - .value_name("PATH") + .action(clap::ArgAction::Set) + .value_parser(clap::value_parser!(PathBuf)) .help("Path to ckb executable") .default_value("../target/release/ckb"), ) .arg( - Arg::with_name("port") + Arg::new("port") .short('p') .long("port") - .takes_value(true) + .action(clap::ArgAction::Set) + .value_parser(clap::value_parser!(u16)) .help("Starting port number used to start ckb nodes") .default_value("9000"), ) .arg( - Arg::with_name("max-time") + Arg::new("max-time") .long("max-time") - .takes_value(true) - .value_name("SECONDS") - .help("Exit when total running time exceeds this limit"), + .action(clap::ArgAction::Set) + .value_parser(clap::value_parser!(u64)) + .help("Exit when total running time exceeds this limit") + .default_value("0"), ) .arg( - Arg::with_name("list-specs") + Arg::new("list-specs") .long("list-specs") + .action(clap::ArgAction::SetTrue) .help("list all specs"), ) - .arg(Arg::with_name("specs").multiple(true).help("Specs to run")) .arg( - Arg::with_name("concurrent") + Arg::new("specs") + .action(clap::ArgAction::Append) + .help("Specs to run"), + ) + .arg( + Arg::new("concurrent") .short('c') .long("concurrent") - .takes_value(true) + .action(clap::ArgAction::Set) + .value_parser(clap::value_parser!(usize)) .help("The number of specs can running concurrently") .default_value("4"), ) .arg( - Arg::with_name("verbose") + Arg::new("verbose") .long("verbose") + .action(clap::ArgAction::SetTrue) .help("Show verbose log"), ) .arg( - Arg::with_name("no-fail-fast") + Arg::new("no-fail-fast") .long("no-fail-fast") + .action(clap::ArgAction::SetTrue) .help("Run all tests regardless of failure"), ) .arg( - Arg::with_name("no-report") + Arg::new("no-report") .long("no-report") + .action(clap::ArgAction::SetTrue) .help("Do not show integration test report"), ) .arg( - Arg::with_name("log-file") + Arg::new("log-file") .long("log-file") - .takes_value(true) + .action(clap::ArgAction::Set) + .value_parser(clap::value_parser!(PathBuf)) .help("Write log outputs into file."), ) - .arg(Arg::with_name("keep-tmp-data").long("keep-tmp-data").help( + .arg(Arg::new("keep-tmp-data").long("keep-tmp-data").action(clap::ArgAction::SetTrue).help( "Keep all temporary files. Default: only keep temporary file for the failed tests.", )) - .arg(Arg::with_name("vendor").long("vendor")) + .arg(Arg::new("vendor").long("vendor").action(clap::ArgAction::SetTrue).value_parser(clap::value_parser!(PathBuf))) } fn filter_specs( diff --git a/test/src/rpc.rs b/test/src/rpc.rs index bb4b9a81dc..0cafcbe572 100644 --- a/test/src/rpc.rs +++ b/test/src/rpc.rs @@ -16,14 +16,14 @@ use ckb_types::core::{ Version as CoreVersion, }; use ckb_types::{packed::Byte32, prelude::*, H256}; -use lazy_static::lazy_static; -lazy_static! { - pub static ref HTTP_CLIENT: reqwest::blocking::Client = reqwest::blocking::Client::builder() - .timeout(::std::time::Duration::from_secs(30)) - .build() - .expect("reqwest Client build"); -} +pub static HTTP_CLIENT: std::sync::LazyLock = + std::sync::LazyLock::new(|| { + reqwest::blocking::Client::builder() + .timeout(::std::time::Duration::from_secs(30)) + .build() + .expect("reqwest Client build") + }); pub struct RpcClient { inner: Inner, diff --git a/tx-pool/Cargo.toml b/tx-pool/Cargo.toml index 79e459a362..cc42e7b52f 100644 --- a/tx-pool/Cargo.toml +++ b/tx-pool/Cargo.toml @@ -25,7 +25,7 @@ ckb-util = { path = "../util", version = "= 0.119.0-pre" } ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } ckb-chain-spec = { path = "../spec", version = "= 0.119.0-pre" } ckb-snapshot = { path = "../util/snapshot", version = "= 0.119.0-pre" } -ckb-metrics = {path = "../util/metrics", version = "= 0.119.0-pre"} +ckb-metrics = { path = "../util/metrics", version = "= 0.119.0-pre" } ckb-error = { path = "../error", version = "= 0.119.0-pre" } tokio = { version = "1", features = ["sync", "process"] } ckb-async-runtime = { path = "../util/runtime", version = "= 0.119.0-pre" } @@ -36,10 +36,12 @@ ckb-channel = { path = "../util/channel", version = "= 0.119.0-pre" } ckb-traits = { path = "../traits", version = "= 0.119.0-pre" } ckb-db = { path = "../db", version = "= 0.119.0-pre" } ckb-script = { path = "../script", version = "= 0.119.0-pre" } -sentry = { version = "0.26.0", optional = true } +sentry = { version = "0.34.0", optional = true } serde_json = "1.0" rand = "0.8.4" -hyper = { version = "0.14", features = ["http1", "client", "tcp"] } +hyper = { version = "1", features = ["http1", "http2", "client"] } +hyper-util = { version = "0.1", features = ["client-legacy", "http1", "http2"] } +http-body-util = "0.1" multi_index_map = "0.6.0" slab = "0.4" rustc-hash = "1.1" @@ -48,11 +50,17 @@ tokio-util = "0.7.8" [dev-dependencies] tempfile.workspace = true ckb-hash = { path = "../util/hash", version = "= 0.119.0-pre" } -ckb-systemtime = {path = "../util/systemtime", version = "= 0.119.0-pre", features = ["enable_faketime"]} +ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = [ + "enable_faketime", +] } [features] default = [] internal = [] with_sentry = ["sentry"] portable = ["ckb-db/portable", "ckb-store/portable", "ckb-snapshot/portable"] -march-native = ["ckb-db/march-native", "ckb-store/march-native", "ckb-snapshot/march-native"] +march-native = [ + "ckb-db/march-native", + "ckb-store/march-native", + "ckb-snapshot/march-native", +] diff --git a/tx-pool/src/block_assembler/mod.rs b/tx-pool/src/block_assembler/mod.rs index 81acca0951..dc6e0a1e93 100644 --- a/tx-pool/src/block_assembler/mod.rs +++ b/tx-pool/src/block_assembler/mod.rs @@ -21,6 +21,7 @@ use ckb_snapshot::Snapshot; use ckb_store::ChainStore; use ckb_systemtime::unix_time_as_millis; use ckb_types::{ + bytes, core::{ cell::{OverlayCellChecker, TransactionsChecker}, BlockNumber, Capacity, Cycle, EpochExt, EpochNumberWithFraction, ScriptHashType, @@ -32,7 +33,9 @@ use ckb_types::{ }, prelude::*, }; -use hyper::{client::HttpConnector, Body, Client, Method, Request}; +use http_body_util::Full; +use hyper::{Method, Request}; +use hyper_util::client::legacy::{connect::HttpConnector, Client}; use std::collections::HashSet; use std::sync::{ atomic::{AtomicU64, Ordering}, @@ -99,7 +102,7 @@ pub struct BlockAssembler { pub(crate) work_id: Arc, pub(crate) candidate_uncles: Arc>, pub(crate) current: Arc>, - pub(crate) poster: Arc>, + pub(crate) poster: Arc>>, } impl BlockAssembler { @@ -158,7 +161,10 @@ impl BlockAssembler { work_id: Arc::new(work_id), candidate_uncles: Arc::new(Mutex::new(CandidateUncles::new())), current: Arc::new(Mutex::new(current)), - poster: Arc::new(Client::new()), + poster: Arc::new( + Client::builder(hyper_util::rt::TokioExecutor::new()) + .build::<_, Full>(HttpConnector::new()), + ), } } @@ -646,7 +652,7 @@ impl BlockAssembler { .method(Method::POST) .uri(url.as_ref()) .header("content-type", "application/json") - .body(Body::from(template_json.to_owned())) + .body(Full::new(template_json.to_owned().into())) { let client = Arc::clone(&self.poster); let url = url.to_owned(); diff --git a/util/Cargo.toml b/util/Cargo.toml index ca722018ec..74174a25b7 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -10,9 +10,8 @@ repository = "https://github.com/nervosnetwork/ckb" [dependencies] parking_lot = "0.12" -linked-hash-map = { version = "0.5", features = ["serde_impl"] } +linked-hash-map = { version = "0.5", features = ["serde_impl"] } regex = "1.1.6" -once_cell = "1.8.0" [dev-dependencies] ckb-fixed-hash = { path = "fixed-hash", version = "= 0.119.0-pre" } diff --git a/util/app-config/Cargo.toml b/util/app-config/Cargo.toml index bf57c112eb..dd77fec8a3 100644 --- a/util/app-config/Cargo.toml +++ b/util/app-config/Cargo.toml @@ -25,7 +25,7 @@ ckb-types = { path = "../types", version = "= 0.119.0-pre" } secio = { version = "0.6", package = "tentacle-secio" } multiaddr = { version = "0.3.0", package = "tentacle-multiaddr" } rand = "0.8" -sentry = { version = "0.26.0", optional = true } +sentry = { version = "0.34.0", optional = true } ckb-systemtime = { path = "../systemtime", version = "= 0.119.0-pre" } url = { version = "2.2.2", features = ["serde"] } ubyte = { version = "0.10", features = ["serde"] } diff --git a/util/crypto/Cargo.toml b/util/crypto/Cargo.toml index e843e635c3..17b010eab8 100644 --- a/util/crypto/Cargo.toml +++ b/util/crypto/Cargo.toml @@ -10,7 +10,6 @@ repository = "https://github.com/nervosnetwork/ckb" [dependencies] ckb-fixed-hash = { path = "../fixed-hash", version = "= 0.119.0-pre" } -lazy_static = "1.3" secp256k1 = { version = "0.29", features = ["recovery"], optional = true } thiserror = "1.0.22" rand = { version = "0.8", features = ["small_rng"] } diff --git a/util/crypto/src/secp/mod.rs b/util/crypto/src/secp/mod.rs index 32ff3effbf..3ce6a62450 100644 --- a/util/crypto/src/secp/mod.rs +++ b/util/crypto/src/secp/mod.rs @@ -1,15 +1,13 @@ //! `secp256k1` wrapper use ckb_fixed_hash::H256; -use lazy_static::lazy_static; /// A (hashed) message input to an ECDSA signature pub type Message = H256; -lazy_static! { - /// The reference to lazily-initialized static secp256k1 engine, used to execute all signature operations - pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new(); -} +/// The reference to lazily-initialized static secp256k1 engine, used to execute all signature operations +pub static SECP256K1: std::sync::LazyLock> = + std::sync::LazyLock::new(secp256k1::Secp256k1::new); mod error; mod generator; diff --git a/util/jsonrpc-types/Cargo.toml b/util/jsonrpc-types/Cargo.toml index 279bcc7382..04afdc6945 100644 --- a/util/jsonrpc-types/Cargo.toml +++ b/util/jsonrpc-types/Cargo.toml @@ -19,4 +19,3 @@ schemars = { version = "0.8.19", package = "ckb_schemars" } [dev-dependencies] proptest = "1.0" regex = "1.1" -lazy_static = "1.3" diff --git a/util/jsonrpc-types/src/tests/blockchain.rs b/util/jsonrpc-types/src/tests/blockchain.rs index a82be1a06b..38d1294c82 100644 --- a/util/jsonrpc-types/src/tests/blockchain.rs +++ b/util/jsonrpc-types/src/tests/blockchain.rs @@ -1,5 +1,4 @@ use ckb_types::{bytes::Bytes, core, h256, packed, prelude::*}; -use lazy_static::lazy_static; use proptest::{collection::size_range, prelude::*}; use regex::Regex; @@ -160,9 +159,10 @@ fn _test_block_convert(data: Bytes, arg: Bytes) -> Result<(), TestCaseError> { } fn header_field_format_check(json: &str) { - lazy_static! { - static ref RE: Regex = Regex::new("\"(version|compact_target|parent_hash|timestamp|number|epoch|transactions_root|proposals_hash|extra_hash|dao|nonce)\":\"(?P.*?\")").unwrap(); - } + static RE: std::sync::LazyLock = std::sync::LazyLock::new(|| { + Regex::new("\"(version|compact_target|parent_hash|timestamp|number|epoch|transactions_root|proposals_hash|extra_hash|dao|nonce)\":\"(?P.*?\")").unwrap() + }); + for caps in RE.captures_iter(json) { assert!(&caps["value"].starts_with("0x")); } diff --git a/util/logger-service/Cargo.toml b/util/logger-service/Cargo.toml index 1dae10143f..e18715b940 100644 --- a/util/logger-service/Cargo.toml +++ b/util/logger-service/Cargo.toml @@ -15,10 +15,9 @@ ckb-channel = { path = "../channel", version = "= 0.119.0-pre" } yansi = "0.5" log = "0.4" env_logger = "0.10" -once_cell = "1.8.0" regex = "1.1.6" backtrace = "0.3" -sentry = { version = "0.26.0", optional = true, features = ["log"] } +sentry = { version = "0.34.0", optional = true, features = ["log"] } time = { version = "0.3.36", features = ["formatting"] } [dev-dependencies] diff --git a/util/logger-service/src/lib.rs b/util/logger-service/src/lib.rs index 37c7eb2684..f4b7765405 100644 --- a/util/logger-service/src/lib.rs +++ b/util/logger-service/src/lib.rs @@ -4,11 +4,11 @@ use backtrace::Backtrace; use ckb_channel::{self, unbounded}; use env_logger::filter::{Builder, Filter}; use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; -use once_cell::sync::OnceCell; use regex::Regex; use std::collections::HashMap; use std::io::Write; use std::path::{Path, PathBuf}; +use std::sync::OnceLock; use std::{fs, panic, process, sync, thread}; use time::{ format_description::{self, FormatItem}, @@ -22,9 +22,9 @@ use yansi::Paint; #[cfg(test)] mod tests; -static CONTROL_HANDLE: OnceCell> = OnceCell::new(); -static FORMAT: OnceCell>> = OnceCell::new(); -static RE: OnceCell = OnceCell::new(); +static CONTROL_HANDLE: OnceLock> = OnceLock::new(); +static FORMAT: OnceLock>> = OnceLock::new(); +static RE: OnceLock = OnceLock::new(); enum Message { Record { diff --git a/util/memory-tracker/Cargo.toml b/util/memory-tracker/Cargo.toml index 10e1739b0d..8c787a8d2b 100644 --- a/util/memory-tracker/Cargo.toml +++ b/util/memory-tracker/Cargo.toml @@ -17,7 +17,6 @@ ckb-db = { path = "../../db", version = "= 0.119.0-pre" } jemalloc-ctl = { package = "tikv-jemalloc-ctl", version = "0.5.0" } jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.5.0" } libc = "0.2" -once_cell = "1.8.0" [features] default = [] diff --git a/util/memory-tracker/src/process.rs b/util/memory-tracker/src/process.rs index 0a3ad8d392..8ea2be1a26 100644 --- a/util/memory-tracker/src/process.rs +++ b/util/memory-tracker/src/process.rs @@ -122,7 +122,7 @@ pub struct Memory { impl FromStr for Memory { type Err = io::Error; fn from_str(value: &str) -> Result { - static PAGE_SIZE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + static PAGE_SIZE: std::sync::OnceLock = std::sync::OnceLock::new(); let page_size = PAGE_SIZE.get_or_init(|| unsafe { libc::sysconf(libc::_SC_PAGESIZE) as u64 }); let mut parts = value.split_ascii_whitespace(); @@ -179,7 +179,7 @@ impl FromStr for Memory { } fn get_current_process_memory() -> Result { - static PID: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + static PID: std::sync::OnceLock = std::sync::OnceLock::new(); let pid = PID.get_or_init(|| unsafe { libc::getpid() }); let content = fs::read_to_string(format!("/proc/{pid}/statm"))?; diff --git a/util/metrics-service/Cargo.toml b/util/metrics-service/Cargo.toml index 5401df511a..aa12084c7c 100644 --- a/util/metrics-service/Cargo.toml +++ b/util/metrics-service/Cargo.toml @@ -15,5 +15,8 @@ ckb-logger = { path = "../logger", version = "= 0.119.0-pre" } ckb-async-runtime = { path = "../runtime", version = "= 0.119.0-pre" } ckb-util = { path = "..", version = "= 0.119.0-pre" } prometheus = "0.13.3" -hyper = { version = "0.14", features = ["http1", "tcp", "server"] } +hyper = { version = "1", features = ["http1", "http2", "server"] } +http-body-util = "0.1" +hyper-util = { version = "0.1", features = ["server-auto", "server-graceful"] } ckb-stop-handler = { path = "../stop-handler", version = "= 0.119.0-pre" } +tokio = { version = "1", features = ["sync"] } diff --git a/util/metrics-service/src/lib.rs b/util/metrics-service/src/lib.rs index c997671c7a..ca6e4505db 100644 --- a/util/metrics-service/src/lib.rs +++ b/util/metrics-service/src/lib.rs @@ -1,13 +1,18 @@ //! The service which handles the metrics data in CKB. -use std::{convert::Infallible, net::SocketAddr}; +use std::net::SocketAddr; +use http_body_util::Full; use hyper::{ - header::CONTENT_TYPE, - service::{make_service_fn, service_fn}, - Body, Error as HyperError, Method, Request, Response, Server, + body::Bytes, header::CONTENT_TYPE, service::service_fn, Error as HyperError, Method, Request, + Response, +}; +use hyper_util::{ + rt::TokioExecutor, + server::{conn::auto, graceful::GracefulShutdown}, }; use prometheus::Encoder as _; +use tokio::net::TcpListener; use ckb_async_runtime::Handle; use ckb_logger::info; @@ -56,28 +61,51 @@ fn run_exporter(exporter: Exporter, handle: &Handle) -> Result<(), String> { let addr = listen_address .parse::() .map_err(|err| format!("failed to parse listen_address because {err}"))?; - let make_svc = make_service_fn(move |_conn| async move { - Ok::<_, Infallible>(service_fn(start_prometheus_service)) - }); + let make_svc = service_fn(start_prometheus_service); ckb_logger::info!("Start prometheus exporter at {}", addr); handle.spawn(async move { - let server = Server::bind(&addr) - .serve(make_svc) - .with_graceful_shutdown(async { - let exit_rx: CancellationToken = new_tokio_exit_rx(); - exit_rx.cancelled().await; - info!("Prometheus server received exit signal; exit now"); - }); - if let Err(err) = server.await { - ckb_logger::error!("prometheus server error: {}", err); + let listener = TcpListener::bind(&addr).await.unwrap(); + let server = auto::Builder::new(TokioExecutor::new()); + let graceful = GracefulShutdown::new(); + let stop_rx: CancellationToken = new_tokio_exit_rx(); + loop { + tokio::select! { + conn = listener.accept() => { + let (stream, _) = match conn { + Ok(conn) => conn, + Err(e) => { + eprintln!("accept error: {}", e); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + continue; + } + }; + let stream = hyper_util::rt::TokioIo::new(Box::pin(stream)); + let conn = server.serve_connection_with_upgrades(stream, make_svc); + + let conn = graceful.watch(conn.into_owned()); + tokio::spawn(async move { + if let Err(err) = conn.await { + info!("connection error: {}", err); + } + }); + }, + _ = stop_rx.cancelled() => { + info!("Prometheus server received exit signal; exit now"); + break; + } + } } + drop(listener); + graceful.shutdown().await; }); } } Ok(()) } -async fn start_prometheus_service(req: Request) -> Result, HyperError> { +async fn start_prometheus_service( + req: Request, +) -> Result>, HyperError> { Ok(match (req.method(), req.uri().path()) { (&Method::GET, "/") => { let mut buffer = vec![]; @@ -87,11 +115,11 @@ async fn start_prometheus_service(req: Request) -> Result, Response::builder() .status(200) .header(CONTENT_TYPE, encoder.format_type()) - .body(Body::from(buffer)) + .body(Full::new(Bytes::from(buffer))) } _ => Response::builder() .status(404) - .body(Body::from("Page Not Found")), + .body(Full::from("Page Not Found")), } .unwrap()) } diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index c74de3d3f3..1f5431300f 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -11,4 +11,3 @@ repository = "https://github.com/nervosnetwork/ckb" [dependencies] prometheus = "0.13.3" prometheus-static-metric = "0.5.1" -once_cell = "1.17.1" diff --git a/util/metrics/src/lib.rs b/util/metrics/src/lib.rs index 41b9d7d895..6ea701f0e4 100644 --- a/util/metrics/src/lib.rs +++ b/util/metrics/src/lib.rs @@ -126,7 +126,7 @@ pub struct Metrics { pub ckb_inflight_timeout_count: IntCounter, } -static METRICS: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { +static METRICS: std::sync::LazyLock = std::sync::LazyLock::new(|| { Metrics { ckb_chain_tip: register_int_gauge!("ckb_chain_tip", "The CKB chain tip header number").unwrap(), ckb_chain_unverified_tip: register_int_gauge!( @@ -314,8 +314,7 @@ static METRICS: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { /// Indicate whether the metrics service is enabled. /// This value will set by ckb-metrics-service -pub static METRICS_SERVICE_ENABLED: once_cell::sync::OnceCell = - once_cell::sync::OnceCell::new(); +pub static METRICS_SERVICE_ENABLED: std::sync::OnceLock = std::sync::OnceLock::new(); thread_local! { static ENABLE_COLLECT_METRICS: Cell>= Cell::default(); diff --git a/util/network-alert/Cargo.toml b/util/network-alert/Cargo.toml index e39cd7272f..0a703190b1 100644 --- a/util/network-alert/Cargo.toml +++ b/util/network-alert/Cargo.toml @@ -13,9 +13,9 @@ ckb-multisig = { path = "../multisig", version = "= 0.119.0-pre" } ckb-types = { path = "../types", version = "= 0.119.0-pre" } ckb-util = { path = "..", version = "= 0.119.0-pre" } ckb-network = { path = "../../network", version = "= 0.119.0-pre" } -ckb-notify = { path = "../../notify", version = "= 0.119.0-pre"} +ckb-notify = { path = "../../notify", version = "= 0.119.0-pre" } ckb-jsonrpc-types = { path = "../jsonrpc-types", version = "= 0.119.0-pre" } -ckb-logger = { path = "../logger", version = "= 0.119.0-pre"} +ckb-logger = { path = "../logger", version = "= 0.119.0-pre" } ckb-app-config = { path = "../app-config", version = "= 0.119.0-pre" } ckb-error = { path = "../../error", version = "= 0.119.0-pre" } ckb-systemtime = { path = "../systemtime", version = "= 0.119.0-pre" } @@ -25,7 +25,8 @@ semver = "1.0" [dev-dependencies] ckb-crypto = { path = "../crypto", version = "= 0.119.0-pre" } ckb-async-runtime = { path = "../runtime", version = "= 0.119.0-pre" } -once_cell = "1.8.0" -ckb-systemtime = {path = "../systemtime", version = "= 0.119.0-pre", features = ["enable_faketime"]} +ckb-systemtime = { path = "../systemtime", version = "= 0.119.0-pre", features = [ + "enable_faketime", +] } faster-hex = "0.6" serde_json = "1.0" diff --git a/util/network-alert/src/tests/test_notifier.rs b/util/network-alert/src/tests/test_notifier.rs index 2145eb6d07..eb8b906537 100644 --- a/util/network-alert/src/tests/test_notifier.rs +++ b/util/network-alert/src/tests/test_notifier.rs @@ -3,7 +3,6 @@ use ckb_async_runtime::{new_background_runtime, Handle}; use ckb_notify::NotifyService; use ckb_types::{packed, prelude::*}; -use once_cell::unsync; fn build_alert( id: u32, @@ -26,7 +25,7 @@ fn new_notifier(version: &str) -> Notifier { thread_local! { // NOTICE:we can't put the runtime directly into thread_local here, // on windows the runtime in thread_local will get stuck when dropping - static RUNTIME_HANDLE: unsync::OnceCell = const { unsync::OnceCell::new() }; + static RUNTIME_HANDLE: std::cell::OnceCell = const { std::cell::OnceCell::new() }; } let notify_controller = RUNTIME_HANDLE.with(|runtime| { diff --git a/util/rich-indexer/Cargo.toml b/util/rich-indexer/Cargo.toml index 093008b0fd..b3de5e7bd9 100644 --- a/util/rich-indexer/Cargo.toml +++ b/util/rich-indexer/Cargo.toml @@ -21,7 +21,6 @@ ckb-types = { path = "../types", version = "= 0.119.0-pre" } futures = "0.3" log = "0.4" num-bigint = "0.4" -once_cell = "1.8.0" sql-builder = "3.1" sqlx = { version = "0.8.2", features = [ "runtime-tokio-rustls", diff --git a/util/rich-indexer/src/store.rs b/util/rich-indexer/src/store.rs index 2860005292..f4decd8d99 100644 --- a/util/rich-indexer/src/store.rs +++ b/util/rich-indexer/src/store.rs @@ -3,13 +3,13 @@ use ckb_app_config::{DBDriver, RichIndexerConfig}; use futures::TryStreamExt; use include_dir::{include_dir, Dir}; use log::LevelFilter; -use once_cell::sync::OnceCell; use sqlx::{ any::{Any, AnyArguments, AnyConnectOptions, AnyPoolOptions, AnyRow}, migrate::Migrator, query::{Query, QueryAs}, AnyPool, ConnectOptions, IntoArguments, Row, Transaction, }; +use std::sync::OnceLock; use tempfile::tempdir; use std::fs::{self, OpenOptions}; @@ -27,7 +27,7 @@ static MIGRATIONS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/resources/mig #[derive(Clone, Default)] pub struct SQLXPool { - pool: Arc>, + pool: Arc>, pub(crate) db_driver: DBDriver, } diff --git a/util/src/strings.rs b/util/src/strings.rs index 9d8b67af58..9fe79a64a8 100644 --- a/util/src/strings.rs +++ b/util/src/strings.rs @@ -18,7 +18,7 @@ use regex::Regex; /// ``` pub fn check_if_identifier_is_valid(ident: &str) -> Result<(), String> { const IDENT_PATTERN: &str = r#"^[0-9a-zA-Z_-]+$"#; - static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + static RE: std::sync::OnceLock = std::sync::OnceLock::new(); // IDENT_PATTERN is a correct regular expression, so unwrap here let re = RE.get_or_init(|| Regex::new(IDENT_PATTERN).unwrap()); diff --git a/util/stop-handler/Cargo.toml b/util/stop-handler/Cargo.toml index 6d8e34936b..60d24bd9a3 100644 --- a/util/stop-handler/Cargo.toml +++ b/util/stop-handler/Cargo.toml @@ -13,7 +13,6 @@ ckb-logger = { path = "../logger", version = "= 0.119.0-pre" } tokio = { version = "1", features = ["sync", "rt-multi-thread"] } ckb-channel = { path = "../channel", version = "= 0.119.0-pre" } ckb-util = { path = "..", version = "= 0.119.0-pre" } -once_cell = "1.8.0" ckb-async-runtime = { path = "../runtime", version = "= 0.119.0-pre" } tokio-util = "0.7.8" diff --git a/util/stop-handler/src/stop_register.rs b/util/stop-handler/src/stop_register.rs index 73b3efbe1d..d522a12e59 100644 --- a/util/stop-handler/src/stop_register.rs +++ b/util/stop-handler/src/stop_register.rs @@ -28,21 +28,21 @@ pub fn wait_all_ckb_services_exit() { info!("All ckb threads have been stopped"); } -static CKB_HANDLES: once_cell::sync::Lazy> = - once_cell::sync::Lazy::new(|| { +static CKB_HANDLES: std::sync::LazyLock> = + std::sync::LazyLock::new(|| { Mutex::new(CkbServiceHandles { thread_handles: vec![], }) }); -static RECEIVED_STOP_SIGNAL: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(AtomicBool::default); +static RECEIVED_STOP_SIGNAL: std::sync::LazyLock = + std::sync::LazyLock::new(AtomicBool::default); -static TOKIO_EXIT: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(CancellationToken::new); +static TOKIO_EXIT: std::sync::LazyLock = + std::sync::LazyLock::new(CancellationToken::new); -static CROSSBEAM_EXIT_SENDERS: once_cell::sync::Lazy>>> = - once_cell::sync::Lazy::new(|| Mutex::new(vec![])); +static CROSSBEAM_EXIT_SENDERS: std::sync::LazyLock>>> = + std::sync::LazyLock::new(|| Mutex::new(vec![])); /// Create a new CancellationToken for exit signal pub fn new_tokio_exit_rx() -> CancellationToken { diff --git a/util/test-chain-utils/Cargo.toml b/util/test-chain-utils/Cargo.toml index 5a53719275..558e8674ef 100644 --- a/util/test-chain-utils/Cargo.toml +++ b/util/test-chain-utils/Cargo.toml @@ -9,14 +9,13 @@ homepage = "https://github.com/nervosnetwork/ckb" repository = "https://github.com/nervosnetwork/ckb" [dependencies] -ckb-types = {path = "../types", version = "= 0.119.0-pre"} +ckb-types = { path = "../types", version = "= 0.119.0-pre" } ckb-db = { path = "../../db", version = "= 0.119.0-pre" } ckb-store = { path = "../../store", version = "= 0.119.0-pre" } ckb-chain-spec = { path = "../../spec", version = "= 0.119.0-pre" } ckb-dao-utils = { path = "../dao/utils", version = "= 0.119.0-pre" } ckb-dao = { path = "../dao", version = "= 0.119.0-pre" } ckb-traits = { path = "../../traits", version = "= 0.119.0-pre" } -lazy_static = "1.3.0" ckb-systemtime = { path = "../systemtime", version = "= 0.119.0-pre" } ckb-resource = { path = "../../resource", version = "= 0.119.0-pre" } ckb-db-schema = { path = "../../db-schema", version = "= 0.119.0-pre" } @@ -24,4 +23,6 @@ ckb-util = { path = "..", version = "= 0.119.0-pre" } tempfile.workspace = true [dev-dependencies] -ckb-systemtime = { path = "../systemtime", version = "= 0.119.0-pre", features = ["enable_faketime"] } +ckb-systemtime = { path = "../systemtime", version = "= 0.119.0-pre", features = [ + "enable_faketime", +] } diff --git a/util/test-chain-utils/src/chain.rs b/util/test-chain-utils/src/chain.rs index 7669089979..7535ea7de4 100644 --- a/util/test-chain-utils/src/chain.rs +++ b/util/test-chain-utils/src/chain.rs @@ -16,7 +16,6 @@ use ckb_types::{ utilities::difficulty_to_compact, H256, U256, }; -use lazy_static::lazy_static; use std::fs::File; use std::io::Read; use std::path::Path; @@ -39,10 +38,8 @@ fn load_cell_from_path(path: &str) -> (CellOutput, Bytes, Script) { (cell, data, script) } -lazy_static! { - static ref SUCCESS_CELL: (CellOutput, Bytes, Script) = - load_cell_from_path("../../script/testdata/always_success"); -} +static SUCCESS_CELL: std::sync::LazyLock<(CellOutput, Bytes, Script)> = + std::sync::LazyLock::new(|| load_cell_from_path("../../script/testdata/always_success")); // #include "ckb_syscalls.h" @@ -60,10 +57,8 @@ lazy_static! { // return 0; // } -lazy_static! { - static ref LOAD_INPUT_DATA_HASH: (CellOutput, Bytes, Script) = - load_cell_from_path("vendor/load_input_data_hash"); -} +static LOAD_INPUT_DATA_HASH: std::sync::LazyLock<(CellOutput, Bytes, Script)> = + std::sync::LazyLock::new(|| load_cell_from_path("vendor/load_input_data_hash")); /// Script for loading input data hash from input data. #[doc(hidden)] @@ -86,10 +81,8 @@ pub fn load_input_data_hash_cell() -> &'static (CellOutput, Bytes, Script) { // return 0; // } -lazy_static! { - static ref LOAD_INPUT_ONE_BYTE: (CellOutput, Bytes, Script) = - load_cell_from_path("vendor/load_input_one_byte"); -} +static LOAD_INPUT_ONE_BYTE: std::sync::LazyLock<(CellOutput, Bytes, Script)> = + std::sync::LazyLock::new(|| load_cell_from_path("vendor/load_input_one_byte")); /// Script for loading one byte from input data. #[doc(hidden)] @@ -103,10 +96,8 @@ pub fn always_success_cell() -> &'static (CellOutput, Bytes, Script) { &SUCCESS_CELL } -lazy_static! { - static ref IS_EVEN_LIB: (CellOutput, Bytes, Script) = - load_cell_from_path("../../script/testdata/is_even.lib"); -} +static IS_EVEN_LIB: std::sync::LazyLock<(CellOutput, Bytes, Script)> = + std::sync::LazyLock::new(|| load_cell_from_path("../../script/testdata/is_even.lib")); #[doc(hidden)] pub fn is_even_lib() -> &'static (CellOutput, Bytes, Script) { @@ -114,10 +105,8 @@ pub fn is_even_lib() -> &'static (CellOutput, Bytes, Script) { } // from script/testdata without ty_pause -lazy_static! { - static ref LOAD_IS_EVEN: (CellOutput, Bytes, Script) = - load_cell_from_path("vendor/load_is_even_with_snapshot"); -} +static LOAD_IS_EVEN: std::sync::LazyLock<(CellOutput, Bytes, Script)> = + std::sync::LazyLock::new(|| load_cell_from_path("vendor/load_is_even_with_snapshot")); #[doc(hidden)] pub fn load_is_even() -> &'static (CellOutput, Bytes, Script) { diff --git a/util/types/Cargo.toml b/util/types/Cargo.toml index f73489ec43..d73cdb39a1 100644 --- a/util/types/Cargo.toml +++ b/util/types/Cargo.toml @@ -26,8 +26,7 @@ ckb-gen-types = { path = "../gen-types", version = "= 0.119.0-pre" } bit-vec = "0.6.3" ckb-error = { path = "../../error", version = "= 0.119.0-pre" } ckb-rational = { path = "../rational", version = "= 0.119.0-pre" } -once_cell = "1.8.0" -derive_more = { version = "0.99.0", default-features = false, features = [ +derive_more = { version = "1", default-features = false, features = [ "display", ] } ckb-merkle-mountain-range = "0.5.2" diff --git a/util/types/src/core/cell.rs b/util/types/src/core/cell.rs index e5b62499ab..c7be1c4d64 100644 --- a/util/types/src/core/cell.rs +++ b/util/types/src/core/cell.rs @@ -8,10 +8,10 @@ use crate::{ }; use ckb_error::Error; use ckb_occupied_capacity::Result as CapacityResult; -use once_cell::sync::OnceCell; use std::collections::{hash_map::Entry, HashMap, HashSet}; use std::fmt; use std::hash::{BuildHasher, Hash, Hasher}; +use std::sync::OnceLock; /// TODO(doc): @quake #[derive(Debug)] @@ -25,7 +25,7 @@ pub enum ResolvedDep { /// type alias system cells map pub type SystemCellMap = HashMap; /// system cell memory map cache -pub static SYSTEM_CELL: OnceCell = OnceCell::new(); +pub static SYSTEM_CELL: OnceLock = OnceLock::new(); const MAX_DEP_EXPANSION_LIMIT: usize = 2048; diff --git a/util/types/src/global.rs b/util/types/src/global.rs index 9c02d6aac9..ed43a77516 100644 --- a/util/types/src/global.rs +++ b/util/types/src/global.rs @@ -1,7 +1,7 @@ //! Global data, initialized in the launch phase. -use once_cell::sync::OnceCell; use std::path::PathBuf; +use std::sync::OnceLock; /// ckb data directory path, located under root/data, initialized during the launch phase -pub static DATA_DIR: OnceCell = OnceCell::new(); +pub static DATA_DIR: OnceLock = OnceLock::new(); diff --git a/verification/Cargo.toml b/verification/Cargo.toml index c60cb91800..4565967bc4 100644 --- a/verification/Cargo.toml +++ b/verification/Cargo.toml @@ -19,11 +19,15 @@ ckb-chain-spec = { path = "../spec", version = "= 0.119.0-pre" } ckb-dao = { path = "../util/dao", version = "= 0.119.0-pre" } ckb-dao-utils = { path = "../util/dao/utils", version = "= 0.119.0-pre" } ckb-error = { path = "../error", version = "= 0.119.0-pre" } -derive_more = { version = "0.99.0", default-features=false, features = ["display"] } +derive_more = { version = "1", default-features = false, features = [ + "display", +] } ckb-verification-traits = { path = "./traits", version = "= 0.119.0-pre" } tokio = { version = "1", features = ["sync", "process"] } [dev-dependencies] ckb-test-chain-utils = { path = "../util/test-chain-utils", version = "= 0.119.0-pre" } ckb-resource = { path = "../resource", version = "= 0.119.0-pre" } -ckb-systemtime = {path = "../util/systemtime", version = "= 0.119.0-pre", features=["enable_faketime"]} +ckb-systemtime = { path = "../util/systemtime", version = "= 0.119.0-pre", features = [ + "enable_faketime", +] } From 31741d704dc416fb6b5f8bd9403fa87685c1face Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:21:41 +0000 Subject: [PATCH 6/7] chore(deps): bump nix from 0.24.3 to 0.29.0 Bumps [nix](https://github.com/nix-rust/nix) from 0.24.3 to 0.29.0. - [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md) - [Commits](https://github.com/nix-rust/nix/compare/v0.24.3...v0.29.0) --- updated-dependencies: - dependency-name: nix dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 15 ++------------- ckb-bin/Cargo.toml | 2 +- test/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd09682ce5..3f0496519d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ "daemonize", "fdlimit", "is-terminal", - "nix 0.24.3", + "nix", "rayon", "sentry", "serde", @@ -2208,7 +2208,7 @@ version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ - "nix 0.29.0", + "nix", "windows-sys 0.59.0", ] @@ -3728,17 +3728,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - [[package]] name = "nix" version = "0.29.0" diff --git a/ckb-bin/Cargo.toml b/ckb-bin/Cargo.toml index c6be0d57c7..06ff00b712 100644 --- a/ckb-bin/Cargo.toml +++ b/ckb-bin/Cargo.toml @@ -52,7 +52,7 @@ tokio = { version = "1", features = ["sync"] } [target.'cfg(not(target_os="windows"))'.dependencies] daemonize = { version = "0.5.0" } -nix = { version = "0.24.0", default-features = false, features = ["signal"] } +nix = { version = "0.29.0", default-features = false, features = ["signal"] } colored = "2.0" [features] diff --git a/test/Cargo.toml b/test/Cargo.toml index 3ea017891c..ec54004c90 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -44,7 +44,7 @@ ctrlc = { version = "3.1", features = ["termination"] } log = "0.4" [target.'cfg(not(target_os="windows"))'.dependencies] -nix = { version = "0.24.0", default-features = false, features = ["signal"] } +nix = { version = "0.29.0", default-features = false, features = ["signal"] } [target.'cfg(target_os="windows")'.dependencies] windows-sys = { version = "0.52", features = [ From 4101eb37be02c9df912f19877940006ac2881fac Mon Sep 17 00:00:00 2001 From: driftluo Date: Wed, 23 Oct 2024 22:08:09 +0800 Subject: [PATCH 7/7] chore: upgrade axum --- Cargo.lock | 222 ++++++++++++++++++---------------------------- Cargo.toml | 2 +- rpc/Cargo.toml | 7 +- rpc/src/server.rs | 8 +- 4 files changed, 98 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1bfa18325..20245e39fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,19 +223,20 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.6.20" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", - "base64 0.21.7", - "bitflags 1.3.2", + "base64 0.22.1", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.31", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-util", "itoa", "matchit", "memchr", @@ -248,29 +249,34 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tokio", "tokio-tungstenite", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "http 1.1.0", + "http-body", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -1155,7 +1161,7 @@ dependencies = [ "ckb-stop-handler", "ckb-util", "http-body-util", - "hyper 1.5.0", + "hyper", "hyper-util", "prometheus", "tokio", @@ -1206,7 +1212,7 @@ dependencies = [ "eaglesong", "futures", "http-body-util", - "hyper 1.5.0", + "hyper", "hyper-tls", "hyper-util", "indicatif", @@ -1710,7 +1716,7 @@ dependencies = [ "ckb-util", "ckb-verification", "http-body-util", - "hyper 1.5.0", + "hyper", "hyper-util", "lru", "multi_index_map", @@ -1944,9 +1950,9 @@ dependencies = [ [[package]] name = "console-api" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" +checksum = "86ed14aa9c9f927213c6e4f3ef75faaad3406134efe84ba2cb7983431d5f0931" dependencies = [ "futures-core", "prost", @@ -1957,9 +1963,9 @@ dependencies = [ [[package]] name = "console-subscriber" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7481d4c57092cd1c19dd541b92bdce883de840df30aa5d03fd48a3935c01842e" +checksum = "e2e3a111a37f3333946ebf9da370ba5c5577b18eb342ec683eb488dd21980302" dependencies = [ "console-api", "crossbeam-channel", @@ -1967,6 +1973,8 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", + "hyper-util", + "prost", "prost-types", "serde", "serde_json", @@ -2874,25 +2882,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.6.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.6" @@ -3089,17 +3078,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -3119,16 +3097,10 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.1", + "http-body", "pin-project-lite", ] -[[package]] -name = "http-range-header" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" - [[package]] name = "httparse" version = "1.9.5" @@ -3156,30 +3128,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "hyper" -version = "0.14.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.5.0" @@ -3189,9 +3137,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", + "h2", "http 1.1.0", - "http-body 1.0.1", + "http-body", "httparse", "httpdate", "itoa", @@ -3209,7 +3157,7 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.5.0", + "hyper", "hyper-util", "rustls", "rustls-pki-types", @@ -3220,14 +3168,15 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.31", + "hyper", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -3238,7 +3187,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.5.0", + "hyper", "hyper-util", "native-tls", "tokio", @@ -3256,8 +3205,8 @@ dependencies = [ "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.1", - "hyper 1.5.0", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", @@ -3551,9 +3500,9 @@ dependencies = [ [[package]] name = "jsonrpc-utils" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe6601e4eedf0730aebf2ad532cd22c05c67d3cb20105577dd12a5f004abd3b" +checksum = "b70b75b921afd705aef070f0eab39e566031b929433cffa9fc01ea44ce1339d0" dependencies = [ "anyhow", "axum", @@ -4579,9 +4528,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", "prost-derive", @@ -4589,9 +4538,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", "itertools 0.12.1", @@ -4602,9 +4551,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ "prost", ] @@ -4845,11 +4794,11 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.6", + "h2", "http 1.1.0", - "http-body 1.0.1", + "http-body", "http-body-util", - "hyper 1.5.0", + "hyper", "hyper-rustls", "hyper-tls", "hyper-util", @@ -6117,16 +6066,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.4.0" @@ -6172,9 +6111,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", @@ -6220,26 +6159,29 @@ dependencies = [ [[package]] name = "tonic" -version = "0.10.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.7", + "base64 0.22.1", "bytes", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.31", + "h2", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", "prost", + "socket2", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -6266,18 +6208,31 @@ dependencies = [ ] [[package]] -name = "tower-http" -version = "0.3.5" +name = "tower" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ - "bitflags 1.3.2", - "bytes", "futures-core", "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "http-range-header", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +dependencies = [ + "bitflags 2.6.0", + "bytes", + "http 1.1.0", + "http-body", "pin-project-lite", "tokio", "tower-layer", @@ -6398,20 +6353,19 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" dependencies = [ "byteorder", "bytes", "data-encoding", - "http 0.2.12", + "http 1.1.0", "httparse", "log", "rand 0.8.5", "sha1", "thiserror", - "url", "utf-8", ] diff --git a/Cargo.toml b/Cargo.toml index d0fd227a91..2dea28b5b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ ckb-build-info = { path = "util/build-info", version = "= 0.119.0-pre" } [dependencies] ckb-build-info = { path = "util/build-info", version = "= 0.119.0-pre" } ckb-bin = { path = "ckb-bin", version = "= 0.119.0-pre" } -console-subscriber = { version = "0.2.0", optional = true } +console-subscriber = { version = "0.4.0", optional = true } [dev-dependencies] diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 7d1675b21e..d795af7bf6 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -24,7 +24,7 @@ ckb-app-config = { path = "../util/app-config", version = "= 0.119.0-pre" } ckb-constant = { path = "../util/constant", version = "= 0.119.0-pre" } jsonrpc-core = "18.0" serde_json = "1.0" -jsonrpc-utils = { version = "0.2.6", features = ["server", "macros", "axum"] } +jsonrpc-utils = { version = "0.3", features = ["server", "macros", "axum"] } ckb-jsonrpc-types = { path = "../util/jsonrpc-types", version = "= 0.119.0-pre" } ckb-verification = { path = "../verification", version = "= 0.119.0-pre" } ckb-verification-traits = { path = "../verification/traits", version = "= 0.119.0-pre" } @@ -44,14 +44,15 @@ ckb-stop-handler = { path = "../util/stop-handler", version = "= 0.119.0-pre" } itertools.workspace = true tokio = "1" async-trait = "0.1" -axum = "0.6.20" +axum = "0.7" tokio-util = { version = "0.7.3", features = ["codec"] } futures-util = { version = "0.3.21" } -tower-http = { version = "0.3.5", features = ["timeout", "cors"] } +tower-http = { version = "0.6", features = ["timeout", "cors"] } async-stream = "0.3.3" ckb-async-runtime = { path = "../util/runtime", version = "= 0.119.0-pre" } # issue tracking: https://github.com/GREsau/schemars/pull/251 schemars = { version = "0.8.19", package = "ckb_schemars" } + [dev-dependencies] reqwest = { version = "0.12", features = ["blocking", "json"] } serde = { version = "1.0", features = ["derive"] } diff --git a/rpc/src/server.rs b/rpc/src/server.rs index 9388acc091..e32a263a22 100644 --- a/rpc/src/server.rs +++ b/rpc/src/server.rs @@ -128,16 +128,18 @@ impl RpcServer { let (tx_addr, rx_addr) = tokio::sync::oneshot::channel::(); handler.spawn(async move { - let server = axum::Server::bind( + let listener = tokio::net::TcpListener::bind( &address .to_socket_addrs() .expect("config listen_address parsed") .next() .expect("config listen_address parsed"), ) - .serve(app.clone().into_make_service()); + .await + .unwrap(); + let server = axum::serve(listener, app.into_make_service()); - let _ = tx_addr.send(server.local_addr()); + let _ = tx_addr.send(server.local_addr().unwrap()); let graceful = server.with_graceful_shutdown(async move { new_tokio_exit_rx().cancelled().await; });