Browse Source

feat: return bank/block info with block-related results (#6716)

Sunny Gleason 6 năm trước cách đây
mục cha
commit
5903339c17

+ 17 - 8
book/src/api-reference/jsonrpc-api.md

@@ -96,6 +96,13 @@ If commitment configuration is not provided, the node will default to `"commitme
 
 Only methods that query bank state accept the commitment parameter. They are indicated in the API Reference below.
 
+#### RpcResponse Structure
+Many methods that take a commitment parameter return an RpcResponse JSON object comprised of two parts:
+
+* `context` : An RpcResponseContext JSON structure including a `slot` field at which the operation was evaluated.
+* `value` : The value returned by the operation itself.
+
+
 ## JSON RPC API Reference
 
 ### confirmTransaction
@@ -109,7 +116,7 @@ Returns a transaction receipt
 
 #### Results:
 
-* `boolean` - Transaction status, true if Transaction is confirmed
+* `RpcResponse<boolean>` - RpcResponse JSON object with `value` field set to Transaction status, boolean true if Transaction is confirmed
 
 #### Example:
 
@@ -118,7 +125,7 @@ Returns a transaction receipt
 curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"confirmTransaction", "params":["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW"]}' http://localhost:8899
 
 // Result
-{"jsonrpc":"2.0","result":true,"id":1}
+{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":true},"id":1}
 ```
 
 ### getAccountInfo
@@ -132,8 +139,9 @@ Returns all information associated with the account of provided Pubkey
 
 #### Results:
 
-The result field will be a JSON object with the following sub fields:
+The result value will be an RpcResponse JSON object containing an AccountInfo JSON object.
 
+* `RpcResponse<AccountInfo>`, RpcResponse JSON object with `value` field set to AccountInfo, a JSON object containing:
 * `lamports`, number of lamports assigned to this account, as a signed 64-bit integer
 * `owner`, array of 32 bytes representing the program this account has been assigned to
 * `data`, array of bytes representing any data associated with the account
@@ -146,7 +154,7 @@ The result field will be a JSON object with the following sub fields:
 curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getAccountInfo", "params":["2gVkYWexTHR5Hb2aLeQN3tnngvWzisFKXDUPrgMHpdST"]}' http://localhost:8899
 
 // Result
-{"jsonrpc":"2.0","result":{"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"id":1}
+{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]}},"id":1}
 ```
 
 ### getBalance
@@ -160,7 +168,7 @@ Returns the balance of the account of provided Pubkey
 
 #### Results:
 
-* `integer` - quantity, as a signed 64-bit integer
+* `RpcResponse<integer>` - RpcResponse JSON object with `value` field set to quantity, as a signed 64-bit integer
 
 #### Example:
 
@@ -169,7 +177,7 @@ Returns the balance of the account of provided Pubkey
 curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getBalance", "params":["83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri"]}' http://localhost:8899
 
 // Result
-{"jsonrpc":"2.0","result":0,"id":1}
+{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":0},"id":1}
 ```
 
 ### getBlockCommitment
@@ -410,8 +418,9 @@ Returns a recent block hash from the ledger, and a fee schedule that can be used
 
 #### Results:
 
-An array consisting of
+An RpcResponse containing an array consisting of a string blockhash and FeeCalculator JSON object.
 
+* `RpcResponse<array>` - RpcResponse JSON object with `value` field set to an array including:
 * `string` - a Hash as base-58 encoded string
 * `FeeCalculator object` - the fee schedule for this block hash
 
@@ -422,7 +431,7 @@ An array consisting of
 curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getRecentBlockhash"}' http://localhost:8899
 
 // Result
-{"jsonrpc":"2.0","result":["GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC",{"lamportsPerSignature": 0}],"id":1}
+{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":["GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC",{"lamportsPerSignature": 0}]},"id":1}
 ```
 
 ### getSignatureStatus

+ 2 - 5
cli/tests/deploy.rs

@@ -3,7 +3,7 @@ use solana_cli::cli::{process_command, CliCommand, CliConfig};
 use solana_client::rpc_client::RpcClient;
 use solana_core::validator::new_validator_for_tests;
 use solana_drone::drone::run_local_drone;
-use solana_sdk::{bpf_loader, commitment_config::CommitmentConfig, pubkey::Pubkey};
+use solana_sdk::{bpf_loader, pubkey::Pubkey};
 use std::{
     fs::{remove_dir_all, File},
     io::Read,
@@ -59,10 +59,7 @@ fn test_cli_deploy_program() {
         .as_str()
         .unwrap();
     let program_id = Pubkey::from_str(&program_id_str).unwrap();
-
-    let account = rpc_client
-        .get_account_with_commitment(&program_id, CommitmentConfig::recent())
-        .unwrap();
+    let account = rpc_client.get_account(&program_id).unwrap();
     assert_eq!(account.lamports, minimum_balance_for_rent_exemption);
     assert_eq!(account.owner, bpf_loader::id());
     assert_eq!(account.executable, true);

+ 12 - 5
client/src/mock_rpc_client_request.rs

@@ -1,3 +1,4 @@
+use crate::rpc_request::{Response, RpcResponseContext};
 use crate::{
     client_error::ClientError, generic_rpc_client_request::GenericRpcClientRequest,
     rpc_request::RpcRequest,
@@ -48,12 +49,18 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
             }
             RpcRequest::GetBalance => {
                 let n = if self.url == "airdrop" { 0 } else { 50 };
-                Value::Number(Number::from(n))
+                serde_json::to_value(Response {
+                    context: RpcResponseContext { slot: 1 },
+                    value: Value::Number(Number::from(n)),
+                })?
             }
-            RpcRequest::GetRecentBlockhash => Value::Array(vec![
-                Value::String(PUBKEY.to_string()),
-                serde_json::to_value(FeeCalculator::default()).unwrap(),
-            ]),
+            RpcRequest::GetRecentBlockhash => serde_json::to_value(Response {
+                context: RpcResponseContext { slot: 1 },
+                value: (
+                    Value::String(PUBKEY.to_string()),
+                    serde_json::to_value(FeeCalculator::default()).unwrap(),
+                ),
+            })?,
             RpcRequest::GetSignatureStatus => {
                 let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
                     Some(Err(TransactionError::AccountInUse))

+ 84 - 41
client/src/rpc_client.rs

@@ -1,3 +1,4 @@
+use crate::rpc_request::{Response, RpcResponse};
 use crate::{
     client_error::ClientError,
     generic_rpc_client_request::GenericRpcClientRequest,
@@ -55,31 +56,39 @@ impl RpcClient {
         }
     }
 
-    pub fn confirm_transaction(&self, signature: &str) -> Result<bool, ClientError> {
-        self.confirm_transaction_with_commitment(signature, CommitmentConfig::default())
+    pub fn confirm_transaction(&self, signature: &str) -> io::Result<bool> {
+        Ok(self
+            .confirm_transaction_with_commitment(signature, CommitmentConfig::default())?
+            .value)
     }
 
     pub fn confirm_transaction_with_commitment(
         &self,
         signature: &str,
         commitment_config: CommitmentConfig,
-    ) -> Result<bool, ClientError> {
+    ) -> RpcResponse<bool> {
         let params = json!(signature);
-        let response = self.client.send(
-            &RpcRequest::ConfirmTransaction,
-            Some(params),
-            0,
-            Some(commitment_config),
-        )?;
-        if response.as_bool().is_none() {
-            Err(io::Error::new(
+        let response = self
+            .client
+            .send(
+                &RpcRequest::ConfirmTransaction,
+                Some(params),
+                0,
+                Some(commitment_config),
+            )
+            .map_err(|err| {
+                io::Error::new(
+                    io::ErrorKind::Other,
+                    format!("ConfirmTransaction request failure {:?}", err),
+                )
+            })?;
+
+        serde_json::from_value::<Response<bool>>(response).map_err(|err| {
+            io::Error::new(
                 io::ErrorKind::Other,
-                "Received result of an unexpected type",
+                format!("Received result of an unexpected type {:?}", err),
             )
-            .into())
-        } else {
-            Ok(response.as_bool().unwrap())
-        }
+        })
     }
 
     pub fn send_transaction(&self, transaction: &Transaction) -> Result<String, ClientError> {
@@ -378,46 +387,69 @@ impl RpcClient {
         retries: usize,
     ) -> Result<Option<u64>, Box<dyn error::Error>> {
         let params = json!(format!("{}", pubkey));
-        let res = self
+        let balance_json = self
             .client
-            .send(&RpcRequest::GetBalance, Some(params), retries, None)?
-            .as_u64();
-        Ok(res)
+            .send(&RpcRequest::GetBalance, Some(params), retries, None)
+            .map_err(|err| {
+                io::Error::new(
+                    io::ErrorKind::Other,
+                    format!("RetryGetBalance request failure: {:?}", err),
+                )
+            })?;
+
+        Ok(Some(
+            serde_json::from_value::<Response<u64>>(balance_json)
+                .map_err(|err| {
+                    io::Error::new(
+                        io::ErrorKind::Other,
+                        format!("RetryGetBalance parse failure: {:?}", err),
+                    )
+                })?
+                .value,
+        ))
     }
 
     pub fn get_account(&self, pubkey: &Pubkey) -> io::Result<Account> {
-        self.get_account_with_commitment(pubkey, CommitmentConfig::default())
+        Ok(self
+            .get_account_with_commitment(pubkey, CommitmentConfig::default())
+            .map(|x| x.value.unwrap())?)
     }
 
     pub fn get_account_with_commitment(
         &self,
         pubkey: &Pubkey,
         commitment_config: CommitmentConfig,
-    ) -> io::Result<Account> {
+    ) -> RpcResponse<Option<Account>> {
         let params = json!(format!("{}", pubkey));
         let response = self.client.send(
             &RpcRequest::GetAccountInfo,
             Some(params),
             0,
-            commitment_config.ok(),
+            Some(commitment_config),
         );
 
         response
-            .and_then(|account_json| {
-                let account: Account = serde_json::from_value(account_json)?;
-                trace!("Response account {:?} {:?}", pubkey, account);
-                Ok(account)
+            .map(|result_json| {
+                if result_json.is_null() {
+                    return Err(io::Error::new(
+                        io::ErrorKind::Other,
+                        format!("AccountNotFound: pubkey={}", pubkey),
+                    ));
+                }
+                let result = serde_json::from_value::<Response<Option<Account>>>(result_json)?;
+                trace!("Response account {:?} {:?}", pubkey, result);
+                Ok(result)
             })
             .map_err(|err| {
                 io::Error::new(
                     io::ErrorKind::Other,
                     format!("AccountNotFound: pubkey={}: {}", pubkey, err),
                 )
-            })
+            })?
     }
 
     pub fn get_account_data(&self, pubkey: &Pubkey) -> io::Result<Vec<u8>> {
-        self.get_account(pubkey).map(|account| account.data)
+        Ok(self.get_account(pubkey).unwrap().data)
     }
 
     pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> io::Result<u64> {
@@ -456,14 +488,16 @@ impl RpcClient {
 
     /// Request the balance of the account `pubkey`.
     pub fn get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
-        self.get_balance_with_commitment(pubkey, CommitmentConfig::default())
+        Ok(self
+            .get_balance_with_commitment(pubkey, CommitmentConfig::default())?
+            .value)
     }
 
     pub fn get_balance_with_commitment(
         &self,
         pubkey: &Pubkey,
         commitment_config: CommitmentConfig,
-    ) -> io::Result<u64> {
+    ) -> RpcResponse<u64> {
         let params = json!(pubkey.to_string());
         let balance_json = self
             .client
@@ -479,7 +513,8 @@ impl RpcClient {
                     format!("GetBalance request failure: {:?}", err),
                 )
             })?;
-        serde_json::from_value(balance_json).map_err(|err| {
+
+        serde_json::from_value::<Response<u64>>(balance_json).map_err(|err| {
             io::Error::new(
                 io::ErrorKind::Other,
                 format!("GetBalance parse failure: {:?}", err),
@@ -553,13 +588,15 @@ impl RpcClient {
     }
 
     pub fn get_recent_blockhash(&self) -> io::Result<(Hash, FeeCalculator)> {
-        self.get_recent_blockhash_with_commitment(CommitmentConfig::default())
+        Ok(self
+            .get_recent_blockhash_with_commitment(CommitmentConfig::default())?
+            .value)
     }
 
     pub fn get_recent_blockhash_with_commitment(
         &self,
         commitment_config: CommitmentConfig,
-    ) -> io::Result<(Hash, FeeCalculator)> {
+    ) -> RpcResponse<(Hash, FeeCalculator)> {
         let response = self
             .client
             .send(
@@ -575,21 +612,27 @@ impl RpcClient {
                 )
             })?;
 
-        let (blockhash, fee_calculator) =
-            serde_json::from_value::<(String, FeeCalculator)>(response).map_err(|err| {
+        let Response {
+            context,
+            value: (blockhash_str, fee_calculator),
+        } = serde_json::from_value::<Response<(String, FeeCalculator)>>(response).map_err(
+            |err| {
                 io::Error::new(
                     io::ErrorKind::Other,
                     format!("GetRecentBlockhash parse failure: {:?}", err),
                 )
-            })?;
-
-        let blockhash = blockhash.parse().map_err(|err| {
+            },
+        )?;
+        let blockhash = blockhash_str.parse().map_err(|err| {
             io::Error::new(
                 io::ErrorKind::Other,
                 format!("GetRecentBlockhash hash parse failure: {:?}", err),
             )
         })?;
-        Ok((blockhash, fee_calculator))
+        Ok(Response {
+            context,
+            value: (blockhash, fee_calculator),
+        })
     }
 
     pub fn get_new_blockhash(&self, blockhash: &Hash) -> io::Result<(Hash, FeeCalculator)> {
@@ -658,7 +701,7 @@ impl RpcClient {
         loop {
             match self.get_balance_with_commitment(&pubkey, commitment_config.clone()) {
                 Ok(bal) => {
-                    return Ok(bal);
+                    return Ok(bal.value);
                 }
                 Err(e) => {
                     sleep(*polling_frequency);

+ 16 - 1
client/src/rpc_request.rs

@@ -1,9 +1,24 @@
+use jsonrpc_core::Result as JsonResult;
 use serde_json::{json, Value};
 use solana_sdk::{
     clock::{Epoch, Slot},
     commitment_config::CommitmentConfig,
 };
-use std::{error, fmt};
+use std::{error, fmt, io};
+
+pub type RpcResponseIn<T> = JsonResult<Response<T>>;
+pub type RpcResponse<T> = io::Result<Response<T>>;
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub struct RpcResponseContext {
+    pub slot: u64,
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub struct Response<T> {
+    pub context: RpcResponseContext,
+    pub value: T,
+}
 
 #[derive(Serialize, Deserialize, Clone, Debug)]
 #[serde(rename_all = "camelCase")]

+ 12 - 8
client/src/thin_client.rs

@@ -4,6 +4,7 @@
 //! unstable and may change in future releases.
 
 use crate::rpc_client::RpcClient;
+use crate::rpc_request::Response;
 use bincode::{serialize_into, serialized_size};
 use log::*;
 use solana_sdk::{
@@ -383,7 +384,11 @@ impl SyncClient for ThinClient {
     }
 
     fn get_account(&self, pubkey: &Pubkey) -> TransportResult<Option<Account>> {
-        Ok(self.rpc_client().get_account(pubkey).ok())
+        let account = self.rpc_client().get_account(pubkey);
+        match account {
+            Ok(value) => Ok(Some(value)),
+            Err(_) => Ok(None),
+        }
     }
 
     fn get_account_with_commitment(
@@ -393,13 +398,12 @@ impl SyncClient for ThinClient {
     ) -> TransportResult<Option<Account>> {
         Ok(self
             .rpc_client()
-            .get_account_with_commitment(pubkey, commitment_config)
-            .ok())
+            .get_account_with_commitment(pubkey, commitment_config)?
+            .value)
     }
 
     fn get_balance(&self, pubkey: &Pubkey) -> TransportResult<u64> {
-        let balance = self.rpc_client().get_balance(pubkey)?;
-        Ok(balance)
+        Ok(self.rpc_client().get_balance(pubkey)?)
     }
 
     fn get_balance_with_commitment(
@@ -410,7 +414,7 @@ impl SyncClient for ThinClient {
         let balance = self
             .rpc_client()
             .get_balance_with_commitment(pubkey, commitment_config)?;
-        Ok(balance)
+        Ok(balance.value)
     }
 
     fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
@@ -426,9 +430,9 @@ impl SyncClient for ThinClient {
         let recent_blockhash =
             self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
         match recent_blockhash {
-            Ok(recent_blockhash) => {
+            Ok(Response { value, .. }) => {
                 self.optimizer.report(index, duration_as_ms(&now.elapsed()));
-                Ok(recent_blockhash)
+                Ok(value)
             }
             Err(e) => {
                 self.optimizer.report(index, std::u64::MAX);

+ 102 - 54
core/src/rpc.rs

@@ -12,7 +12,9 @@ use crate::{
 use bincode::serialize;
 use jsonrpc_core::{Error, Metadata, Result};
 use jsonrpc_derive::rpc;
-use solana_client::rpc_request::{RpcEpochInfo, RpcVoteAccountInfo, RpcVoteAccountStatus};
+use solana_client::rpc_request::{
+    Response, RpcEpochInfo, RpcResponseContext, RpcVoteAccountInfo, RpcVoteAccountStatus,
+};
 use solana_drone::drone::request_airdrop_transaction;
 use solana_ledger::{
     bank_forks::BankForks, blocktree::Blocktree, rooted_slot_iterator::RootedSlotIterator,
@@ -40,6 +42,13 @@ use std::{
     time::{Duration, Instant},
 };
 
+type RpcResponse<T> = Result<Response<T>>;
+
+fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
+    let context = RpcResponseContext { slot: bank.slot() };
+    Ok(Response { context, value })
+}
+
 #[derive(Debug, Clone)]
 pub struct JsonRpcConfig {
     pub enable_validator_exit: bool, // Enable the 'validatorExit' command
@@ -100,12 +109,14 @@ impl JsonRpcRequestProcessor {
 
     pub fn get_account_info(
         &self,
-        pubkey: &Pubkey,
+        pubkey: Result<Pubkey>,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<Account> {
-        self.bank(commitment)
-            .get_account(&pubkey)
-            .ok_or_else(Error::invalid_request)
+    ) -> RpcResponse<Option<Account>> {
+        let bank = &*self.bank(commitment);
+        match pubkey {
+            Ok(key) => new_response(bank, bank.get_account(&key)),
+            Err(e) => Err(e),
+        }
     }
 
     pub fn get_minimum_balance_for_rent_exemption(
@@ -141,16 +152,43 @@ impl JsonRpcRequestProcessor {
         Ok(*self.bank(None).epoch_schedule())
     }
 
-    pub fn get_balance(&self, pubkey: &Pubkey, commitment: Option<CommitmentConfig>) -> u64 {
-        self.bank(commitment).get_balance(&pubkey)
+    pub fn get_balance(
+        &self,
+        pubkey: Result<Pubkey>,
+        commitment: Option<CommitmentConfig>,
+    ) -> RpcResponse<u64> {
+        let bank = &*self.bank(commitment);
+        match pubkey {
+            Ok(key) => new_response(bank, bank.get_balance(&key)),
+            Err(e) => Err(e),
+        }
     }
 
     fn get_recent_blockhash(
         &self,
         commitment: Option<CommitmentConfig>,
-    ) -> (String, FeeCalculator) {
-        let (blockhash, fee_calculator) = self.bank(commitment).confirmed_last_blockhash();
-        (blockhash.to_string(), fee_calculator)
+    ) -> RpcResponse<(String, FeeCalculator)> {
+        let bank = &*self.bank(commitment);
+        let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
+        new_response(bank, (blockhash.to_string(), fee_calculator))
+    }
+
+    pub fn confirm_transaction(
+        &self,
+        signature: Result<Signature>,
+        commitment: Option<CommitmentConfig>,
+    ) -> RpcResponse<bool> {
+        let bank = &*self.bank(commitment);
+        match signature {
+            Err(e) => Err(e),
+            Ok(sig) => {
+                let status = bank.get_signature_confirmation_status(&sig);
+                match status {
+                    Some((_, result)) => new_response(bank, result.is_ok()),
+                    None => new_response(bank, false),
+                }
+            }
+        }
     }
 
     fn get_block_commitment(&self, block: Slot) -> (Option<BlockCommitment>, u64) {
@@ -333,7 +371,7 @@ pub trait RpcSol {
         meta: Self::Metadata,
         signature_str: String,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<bool>;
+    ) -> RpcResponse<bool>;
 
     #[rpc(meta, name = "getAccountInfo")]
     fn get_account_info(
@@ -341,7 +379,7 @@ pub trait RpcSol {
         meta: Self::Metadata,
         pubkey_str: String,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<Account>;
+    ) -> RpcResponse<Option<Account>>;
 
     #[rpc(meta, name = "getProgramAccounts")]
     fn get_program_accounts(
@@ -375,7 +413,7 @@ pub trait RpcSol {
         meta: Self::Metadata,
         pubkey_str: String,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<u64>;
+    ) -> RpcResponse<u64>;
 
     #[rpc(meta, name = "getClusterNodes")]
     fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>>;
@@ -409,7 +447,7 @@ pub trait RpcSol {
         &self,
         meta: Self::Metadata,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<(String, FeeCalculator)>;
+    ) -> RpcResponse<(String, FeeCalculator)>;
 
     #[rpc(meta, name = "getSignatureStatus")]
     fn get_signature_status(
@@ -521,20 +559,15 @@ impl RpcSol for RpcSolImpl {
     fn confirm_transaction(
         &self,
         meta: Self::Metadata,
-        signature_str: String,
+        id: String,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<bool> {
-        debug!(
-            "confirm_transaction rpc request received: {:?}",
-            signature_str
-        );
-        self.get_signature_status(meta, signature_str, commitment)
-            .map(|status_option| {
-                if status_option.is_none() {
-                    return false;
-                }
-                status_option.unwrap().is_ok()
-            })
+    ) -> RpcResponse<bool> {
+        debug!("confirm_transaction rpc request received: {:?}", id);
+        let signature = verify_signature(&id);
+        meta.request_processor
+            .read()
+            .unwrap()
+            .confirm_transaction(signature, commitment)
     }
 
     fn get_account_info(
@@ -542,13 +575,13 @@ impl RpcSol for RpcSolImpl {
         meta: Self::Metadata,
         pubkey_str: String,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<Account> {
+    ) -> RpcResponse<Option<Account>> {
         debug!("get_account_info rpc request received: {:?}", pubkey_str);
-        let pubkey = verify_pubkey(pubkey_str)?;
+        let pubkey = verify_pubkey(pubkey_str);
         meta.request_processor
             .read()
             .unwrap()
-            .get_account_info(&pubkey, commitment)
+            .get_account_info(pubkey, commitment)
     }
 
     fn get_minimum_balance_for_rent_exemption(
@@ -613,14 +646,13 @@ impl RpcSol for RpcSolImpl {
         meta: Self::Metadata,
         pubkey_str: String,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<u64> {
+    ) -> RpcResponse<u64> {
         debug!("get_balance rpc request received: {:?}", pubkey_str);
-        let pubkey = verify_pubkey(pubkey_str)?;
-        Ok(meta
-            .request_processor
+        let pubkey = verify_pubkey(pubkey_str);
+        meta.request_processor
             .read()
             .unwrap()
-            .get_balance(&pubkey, commitment))
+            .get_balance(pubkey, commitment)
     }
 
     fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>> {
@@ -707,13 +739,12 @@ impl RpcSol for RpcSolImpl {
         &self,
         meta: Self::Metadata,
         commitment: Option<CommitmentConfig>,
-    ) -> Result<(String, FeeCalculator)> {
+    ) -> RpcResponse<(String, FeeCalculator)> {
         debug!("get_recent_blockhash rpc request received");
-        Ok(meta
-            .request_processor
+        meta.request_processor
             .read()
             .unwrap()
-            .get_recent_blockhash(commitment))
+            .get_recent_blockhash(commitment)
     }
 
     fn get_signature_status(
@@ -1150,10 +1181,15 @@ pub mod tests {
             bob_pubkey
         );
         let res = io.handle_request_sync(&req, meta);
-        let expected = format!(r#"{{"jsonrpc":"2.0","result":20,"id":1}}"#);
-        let expected: Response =
-            serde_json::from_str(&expected).expect("expected response deserialization");
-        let result: Response = serde_json::from_str(&res.expect("actual response"))
+        let expected = json!({
+            "jsonrpc": "2.0",
+            "result": {
+                "context":{"slot":0},
+                "value":20,
+                },
+            "id": 1,
+        });
+        let result = serde_json::from_str::<Value>(&res.expect("actual response"))
             .expect("actual response deserialization");
         assert_eq!(expected, result);
     }
@@ -1328,19 +1364,22 @@ pub mod tests {
             bob_pubkey
         );
         let res = io.handle_request_sync(&req, meta);
-        let expected = r#"{
-            "jsonrpc":"2.0",
-            "result":{
+        let expected = json!({
+            "jsonrpc": "2.0",
+            "result": {
+                "context":{"slot":0},
+                "value":{
                 "owner": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                 "lamports": 20,
                 "data": [],
                 "executable": false,
                 "rent_epoch": 0
             },
-            "id":1}
-        "#;
+                },
+            "id": 1,
+        });
         let expected: Response =
-            serde_json::from_str(&expected).expect("expected response deserialization");
+            serde_json::from_value(expected).expect("expected response deserialization");
         let result: Response = serde_json::from_str(&res.expect("actual response"))
             .expect("actual response deserialization");
         assert_eq!(expected, result);
@@ -1404,9 +1443,16 @@ pub mod tests {
             tx.signatures[0]
         );
         let res = io.handle_request_sync(&req, meta);
-        let expected = format!(r#"{{"jsonrpc":"2.0","result":true,"id":1}}"#);
+        let expected = json!({
+            "jsonrpc": "2.0",
+            "result": {
+                "context":{"slot":0},
+                "value":true,
+                },
+            "id": 1,
+        });
         let expected: Response =
-            serde_json::from_str(&expected).expect("expected response deserialization");
+            serde_json::from_value(expected).expect("expected response deserialization");
         let result: Response = serde_json::from_str(&res.expect("actual response"))
             .expect("actual response deserialization");
         assert_eq!(expected, result);
@@ -1496,14 +1542,16 @@ pub mod tests {
         let res = io.handle_request_sync(&req, meta);
         let expected = json!({
             "jsonrpc": "2.0",
-            "result": [ blockhash.to_string(), {
+            "result": {
+            "context":{"slot":0},
+            "value":[ blockhash.to_string(), {
                 "burnPercent": DEFAULT_BURN_PERCENT,
                 "lamportsPerSignature": 0,
                 "maxLamportsPerSignature": 0,
                 "minLamportsPerSignature": 0,
                 "targetLamportsPerSignature": 0,
                 "targetSignaturesPerSlot": 0
-            }],
+            }]},
             "id": 1
         });
         let expected: Response =

+ 3 - 1
core/src/rpc_service.rs

@@ -229,7 +229,9 @@ mod tests {
                 .request_processor
                 .read()
                 .unwrap()
-                .get_balance(&mint_keypair.pubkey(), None)
+                .get_balance(Ok(mint_keypair.pubkey()), None)
+                .unwrap()
+                .value
         );
         rpc_service.exit();
         rpc_service.join().unwrap();

+ 8 - 9
core/tests/client.rs

@@ -1,5 +1,6 @@
 use solana_client::rpc_client::RpcClient;
 use solana_core::validator::new_validator_for_tests;
+use solana_sdk::commitment_config::CommitmentConfig;
 use solana_sdk::pubkey::Pubkey;
 use solana_sdk::signature::KeypairUtil;
 use solana_sdk::system_transaction;
@@ -22,7 +23,6 @@ fn test_rpc_client() {
     );
 
     assert_eq!(client.get_balance(&bob_pubkey).unwrap(), 0);
-
     assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 10000);
 
     let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
@@ -34,14 +34,13 @@ fn test_rpc_client() {
 
     let now = Instant::now();
     while now.elapsed().as_secs() <= 20 {
-        let response = client.confirm_transaction(signature.as_str());
-
-        match response {
-            Ok(true) => {
-                confirmed_tx = true;
-                break;
-            }
-            _ => (),
+        let response = client
+            .confirm_transaction_with_commitment(signature.as_str(), CommitmentConfig::default())
+            .unwrap();
+
+        if response.value {
+            confirmed_tx = true;
+            break;
         }
 
         sleep(Duration::from_millis(500));

+ 6 - 2
core/tests/rpc.rs

@@ -34,7 +34,11 @@ fn test_rpc_send_tx() {
         .send()
         .unwrap();
     let json: Value = serde_json::from_str(&response.text().unwrap()).unwrap();
-    let blockhash: Hash = json["result"][0].as_str().unwrap().parse().unwrap();
+    let blockhash: Hash = json["result"]["value"][0]
+        .as_str()
+        .unwrap()
+        .parse()
+        .unwrap();
 
     info!("blockhash: {:?}", blockhash);
     let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash);
@@ -78,7 +82,7 @@ fn test_rpc_send_tx() {
         let response_json_text = response.text().unwrap();
         let json: Value = serde_json::from_str(&response_json_text).unwrap();
 
-        if true == json["result"] {
+        if true == json["result"]["value"] {
             confirmed_tx = true;
             break;
         }