RPC: respect data slice config if account parsing fails (#28387)

* RPC: respect data slice config if account parsing fails

* Remove check_slice_and_encoding method
This commit is contained in:
Justin Starry 2022-10-19 16:49:12 +08:00 committed by GitHub
parent 491ec1e275
commit 58e27d45dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 44 deletions

View File

@ -117,7 +117,10 @@ impl UiAccount {
{ {
UiAccountData::Json(parsed_data) UiAccountData::Json(parsed_data)
} else { } else {
UiAccountData::Binary(base64::encode(account.data()), UiAccountEncoding::Base64) UiAccountData::Binary(
base64::encode(slice_data(account.data(), data_slice_config)),
UiAccountEncoding::Base64,
)
} }
} }
}; };

View File

@ -257,7 +257,7 @@ Returns all information associated with the account of provided Pubkey
"base64" will return base64 encoded data for Account data of any size. "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. "base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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>`. ["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; has no effect on parsed account data.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at. - (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results: #### Results:
@ -1797,7 +1797,7 @@ Returns the account information for a list of Pubkeys.
"base64" will return base64 encoded data for Account data of any size. "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. "base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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>`. ["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; has no effect on parsed account data.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at. - (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results: #### Results:
@ -1944,7 +1944,7 @@ Returns all accounts owned by the provided program Pubkey
"base64" will return base64 encoded data for Account data of any size. "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. "base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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>`. ["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; has no effect on parsed account data.
- (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) `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) `withContext: bool` - wrap the result in an RpcResponse JSON object.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at. - (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
@ -2724,7 +2724,7 @@ Returns all SPL Token accounts by approved Delegate.
"base64" will return base64 encoded data for Account data of any size. "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. "base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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>`. ["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; has no effect on parsed account data.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at. - (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results: #### Results:
@ -2831,7 +2831,7 @@ Returns all SPL Token accounts by token owner.
"base64" will return base64 encoded data for Account data of any size. "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. "base64+zstd" compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result.
["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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>`. ["jsonParsed" encoding](jsonrpc-api.md#parsed-responses) 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) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; has no effect on parsed account data.
- (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at. - (optional) `minContextSlot: <number>` - set the minimum slot that the request can be evaluated at.
#### Results: #### Results:

View File

@ -420,7 +420,6 @@ impl JsonRpcRequestProcessor {
min_context_slot, min_context_slot,
})?; })?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary); let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, data_slice.is_some())?;
let response = get_encoded_account(&bank, pubkey, encoding, data_slice)?; let response = get_encoded_account(&bank, pubkey, encoding, data_slice)?;
Ok(new_response(&bank, response)) Ok(new_response(&bank, response))
@ -442,7 +441,6 @@ impl JsonRpcRequestProcessor {
min_context_slot, min_context_slot,
})?; })?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Base64); let encoding = encoding.unwrap_or(UiAccountEncoding::Base64);
check_slice_and_encoding(&encoding, data_slice.is_some())?;
let accounts = pubkeys let accounts = pubkeys
.into_iter() .into_iter()
@ -478,7 +476,6 @@ impl JsonRpcRequestProcessor {
min_context_slot, min_context_slot,
})?; })?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary); let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
optimize_filters(&mut filters); optimize_filters(&mut filters);
let keyed_accounts = { let keyed_accounts = {
if let Some(owner) = get_spl_token_owner_filter(program_id, &filters) { if let Some(owner) = get_spl_token_owner_filter(program_id, &filters) {
@ -1901,7 +1898,6 @@ impl JsonRpcRequestProcessor {
min_context_slot, min_context_slot,
})?; })?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary); 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)?; let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
let mut filters = vec![]; let mut filters = vec![];
@ -1952,7 +1948,6 @@ impl JsonRpcRequestProcessor {
min_context_slot, min_context_slot,
})?; })?;
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary); 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)?; let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
let mut filters = vec![ let mut filters = vec![
@ -2291,29 +2286,6 @@ pub(crate) fn check_is_at_least_confirmed(commitment: CommitmentConfig) -> Resul
Ok(()) Ok(())
} }
fn check_slice_and_encoding(encoding: &UiAccountEncoding, data_slice_is_some: bool) -> Result<()> {
match encoding {
UiAccountEncoding::JsonParsed => {
if data_slice_is_some {
let message =
"Sliced account data can only be encoded using binary (base 58) or base64 encoding."
.to_string();
Err(error::Error {
code: error::ErrorCode::InvalidRequest,
message,
data: None,
})
} else {
Ok(())
}
}
UiAccountEncoding::Binary
| UiAccountEncoding::Base58
| UiAccountEncoding::Base64
| UiAccountEncoding::Base64Zstd => Ok(()),
}
}
fn get_encoded_account( fn get_encoded_account(
bank: &Arc<Bank>, bank: &Arc<Bank>,
pubkey: &Pubkey, pubkey: &Pubkey,
@ -5529,12 +5501,12 @@ pub mod tests {
json!([address, {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}}]), json!([address, {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}}]),
), ),
); );
let response = parse_failure_response(rpc.handle_request_sync(request)); let result: Value = parse_success_result(rpc.handle_request_sync(request));
let expected = ( let expected = json!([base64::encode(&data[1..3]), "base64"]);
ErrorCode::InvalidRequest.code(), assert_eq!(
String::from("Sliced account data can only be encoded using binary (base 58) or base64 encoding."), result["value"]["data"], expected,
"should use data slice if parsing fails"
); );
assert_eq!(response, expected);
} }
#[test] #[test]
@ -5625,12 +5597,28 @@ pub mod tests {
{"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}}, {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}},
])), ])),
); );
let response = parse_failure_response(rpc.handle_request_sync(request)); let result: RpcResponse<Value> = parse_success_result(rpc.handle_request_sync(request));
let expected = ( let expected = json!([
ErrorCode::InvalidRequest.code(), {
String::from("Sliced account data can only be encoded using binary (base 58) or base64 encoding."), "owner": "11111111111111111111111111111111",
"lamports": TEST_MINT_LAMPORTS,
"data": ["", "base64"],
"executable": false,
"rentEpoch": 0
},
null,
{
"owner": "11111111111111111111111111111111",
"lamports": 42,
"data": [base64::encode(&data[1..3]), "base64"],
"executable": false,
"rentEpoch": 0
}
]);
assert_eq!(
result.value, expected,
"should use data slice if parsing fails"
); );
assert_eq!(response, expected);
} }
#[test] #[test]