@ -614,26 +614,46 @@ impl RpcClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> {
|
pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> {
|
||||||
Ok(self
|
let (blockhash, fee_calculator, _last_valid_slot) = self
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::default())?
|
.get_recent_blockhash_with_commitment(CommitmentConfig::default())?
|
||||||
.value)
|
.value;
|
||||||
|
Ok((blockhash, fee_calculator))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_recent_blockhash_with_commitment(
|
pub fn get_recent_blockhash_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
) -> RpcResult<(Hash, FeeCalculator)> {
|
) -> RpcResult<(Hash, FeeCalculator, Slot)> {
|
||||||
let Response {
|
let (context, blockhash, fee_calculator, last_valid_slot) = if let Ok(Response {
|
||||||
|
context,
|
||||||
|
value:
|
||||||
|
RpcFees {
|
||||||
|
blockhash,
|
||||||
|
fee_calculator,
|
||||||
|
last_valid_slot,
|
||||||
|
},
|
||||||
|
}) =
|
||||||
|
self.send::<Response<RpcFees>>(RpcRequest::GetFees, json!([commitment_config]))
|
||||||
|
{
|
||||||
|
(context, blockhash, fee_calculator, last_valid_slot)
|
||||||
|
} else if let Ok(Response {
|
||||||
context,
|
context,
|
||||||
value:
|
value:
|
||||||
RpcBlockhashFeeCalculator {
|
RpcBlockhashFeeCalculator {
|
||||||
blockhash,
|
blockhash,
|
||||||
fee_calculator,
|
fee_calculator,
|
||||||
},
|
},
|
||||||
} = self.send::<Response<RpcBlockhashFeeCalculator>>(
|
}) = self.send::<Response<RpcBlockhashFeeCalculator>>(
|
||||||
RpcRequest::GetRecentBlockhash,
|
RpcRequest::GetRecentBlockhash,
|
||||||
json!([commitment_config]),
|
json!([commitment_config]),
|
||||||
)?;
|
) {
|
||||||
|
(context, blockhash, fee_calculator, 0)
|
||||||
|
} else {
|
||||||
|
return Err(ClientError::new_with_request(
|
||||||
|
RpcError::ParseError("RpcBlockhashFeeCalculator or RpcFees".to_string()).into(),
|
||||||
|
RpcRequest::GetRecentBlockhash,
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
let blockhash = blockhash.parse().map_err(|_| {
|
let blockhash = blockhash.parse().map_err(|_| {
|
||||||
ClientError::new_with_request(
|
ClientError::new_with_request(
|
||||||
@ -643,7 +663,7 @@ impl RpcClient {
|
|||||||
})?;
|
})?;
|
||||||
Ok(Response {
|
Ok(Response {
|
||||||
context,
|
context,
|
||||||
value: (blockhash, fee_calculator),
|
value: (blockhash, fee_calculator, last_valid_slot),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,15 +16,17 @@ pub enum RpcRequest {
|
|||||||
GetConfirmedTransaction,
|
GetConfirmedTransaction,
|
||||||
GetEpochInfo,
|
GetEpochInfo,
|
||||||
GetEpochSchedule,
|
GetEpochSchedule,
|
||||||
|
GetFeeCalculatorForBlockhash,
|
||||||
|
GetFeeRateGovernor,
|
||||||
|
GetFees,
|
||||||
GetGenesisHash,
|
GetGenesisHash,
|
||||||
GetIdentity,
|
GetIdentity,
|
||||||
GetInflation,
|
GetInflation,
|
||||||
GetLargestAccounts,
|
GetLargestAccounts,
|
||||||
GetLeaderSchedule,
|
GetLeaderSchedule,
|
||||||
|
GetMinimumBalanceForRentExemption,
|
||||||
GetProgramAccounts,
|
GetProgramAccounts,
|
||||||
GetRecentBlockhash,
|
GetRecentBlockhash,
|
||||||
GetFeeCalculatorForBlockhash,
|
|
||||||
GetFeeRateGovernor,
|
|
||||||
GetSignatureStatuses,
|
GetSignatureStatuses,
|
||||||
GetSlot,
|
GetSlot,
|
||||||
GetSlotLeader,
|
GetSlotLeader,
|
||||||
@ -37,13 +39,12 @@ pub enum RpcRequest {
|
|||||||
GetTransactionCount,
|
GetTransactionCount,
|
||||||
GetVersion,
|
GetVersion,
|
||||||
GetVoteAccounts,
|
GetVoteAccounts,
|
||||||
|
MinimumLedgerSlot,
|
||||||
RegisterNode,
|
RegisterNode,
|
||||||
RequestAirdrop,
|
RequestAirdrop,
|
||||||
SendTransaction,
|
SendTransaction,
|
||||||
SimulateTransaction,
|
SimulateTransaction,
|
||||||
SignVote,
|
SignVote,
|
||||||
GetMinimumBalanceForRentExemption,
|
|
||||||
MinimumLedgerSlot,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RpcRequest {
|
impl fmt::Display for RpcRequest {
|
||||||
@ -61,15 +62,17 @@ impl fmt::Display for RpcRequest {
|
|||||||
RpcRequest::GetConfirmedTransaction => "getConfirmedTransaction",
|
RpcRequest::GetConfirmedTransaction => "getConfirmedTransaction",
|
||||||
RpcRequest::GetEpochInfo => "getEpochInfo",
|
RpcRequest::GetEpochInfo => "getEpochInfo",
|
||||||
RpcRequest::GetEpochSchedule => "getEpochSchedule",
|
RpcRequest::GetEpochSchedule => "getEpochSchedule",
|
||||||
|
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
|
||||||
|
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
||||||
|
RpcRequest::GetFees => "getFees",
|
||||||
RpcRequest::GetGenesisHash => "getGenesisHash",
|
RpcRequest::GetGenesisHash => "getGenesisHash",
|
||||||
RpcRequest::GetIdentity => "getIdentity",
|
RpcRequest::GetIdentity => "getIdentity",
|
||||||
RpcRequest::GetInflation => "getInflation",
|
RpcRequest::GetInflation => "getInflation",
|
||||||
RpcRequest::GetLargestAccounts => "getLargestAccounts",
|
RpcRequest::GetLargestAccounts => "getLargestAccounts",
|
||||||
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
|
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
|
||||||
|
RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
|
||||||
RpcRequest::GetProgramAccounts => "getProgramAccounts",
|
RpcRequest::GetProgramAccounts => "getProgramAccounts",
|
||||||
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
|
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
|
||||||
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
|
|
||||||
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
|
||||||
RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
|
RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
|
||||||
RpcRequest::GetSlot => "getSlot",
|
RpcRequest::GetSlot => "getSlot",
|
||||||
RpcRequest::GetSlotLeader => "getSlotLeader",
|
RpcRequest::GetSlotLeader => "getSlotLeader",
|
||||||
@ -82,13 +85,12 @@ impl fmt::Display for RpcRequest {
|
|||||||
RpcRequest::GetTransactionCount => "getTransactionCount",
|
RpcRequest::GetTransactionCount => "getTransactionCount",
|
||||||
RpcRequest::GetVersion => "getVersion",
|
RpcRequest::GetVersion => "getVersion",
|
||||||
RpcRequest::GetVoteAccounts => "getVoteAccounts",
|
RpcRequest::GetVoteAccounts => "getVoteAccounts",
|
||||||
|
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
|
||||||
RpcRequest::RegisterNode => "registerNode",
|
RpcRequest::RegisterNode => "registerNode",
|
||||||
RpcRequest::RequestAirdrop => "requestAirdrop",
|
RpcRequest::RequestAirdrop => "requestAirdrop",
|
||||||
RpcRequest::SendTransaction => "sendTransaction",
|
RpcRequest::SendTransaction => "sendTransaction",
|
||||||
RpcRequest::SimulateTransaction => "simulateTransaction",
|
RpcRequest::SimulateTransaction => "simulateTransaction",
|
||||||
RpcRequest::SignVote => "signVote",
|
RpcRequest::SignVote => "signVote",
|
||||||
RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
|
|
||||||
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{}", method)
|
write!(f, "{}", method)
|
||||||
|
@ -35,6 +35,14 @@ pub struct RpcBlockhashFeeCalculator {
|
|||||||
pub fee_calculator: FeeCalculator,
|
pub fee_calculator: FeeCalculator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RpcFees {
|
||||||
|
pub blockhash: String,
|
||||||
|
pub fee_calculator: FeeCalculator,
|
||||||
|
pub last_valid_slot: Slot,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RpcFeeCalculator {
|
pub struct RpcFeeCalculator {
|
||||||
|
@ -441,7 +441,7 @@ impl SyncClient for ThinClient {
|
|||||||
match recent_blockhash {
|
match recent_blockhash {
|
||||||
Ok(Response { value, .. }) => {
|
Ok(Response { value, .. }) => {
|
||||||
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
|
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
|
||||||
Ok(value)
|
Ok((value.0, value.1))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.optimizer.report(index, std::u64::MAX);
|
self.optimizer.report(index, std::u64::MAX);
|
||||||
|
@ -207,6 +207,22 @@ impl JsonRpcRequestProcessor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> {
|
||||||
|
let bank = &*self.bank(commitment)?;
|
||||||
|
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
|
||||||
|
let last_valid_slot = bank
|
||||||
|
.get_blockhash_last_valid_slot(&blockhash)
|
||||||
|
.expect("bank blockhash queue should contain blockhash");
|
||||||
|
new_response(
|
||||||
|
bank,
|
||||||
|
RpcFees {
|
||||||
|
blockhash: blockhash.to_string(),
|
||||||
|
fee_calculator,
|
||||||
|
last_valid_slot,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_fee_calculator_for_blockhash(
|
fn get_fee_calculator_for_blockhash(
|
||||||
&self,
|
&self,
|
||||||
blockhash: &Hash,
|
blockhash: &Hash,
|
||||||
@ -793,6 +809,13 @@ pub trait RpcSol {
|
|||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
) -> RpcResponse<RpcBlockhashFeeCalculator>;
|
) -> RpcResponse<RpcBlockhashFeeCalculator>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getFees")]
|
||||||
|
fn get_fees(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> RpcResponse<RpcFees>;
|
||||||
|
|
||||||
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
|
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
|
||||||
fn get_fee_calculator_for_blockhash(
|
fn get_fee_calculator_for_blockhash(
|
||||||
&self,
|
&self,
|
||||||
@ -1126,6 +1149,15 @@ impl RpcSol for RpcSolImpl {
|
|||||||
.get_recent_blockhash(commitment)
|
.get_recent_blockhash(commitment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_fees(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> RpcResponse<RpcFees> {
|
||||||
|
debug!("get_fees rpc request received");
|
||||||
|
meta.request_processor.read().unwrap().get_fees(commitment)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_fee_calculator_for_blockhash(
|
fn get_fee_calculator_for_blockhash(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
@ -1571,6 +1603,7 @@ pub mod tests {
|
|||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
clock::MAX_RECENT_BLOCKHASHES,
|
||||||
fee_calculator::DEFAULT_BURN_PERCENT,
|
fee_calculator::DEFAULT_BURN_PERCENT,
|
||||||
hash::{hash, Hash},
|
hash::{hash, Hash},
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
@ -2517,6 +2550,38 @@ pub mod tests {
|
|||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rpc_get_fees() {
|
||||||
|
let bob_pubkey = Pubkey::new_rand();
|
||||||
|
let RpcHandler {
|
||||||
|
io,
|
||||||
|
meta,
|
||||||
|
blockhash,
|
||||||
|
..
|
||||||
|
} = start_rpc_handler_with_tx(&bob_pubkey);
|
||||||
|
|
||||||
|
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getFees"}"#;
|
||||||
|
let res = io.handle_request_sync(&req, meta);
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": {
|
||||||
|
"context":{"slot":0},
|
||||||
|
"value":{
|
||||||
|
"blockhash": blockhash.to_string(),
|
||||||
|
"feeCalculator": {
|
||||||
|
"lamportsPerSignature": 0,
|
||||||
|
},
|
||||||
|
"lastValidSlot": MAX_RECENT_BLOCKHASHES,
|
||||||
|
}},
|
||||||
|
"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]
|
#[test]
|
||||||
fn test_rpc_get_fee_calculator_for_blockhash() {
|
fn test_rpc_get_fee_calculator_for_blockhash() {
|
||||||
let bob_pubkey = Pubkey::new_rand();
|
let bob_pubkey = Pubkey::new_rand();
|
||||||
|
@ -27,6 +27,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
|
|||||||
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
|
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
|
||||||
* [getFeeCalculatorForBlockhash](jsonrpc-api.md#getfeecalculatorforblockhash)
|
* [getFeeCalculatorForBlockhash](jsonrpc-api.md#getfeecalculatorforblockhash)
|
||||||
* [getFeeRateGovernor](jsonrpc-api.md#getfeerategovernor)
|
* [getFeeRateGovernor](jsonrpc-api.md#getfeerategovernor)
|
||||||
|
* [getFees](jsonrpc-api.md#getfees)
|
||||||
* [getFirstAvailableBlock](jsonrpc-api.md#getfirstavailableblock)
|
* [getFirstAvailableBlock](jsonrpc-api.md#getfirstavailableblock)
|
||||||
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
|
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
|
||||||
* [getIdentity](jsonrpc-api.md#getidentity)
|
* [getIdentity](jsonrpc-api.md#getidentity)
|
||||||
@ -538,6 +539,34 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
|
|||||||
{"jsonrpc":"2.0","result":{"context":{"slot":54},"value":{"feeRateGovernor":{"burnPercent":50,"maxLamportsPerSignature":100000,"minLamportsPerSignature":5000,"targetLamportsPerSignature":10000,"targetSignaturesPerSlot":20000}}},"id":1}
|
{"jsonrpc":"2.0","result":{"context":{"slot":54},"value":{"feeRateGovernor":{"burnPercent":50,"maxLamportsPerSignature":100000,"minLamportsPerSignature":5000,"targetLamportsPerSignature":10000,"targetSignaturesPerSlot":20000}}},"id":1}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### getFees
|
||||||
|
|
||||||
|
Returns a recent block hash from the ledger, a fee schedule that can be used to
|
||||||
|
compute the cost of submitting a transaction using it, and the last slot in
|
||||||
|
which the blockhash will be valid.
|
||||||
|
|
||||||
|
#### Parameters:
|
||||||
|
|
||||||
|
* `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||||
|
|
||||||
|
#### Results:
|
||||||
|
|
||||||
|
The result will be an RpcResponse JSON object with `value` set to a JSON object with the following fields:
|
||||||
|
|
||||||
|
* `blockhash: <string>` - a Hash as base-58 encoded string
|
||||||
|
* `feeCalculator: <object>` - FeeCalculator object, the fee schedule for this block hash
|
||||||
|
* `lastValidSlot: <u64>` - last slot in which a blockhash will be valid
|
||||||
|
|
||||||
|
#### Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
// Request
|
||||||
|
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getFees"}' http://localhost:8899
|
||||||
|
|
||||||
|
// Result
|
||||||
|
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"blockhash":"CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR","feeCalculator":{lamportsPerSignature":5000},"lastValidSlot":297}},"id":1}
|
||||||
|
```
|
||||||
|
|
||||||
### getFirstAvailableBlock
|
### getFirstAvailableBlock
|
||||||
|
|
||||||
Returns the slot of the lowest confirmed block that has not been purged from the ledger
|
Returns the slot of the lowest confirmed block that has not been purged from the ledger
|
||||||
@ -765,7 +794,7 @@ An RpcResponse containing a JSON object consisting of a string blockhash and Fee
|
|||||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getRecentBlockhash"}' http://localhost:8899
|
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getRecentBlockhash"}' http://localhost:8899
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"blockhash":"CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR","feeCalculator":{"burnPercent":50,"lamportsPerSignature":5000,"maxLamportsPerSignature":100000,"minLamportsPerSignature":5000,"targetLamportsPerSignature":10000,"targetSignaturesPerSlot":20000}}},"id":1}
|
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"blockhash":"CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR","feeCalculator":{"lamportsPerSignature":5000}}},"id":1}
|
||||||
```
|
```
|
||||||
|
|
||||||
### getSignatureStatuses
|
### getSignatureStatuses
|
||||||
|
@ -936,6 +936,15 @@ impl Bank {
|
|||||||
&self.fee_rate_governor
|
&self.fee_rate_governor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_blockhash_last_valid_slot(&self, blockhash: &Hash) -> Option<Slot> {
|
||||||
|
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
||||||
|
// This calculation will need to be updated to consider epoch boundaries if BlockhashQueue
|
||||||
|
// length is made variable by epoch
|
||||||
|
blockhash_queue
|
||||||
|
.get_hash_age(blockhash)
|
||||||
|
.map(|age| self.slot + blockhash_queue.len() as u64 - age)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn confirmed_last_blockhash(&self) -> (Hash, FeeCalculator) {
|
pub fn confirmed_last_blockhash(&self) -> (Hash, FeeCalculator) {
|
||||||
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
||||||
|
|
||||||
|
@ -58,6 +58,12 @@ impl BlockhashQueue {
|
|||||||
.map(|age| self.hash_height - age.hash_height <= max_age as u64)
|
.map(|age| self.hash_height - age.hash_height <= max_age as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
|
||||||
|
self.ages
|
||||||
|
.get(hash)
|
||||||
|
.map(|age| self.hash_height - age.hash_height)
|
||||||
|
}
|
||||||
|
|
||||||
/// check if hash is valid
|
/// check if hash is valid
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn check_hash(&self, hash: Hash) -> bool {
|
pub fn check_hash(&self, hash: Hash) -> bool {
|
||||||
@ -119,6 +125,10 @@ impl BlockhashQueue {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| recent_blockhashes::IterItem(v.hash_height, k, &v.fee_calculator))
|
.map(|(k, v)| recent_blockhashes::IterItem(v.hash_height, k, &v.fee_calculator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.max_age
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
Reference in New Issue
Block a user