Skip to content

Commit 65adcb1

Browse files
authored
feat(rpc)!: add getstandardfee RPC returning the ZIP-317 marginal fee (#10717)
* feat(rpc): add getstandardfee RPC returning the standard fee per logical action Add a parameterless `getstandardfee` JSON-RPC method that returns the recommended standard fee per logical action. This is the static interface placeholder (version 0): it returns the existing ZIP-317 marginal fee (5000 zatoshis, reusing `MARGINAL_FEE` from zip317.rs) so wallets can integrate against a stable method signature now, while a future change replaces the value with a dynamic estimate and increments the version field without altering the result shape. The result object is { standard_fee, version }
1 parent af81798 commit 65adcb1

6 files changed

Lines changed: 79 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ and this project adheres to [Semantic Versioning](https://semver.org).
5757

5858
### Added
5959

60+
- Added the `getstandardfee` RPC, a parameterless method returning the
61+
recommended standard fee per logical action (the ZIP-317 marginal fee, 5000
62+
zatoshis) with a `version` field for future dynamic fee estimation
63+
([#10717](https://github.com/ZcashFoundation/zebra/pull/10717))
6064
- Support for the NU6.3 "Ironwood" shielded pool and v6 transaction format,
6165
activating on Testnet at height 4,134,000. The consensus parameters (v6 version
6266
group ID, consensus branch ID, and Testnet activation height) match

zebra-chain/src/transaction/unmined/zip317.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod tests;
2020
/// The marginal fee for the ZIP-317 fee calculation, in zatoshis per logical action.
2121
//
2222
// TODO: allow Amount<NonNegative> in constants
23-
const MARGINAL_FEE: u64 = 5_000;
23+
pub const MARGINAL_FEE: u64 = 5_000;
2424

2525
/// The number of grace logical actions allowed by the ZIP-317 fee calculation.
2626
const GRACE_ACTIONS: u32 = 2;

zebra-rpc/src/methods.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ use types::{
125125
get_mempool_info::GetMempoolInfoResponse,
126126
get_mining_info::GetMiningInfoResponse,
127127
get_raw_mempool::{self, GetRawMempoolResponse},
128+
get_standard_fee::GetStandardFeeResponse,
128129
long_poll::LongPollInput,
129130
network_info::{GetNetworkInfoResponse, NetworkInfo},
130131
peer_info::PeerInfo,
@@ -647,6 +648,16 @@ pub trait Rpc {
647648
#[method(name = "z_validateaddress")]
648649
async fn z_validate_address(&self, address: String) -> Result<ZValidateAddressResponse>;
649650

651+
/// Returns the recommended standard fee per logical action, in zatoshis.
652+
///
653+
/// Currently returns a static fee with `version` 0; this will be replaced by
654+
/// a dynamic estimate without changing the parameters or result shape.
655+
///
656+
/// method: post
657+
/// tags: wallet
658+
#[method(name = "getstandardfee")]
659+
async fn get_standard_fee(&self) -> Result<GetStandardFeeResponse>;
660+
650661
/// Returns the block subsidy reward of the block at `height`, taking into account the mining slow start.
651662
/// Returns an error if `height` is less than the height of the first halving for the current network.
652663
///
@@ -2858,6 +2869,14 @@ where
28582869
z_validate_address(network, raw_address)
28592870
}
28602871

2872+
async fn get_standard_fee(&self) -> Result<GetStandardFeeResponse> {
2873+
use zebra_chain::transaction::zip317::MARGINAL_FEE;
2874+
2875+
const VERSION: u32 = 0;
2876+
2877+
Ok(GetStandardFeeResponse::new(MARGINAL_FEE, VERSION))
2878+
}
2879+
28612880
async fn get_block_subsidy(&self, height: Option<u32>) -> Result<GetBlockSubsidyResponse> {
28622881
let net = self.network.clone();
28632882

zebra-rpc/src/methods/tests/vectors.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3292,3 +3292,41 @@ async fn rpc_gettxout() {
32923292
let rpc_tx_queue_task_result = rpc_tx_queue.now_or_never();
32933293
assert!(rpc_tx_queue_task_result.is_none());
32943294
}
3295+
3296+
#[tokio::test(flavor = "multi_thread")]
3297+
async fn rpc_get_standard_fee() {
3298+
let _init_guard = zebra_test::init();
3299+
3300+
let mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
3301+
let state: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
3302+
let read_state: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
3303+
3304+
let (tip, _tip_sender) = MockChainTip::new();
3305+
3306+
let (_tx, rx) = tokio::sync::watch::channel(None);
3307+
let (rpc, _rpc_tx_queue) = RpcImpl::new(
3308+
Mainnet,
3309+
Default::default(),
3310+
Default::default(),
3311+
"0.0.1",
3312+
"RPC test",
3313+
Buffer::new(mempool.clone(), 1),
3314+
Buffer::new(state.clone(), 1),
3315+
Buffer::new(read_state.clone(), 1),
3316+
MockService::build().for_unit_tests(),
3317+
MockSyncStatus::default(),
3318+
tip,
3319+
MockAddressBookPeers::default(),
3320+
rx,
3321+
None,
3322+
);
3323+
3324+
let response = rpc
3325+
.get_standard_fee()
3326+
.await
3327+
.expect("get_standard_fee should succeed");
3328+
3329+
// Static v0 placeholder: the ZIP-317 marginal fee and version 0.
3330+
assert_eq!(response.standard_fee(), 5000);
3331+
assert_eq!(response.version(), 0);
3332+
}

zebra-rpc/src/methods/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod get_blockchain_info;
66
pub mod get_mempool_info;
77
pub mod get_mining_info;
88
pub mod get_raw_mempool;
9+
pub mod get_standard_fee;
910
pub mod long_poll;
1011
pub mod network_info;
1112
pub mod peer_info;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//! Types for the `getstandardfee` RPC.
2+
3+
use derive_getters::Getters;
4+
use derive_new::new;
5+
6+
/// A response to a `getstandardfee` RPC request.
7+
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
8+
pub struct GetStandardFeeResponse {
9+
/// Recommended fee per logical action, in zatoshis.
10+
#[getter(copy)]
11+
pub(crate) standard_fee: u64,
12+
13+
/// Estimator version identifier.
14+
#[getter(copy)]
15+
pub(crate) version: u32,
16+
}

0 commit comments

Comments
 (0)