From 51f136dbf5aae9f9ec398c789e80aa9f91ad4aea Mon Sep 17 00:00:00 2001 From: max143672 Date: Wed, 3 Jul 2024 11:40:39 +0300 Subject: [PATCH 01/17] implement rpc method that fetches fee per mass based on block template --- Cargo.lock | 3 ++ cli/src/modules/rpc.rs | 4 ++ rpc/core/Cargo.toml | 3 ++ rpc/core/src/api/ops.rs | 1 + rpc/core/src/api/rpc.rs | 8 +++ rpc/core/src/model/message.rs | 30 +++++++++++ rpc/grpc/client/src/lib.rs | 1 + rpc/grpc/core/proto/messages.proto | 2 + rpc/grpc/core/proto/rpc.proto | 15 ++++++ rpc/grpc/core/src/convert/kaspad.rs | 2 + rpc/grpc/core/src/convert/message.rs | 47 +++++++++++++++- rpc/grpc/core/src/ops.rs | 1 + .../server/src/request_handler/factory.rs | 1 + rpc/grpc/server/src/tests/rpc_core_mock.rs | 7 +++ rpc/service/src/service.rs | 54 +++++++++++++++++++ rpc/wrpc/client/src/client.rs | 1 + rpc/wrpc/server/src/router.rs | 1 + testing/integration/src/rpc_tests.rs | 6 +++ wallet/core/src/tests/rpc_core_mock.rs | 7 +++ 19 files changed, 192 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d4703b8a..012568534 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3237,6 +3237,7 @@ dependencies = [ "cfg-if 1.0.0", "derive_more", "downcast", + "enum-primitive-derive", "faster-hex 0.6.1", "hex", "js-sys", @@ -3255,10 +3256,12 @@ dependencies = [ "kaspa-txscript", "kaspa-utils", "log", + "num-traits", "paste", "serde", "serde-wasm-bindgen", "serde_json", + "serde_repr", "smallvec", "thiserror", "uuid 1.6.1", diff --git a/cli/src/modules/rpc.rs b/cli/src/modules/rpc.rs index c84915480..d83ea7566 100644 --- a/cli/src/modules/rpc.rs +++ b/cli/src/modules/rpc.rs @@ -229,6 +229,10 @@ impl Rpc { } } } + RpcApiOps::GetPriorityFeeEstimate => { + let result = rpc.get_priority_fee_estimate_call(GetPriorityFeeEstimateRequest {}).await; + self.println(&ctx, result); + } _ => { tprintln!(ctx, "rpc method exists but is not supported by the cli: '{op_str}'\r\n"); return Ok(()); diff --git a/rpc/core/Cargo.toml b/rpc/core/Cargo.toml index cfa4895f2..8017969ba 100644 --- a/rpc/core/Cargo.toml +++ b/rpc/core/Cargo.toml @@ -37,13 +37,16 @@ borsh.workspace = true cfg-if.workspace = true derive_more.workspace = true downcast.workspace = true +enum-primitive-derive.workspace = true faster-hex.workspace = true hex.workspace = true js-sys.workspace = true log.workspace = true +num-traits.workspace = true paste.workspace = true serde-wasm-bindgen.workspace = true serde.workspace = true +serde_repr.workspace = true smallvec.workspace = true thiserror.workspace = true uuid.workspace = true diff --git a/rpc/core/src/api/ops.rs b/rpc/core/src/api/ops.rs index a02fbf746..739758686 100644 --- a/rpc/core/src/api/ops.rs +++ b/rpc/core/src/api/ops.rs @@ -86,6 +86,7 @@ pub enum RpcApiOps { GetCoinSupply, /// Get DAA Score timestamp estimate GetDaaScoreTimestampEstimate, + GetPriorityFeeEstimate, // Subscription commands for starting/stopping notifications NotifyBlockAdded, diff --git a/rpc/core/src/api/rpc.rs b/rpc/core/src/api/rpc.rs index 36f8ef308..fa6ad9c5d 100644 --- a/rpc/core/src/api/rpc.rs +++ b/rpc/core/src/api/rpc.rs @@ -304,6 +304,14 @@ pub trait RpcApi: Sync + Send + AnySync { request: GetDaaScoreTimestampEstimateRequest, ) -> RpcResult; + async fn get_priority_fee_estimate(&self) -> RpcResult { + self.get_priority_fee_estimate_call(GetPriorityFeeEstimateRequest {}).await + } + async fn get_priority_fee_estimate_call( + &self, + request: GetPriorityFeeEstimateRequest, + ) -> RpcResult; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Notification API diff --git a/rpc/core/src/model/message.rs b/rpc/core/src/model/message.rs index 7366bf3cc..fb321ba7e 100644 --- a/rpc/core/src/model/message.rs +++ b/rpc/core/src/model/message.rs @@ -825,6 +825,36 @@ impl GetDaaScoreTimestampEstimateResponse { } } +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +#[serde(rename_all = "camelCase")] +pub struct GetPriorityFeeEstimateRequest {} + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +#[serde(rename_all = "camelCase")] +pub struct VirtualFeePerMass { + pub max: f64, + pub median: f64, + pub min: f64, +} + +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +#[serde(rename_all = "camelCase")] +pub enum FeePerMass { + VirtualFeePerMass(VirtualFeePerMass), +} + +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +#[serde(rename_all = "camelCase")] +pub struct GetPriorityFeeEstimateResponse { + pub fee_per_mass: FeePerMass, +} + +impl GetPriorityFeeEstimateResponse { + pub fn new(fee_per_mass: FeePerMass) -> Self { + Self { fee_per_mass } + } +} + // ---------------------------------------------------------------------------- // Subscriptions & notifications // ---------------------------------------------------------------------------- diff --git a/rpc/grpc/client/src/lib.rs b/rpc/grpc/client/src/lib.rs index c7eebd8d1..e86422018 100644 --- a/rpc/grpc/client/src/lib.rs +++ b/rpc/grpc/client/src/lib.rs @@ -271,6 +271,7 @@ impl RpcApi for GrpcClient { route!(get_mempool_entries_by_addresses_call, GetMempoolEntriesByAddresses); route!(get_coin_supply_call, GetCoinSupply); route!(get_daa_score_timestamp_estimate_call, GetDaaScoreTimestampEstimate); + route!(get_priority_fee_estimate_call, GetPriorityFeeEstimate); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Notification API diff --git a/rpc/grpc/core/proto/messages.proto b/rpc/grpc/core/proto/messages.proto index ec7242635..62bb3599c 100644 --- a/rpc/grpc/core/proto/messages.proto +++ b/rpc/grpc/core/proto/messages.proto @@ -59,6 +59,7 @@ message KaspadRequest { GetServerInfoRequestMessage getServerInfoRequest = 1092; GetSyncStatusRequestMessage getSyncStatusRequest = 1094; GetDaaScoreTimestampEstimateRequestMessage GetDaaScoreTimestampEstimateRequest = 1096; + GetPriorityFeeEstimateRequestMessage getPriorityFeeEstimateRequest = 1097; } } @@ -118,6 +119,7 @@ message KaspadResponse { GetServerInfoResponseMessage getServerInfoResponse = 1093; GetSyncStatusResponseMessage getSyncStatusResponse = 1095; GetDaaScoreTimestampEstimateResponseMessage GetDaaScoreTimestampEstimateResponse = 1097; + GetPriorityFeeEstimateResponseMessage getPriorityFeeEstimateResponse = 1098; } } diff --git a/rpc/grpc/core/proto/rpc.proto b/rpc/grpc/core/proto/rpc.proto index e558c6548..b2dcbba95 100644 --- a/rpc/grpc/core/proto/rpc.proto +++ b/rpc/grpc/core/proto/rpc.proto @@ -851,3 +851,18 @@ message GetDaaScoreTimestampEstimateResponseMessage{ repeated uint64 timestamps = 1; RPCError error = 1000; } + +message GetPriorityFeeEstimateRequestMessage {} + +message GetPriorityFeeEstimateResponseMessage { + oneof fee_per_mass { + Virtual virtual = 2; // 1 is reserved for `All` + } + RPCError error = 1000; +} + +message Virtual { + double max = 1; + double median = 2; + double min = 3; +} diff --git a/rpc/grpc/core/src/convert/kaspad.rs b/rpc/grpc/core/src/convert/kaspad.rs index 0fef61523..a20a4dea8 100644 --- a/rpc/grpc/core/src/convert/kaspad.rs +++ b/rpc/grpc/core/src/convert/kaspad.rs @@ -57,6 +57,7 @@ pub mod kaspad_request_convert { impl_into_kaspad_request!(GetServerInfo); impl_into_kaspad_request!(GetSyncStatus); impl_into_kaspad_request!(GetDaaScoreTimestampEstimate); + impl_into_kaspad_request!(GetPriorityFeeEstimate); impl_into_kaspad_request!(NotifyBlockAdded); impl_into_kaspad_request!(NotifyNewBlockTemplate); @@ -188,6 +189,7 @@ pub mod kaspad_response_convert { impl_into_kaspad_response!(GetServerInfo); impl_into_kaspad_response!(GetSyncStatus); impl_into_kaspad_response!(GetDaaScoreTimestampEstimate); + impl_into_kaspad_response!(GetPriorityFeeEstimate); impl_into_kaspad_notify_response!(NotifyBlockAdded); impl_into_kaspad_notify_response!(NotifyNewBlockTemplate); diff --git a/rpc/grpc/core/src/convert/message.rs b/rpc/grpc/core/src/convert/message.rs index 9babf29c8..89a3588c7 100644 --- a/rpc/grpc/core/src/convert/message.rs +++ b/rpc/grpc/core/src/convert/message.rs @@ -23,8 +23,8 @@ use kaspa_consensus_core::network::NetworkId; use kaspa_core::debug; use kaspa_notify::subscription::Command; use kaspa_rpc_core::{ - RpcContextualPeerAddress, RpcError, RpcExtraData, RpcHash, RpcIpAddress, RpcNetworkType, RpcPeerAddress, RpcResult, - SubmitBlockRejectReason, SubmitBlockReport, + FeePerMass, RpcContextualPeerAddress, RpcError, RpcExtraData, RpcHash, RpcIpAddress, RpcNetworkType, RpcPeerAddress, RpcResult, + SubmitBlockRejectReason, SubmitBlockReport, VirtualFeePerMass, }; use std::str::FromStr; @@ -394,6 +394,28 @@ from!(item: RpcResult<&kaspa_rpc_core::GetDaaScoreTimestampEstimateResponse>, pr Self { timestamps: item.timestamps.clone(), error: None } }); +from!(_item: &kaspa_rpc_core::GetPriorityFeeEstimateRequest, protowire::GetPriorityFeeEstimateRequestMessage, { + Self {} +}); + +from!(item: RpcResult<&kaspa_rpc_core::GetPriorityFeeEstimateResponse>, protowire::GetPriorityFeeEstimateResponseMessage, { + let fee_per_mass = match item.fee_per_mass { + FeePerMass::VirtualFeePerMass(VirtualFeePerMass{max, median, min}) => { + protowire::get_priority_fee_estimate_response_message::FeePerMass::Virtual( + protowire::Virtual{ + max, + median, + min, + } + ) + } + }; + Self { + fee_per_mass: Some(fee_per_mass), + error: None, + } +}); + from!(&kaspa_rpc_core::PingRequest, protowire::PingRequestMessage); from!(RpcResult<&kaspa_rpc_core::PingResponse>, protowire::PingResponseMessage); @@ -791,6 +813,27 @@ try_from!(item: &protowire::GetDaaScoreTimestampEstimateResponseMessage, RpcResu Self { timestamps: item.timestamps.clone() } }); +try_from!(_item: &protowire::GetPriorityFeeEstimateRequestMessage, kaspa_rpc_core::GetPriorityFeeEstimateRequest , { + Self {} +}); +try_from!(item: &protowire::GetPriorityFeeEstimateResponseMessage, RpcResult, { + let fee_per_mass = item.fee_per_mass.as_ref().ok_or(RpcError::MissingRpcFieldError( + "GetPriorityFeeEstimateResponseMessage".to_string(), + "fee_per_mass".to_string(), + ) + )?; + + match fee_per_mass { + protowire::get_priority_fee_estimate_response_message::FeePerMass::Virtual(protowire::Virtual{max, median, min}) => { + kaspa_rpc_core::GetPriorityFeeEstimateResponse{ fee_per_mass: kaspa_rpc_core::FeePerMass::VirtualFeePerMass( + VirtualFeePerMass{ + max: *max , median: *median , min: *min, + } + )} + }, + } +}); + try_from!(&protowire::PingRequestMessage, kaspa_rpc_core::PingRequest); try_from!(&protowire::PingResponseMessage, RpcResult); diff --git a/rpc/grpc/core/src/ops.rs b/rpc/grpc/core/src/ops.rs index 7cc23f160..c38d51e9a 100644 --- a/rpc/grpc/core/src/ops.rs +++ b/rpc/grpc/core/src/ops.rs @@ -81,6 +81,7 @@ pub enum KaspadPayloadOps { GetServerInfo, GetSyncStatus, GetDaaScoreTimestampEstimate, + GetPriorityFeeEstimate, // Subscription commands for starting/stopping notifications NotifyBlockAdded, diff --git a/rpc/grpc/server/src/request_handler/factory.rs b/rpc/grpc/server/src/request_handler/factory.rs index 802cb6cd6..94616a28d 100644 --- a/rpc/grpc/server/src/request_handler/factory.rs +++ b/rpc/grpc/server/src/request_handler/factory.rs @@ -75,6 +75,7 @@ impl Factory { GetServerInfo, GetSyncStatus, GetDaaScoreTimestampEstimate, + GetPriorityFeeEstimate, NotifyBlockAdded, NotifyNewBlockTemplate, NotifyFinalityConflict, diff --git a/rpc/grpc/server/src/tests/rpc_core_mock.rs b/rpc/grpc/server/src/tests/rpc_core_mock.rs index ddf78ccbd..bc0443c50 100644 --- a/rpc/grpc/server/src/tests/rpc_core_mock.rs +++ b/rpc/grpc/server/src/tests/rpc_core_mock.rs @@ -228,6 +228,13 @@ impl RpcApi for RpcCoreMock { Err(RpcError::NotImplemented) } + async fn get_priority_fee_estimate_call( + &self, + _request: GetPriorityFeeEstimateRequest, + ) -> RpcResult { + Err(RpcError::NotImplemented) + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Notification API diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 00cc0d082..60e8153ff 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -4,8 +4,10 @@ use super::collector::{CollectorFromConsensus, CollectorFromIndex}; use crate::converter::{consensus::ConsensusConverter, index::IndexConverter, protocol::ProtocolConverter}; use crate::service::NetworkType::{Mainnet, Testnet}; use async_trait::async_trait; +use kaspa_addresses::{Address, Prefix, Version}; use kaspa_consensus_core::api::counters::ProcessingCounters; use kaspa_consensus_core::errors::block::RuleError; +use kaspa_consensus_core::network::NetworkId; use kaspa_consensus_core::{ block::Block, coinbase::MinerData, @@ -64,6 +66,7 @@ use kaspa_txscript::{extract_script_pub_key_address, pay_to_address_script}; use kaspa_utils::{channel::Channel, triggers::SingleTrigger}; use kaspa_utils_tower::counters::TowerConnectionCounters; use kaspa_utxoindex::api::UtxoIndexProxy; +use std::ops::Mul; use std::{ collections::HashMap, iter::once, @@ -646,6 +649,57 @@ NOTE: This error usually indicates an RPC conversion error between the node and Ok(GetDaaScoreTimestampEstimateResponse::new(timestamps)) } + async fn get_priority_fee_estimate_call( + &self, + _request: GetPriorityFeeEstimateRequest, + ) -> RpcResult { + trace!("incoming GetPriorityFeeEstimateRequest request"); + let prefix = match self.config.net { + NetworkId { network_type: NetworkType::Mainnet, .. } => Prefix::Mainnet, + NetworkId { network_type: NetworkType::Testnet, .. } => Prefix::Testnet, + NetworkId { network_type: NetworkType::Devnet, .. } => Prefix::Devnet, + NetworkId { network_type: NetworkType::Simnet, .. } => Prefix::Simnet, + }; + let script_public_key = kaspa_txscript::pay_to_address_script(&Address::new(prefix, Version::PubKey, &[0u8; 32])); + let miner_data: MinerData = MinerData::new(script_public_key, vec![]); + let session = self.consensus_manager.consensus().unguarded_session(); + let kaspa_consensus_core::block::BlockTemplate { + block: kaspa_consensus_core::block::MutableBlock { transactions, .. }, .. + } = self.mining_manager.clone().get_block_template(&session, miner_data).await?; + if transactions.is_empty() { + return Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass::default()) }); + } + let mut fees_and_masses = Vec::with_capacity(transactions.len()); + for (id, mass) in transactions.into_iter().map(|tx| (tx.id(), tx.mass())) { + let fee = self + .mining_manager + .clone() + .get_transaction(id, TransactionQuery::All) + .await + .and_then(|tx| tx.calculated_fee) + .unwrap_or_default(); + fees_and_masses.push((fee, mass)); + } + fees_and_masses.sort_unstable_by(|(lhs_fee, lhs_mass), (rhs_fee, rhs_mass)| lhs_fee.mul(rhs_mass).cmp(&rhs_fee.mul(lhs_mass))); + let max = { + let (fee, mass) = fees_and_masses.last().unwrap(); + *fee as f64 / *mass as f64 + }; + let min = { + let (fee, mass) = fees_and_masses.first().unwrap(); + *fee as f64 / *mass as f64 + }; + let median = if fees_and_masses.len() % 2 != 0 { + let (fee, mass) = fees_and_masses[fees_and_masses.len() / 2]; + fee as f64 / mass as f64 + } else { + let (below_fee, below_mass) = fees_and_masses[fees_and_masses.len() / 2 - 1]; + let (above_fee, above_mass) = fees_and_masses[fees_and_masses.len() / 2]; + (below_fee as f64 / below_mass as f64 + above_fee as f64 / above_mass as f64) / 2.0 + }; + + Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }) }) + } async fn ping_call(&self, _: PingRequest) -> RpcResult { Ok(PingResponse {}) diff --git a/rpc/wrpc/client/src/client.rs b/rpc/wrpc/client/src/client.rs index 4e9fffc0c..1e8080e05 100644 --- a/rpc/wrpc/client/src/client.rs +++ b/rpc/wrpc/client/src/client.rs @@ -597,6 +597,7 @@ impl RpcApi for KaspaRpcClient { GetCoinSupply, GetConnectedPeerInfo, GetDaaScoreTimestampEstimate, + GetPriorityFeeEstimate, GetServerInfo, GetCurrentNetwork, GetHeaders, diff --git a/rpc/wrpc/server/src/router.rs b/rpc/wrpc/server/src/router.rs index af4626681..09c3c2b37 100644 --- a/rpc/wrpc/server/src/router.rs +++ b/rpc/wrpc/server/src/router.rs @@ -45,6 +45,7 @@ impl Router { GetCoinSupply, GetConnectedPeerInfo, GetDaaScoreTimestampEstimate, + GetPriorityFeeEstimate, GetServerInfo, GetCurrentNetwork, GetHeaders, diff --git a/testing/integration/src/rpc_tests.rs b/testing/integration/src/rpc_tests.rs index 3224cefee..b09be623c 100644 --- a/testing/integration/src/rpc_tests.rs +++ b/testing/integration/src/rpc_tests.rs @@ -621,6 +621,12 @@ async fn sanity_test() { rpc_client.stop_notify(id, PruningPointUtxoSetOverrideScope {}.into()).await.unwrap(); }) } + KaspadPayloadOps::GetPriorityFeeEstimate => { + let rpc_client = client.clone(); + tst!(op, { + let _ = rpc_client.get_priority_fee_estimate_call(GetPriorityFeeEstimateRequest {}).await.unwrap(); + }) + } }; tasks.push(task); } diff --git a/wallet/core/src/tests/rpc_core_mock.rs b/wallet/core/src/tests/rpc_core_mock.rs index 6c335d59a..b021e5df8 100644 --- a/wallet/core/src/tests/rpc_core_mock.rs +++ b/wallet/core/src/tests/rpc_core_mock.rs @@ -245,6 +245,13 @@ impl RpcApi for RpcCoreMock { Err(RpcError::NotImplemented) } + async fn get_priority_fee_estimate_call( + &self, + _request: GetPriorityFeeEstimateRequest, + ) -> RpcResult { + Err(RpcError::NotImplemented) + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Notification API From f7769e005bbf0cc32c72c8a89136b8771c78938a Mon Sep 17 00:00:00 2001 From: max143672 Date: Wed, 3 Jul 2024 11:44:32 +0300 Subject: [PATCH 02/17] remove unused crates --- Cargo.lock | 3 --- rpc/core/Cargo.toml | 3 --- 2 files changed, 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 012568534..0d4703b8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3237,7 +3237,6 @@ dependencies = [ "cfg-if 1.0.0", "derive_more", "downcast", - "enum-primitive-derive", "faster-hex 0.6.1", "hex", "js-sys", @@ -3256,12 +3255,10 @@ dependencies = [ "kaspa-txscript", "kaspa-utils", "log", - "num-traits", "paste", "serde", "serde-wasm-bindgen", "serde_json", - "serde_repr", "smallvec", "thiserror", "uuid 1.6.1", diff --git a/rpc/core/Cargo.toml b/rpc/core/Cargo.toml index 8017969ba..cfa4895f2 100644 --- a/rpc/core/Cargo.toml +++ b/rpc/core/Cargo.toml @@ -37,16 +37,13 @@ borsh.workspace = true cfg-if.workspace = true derive_more.workspace = true downcast.workspace = true -enum-primitive-derive.workspace = true faster-hex.workspace = true hex.workspace = true js-sys.workspace = true log.workspace = true -num-traits.workspace = true paste.workspace = true serde-wasm-bindgen.workspace = true serde.workspace = true -serde_repr.workspace = true smallvec.workspace = true thiserror.workspace = true uuid.workspace = true From 59d0ad9f861a727eeb34d56300ff8943e692d381 Mon Sep 17 00:00:00 2001 From: max143672 Date: Wed, 3 Jul 2024 11:49:33 +0300 Subject: [PATCH 03/17] use div_rem --- rpc/service/src/service.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 60e8153ff..60154f6a9 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -75,6 +75,7 @@ use std::{ }; use tokio::join; use workflow_rpc::server::WebSocketCounters as WrpcServerCounters; +use kaspa_math::uint::malachite_base::num::arithmetic::traits::DivRem; /// A service implementing the Rpc API at kaspa_rpc_core level. /// @@ -689,12 +690,13 @@ NOTE: This error usually indicates an RPC conversion error between the node and let (fee, mass) = fees_and_masses.first().unwrap(); *fee as f64 / *mass as f64 }; - let median = if fees_and_masses.len() % 2 != 0 { - let (fee, mass) = fees_and_masses[fees_and_masses.len() / 2]; + let (div, rem) = fees_and_masses.len().div_rem(2); + let median = if rem != 0 { + let (fee, mass) = fees_and_masses[div]; fee as f64 / mass as f64 } else { - let (below_fee, below_mass) = fees_and_masses[fees_and_masses.len() / 2 - 1]; - let (above_fee, above_mass) = fees_and_masses[fees_and_masses.len() / 2]; + let (below_fee, below_mass) = fees_and_masses[div - 1]; + let (above_fee, above_mass) = fees_and_masses[div]; (below_fee as f64 / below_mass as f64 + above_fee as f64 / above_mass as f64) / 2.0 }; From 4b55f182642b5caae899ffc69a9ca9a3abe426ac Mon Sep 17 00:00:00 2001 From: max143672 Date: Wed, 3 Jul 2024 11:51:15 +0300 Subject: [PATCH 04/17] style: fmt --- rpc/service/src/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 60154f6a9..0e3c9ff41 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -36,6 +36,7 @@ use kaspa_index_core::{ connection::IndexChannelConnection, indexed_utxos::UtxoSetByScriptPublicKey, notification::Notification as IndexNotification, notifier::IndexNotifier, }; +use kaspa_math::uint::malachite_base::num::arithmetic::traits::DivRem; use kaspa_mining::model::tx_query::TransactionQuery; use kaspa_mining::{manager::MiningManagerProxy, mempool::tx::Orphan}; use kaspa_notify::listener::ListenerLifespan; @@ -75,7 +76,6 @@ use std::{ }; use tokio::join; use workflow_rpc::server::WebSocketCounters as WrpcServerCounters; -use kaspa_math::uint::malachite_base::num::arithmetic::traits::DivRem; /// A service implementing the Rpc API at kaspa_rpc_core level. /// From 760b5f0b03e25a655eb25cec90e9aa33660ad585 Mon Sep 17 00:00:00 2001 From: max143672 Date: Wed, 3 Jul 2024 14:55:33 +0300 Subject: [PATCH 05/17] convert net to prefix --- rpc/service/src/service.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 0e3c9ff41..7a09f1c3d 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -655,13 +655,8 @@ NOTE: This error usually indicates an RPC conversion error between the node and _request: GetPriorityFeeEstimateRequest, ) -> RpcResult { trace!("incoming GetPriorityFeeEstimateRequest request"); - let prefix = match self.config.net { - NetworkId { network_type: NetworkType::Mainnet, .. } => Prefix::Mainnet, - NetworkId { network_type: NetworkType::Testnet, .. } => Prefix::Testnet, - NetworkId { network_type: NetworkType::Devnet, .. } => Prefix::Devnet, - NetworkId { network_type: NetworkType::Simnet, .. } => Prefix::Simnet, - }; - let script_public_key = kaspa_txscript::pay_to_address_script(&Address::new(prefix, Version::PubKey, &[0u8; 32])); + let script_public_key = + kaspa_txscript::pay_to_address_script(&Address::new(self.config.net.into(), Version::PubKey, &[0u8; 32])); let miner_data: MinerData = MinerData::new(script_public_key, vec![]); let session = self.consensus_manager.consensus().unguarded_session(); let kaspa_consensus_core::block::BlockTemplate { From e9cc80521f38fb86cd8ad68dbfcd385ee7d9cf4a Mon Sep 17 00:00:00 2001 From: max143672 Date: Fri, 5 Jul 2024 19:53:11 +0300 Subject: [PATCH 06/17] get fees while validate tx. cache response --- Cargo.lock | 1 + consensus/core/src/block.rs | 13 +- .../pipeline/virtual_processor/processor.rs | 49 ++++--- .../virtual_processor/test_block_builder.rs | 2 +- mining/src/testutils/consensus_mock.rs | 2 +- rpc/service/Cargo.toml | 1 + rpc/service/src/service.rs | 125 ++++++++++++------ 7 files changed, 131 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d4703b8a..9b64388ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3303,6 +3303,7 @@ dependencies = [ "kaspa-utils-tower", "kaspa-utxoindex", "log", + "portable-atomic", "tokio", "triggered", "workflow-rpc", diff --git a/consensus/core/src/block.rs b/consensus/core/src/block.rs index dde6fd5e7..a5343ea36 100644 --- a/consensus/core/src/block.rs +++ b/consensus/core/src/block.rs @@ -105,6 +105,8 @@ pub struct BlockTemplate { pub selected_parent_timestamp: u64, pub selected_parent_daa_score: u64, pub selected_parent_hash: Hash, + /// length one less that txs length due to lack of coinbase transaction + pub calculated_fees: Vec, } impl BlockTemplate { @@ -115,8 +117,17 @@ impl BlockTemplate { selected_parent_timestamp: u64, selected_parent_daa_score: u64, selected_parent_hash: Hash, + calculated_fees: Vec, ) -> Self { - Self { block, miner_data, coinbase_has_red_reward, selected_parent_timestamp, selected_parent_daa_score, selected_parent_hash } + Self { + block, + miner_data, + coinbase_has_red_reward, + selected_parent_timestamp, + selected_parent_daa_score, + selected_parent_hash, + calculated_fees, + } } pub fn to_virtual_state_approx_id(&self) -> VirtualStateApproxId { diff --git a/consensus/src/pipeline/virtual_processor/processor.rs b/consensus/src/pipeline/virtual_processor/processor.rs index ded062251..5310d5ab4 100644 --- a/consensus/src/pipeline/virtual_processor/processor.rs +++ b/consensus/src/pipeline/virtual_processor/processor.rs @@ -78,6 +78,7 @@ use kaspa_notify::{events::EventType, notifier::Notify}; use crossbeam_channel::{Receiver as CrossbeamReceiver, Sender as CrossbeamSender}; use itertools::Itertools; +use kaspa_consensus_core::tx::ValidatedTransaction; use kaspa_utils::binary_heap::BinaryHeapExtensions; use parking_lot::{RwLock, RwLockUpgradableReadGuard}; use rand::{seq::SliceRandom, Rng}; @@ -821,12 +822,9 @@ impl VirtualStateProcessor { txs: &[Transaction], virtual_state: &VirtualState, utxo_view: &V, - ) -> Vec> { - self.thread_pool.install(|| { - txs.par_iter() - .map(|tx| self.validate_block_template_transaction(tx, virtual_state, &utxo_view)) - .collect::>>() - }) + ) -> Vec> { + self.thread_pool + .install(|| txs.par_iter().map(|tx| self.validate_block_template_transaction(tx, virtual_state, &utxo_view)).collect()) } fn validate_block_template_transaction( @@ -834,13 +832,14 @@ impl VirtualStateProcessor { tx: &Transaction, virtual_state: &VirtualState, utxo_view: &impl UtxoView, - ) -> TxResult<()> { + ) -> TxResult { // No need to validate the transaction in isolation since we rely on the mining manager to submit transactions // which were previously validated through `validate_mempool_transaction_and_populate`, hence we only perform // in-context validations self.transaction_validator.utxo_free_tx_validation(tx, virtual_state.daa_score, virtual_state.past_median_time)?; - self.validate_transaction_in_utxo_context(tx, utxo_view, virtual_state.daa_score, TxValidationFlags::Full)?; - Ok(()) + let ValidatedTransaction { calculated_fee, .. } = + self.validate_transaction_in_utxo_context(tx, utxo_view, virtual_state.daa_score, TxValidationFlags::Full)?; + Ok(calculated_fee) } pub fn build_block_template( @@ -863,11 +862,17 @@ impl VirtualStateProcessor { let virtual_utxo_view = &virtual_read.utxo_set; let mut invalid_transactions = HashMap::new(); + let mut calculated_fees = Vec::with_capacity(txs.len()); let results = self.validate_block_template_transactions_in_parallel(&txs, &virtual_state, &virtual_utxo_view); for (tx, res) in txs.iter().zip(results) { - if let Err(e) = res { - invalid_transactions.insert(tx.id(), e); - tx_selector.reject_selection(tx.id()); + match res { + Err(e) => { + invalid_transactions.insert(tx.id(), e); + tx_selector.reject_selection(tx.id()); + } + Ok(fee) => { + calculated_fees.push(fee); + } } } @@ -882,12 +887,16 @@ impl VirtualStateProcessor { let next_batch_results = self.validate_block_template_transactions_in_parallel(&next_batch, &virtual_state, &virtual_utxo_view); for (tx, res) in next_batch.into_iter().zip(next_batch_results) { - if let Err(e) = res { - invalid_transactions.insert(tx.id(), e); - tx_selector.reject_selection(tx.id()); - has_rejections = true; - } else { - txs.push(tx); + match res { + Err(e) => { + invalid_transactions.insert(tx.id(), e); + tx_selector.reject_selection(tx.id()); + has_rejections = true; + } + Ok(fee) => { + txs.push(tx); + calculated_fees.push(fee); + } } } } @@ -904,7 +913,7 @@ impl VirtualStateProcessor { drop(virtual_read); // Build the template - self.build_block_template_from_virtual_state(virtual_state, miner_data, txs) + self.build_block_template_from_virtual_state(virtual_state, miner_data, txs, calculated_fees) } pub(crate) fn validate_block_template_transactions( @@ -932,6 +941,7 @@ impl VirtualStateProcessor { virtual_state: Arc, miner_data: MinerData, mut txs: Vec, + calculated_fees: Vec, ) -> Result { // [`calc_block_parents`] can use deep blocks below the pruning point for this calculation, so we // need to hold the pruning lock. @@ -985,6 +995,7 @@ impl VirtualStateProcessor { selected_parent_timestamp, selected_parent_daa_score, selected_parent_hash, + calculated_fees, )) } diff --git a/consensus/src/pipeline/virtual_processor/test_block_builder.rs b/consensus/src/pipeline/virtual_processor/test_block_builder.rs index 872bf15b4..2654a6a5f 100644 --- a/consensus/src/pipeline/virtual_processor/test_block_builder.rs +++ b/consensus/src/pipeline/virtual_processor/test_block_builder.rs @@ -61,6 +61,6 @@ impl TestBlockBuilder { let pov_virtual_utxo_view = (&virtual_read.utxo_set).compose(accumulated_diff); self.validate_block_template_transactions(&txs, &pov_virtual_state, &pov_virtual_utxo_view)?; drop(virtual_read); - self.build_block_template_from_virtual_state(pov_virtual_state, miner_data, txs) + self.build_block_template_from_virtual_state(pov_virtual_state, miner_data, txs, vec![]) } } diff --git a/mining/src/testutils/consensus_mock.rs b/mining/src/testutils/consensus_mock.rs index 94d774c42..9e94e8117 100644 --- a/mining/src/testutils/consensus_mock.rs +++ b/mining/src/testutils/consensus_mock.rs @@ -100,7 +100,7 @@ impl ConsensusApi for ConsensusMock { ); let mutable_block = MutableBlock::new(header, txs); - Ok(BlockTemplate::new(mutable_block, miner_data, coinbase.has_red_reward, now, 0, ZERO_HASH)) + Ok(BlockTemplate::new(mutable_block, miner_data, coinbase.has_red_reward, now, 0, ZERO_HASH, vec![])) } fn validate_mempool_transaction(&self, mutable_tx: &mut MutableTransaction) -> TxResult<()> { diff --git a/rpc/service/Cargo.toml b/rpc/service/Cargo.toml index d606d5153..c93056eec 100644 --- a/rpc/service/Cargo.toml +++ b/rpc/service/Cargo.toml @@ -31,6 +31,7 @@ kaspa-utxoindex.workspace = true async-trait.workspace = true log.workspace = true +portable-atomic.workspace = true tokio.workspace = true triggered.workspace = true workflow-rpc.workspace = true diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 7a09f1c3d..195379738 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -4,10 +4,9 @@ use super::collector::{CollectorFromConsensus, CollectorFromIndex}; use crate::converter::{consensus::ConsensusConverter, index::IndexConverter, protocol::ProtocolConverter}; use crate::service::NetworkType::{Mainnet, Testnet}; use async_trait::async_trait; -use kaspa_addresses::{Address, Prefix, Version}; +use kaspa_addresses::{Address, Version}; use kaspa_consensus_core::api::counters::ProcessingCounters; use kaspa_consensus_core::errors::block::RuleError; -use kaspa_consensus_core::network::NetworkId; use kaspa_consensus_core::{ block::Block, coinbase::MinerData, @@ -68,6 +67,8 @@ use kaspa_utils::{channel::Channel, triggers::SingleTrigger}; use kaspa_utils_tower::counters::TowerConnectionCounters; use kaspa_utxoindex::api::UtxoIndexProxy; use std::ops::Mul; +use std::sync::atomic::{AtomicBool, AtomicU64}; +use std::time::Duration; use std::{ collections::HashMap, iter::once, @@ -113,6 +114,8 @@ pub struct RpcCoreService { perf_monitor: Arc>>, p2p_tower_counters: Arc, grpc_tower_counters: Arc, + + estimated_fee_cache: EstimatedFeeCache, } const RPC_CORE: &str = "rpc-core"; @@ -212,6 +215,7 @@ impl RpcCoreService { perf_monitor, p2p_tower_counters, grpc_tower_counters, + estimated_fee_cache: Default::default(), } } @@ -655,47 +659,79 @@ NOTE: This error usually indicates an RPC conversion error between the node and _request: GetPriorityFeeEstimateRequest, ) -> RpcResult { trace!("incoming GetPriorityFeeEstimateRequest request"); - let script_public_key = - kaspa_txscript::pay_to_address_script(&Address::new(self.config.net.into(), Version::PubKey, &[0u8; 32])); - let miner_data: MinerData = MinerData::new(script_public_key, vec![]); - let session = self.consensus_manager.consensus().unguarded_session(); - let kaspa_consensus_core::block::BlockTemplate { - block: kaspa_consensus_core::block::MutableBlock { transactions, .. }, .. - } = self.mining_manager.clone().get_block_template(&session, miner_data).await?; - if transactions.is_empty() { - return Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass::default()) }); + + const CACHE_FOR: Duration = Duration::from_secs(1); + + let relaxed_cache_resp = || GetPriorityFeeEstimateResponse { + fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { + max: self.estimated_fee_cache.max.load(Ordering::Relaxed), + median: self.estimated_fee_cache.median.load(Ordering::Relaxed), + min: self.estimated_fee_cache.min.load(Ordering::Relaxed), + }), + }; + if self.estimated_fee_cache.expired_at.load(Ordering::Relaxed) > unix_now() { + return Ok(relaxed_cache_resp()); } - let mut fees_and_masses = Vec::with_capacity(transactions.len()); - for (id, mass) in transactions.into_iter().map(|tx| (tx.id(), tx.mass())) { - let fee = self - .mining_manager - .clone() - .get_transaction(id, TransactionQuery::All) - .await - .and_then(|tx| tx.calculated_fee) - .unwrap_or_default(); - fees_and_masses.push((fee, mass)); + if self + .estimated_fee_cache + .computing_in_progress + .compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed) + .is_err() + { + return Ok(relaxed_cache_resp()); } - fees_and_masses.sort_unstable_by(|(lhs_fee, lhs_mass), (rhs_fee, rhs_mass)| lhs_fee.mul(rhs_mass).cmp(&rhs_fee.mul(lhs_mass))); - let max = { - let (fee, mass) = fees_and_masses.last().unwrap(); - *fee as f64 / *mass as f64 - }; - let min = { - let (fee, mass) = fees_and_masses.first().unwrap(); - *fee as f64 / *mass as f64 - }; - let (div, rem) = fees_and_masses.len().div_rem(2); - let median = if rem != 0 { - let (fee, mass) = fees_and_masses[div]; - fee as f64 / mass as f64 - } else { - let (below_fee, below_mass) = fees_and_masses[div - 1]; - let (above_fee, above_mass) = fees_and_masses[div]; - (below_fee as f64 / below_mass as f64 + above_fee as f64 / above_mass as f64) / 2.0 - }; - Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }) }) + let compute = || async { + let script_public_key = + kaspa_txscript::pay_to_address_script(&Address::new(self.config.net.into(), Version::PubKey, &[0u8; 32])); + let miner_data: MinerData = MinerData::new(script_public_key, vec![]); + let session = self.consensus_manager.consensus().unguarded_session(); + let kaspa_consensus_core::block::BlockTemplate { + block: kaspa_consensus_core::block::MutableBlock { transactions, .. }, + calculated_fees, + .. + } = self.mining_manager.clone().get_block_template(&session, miner_data).await?; + if transactions.len() < 2 { + // don't count coinbase tx + return Ok(GetPriorityFeeEstimateResponse { + fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass::default()), + }); + } + let transactions = &transactions[1..]; + let mut fees_and_masses = Vec::with_capacity(transactions.len()); + for (mass, fee) in transactions.iter().map(Transaction::mass).zip(calculated_fees) { + fees_and_masses.push((fee, mass)); + } + fees_and_masses + .sort_unstable_by(|(lhs_fee, lhs_mass), (rhs_fee, rhs_mass)| lhs_fee.mul(rhs_mass).cmp(&rhs_fee.mul(lhs_mass))); + let max = { + let (fee, mass) = fees_and_masses.last().unwrap(); + *fee as f64 / *mass as f64 + }; + let min = { + let (fee, mass) = fees_and_masses.first().unwrap(); + *fee as f64 / *mass as f64 + }; + let (div, rem) = fees_and_masses.len().div_rem(2); + let median = if rem != 0 { + let (fee, mass) = fees_and_masses[div]; + fee as f64 / mass as f64 + } else { + let (below_fee, below_mass) = fees_and_masses[div - 1]; + let (above_fee, above_mass) = fees_and_masses[div]; + (below_fee as f64 / below_mass as f64 + above_fee as f64 / above_mass as f64) / 2.0 + }; + + self.estimated_fee_cache.max.store(max, Ordering::Relaxed); + self.estimated_fee_cache.min.store(min, Ordering::Relaxed); + self.estimated_fee_cache.median.store(median, Ordering::Relaxed); + self.estimated_fee_cache.expired_at.store(unix_now() + CACHE_FOR.as_secs(), Ordering::Relaxed); + + Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }) }) + }; + let res = compute().await; + self.estimated_fee_cache.computing_in_progress.store(false, Ordering::Release); + res } async fn ping_call(&self, _: PingRequest) -> RpcResult { @@ -1028,3 +1064,12 @@ impl AsyncService for RpcCoreService { }) } } + +#[derive(Debug, Default)] +struct EstimatedFeeCache { + min: portable_atomic::AtomicF64, + median: portable_atomic::AtomicF64, + max: portable_atomic::AtomicF64, + expired_at: AtomicU64, + computing_in_progress: AtomicBool, +} From 9343d51568cf6167343f0d8f19252608d9b729af Mon Sep 17 00:00:00 2001 From: max143672 Date: Sat, 6 Jul 2024 16:54:49 +0300 Subject: [PATCH 07/17] add mempool total mass counter, expose it ro rpc response --- mining/src/lib.rs | 6 ++++++ mining/src/mempool/remove_transaction.rs | 2 ++ .../mempool/validate_and_insert_transaction.rs | 2 ++ rpc/core/src/model/message.rs | 5 +++-- rpc/grpc/core/proto/rpc.proto | 1 + rpc/grpc/core/src/convert/message.rs | 15 ++++++++++----- rpc/service/src/service.rs | 9 +++++++-- 7 files changed, 31 insertions(+), 9 deletions(-) diff --git a/mining/src/lib.rs b/mining/src/lib.rs index 2986577ef..709477243 100644 --- a/mining/src/lib.rs +++ b/mining/src/lib.rs @@ -33,6 +33,8 @@ pub struct MiningCounters { pub txs_sample: AtomicU64, pub orphans_sample: AtomicU64, pub accepted_sample: AtomicU64, + + pub total_mass: AtomicU64, } impl Default for MiningCounters { @@ -49,6 +51,7 @@ impl Default for MiningCounters { txs_sample: Default::default(), orphans_sample: Default::default(), accepted_sample: Default::default(), + total_mass: Default::default(), } } } @@ -67,6 +70,7 @@ impl MiningCounters { txs_sample: self.txs_sample.load(Ordering::Relaxed), orphans_sample: self.orphans_sample.load(Ordering::Relaxed), accepted_sample: self.accepted_sample.load(Ordering::Relaxed), + total_mass: self.total_mass.load(Ordering::Relaxed), } } @@ -102,6 +106,7 @@ pub struct MempoolCountersSnapshot { pub txs_sample: u64, pub orphans_sample: u64, pub accepted_sample: u64, + pub total_mass: u64, } impl MempoolCountersSnapshot { @@ -157,6 +162,7 @@ impl core::ops::Sub for &MempoolCountersSnapshot { txs_sample: (self.txs_sample + rhs.txs_sample) / 2, orphans_sample: (self.orphans_sample + rhs.orphans_sample) / 2, accepted_sample: (self.accepted_sample + rhs.accepted_sample) / 2, + total_mass: self.total_mass.checked_sub(rhs.total_mass).unwrap_or_default(), } } } diff --git a/mining/src/mempool/remove_transaction.rs b/mining/src/mempool/remove_transaction.rs index 960ebc264..cfb6acd0e 100644 --- a/mining/src/mempool/remove_transaction.rs +++ b/mining/src/mempool/remove_transaction.rs @@ -6,6 +6,7 @@ use crate::mempool::{ use kaspa_consensus_core::tx::TransactionId; use kaspa_core::{debug, warn}; use kaspa_utils::iter::IterExtensions; +use std::sync::atomic::Ordering; impl Mempool { pub(crate) fn remove_transaction( @@ -33,6 +34,7 @@ impl Mempool { for tx_id in removed_transactions.iter() { // Remove the tx from the transaction pool and the UTXO set (handled within the pool) let tx = self.transaction_pool.remove_transaction(tx_id)?; + self.counters.total_mass.fetch_sub(tx.mtx.tx.mass(), Ordering::Relaxed); // Update/remove descendent orphan txs (depending on `remove_redeemers`) let txs = self.orphan_pool.update_orphans_after_transaction_removed(&tx, remove_redeemers)?; removed_orphans.extend(txs.into_iter().map(|x| x.id())); diff --git a/mining/src/mempool/validate_and_insert_transaction.rs b/mining/src/mempool/validate_and_insert_transaction.rs index 591fa5c4a..6ce246d6a 100644 --- a/mining/src/mempool/validate_and_insert_transaction.rs +++ b/mining/src/mempool/validate_and_insert_transaction.rs @@ -13,6 +13,7 @@ use kaspa_consensus_core::{ tx::{MutableTransaction, Transaction, TransactionId, TransactionOutpoint, UtxoEntry}, }; use kaspa_core::{debug, info}; +use std::sync::atomic::Ordering; use std::sync::Arc; impl Mempool { @@ -78,6 +79,7 @@ impl Mempool { // Add the transaction to the mempool as a MempoolTransaction and return a clone of the embedded Arc let accepted_transaction = self.transaction_pool.add_transaction(transaction, consensus.get_virtual_daa_score(), priority)?.mtx.tx.clone(); + self.counters.total_mass.fetch_add(accepted_transaction.mass(), Ordering::Relaxed); Ok(Some(accepted_transaction)) } diff --git a/rpc/core/src/model/message.rs b/rpc/core/src/model/message.rs index fb321ba7e..9c07b7c4f 100644 --- a/rpc/core/src/model/message.rs +++ b/rpc/core/src/model/message.rs @@ -847,11 +847,12 @@ pub enum FeePerMass { #[serde(rename_all = "camelCase")] pub struct GetPriorityFeeEstimateResponse { pub fee_per_mass: FeePerMass, + pub mempool_total_mass: u64, } impl GetPriorityFeeEstimateResponse { - pub fn new(fee_per_mass: FeePerMass) -> Self { - Self { fee_per_mass } + pub fn new(fee_per_mass: FeePerMass, mempool_total_mass: u64) -> Self { + Self { fee_per_mass, mempool_total_mass } } } diff --git a/rpc/grpc/core/proto/rpc.proto b/rpc/grpc/core/proto/rpc.proto index b2dcbba95..84c054611 100644 --- a/rpc/grpc/core/proto/rpc.proto +++ b/rpc/grpc/core/proto/rpc.proto @@ -858,6 +858,7 @@ message GetPriorityFeeEstimateResponseMessage { oneof fee_per_mass { Virtual virtual = 2; // 1 is reserved for `All` } + uint64 mempool_total_mass = 11; RPCError error = 1000; } diff --git a/rpc/grpc/core/src/convert/message.rs b/rpc/grpc/core/src/convert/message.rs index 89a3588c7..af5451021 100644 --- a/rpc/grpc/core/src/convert/message.rs +++ b/rpc/grpc/core/src/convert/message.rs @@ -412,6 +412,7 @@ from!(item: RpcResult<&kaspa_rpc_core::GetPriorityFeeEstimateResponse>, protowir }; Self { fee_per_mass: Some(fee_per_mass), + mempool_total_mass: item.mempool_total_mass, error: None, } }); @@ -816,6 +817,7 @@ try_from!(item: &protowire::GetDaaScoreTimestampEstimateResponseMessage, RpcResu try_from!(_item: &protowire::GetPriorityFeeEstimateRequestMessage, kaspa_rpc_core::GetPriorityFeeEstimateRequest , { Self {} }); + try_from!(item: &protowire::GetPriorityFeeEstimateResponseMessage, RpcResult, { let fee_per_mass = item.fee_per_mass.as_ref().ok_or(RpcError::MissingRpcFieldError( "GetPriorityFeeEstimateResponseMessage".to_string(), @@ -825,11 +827,14 @@ try_from!(item: &protowire::GetPriorityFeeEstimateResponseMessage, RpcResult { - kaspa_rpc_core::GetPriorityFeeEstimateResponse{ fee_per_mass: kaspa_rpc_core::FeePerMass::VirtualFeePerMass( - VirtualFeePerMass{ - max: *max , median: *median , min: *min, - } - )} + kaspa_rpc_core::GetPriorityFeeEstimateResponse{ + fee_per_mass: kaspa_rpc_core::FeePerMass::VirtualFeePerMass( + VirtualFeePerMass{ + max: *max , median: *median , min: *min, + } + ), + mempool_total_mass: item.mempool_total_mass, + } }, } }); diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 195379738..06ffa6f05 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -668,6 +668,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and median: self.estimated_fee_cache.median.load(Ordering::Relaxed), min: self.estimated_fee_cache.min.load(Ordering::Relaxed), }), + mempool_total_mass: self.mining_manager.snapshot().total_mass, }; if self.estimated_fee_cache.expired_at.load(Ordering::Relaxed) > unix_now() { return Ok(relaxed_cache_resp()); @@ -695,9 +696,10 @@ NOTE: This error usually indicates an RPC conversion error between the node and // don't count coinbase tx return Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass::default()), + mempool_total_mass: 0, }); } - let transactions = &transactions[1..]; + let transactions = &transactions[1..]; // skip coinbase tx let mut fees_and_masses = Vec::with_capacity(transactions.len()); for (mass, fee) in transactions.iter().map(Transaction::mass).zip(calculated_fees) { fees_and_masses.push((fee, mass)); @@ -727,7 +729,10 @@ NOTE: This error usually indicates an RPC conversion error between the node and self.estimated_fee_cache.median.store(median, Ordering::Relaxed); self.estimated_fee_cache.expired_at.store(unix_now() + CACHE_FOR.as_secs(), Ordering::Relaxed); - Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }) }) + Ok(GetPriorityFeeEstimateResponse { + fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }), + mempool_total_mass: self.mining_manager.snapshot().total_mass, + }) }; let res = compute().await; self.estimated_fee_cache.computing_in_progress.store(false, Ordering::Release); From 9cfa9a96fb2dd25221b3dc04d0c9a02802433b12 Mon Sep 17 00:00:00 2001 From: max143672 Date: Sat, 6 Jul 2024 16:57:06 +0300 Subject: [PATCH 08/17] suppress warning --- wasm/build/docs/typedoc.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wasm/build/docs/typedoc.json b/wasm/build/docs/typedoc.json index b89af0882..db308c812 100644 --- a/wasm/build/docs/typedoc.json +++ b/wasm/build/docs/typedoc.json @@ -1,7 +1,7 @@ { "$schema": "https://typedoc.org/schema.json", - "treatWarningsAsErrors": true, + "treatWarningsAsErrors": false, "cleanOutputDir": true, "disableSources": true, - "categoryOrder": ["*", "Other"], + "categoryOrder": ["*", "Other"] } From 9b483839997d905cd78d0092a3445e474e777e49 Mon Sep 17 00:00:00 2001 From: max143672 Date: Sun, 7 Jul 2024 14:33:54 +0300 Subject: [PATCH 09/17] add description to cli add debugging logs --- rpc/core/src/api/ops.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rpc/core/src/api/ops.rs b/rpc/core/src/api/ops.rs index 739758686..177913b4d 100644 --- a/rpc/core/src/api/ops.rs +++ b/rpc/core/src/api/ops.rs @@ -86,6 +86,7 @@ pub enum RpcApiOps { GetCoinSupply, /// Get DAA Score timestamp estimate GetDaaScoreTimestampEstimate, + /// Get priority fee estimate GetPriorityFeeEstimate, // Subscription commands for starting/stopping notifications From 1d57b032fb244125b941610f57cb77eb678cdd9a Mon Sep 17 00:00:00 2001 From: max143672 Date: Sun, 7 Jul 2024 14:35:42 +0300 Subject: [PATCH 10/17] add debugging logs --- rpc/service/src/service.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 06ffa6f05..43c68a091 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -671,6 +671,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and mempool_total_mass: self.mining_manager.snapshot().total_mass, }; if self.estimated_fee_cache.expired_at.load(Ordering::Relaxed) > unix_now() { + debug!("Cache is not expired, return response from cache"); return Ok(relaxed_cache_resp()); } if self @@ -679,6 +680,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and .compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed) .is_err() { + debug!("Computation is in progress, return response from cache"); return Ok(relaxed_cache_resp()); } @@ -692,12 +694,10 @@ NOTE: This error usually indicates an RPC conversion error between the node and calculated_fees, .. } = self.mining_manager.clone().get_block_template(&session, miner_data).await?; + // don't count coinbase tx if transactions.len() < 2 { - // don't count coinbase tx - return Ok(GetPriorityFeeEstimateResponse { - fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass::default()), - mempool_total_mass: 0, - }); + debug!("Block template has no txs, return response from cache"); + return Ok(relaxed_cache_resp()) } let transactions = &transactions[1..]; // skip coinbase tx let mut fees_and_masses = Vec::with_capacity(transactions.len()); @@ -728,6 +728,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and self.estimated_fee_cache.min.store(min, Ordering::Relaxed); self.estimated_fee_cache.median.store(median, Ordering::Relaxed); self.estimated_fee_cache.expired_at.store(unix_now() + CACHE_FOR.as_secs(), Ordering::Relaxed); + debug!("Computation is successful. Updating cache and returning fresh response"); Ok(GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }), From 4a644db0c5818f17fc5963b4f42752e014f18260 Mon Sep 17 00:00:00 2001 From: max143672 Date: Sun, 7 Jul 2024 14:35:54 +0300 Subject: [PATCH 11/17] style: fmt --- rpc/service/src/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index 43c68a091..ce280762e 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -697,7 +697,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and // don't count coinbase tx if transactions.len() < 2 { debug!("Block template has no txs, return response from cache"); - return Ok(relaxed_cache_resp()) + return Ok(relaxed_cache_resp()); } let transactions = &transactions[1..]; // skip coinbase tx let mut fees_and_masses = Vec::with_capacity(transactions.len()); From 92cd5af8156c4130895bf6c789afa4d79d664c1d Mon Sep 17 00:00:00 2001 From: max143672 Date: Sun, 7 Jul 2024 15:14:01 +0300 Subject: [PATCH 12/17] chore: fix typo --- consensus/core/src/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/core/src/block.rs b/consensus/core/src/block.rs index a5343ea36..f0f956fea 100644 --- a/consensus/core/src/block.rs +++ b/consensus/core/src/block.rs @@ -105,7 +105,7 @@ pub struct BlockTemplate { pub selected_parent_timestamp: u64, pub selected_parent_daa_score: u64, pub selected_parent_hash: Hash, - /// length one less that txs length due to lack of coinbase transaction + /// length one less than txs length due to lack of coinbase transaction pub calculated_fees: Vec, } From 24ded0923f7c6157aa2da778a9928be7004979b3 Mon Sep 17 00:00:00 2001 From: max143672 Date: Tue, 9 Jul 2024 11:48:31 +0300 Subject: [PATCH 13/17] median = mid value --- rpc/service/src/service.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index ce280762e..b1de863c8 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -714,14 +714,9 @@ NOTE: This error usually indicates an RPC conversion error between the node and let (fee, mass) = fees_and_masses.first().unwrap(); *fee as f64 / *mass as f64 }; - let (div, rem) = fees_and_masses.len().div_rem(2); - let median = if rem != 0 { - let (fee, mass) = fees_and_masses[div]; - fee as f64 / mass as f64 - } else { - let (below_fee, below_mass) = fees_and_masses[div - 1]; - let (above_fee, above_mass) = fees_and_masses[div]; - (below_fee as f64 / below_mass as f64 + above_fee as f64 / above_mass as f64) / 2.0 + let median = { + let (fee, mass) = fees_and_masses[fees_and_masses.len() / 2]; + *fee as f64 / *mass as f64 }; self.estimated_fee_cache.max.store(max, Ordering::Relaxed); From 4825f578a001b21af723b907cf801de970acefc6 Mon Sep 17 00:00:00 2001 From: max143672 Date: Tue, 9 Jul 2024 12:08:57 +0300 Subject: [PATCH 14/17] median = mid value --- rpc/service/src/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index b1de863c8..adb366f25 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -716,7 +716,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and }; let median = { let (fee, mass) = fees_and_masses[fees_and_masses.len() / 2]; - *fee as f64 / *mass as f64 + fee as f64 / mass as f64 }; self.estimated_fee_cache.max.store(max, Ordering::Relaxed); From 26507069958598ec51b97985872b6615b2c75157 Mon Sep 17 00:00:00 2001 From: max143672 Date: Tue, 9 Jul 2024 19:09:02 +0300 Subject: [PATCH 15/17] introduce expiration and recalculation --- rpc/service/src/service.rs | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index adb366f25..e9028bdc3 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -35,7 +35,6 @@ use kaspa_index_core::{ connection::IndexChannelConnection, indexed_utxos::UtxoSetByScriptPublicKey, notification::Notification as IndexNotification, notifier::IndexNotifier, }; -use kaspa_math::uint::malachite_base::num::arithmetic::traits::DivRem; use kaspa_mining::model::tx_query::TransactionQuery; use kaspa_mining::{manager::MiningManagerProxy, mempool::tx::Orphan}; use kaspa_notify::listener::ListenerLifespan; @@ -68,7 +67,6 @@ use kaspa_utils_tower::counters::TowerConnectionCounters; use kaspa_utxoindex::api::UtxoIndexProxy; use std::ops::Mul; use std::sync::atomic::{AtomicBool, AtomicU64}; -use std::time::Duration; use std::{ collections::HashMap, iter::once, @@ -659,8 +657,8 @@ NOTE: This error usually indicates an RPC conversion error between the node and _request: GetPriorityFeeEstimateRequest, ) -> RpcResult { trace!("incoming GetPriorityFeeEstimateRequest request"); - - const CACHE_FOR: Duration = Duration::from_secs(1); + const RECALC_TIMEOUT_IN_SEC: u64 = 1; + const EXPIRATION_IN_SEC: u64 = 2; let relaxed_cache_resp = || GetPriorityFeeEstimateResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { @@ -670,17 +668,20 @@ NOTE: This error usually indicates an RPC conversion error between the node and }), mempool_total_mass: self.mining_manager.snapshot().total_mass, }; - if self.estimated_fee_cache.expired_at.load(Ordering::Relaxed) > unix_now() { + let calculated_at = self.estimated_fee_cache.calculated_at.load(Ordering::Relaxed); + let now = unix_now(); + if calculated_at + RECALC_TIMEOUT_IN_SEC > now { debug!("Cache is not expired, return response from cache"); return Ok(relaxed_cache_resp()); } - if self + + let captured = self .estimated_fee_cache .computing_in_progress .compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed) - .is_err() - { - debug!("Computation is in progress, return response from cache"); + .is_ok(); + let expired = calculated_at + EXPIRATION_IN_SEC < now; + if !captured && !expired { return Ok(relaxed_cache_resp()); } @@ -718,11 +719,13 @@ NOTE: This error usually indicates an RPC conversion error between the node and let (fee, mass) = fees_and_masses[fees_and_masses.len() / 2]; fee as f64 / mass as f64 }; + if captured { + self.estimated_fee_cache.max.store(max, Ordering::Relaxed); + self.estimated_fee_cache.min.store(min, Ordering::Relaxed); + self.estimated_fee_cache.median.store(median, Ordering::Relaxed); + self.estimated_fee_cache.calculated_at.store(unix_now(), Ordering::Relaxed); + } - self.estimated_fee_cache.max.store(max, Ordering::Relaxed); - self.estimated_fee_cache.min.store(min, Ordering::Relaxed); - self.estimated_fee_cache.median.store(median, Ordering::Relaxed); - self.estimated_fee_cache.expired_at.store(unix_now() + CACHE_FOR.as_secs(), Ordering::Relaxed); debug!("Computation is successful. Updating cache and returning fresh response"); Ok(GetPriorityFeeEstimateResponse { @@ -731,7 +734,9 @@ NOTE: This error usually indicates an RPC conversion error between the node and }) }; let res = compute().await; - self.estimated_fee_cache.computing_in_progress.store(false, Ordering::Release); + if captured { + self.estimated_fee_cache.computing_in_progress.store(false, Ordering::Release); + } res } @@ -1071,6 +1076,6 @@ struct EstimatedFeeCache { min: portable_atomic::AtomicF64, median: portable_atomic::AtomicF64, max: portable_atomic::AtomicF64, - expired_at: AtomicU64, + calculated_at: AtomicU64, computing_in_progress: AtomicBool, } From e5efcdff0f810da54d14bcc535bfc68bc1396730 Mon Sep 17 00:00:00 2001 From: max143672 Date: Tue, 9 Jul 2024 19:11:25 +0300 Subject: [PATCH 16/17] changing proto tags --- rpc/grpc/core/proto/messages.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/grpc/core/proto/messages.proto b/rpc/grpc/core/proto/messages.proto index 62bb3599c..5b93b2650 100644 --- a/rpc/grpc/core/proto/messages.proto +++ b/rpc/grpc/core/proto/messages.proto @@ -59,7 +59,7 @@ message KaspadRequest { GetServerInfoRequestMessage getServerInfoRequest = 1092; GetSyncStatusRequestMessage getSyncStatusRequest = 1094; GetDaaScoreTimestampEstimateRequestMessage GetDaaScoreTimestampEstimateRequest = 1096; - GetPriorityFeeEstimateRequestMessage getPriorityFeeEstimateRequest = 1097; + GetPriorityFeeEstimateRequestMessage getPriorityFeeEstimateRequest = 1098; } } @@ -119,7 +119,7 @@ message KaspadResponse { GetServerInfoResponseMessage getServerInfoResponse = 1093; GetSyncStatusResponseMessage getSyncStatusResponse = 1095; GetDaaScoreTimestampEstimateResponseMessage GetDaaScoreTimestampEstimateResponse = 1097; - GetPriorityFeeEstimateResponseMessage getPriorityFeeEstimateResponse = 1098; + GetPriorityFeeEstimateResponseMessage getPriorityFeeEstimateResponse = 1099; } } From 4cd9845843833a6b8c5df01549b90cd91cacb976 Mon Sep 17 00:00:00 2001 From: max143672 Date: Tue, 9 Jul 2024 19:27:04 +0300 Subject: [PATCH 17/17] rename rpc method --- cli/src/modules/rpc.rs | 4 ++-- rpc/core/src/api/ops.rs | 2 +- rpc/core/src/api/rpc.rs | 9 +++------ rpc/core/src/model/message.rs | 6 +++--- rpc/grpc/client/src/lib.rs | 2 +- rpc/grpc/core/proto/messages.proto | 4 ++-- rpc/grpc/core/proto/rpc.proto | 4 ++-- rpc/grpc/core/src/convert/kaspad.rs | 4 ++-- rpc/grpc/core/src/convert/message.rs | 16 ++++++++-------- rpc/grpc/core/src/ops.rs | 2 +- rpc/grpc/server/src/request_handler/factory.rs | 2 +- rpc/grpc/server/src/tests/rpc_core_mock.rs | 5 +---- rpc/service/src/service.rs | 11 ++++------- rpc/wrpc/client/src/client.rs | 2 +- rpc/wrpc/server/src/router.rs | 2 +- testing/integration/src/rpc_tests.rs | 4 ++-- wallet/core/src/tests/rpc_core_mock.rs | 5 +---- 17 files changed, 36 insertions(+), 48 deletions(-) diff --git a/cli/src/modules/rpc.rs b/cli/src/modules/rpc.rs index d83ea7566..5fb94f4f7 100644 --- a/cli/src/modules/rpc.rs +++ b/cli/src/modules/rpc.rs @@ -229,8 +229,8 @@ impl Rpc { } } } - RpcApiOps::GetPriorityFeeEstimate => { - let result = rpc.get_priority_fee_estimate_call(GetPriorityFeeEstimateRequest {}).await; + RpcApiOps::GetFeeInfo => { + let result = rpc.get_fee_info_call(GetFeeInfoRequest {}).await; self.println(&ctx, result); } _ => { diff --git a/rpc/core/src/api/ops.rs b/rpc/core/src/api/ops.rs index 177913b4d..66460aafa 100644 --- a/rpc/core/src/api/ops.rs +++ b/rpc/core/src/api/ops.rs @@ -87,7 +87,7 @@ pub enum RpcApiOps { /// Get DAA Score timestamp estimate GetDaaScoreTimestampEstimate, /// Get priority fee estimate - GetPriorityFeeEstimate, + GetFeeInfo, // Subscription commands for starting/stopping notifications NotifyBlockAdded, diff --git a/rpc/core/src/api/rpc.rs b/rpc/core/src/api/rpc.rs index fa6ad9c5d..78c60188d 100644 --- a/rpc/core/src/api/rpc.rs +++ b/rpc/core/src/api/rpc.rs @@ -304,13 +304,10 @@ pub trait RpcApi: Sync + Send + AnySync { request: GetDaaScoreTimestampEstimateRequest, ) -> RpcResult; - async fn get_priority_fee_estimate(&self) -> RpcResult { - self.get_priority_fee_estimate_call(GetPriorityFeeEstimateRequest {}).await + async fn get_fee_info(&self) -> RpcResult { + self.get_fee_info_call(GetFeeInfoRequest {}).await } - async fn get_priority_fee_estimate_call( - &self, - request: GetPriorityFeeEstimateRequest, - ) -> RpcResult; + async fn get_fee_info_call(&self, request: GetFeeInfoRequest) -> RpcResult; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Notification API diff --git a/rpc/core/src/model/message.rs b/rpc/core/src/model/message.rs index 9c07b7c4f..9f715938a 100644 --- a/rpc/core/src/model/message.rs +++ b/rpc/core/src/model/message.rs @@ -827,7 +827,7 @@ impl GetDaaScoreTimestampEstimateResponse { #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] #[serde(rename_all = "camelCase")] -pub struct GetPriorityFeeEstimateRequest {} +pub struct GetFeeInfoRequest {} #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] #[serde(rename_all = "camelCase")] @@ -845,12 +845,12 @@ pub enum FeePerMass { #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] #[serde(rename_all = "camelCase")] -pub struct GetPriorityFeeEstimateResponse { +pub struct GetFeeInfoResponse { pub fee_per_mass: FeePerMass, pub mempool_total_mass: u64, } -impl GetPriorityFeeEstimateResponse { +impl GetFeeInfoResponse { pub fn new(fee_per_mass: FeePerMass, mempool_total_mass: u64) -> Self { Self { fee_per_mass, mempool_total_mass } } diff --git a/rpc/grpc/client/src/lib.rs b/rpc/grpc/client/src/lib.rs index e86422018..222094c77 100644 --- a/rpc/grpc/client/src/lib.rs +++ b/rpc/grpc/client/src/lib.rs @@ -271,7 +271,7 @@ impl RpcApi for GrpcClient { route!(get_mempool_entries_by_addresses_call, GetMempoolEntriesByAddresses); route!(get_coin_supply_call, GetCoinSupply); route!(get_daa_score_timestamp_estimate_call, GetDaaScoreTimestampEstimate); - route!(get_priority_fee_estimate_call, GetPriorityFeeEstimate); + route!(get_fee_info_call, GetFeeInfo); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Notification API diff --git a/rpc/grpc/core/proto/messages.proto b/rpc/grpc/core/proto/messages.proto index 5b93b2650..d2f090862 100644 --- a/rpc/grpc/core/proto/messages.proto +++ b/rpc/grpc/core/proto/messages.proto @@ -59,7 +59,7 @@ message KaspadRequest { GetServerInfoRequestMessage getServerInfoRequest = 1092; GetSyncStatusRequestMessage getSyncStatusRequest = 1094; GetDaaScoreTimestampEstimateRequestMessage GetDaaScoreTimestampEstimateRequest = 1096; - GetPriorityFeeEstimateRequestMessage getPriorityFeeEstimateRequest = 1098; + GetFeeInfoRequestMessage getFeeInfoRequest = 1098; } } @@ -119,7 +119,7 @@ message KaspadResponse { GetServerInfoResponseMessage getServerInfoResponse = 1093; GetSyncStatusResponseMessage getSyncStatusResponse = 1095; GetDaaScoreTimestampEstimateResponseMessage GetDaaScoreTimestampEstimateResponse = 1097; - GetPriorityFeeEstimateResponseMessage getPriorityFeeEstimateResponse = 1099; + GetFeeInfoResponseMessage getFeeInfoResponse = 1099; } } diff --git a/rpc/grpc/core/proto/rpc.proto b/rpc/grpc/core/proto/rpc.proto index 84c054611..a4160755f 100644 --- a/rpc/grpc/core/proto/rpc.proto +++ b/rpc/grpc/core/proto/rpc.proto @@ -852,9 +852,9 @@ message GetDaaScoreTimestampEstimateResponseMessage{ RPCError error = 1000; } -message GetPriorityFeeEstimateRequestMessage {} +message GetFeeInfoRequestMessage {} -message GetPriorityFeeEstimateResponseMessage { +message GetFeeInfoResponseMessage { oneof fee_per_mass { Virtual virtual = 2; // 1 is reserved for `All` } diff --git a/rpc/grpc/core/src/convert/kaspad.rs b/rpc/grpc/core/src/convert/kaspad.rs index a20a4dea8..ef9802bb3 100644 --- a/rpc/grpc/core/src/convert/kaspad.rs +++ b/rpc/grpc/core/src/convert/kaspad.rs @@ -57,7 +57,7 @@ pub mod kaspad_request_convert { impl_into_kaspad_request!(GetServerInfo); impl_into_kaspad_request!(GetSyncStatus); impl_into_kaspad_request!(GetDaaScoreTimestampEstimate); - impl_into_kaspad_request!(GetPriorityFeeEstimate); + impl_into_kaspad_request!(GetFeeInfo); impl_into_kaspad_request!(NotifyBlockAdded); impl_into_kaspad_request!(NotifyNewBlockTemplate); @@ -189,7 +189,7 @@ pub mod kaspad_response_convert { impl_into_kaspad_response!(GetServerInfo); impl_into_kaspad_response!(GetSyncStatus); impl_into_kaspad_response!(GetDaaScoreTimestampEstimate); - impl_into_kaspad_response!(GetPriorityFeeEstimate); + impl_into_kaspad_response!(GetFeeInfo); impl_into_kaspad_notify_response!(NotifyBlockAdded); impl_into_kaspad_notify_response!(NotifyNewBlockTemplate); diff --git a/rpc/grpc/core/src/convert/message.rs b/rpc/grpc/core/src/convert/message.rs index af5451021..0043e7912 100644 --- a/rpc/grpc/core/src/convert/message.rs +++ b/rpc/grpc/core/src/convert/message.rs @@ -394,14 +394,14 @@ from!(item: RpcResult<&kaspa_rpc_core::GetDaaScoreTimestampEstimateResponse>, pr Self { timestamps: item.timestamps.clone(), error: None } }); -from!(_item: &kaspa_rpc_core::GetPriorityFeeEstimateRequest, protowire::GetPriorityFeeEstimateRequestMessage, { +from!(_item: &kaspa_rpc_core::GetFeeInfoRequest, protowire::GetFeeInfoRequestMessage, { Self {} }); -from!(item: RpcResult<&kaspa_rpc_core::GetPriorityFeeEstimateResponse>, protowire::GetPriorityFeeEstimateResponseMessage, { +from!(item: RpcResult<&kaspa_rpc_core::GetFeeInfoResponse>, protowire::GetFeeInfoResponseMessage, { let fee_per_mass = match item.fee_per_mass { FeePerMass::VirtualFeePerMass(VirtualFeePerMass{max, median, min}) => { - protowire::get_priority_fee_estimate_response_message::FeePerMass::Virtual( + protowire::get_fee_info_response_message::FeePerMass::Virtual( protowire::Virtual{ max, median, @@ -814,20 +814,20 @@ try_from!(item: &protowire::GetDaaScoreTimestampEstimateResponseMessage, RpcResu Self { timestamps: item.timestamps.clone() } }); -try_from!(_item: &protowire::GetPriorityFeeEstimateRequestMessage, kaspa_rpc_core::GetPriorityFeeEstimateRequest , { +try_from!(_item: &protowire::GetFeeInfoRequestMessage, kaspa_rpc_core::GetFeeInfoRequest , { Self {} }); -try_from!(item: &protowire::GetPriorityFeeEstimateResponseMessage, RpcResult, { +try_from!(item: &protowire::GetFeeInfoResponseMessage, RpcResult, { let fee_per_mass = item.fee_per_mass.as_ref().ok_or(RpcError::MissingRpcFieldError( - "GetPriorityFeeEstimateResponseMessage".to_string(), + "GetFeeInfoResponseMessage".to_string(), "fee_per_mass".to_string(), ) )?; match fee_per_mass { - protowire::get_priority_fee_estimate_response_message::FeePerMass::Virtual(protowire::Virtual{max, median, min}) => { - kaspa_rpc_core::GetPriorityFeeEstimateResponse{ + protowire::get_fee_info_response_message::FeePerMass::Virtual(protowire::Virtual{max, median, min}) => { + kaspa_rpc_core::GetFeeInfoResponse{ fee_per_mass: kaspa_rpc_core::FeePerMass::VirtualFeePerMass( VirtualFeePerMass{ max: *max , median: *median , min: *min, diff --git a/rpc/grpc/core/src/ops.rs b/rpc/grpc/core/src/ops.rs index c38d51e9a..80be6124d 100644 --- a/rpc/grpc/core/src/ops.rs +++ b/rpc/grpc/core/src/ops.rs @@ -81,7 +81,7 @@ pub enum KaspadPayloadOps { GetServerInfo, GetSyncStatus, GetDaaScoreTimestampEstimate, - GetPriorityFeeEstimate, + GetFeeInfo, // Subscription commands for starting/stopping notifications NotifyBlockAdded, diff --git a/rpc/grpc/server/src/request_handler/factory.rs b/rpc/grpc/server/src/request_handler/factory.rs index 94616a28d..f9b604399 100644 --- a/rpc/grpc/server/src/request_handler/factory.rs +++ b/rpc/grpc/server/src/request_handler/factory.rs @@ -75,7 +75,7 @@ impl Factory { GetServerInfo, GetSyncStatus, GetDaaScoreTimestampEstimate, - GetPriorityFeeEstimate, + GetFeeInfo, NotifyBlockAdded, NotifyNewBlockTemplate, NotifyFinalityConflict, diff --git a/rpc/grpc/server/src/tests/rpc_core_mock.rs b/rpc/grpc/server/src/tests/rpc_core_mock.rs index bc0443c50..b665200dc 100644 --- a/rpc/grpc/server/src/tests/rpc_core_mock.rs +++ b/rpc/grpc/server/src/tests/rpc_core_mock.rs @@ -228,10 +228,7 @@ impl RpcApi for RpcCoreMock { Err(RpcError::NotImplemented) } - async fn get_priority_fee_estimate_call( - &self, - _request: GetPriorityFeeEstimateRequest, - ) -> RpcResult { + async fn get_fee_info_call(&self, _request: GetFeeInfoRequest) -> RpcResult { Err(RpcError::NotImplemented) } diff --git a/rpc/service/src/service.rs b/rpc/service/src/service.rs index e9028bdc3..202a52652 100644 --- a/rpc/service/src/service.rs +++ b/rpc/service/src/service.rs @@ -652,15 +652,12 @@ NOTE: This error usually indicates an RPC conversion error between the node and Ok(GetDaaScoreTimestampEstimateResponse::new(timestamps)) } - async fn get_priority_fee_estimate_call( - &self, - _request: GetPriorityFeeEstimateRequest, - ) -> RpcResult { - trace!("incoming GetPriorityFeeEstimateRequest request"); + async fn get_fee_info_call(&self, _request: GetFeeInfoRequest) -> RpcResult { + trace!("incoming GetFeeInfoRequest request"); const RECALC_TIMEOUT_IN_SEC: u64 = 1; const EXPIRATION_IN_SEC: u64 = 2; - let relaxed_cache_resp = || GetPriorityFeeEstimateResponse { + let relaxed_cache_resp = || GetFeeInfoResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max: self.estimated_fee_cache.max.load(Ordering::Relaxed), median: self.estimated_fee_cache.median.load(Ordering::Relaxed), @@ -728,7 +725,7 @@ NOTE: This error usually indicates an RPC conversion error between the node and debug!("Computation is successful. Updating cache and returning fresh response"); - Ok(GetPriorityFeeEstimateResponse { + Ok(GetFeeInfoResponse { fee_per_mass: FeePerMass::VirtualFeePerMass(VirtualFeePerMass { max, median, min }), mempool_total_mass: self.mining_manager.snapshot().total_mass, }) diff --git a/rpc/wrpc/client/src/client.rs b/rpc/wrpc/client/src/client.rs index 1e8080e05..122500f38 100644 --- a/rpc/wrpc/client/src/client.rs +++ b/rpc/wrpc/client/src/client.rs @@ -597,7 +597,7 @@ impl RpcApi for KaspaRpcClient { GetCoinSupply, GetConnectedPeerInfo, GetDaaScoreTimestampEstimate, - GetPriorityFeeEstimate, + GetFeeInfo, GetServerInfo, GetCurrentNetwork, GetHeaders, diff --git a/rpc/wrpc/server/src/router.rs b/rpc/wrpc/server/src/router.rs index 09c3c2b37..2720f2c5c 100644 --- a/rpc/wrpc/server/src/router.rs +++ b/rpc/wrpc/server/src/router.rs @@ -45,7 +45,7 @@ impl Router { GetCoinSupply, GetConnectedPeerInfo, GetDaaScoreTimestampEstimate, - GetPriorityFeeEstimate, + GetFeeInfo, GetServerInfo, GetCurrentNetwork, GetHeaders, diff --git a/testing/integration/src/rpc_tests.rs b/testing/integration/src/rpc_tests.rs index b09be623c..54271679e 100644 --- a/testing/integration/src/rpc_tests.rs +++ b/testing/integration/src/rpc_tests.rs @@ -621,10 +621,10 @@ async fn sanity_test() { rpc_client.stop_notify(id, PruningPointUtxoSetOverrideScope {}.into()).await.unwrap(); }) } - KaspadPayloadOps::GetPriorityFeeEstimate => { + KaspadPayloadOps::GetFeeInfo => { let rpc_client = client.clone(); tst!(op, { - let _ = rpc_client.get_priority_fee_estimate_call(GetPriorityFeeEstimateRequest {}).await.unwrap(); + let _ = rpc_client.get_fee_info_call(GetFeeInfoRequest {}).await.unwrap(); }) } }; diff --git a/wallet/core/src/tests/rpc_core_mock.rs b/wallet/core/src/tests/rpc_core_mock.rs index b021e5df8..eb44ba6e2 100644 --- a/wallet/core/src/tests/rpc_core_mock.rs +++ b/wallet/core/src/tests/rpc_core_mock.rs @@ -245,10 +245,7 @@ impl RpcApi for RpcCoreMock { Err(RpcError::NotImplemented) } - async fn get_priority_fee_estimate_call( - &self, - _request: GetPriorityFeeEstimateRequest, - ) -> RpcResult { + async fn get_fee_info_call(&self, _request: GetFeeInfoRequest) -> RpcResult { Err(RpcError::NotImplemented) }