Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Binary64 option for account data #11474

Merged
merged 3 commits into from
Aug 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions account-decoder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license = "Apache-2.0"
edition = "2018"

[dependencies]
base64 = "0.12.3"
bincode = "1.3.1"
bs58 = "0.3.1"
Inflector = "0.11.4"
Expand Down
4 changes: 4 additions & 0 deletions account-decoder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct UiAccount {
pub enum UiAccountData {
Binary(String),
Json(ParsedAccount),
Binary64(String),
}

impl From<Vec<u8>> for UiAccountData {
Expand All @@ -43,6 +44,7 @@ impl From<Vec<u8>> for UiAccountData {
pub enum UiAccountEncoding {
Binary,
JsonParsed,
Binary64,
}

impl UiAccount {
Expand All @@ -53,6 +55,7 @@ impl UiAccount {
) -> Self {
let data = match encoding {
UiAccountEncoding::Binary => account.data.into(),
UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(account.data)),
UiAccountEncoding::JsonParsed => {
if let Ok(parsed_data) =
parse_account_data(&account.owner, &account.data, additional_data)
Expand All @@ -76,6 +79,7 @@ impl UiAccount {
let data = match &self.data {
UiAccountData::Json(_) => None,
UiAccountData::Binary(blob) => bs58::decode(blob).into_vec().ok(),
UiAccountData::Binary64(blob) => base64::decode(blob).ok(),
}?;
Some(Account {
lamports: self.lamports,
Expand Down
2 changes: 1 addition & 1 deletion cli/src/offline/blockhash_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ mod tests {
)
.unwrap();
let nonce_pubkey = Pubkey::new(&[4u8; 32]);
let rpc_nonce_account = UiAccount::encode(nonce_account, UiAccountEncoding::Binary, None);
let rpc_nonce_account = UiAccount::encode(nonce_account, UiAccountEncoding::Binary64, None);
let get_account_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(Some(rpc_nonce_account)),
Expand Down
20 changes: 18 additions & 2 deletions client/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
http_sender::HttpSender,
mock_sender::{MockSender, Mocks},
rpc_config::RpcAccountInfoConfig,
rpc_config::{
RpcGetConfirmedSignaturesForAddress2Config, RpcLargestAccountsConfig,
RpcSendTransactionConfig, RpcTokenAccountsFilter,
Expand All @@ -20,6 +21,8 @@ use solana_account_decoder::{
UiTokenAmount,
},
UiAccount,
UiAccountData::{Binary, Binary64},
UiAccountEncoding,
};
use solana_sdk::{
account::Account,
Expand Down Expand Up @@ -466,9 +469,13 @@ impl RpcClient {
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<Option<Account>> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Binary64),
commitment: Some(commitment_config),
};
let response = self.sender.send(
RpcRequest::GetAccountInfo,
json!([pubkey.to_string(), commitment_config]),
json!([pubkey.to_string(), config]),
);

response
Expand All @@ -480,8 +487,17 @@ impl RpcClient {
}
let Response {
context,
value: rpc_account,
value: mut rpc_account,
} = serde_json::from_value::<Response<Option<UiAccount>>>(result_json)?;
if let Some(ref mut account) = rpc_account {
if let Binary(_) = &account.data {
let tmp = Binary64(String::new());
match std::mem::replace(&mut account.data, tmp) {
Binary(new_data) => account.data = Binary64(new_data),
_ => panic!("should have gotten binary here."),
}
}
}
trace!("Response account {:?} {:?}", pubkey, rpc_account);
let account = rpc_account.and_then(|rpc_account| rpc_account.decode());
Ok(Response {
Expand Down
34 changes: 20 additions & 14 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
rpc_health::*, validator::ValidatorExit,
};
use bincode::{config::Options, serialize};
use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_core::{types::error, Error, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_account_decoder::{
parse_account_data::AccountAdditionalData,
Expand Down Expand Up @@ -240,21 +240,27 @@ impl JsonRpcRequestProcessor {
&self,
pubkey: &Pubkey,
config: Option<RpcAccountInfoConfig>,
) -> RpcResponse<Option<UiAccount>> {
) -> Result<RpcResponse<Option<UiAccount>>> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
new_response(
&bank,
bank.get_account(pubkey).and_then(|account| {
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed
{
get_parsed_token_account(bank.clone(), account)
} else {
Some(UiAccount::encode(account, encoding, None))
}
}),
)
let mut response = None;
if let Some(account) = bank.get_account(pubkey) {
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed {
response = get_parsed_token_account(bank.clone(), account);
} else if encoding == UiAccountEncoding::Binary && account.data.len() > 128 {
let message = "Encoded binary (base 58) data should be less than 128 bytes, please use Binary64 encoding.".to_string();
return Err(error::Error {
code: error::ErrorCode::InvalidRequest,
message,
data: None,
});
} else {
response = Some(UiAccount::encode(account, encoding, None));
}
}

Ok(new_response(&bank, response))
}

pub fn get_minimum_balance_for_rent_exemption(
Expand Down Expand Up @@ -1701,7 +1707,7 @@ impl RpcSol for RpcSolImpl {
) -> Result<RpcResponse<Option<UiAccount>>> {
debug!("get_account_info rpc request received: {:?}", pubkey_str);
let pubkey = verify_pubkey(pubkey_str)?;
Ok(meta.get_account_info(&pubkey, config))
meta.get_account_info(&pubkey, config)
}

fn get_minimum_balance_for_rent_exemption(
Expand Down
13 changes: 13 additions & 0 deletions core/tests/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ fn test_rpc_send_tx() {

assert_eq!(confirmed_tx, true);

use solana_account_decoder::UiAccountEncoding;
use solana_client::rpc_config::RpcAccountInfoConfig;
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Binary64),
commitment: None,
};
let req = json_req!(
"getAccountInfo",
json!([bs58::encode(bob_pubkey).into_string(), config])
);
let json: Value = post_rpc(req, &leader_data);
info!("{:?}", json["result"]["value"]);

server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/apps/jsonrpc-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ Returns all information associated with the account of provided Pubkey
- `<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)
- (optional) `encoding: <string>` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary.
- (optional) `encoding: <string>` - encoding for Account data, either "binary", "binary64", or jsonParsed". If parameter not provided, the default encoding is "binary". "binary" is base-58 encoded and limited to Account data of less than 128 bytes. "binary64" will return base64 encoded data for Account data of any size.
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**

#### Results:
Expand Down