diff --git a/account-decoder/src/lib.rs b/account-decoder/src/lib.rs index 233e8024a4..0fb64d947a 100644 --- a/account-decoder/src/lib.rs +++ b/account-decoder/src/lib.rs @@ -117,7 +117,10 @@ impl UiAccount { { UiAccountData::Json(parsed_data) } else { - UiAccountData::Binary(base64::encode(account.data()), UiAccountEncoding::Base64) + UiAccountData::Binary( + base64::encode(slice_data(account.data(), data_slice_config)), + UiAccountEncoding::Base64, + ) } } }; diff --git a/docs/src/developing/clients/jsonrpc-api.md b/docs/src/developing/clients/jsonrpc-api.md index 78c41bbd8e..02cde1f610 100644 --- a/docs/src/developing/clients/jsonrpc-api.md +++ b/docs/src/developing/clients/jsonrpc-api.md @@ -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+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 ``. - - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "base58", "base64" or "base64+zstd" encodings. + - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; has no effect on parsed account data. - (optional) `minContextSlot: ` - set the minimum slot that the request can be evaluated at. #### 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+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 ``. - - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "base58", "base64" or "base64+zstd" encodings. + - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; has no effect on parsed account data. - (optional) `minContextSlot: ` - set the minimum slot that the request can be evaluated at. #### 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+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 ``. - - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "base58", "base64" or "base64+zstd" encodings. + - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; has no effect on parsed account data. - (optional) `filters: ` - 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: ` - 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+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 ``. - - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "base58", "base64" or "base64+zstd" encodings. + - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; has no effect on parsed account data. - (optional) `minContextSlot: ` - set the minimum slot that the request can be evaluated at. #### 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+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 ``. - - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "base58", "base64" or "base64+zstd" encodings. + - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; has no effect on parsed account data. - (optional) `minContextSlot: ` - set the minimum slot that the request can be evaluated at. #### Results: diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index a65b7bbdd4..0247ccac0b 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -420,7 +420,6 @@ impl JsonRpcRequestProcessor { 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, data_slice)?; Ok(new_response(&bank, response)) @@ -442,7 +441,6 @@ impl JsonRpcRequestProcessor { min_context_slot, })?; let encoding = encoding.unwrap_or(UiAccountEncoding::Base64); - check_slice_and_encoding(&encoding, data_slice.is_some())?; let accounts = pubkeys .into_iter() @@ -478,7 +476,6 @@ impl JsonRpcRequestProcessor { 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 = { if let Some(owner) = get_spl_token_owner_filter(program_id, &filters) { @@ -1901,7 +1898,6 @@ impl JsonRpcRequestProcessor { 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)?; let mut filters = vec![]; @@ -1952,7 +1948,6 @@ impl JsonRpcRequestProcessor { 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)?; let mut filters = vec![ @@ -2291,29 +2286,6 @@ pub(crate) fn check_is_at_least_confirmed(commitment: CommitmentConfig) -> Resul 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( bank: &Arc, pubkey: &Pubkey, @@ -5529,12 +5501,12 @@ pub mod tests { json!([address, {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}}]), ), ); - let response = parse_failure_response(rpc.handle_request_sync(request)); - let expected = ( - ErrorCode::InvalidRequest.code(), - String::from("Sliced account data can only be encoded using binary (base 58) or base64 encoding."), + let result: Value = parse_success_result(rpc.handle_request_sync(request)); + let expected = json!([base64::encode(&data[1..3]), "base64"]); + assert_eq!( + result["value"]["data"], expected, + "should use data slice if parsing fails" ); - assert_eq!(response, expected); } #[test] @@ -5625,12 +5597,28 @@ pub mod tests { {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}}, ])), ); - let response = parse_failure_response(rpc.handle_request_sync(request)); - let expected = ( - ErrorCode::InvalidRequest.code(), - String::from("Sliced account data can only be encoded using binary (base 58) or base64 encoding."), + let result: RpcResponse = parse_success_result(rpc.handle_request_sync(request)); + let expected = json!([ + { + "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]