RPC: Add minContextSlot param to ensure consistent responses (#25161)

* RPC: Add minContextSlot param to ensure consistent responses

* revert changes to deprecated endpoints

* update docs
This commit is contained in:
Justin Starry 2022-05-17 14:46:02 +08:00 committed by GitHub
parent 4e352bffaf
commit 4690956849
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 391 additions and 195 deletions

View File

@ -144,6 +144,7 @@ fn test_account_subscription() {
commitment: Some(CommitmentConfig::finalized()),
encoding: None,
data_slice: None,
min_context_slot: None,
});
let (mut client, receiver) = PubsubClient::account_subscribe(
&format!("ws://0.0.0.0:{}/", pubsub_addr.port()),

View File

@ -2165,6 +2165,7 @@ impl RpcClient {
RpcEpochConfig {
epoch,
commitment: Some(self.commitment()),
min_context_slot: None,
}
]),
)
@ -3074,6 +3075,7 @@ impl RpcClient {
until: config.until.map(|signature| signature.to_string()),
limit: config.limit,
commitment: config.commitment,
min_context_slot: None,
};
let result: Vec<RpcConfirmedTransactionStatusWithSignature> = self
@ -3726,6 +3728,7 @@ impl RpcClient {
RpcEpochConfig {
epoch,
commitment: Some(self.commitment()),
min_context_slot: None,
}
]),
)
@ -3896,6 +3899,7 @@ impl RpcClient {
encoding: Some(UiAccountEncoding::Base64Zstd),
commitment: Some(self.maybe_map_commitment(commitment_config).await?),
data_slice: None,
min_context_slot: None,
};
self.get_account_with_config(pubkey, config).await
@ -4131,6 +4135,7 @@ impl RpcClient {
encoding: Some(UiAccountEncoding::Base64Zstd),
commitment: Some(self.maybe_map_commitment(commitment_config).await?),
data_slice: None,
min_context_slot: None,
},
)
.await
@ -4469,6 +4474,7 @@ impl RpcClient {
/// length: 5,
/// }),
/// commitment: Some(CommitmentConfig::processed()),
/// min_context_slot: Some(1234),
/// },
/// with_context: Some(false),
/// };
@ -4784,6 +4790,7 @@ impl RpcClient {
encoding: Some(UiAccountEncoding::JsonParsed),
commitment: Some(self.maybe_map_commitment(commitment_config).await?),
data_slice: None,
min_context_slot: None,
};
let response = self
.send(
@ -4886,6 +4893,7 @@ impl RpcClient {
encoding: Some(UiAccountEncoding::JsonParsed),
commitment: Some(self.maybe_map_commitment(commitment_config).await?),
data_slice: None,
min_context_slot: None,
};
self.send(
@ -4927,6 +4935,7 @@ impl RpcClient {
encoding: Some(UiAccountEncoding::JsonParsed),
commitment: Some(self.maybe_map_commitment(commitment_config).await?),
data_slice: None,
min_context_slot: None,
};
self.send(

View File

@ -3691,6 +3691,7 @@ impl RpcClient {
/// length: 5,
/// }),
/// commitment: Some(CommitmentConfig::processed()),
/// min_context_slot: Some(1234),
/// },
/// with_context: Some(false),
/// };

View File

@ -22,6 +22,7 @@ pub struct RpcSendTransactionConfig {
pub preflight_commitment: Option<CommitmentLevel>,
pub encoding: Option<UiTransactionEncoding>,
pub max_retries: Option<usize>,
pub min_context_slot: Option<Slot>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
@ -42,6 +43,7 @@ pub struct RpcSimulateTransactionConfig {
pub commitment: Option<CommitmentConfig>,
pub encoding: Option<UiTransactionEncoding>,
pub accounts: Option<RpcSimulateTransactionAccountsConfig>,
pub min_context_slot: Option<Slot>,
}
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
@ -132,6 +134,7 @@ pub struct RpcEpochConfig {
pub epoch: Option<Epoch>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
pub min_context_slot: Option<Slot>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
@ -141,6 +144,7 @@ pub struct RpcAccountInfoConfig {
pub data_slice: Option<UiDataSliceConfig>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
pub min_context_slot: Option<Slot>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
@ -208,6 +212,7 @@ pub struct RpcSignaturesForAddressConfig {
pub limit: Option<usize>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
pub min_context_slot: Option<Slot>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@ -317,3 +322,11 @@ impl RpcBlocksConfigWrapper {
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcContextConfig {
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
pub min_context_slot: Option<Slot>,
}

View File

@ -22,6 +22,7 @@ pub const JSON_RPC_SCAN_ERROR: i64 = -32012;
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_LEN_MISMATCH: i64 = -32013;
pub const JSON_RPC_SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET: i64 = -32014;
pub const JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION: i64 = -32015;
pub const JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED: i64 = -32016;
#[derive(Error, Debug)]
pub enum RpcCustomError {
@ -61,6 +62,8 @@ pub enum RpcCustomError {
BlockStatusNotAvailableYet { slot: Slot },
#[error("UnsupportedTransactionVersion")]
UnsupportedTransactionVersion(u8),
#[error("MinContextSlotNotReached")]
MinContextSlotNotReached { context_slot: Slot },
}
#[derive(Debug, Serialize, Deserialize)]
@ -69,6 +72,12 @@ pub struct NodeUnhealthyErrorData {
pub num_slots_behind: Option<Slot>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MinContextSlotNotReachedErrorData {
pub context_slot: Slot,
}
impl From<EncodeError> for RpcCustomError {
fn from(err: EncodeError) -> Self {
match err {
@ -188,6 +197,13 @@ impl From<RpcCustomError> for Error {
message: format!("Transaction version ({}) is not supported", version),
data: None,
},
RpcCustomError::MinContextSlotNotReached { context_slot } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED),
message: "Minimum context slot has not been reached".to_string(),
data: Some(serde_json::json!(MinContextSlotNotReachedErrorData {
context_slot,
})),
},
}
}
}

View File

@ -226,15 +226,15 @@ Returns all information associated with the account of provided Pubkey
#### Parameters:
- `<string>` - Pubkey of account to query, as base-58 encoded string
- `<object>` - (optional) Configuration object containing the following optional
fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
"base58" is limited to Account data of less than 129 bytes.
"base64" will return base64 encoded data for Account data of any size.
"base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a parser cannot be found, the field falls back to "base64" encoding, detectable when the `data` field is type `<string>`.
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "base58", "base64" or "base64+zstd" encodings.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -350,7 +350,9 @@ Returns the balance of the account of provided Pubkey
#### Parameters:
- `<string>` - Pubkey of account to query, as base-58 encoded string
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -601,7 +603,9 @@ Returns the current block height of the node
#### Parameters:
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -921,7 +925,9 @@ Returns information about the current epoch
#### Parameters:
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -1351,10 +1357,10 @@ Returns the inflation / staking reward for a list of addresses for an epoch
#### Parameters:
- `<array>` - An array of addresses to query, as base-58 encoded strings
* `<object>` - (optional) Configuration object containing the following optional fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `epoch: <u64>` - An epoch for which the reward occurs. If omitted, the previous epoch will be used
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results
@ -1526,7 +1532,9 @@ Returns the latest blockhash
#### Parameters:
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) (used for retrieving blockhash)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment) (used for retrieving blockhash)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -1738,14 +1746,15 @@ Returns the account information for a list of Pubkeys.
#### Parameters:
- `<array>` - An array of Pubkeys to query, as base-58 encoded strings (up to a maximum of 100).
- `<object>` - (optional) Configuration object containing the following optional fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
"base58" is limited to Account data of less than 129 bytes.
"base64" will return base64 encoded data for Account data of any size.
"base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a parser cannot be found, the field falls back to "base64" encoding, detectable when the `data` field is type `<string>`.
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "base58", "base64" or "base64+zstd" encodings.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -1880,9 +1889,9 @@ Returns all accounts owned by the provided program Pubkey
#### Parameters:
- `<string>` - Pubkey of program, as base-58 encoded string
- `<object>` - (optional) Configuration object containing the following optional fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
"base58" is limited to Account data of less than 129 bytes.
"base64" will return base64 encoded data for Account data of any size.
"base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
@ -1890,6 +1899,7 @@ Returns all accounts owned by the provided program Pubkey
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "base58", "base64" or "base64+zstd" encodings.
- (optional) `filters: <array>` - filter results using up to 4 [filter objects](jsonrpc-api.md#filters); account must meet all filter criteria to be included in results
- (optional) `withContext: bool` - wrap the result in an RpcResponse JSON object.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
##### Filters:
@ -2071,11 +2081,12 @@ provided signature or most recent confirmed block
- `<string>` - account address as base-58 encoded string
- `<object>` - (optional) Configuration object containing the following fields:
- `limit: <number>` - (optional) maximum transaction signatures to return (between 1 and 1,000, default: 1,000).
- `before: <string>` - (optional) start searching backwards from this transaction signature.
- (optional) `limit: <number>` - maximum transaction signatures to return (between 1 and 1,000, default: 1,000).
- (optional) `before: <string>` - start searching backwards from this transaction signature.
If not provided the search starts from the top of the highest max confirmed block.
- `until: <string>` - (optional) search until this transaction signature, if found before limit reached.
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment); "processed" is not supported. If parameter not provided, the default is "finalized".
- (optional) `until: <string>` - search until this transaction signature, if found before limit reached.
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -2258,7 +2269,9 @@ Returns the slot that has reached the [given or default commitment level](jsonrp
#### Parameters:
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -2286,7 +2299,9 @@ Returns the current slot leader
#### Parameters:
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -2367,9 +2382,10 @@ Returns epoch activation information for a stake account
#### Parameters:
- `<string>` - Pubkey of stake account to query, as base-58 encoded string
- `<object>` - (optional) Configuration object containing the following optional fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `epoch: <u64>` - epoch for which to calculate activation details. If parameter not provided, defaults to current epoch.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -2548,11 +2564,15 @@ Returns all SPL Token accounts by approved Delegate.
- `<object>` - Either:
- `mint: <string>` - Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or
- `programId: <string>` - Pubkey of the Token program that owns the accounts, as base-58 encoded string
- `<object>` - (optional) Configuration object containing the following optional fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd" or "jsonParsed".
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a valid mint cannot be found for a particular account, that account will be filtered out from results.
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
"base58" is limited to Account data of less than 129 bytes.
"base64" will return base64 encoded data for Account data of any size.
"base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a parser cannot be found, the field falls back to "base64" encoding, detectable when the `data` field is type `<string>`.
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "base58", "base64" or "base64+zstd" encodings.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -2650,11 +2670,15 @@ Returns all SPL Token accounts by token owner.
- `<object>` - Either:
- `mint: <string>` - Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or
- `programId: <string>` - Pubkey of the Token program that owns the accounts, as base-58 encoded string
- `<object>` - (optional) Configuration object containing the following optional fields:
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd" or "jsonParsed".
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a valid mint cannot be found for a particular account, that account will be filtered out from results.
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `encoding: <string>` - encoding for Account data, either "base58" (_slow_), "base64", "base64+zstd", or "jsonParsed".
"base58" is limited to Account data of less than 129 bytes.
"base64" will return base64 encoded data for Account data of any size.
"base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a parser cannot be found, the field falls back to "base64" encoding, detectable when the `data` field is type `<string>`.
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "base58", "base64" or "base64+zstd" encodings.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -3011,7 +3035,9 @@ Returns the current Transaction count from the ledger
#### Parameters:
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -3189,7 +3215,9 @@ Returns whether a blockhash is still valid or not
#### Parameters:
- `blockhash: <string>` - the blockhash of this block, as base-58 encoded string
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) (used for retrieving blockhash)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment) (used for retrieving blockhash)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -3329,6 +3357,7 @@ submission.
- `encoding: <string>` - (optional) Encoding used for the transaction data. Either `"base58"` (_slow_, **DEPRECATED**), or `"base64"`. (default: `"base58"`).
- `maxRetries: <usize>` - (optional) Maximum number of times for the RPC node to retry sending the transaction to the leader.
If this parameter not provided, the RPC node will retry the transaction until it is finalized or until the blockhash expires.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -3377,6 +3406,7 @@ Simulate sending a transaction
- `encoding: <string>` - (optional) encoding for returned Account data, either "base64" (default), "base64+zstd" or "jsonParsed".
"jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If "jsonParsed" is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`.
- `addresses: <array>` - An array of accounts to return, as base-58 encoded strings
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:
@ -5056,7 +5086,9 @@ Returns the fee calculator associated with the query blockhash, or `null` if the
#### Parameters:
- `<string>` - query blockhash as a Base58 encoded string
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
- `<object>` - (optional) Configuration object containing the following fields:
- (optional) `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results:

View File

@ -121,6 +121,7 @@ fn test_rpc_send_tx() {
encoding: Some(UiAccountEncoding::Base64),
commitment: None,
data_slice: None,
min_context_slot: None,
};
let req = json_req!(
"getAccountInfo",

View File

@ -208,6 +208,23 @@ pub struct JsonRpcRequestProcessor {
impl Metadata for JsonRpcRequestProcessor {}
impl JsonRpcRequestProcessor {
fn get_bank_with_config(&self, config: RpcContextConfig) -> Result<Arc<Bank>> {
let RpcContextConfig {
commitment,
min_context_slot,
} = config;
let bank = self.bank(commitment);
if let Some(min_context_slot) = min_context_slot {
if bank.slot() < min_context_slot {
return Err(RpcCustomError::MinContextSlotNotReached {
context_slot: bank.slot(),
}
.into());
}
}
Ok(bank)
}
#[allow(deprecated)]
fn bank(&self, commitment: Option<CommitmentConfig>) -> Arc<Bank> {
debug!("RPC commitment_config: {:?}", commitment);
@ -374,12 +391,20 @@ impl JsonRpcRequestProcessor {
pubkey: &Pubkey,
config: Option<RpcAccountInfoConfig>,
) -> Result<RpcResponse<Option<UiAccount>>> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, config.data_slice.is_some())?;
let RpcAccountInfoConfig {
encoding,
data_slice,
commitment,
min_context_slot,
} = config.unwrap_or_default();
let bank = self.get_bank_with_config(RpcContextConfig {
commitment,
min_context_slot,
})?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, data_slice.is_some())?;
let response = get_encoded_account(&bank, pubkey, encoding, config.data_slice)?;
let response = get_encoded_account(&bank, pubkey, encoding, data_slice)?;
Ok(new_response(&bank, response))
}
@ -388,14 +413,22 @@ impl JsonRpcRequestProcessor {
pubkeys: Vec<Pubkey>,
config: Option<RpcAccountInfoConfig>,
) -> Result<RpcResponse<Vec<Option<UiAccount>>>> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Base64);
check_slice_and_encoding(&encoding, config.data_slice.is_some())?;
let RpcAccountInfoConfig {
encoding,
data_slice,
commitment,
min_context_slot,
} = config.unwrap_or_default();
let bank = self.get_bank_with_config(RpcContextConfig {
commitment,
min_context_slot,
})?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Base64);
check_slice_and_encoding(&encoding, data_slice.is_some())?;
let accounts = pubkeys
.into_iter()
.map(|pubkey| get_encoded_account(&bank, &pubkey, encoding, config.data_slice))
.map(|pubkey| get_encoded_account(&bank, &pubkey, encoding, data_slice))
.collect::<Result<Vec<_>>>()?;
Ok(new_response(&bank, accounts))
}
@ -416,10 +449,17 @@ impl JsonRpcRequestProcessor {
mut filters: Vec<RpcFilterType>,
with_context: bool,
) -> Result<OptionalContext<Vec<RpcKeyedAccount>>> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
let data_slice_config = config.data_slice;
let RpcAccountInfoConfig {
encoding,
data_slice: data_slice_config,
commitment,
min_context_slot,
} = config.unwrap_or_default();
let bank = self.get_bank_with_config(RpcContextConfig {
commitment,
min_context_slot,
})?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
optimize_filters(&mut filters);
let keyed_accounts = {
@ -460,11 +500,15 @@ impl JsonRpcRequestProcessor {
let config = config.unwrap_or_default();
let epoch_schedule = self.get_epoch_schedule();
let first_available_block = self.get_first_available_block().await;
let epoch = config.epoch.unwrap_or_else(|| {
epoch_schedule
.get_epoch(self.get_slot(config.commitment))
.saturating_sub(1)
});
let epoch = match config.epoch {
Some(epoch) => epoch,
None => epoch_schedule
.get_epoch(self.get_slot(RpcContextConfig {
commitment: config.commitment,
min_context_slot: config.min_context_slot,
})?)
.saturating_sub(1),
};
// Rewards for this epoch are found in the first confirmed block of the next epoch
let first_slot_in_epoch = epoch_schedule.get_first_slot_in_epoch(epoch.saturating_add(1));
@ -573,31 +617,31 @@ impl JsonRpcRequestProcessor {
pub fn get_balance(
&self,
pubkey: &Pubkey,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<u64> {
let bank = self.bank(commitment);
new_response(&bank, bank.get_balance(pubkey))
config: RpcContextConfig,
) -> Result<RpcResponse<u64>> {
let bank = self.get_bank_with_config(config)?;
Ok(new_response(&bank, bank.get_balance(pubkey)))
}
fn get_recent_blockhash(
&self,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator> {
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>> {
let bank = self.bank(commitment);
let blockhash = bank.confirmed_last_blockhash();
let lamports_per_signature = bank
.get_lamports_per_signature_for_blockhash(&blockhash)
.unwrap();
new_response(
Ok(new_response(
&bank,
RpcBlockhashFeeCalculator {
blockhash: blockhash.to_string(),
fee_calculator: FeeCalculator::new(lamports_per_signature),
},
)
))
}
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> {
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> Result<RpcResponse<RpcFees>> {
let bank = self.bank(commitment);
let blockhash = bank.confirmed_last_blockhash();
let lamports_per_signature = bank
@ -610,7 +654,7 @@ impl JsonRpcRequestProcessor {
let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash)
.expect("bank blockhash queue should contain blockhash");
new_response(
Ok(new_response(
&bank,
RpcFees {
blockhash: blockhash.to_string(),
@ -618,22 +662,22 @@ impl JsonRpcRequestProcessor {
last_valid_slot,
last_valid_block_height,
},
)
))
}
fn get_fee_calculator_for_blockhash(
&self,
blockhash: &Hash,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<Option<RpcFeeCalculator>> {
) -> Result<RpcResponse<Option<RpcFeeCalculator>>> {
let bank = self.bank(commitment);
let lamports_per_signature = bank.get_lamports_per_signature_for_blockhash(blockhash);
new_response(
Ok(new_response(
&bank,
lamports_per_signature.map(|lamports_per_signature| RpcFeeCalculator {
fee_calculator: FeeCalculator::new(lamports_per_signature),
}),
)
))
}
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
@ -652,12 +696,12 @@ impl JsonRpcRequestProcessor {
&self,
signature: &Signature,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<bool> {
) -> Result<RpcResponse<bool>> {
let bank = self.bank(commitment);
let status = bank.get_signature_status(signature);
match status {
Some(status) => new_response(&bank, status.is_ok()),
None => new_response(&bank, false),
Some(status) => Ok(new_response(&bank, status.is_ok())),
None => Ok(new_response(&bank, false)),
}
}
@ -671,12 +715,14 @@ impl JsonRpcRequestProcessor {
}
}
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Slot {
self.bank(commitment).slot()
fn get_slot(&self, config: RpcContextConfig) -> Result<Slot> {
let bank = self.get_bank_with_config(config)?;
Ok(bank.slot())
}
fn get_block_height(&self, commitment: Option<CommitmentConfig>) -> u64 {
self.bank(commitment).block_height()
fn get_block_height(&self, config: RpcContextConfig) -> Result<u64> {
let bank = self.get_bank_with_config(config)?;
Ok(bank.block_height())
}
fn get_max_retransmit_slot(&self) -> Slot {
@ -687,8 +733,9 @@ impl JsonRpcRequestProcessor {
self.max_slots.shred_insert.load(Ordering::Relaxed)
}
fn get_slot_leader(&self, commitment: Option<CommitmentConfig>) -> String {
self.bank(commitment).collector_id().to_string()
fn get_slot_leader(&self, config: RpcContextConfig) -> Result<String> {
let bank = self.get_bank_with_config(config)?;
Ok(bank.collector_id().to_string())
}
fn get_slot_leaders(
@ -741,12 +788,14 @@ impl JsonRpcRequestProcessor {
}
}
fn get_transaction_count(&self, commitment: Option<CommitmentConfig>) -> u64 {
self.bank(commitment).transaction_count() as u64
fn get_transaction_count(&self, config: RpcContextConfig) -> Result<u64> {
let bank = self.get_bank_with_config(config)?;
Ok(bank.transaction_count() as u64)
}
fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> u64 {
self.bank(commitment).capitalization()
fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
let bank = self.bank(commitment);
Ok(bank.capitalization())
}
fn get_cached_largest_accounts(
@ -1280,26 +1329,30 @@ impl JsonRpcRequestProcessor {
&self,
signature: Signature,
commitment: Option<CommitmentConfig>,
) -> Option<RpcSignatureConfirmation> {
) -> Result<Option<RpcSignatureConfirmation>> {
let bank = self.bank(commitment);
let transaction_status = self.get_transaction_status(signature, &bank)?;
let confirmations = transaction_status
.confirmations
.unwrap_or(MAX_LOCKOUT_HISTORY + 1);
Some(RpcSignatureConfirmation {
confirmations,
status: transaction_status.status,
})
Ok(self
.get_transaction_status(signature, &bank)
.map(|transaction_status| {
let confirmations = transaction_status
.confirmations
.unwrap_or(MAX_LOCKOUT_HISTORY + 1);
RpcSignatureConfirmation {
confirmations,
status: transaction_status.status,
}
}))
}
pub fn get_signature_status(
&self,
signature: Signature,
commitment: Option<CommitmentConfig>,
) -> Option<transaction::Result<()>> {
) -> Result<Option<transaction::Result<()>>> {
let bank = self.bank(commitment);
let (_, status) = bank.get_signature_status_slot(&signature)?;
Some(status)
Ok(bank
.get_signature_status_slot(&signature)
.map(|(_, status)| status))
}
pub async fn get_signature_statuses(
@ -1500,9 +1553,9 @@ impl JsonRpcRequestProcessor {
before: Option<Signature>,
until: Option<Signature>,
mut limit: usize,
commitment: Option<CommitmentConfig>,
config: RpcContextConfig,
) -> Result<Vec<RpcConfirmedTransactionStatusWithSignature>> {
let commitment = commitment.unwrap_or_default();
let commitment = config.commitment.unwrap_or_default();
check_is_at_least_confirmed(commitment)?;
if self.config.enable_rpc_transaction_history {
@ -1512,9 +1565,16 @@ impl JsonRpcRequestProcessor {
.unwrap()
.highest_confirmed_root();
let highest_slot = if commitment.is_confirmed() {
let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
let confirmed_bank = self.get_bank_with_config(config)?;
confirmed_bank.slot()
} else {
let min_context_slot = config.min_context_slot.unwrap_or_default();
if highest_confirmed_root < min_context_slot {
return Err(RpcCustomError::MinContextSlotNotReached {
context_slot: highest_confirmed_root,
}
.into());
}
highest_confirmed_root
};
@ -1638,7 +1698,10 @@ impl JsonRpcRequestProcessor {
config: Option<RpcEpochConfig>,
) -> Result<RpcStakeActivation> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let bank = self.get_bank_with_config(RpcContextConfig {
commitment: config.commitment,
min_context_slot: config.min_context_slot,
})?;
let epoch = config.epoch.unwrap_or_else(|| bank.epoch());
if bank.epoch().saturating_sub(epoch) > solana_sdk::stake_history::MAX_ENTRIES as u64 {
return Err(Error::invalid_params(format!(
@ -1803,10 +1866,17 @@ impl JsonRpcRequestProcessor {
token_account_filter: TokenAccountsFilter,
config: Option<RpcAccountInfoConfig>,
) -> Result<RpcResponse<Vec<RpcKeyedAccount>>> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
let data_slice_config = config.data_slice;
let RpcAccountInfoConfig {
encoding,
data_slice: data_slice_config,
commitment,
min_context_slot,
} = config.unwrap_or_default();
let bank = self.get_bank_with_config(RpcContextConfig {
commitment,
min_context_slot,
})?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
@ -1848,10 +1918,17 @@ impl JsonRpcRequestProcessor {
token_account_filter: TokenAccountsFilter,
config: Option<RpcAccountInfoConfig>,
) -> Result<RpcResponse<Vec<RpcKeyedAccount>>> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
let data_slice_config = config.data_slice;
let RpcAccountInfoConfig {
encoding,
data_slice: data_slice_config,
commitment,
min_context_slot,
} = config.unwrap_or_default();
let bank = self.get_bank_with_config(RpcContextConfig {
commitment,
min_context_slot,
})?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
@ -2048,42 +2125,39 @@ impl JsonRpcRequestProcessor {
}
}
fn get_latest_blockhash(
&self,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhash> {
let bank = self.bank(commitment);
fn get_latest_blockhash(&self, config: RpcContextConfig) -> Result<RpcResponse<RpcBlockhash>> {
let bank = self.get_bank_with_config(config)?;
let blockhash = bank.last_blockhash();
let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash)
.expect("bank blockhash queue should contain blockhash");
new_response(
Ok(new_response(
&bank,
RpcBlockhash {
blockhash: blockhash.to_string(),
last_valid_block_height,
},
)
))
}
fn is_blockhash_valid(
&self,
blockhash: &Hash,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<bool> {
let bank = self.bank(commitment);
config: RpcContextConfig,
) -> Result<RpcResponse<bool>> {
let bank = self.get_bank_with_config(config)?;
let is_valid = bank.is_blockhash_valid(blockhash);
new_response(&bank, is_valid)
Ok(new_response(&bank, is_valid))
}
fn get_fee_for_message(
&self,
message: &SanitizedMessage,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<Option<u64>> {
let bank = self.bank(commitment);
config: RpcContextConfig,
) -> Result<RpcResponse<Option<u64>>> {
let bank = self.get_bank_with_config(config)?;
let fee = bank.get_fee_for_message(message);
new_response(&bank, fee)
Ok(new_response(&bank, fee))
}
}
@ -2406,14 +2480,14 @@ pub mod rpc_minimal {
&self,
meta: Self::Metadata,
pubkey_str: String,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<u64>>;
#[rpc(meta, name = "getEpochInfo")]
fn get_epoch_info(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<EpochInfo>;
#[rpc(meta, name = "getGenesisHash")]
@ -2426,17 +2500,13 @@ pub mod rpc_minimal {
fn get_identity(&self, meta: Self::Metadata) -> Result<RpcIdentity>;
#[rpc(meta, name = "getSlot")]
fn get_slot(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<Slot>;
fn get_slot(&self, meta: Self::Metadata, config: Option<RpcContextConfig>) -> Result<Slot>;
#[rpc(meta, name = "getBlockHeight")]
fn get_block_height(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<u64>;
#[rpc(meta, name = "getHighestSnapshotSlot")]
@ -2446,7 +2516,7 @@ pub mod rpc_minimal {
fn get_transaction_count(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<u64>;
#[rpc(meta, name = "getVersion")]
@ -2480,20 +2550,20 @@ pub mod rpc_minimal {
&self,
meta: Self::Metadata,
pubkey_str: String,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<u64>> {
debug!("get_balance rpc request received: {:?}", pubkey_str);
let pubkey = verify_pubkey(&pubkey_str)?;
Ok(meta.get_balance(&pubkey, commitment))
meta.get_balance(&pubkey, config.unwrap_or_default())
}
fn get_epoch_info(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<EpochInfo> {
debug!("get_epoch_info rpc request received");
let bank = meta.bank(commitment);
let bank = meta.get_bank_with_config(config.unwrap_or_default())?;
Ok(bank.get_epoch_info())
}
@ -2523,22 +2593,18 @@ pub mod rpc_minimal {
})
}
fn get_slot(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<Slot> {
fn get_slot(&self, meta: Self::Metadata, config: Option<RpcContextConfig>) -> Result<Slot> {
debug!("get_slot rpc request received");
Ok(meta.get_slot(commitment))
meta.get_slot(config.unwrap_or_default())
}
fn get_block_height(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<u64> {
debug!("get_block_height rpc request received");
Ok(meta.get_block_height(commitment))
meta.get_block_height(config.unwrap_or_default())
}
fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo> {
@ -2576,10 +2642,10 @@ pub mod rpc_minimal {
fn get_transaction_count(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<u64> {
debug!("get_transaction_count rpc request received");
Ok(meta.get_transaction_count(commitment))
meta.get_transaction_count(config.unwrap_or_default())
}
fn get_version(&self, _: Self::Metadata) -> Result<RpcVersionInfo> {
@ -2673,7 +2739,7 @@ pub mod rpc_bank {
fn get_slot_leader(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<String>;
#[rpc(meta, name = "getSlotLeaders")]
@ -2734,10 +2800,10 @@ pub mod rpc_bank {
fn get_slot_leader(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<String> {
debug!("get_slot_leader rpc request received");
Ok(meta.get_slot_leader(commitment))
meta.get_slot_leader(config.unwrap_or_default())
}
fn get_slot_leaders(
@ -3279,7 +3345,7 @@ pub mod rpc_full {
fn get_latest_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<RpcBlockhash>>;
#[rpc(meta, name = "isBlockhashValid")]
@ -3287,7 +3353,7 @@ pub mod rpc_full {
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<bool>>;
#[rpc(meta, name = "getFeeForMessage")]
@ -3295,7 +3361,7 @@ pub mod rpc_full {
&self,
meta: Self::Metadata,
data: String,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<Option<u64>>>;
}
@ -3482,8 +3548,14 @@ pub mod rpc_full {
config: Option<RpcSendTransactionConfig>,
) -> Result<String> {
debug!("send_transaction rpc request received");
let config = config.unwrap_or_default();
let tx_encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
let RpcSendTransactionConfig {
skip_preflight,
preflight_commitment,
encoding,
max_retries,
min_context_slot,
} = config.unwrap_or_default();
let tx_encoding = encoding.unwrap_or(UiTransactionEncoding::Base58);
let binary_encoding = tx_encoding.into_binary_encoding().ok_or_else(|| {
Error::invalid_params(format!(
"unsupported encoding: {}. Supported encodings: base58, base64",
@ -3493,10 +3565,13 @@ pub mod rpc_full {
let (wire_transaction, unsanitized_tx) =
decode_and_deserialize::<VersionedTransaction>(data, binary_encoding)?;
let preflight_commitment = config
.preflight_commitment
.map(|commitment| CommitmentConfig { commitment });
let preflight_bank = &*meta.bank(preflight_commitment);
let preflight_commitment =
preflight_commitment.map(|commitment| CommitmentConfig { commitment });
let preflight_bank = &*meta.get_bank_with_config(RpcContextConfig {
commitment: preflight_commitment,
min_context_slot,
})?;
let transaction = sanitize_transaction(unsanitized_tx, preflight_bank)?;
let signature = *transaction.signature();
@ -3520,7 +3595,7 @@ pub mod rpc_full {
preflight_bank.block_height() + MAX_RECENT_BLOCKHASHES as u64;
}
if !config.skip_preflight {
if !skip_preflight {
if let Err(e) = verify_transaction(&transaction, &preflight_bank.feature_set) {
return Err(e);
}
@ -3579,7 +3654,7 @@ pub mod rpc_full {
wire_transaction,
last_valid_block_height,
durable_nonce_info,
config.max_retries,
max_retries,
)
}
@ -3590,8 +3665,15 @@ pub mod rpc_full {
config: Option<RpcSimulateTransactionConfig>,
) -> Result<RpcResponse<RpcSimulateTransactionResult>> {
debug!("simulate_transaction rpc request received");
let config = config.unwrap_or_default();
let tx_encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
let RpcSimulateTransactionConfig {
sig_verify,
replace_recent_blockhash,
commitment,
encoding,
accounts: config_accounts,
min_context_slot,
} = config.unwrap_or_default();
let tx_encoding = encoding.unwrap_or(UiTransactionEncoding::Base58);
let binary_encoding = tx_encoding.into_binary_encoding().ok_or_else(|| {
Error::invalid_params(format!(
"unsupported encoding: {}. Supported encodings: base58, base64",
@ -3601,9 +3683,12 @@ pub mod rpc_full {
let (_, mut unsanitized_tx) =
decode_and_deserialize::<VersionedTransaction>(data, binary_encoding)?;
let bank = &*meta.bank(config.commitment);
if config.replace_recent_blockhash {
if config.sig_verify {
let bank = &*meta.get_bank_with_config(RpcContextConfig {
commitment,
min_context_slot,
})?;
if replace_recent_blockhash {
if sig_verify {
return Err(Error::invalid_params(
"sigVerify may not be used with replaceRecentBlockhash",
));
@ -3614,7 +3699,7 @@ pub mod rpc_full {
}
let transaction = sanitize_transaction(unsanitized_tx, bank)?;
if config.sig_verify {
if sig_verify {
verify_transaction(&transaction, &bank.feature_set)?;
}
let number_of_accounts = transaction.message().account_keys().len();
@ -3627,7 +3712,7 @@ pub mod rpc_full {
return_data,
} = bank.simulate_transaction(transaction);
let accounts = if let Some(config_accounts) = config.accounts {
let accounts = if let Some(config_accounts) = config_accounts {
let accounts_encoding = config_accounts
.encoding
.unwrap_or(UiAccountEncoding::Base64);
@ -3760,20 +3845,30 @@ pub mod rpc_full {
address: String,
config: Option<RpcSignaturesForAddressConfig>,
) -> BoxFuture<Result<Vec<RpcConfirmedTransactionStatusWithSignature>>> {
let config = config.unwrap_or_default();
let commitment = config.commitment;
let verification = verify_and_parse_signatures_for_address_params(
address,
config.before,
config.until,
config.limit,
);
let RpcSignaturesForAddressConfig {
before,
until,
limit,
commitment,
min_context_slot,
} = config.unwrap_or_default();
let verification =
verify_and_parse_signatures_for_address_params(address, before, until, limit);
match verification {
Err(err) => Box::pin(future::err(err)),
Ok((address, before, until, limit)) => Box::pin(async move {
meta.get_signatures_for_address(address, before, until, limit, commitment)
.await
meta.get_signatures_for_address(
address,
before,
until,
limit,
RpcContextConfig {
commitment,
min_context_slot,
},
)
.await
}),
}
}
@ -3810,28 +3905,28 @@ pub mod rpc_full {
fn get_latest_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<RpcBlockhash>> {
debug!("get_latest_blockhash rpc request received");
Ok(meta.get_latest_blockhash(commitment))
meta.get_latest_blockhash(config.unwrap_or_default())
}
fn is_blockhash_valid(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<bool>> {
let blockhash = Hash::from_str(&blockhash)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
Ok(meta.is_blockhash_valid(&blockhash, commitment))
meta.is_blockhash_valid(&blockhash, config.unwrap_or_default())
}
fn get_fee_for_message(
&self,
meta: Self::Metadata,
data: String,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<Option<u64>>> {
debug!("get_fee_for_message rpc request received");
let (_, message) =
@ -3839,7 +3934,7 @@ pub mod rpc_full {
let sanitized_message = SanitizedMessage::try_from(message).map_err(|err| {
Error::invalid_params(format!("invalid transaction message: {}", err))
})?;
Ok(meta.get_fee_for_message(&sanitized_message, commitment))
meta.get_fee_for_message(&sanitized_message, config.unwrap_or_default())
}
}
}
@ -3894,7 +3989,7 @@ pub mod rpc_deprecated_v1_9 {
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>> {
debug!("get_recent_blockhash rpc request received");
Ok(meta.get_recent_blockhash(commitment))
meta.get_recent_blockhash(commitment)
}
fn get_fees(
@ -3903,7 +3998,7 @@ pub mod rpc_deprecated_v1_9 {
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcFees>> {
debug!("get_fees rpc request received");
Ok(meta.get_fees(commitment))
meta.get_fees(commitment)
}
fn get_fee_calculator_for_blockhash(
@ -3915,7 +4010,7 @@ pub mod rpc_deprecated_v1_9 {
debug!("get_fee_calculator_for_blockhash rpc request received");
let blockhash = Hash::from_str(&blockhash)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment))
meta.get_fee_calculator_for_blockhash(&blockhash, commitment)
}
fn get_fee_rate_governor(
@ -4087,8 +4182,17 @@ pub mod rpc_deprecated_v1_7 {
match verification {
Err(err) => Box::pin(future::err(err)),
Ok((address, before, until, limit)) => Box::pin(async move {
meta.get_signatures_for_address(address, before, until, limit, commitment)
.await
meta.get_signatures_for_address(
address,
before,
until,
limit,
RpcContextConfig {
commitment,
min_context_slot: None,
},
)
.await
}),
}
}
@ -4160,7 +4264,7 @@ pub mod rpc_obsolete_v1_7 {
) -> Result<RpcResponse<bool>> {
debug!("confirm_transaction rpc request received: {:?}", id);
let signature = verify_signature(&id)?;
Ok(meta.confirm_transaction(&signature, commitment))
meta.confirm_transaction(&signature, commitment)
}
fn get_signature_status(
@ -4174,7 +4278,7 @@ pub mod rpc_obsolete_v1_7 {
signature_str
);
let signature = verify_signature(&signature_str)?;
Ok(meta.get_signature_status(signature, commitment))
meta.get_signature_status(signature, commitment)
}
fn get_signature_confirmation(
@ -4188,7 +4292,7 @@ pub mod rpc_obsolete_v1_7 {
signature_str
);
let signature = verify_signature(&signature_str)?;
Ok(meta.get_signature_confirmation_status(signature, commitment))
meta.get_signature_confirmation_status(signature, commitment)
}
fn get_total_supply(
@ -4197,7 +4301,7 @@ pub mod rpc_obsolete_v1_7 {
commitment: Option<CommitmentConfig>,
) -> Result<u64> {
debug!("get_total_supply rpc request received");
Ok(meta.get_total_supply(commitment))
meta.get_total_supply(commitment)
}
fn get_confirmed_signatures_for_address(
@ -4795,7 +4899,12 @@ pub mod tests {
.unwrap();
let request_processor =
JsonRpcRequestProcessor::new_from_bank(&bank, SocketAddrSpace::Unspecified);
assert_eq!(request_processor.get_transaction_count(None), 1);
assert_eq!(
request_processor
.get_transaction_count(RpcContextConfig::default())
.unwrap(),
1
);
}
#[test]

View File

@ -412,12 +412,17 @@ impl RpcSolPubSubInternal for RpcSolPubSubImpl {
pubkey_str: String,
config: Option<RpcAccountInfoConfig>,
) -> Result<SubscriptionId> {
let config = config.unwrap_or_default();
let RpcAccountInfoConfig {
encoding,
data_slice,
commitment,
min_context_slot: _, // ignored
} = config.unwrap_or_default();
let params = AccountSubscriptionParams {
pubkey: param::<Pubkey>(&pubkey_str, "pubkey")?,
commitment: config.commitment.unwrap_or_default(),
data_slice: config.data_slice,
encoding: config.encoding.unwrap_or(UiAccountEncoding::Binary),
commitment: commitment.unwrap_or_default(),
data_slice,
encoding: encoding.unwrap_or(UiAccountEncoding::Binary),
};
self.subscribe(SubscriptionParams::Account(params))
}
@ -865,6 +870,7 @@ mod tests {
commitment: Some(CommitmentConfig::processed()),
encoding: Some(encoding),
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();
@ -992,6 +998,7 @@ mod tests {
commitment: Some(CommitmentConfig::processed()),
encoding: Some(UiAccountEncoding::JsonParsed),
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();
@ -1129,6 +1136,7 @@ mod tests {
commitment: Some(CommitmentConfig::finalized()),
encoding: None,
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();
@ -1181,6 +1189,7 @@ mod tests {
commitment: Some(CommitmentConfig::finalized()),
encoding: None,
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();

View File

@ -559,6 +559,7 @@ mod tests {
use {
super::*,
crate::rpc::create_validator_exit,
solana_client::rpc_config::RpcContextConfig,
solana_gossip::{
contact_info::ContactInfo,
crds::GossipRoute,
@ -639,7 +640,8 @@ mod tests {
10_000,
rpc_service
.request_processor
.get_balance(&mint_keypair.pubkey(), None)
.get_balance(&mint_keypair.pubkey(), RpcContextConfig::default())
.unwrap()
.value
);
rpc_service.exit();

View File

@ -1346,6 +1346,7 @@ pub(crate) mod tests {
commitment: Some(CommitmentConfig::processed()),
encoding: None,
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();
@ -2684,6 +2685,7 @@ pub(crate) mod tests {
commitment: Some(CommitmentConfig::confirmed()),
encoding: None,
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();
@ -2771,6 +2773,7 @@ pub(crate) mod tests {
commitment: Some(CommitmentConfig::confirmed()),
encoding: None,
data_slice: None,
min_context_slot: None,
}),
)
.unwrap();