RPC: Add getFeeCalculatorForBlockhash method call (#8687)

Returns the `FeeCalculator` associated with the given blockhash, or
`null` if said blockhash has expired
This commit is contained in:
Trent Nelson
2020-03-06 17:01:31 -07:00
committed by GitHub
parent 3eb00ef60f
commit 4db074a5aa
9 changed files with 184 additions and 6 deletions

View File

@ -9,9 +9,10 @@ use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_client::rpc_response::{
Response, RpcAccount, RpcBlockCommitment, RpcBlockhashFeeCalculator, RpcConfirmedBlock,
RpcContactInfo, RpcEpochInfo, RpcFeeRateGovernor, RpcIdentity, RpcKeyedAccount,
RpcLeaderSchedule, RpcResponseContext, RpcSignatureConfirmation, RpcStorageTurn,
RpcTransactionEncoding, RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
RpcContactInfo, RpcEpochInfo, RpcFeeCalculator, RpcFeeRateGovernor, RpcIdentity,
RpcKeyedAccount, RpcLeaderSchedule, RpcResponseContext, RpcSignatureConfirmation,
RpcStorageTurn, RpcTransactionEncoding, RpcVersionInfo, RpcVoteAccountInfo,
RpcVoteAccountStatus,
};
use solana_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{
@ -33,6 +34,7 @@ use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
use std::{
collections::HashMap,
net::{SocketAddr, UdpSocket},
str::FromStr,
sync::{Arc, RwLock},
thread::sleep,
time::{Duration, Instant},
@ -165,6 +167,18 @@ impl JsonRpcRequestProcessor {
)
}
fn get_fee_calculator_for_blockhash(
&self,
blockhash: &Hash,
) -> RpcResponse<Option<RpcFeeCalculator>> {
let bank = &*self.bank(None);
let fee_calculator = bank.get_fee_calculator(blockhash);
new_response(
bank,
fee_calculator.map(|fee_calculator| RpcFeeCalculator { fee_calculator }),
)
}
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
let bank = &*self.bank(None);
let fee_rate_governor = bank.get_fee_rate_governor();
@ -503,6 +517,13 @@ pub trait RpcSol {
commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator>;
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
fn get_fee_calculator_for_blockhash(
&self,
meta: Self::Metadata,
blockhash: String,
) -> RpcResponse<Option<RpcFeeCalculator>>;
#[rpc(meta, name = "getFeeRateGovernor")]
fn get_fee_rate_governor(&self, meta: Self::Metadata) -> RpcResponse<RpcFeeRateGovernor>;
@ -831,6 +852,20 @@ impl RpcSol for RpcSolImpl {
.get_recent_blockhash(commitment)
}
fn get_fee_calculator_for_blockhash(
&self,
meta: Self::Metadata,
blockhash: String,
) -> RpcResponse<Option<RpcFeeCalculator>> {
debug!("get_fee_calculator_for_blockhash rpc request received");
let blockhash =
Hash::from_str(&blockhash).map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
meta.request_processor
.read()
.unwrap()
.get_fee_calculator_for_blockhash(&blockhash)
}
fn get_fee_rate_governor(&self, meta: Self::Metadata) -> RpcResponse<RpcFeeRateGovernor> {
debug!("get_fee_rate_governor rpc request received");
meta.request_processor
@ -1821,6 +1856,54 @@ pub mod tests {
assert_eq!(expected, result);
}
#[test]
fn test_rpc_get_fee_calculator_for_blockhash() {
let bob_pubkey = Pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
let fee_calculator = RpcFeeCalculator { fee_calculator };
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getFeeCalculatorForBlockhash","params":["{:?}"]}}"#,
blockhash
);
let res = io.handle_request_sync(&req, meta.clone());
let expected = json!({
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":fee_calculator,
},
"id": 1
});
let expected: Response =
serde_json::from_value(expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
assert_eq!(expected, result);
// Expired (non-existent) blockhash
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getFeeCalculatorForBlockhash","params":["{:?}"]}}"#,
Hash::default()
);
let res = io.handle_request_sync(&req, meta.clone());
let expected = json!({
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":Value::Null,
},
"id": 1
});
let expected: Response =
serde_json::from_value(expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
assert_eq!(expected, result);
}
#[test]
fn test_rpc_get_fee_rate_governor() {
let bob_pubkey = Pubkey::new_rand();