Add Binary64 option for account data (#11474)

* Add Binary64 option for account data

* Decode into binary64

* Reword docs
This commit is contained in:
sakridge 2020-08-08 22:40:13 -07:00 committed by GitHub
parent 4d918f83ff
commit 068d23f298
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 59 additions and 18 deletions

1
Cargo.lock generated
View File

@ -3204,6 +3204,7 @@ name = "solana-account-decoder"
version = "1.4.0"
dependencies = [
"Inflector",
"base64 0.12.3",
"bincode",
"bs58",
"lazy_static",

View File

@ -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"

View File

@ -30,6 +30,7 @@ pub struct UiAccount {
pub enum UiAccountData {
Binary(String),
Json(ParsedAccount),
Binary64(String),
}
impl From<Vec<u8>> for UiAccountData {
@ -43,6 +44,7 @@ impl From<Vec<u8>> for UiAccountData {
pub enum UiAccountEncoding {
Binary,
JsonParsed,
Binary64,
}
impl UiAccount {
@ -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)
@ -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,

View File

@ -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)),

View File

@ -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,
@ -20,6 +21,8 @@ use solana_account_decoder::{
UiTokenAmount,
},
UiAccount,
UiAccountData::{Binary, Binary64},
UiAccountEncoding,
};
use solana_sdk::{
account::Account,
@ -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
@ -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 {

View File

@ -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,
@ -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(
@ -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(

View File

@ -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();
}

View File

@ -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: