Remove tuples from JSON RPC responses (#7806)

* Remove RpcConfirmedBlock tuple

* Remove getRecentBlockhash tuple

* Remove getProgramAccounts tuple

* Remove tuple from get_signature_confirmation_status

* Collect Rpc response types

* Camel-case epoch schedule for rpc response

* Remove getBlockCommitment tuple

* Remove getStorageTurn tuple

* Update json-rpc docs
This commit is contained in:
Tyera Eulberg 2020-01-15 00:25:45 -07:00 committed by GitHub
parent 50c1c08235
commit 6d3b8b6d7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 446 additions and 348 deletions

View File

@ -193,13 +193,13 @@ Returns commitment for particular block
#### Results:
The result field will be an array with two fields:
The result field will be a JSON object containing:
* Commitment
* `commitment` - commitment, comprising either:
* `null` - Unknown block
* `object` - BlockCommitment
* `array` - commitment, array of u64 integers logging the amount of cluster stake in lamports that has voted on the block at each depth from 0 to `MAX_LOCKOUT_HISTORY`
* 'integer' - total active stake, in lamports, of the current epoch
* `totalStake` - total active stake, in lamports, of the current epoch
#### Example:
@ -287,9 +287,9 @@ The result field will be an object with the following fields:
* `blockhash` - the blockhash of this block, as base-58 encoded string
* `previousBlockhash` - the blockhash of this block's parent, as base-58 encoded string
* `parentSlot` - the slot index of this block's parent
* `transactions` - an array of tuples containing:
* [Transaction](transaction-api.md) object, either in JSON format or base-58 encoded binary data, depending on encoding parameter
* Transaction status object, containing:
* `transactions` - an array of JSON objects containing:
* `transaction` - [Transaction](transaction-api.md) object, either in JSON format or base-58 encoded binary data, depending on encoding parameter
* `meta` - transaction status metadata object, containing `null` or:
* `status` - Transaction status:
* `"Ok": null` - Transaction was successful
* `"Err": <ERR>` - Transaction failed with TransactionError [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14)
@ -376,11 +376,11 @@ None
The result field will be an object with the following fields:
* `slots_per_epoch`, the maximum number of slots in each epoch
* `leader_schedule_slot_offset`, the number of slots before beginning of an epoch to calculate a leader schedule for that epoch
* `slotsPerEpoch`, the maximum number of slots in each epoch
* `leaderScheduleSlotOffset`, the number of slots before beginning of an epoch to calculate a leader schedule for that epoch
* `warmup`, whether epochs start short and grow
* `first_normal_epoch`, first normal-length epoch, log2(slots_per_epoch) - log2(MINIMUM_SLOTS_PER_EPOCH)
* `first_normal_slot`, MINIMUM_SLOTS_PER_EPOCH * (2.pow(first_normal_epoch) - 1)
* `firstNormalEpoch`, first normal-length epoch, log2(slotsPerEpoch) - log2(MINIMUM_SLOTS_PER_EPOCH)
* `firstNormalSlot`, MINIMUM_SLOTS_PER_EPOCH * (2.pow(firstNormalEpoch) - 1)
#### Example:
@ -389,7 +389,7 @@ The result field will be an object with the following fields:
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getEpochSchedule"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":{"first_normal_epoch":8,"first_normal_slot":8160,"leader_schedule_slot_offset":8192,"slots_per_epoch":8192,"warmup":true},"id":1}
{"jsonrpc":"2.0","result":{"firstNormalEpoch":8,"firstNormalSlot":8160,"leaderScheduleSlotOffset":8192,"slotsPerEpoch":8192,"warmup":true},"id":1}
```
### getGenesisHash
@ -526,9 +526,9 @@ Returns a recent block hash from the ledger, and a fee schedule that can be used
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
* `RpcResponse<array>` - RpcResponse JSON object with `value` field set to a JSON object including:
* `blockhash` - a Hash as base-58 encoded string
* `feeCalculator` - FeeCalculator object, the fee schedule for this block hash
#### Example:
@ -641,10 +641,10 @@ None
#### Results:
An array consisting of
A JSON object consisting of
* `string` - a Hash as base-58 encoded string indicating the blockhash of the turn slot
* `u64` - the current storage turn slot
* `blockhash` - a Hash as base-58 encoded string indicating the blockhash of the turn slot
* `slot` - the current storage turn slot
#### Example:
@ -652,7 +652,7 @@ An array consisting of
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getStorageTurn"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":["GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC", "2048"],"id":1}
{"jsonrpc":"2.0","result":{"blockhash": "GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC", "slot": "2048"},"id":1}
```
### getStorageTurnRate
@ -673,7 +673,7 @@ None
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getStorageTurnRate"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":"1024","id":1}
{"jsonrpc":"2.0","result":1024,"id":1}
```
### getTransactionCount

View File

@ -1989,7 +1989,8 @@ mod tests {
use serde_json::Value;
use solana_client::{
mock_rpc_client_request::SIGNATURE,
rpc_request::{self, RpcRequest, RpcResponseContext},
rpc_request::RpcRequest,
rpc_response::{Response, RpcResponseContext},
};
use solana_sdk::{
account::Account,
@ -2669,7 +2670,7 @@ mod tests {
// Nonced pay
let blockhash = Hash::default();
let nonce_response = json!(rpc_request::Response {
let nonce_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(Account::new_data(
1,
@ -2695,7 +2696,7 @@ mod tests {
let bob_keypair = Keypair::new();
let bob_pubkey = bob_keypair.pubkey();
let blockhash = Hash::default();
let nonce_authority_response = json!(rpc_request::Response {
let nonce_authority_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(Account::new_data(
1,

View File

@ -9,7 +9,7 @@ use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand};
use console::{style, Emoji};
use indicatif::{ProgressBar, ProgressStyle};
use solana_clap_utils::{input_parsers::*, input_validators::*};
use solana_client::{rpc_client::RpcClient, rpc_request::RpcVoteAccountInfo};
use solana_client::{rpc_client::RpcClient, rpc_response::RpcVoteAccountInfo};
use solana_sdk::{
clock::{self, Slot},
commitment_config::CommitmentConfig,

View File

@ -8,4 +8,5 @@ pub mod perf_utils;
pub mod rpc_client;
pub mod rpc_client_request;
pub mod rpc_request;
pub mod rpc_response;
pub mod thin_client;

View File

@ -1,7 +1,8 @@
use crate::rpc_request::{Response, RpcResponseContext};
use crate::{
client_error::ClientError, generic_rpc_client_request::GenericRpcClientRequest,
client_error::ClientError,
generic_rpc_client_request::GenericRpcClientRequest,
rpc_request::RpcRequest,
rpc_response::{Response, RpcResponseContext},
};
use serde_json::{Number, Value};
use solana_sdk::{

View File

@ -1,12 +1,12 @@
use crate::rpc_request::{Response, RpcResponse};
use crate::{
client_error::ClientError,
generic_rpc_client_request::GenericRpcClientRequest,
mock_rpc_client_request::{MockRpcClientRequest, Mocks},
rpc_client_request::RpcClientRequest,
rpc_request::{
RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule, RpcRequest,
RpcVersionInfo, RpcVoteAccountStatus,
rpc_request::RpcRequest,
rpc_response::{
Response, RpcBlockhashFeeCalculator, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo,
RpcLeaderSchedule, RpcResponse, RpcVersionInfo, RpcVoteAccountStatus,
},
};
use bincode::serialize;
@ -753,8 +753,12 @@ impl RpcClient {
let Response {
context,
value: (blockhash_str, fee_calculator),
} = serde_json::from_value::<Response<(String, FeeCalculator)>>(response).map_err(
value:
RpcBlockhashFeeCalculator {
blockhash,
fee_calculator,
},
} = serde_json::from_value::<Response<RpcBlockhashFeeCalculator>>(response).map_err(
|err| {
io::Error::new(
io::ErrorKind::Other,
@ -762,7 +766,7 @@ impl RpcClient {
)
},
)?;
let blockhash = blockhash_str.parse().map_err(|err| {
let blockhash = blockhash.parse().map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
format!("GetRecentBlockhash hash parse failure: {:?}", err),

View File

@ -1,197 +1,5 @@
use bincode::serialize;
use jsonrpc_core::Result as JsonResult;
use serde_json::{json, Value};
use solana_sdk::{
clock::{Epoch, Slot},
message::MessageHeader,
transaction::{Result, Transaction},
};
use std::{collections::HashMap, error, fmt, io, net::SocketAddr};
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(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcConfirmedBlock {
pub previous_blockhash: String,
pub blockhash: String,
pub parent_slot: Slot,
pub transactions: Vec<(RpcEncodedTransaction, Option<RpcTransactionStatus>)>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum RpcTransactionEncoding {
Binary,
Json,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub enum RpcEncodedTransaction {
Binary(String),
Json(RpcTransaction),
}
impl RpcEncodedTransaction {
pub fn encode(transaction: Transaction, encoding: RpcTransactionEncoding) -> Self {
if encoding == RpcTransactionEncoding::Json {
RpcEncodedTransaction::Json(RpcTransaction {
signatures: transaction
.signatures
.iter()
.map(|sig| sig.to_string())
.collect(),
message: RpcMessage {
header: transaction.message.header,
account_keys: transaction
.message
.account_keys
.iter()
.map(|pubkey| pubkey.to_string())
.collect(),
recent_blockhash: transaction.message.recent_blockhash.to_string(),
instructions: transaction
.message
.instructions
.iter()
.map(|instruction| RpcCompiledInstruction {
program_id_index: instruction.program_id_index,
accounts: instruction.accounts.clone(),
data: bs58::encode(instruction.data.clone()).into_string(),
})
.collect(),
},
})
} else {
RpcEncodedTransaction::Binary(
bs58::encode(serialize(&transaction).unwrap()).into_string(),
)
}
}
}
/// A duplicate representation of a Transaction for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcTransaction {
pub signatures: Vec<String>,
pub message: RpcMessage,
}
/// A duplicate representation of a Message for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcMessage {
pub header: MessageHeader,
pub account_keys: Vec<String>,
pub recent_blockhash: String,
pub instructions: Vec<RpcCompiledInstruction>,
}
/// A duplicate representation of a Message for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcCompiledInstruction {
pub program_id_index: u8,
pub accounts: Vec<u8>,
pub data: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcTransactionStatus {
pub status: Result<()>,
pub fee: u64,
pub pre_balances: Vec<u64>,
pub post_balances: Vec<u64>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RpcContactInfo {
/// Pubkey of the node as a base-58 string
pub pubkey: String,
/// Gossip port
pub gossip: Option<SocketAddr>,
/// Tpu port
pub tpu: Option<SocketAddr>,
/// JSON RPC port
pub rpc: Option<SocketAddr>,
}
/// Map of leader base58 identity pubkeys to the slot indices relative to the first epoch slot
pub type RpcLeaderSchedule = HashMap<String, Vec<usize>>;
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcEpochInfo {
/// The current epoch
pub epoch: Epoch,
/// The current slot, relative to the start of the current epoch
pub slot_index: u64,
/// The number of slots in this epoch
pub slots_in_epoch: u64,
/// The absolute current slot
pub absolute_slot: Slot,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "kebab-case")]
pub struct RpcVersionInfo {
/// The current version of solana-core
pub solana_core: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcVoteAccountStatus {
pub current: Vec<RpcVoteAccountInfo>,
pub delinquent: Vec<RpcVoteAccountInfo>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcVoteAccountInfo {
/// Vote account pubkey as base-58 encoded string
pub vote_pubkey: String,
/// The pubkey of the node that votes using this account
pub node_pubkey: String,
/// The current stake, in lamports, delegated to this vote account
pub activated_stake: u64,
/// An 8-bit integer used as a fraction (commission/MAX_U8) for rewards payout
pub commission: u8,
/// Whether this account is staked for the current epoch
pub epoch_vote_account: bool,
/// History of how many credits earned by the end of each epoch
/// each tuple is (Epoch, credits, prev_credits)
pub epoch_credits: Vec<(Epoch, u64, u64)>,
/// Most recent slot voted on by this vote account (0 if no votes exist)
pub last_vote: u64,
/// Current root slot for this vote account (0 if not root slot exists)
pub root_slot: Slot,
}
use std::{error, fmt};
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum RpcRequest {

237
client/src/rpc_response.rs Normal file
View File

@ -0,0 +1,237 @@
use bincode::serialize;
use jsonrpc_core::Result as JsonResult;
use solana_sdk::{
account::Account,
clock::{Epoch, Slot},
fee_calculator::FeeCalculator,
message::MessageHeader,
transaction::{Result, Transaction},
};
use std::{collections::HashMap, io, net::SocketAddr};
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(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcBlockCommitment<T> {
pub commitment: Option<T>,
pub total_stake: u64,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcConfirmedBlock {
pub previous_blockhash: String,
pub blockhash: String,
pub parent_slot: Slot,
pub transactions: Vec<RpcTransactionWithStatusMeta>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcTransactionWithStatusMeta {
pub transaction: RpcEncodedTransaction,
pub meta: Option<RpcTransactionStatus>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum RpcTransactionEncoding {
Binary,
Json,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub enum RpcEncodedTransaction {
Binary(String),
Json(RpcTransaction),
}
impl RpcEncodedTransaction {
pub fn encode(transaction: Transaction, encoding: RpcTransactionEncoding) -> Self {
if encoding == RpcTransactionEncoding::Json {
RpcEncodedTransaction::Json(RpcTransaction {
signatures: transaction
.signatures
.iter()
.map(|sig| sig.to_string())
.collect(),
message: RpcMessage {
header: transaction.message.header,
account_keys: transaction
.message
.account_keys
.iter()
.map(|pubkey| pubkey.to_string())
.collect(),
recent_blockhash: transaction.message.recent_blockhash.to_string(),
instructions: transaction
.message
.instructions
.iter()
.map(|instruction| RpcCompiledInstruction {
program_id_index: instruction.program_id_index,
accounts: instruction.accounts.clone(),
data: bs58::encode(instruction.data.clone()).into_string(),
})
.collect(),
},
})
} else {
RpcEncodedTransaction::Binary(
bs58::encode(serialize(&transaction).unwrap()).into_string(),
)
}
}
}
/// A duplicate representation of a Transaction for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcTransaction {
pub signatures: Vec<String>,
pub message: RpcMessage,
}
/// A duplicate representation of a Message for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcMessage {
pub header: MessageHeader,
pub account_keys: Vec<String>,
pub recent_blockhash: String,
pub instructions: Vec<RpcCompiledInstruction>,
}
/// A duplicate representation of a Message for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcCompiledInstruction {
pub program_id_index: u8,
pub accounts: Vec<u8>,
pub data: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcTransactionStatus {
pub status: Result<()>,
pub fee: u64,
pub pre_balances: Vec<u64>,
pub post_balances: Vec<u64>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcBlockhashFeeCalculator {
pub blockhash: String,
pub fee_calculator: FeeCalculator,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcKeyedAccount {
pub pubkey: String,
pub account: Account,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RpcContactInfo {
/// Pubkey of the node as a base-58 string
pub pubkey: String,
/// Gossip port
pub gossip: Option<SocketAddr>,
/// Tpu port
pub tpu: Option<SocketAddr>,
/// JSON RPC port
pub rpc: Option<SocketAddr>,
}
/// Map of leader base58 identity pubkeys to the slot indices relative to the first epoch slot
pub type RpcLeaderSchedule = HashMap<String, Vec<usize>>;
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcEpochInfo {
/// The current epoch
pub epoch: Epoch,
/// The current slot, relative to the start of the current epoch
pub slot_index: u64,
/// The number of slots in this epoch
pub slots_in_epoch: u64,
/// The absolute current slot
pub absolute_slot: Slot,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "kebab-case")]
pub struct RpcVersionInfo {
/// The current version of solana-core
pub solana_core: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcVoteAccountStatus {
pub current: Vec<RpcVoteAccountInfo>,
pub delinquent: Vec<RpcVoteAccountInfo>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcVoteAccountInfo {
/// Vote account pubkey as base-58 encoded string
pub vote_pubkey: String,
/// The pubkey of the node that votes using this account
pub node_pubkey: String,
/// The current stake, in lamports, delegated to this vote account
pub activated_stake: u64,
/// An 8-bit integer used as a fraction (commission/MAX_U8) for rewards payout
pub commission: u8,
/// Whether this account is staked for the current epoch
pub epoch_vote_account: bool,
/// History of how many credits earned by the end of each epoch
/// each tuple is (Epoch, credits, prev_credits)
pub epoch_credits: Vec<(Epoch, u64, u64)>,
/// Most recent slot voted on by this vote account (0 if no votes exist)
pub last_vote: u64,
/// Current root slot for this vote account (0 if not root slot exists)
pub root_slot: Slot,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcSignatureConfirmation {
pub confirmations: usize,
pub status: Result<()>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcStorageTurn {
pub blockhash: String,
pub slot: Slot,
}

View File

@ -3,8 +3,7 @@
//! messages to the network directly. The binary encoding of its messages are
//! unstable and may change in future releases.
use crate::rpc_client::RpcClient;
use crate::rpc_request::Response;
use crate::{rpc_client::RpcClient, rpc_response::Response};
use bincode::{serialize_into, serialized_size};
use log::*;
use solana_sdk::{

View File

@ -17,7 +17,10 @@ use crossbeam_channel::unbounded;
use ed25519_dalek;
use rand::{thread_rng, Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use solana_client::{rpc_client::RpcClient, rpc_request::RpcRequest, thin_client::ThinClient};
use solana_client::{
rpc_client::RpcClient, rpc_request::RpcRequest, rpc_response::RpcStorageTurn,
thin_client::ThinClient,
};
use solana_ledger::{
blockstore::Blockstore, leader_schedule_cache::LeaderScheduleCache, shred::Shred,
};
@ -811,13 +814,15 @@ impl Archiver {
warn!("Error while making rpc request {:?}", err);
Error::IO(io::Error::new(ErrorKind::Other, "rpc error"))
})?;
let (storage_blockhash, turn_slot) =
serde_json::from_value::<(String, u64)>(response).map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
format!("Couldn't parse response: {:?}", err),
)
})?;
let RpcStorageTurn {
blockhash: storage_blockhash,
slot: turn_slot,
} = serde_json::from_value::<RpcStorageTurn>(response).map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
format!("Couldn't parse response: {:?}", err),
)
})?;
let turn_blockhash = storage_blockhash.parse().map_err(|err| {
io::Error::new(
io::ErrorKind::Other,

View File

@ -1020,7 +1020,7 @@ mod tests {
};
use crossbeam_channel::unbounded;
use itertools::Itertools;
use solana_client::rpc_request::RpcEncodedTransaction;
use solana_client::rpc_response::{RpcEncodedTransaction, RpcTransactionWithStatusMeta};
use solana_ledger::{
blockstore::entries_to_test_shreds,
entry::{next_entry, Entry, EntrySlice},
@ -1978,20 +1978,22 @@ mod tests {
let confirmed_block = blockstore.get_confirmed_block(bank.slot(), None).unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for (transaction, result) in confirmed_block.transactions.into_iter() {
for RpcTransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let RpcEncodedTransaction::Json(transaction) = transaction {
if transaction.signatures[0] == success_signature.to_string() {
assert_eq!(result.unwrap().status, Ok(()));
assert_eq!(meta.unwrap().status, Ok(()));
} else if transaction.signatures[0] == ix_error_signature.to_string() {
assert_eq!(
result.unwrap().status,
meta.unwrap().status,
Err(TransactionError::InstructionError(
0,
InstructionError::CustomError(1)
))
);
} else {
assert_eq!(result, None);
assert_eq!(meta, None);
}
}
}

View File

@ -997,7 +997,7 @@ pub(crate) mod tests {
transaction_status_service::TransactionStatusService,
};
use crossbeam_channel::unbounded;
use solana_client::rpc_request::RpcEncodedTransaction;
use solana_client::rpc_response::{RpcEncodedTransaction, RpcTransactionWithStatusMeta};
use solana_ledger::{
block_error::BlockError,
blockstore::make_slot_entries,
@ -1011,22 +1011,21 @@ pub(crate) mod tests {
},
};
use solana_runtime::genesis_utils::GenesisConfigInfo;
use solana_sdk::account::Account;
use solana_sdk::rent::Rent;
use solana_sdk::{
account::Account,
hash::{hash, Hash},
instruction::InstructionError,
packet::PACKET_DATA_SIZE,
rent::Rent,
signature::{Keypair, KeypairUtil, Signature},
system_transaction,
transaction::TransactionError,
};
use solana_stake_program::stake_state;
use solana_vote_program::vote_state;
use solana_vote_program::vote_state::{Vote, VoteState};
use std::iter;
use solana_vote_program::vote_state::{self, Vote, VoteState};
use std::{
fs::remove_dir_all,
iter,
sync::{Arc, RwLock},
};
@ -1803,20 +1802,22 @@ pub(crate) mod tests {
let confirmed_block = blockstore.get_confirmed_block(slot, None).unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for (transaction, result) in confirmed_block.transactions.into_iter() {
for RpcTransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let RpcEncodedTransaction::Json(transaction) = transaction {
if transaction.signatures[0] == signatures[0].to_string() {
assert_eq!(result.unwrap().status, Ok(()));
assert_eq!(meta.unwrap().status, Ok(()));
} else if transaction.signatures[0] == signatures[1].to_string() {
assert_eq!(
result.unwrap().status,
meta.unwrap().status,
Err(TransactionError::InstructionError(
0,
InstructionError::CustomError(1)
))
);
} else {
assert_eq!(result, None);
assert_eq!(meta, None);
}
}
}

View File

@ -11,9 +11,10 @@ use crate::{
use bincode::serialize;
use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_client::rpc_request::{
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule,
RpcResponseContext, RpcTransactionEncoding, RpcVersionInfo, RpcVoteAccountInfo,
use solana_client::rpc_response::{
Response, RpcBlockCommitment, RpcBlockhashFeeCalculator, RpcConfirmedBlock, RpcContactInfo,
RpcEpochInfo, RpcKeyedAccount, RpcLeaderSchedule, RpcResponseContext, RpcSignatureConfirmation,
RpcStorageTurn, RpcTransactionEncoding, RpcVersionInfo, RpcVoteAccountInfo,
RpcVoteAccountStatus,
};
use solana_faucet::faucet::request_airdrop_transaction;
@ -26,7 +27,6 @@ use solana_sdk::{
clock::{Slot, UnixTimestamp},
commitment_config::{CommitmentConfig, CommitmentLevel},
epoch_schedule::EpochSchedule,
fee_calculator::FeeCalculator,
hash::Hash,
inflation::Inflation,
pubkey::Pubkey,
@ -134,12 +134,15 @@ impl JsonRpcRequestProcessor {
&self,
program_id: &Pubkey,
commitment: Option<CommitmentConfig>,
) -> Result<Vec<(String, Account)>> {
) -> Result<Vec<RpcKeyedAccount>> {
Ok(self
.bank(commitment)
.get_program_accounts(&program_id)
.into_iter()
.map(|(pubkey, account)| (pubkey.to_string(), account))
.map(|(pubkey, account)| RpcKeyedAccount {
pubkey: pubkey.to_string(),
account,
})
.collect())
}
@ -168,10 +171,16 @@ impl JsonRpcRequestProcessor {
fn get_recent_blockhash(
&self,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<(String, FeeCalculator)> {
) -> RpcResponse<RpcBlockhashFeeCalculator> {
let bank = &*self.bank(commitment);
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
new_response(bank, (blockhash.to_string(), fee_calculator))
new_response(
bank,
RpcBlockhashFeeCalculator {
blockhash: blockhash.to_string(),
fee_calculator,
},
)
}
pub fn confirm_transaction(
@ -192,21 +201,25 @@ impl JsonRpcRequestProcessor {
}
}
fn get_block_commitment(&self, block: Slot) -> (Option<BlockCommitment>, u64) {
fn get_block_commitment(&self, block: Slot) -> RpcBlockCommitment<BlockCommitment> {
let r_block_commitment = self.block_commitment_cache.read().unwrap();
(
r_block_commitment.get_block_commitment(block).cloned(),
r_block_commitment.total_stake(),
)
RpcBlockCommitment {
commitment: r_block_commitment.get_block_commitment(block).cloned(),
total_stake: r_block_commitment.total_stake(),
}
}
pub fn get_signature_confirmation_status(
&self,
signature: Signature,
commitment: Option<CommitmentConfig>,
) -> Option<(usize, transaction::Result<()>)> {
) -> Option<RpcSignatureConfirmation> {
self.bank(commitment)
.get_signature_confirmation_status(&signature)
.map(|(confirmations, status)| RpcSignatureConfirmation {
confirmations,
status,
})
}
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
@ -283,11 +296,11 @@ impl JsonRpcRequestProcessor {
Ok(self.storage_state.get_storage_turn_rate())
}
fn get_storage_turn(&self) -> Result<(String, u64)> {
Ok((
self.storage_state.get_storage_blockhash().to_string(),
self.storage_state.get_slot(),
))
fn get_storage_turn(&self) -> Result<RpcStorageTurn> {
Ok(RpcStorageTurn {
blockhash: self.storage_state.get_storage_blockhash().to_string(),
slot: self.storage_state.get_slot(),
})
}
fn get_slots_per_segment(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
@ -407,7 +420,7 @@ pub trait RpcSol {
meta: Self::Metadata,
program_id_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Vec<(String, Account)>>;
) -> Result<Vec<RpcKeyedAccount>>;
#[rpc(meta, name = "getMinimumBalanceForRentExemption")]
fn get_minimum_balance_for_rent_exemption(
@ -450,7 +463,7 @@ pub trait RpcSol {
&self,
meta: Self::Metadata,
block: Slot,
) -> Result<(Option<BlockCommitment>, u64)>;
) -> Result<RpcBlockCommitment<BlockCommitment>>;
#[rpc(meta, name = "getGenesisHash")]
fn get_genesis_hash(&self, meta: Self::Metadata) -> Result<String>;
@ -468,7 +481,7 @@ pub trait RpcSol {
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<(String, FeeCalculator)>;
) -> RpcResponse<RpcBlockhashFeeCalculator>;
#[rpc(meta, name = "getSignatureStatus")]
fn get_signature_status(
@ -525,7 +538,7 @@ pub trait RpcSol {
fn get_storage_turn_rate(&self, meta: Self::Metadata) -> Result<u64>;
#[rpc(meta, name = "getStorageTurn")]
fn get_storage_turn(&self, meta: Self::Metadata) -> Result<(String, u64)>;
fn get_storage_turn(&self, meta: Self::Metadata) -> Result<RpcStorageTurn>;
#[rpc(meta, name = "getSlotsPerSegment")]
fn get_slots_per_segment(
@ -554,7 +567,7 @@ pub trait RpcSol {
meta: Self::Metadata,
signature_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Option<(usize, transaction::Result<()>)>>;
) -> Result<Option<RpcSignatureConfirmation>>;
#[rpc(meta, name = "getVersion")]
fn get_version(&self, meta: Self::Metadata) -> Result<RpcVersionInfo>;
@ -635,7 +648,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata,
program_id_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Vec<(String, Account)>> {
) -> Result<Vec<RpcKeyedAccount>> {
debug!(
"get_program_accounts rpc request received: {:?}",
program_id_str
@ -734,7 +747,7 @@ impl RpcSol for RpcSolImpl {
&self,
meta: Self::Metadata,
block: Slot,
) -> Result<(Option<BlockCommitment>, u64)> {
) -> Result<RpcBlockCommitment<BlockCommitment>> {
Ok(meta
.request_processor
.read()
@ -778,7 +791,7 @@ impl RpcSol for RpcSolImpl {
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<(String, FeeCalculator)> {
) -> RpcResponse<RpcBlockhashFeeCalculator> {
debug!("get_recent_blockhash rpc request received");
meta.request_processor
.read()
@ -793,7 +806,7 @@ impl RpcSol for RpcSolImpl {
commitment: Option<CommitmentConfig>,
) -> Result<Option<transaction::Result<()>>> {
self.get_signature_confirmation(meta, signature_str, commitment)
.map(|res| res.map(|x| x.1))
.map(|res| res.map(|x| x.status))
}
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64> {
@ -807,7 +820,7 @@ impl RpcSol for RpcSolImpl {
commitment: Option<CommitmentConfig>,
) -> Result<Option<usize>> {
self.get_signature_confirmation(meta, signature_str, commitment)
.map(|res| res.map(|x| x.0))
.map(|res| res.map(|x| x.confirmations))
}
fn get_signature_confirmation(
@ -815,7 +828,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata,
signature_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Option<(usize, transaction::Result<()>)>> {
) -> Result<Option<RpcSignatureConfirmation>> {
debug!(
"get_signature_confirmation rpc request received: {:?}",
signature_str
@ -915,7 +928,7 @@ impl RpcSol for RpcSolImpl {
.read()
.unwrap()
.get_signature_confirmation_status(signature, commitment.clone())
.map(|x| x.1);
.map(|x| x.status);
if signature_status == Some(Ok(())) {
info!("airdrop signature ok");
@ -992,7 +1005,7 @@ impl RpcSol for RpcSolImpl {
.get_storage_turn_rate()
}
fn get_storage_turn(&self, meta: Self::Metadata) -> Result<(String, u64)> {
fn get_storage_turn(&self, meta: Self::Metadata) -> Result<RpcStorageTurn> {
meta.request_processor.read().unwrap().get_storage_turn()
}
@ -1072,7 +1085,7 @@ pub mod tests {
};
use bincode::deserialize;
use jsonrpc_core::{MetaIoHandler, Output, Response, Value};
use solana_client::rpc_request::RpcEncodedTransaction;
use solana_client::rpc_response::{RpcEncodedTransaction, RpcTransactionWithStatusMeta};
use solana_ledger::{
blockstore::entries_to_test_shreds, blockstore_processor::fill_blockstore_slot_with_ticks,
entry::next_entry_mut, get_tmp_ledger_path,
@ -1538,7 +1551,7 @@ pub mod tests {
"lamports": 20,
"data": [],
"executable": false,
"rent_epoch": 0
"rentEpoch": 0
},
},
"id": 1,
@ -1572,13 +1585,18 @@ pub mod tests {
let expected = format!(
r#"{{
"jsonrpc":"2.0",
"result":[["{}", {{
"owner": {:?},
"lamports": 20,
"data": [],
"executable": false,
"rent_epoch": 0
}}]],
"result":[
{{
"pubkey": "{}",
"account": {{
"owner": {:?},
"lamports": 20,
"data": [],
"executable": false,
"rentEpoch": 0
}}
}}
],
"id":1}}
"#,
bob.pubkey(),
@ -1709,14 +1727,17 @@ pub mod tests {
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":[ blockhash.to_string(), {
"burnPercent": DEFAULT_BURN_PERCENT,
"lamportsPerSignature": 0,
"maxLamportsPerSignature": 0,
"minLamportsPerSignature": 0,
"targetLamportsPerSignature": 0,
"targetSignaturesPerSlot": 0
}]},
"value":{
"blockhash": blockhash.to_string(),
"feeCalculator": {
"burnPercent": DEFAULT_BURN_PERCENT,
"lamportsPerSignature": 0,
"maxLamportsPerSignature": 0,
"minLamportsPerSignature": 0,
"targetLamportsPerSignature": 0,
"targetSignaturesPerSlot": 0
}
}},
"id": 1
});
let expected: Response =
@ -1941,13 +1962,25 @@ pub mod tests {
);
assert_eq!(
request_processor.get_block_commitment(0),
(Some(commitment_slot0), 42)
RpcBlockCommitment {
commitment: Some(commitment_slot0),
total_stake: 42,
}
);
assert_eq!(
request_processor.get_block_commitment(1),
(Some(commitment_slot1), 42)
RpcBlockCommitment {
commitment: Some(commitment_slot1),
total_stake: 42,
}
);
assert_eq!(
request_processor.get_block_commitment(2),
RpcBlockCommitment {
commitment: None,
total_stake: 42,
}
);
assert_eq!(request_processor.get_block_commitment(2), (None, 42));
}
#[test]
@ -1965,16 +1998,18 @@ pub mod tests {
let res = io.handle_request_sync(&req, meta.clone());
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let (commitment, total_staked): (Option<BlockCommitment>, u64) =
if let Response::Single(res) = result {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {
panic!("Expected success");
}
let RpcBlockCommitment {
commitment,
total_stake,
} = if let Response::Single(res) = result {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {
panic!("Expected single response");
};
panic!("Expected success");
}
} else {
panic!("Expected single response");
};
assert_eq!(
commitment,
block_commitment_cache
@ -1983,14 +2018,14 @@ pub mod tests {
.get_block_commitment(0)
.cloned()
);
assert_eq!(total_staked, 42);
assert_eq!(total_stake, 42);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getBlockCommitment","params":[2]}}"#);
let res = io.handle_request_sync(&req, meta);
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let (commitment, total_staked): (Option<BlockCommitment>, u64) =
let commitment_response: RpcBlockCommitment<BlockCommitment> =
if let Response::Single(res) = result {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
@ -2000,8 +2035,8 @@ pub mod tests {
} else {
panic!("Expected single response");
};
assert_eq!(commitment, None);
assert_eq!(total_staked, 42);
assert_eq!(commitment_response.commitment, None);
assert_eq!(commitment_response.total_stake, 42);
}
#[test]
@ -2025,21 +2060,23 @@ pub mod tests {
let confirmed_block = confirmed_block.unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for (transaction, result) in confirmed_block.transactions.into_iter() {
for RpcTransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let RpcEncodedTransaction::Json(transaction) = transaction {
if transaction.signatures[0] == confirmed_block_signatures[0].to_string() {
assert_eq!(transaction.message.recent_blockhash, blockhash.to_string());
assert_eq!(result.unwrap().status, Ok(()));
assert_eq!(meta.unwrap().status, Ok(()));
} else if transaction.signatures[0] == confirmed_block_signatures[1].to_string() {
assert_eq!(
result.unwrap().status,
meta.unwrap().status,
Err(TransactionError::InstructionError(
0,
InstructionError::CustomError(1)
))
);
} else {
assert_eq!(result, None);
assert_eq!(meta, None);
}
}
}
@ -2055,23 +2092,25 @@ pub mod tests {
let confirmed_block = confirmed_block.unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for (transaction, result) in confirmed_block.transactions.into_iter() {
for RpcTransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let RpcEncodedTransaction::Binary(transaction) = transaction {
let decoded_transaction: Transaction =
deserialize(&bs58::decode(&transaction).into_vec().unwrap()).unwrap();
if decoded_transaction.signatures[0] == confirmed_block_signatures[0] {
assert_eq!(decoded_transaction.message.recent_blockhash, blockhash);
assert_eq!(result.unwrap().status, Ok(()));
assert_eq!(meta.unwrap().status, Ok(()));
} else if decoded_transaction.signatures[0] == confirmed_block_signatures[1] {
assert_eq!(
result.unwrap().status,
meta.unwrap().status,
Err(TransactionError::InstructionError(
0,
InstructionError::CustomError(1)
))
);
} else {
assert_eq!(result, None);
assert_eq!(meta, None);
}
}
}

View File

@ -471,7 +471,7 @@ mod tests {
"lamports": 51,
"data": expected_data,
"executable": false,
"rent_epoch": 1,
"rentEpoch": 1,
},
"subscription": 0,
}
@ -618,7 +618,7 @@ mod tests {
"lamports": 100,
"data": [],
"executable": false,
"rent_epoch": 1,
"rentEpoch": 1,
},
"subscription": 0,
}

View File

@ -376,7 +376,7 @@ mod tests {
let string = transport_receiver.poll();
if let Async::Ready(Some(response)) = string.unwrap() {
let expected = format!(
r#"{{"jsonrpc":"2.0","method":"accountNotification","params":{{"result":{{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"executable":false,"lamports":1,"owner":[2,203,81,223,225,24,34,35,203,214,138,130,144,208,35,77,63,16,87,51,47,198,115,123,98,188,19,160,0,0,0,0],"rent_epoch":1}},"subscription":0}}}}"#
r#"{{"jsonrpc":"2.0","method":"accountNotification","params":{{"result":{{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"executable":false,"lamports":1,"owner":[2,203,81,223,225,24,34,35,203,214,138,130,144,208,35,77,63,16,87,51,47,198,115,123,98,188,19,160,0,0,0,0],"rentEpoch":1}},"subscription":0}}}}"#
);
assert_eq!(expected, response);
}
@ -433,7 +433,7 @@ mod tests {
let string = transport_receiver.poll();
if let Async::Ready(Some(response)) = string.unwrap() {
let expected = format!(
r#"{{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["{:?}",{{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"executable":false,"lamports":1,"owner":[2,203,81,223,225,24,34,35,203,214,138,130,144,208,35,77,63,16,87,51,47,198,115,123,98,188,19,160,0,0,0,0],"rent_epoch":1}}],"subscription":0}}}}"#,
r#"{{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["{:?}",{{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"executable":false,"lamports":1,"owner":[2,203,81,223,225,24,34,35,203,214,138,130,144,208,35,77,63,16,87,51,47,198,115,123,98,188,19,160,0,0,0,0],"rentEpoch":1}}],"subscription":0}}}}"#,
alice.pubkey()
);
assert_eq!(expected, response);

View File

@ -1,5 +1,5 @@
use crossbeam_channel::{Receiver, RecvTimeoutError};
use solana_client::rpc_request::RpcTransactionStatus;
use solana_client::rpc_response::RpcTransactionStatus;
use solana_ledger::{blockstore::Blockstore, blockstore_processor::TransactionStatusBatch};
use solana_runtime::bank::{Bank, HashAgeKind};
use std::{

View File

@ -34,7 +34,7 @@ fn test_rpc_send_tx() {
.send()
.unwrap();
let json: Value = serde_json::from_str(&response.text().unwrap()).unwrap();
let blockhash: Hash = json["result"]["value"][0]
let blockhash: Hash = json["result"]["value"]["blockhash"]
.as_str()
.unwrap()
.parse()

View File

@ -21,8 +21,9 @@ use rayon::{
ThreadPool,
};
use rocksdb::DBRawIterator;
use solana_client::rpc_request::{
use solana_client::rpc_response::{
RpcConfirmedBlock, RpcEncodedTransaction, RpcTransactionEncoding, RpcTransactionStatus,
RpcTransactionWithStatusMeta,
};
use solana_measure::measure::Measure;
use solana_metrics::{datapoint_debug, datapoint_error};
@ -1403,18 +1404,19 @@ impl Blockstore {
slot: Slot,
encoding: RpcTransactionEncoding,
iterator: impl Iterator<Item = Transaction> + 'a,
) -> Vec<(RpcEncodedTransaction, Option<RpcTransactionStatus>)> {
) -> Vec<RpcTransactionWithStatusMeta> {
iterator
.map(|transaction| {
let signature = transaction.signatures[0];
let encoded_transaction =
RpcEncodedTransaction::encode(transaction, encoding.clone());
(
encoded_transaction,
self.transaction_status_cf
RpcTransactionWithStatusMeta {
transaction: encoded_transaction,
meta: self
.transaction_status_cf
.get((slot, signature))
.expect("Expect database get to succeed"),
)
}
})
.collect()
}
@ -4748,11 +4750,9 @@ pub mod tests {
transactions: expected_transactions
.iter()
.cloned()
.map(|(tx, status)| {
(
RpcEncodedTransaction::encode(tx, RpcTransactionEncoding::Json),
status,
)
.map(|(tx, meta)| RpcTransactionWithStatusMeta {
transaction: RpcEncodedTransaction::encode(tx, RpcTransactionEncoding::Json),
meta,
})
.collect(),
parent_slot: slot - 1,
@ -4770,11 +4770,9 @@ pub mod tests {
transactions: expected_transactions
.iter()
.cloned()
.map(|(tx, status)| {
(
RpcEncodedTransaction::encode(tx, RpcTransactionEncoding::Json),
status,
)
.map(|(tx, meta)| RpcTransactionWithStatusMeta {
transaction: RpcEncodedTransaction::encode(tx, RpcTransactionEncoding::Json),
meta,
})
.collect(),
parent_slot: slot,
@ -5007,9 +5005,9 @@ pub mod tests {
);
assert_eq!(map.len(), 5);
for x in 0..4 {
assert_eq!(map[x].1.as_ref().unwrap().fee, x as u64);
assert_eq!(map[x].meta.as_ref().unwrap().fee, x as u64);
}
assert_eq!(map[4].1.as_ref(), None);
assert_eq!(map[4].meta, None);
}
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
}

View File

@ -10,7 +10,7 @@ use rocksdb::{
};
use serde::de::DeserializeOwned;
use serde::Serialize;
use solana_client::rpc_request::RpcTransactionStatus;
use solana_client::rpc_response::RpcTransactionStatus;
use solana_sdk::{clock::Slot, signature::Signature};
use std::{collections::HashMap, fs, marker::PhantomData, path::Path, sync::Arc};
use thiserror::Error;

View File

@ -5,6 +5,7 @@ use std::{cmp, fmt, iter::FromIterator};
/// An Account with data that is stored on chain
#[repr(C)]
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "camelCase")]
pub struct Account {
/// lamports in the account
pub lamports: u64,

View File

@ -13,6 +13,7 @@ pub const MINIMUM_SLOTS_PER_EPOCH: u64 = 32;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EpochSchedule {
/// The maximum number of slots in each epoch.
pub slots_per_epoch: u64,