Use rooted bank by default in rpc bank selection (#6759)
* Name anonymous parameters for clarity * Add CommitmentConfig to select bank for rpc * Add commitment information to jsonrpc docs * Update send_and_confirm retries as per commitment defaults * Pass CommitmentConfig into client requests; also various 'use' cleanup * Use _with_commitment methods to speed local_cluster tests * Pass CommitmentConfig into Archiver in order to enable quick confirmations in local_cluster tests * Restore solana ping speed * Increase wallet-sanity timeout to account for longer confirmation time
This commit is contained in:
parent
5e8668799c
commit
b3a75a60a4
@ -1,13 +1,15 @@
|
||||
use clap::{crate_description, crate_name, crate_version, App, Arg};
|
||||
use console::style;
|
||||
use solana_core::archiver::Archiver;
|
||||
use solana_core::cluster_info::{Node, VALIDATOR_PORT_RANGE};
|
||||
use solana_core::contact_info::ContactInfo;
|
||||
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
use std::sync::Arc;
|
||||
use solana_core::{
|
||||
archiver::Archiver,
|
||||
cluster_info::{Node, VALIDATOR_PORT_RANGE},
|
||||
contact_info::ContactInfo,
|
||||
};
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig,
|
||||
signature::{read_keypair_file, Keypair, KeypairUtil},
|
||||
};
|
||||
use std::{net::SocketAddr, path::PathBuf, process::exit, sync::Arc};
|
||||
|
||||
// Return an error if a keypair file cannot be parsed.
|
||||
fn is_keypair(string: String) -> Result<(), String> {
|
||||
@ -118,6 +120,7 @@ fn main() {
|
||||
entrypoint_info,
|
||||
Arc::new(keypair),
|
||||
Arc::new(storage_keypair),
|
||||
CommitmentConfig::recent(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -8,31 +8,35 @@ use rayon::prelude::*;
|
||||
use solana_client::perf_utils::{sample_txs, SampleStats};
|
||||
use solana_core::gen_keys::GenKeys;
|
||||
use solana_drone::drone::request_airdrop_transaction;
|
||||
use solana_exchange_api::exchange_instruction;
|
||||
use solana_exchange_api::exchange_state::*;
|
||||
use solana_exchange_api::id;
|
||||
use solana_exchange_api::{exchange_instruction, exchange_state::*, id};
|
||||
use solana_genesis::Base64Account;
|
||||
use solana_metrics::datapoint_info;
|
||||
use solana_sdk::client::Client;
|
||||
use solana_sdk::client::SyncClient;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::timing::{duration_as_ms, duration_as_s};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_sdk::{system_instruction, system_program};
|
||||
use std::cmp;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::mem;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use std::process::exit;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread::{sleep, Builder};
|
||||
use std::time::{Duration, Instant};
|
||||
use solana_sdk::{
|
||||
client::{Client, SyncClient},
|
||||
commitment_config::CommitmentConfig,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
timing::{duration_as_ms, duration_as_s},
|
||||
transaction::Transaction,
|
||||
{system_instruction, system_program},
|
||||
};
|
||||
use std::{
|
||||
cmp,
|
||||
collections::{HashMap, VecDeque},
|
||||
fs::File,
|
||||
io::prelude::*,
|
||||
mem,
|
||||
net::SocketAddr,
|
||||
path::Path,
|
||||
process::exit,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
Arc, RwLock,
|
||||
},
|
||||
thread::{sleep, Builder},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
// TODO Chunk length as specified results in a bunch of failures, divide by 10 helps...
|
||||
// Assume 4MB network buffers, and 512 byte packets
|
||||
@ -380,7 +384,10 @@ fn swapper<T>(
|
||||
let mut tries = 0;
|
||||
let mut trade_index = 0;
|
||||
while client
|
||||
.get_balance(&trade_infos[trade_index].trade_account)
|
||||
.get_balance_with_commitment(
|
||||
&trade_infos[trade_index].trade_account,
|
||||
CommitmentConfig::recent(),
|
||||
)
|
||||
.unwrap_or(0)
|
||||
== 0
|
||||
{
|
||||
@ -434,7 +441,7 @@ fn swapper<T>(
|
||||
account_group = (account_group + 1) % account_groups as usize;
|
||||
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash()
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.expect("Failed to get blockhash");
|
||||
let to_swap_txs: Vec<_> = to_swap
|
||||
.par_iter()
|
||||
@ -562,7 +569,7 @@ fn trader<T>(
|
||||
account_group = (account_group + 1) % account_groups as usize;
|
||||
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash()
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.expect("Failed to get blockhash");
|
||||
|
||||
trades.chunks(chunk_size).for_each(|chunk| {
|
||||
@ -638,7 +645,9 @@ where
|
||||
T: SyncClient + ?Sized,
|
||||
{
|
||||
for s in &tx.signatures {
|
||||
if let Ok(Some(r)) = sync_client.get_signature_status(s) {
|
||||
if let Ok(Some(r)) =
|
||||
sync_client.get_signature_status_with_commitment(s, CommitmentConfig::recent())
|
||||
{
|
||||
match r {
|
||||
Ok(_) => {
|
||||
return true;
|
||||
@ -659,12 +668,15 @@ fn verify_funding_transfer<T: SyncClient + ?Sized>(
|
||||
) -> bool {
|
||||
if verify_transaction(client, tx) {
|
||||
for a in &tx.message().account_keys[1..] {
|
||||
if client.get_balance(a).unwrap_or(0) >= amount {
|
||||
if client
|
||||
.get_balance_with_commitment(a, CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
>= amount
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
@ -742,8 +754,9 @@ pub fn fund_keys(client: &dyn Client, source: &Keypair, dests: &[Arc<Keypair>],
|
||||
to_fund_txs.len(),
|
||||
);
|
||||
|
||||
let (blockhash, _fee_calculator) =
|
||||
client.get_recent_blockhash().expect("blockhash");
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.expect("blockhash");
|
||||
to_fund_txs.par_iter_mut().for_each(|(k, tx)| {
|
||||
tx.sign(&[*k], blockhash);
|
||||
});
|
||||
@ -780,7 +793,11 @@ pub fn fund_keys(client: &dyn Client, source: &Keypair, dests: &[Arc<Keypair>],
|
||||
});
|
||||
funded.append(&mut new_funded);
|
||||
funded.retain(|(k, b)| {
|
||||
client.get_balance(&k.pubkey()).unwrap_or(0) > lamports && *b > lamports
|
||||
client
|
||||
.get_balance_with_commitment(&k.pubkey(), CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
> lamports
|
||||
&& *b > lamports
|
||||
});
|
||||
debug!(" Funded: {} left: {}", funded.len(), notfunded.len());
|
||||
}
|
||||
@ -819,7 +836,7 @@ pub fn create_token_accounts(client: &dyn Client, signers: &[Arc<Keypair>], acco
|
||||
let mut retries = 0;
|
||||
while !to_create_txs.is_empty() {
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash()
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.expect("Failed to get blockhash");
|
||||
to_create_txs.par_iter_mut().for_each(|(k, tx)| {
|
||||
let kp: &Keypair = k;
|
||||
@ -863,7 +880,11 @@ pub fn create_token_accounts(client: &dyn Client, signers: &[Arc<Keypair>], acco
|
||||
|
||||
let mut new_notfunded: Vec<(&Arc<Keypair>, &Pubkey)> = vec![];
|
||||
for f in ¬funded {
|
||||
if client.get_balance(&f.1).unwrap_or(0) == 0 {
|
||||
if client
|
||||
.get_balance_with_commitment(&f.1, CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
== 0
|
||||
{
|
||||
new_notfunded.push(*f)
|
||||
}
|
||||
}
|
||||
@ -920,7 +941,7 @@ fn generate_keypairs(num: u64) -> Vec<Keypair> {
|
||||
}
|
||||
|
||||
pub fn airdrop_lamports(client: &dyn Client, drone_addr: &SocketAddr, id: &Keypair, amount: u64) {
|
||||
let balance = client.get_balance(&id.pubkey());
|
||||
let balance = client.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent());
|
||||
let balance = balance.unwrap_or(0);
|
||||
if balance >= amount {
|
||||
return;
|
||||
@ -938,19 +959,26 @@ pub fn airdrop_lamports(client: &dyn Client, drone_addr: &SocketAddr, id: &Keypa
|
||||
let mut tries = 0;
|
||||
loop {
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash()
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.expect("Failed to get blockhash");
|
||||
match request_airdrop_transaction(&drone_addr, &id.pubkey(), amount_to_drop, blockhash) {
|
||||
Ok(transaction) => {
|
||||
let signature = client.async_send_transaction(transaction).unwrap();
|
||||
|
||||
for _ in 0..30 {
|
||||
if let Ok(Some(_)) = client.get_signature_status(&signature) {
|
||||
if let Ok(Some(_)) = client.get_signature_status_with_commitment(
|
||||
&signature,
|
||||
CommitmentConfig::recent(),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(100));
|
||||
}
|
||||
if client.get_balance(&id.pubkey()).unwrap_or(0) >= amount {
|
||||
if client
|
||||
.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
>= amount
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
use solana_metrics;
|
||||
|
||||
use crate::cli::Config;
|
||||
use log::*;
|
||||
use rayon::prelude::*;
|
||||
@ -9,10 +7,11 @@ use solana_drone::drone::request_airdrop_transaction;
|
||||
#[cfg(feature = "move")]
|
||||
use solana_librapay_api::{create_genesis, upload_mint_program, upload_payment_program};
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::datapoint_debug;
|
||||
use solana_metrics::{self, datapoint_debug};
|
||||
use solana_sdk::{
|
||||
client::Client,
|
||||
clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE},
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
@ -55,7 +54,7 @@ type LibraKeys = (Keypair, Pubkey, Pubkey, Vec<Keypair>);
|
||||
|
||||
fn get_recent_blockhash<T: Client>(client: &T) -> (Hash, FeeCalculator) {
|
||||
loop {
|
||||
match client.get_recent_blockhash() {
|
||||
match client.get_recent_blockhash_with_commitment(CommitmentConfig::recent()) {
|
||||
Ok((blockhash, fee_calculator)) => return (blockhash, fee_calculator),
|
||||
Err(err) => {
|
||||
info!("Couldn't get recent blockhash: {:?}", err);
|
||||
@ -451,7 +450,11 @@ fn do_tx_transfers<T: Client>(
|
||||
|
||||
fn verify_funding_transfer<T: Client>(client: &T, tx: &Transaction, amount: u64) -> bool {
|
||||
for a in &tx.message().account_keys[1..] {
|
||||
if client.get_balance(a).unwrap_or(0) >= amount {
|
||||
if client
|
||||
.get_balance_with_commitment(a, CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
>= amount
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -666,10 +669,12 @@ pub fn airdrop_lamports<T: Client>(
|
||||
}
|
||||
};
|
||||
|
||||
let current_balance = client.get_balance(&id.pubkey()).unwrap_or_else(|e| {
|
||||
info!("airdrop error {}", e);
|
||||
starting_balance
|
||||
});
|
||||
let current_balance = client
|
||||
.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent())
|
||||
.unwrap_or_else(|e| {
|
||||
info!("airdrop error {}", e);
|
||||
starting_balance
|
||||
});
|
||||
info!("current balance {}...", current_balance);
|
||||
|
||||
metrics_submit_lamport_balance(current_balance);
|
||||
@ -815,7 +820,11 @@ fn fund_move_keys<T: Client>(
|
||||
let create_len = 8;
|
||||
let mut funding_time = Measure::start("funding_time");
|
||||
for (i, keys) in keypairs.chunks(create_len).enumerate() {
|
||||
if client.get_balance(&keys[0].pubkey()).unwrap_or(0) > 0 {
|
||||
if client
|
||||
.get_balance_with_commitment(&keys[0].pubkey(), CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
> 0
|
||||
{
|
||||
// already created these accounts.
|
||||
break;
|
||||
}
|
||||
@ -853,7 +862,9 @@ fn fund_move_keys<T: Client>(
|
||||
client.send_message(&[funding_key], tx.message).unwrap();
|
||||
let mut balance = 0;
|
||||
for _ in 0..20 {
|
||||
if let Ok(balance_) = client.get_balance(&funding_keys[0].pubkey()) {
|
||||
if let Ok(balance_) = client
|
||||
.get_balance_with_commitment(&funding_keys[0].pubkey(), CommitmentConfig::recent())
|
||||
{
|
||||
if balance_ > 0 {
|
||||
balance = balance_;
|
||||
break;
|
||||
@ -1078,7 +1089,12 @@ mod tests {
|
||||
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, false).unwrap();
|
||||
|
||||
for kp in &keypairs {
|
||||
assert_eq!(client.get_balance(&kp.pubkey()).unwrap(), lamports);
|
||||
assert_eq!(
|
||||
client
|
||||
.get_balance_with_commitment(&kp.pubkey(), CommitmentConfig::recent())
|
||||
.unwrap(),
|
||||
lamports
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1096,7 +1112,7 @@ mod tests {
|
||||
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, false).unwrap();
|
||||
|
||||
let max_fee = client
|
||||
.get_recent_blockhash()
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap()
|
||||
.1
|
||||
.max_lamports_per_signature;
|
||||
|
@ -78,6 +78,24 @@ Requests can be sent in batches by sending an array of JSON-RPC request objects
|
||||
* Signature: An Ed25519 signature of a chunk of data.
|
||||
* Transaction: A Solana instruction signed by a client key-pair.
|
||||
|
||||
## Configuring State Commitment
|
||||
|
||||
Solana nodes choose which bank state to query based on a commitment requirement
|
||||
set by the client. Clients may specify either:
|
||||
* `{"commitment":"max"}` - the node will query the most recent bank having reached `MAX_LOCKOUT_HISTORY` confirmations
|
||||
* `{"commitment":"recent"}` - the node will query its most recent bank state
|
||||
|
||||
The commitment parameter should be included as the last element in the `params` array:
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getBalance", "params":["83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",{"commitment":"max"}]}' 192.168.1.88:8899
|
||||
```
|
||||
|
||||
#### Default:
|
||||
If commitment configuration is not provided, the node will default to `"commitment":"max"`
|
||||
|
||||
Only methods that query bank state accept the commitment parameter. They are indicated in the API Reference below.
|
||||
|
||||
## JSON RPC API Reference
|
||||
|
||||
### confirmTransaction
|
||||
@ -91,6 +109,7 @@ Returns a transaction receipt
|
||||
#### Results:
|
||||
|
||||
* `boolean` - Transaction status, true if Transaction is confirmed
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Example:
|
||||
|
||||
@ -109,6 +128,7 @@ Returns all information associated with the account of provided Pubkey
|
||||
#### Parameters:
|
||||
|
||||
* `string` - Pubkey of account to query, as base-58 encoded string
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -136,6 +156,7 @@ Returns the balance of the account of provided Pubkey
|
||||
#### Parameters:
|
||||
|
||||
* `string` - Pubkey of account to query, as base-58 encoded string
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -212,7 +233,7 @@ Returns information about the current epoch
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -288,7 +309,7 @@ Returns the leader schedule for the current epoch
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -311,6 +332,7 @@ Returns minimum balance required to make account rent exempt.
|
||||
#### Parameters:
|
||||
|
||||
* `integer` - account data length, as unsigned integer
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -333,6 +355,7 @@ Returns the current number of blocks since signature has been confirmed.
|
||||
#### Parameters:
|
||||
|
||||
* `string` - Signature of Transaction to confirm, as base-58 encoded string
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -355,6 +378,7 @@ Returns all accounts owned by the provided program Pubkey
|
||||
#### Parameters:
|
||||
|
||||
* `string` - Pubkey of program, as base-58 encoded string
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -382,7 +406,7 @@ Returns a recent block hash from the ledger, and a fee schedule that can be used
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -408,6 +432,7 @@ Returns the status of a given signature. This method is similar to [confirmTrans
|
||||
#### Parameters:
|
||||
|
||||
* `string` - Signature of Transaction to confirm, as base-58 encoded string
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -432,7 +457,7 @@ Returns the current slot the node is processing
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -454,7 +479,7 @@ Returns the current slot leader
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -476,7 +501,7 @@ Returns the current storage segment size in terms of slots
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -542,7 +567,7 @@ Returns the current Transaction count from the ledger
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -569,6 +594,7 @@ None
|
||||
#### Results:
|
||||
|
||||
* `integer` - Total supply, as unsigned 64-bit integer
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Example:
|
||||
|
||||
@ -609,7 +635,7 @@ Returns the account info and associated stake for all the voting accounts in the
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
@ -640,6 +666,7 @@ Requests an airdrop of lamports to a Pubkey
|
||||
|
||||
* `string` - Pubkey of account to receive lamports, as base-58 encoded string
|
||||
* `integer` - lamports, as a signed 64-bit integer
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) (used for retrieving blockhash and verifying airdrop success)
|
||||
|
||||
#### Results:
|
||||
|
||||
|
@ -364,7 +364,7 @@ while [[ $iteration -le $iterations ]]; do
|
||||
echo "--- Wallet sanity ($iteration)"
|
||||
(
|
||||
set -x
|
||||
timeout 60s scripts/wallet-sanity.sh --url http://127.0.0.1"$walletRpcPort"
|
||||
timeout 90s scripts/wallet-sanity.sh --url http://127.0.0.1"$walletRpcPort"
|
||||
) || flag_error
|
||||
|
||||
iteration=$((iteration + 1))
|
||||
|
@ -11,6 +11,7 @@ use serde_json::Value;
|
||||
use solana_client::{rpc_client::RpcClient, rpc_request::RpcVoteAccountInfo};
|
||||
use solana_sdk::{
|
||||
clock,
|
||||
commitment_config::CommitmentConfig,
|
||||
hash::Hash,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
system_transaction,
|
||||
@ -72,7 +73,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||
.long("timeout")
|
||||
.value_name("SECONDS")
|
||||
.takes_value(true)
|
||||
.default_value("10")
|
||||
.default_value("15")
|
||||
.help("Wait up to timeout seconds for transaction confirmation"),
|
||||
),
|
||||
)
|
||||
@ -221,7 +222,10 @@ pub fn process_ping(
|
||||
Ok(signature) => {
|
||||
let transaction_sent = Instant::now();
|
||||
loop {
|
||||
let signature_status = rpc_client.get_signature_status(&signature)?;
|
||||
let signature_status = rpc_client.get_signature_status_with_commitment(
|
||||
&signature,
|
||||
CommitmentConfig::recent(),
|
||||
)?;
|
||||
let elapsed_time = Instant::now().duration_since(transaction_sent);
|
||||
if let Some(transaction_status) = signature_status {
|
||||
match transaction_status {
|
||||
|
@ -11,11 +11,14 @@ use serde_derive::{Deserialize, Serialize};
|
||||
use serde_json::{Map, Value};
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_config_api::{config_instruction, get_config_data, ConfigKeys, ConfigState};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
commitment_config::CommitmentConfig,
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
transaction::Transaction,
|
||||
};
|
||||
use std::error;
|
||||
|
||||
pub const MAX_SHORT_FIELD_LENGTH: usize = 70;
|
||||
@ -297,7 +300,9 @@ pub fn process_set_validator_info(
|
||||
};
|
||||
|
||||
// Check existence of validator-info account
|
||||
let balance = rpc_client.poll_get_balance(&info_pubkey).unwrap_or(0);
|
||||
let balance = rpc_client
|
||||
.poll_get_balance_with_commitment(&info_pubkey, CommitmentConfig::default())
|
||||
.unwrap_or(0);
|
||||
|
||||
let keys = vec![(id(), false), (config.keypair.pubkey(), true)];
|
||||
let (message, signers): (Message, Vec<&Keypair>) = if balance == 0 {
|
||||
|
@ -1,14 +1,16 @@
|
||||
use serde_json::{json, Value};
|
||||
use serde_json::Value;
|
||||
use solana_cli::cli::{process_command, CliCommand, CliConfig};
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_client::rpc_request::RpcRequest;
|
||||
use solana_core::validator::new_validator_for_tests;
|
||||
use solana_drone::drone::run_local_drone;
|
||||
use solana_sdk::bpf_loader;
|
||||
use std::fs::{remove_dir_all, File};
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::channel;
|
||||
use solana_sdk::{bpf_loader, commitment_config::CommitmentConfig, pubkey::Pubkey};
|
||||
use std::{
|
||||
fs::{remove_dir_all, File},
|
||||
io::Read,
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
sync::mpsc::channel,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_cli_deploy_program() {
|
||||
@ -56,35 +58,20 @@ fn test_cli_deploy_program() {
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap();
|
||||
let program_id = Pubkey::from_str(&program_id_str).unwrap();
|
||||
|
||||
let params = json!([program_id_str]);
|
||||
let account_info = rpc_client
|
||||
.retry_make_rpc_request(&RpcRequest::GetAccountInfo, Some(params), 0)
|
||||
let account = rpc_client
|
||||
.get_account_with_commitment(&program_id, CommitmentConfig::recent())
|
||||
.unwrap();
|
||||
let account_info_obj = account_info.as_object().unwrap();
|
||||
assert_eq!(
|
||||
account_info_obj.get("lamports").unwrap().as_u64().unwrap(),
|
||||
minimum_balance_for_rent_exemption
|
||||
);
|
||||
let owner_array = account_info.get("owner").unwrap();
|
||||
assert_eq!(owner_array, &json!(bpf_loader::id()));
|
||||
assert_eq!(
|
||||
account_info_obj
|
||||
.get("executable")
|
||||
.unwrap()
|
||||
.as_bool()
|
||||
.unwrap(),
|
||||
true
|
||||
);
|
||||
assert_eq!(account.lamports, minimum_balance_for_rent_exemption);
|
||||
assert_eq!(account.owner, bpf_loader::id());
|
||||
assert_eq!(account.executable, true);
|
||||
|
||||
let mut file = File::open(pathbuf.to_str().unwrap().to_string()).unwrap();
|
||||
let mut elf = Vec::new();
|
||||
file.read_to_end(&mut elf).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
account_info_obj.get("data").unwrap().as_array().unwrap(),
|
||||
&elf
|
||||
);
|
||||
assert_eq!(account.data, elf);
|
||||
|
||||
server.close().unwrap();
|
||||
remove_dir_all(ledger_path).unwrap();
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::client_error::ClientError;
|
||||
use crate::rpc_request::RpcRequest;
|
||||
use crate::{client_error::ClientError, rpc_request::RpcRequest};
|
||||
use solana_sdk::commitment_config::CommitmentConfig;
|
||||
|
||||
pub(crate) trait GenericRpcClientRequest {
|
||||
fn send(
|
||||
@ -7,5 +7,6 @@ pub(crate) trait GenericRpcClientRequest {
|
||||
request: &RpcRequest,
|
||||
params: Option<serde_json::Value>,
|
||||
retries: usize,
|
||||
commitment_config: Option<CommitmentConfig>,
|
||||
) -> Result<serde_json::Value, ClientError>;
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::client_error::ClientError;
|
||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||
use crate::rpc_request::RpcRequest;
|
||||
use crate::{
|
||||
client_error::ClientError, generic_rpc_client_request::GenericRpcClientRequest,
|
||||
rpc_request::RpcRequest,
|
||||
};
|
||||
use serde_json::{Number, Value};
|
||||
use solana_sdk::fee_calculator::FeeCalculator;
|
||||
use solana_sdk::transaction::{self, TransactionError};
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
transaction::{self, TransactionError},
|
||||
};
|
||||
|
||||
pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8";
|
||||
pub const SIGNATURE: &str =
|
||||
@ -25,6 +29,7 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
||||
request: &RpcRequest,
|
||||
params: Option<serde_json::Value>,
|
||||
_retries: usize,
|
||||
_commitment_config: Option<CommitmentConfig>,
|
||||
) -> Result<serde_json::Value, ClientError> {
|
||||
if self.url == "fails" {
|
||||
return Ok(Value::Null);
|
||||
|
@ -1,10 +1,13 @@
|
||||
use log::*;
|
||||
use solana_sdk::client::Client;
|
||||
use solana_sdk::timing::duration_as_s;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread::sleep;
|
||||
use std::time::{Duration, Instant};
|
||||
use solana_sdk::{client::Client, commitment_config::CommitmentConfig, timing::duration_as_s};
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, RwLock,
|
||||
},
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SampleStats {
|
||||
@ -29,7 +32,9 @@ pub fn sample_txs<T>(
|
||||
let mut total_txs;
|
||||
let mut now = Instant::now();
|
||||
let start_time = now;
|
||||
let initial_txs = client.get_transaction_count().expect("transaction count");
|
||||
let initial_txs = client
|
||||
.get_transaction_count_with_commitment(CommitmentConfig::recent())
|
||||
.expect("transaction count");
|
||||
let mut last_txs = initial_txs;
|
||||
|
||||
loop {
|
||||
@ -37,7 +42,7 @@ pub fn sample_txs<T>(
|
||||
let elapsed = now.elapsed();
|
||||
now = Instant::now();
|
||||
let mut txs;
|
||||
match client.get_transaction_count() {
|
||||
match client.get_transaction_count_with_commitment(CommitmentConfig::recent()) {
|
||||
Err(e) => {
|
||||
// ThinClient with multiple options should pick a better one now.
|
||||
info!("Couldn't get transaction count {:?}", e);
|
||||
|
@ -1,14 +1,17 @@
|
||||
use crate::client_error::ClientError;
|
||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||
use crate::mock_rpc_client_request::MockRpcClientRequest;
|
||||
use crate::rpc_client_request::RpcClientRequest;
|
||||
use crate::rpc_request::{RpcEpochInfo, RpcRequest, RpcVoteAccountStatus};
|
||||
use crate::{
|
||||
client_error::ClientError,
|
||||
generic_rpc_client_request::GenericRpcClientRequest,
|
||||
mock_rpc_client_request::MockRpcClientRequest,
|
||||
rpc_client_request::RpcClientRequest,
|
||||
rpc_request::{RpcEpochInfo, RpcRequest, RpcVoteAccountStatus},
|
||||
};
|
||||
use bincode::serialize;
|
||||
use log::*;
|
||||
use serde_json::{json, Value};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
clock::{Slot, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
|
||||
commitment_config::CommitmentConfig,
|
||||
epoch_schedule::EpochSchedule,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
@ -54,10 +57,10 @@ impl RpcClient {
|
||||
|
||||
pub fn send_transaction(&self, transaction: &Transaction) -> Result<String, ClientError> {
|
||||
let serialized = serialize(transaction).unwrap();
|
||||
let params = json!([serialized]);
|
||||
let params = json!(serialized);
|
||||
let signature = self
|
||||
.client
|
||||
.send(&RpcRequest::SendTransaction, Some(params), 5)?;
|
||||
.send(&RpcRequest::SendTransaction, Some(params), 5, None)?;
|
||||
if signature.as_str().is_none() {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -73,19 +76,37 @@ impl RpcClient {
|
||||
&self,
|
||||
signature: &str,
|
||||
) -> Result<Option<transaction::Result<()>>, ClientError> {
|
||||
let params = json!([signature.to_string()]);
|
||||
let signature_status =
|
||||
self.client
|
||||
.send(&RpcRequest::GetSignatureStatus, Some(params), 5)?;
|
||||
self.get_signature_status_with_commitment(signature, CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_signature_status_with_commitment(
|
||||
&self,
|
||||
signature: &str,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<Option<transaction::Result<()>>, ClientError> {
|
||||
let params = json!(signature.to_string());
|
||||
let signature_status = self.client.send(
|
||||
&RpcRequest::GetSignatureStatus,
|
||||
Some(params),
|
||||
5,
|
||||
commitment_config.ok(),
|
||||
)?;
|
||||
let result: Option<transaction::Result<()>> =
|
||||
serde_json::from_value(signature_status).unwrap();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn get_slot(&self) -> io::Result<Slot> {
|
||||
self.get_slot_with_commitment(CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_slot_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<Slot> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetSlot, None, 0)
|
||||
.send(&RpcRequest::GetSlot, None, 0, commitment_config.ok())
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -104,7 +125,7 @@ impl RpcClient {
|
||||
pub fn get_vote_accounts(&self) -> io::Result<RpcVoteAccountStatus> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetVoteAccounts, None, 0)
|
||||
.send(&RpcRequest::GetVoteAccounts, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -123,7 +144,7 @@ impl RpcClient {
|
||||
pub fn get_epoch_info(&self) -> io::Result<RpcEpochInfo> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetEpochInfo, None, 0)
|
||||
.send(&RpcRequest::GetEpochInfo, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -142,7 +163,7 @@ impl RpcClient {
|
||||
pub fn get_epoch_schedule(&self) -> io::Result<EpochSchedule> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetEpochSchedule, None, 0)
|
||||
.send(&RpcRequest::GetEpochSchedule, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -161,7 +182,7 @@ impl RpcClient {
|
||||
pub fn get_inflation(&self) -> io::Result<Inflation> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetInflation, None, 0)
|
||||
.send(&RpcRequest::GetInflation, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -180,7 +201,7 @@ impl RpcClient {
|
||||
pub fn get_version(&self) -> io::Result<String> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetVersion, None, 0)
|
||||
.send(&RpcRequest::GetVersion, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -203,7 +224,7 @@ impl RpcClient {
|
||||
) -> Result<String, ClientError> {
|
||||
let mut send_retries = 20;
|
||||
loop {
|
||||
let mut status_retries = 4;
|
||||
let mut status_retries = 15;
|
||||
let signature_str = self.send_transaction(transaction)?;
|
||||
let status = loop {
|
||||
let status = self.get_signature_status(&signature_str)?;
|
||||
@ -216,10 +237,8 @@ impl RpcClient {
|
||||
break status;
|
||||
}
|
||||
if cfg!(not(test)) {
|
||||
// Retry ~twice during a slot
|
||||
sleep(Duration::from_millis(
|
||||
500 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND,
|
||||
));
|
||||
// Retry twice a second
|
||||
sleep(Duration::from_millis(500));
|
||||
}
|
||||
};
|
||||
send_retries = if let Some(result) = status.clone() {
|
||||
@ -252,7 +271,7 @@ impl RpcClient {
|
||||
) -> Result<(), Box<dyn error::Error>> {
|
||||
let mut send_retries = 5;
|
||||
loop {
|
||||
let mut status_retries = 4;
|
||||
let mut status_retries = 15;
|
||||
|
||||
// Send all transactions
|
||||
let mut transactions_signatures = vec![];
|
||||
@ -273,10 +292,8 @@ impl RpcClient {
|
||||
status_retries -= 1;
|
||||
|
||||
if cfg!(not(test)) {
|
||||
// Retry ~twice during a slot
|
||||
sleep(Duration::from_millis(
|
||||
500 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND,
|
||||
));
|
||||
// Retry twice a second
|
||||
sleep(Duration::from_millis(500));
|
||||
}
|
||||
|
||||
transactions_signatures = transactions_signatures
|
||||
@ -333,19 +350,30 @@ impl RpcClient {
|
||||
pubkey: &Pubkey,
|
||||
retries: usize,
|
||||
) -> Result<Option<u64>, Box<dyn error::Error>> {
|
||||
let params = json!([format!("{}", pubkey)]);
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let res = self
|
||||
.client
|
||||
.send(&RpcRequest::GetBalance, Some(params), retries)?
|
||||
.send(&RpcRequest::GetBalance, Some(params), retries, None)?
|
||||
.as_u64();
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn get_account(&self, pubkey: &Pubkey) -> io::Result<Account> {
|
||||
let params = json!([format!("{}", pubkey)]);
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetAccountInfo, Some(params), 0);
|
||||
self.get_account_with_commitment(pubkey, CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_account_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<Account> {
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let response = self.client.send(
|
||||
&RpcRequest::GetAccountInfo,
|
||||
Some(params),
|
||||
0,
|
||||
commitment_config.ok(),
|
||||
);
|
||||
|
||||
response
|
||||
.and_then(|account_json| {
|
||||
@ -366,13 +394,14 @@ impl RpcClient {
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> io::Result<u64> {
|
||||
let params = json!([data_len]);
|
||||
let params = json!(data_len);
|
||||
let minimum_balance_json = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetMinimumBalanceForRentExemption,
|
||||
Some(params),
|
||||
0,
|
||||
None,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -398,18 +427,25 @@ impl RpcClient {
|
||||
Ok(minimum_balance)
|
||||
}
|
||||
|
||||
/// Request the balance of the user holding `pubkey`. This method blocks
|
||||
/// until the server sends a response. If the response packet is dropped
|
||||
/// by the network, this method will hang indefinitely.
|
||||
/// Request the balance of the account `pubkey`.
|
||||
pub fn get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
|
||||
self.get_account(pubkey).map(|account| account.lamports)
|
||||
self.get_balance_with_commitment(pubkey, CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
self.get_account_with_commitment(pubkey, commitment_config)
|
||||
.map(|account| account.lamports)
|
||||
}
|
||||
|
||||
pub fn get_program_accounts(&self, pubkey: &Pubkey) -> io::Result<Vec<(Pubkey, Account)>> {
|
||||
let params = json!([format!("{}", pubkey)]);
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetProgramAccounts, Some(params), 0)
|
||||
.send(&RpcRequest::GetProgramAccounts, Some(params), 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -438,12 +474,23 @@ impl RpcClient {
|
||||
Ok(pubkey_accounts)
|
||||
}
|
||||
|
||||
/// Request the transaction count. If the response packet is dropped by the network,
|
||||
/// this method will try again 5 times.
|
||||
/// Request the transaction count.
|
||||
pub fn get_transaction_count(&self) -> io::Result<u64> {
|
||||
self.get_transaction_count_with_commitment(CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_transaction_count_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetTransactionCount, None, 0)
|
||||
.send(
|
||||
&RpcRequest::GetTransactionCount,
|
||||
None,
|
||||
0,
|
||||
commitment_config.ok(),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -460,9 +507,21 @@ impl RpcClient {
|
||||
}
|
||||
|
||||
pub fn get_recent_blockhash(&self) -> io::Result<(Hash, FeeCalculator)> {
|
||||
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_recent_blockhash_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<(Hash, FeeCalculator)> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetRecentBlockhash, None, 0)
|
||||
.send(
|
||||
&RpcRequest::GetRecentBlockhash,
|
||||
None,
|
||||
0,
|
||||
commitment_config.ok(),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -518,7 +577,7 @@ impl RpcClient {
|
||||
pub fn get_genesis_blockhash(&self) -> io::Result<Hash> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetGenesisBlockhash, None, 0)
|
||||
.send(&RpcRequest::GetGenesisBlockhash, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -542,15 +601,16 @@ impl RpcClient {
|
||||
Ok(blockhash)
|
||||
}
|
||||
|
||||
pub fn poll_balance_with_timeout(
|
||||
pub fn poll_balance_with_timeout_and_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
polling_frequency: &Duration,
|
||||
timeout: &Duration,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
let now = Instant::now();
|
||||
loop {
|
||||
match self.get_balance(&pubkey) {
|
||||
match self.get_balance_with_commitment(&pubkey, commitment_config.clone()) {
|
||||
Ok(bal) => {
|
||||
return Ok(bal);
|
||||
}
|
||||
@ -564,14 +624,29 @@ impl RpcClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll_get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
|
||||
self.poll_balance_with_timeout(pubkey, &Duration::from_millis(100), &Duration::from_secs(1))
|
||||
pub fn poll_get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
self.poll_balance_with_timeout_and_commitment(
|
||||
pubkey,
|
||||
&Duration::from_millis(100),
|
||||
&Duration::from_secs(1),
|
||||
commitment_config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn wait_for_balance(&self, pubkey: &Pubkey, expected_balance: Option<u64>) -> Option<u64> {
|
||||
pub fn wait_for_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
expected_balance: Option<u64>,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Option<u64> {
|
||||
const LAST: usize = 30;
|
||||
for run in 0..LAST {
|
||||
let balance_result = self.poll_get_balance(pubkey);
|
||||
let balance_result =
|
||||
self.poll_get_balance_with_commitment(pubkey, commitment_config.clone());
|
||||
if expected_balance.is_none() {
|
||||
return balance_result.ok();
|
||||
}
|
||||
@ -593,8 +668,23 @@ impl RpcClient {
|
||||
|
||||
/// Poll the server to confirm a transaction.
|
||||
pub fn poll_for_signature(&self, signature: &Signature) -> io::Result<()> {
|
||||
self.poll_for_signature_with_commitment(signature, CommitmentConfig::default())
|
||||
}
|
||||
|
||||
/// Poll the server to confirm a transaction.
|
||||
pub fn poll_for_signature_with_commitment(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<()> {
|
||||
let now = Instant::now();
|
||||
while !self.check_signature(signature) {
|
||||
loop {
|
||||
if let Ok(Some(_)) = self.get_signature_status_with_commitment(
|
||||
&signature.to_string(),
|
||||
commitment_config.clone(),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
if now.elapsed().as_secs() > 15 {
|
||||
// TODO: Return a better error.
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "signature not found"));
|
||||
@ -607,12 +697,15 @@ impl RpcClient {
|
||||
/// Check a signature in the bank.
|
||||
pub fn check_signature(&self, signature: &Signature) -> bool {
|
||||
trace!("check_signature: {:?}", signature);
|
||||
let params = json!([format!("{}", signature)]);
|
||||
let params = json!(format!("{}", signature));
|
||||
|
||||
for _ in 0..30 {
|
||||
let response =
|
||||
self.client
|
||||
.send(&RpcRequest::ConfirmTransaction, Some(params.clone()), 0);
|
||||
let response = self.client.send(
|
||||
&RpcRequest::ConfirmTransaction,
|
||||
Some(params.clone()),
|
||||
0,
|
||||
Some(CommitmentConfig::recent()),
|
||||
);
|
||||
|
||||
match response {
|
||||
Ok(confirmation) => {
|
||||
@ -666,7 +759,7 @@ impl RpcClient {
|
||||
debug!("check_confirmations request failed: {:?}", err);
|
||||
}
|
||||
};
|
||||
if now.elapsed().as_secs() > 15 {
|
||||
if now.elapsed().as_secs() > 20 {
|
||||
info!(
|
||||
"signature {} confirmed {} out of {} failed after {} ms",
|
||||
signature,
|
||||
@ -690,13 +783,14 @@ impl RpcClient {
|
||||
&self,
|
||||
sig: &Signature,
|
||||
) -> io::Result<usize> {
|
||||
let params = json!([format!("{}", sig)]);
|
||||
let params = json!(format!("{}", sig));
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetNumBlocksSinceSignatureConfirmation,
|
||||
Some(params.clone()),
|
||||
1,
|
||||
CommitmentConfig::recent().ok(),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -721,7 +815,7 @@ impl RpcClient {
|
||||
pub fn validator_exit(&self) -> io::Result<bool> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::ValidatorExit, None, 0)
|
||||
.send(&RpcRequest::ValidatorExit, None, 0, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -742,8 +836,9 @@ impl RpcClient {
|
||||
request: &RpcRequest,
|
||||
params: Option<Value>,
|
||||
retries: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Value, ClientError> {
|
||||
self.client.send(request, params, retries)
|
||||
self.client.send(request, params, retries, commitment)
|
||||
}
|
||||
}
|
||||
|
||||
@ -763,11 +858,12 @@ mod tests {
|
||||
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
|
||||
use serde_json::Number;
|
||||
use solana_logger;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_transaction;
|
||||
use solana_sdk::transaction::TransactionError;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
use solana_sdk::{
|
||||
signature::{Keypair, KeypairUtil},
|
||||
system_transaction,
|
||||
transaction::TransactionError,
|
||||
};
|
||||
use std::{sync::mpsc::channel, thread};
|
||||
|
||||
#[test]
|
||||
fn test_make_rpc_request() {
|
||||
@ -808,10 +904,12 @@ mod tests {
|
||||
&RpcRequest::GetBalance,
|
||||
Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"])),
|
||||
0,
|
||||
None,
|
||||
);
|
||||
assert_eq!(balance.unwrap().as_u64().unwrap(), 50);
|
||||
|
||||
let blockhash = rpc_client.retry_make_rpc_request(&RpcRequest::GetRecentBlockhash, None, 0);
|
||||
let blockhash =
|
||||
rpc_client.retry_make_rpc_request(&RpcRequest::GetRecentBlockhash, None, 0, None);
|
||||
assert_eq!(
|
||||
blockhash.unwrap().as_str().unwrap(),
|
||||
"deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"
|
||||
@ -822,6 +920,7 @@ mod tests {
|
||||
&RpcRequest::GetRecentBlockhash,
|
||||
Some(json!("parameter")),
|
||||
0,
|
||||
None,
|
||||
);
|
||||
assert_eq!(blockhash.is_err(), true);
|
||||
}
|
||||
@ -860,6 +959,7 @@ mod tests {
|
||||
&RpcRequest::GetBalance,
|
||||
Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"])),
|
||||
10,
|
||||
None,
|
||||
);
|
||||
assert_eq!(balance.unwrap().as_u64().unwrap(), 5);
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
use crate::client_error::ClientError;
|
||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||
use crate::rpc_request::{RpcError, RpcRequest};
|
||||
use crate::{
|
||||
client_error::ClientError,
|
||||
generic_rpc_client_request::GenericRpcClientRequest,
|
||||
rpc_request::{RpcError, RpcRequest},
|
||||
};
|
||||
use log::*;
|
||||
use reqwest::{self, header::CONTENT_TYPE};
|
||||
use solana_sdk::clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT};
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use solana_sdk::{
|
||||
clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
|
||||
commitment_config::CommitmentConfig,
|
||||
};
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
pub struct RpcClientRequest {
|
||||
client: reqwest::Client,
|
||||
@ -36,11 +40,12 @@ impl GenericRpcClientRequest for RpcClientRequest {
|
||||
request: &RpcRequest,
|
||||
params: Option<serde_json::Value>,
|
||||
mut retries: usize,
|
||||
commitment_config: Option<CommitmentConfig>,
|
||||
) -> Result<serde_json::Value, ClientError> {
|
||||
// Concurrent requests are not supported so reuse the same request id for all requests
|
||||
let request_id = 1;
|
||||
|
||||
let request_json = request.build_request_json(request_id, params);
|
||||
let request_json = request.build_request_json(request_id, params, commitment_config);
|
||||
|
||||
loop {
|
||||
match self
|
||||
|
@ -1,5 +1,8 @@
|
||||
use serde_json::{json, Value};
|
||||
use solana_sdk::clock::{Epoch, Slot};
|
||||
use solana_sdk::{
|
||||
clock::{Epoch, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
};
|
||||
use std::{error, fmt};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
@ -83,7 +86,12 @@ pub enum RpcRequest {
|
||||
}
|
||||
|
||||
impl RpcRequest {
|
||||
pub(crate) fn build_request_json(&self, id: u64, params: Option<Value>) -> Value {
|
||||
pub(crate) fn build_request_json(
|
||||
&self,
|
||||
id: u64,
|
||||
params: Option<Value>,
|
||||
commitment_config: Option<CommitmentConfig>,
|
||||
) -> Value {
|
||||
let jsonrpc = "2.0";
|
||||
let method = match self {
|
||||
RpcRequest::ConfirmTransaction => "confirmTransaction",
|
||||
@ -123,7 +131,13 @@ impl RpcRequest {
|
||||
"method": method,
|
||||
});
|
||||
if let Some(param_string) = params {
|
||||
request["params"] = param_string;
|
||||
if let Some(config) = commitment_config {
|
||||
request["params"] = json!([param_string, config]);
|
||||
} else {
|
||||
request["params"] = json!([param_string]);
|
||||
}
|
||||
} else if let Some(config) = commitment_config {
|
||||
request["params"] = json!([config]);
|
||||
}
|
||||
request
|
||||
}
|
||||
@ -154,45 +168,65 @@ impl error::Error for RpcError {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use solana_sdk::commitment_config::CommitmentLevel;
|
||||
|
||||
#[test]
|
||||
fn test_build_request_json() {
|
||||
let test_request = RpcRequest::GetAccountInfo;
|
||||
let addr = json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]);
|
||||
let request = test_request.build_request_json(1, Some(addr.clone()));
|
||||
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
||||
let request = test_request.build_request_json(1, Some(addr.clone()), None);
|
||||
assert_eq!(request["method"], "getAccountInfo");
|
||||
assert_eq!(request["params"], addr,);
|
||||
assert_eq!(request["params"], json!([addr]));
|
||||
|
||||
let test_request = RpcRequest::GetBalance;
|
||||
let request = test_request.build_request_json(1, Some(addr));
|
||||
let request = test_request.build_request_json(1, Some(addr), None);
|
||||
assert_eq!(request["method"], "getBalance");
|
||||
|
||||
let test_request = RpcRequest::GetEpochInfo;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "getEpochInfo");
|
||||
|
||||
let test_request = RpcRequest::GetInflation;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "getInflation");
|
||||
|
||||
let test_request = RpcRequest::GetRecentBlockhash;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "getRecentBlockhash");
|
||||
|
||||
let test_request = RpcRequest::GetSlot;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "getSlot");
|
||||
|
||||
let test_request = RpcRequest::GetTransactionCount;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "getTransactionCount");
|
||||
|
||||
let test_request = RpcRequest::RequestAirdrop;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "requestAirdrop");
|
||||
|
||||
let test_request = RpcRequest::SendTransaction;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
assert_eq!(request["method"], "sendTransaction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_request_json_config_options() {
|
||||
let commitment_config = CommitmentConfig {
|
||||
commitment: CommitmentLevel::Max,
|
||||
};
|
||||
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
||||
|
||||
// Test request with CommitmentConfig and no params
|
||||
let test_request = RpcRequest::GetRecentBlockhash;
|
||||
let request = test_request.build_request_json(1, None, Some(commitment_config.clone()));
|
||||
assert_eq!(request["params"], json!([commitment_config.clone()]));
|
||||
|
||||
// Test request with CommitmentConfig and params
|
||||
let test_request = RpcRequest::GetBalance;
|
||||
let request =
|
||||
test_request.build_request_json(1, Some(addr.clone()), Some(commitment_config.clone()));
|
||||
assert_eq!(request["params"], json!([addr, commitment_config]));
|
||||
}
|
||||
}
|
||||
|
@ -6,25 +6,32 @@
|
||||
use crate::rpc_client::RpcClient;
|
||||
use bincode::{serialize_into, serialized_size};
|
||||
use log::*;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::client::{AsyncClient, Client, SyncClient};
|
||||
use solana_sdk::clock::MAX_PROCESSING_AGE;
|
||||
use solana_sdk::fee_calculator::FeeCalculator;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::instruction::Instruction;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::packet::PACKET_DATA_SIZE;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::timing::duration_as_ms;
|
||||
use solana_sdk::transaction::{self, Transaction};
|
||||
use solana_sdk::transport::Result as TransportResult;
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, UdpSocket};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::RwLock;
|
||||
use std::time::{Duration, Instant};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
client::{AsyncClient, Client, SyncClient},
|
||||
clock::MAX_PROCESSING_AGE,
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
instruction::Instruction,
|
||||
message::Message,
|
||||
packet::PACKET_DATA_SIZE,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil, Signature},
|
||||
system_instruction,
|
||||
timing::duration_as_ms,
|
||||
transaction::{self, Transaction},
|
||||
transport::Result as TransportResult,
|
||||
};
|
||||
use std::{
|
||||
io,
|
||||
net::{SocketAddr, UdpSocket},
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
RwLock,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
struct ClientOptimizer {
|
||||
cur_index: AtomicUsize,
|
||||
@ -244,22 +251,78 @@ impl ThinClient {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn poll_balance_with_timeout_and_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
polling_frequency: &Duration,
|
||||
timeout: &Duration,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
self.rpc_client().poll_balance_with_timeout_and_commitment(
|
||||
pubkey,
|
||||
polling_frequency,
|
||||
timeout,
|
||||
commitment_config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn poll_balance_with_timeout(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
polling_frequency: &Duration,
|
||||
timeout: &Duration,
|
||||
) -> io::Result<u64> {
|
||||
self.rpc_client()
|
||||
.poll_balance_with_timeout(pubkey, polling_frequency, timeout)
|
||||
self.rpc_client().poll_balance_with_timeout_and_commitment(
|
||||
pubkey,
|
||||
polling_frequency,
|
||||
timeout,
|
||||
CommitmentConfig::default(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn poll_get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
|
||||
self.rpc_client().poll_get_balance(pubkey)
|
||||
self.rpc_client()
|
||||
.poll_get_balance_with_commitment(pubkey, CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn poll_get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
self.rpc_client()
|
||||
.poll_get_balance_with_commitment(pubkey, commitment_config)
|
||||
}
|
||||
|
||||
pub fn wait_for_balance(&self, pubkey: &Pubkey, expected_balance: Option<u64>) -> Option<u64> {
|
||||
self.rpc_client().wait_for_balance(pubkey, expected_balance)
|
||||
self.rpc_client().wait_for_balance_with_commitment(
|
||||
pubkey,
|
||||
expected_balance,
|
||||
CommitmentConfig::default(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn wait_for_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
expected_balance: Option<u64>,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Option<u64> {
|
||||
self.rpc_client().wait_for_balance_with_commitment(
|
||||
pubkey,
|
||||
expected_balance,
|
||||
commitment_config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn poll_for_signature_with_commitment(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<()> {
|
||||
Ok(self
|
||||
.rpc_client()
|
||||
.poll_for_signature_with_commitment(signature, commitment_config)?)
|
||||
}
|
||||
|
||||
/// Check a signature in the bank. This method blocks
|
||||
@ -323,15 +386,45 @@ impl SyncClient for ThinClient {
|
||||
Ok(self.rpc_client().get_account(pubkey).ok())
|
||||
}
|
||||
|
||||
fn get_account_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<Option<Account>> {
|
||||
Ok(self
|
||||
.rpc_client()
|
||||
.get_account_with_commitment(pubkey, commitment_config)
|
||||
.ok())
|
||||
}
|
||||
|
||||
fn get_balance(&self, pubkey: &Pubkey) -> TransportResult<u64> {
|
||||
let balance = self.rpc_client().get_balance(pubkey)?;
|
||||
Ok(balance)
|
||||
}
|
||||
|
||||
fn get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<u64> {
|
||||
let balance = self
|
||||
.rpc_client()
|
||||
.get_balance_with_commitment(pubkey, commitment_config)?;
|
||||
Ok(balance)
|
||||
}
|
||||
|
||||
fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
|
||||
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())
|
||||
}
|
||||
|
||||
fn get_recent_blockhash_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<(Hash, FeeCalculator)> {
|
||||
let index = self.optimizer.experiment();
|
||||
let now = Instant::now();
|
||||
let recent_blockhash = self.rpc_clients[index].get_recent_blockhash();
|
||||
let recent_blockhash =
|
||||
self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
|
||||
match recent_blockhash {
|
||||
Ok(recent_blockhash) => {
|
||||
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
|
||||
@ -360,13 +453,40 @@ impl SyncClient for ThinClient {
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
fn get_signature_status_with_commitment(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<Option<transaction::Result<()>>> {
|
||||
let status = self
|
||||
.rpc_client()
|
||||
.get_signature_status_with_commitment(&signature.to_string(), commitment_config)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("send_transaction failed with error {:?}", err),
|
||||
)
|
||||
})?;
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
fn get_slot(&self) -> TransportResult<u64> {
|
||||
let slot = self.rpc_client().get_slot().map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("send_transaction failed with error {:?}", err),
|
||||
)
|
||||
})?;
|
||||
self.get_slot_with_commitment(CommitmentConfig::default())
|
||||
}
|
||||
|
||||
fn get_slot_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<u64> {
|
||||
let slot = self
|
||||
.rpc_client()
|
||||
.get_slot_with_commitment(commitment_config)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("send_transaction failed with error {:?}", err),
|
||||
)
|
||||
})?;
|
||||
Ok(slot)
|
||||
}
|
||||
|
||||
@ -385,6 +505,27 @@ impl SyncClient for ThinClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_transaction_count_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> TransportResult<u64> {
|
||||
let index = self.optimizer.experiment();
|
||||
let now = Instant::now();
|
||||
match self
|
||||
.rpc_client()
|
||||
.get_transaction_count_with_commitment(commitment_config)
|
||||
{
|
||||
Ok(transaction_count) => {
|
||||
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
|
||||
Ok(transaction_count)
|
||||
}
|
||||
Err(e) => {
|
||||
self.optimizer.report(index, std::u64::MAX);
|
||||
Err(e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Poll the server until the signature has been confirmed by at least `min_confirmed_blocks`
|
||||
fn poll_for_signature_confirmation(
|
||||
&self,
|
||||
|
@ -29,6 +29,7 @@ use solana_sdk::{
|
||||
account_utils::State,
|
||||
client::{AsyncClient, SyncClient},
|
||||
clock::{get_complete_segment_from_slot, get_segment_from_slot, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
hash::{Hash, Hasher},
|
||||
message::Message,
|
||||
signature::{Keypair, KeypairUtil, Signature},
|
||||
@ -78,6 +79,7 @@ struct ArchiverMeta {
|
||||
blockhash: Hash,
|
||||
sha_state: Hash,
|
||||
num_chacha_blocks: usize,
|
||||
client_commitment: CommitmentConfig,
|
||||
}
|
||||
|
||||
pub(crate) fn sample_file(in_path: &Path, sample_offsets: &[u64]) -> io::Result<Hash> {
|
||||
@ -208,6 +210,7 @@ impl Archiver {
|
||||
cluster_entrypoint: ContactInfo,
|
||||
keypair: Arc<Keypair>,
|
||||
storage_keypair: Arc<Keypair>,
|
||||
client_commitment: CommitmentConfig,
|
||||
) -> Result<Self> {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
|
||||
@ -246,7 +249,12 @@ impl Archiver {
|
||||
let client = crate::gossip_service::get_client(&nodes);
|
||||
|
||||
info!("Setting up mining account...");
|
||||
if let Err(e) = Self::setup_mining_account(&client, &keypair, &storage_keypair) {
|
||||
if let Err(e) = Self::setup_mining_account(
|
||||
&client,
|
||||
&keypair,
|
||||
&storage_keypair,
|
||||
client_commitment.clone(),
|
||||
) {
|
||||
//shutdown services before exiting
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
gossip_service.join()?;
|
||||
@ -279,6 +287,7 @@ impl Archiver {
|
||||
let node_info = node.info.clone();
|
||||
let mut meta = ArchiverMeta {
|
||||
ledger_path: ledger_path.to_path_buf(),
|
||||
client_commitment,
|
||||
..ArchiverMeta::default()
|
||||
};
|
||||
spawn(move || {
|
||||
@ -383,7 +392,12 @@ impl Archiver {
|
||||
}
|
||||
};
|
||||
meta.blockhash = storage_blockhash;
|
||||
Self::redeem_rewards(&cluster_info, archiver_keypair, storage_keypair);
|
||||
Self::redeem_rewards(
|
||||
&cluster_info,
|
||||
archiver_keypair,
|
||||
storage_keypair,
|
||||
meta.client_commitment.clone(),
|
||||
);
|
||||
}
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
}
|
||||
@ -392,11 +406,14 @@ impl Archiver {
|
||||
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
||||
archiver_keypair: &Arc<Keypair>,
|
||||
storage_keypair: &Arc<Keypair>,
|
||||
client_commitment: CommitmentConfig,
|
||||
) {
|
||||
let nodes = cluster_info.read().unwrap().tvu_peers();
|
||||
let client = crate::gossip_service::get_client(&nodes);
|
||||
|
||||
if let Ok(Some(account)) = client.get_account(&storage_keypair.pubkey()) {
|
||||
if let Ok(Some(account)) =
|
||||
client.get_account_with_commitment(&storage_keypair.pubkey(), client_commitment.clone())
|
||||
{
|
||||
if let Ok(StorageContract::ArchiverStorage { validations, .. }) = account.state() {
|
||||
if !validations.is_empty() {
|
||||
let ix = storage_instruction::claim_reward(
|
||||
@ -410,7 +427,10 @@ impl Archiver {
|
||||
} else {
|
||||
info!(
|
||||
"collected mining rewards: Account balance {:?}",
|
||||
client.get_balance(&archiver_keypair.pubkey())
|
||||
client.get_balance_with_commitment(
|
||||
&archiver_keypair.pubkey(),
|
||||
client_commitment.clone()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -432,15 +452,16 @@ impl Archiver {
|
||||
blob_fetch_receiver: PacketReceiver,
|
||||
slot_sender: Sender<u64>,
|
||||
) -> Result<(WindowService)> {
|
||||
let slots_per_segment = match Self::get_segment_config(&cluster_info) {
|
||||
Ok(slots_per_segment) => slots_per_segment,
|
||||
Err(e) => {
|
||||
error!("unable to get segment size configuration, exiting...");
|
||||
//shutdown services before exiting
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
let slots_per_segment =
|
||||
match Self::get_segment_config(&cluster_info, meta.client_commitment.clone()) {
|
||||
Ok(slots_per_segment) => slots_per_segment,
|
||||
Err(e) => {
|
||||
error!("unable to get segment size configuration, exiting...");
|
||||
//shutdown services before exiting
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
let (segment_blockhash, segment_slot) = match Self::poll_for_segment(
|
||||
&cluster_info,
|
||||
slots_per_segment,
|
||||
@ -588,13 +609,15 @@ impl Archiver {
|
||||
client: &ThinClient,
|
||||
keypair: &Keypair,
|
||||
storage_keypair: &Keypair,
|
||||
client_commitment: CommitmentConfig,
|
||||
) -> Result<()> {
|
||||
// make sure archiver has some balance
|
||||
info!("checking archiver keypair...");
|
||||
if client.poll_balance_with_timeout(
|
||||
if client.poll_balance_with_timeout_and_commitment(
|
||||
&keypair.pubkey(),
|
||||
&Duration::from_millis(100),
|
||||
&Duration::from_secs(5),
|
||||
client_commitment.clone(),
|
||||
)? == 0
|
||||
{
|
||||
return Err(
|
||||
@ -604,17 +627,19 @@ impl Archiver {
|
||||
|
||||
info!("checking storage account keypair...");
|
||||
// check if the storage account exists
|
||||
let balance = client.poll_get_balance(&storage_keypair.pubkey());
|
||||
let balance = client
|
||||
.poll_get_balance_with_commitment(&storage_keypair.pubkey(), client_commitment.clone());
|
||||
if balance.is_err() || balance.unwrap() == 0 {
|
||||
let blockhash = match client.get_recent_blockhash() {
|
||||
Ok((blockhash, _)) => blockhash,
|
||||
Err(_) => {
|
||||
return Err(Error::IO(<io::Error>::new(
|
||||
io::ErrorKind::Other,
|
||||
"unable to get recent blockhash, can't submit proof",
|
||||
)));
|
||||
}
|
||||
};
|
||||
let blockhash =
|
||||
match client.get_recent_blockhash_with_commitment(client_commitment.clone()) {
|
||||
Ok((blockhash, _)) => blockhash,
|
||||
Err(_) => {
|
||||
return Err(Error::IO(<io::Error>::new(
|
||||
io::ErrorKind::Other,
|
||||
"unable to get recent blockhash, can't submit proof",
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
let ix = storage_instruction::create_storage_account(
|
||||
&keypair.pubkey(),
|
||||
@ -626,7 +651,7 @@ impl Archiver {
|
||||
let tx = Transaction::new_signed_instructions(&[keypair], ix, blockhash);
|
||||
let signature = client.async_send_transaction(tx)?;
|
||||
client
|
||||
.poll_for_signature(&signature)
|
||||
.poll_for_signature_with_commitment(&signature, client_commitment.clone())
|
||||
.map_err(|err| match err {
|
||||
TransportError::IoError(e) => e,
|
||||
TransportError::TransactionError(_) => io::Error::new(
|
||||
@ -647,25 +672,32 @@ impl Archiver {
|
||||
// No point if we've got no storage account...
|
||||
let nodes = cluster_info.read().unwrap().tvu_peers();
|
||||
let client = crate::gossip_service::get_client(&nodes);
|
||||
let storage_balance = client.poll_get_balance(&storage_keypair.pubkey());
|
||||
let storage_balance = client.poll_get_balance_with_commitment(
|
||||
&storage_keypair.pubkey(),
|
||||
meta.client_commitment.clone(),
|
||||
);
|
||||
if storage_balance.is_err() || storage_balance.unwrap() == 0 {
|
||||
error!("Unable to submit mining proof, no storage account");
|
||||
return;
|
||||
}
|
||||
// ...or no lamports for fees
|
||||
let balance = client.poll_get_balance(&archiver_keypair.pubkey());
|
||||
let balance = client.poll_get_balance_with_commitment(
|
||||
&archiver_keypair.pubkey(),
|
||||
meta.client_commitment.clone(),
|
||||
);
|
||||
if balance.is_err() || balance.unwrap() == 0 {
|
||||
error!("Unable to submit mining proof, insufficient Archiver Account balance");
|
||||
return;
|
||||
}
|
||||
|
||||
let blockhash = match client.get_recent_blockhash() {
|
||||
Ok((blockhash, _)) => blockhash,
|
||||
Err(_) => {
|
||||
error!("unable to get recent blockhash, can't submit proof");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let blockhash =
|
||||
match client.get_recent_blockhash_with_commitment(meta.client_commitment.clone()) {
|
||||
Ok((blockhash, _)) => blockhash,
|
||||
Err(_) => {
|
||||
error!("unable to get recent blockhash, can't submit proof");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let instruction = storage_instruction::mining_proof(
|
||||
&storage_keypair.pubkey(),
|
||||
meta.sha_state,
|
||||
@ -700,7 +732,10 @@ impl Archiver {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_segment_config(cluster_info: &Arc<RwLock<ClusterInfo>>) -> result::Result<u64, Error> {
|
||||
fn get_segment_config(
|
||||
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
||||
client_commitment: CommitmentConfig,
|
||||
) -> result::Result<u64, Error> {
|
||||
let rpc_peers = {
|
||||
let cluster_info = cluster_info.read().unwrap();
|
||||
cluster_info.rpc_peers()
|
||||
@ -712,7 +747,12 @@ impl Archiver {
|
||||
RpcClient::new_socket(rpc_peers[node_index].rpc)
|
||||
};
|
||||
Ok(rpc_client
|
||||
.retry_make_rpc_request(&RpcRequest::GetSlotsPerSegment, None, 0)
|
||||
.retry_make_rpc_request(
|
||||
&RpcRequest::GetSlotsPerSegment,
|
||||
None,
|
||||
0,
|
||||
Some(client_commitment),
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("Error while making rpc request {:?}", err);
|
||||
Error::IO(io::Error::new(ErrorKind::Other, "rpc error"))
|
||||
@ -764,7 +804,7 @@ impl Archiver {
|
||||
RpcClient::new_socket(rpc_peers[node_index].rpc)
|
||||
};
|
||||
let response = rpc_client
|
||||
.retry_make_rpc_request(&RpcRequest::GetStorageTurn, None, 0)
|
||||
.retry_make_rpc_request(&RpcRequest::GetStorageTurn, None, 0, None)
|
||||
.map_err(|err| {
|
||||
warn!("Error while making rpc request {:?}", err);
|
||||
Error::IO(io::Error::new(ErrorKind::Other, "rpc error"))
|
||||
|
441
core/src/rpc.rs
441
core/src/rpc.rs
@ -19,6 +19,7 @@ use solana_runtime::bank::Bank;
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
clock::Slot,
|
||||
commitment_config::{CommitmentConfig, CommitmentLevel},
|
||||
epoch_schedule::EpochSchedule,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
@ -60,8 +61,18 @@ pub struct JsonRpcRequestProcessor {
|
||||
}
|
||||
|
||||
impl JsonRpcRequestProcessor {
|
||||
fn bank(&self) -> Arc<Bank> {
|
||||
self.bank_forks.read().unwrap().working_bank()
|
||||
fn bank(&self, commitment: Option<CommitmentConfig>) -> Arc<Bank> {
|
||||
debug!("RPC commitment_config: {:?}", commitment);
|
||||
let r_bank_forks = self.bank_forks.read().unwrap();
|
||||
if commitment.is_some() && commitment.unwrap().commitment == CommitmentLevel::Recent {
|
||||
let bank = r_bank_forks.working_bank();
|
||||
debug!("RPC using working_bank: {:?}", bank.slot());
|
||||
bank
|
||||
} else {
|
||||
let slot = r_bank_forks.root();
|
||||
debug!("RPC using block: {:?}", slot);
|
||||
r_bank_forks.get(slot).cloned().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
@ -80,43 +91,62 @@ impl JsonRpcRequestProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_account_info(&self, pubkey: &Pubkey) -> Result<Account> {
|
||||
self.bank()
|
||||
pub fn get_account_info(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Account> {
|
||||
self.bank(commitment)
|
||||
.get_account(&pubkey)
|
||||
.ok_or_else(Error::invalid_request)
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64> {
|
||||
Ok(self.bank().get_minimum_balance_for_rent_exemption(data_len))
|
||||
pub fn get_minimum_balance_for_rent_exemption(
|
||||
&self,
|
||||
data_len: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
Ok(self
|
||||
.bank(commitment)
|
||||
.get_minimum_balance_for_rent_exemption(data_len))
|
||||
}
|
||||
|
||||
pub fn get_program_accounts(&self, program_id: &Pubkey) -> Result<Vec<(String, Account)>> {
|
||||
pub fn get_program_accounts(
|
||||
&self,
|
||||
program_id: &Pubkey,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<(String, Account)>> {
|
||||
Ok(self
|
||||
.bank()
|
||||
.bank(commitment)
|
||||
.get_program_accounts(&program_id)
|
||||
.into_iter()
|
||||
.map(|(pubkey, account)| (pubkey.to_string(), account))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn get_inflation(&self) -> Result<Inflation> {
|
||||
Ok(self.bank().inflation())
|
||||
pub fn get_inflation(&self, commitment: Option<CommitmentConfig>) -> Result<Inflation> {
|
||||
Ok(self.bank(commitment).inflation())
|
||||
}
|
||||
|
||||
pub fn get_epoch_schedule(&self) -> Result<EpochSchedule> {
|
||||
Ok(*self.bank().epoch_schedule())
|
||||
// Since epoch schedule data comes from the genesis block, any commitment level should be
|
||||
// fine
|
||||
Ok(*self.bank(None).epoch_schedule())
|
||||
}
|
||||
|
||||
pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
|
||||
self.bank().get_balance(&pubkey)
|
||||
pub fn get_balance(&self, pubkey: &Pubkey, commitment: Option<CommitmentConfig>) -> u64 {
|
||||
self.bank(commitment).get_balance(&pubkey)
|
||||
}
|
||||
|
||||
fn get_recent_blockhash(&self) -> (String, FeeCalculator) {
|
||||
let (blockhash, fee_calculator) = self.bank().confirmed_last_blockhash();
|
||||
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)
|
||||
}
|
||||
|
||||
fn get_block_commitment(&self, block: u64) -> (Option<BlockCommitment>, u64) {
|
||||
fn get_block_commitment(&self, block: Slot) -> (Option<BlockCommitment>, u64) {
|
||||
let r_block_commitment = self.block_commitment_cache.read().unwrap();
|
||||
(
|
||||
r_block_commitment.get_block_commitment(block).cloned(),
|
||||
@ -124,41 +154,36 @@ impl JsonRpcRequestProcessor {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_signature_status(&self, signature: Signature) -> Option<transaction::Result<()>> {
|
||||
self.get_signature_confirmation_status(signature)
|
||||
.map(|x| x.1)
|
||||
}
|
||||
|
||||
pub fn get_signature_confirmations(&self, signature: Signature) -> Option<usize> {
|
||||
self.get_signature_confirmation_status(signature)
|
||||
.map(|x| x.0)
|
||||
}
|
||||
|
||||
pub fn get_signature_confirmation_status(
|
||||
&self,
|
||||
signature: Signature,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Option<(usize, transaction::Result<()>)> {
|
||||
self.bank().get_signature_confirmation_status(&signature)
|
||||
self.bank(commitment)
|
||||
.get_signature_confirmation_status(&signature)
|
||||
}
|
||||
|
||||
fn get_slot(&self) -> Result<u64> {
|
||||
Ok(self.bank().slot())
|
||||
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
||||
Ok(self.bank(commitment).slot())
|
||||
}
|
||||
|
||||
fn get_slot_leader(&self) -> Result<String> {
|
||||
Ok(self.bank().collector_id().to_string())
|
||||
fn get_slot_leader(&self, commitment: Option<CommitmentConfig>) -> Result<String> {
|
||||
Ok(self.bank(commitment).collector_id().to_string())
|
||||
}
|
||||
|
||||
fn get_transaction_count(&self) -> Result<u64> {
|
||||
Ok(self.bank().transaction_count() as u64)
|
||||
fn get_transaction_count(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
||||
Ok(self.bank(commitment).transaction_count() as u64)
|
||||
}
|
||||
|
||||
fn get_total_supply(&self) -> Result<u64> {
|
||||
Ok(self.bank().capitalization())
|
||||
fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
||||
Ok(self.bank(commitment).capitalization())
|
||||
}
|
||||
|
||||
fn get_vote_accounts(&self) -> Result<RpcVoteAccountStatus> {
|
||||
let bank = self.bank();
|
||||
fn get_vote_accounts(
|
||||
&self,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<RpcVoteAccountStatus> {
|
||||
let bank = self.bank(commitment);
|
||||
let vote_accounts = bank.vote_accounts();
|
||||
let epoch_vote_accounts = bank
|
||||
.epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0)
|
||||
@ -212,8 +237,8 @@ impl JsonRpcRequestProcessor {
|
||||
))
|
||||
}
|
||||
|
||||
fn get_slots_per_segment(&self) -> Result<u64> {
|
||||
Ok(self.bank().slots_per_segment())
|
||||
fn get_slots_per_segment(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
||||
Ok(self.bank(commitment).slots_per_segment())
|
||||
}
|
||||
|
||||
fn get_storage_pubkeys_for_slot(&self, slot: Slot) -> Result<Vec<Pubkey>> {
|
||||
@ -281,139 +306,224 @@ pub trait RpcSol {
|
||||
type Metadata;
|
||||
|
||||
#[rpc(meta, name = "confirmTransaction")]
|
||||
fn confirm_transaction(&self, _: Self::Metadata, _: String) -> Result<bool>;
|
||||
fn confirm_transaction(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<bool>;
|
||||
|
||||
#[rpc(meta, name = "getAccountInfo")]
|
||||
fn get_account_info(&self, _: Self::Metadata, _: String) -> Result<Account>;
|
||||
fn get_account_info(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Account>;
|
||||
|
||||
#[rpc(meta, name = "getProgramAccounts")]
|
||||
fn get_program_accounts(&self, _: Self::Metadata, _: String) -> Result<Vec<(String, Account)>>;
|
||||
fn get_program_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
program_id_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<(String, Account)>>;
|
||||
|
||||
#[rpc(meta, name = "getMinimumBalanceForRentExemption")]
|
||||
fn get_minimum_balance_for_rent_exemption(&self, _: Self::Metadata, _: usize) -> Result<u64>;
|
||||
fn get_minimum_balance_for_rent_exemption(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
data_len: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getInflation")]
|
||||
fn get_inflation(&self, _: Self::Metadata) -> Result<Inflation>;
|
||||
fn get_inflation(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Inflation>;
|
||||
|
||||
#[rpc(meta, name = "getEpochSchedule")]
|
||||
fn get_epoch_schedule(&self, _: Self::Metadata) -> Result<EpochSchedule>;
|
||||
fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>;
|
||||
|
||||
#[rpc(meta, name = "getBalance")]
|
||||
fn get_balance(&self, _: Self::Metadata, _: String) -> Result<u64>;
|
||||
fn get_balance(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getClusterNodes")]
|
||||
fn get_cluster_nodes(&self, _: Self::Metadata) -> Result<Vec<RpcContactInfo>>;
|
||||
fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>>;
|
||||
|
||||
#[rpc(meta, name = "getEpochInfo")]
|
||||
fn get_epoch_info(&self, _: Self::Metadata) -> Result<RpcEpochInfo>;
|
||||
fn get_epoch_info(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<RpcEpochInfo>;
|
||||
|
||||
#[rpc(meta, name = "getBlockCommitment")]
|
||||
fn get_block_commitment(
|
||||
&self,
|
||||
_: Self::Metadata,
|
||||
_: u64,
|
||||
meta: Self::Metadata,
|
||||
block: u64,
|
||||
) -> Result<(Option<BlockCommitment>, u64)>;
|
||||
|
||||
#[rpc(meta, name = "getGenesisBlockhash")]
|
||||
fn get_genesis_blockhash(&self, _: Self::Metadata) -> Result<String>;
|
||||
fn get_genesis_blockhash(&self, meta: Self::Metadata) -> Result<String>;
|
||||
|
||||
#[rpc(meta, name = "getLeaderSchedule")]
|
||||
fn get_leader_schedule(&self, _: Self::Metadata) -> Result<Option<Vec<String>>>;
|
||||
fn get_leader_schedule(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<Vec<String>>>;
|
||||
|
||||
#[rpc(meta, name = "getRecentBlockhash")]
|
||||
fn get_recent_blockhash(&self, _: Self::Metadata) -> Result<(String, FeeCalculator)>;
|
||||
fn get_recent_blockhash(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<(String, FeeCalculator)>;
|
||||
|
||||
#[rpc(meta, name = "getSignatureStatus")]
|
||||
fn get_signature_status(
|
||||
&self,
|
||||
_: Self::Metadata,
|
||||
_: String,
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<transaction::Result<()>>>;
|
||||
|
||||
#[rpc(meta, name = "getSlot")]
|
||||
fn get_slot(&self, _: Self::Metadata) -> Result<u64>;
|
||||
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getTransactionCount")]
|
||||
fn get_transaction_count(&self, _: Self::Metadata) -> Result<u64>;
|
||||
fn get_transaction_count(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getTotalSupply")]
|
||||
fn get_total_supply(&self, _: Self::Metadata) -> Result<u64>;
|
||||
fn get_total_supply(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "requestAirdrop")]
|
||||
fn request_airdrop(&self, _: Self::Metadata, _: String, _: u64) -> Result<String>;
|
||||
fn request_airdrop(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
lamports: u64,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<String>;
|
||||
|
||||
#[rpc(meta, name = "sendTransaction")]
|
||||
fn send_transaction(&self, _: Self::Metadata, _: Vec<u8>) -> Result<String>;
|
||||
fn send_transaction(&self, meta: Self::Metadata, data: Vec<u8>) -> Result<String>;
|
||||
|
||||
#[rpc(meta, name = "getSlotLeader")]
|
||||
fn get_slot_leader(&self, _: Self::Metadata) -> Result<String>;
|
||||
fn get_slot_leader(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<String>;
|
||||
|
||||
#[rpc(meta, name = "getVoteAccounts")]
|
||||
fn get_vote_accounts(&self, _: Self::Metadata) -> Result<RpcVoteAccountStatus>;
|
||||
fn get_vote_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<RpcVoteAccountStatus>;
|
||||
|
||||
#[rpc(meta, name = "getStorageTurnRate")]
|
||||
fn get_storage_turn_rate(&self, _: Self::Metadata) -> Result<u64>;
|
||||
fn get_storage_turn_rate(&self, meta: Self::Metadata) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getStorageTurn")]
|
||||
fn get_storage_turn(&self, _: Self::Metadata) -> Result<(String, u64)>;
|
||||
fn get_storage_turn(&self, meta: Self::Metadata) -> Result<(String, u64)>;
|
||||
|
||||
#[rpc(meta, name = "getSlotsPerSegment")]
|
||||
fn get_slots_per_segment(&self, _: Self::Metadata) -> Result<u64>;
|
||||
fn get_slots_per_segment(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getStoragePubkeysForSlot")]
|
||||
fn get_storage_pubkeys_for_slot(&self, _: Self::Metadata, _: u64) -> Result<Vec<Pubkey>>;
|
||||
fn get_storage_pubkeys_for_slot(&self, meta: Self::Metadata, slot: u64) -> Result<Vec<Pubkey>>;
|
||||
|
||||
#[rpc(meta, name = "validatorExit")]
|
||||
fn validator_exit(&self, _: Self::Metadata) -> Result<bool>;
|
||||
fn validator_exit(&self, meta: Self::Metadata) -> Result<bool>;
|
||||
|
||||
#[rpc(meta, name = "getNumBlocksSinceSignatureConfirmation")]
|
||||
fn get_num_blocks_since_signature_confirmation(
|
||||
&self,
|
||||
_: Self::Metadata,
|
||||
_: String,
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<usize>>;
|
||||
|
||||
#[rpc(meta, name = "getSignatureConfirmation")]
|
||||
fn get_signature_confirmation(
|
||||
&self,
|
||||
_: Self::Metadata,
|
||||
_: String,
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<(usize, transaction::Result<()>)>>;
|
||||
|
||||
#[rpc(meta, name = "getVersion")]
|
||||
fn get_version(&self, _: Self::Metadata) -> Result<RpcVersionInfo>;
|
||||
fn get_version(&self, meta: Self::Metadata) -> Result<RpcVersionInfo>;
|
||||
|
||||
#[rpc(meta, name = "setLogFilter")]
|
||||
fn set_log_filter(&self, _: Self::Metadata, _: String) -> Result<()>;
|
||||
fn set_log_filter(&self, _meta: Self::Metadata, filter: String) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct RpcSolImpl;
|
||||
impl RpcSol for RpcSolImpl {
|
||||
type Metadata = Meta;
|
||||
|
||||
fn confirm_transaction(&self, meta: Self::Metadata, id: String) -> Result<bool> {
|
||||
debug!("confirm_transaction rpc request received: {:?}", id);
|
||||
self.get_signature_status(meta, id).map(|status_option| {
|
||||
if status_option.is_none() {
|
||||
return false;
|
||||
}
|
||||
status_option.unwrap().is_ok()
|
||||
})
|
||||
fn confirm_transaction(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
signature_str: 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()
|
||||
})
|
||||
}
|
||||
|
||||
fn get_account_info(&self, meta: Self::Metadata, id: String) -> Result<Account> {
|
||||
debug!("get_account_info rpc request received: {:?}", id);
|
||||
let pubkey = verify_pubkey(id)?;
|
||||
fn get_account_info(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Account> {
|
||||
debug!("get_account_info rpc request received: {:?}", pubkey_str);
|
||||
let pubkey = verify_pubkey(pubkey_str)?;
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_account_info(&pubkey)
|
||||
.get_account_info(&pubkey, commitment)
|
||||
}
|
||||
|
||||
fn get_minimum_balance_for_rent_exemption(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
data_len: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
debug!(
|
||||
"get_minimum_balance_for_rent_exemption rpc request received: {:?}",
|
||||
@ -422,29 +532,37 @@ impl RpcSol for RpcSolImpl {
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_minimum_balance_for_rent_exemption(data_len)
|
||||
.get_minimum_balance_for_rent_exemption(data_len, commitment)
|
||||
}
|
||||
|
||||
fn get_program_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
id: String,
|
||||
program_id_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<(String, Account)>> {
|
||||
debug!("get_program_accounts rpc request received: {:?}", id);
|
||||
let program_id = verify_pubkey(id)?;
|
||||
debug!(
|
||||
"get_program_accounts rpc request received: {:?}",
|
||||
program_id_str
|
||||
);
|
||||
let program_id = verify_pubkey(program_id_str)?;
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_program_accounts(&program_id)
|
||||
.get_program_accounts(&program_id, commitment)
|
||||
}
|
||||
|
||||
fn get_inflation(&self, meta: Self::Metadata) -> Result<Inflation> {
|
||||
fn get_inflation(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Inflation> {
|
||||
debug!("get_inflation rpc request received");
|
||||
Ok(meta
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_inflation()
|
||||
.get_inflation(commitment)
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
@ -458,10 +576,19 @@ impl RpcSol for RpcSolImpl {
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
fn get_balance(&self, meta: Self::Metadata, id: String) -> Result<u64> {
|
||||
debug!("get_balance rpc request received: {:?}", id);
|
||||
let pubkey = verify_pubkey(id)?;
|
||||
Ok(meta.request_processor.read().unwrap().get_balance(&pubkey))
|
||||
fn get_balance(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
debug!("get_balance rpc request received: {:?}", pubkey_str);
|
||||
let pubkey = verify_pubkey(pubkey_str)?;
|
||||
Ok(meta
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_balance(&pubkey, commitment))
|
||||
}
|
||||
|
||||
fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>> {
|
||||
@ -491,8 +618,12 @@ impl RpcSol for RpcSolImpl {
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn get_epoch_info(&self, meta: Self::Metadata) -> Result<RpcEpochInfo> {
|
||||
let bank = meta.request_processor.read().unwrap().bank();
|
||||
fn get_epoch_info(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<RpcEpochInfo> {
|
||||
let bank = meta.request_processor.read().unwrap().bank(commitment);
|
||||
let epoch_schedule = bank.epoch_schedule();
|
||||
let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(bank.slot());
|
||||
let slot = bank.slot();
|
||||
@ -507,7 +638,7 @@ impl RpcSol for RpcSolImpl {
|
||||
fn get_block_commitment(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
block: u64,
|
||||
block: Slot,
|
||||
) -> Result<(Option<BlockCommitment>, u64)> {
|
||||
Ok(meta
|
||||
.request_processor
|
||||
@ -521,8 +652,12 @@ impl RpcSol for RpcSolImpl {
|
||||
Ok(meta.genesis_blockhash.to_string())
|
||||
}
|
||||
|
||||
fn get_leader_schedule(&self, meta: Self::Metadata) -> Result<Option<Vec<String>>> {
|
||||
let bank = meta.request_processor.read().unwrap().bank();
|
||||
fn get_leader_schedule(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<Vec<String>>> {
|
||||
let bank = meta.request_processor.read().unwrap().bank(commitment);
|
||||
Ok(
|
||||
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank).map(
|
||||
|leader_schedule| {
|
||||
@ -536,66 +671,93 @@ impl RpcSol for RpcSolImpl {
|
||||
)
|
||||
}
|
||||
|
||||
fn get_recent_blockhash(&self, meta: Self::Metadata) -> Result<(String, FeeCalculator)> {
|
||||
fn get_recent_blockhash(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<(String, FeeCalculator)> {
|
||||
debug!("get_recent_blockhash rpc request received");
|
||||
Ok(meta
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_recent_blockhash())
|
||||
.get_recent_blockhash(commitment))
|
||||
}
|
||||
|
||||
fn get_signature_status(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
id: String,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<transaction::Result<()>>> {
|
||||
self.get_signature_confirmation(meta, id)
|
||||
self.get_signature_confirmation(meta, signature_str, commitment)
|
||||
.map(|res| res.map(|x| x.1))
|
||||
}
|
||||
|
||||
fn get_slot(&self, meta: Self::Metadata) -> Result<u64> {
|
||||
meta.request_processor.read().unwrap().get_slot()
|
||||
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
||||
meta.request_processor.read().unwrap().get_slot(commitment)
|
||||
}
|
||||
|
||||
fn get_num_blocks_since_signature_confirmation(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
id: String,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<usize>> {
|
||||
self.get_signature_confirmation(meta, id)
|
||||
self.get_signature_confirmation(meta, signature_str, commitment)
|
||||
.map(|res| res.map(|x| x.0))
|
||||
}
|
||||
|
||||
fn get_signature_confirmation(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
id: String,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<(usize, transaction::Result<()>)>> {
|
||||
debug!("get_signature_confirmation rpc request received: {:?}", id);
|
||||
let signature = verify_signature(&id)?;
|
||||
debug!(
|
||||
"get_signature_confirmation rpc request received: {:?}",
|
||||
signature_str
|
||||
);
|
||||
let signature = verify_signature(&signature_str)?;
|
||||
Ok(meta
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_signature_confirmation_status(signature))
|
||||
.get_signature_confirmation_status(signature, commitment))
|
||||
}
|
||||
|
||||
fn get_transaction_count(&self, meta: Self::Metadata) -> Result<u64> {
|
||||
fn get_transaction_count(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
debug!("get_transaction_count rpc request received");
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_transaction_count()
|
||||
.get_transaction_count(commitment)
|
||||
}
|
||||
|
||||
fn get_total_supply(&self, meta: Self::Metadata) -> Result<u64> {
|
||||
fn get_total_supply(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
debug!("get_total_supply rpc request received");
|
||||
meta.request_processor.read().unwrap().get_total_supply()
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_total_supply(commitment)
|
||||
}
|
||||
|
||||
fn request_airdrop(&self, meta: Self::Metadata, id: String, lamports: u64) -> Result<String> {
|
||||
trace!("request_airdrop id={} lamports={}", id, lamports);
|
||||
fn request_airdrop(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
lamports: u64,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<String> {
|
||||
trace!("request_airdrop id={} lamports={}", pubkey_str, lamports);
|
||||
|
||||
let drone_addr = meta
|
||||
.request_processor
|
||||
@ -604,13 +766,13 @@ impl RpcSol for RpcSolImpl {
|
||||
.config
|
||||
.drone_addr
|
||||
.ok_or_else(Error::invalid_request)?;
|
||||
let pubkey = verify_pubkey(id)?;
|
||||
let pubkey = verify_pubkey(pubkey_str)?;
|
||||
|
||||
let blockhash = meta
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.bank()
|
||||
.bank(commitment.clone())
|
||||
.confirmed_last_blockhash()
|
||||
.0;
|
||||
let transaction = request_airdrop_transaction(&drone_addr, &pubkey, lamports, blockhash)
|
||||
@ -641,7 +803,8 @@ impl RpcSol for RpcSolImpl {
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_signature_status(signature);
|
||||
.get_signature_confirmation_status(signature, commitment.clone())
|
||||
.map(|x| x.1);
|
||||
|
||||
if signature_status == Some(Ok(())) {
|
||||
info!("airdrop signature ok");
|
||||
@ -689,12 +852,26 @@ impl RpcSol for RpcSolImpl {
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
fn get_slot_leader(&self, meta: Self::Metadata) -> Result<String> {
|
||||
meta.request_processor.read().unwrap().get_slot_leader()
|
||||
fn get_slot_leader(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<String> {
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_slot_leader(commitment)
|
||||
}
|
||||
|
||||
fn get_vote_accounts(&self, meta: Self::Metadata) -> Result<RpcVoteAccountStatus> {
|
||||
meta.request_processor.read().unwrap().get_vote_accounts()
|
||||
fn get_vote_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<RpcVoteAccountStatus> {
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_vote_accounts(commitment)
|
||||
}
|
||||
|
||||
fn get_storage_turn_rate(&self, meta: Self::Metadata) -> Result<u64> {
|
||||
@ -708,11 +885,15 @@ impl RpcSol for RpcSolImpl {
|
||||
meta.request_processor.read().unwrap().get_storage_turn()
|
||||
}
|
||||
|
||||
fn get_slots_per_segment(&self, meta: Self::Metadata) -> Result<u64> {
|
||||
fn get_slots_per_segment(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_slots_per_segment()
|
||||
.get_slots_per_segment(commitment)
|
||||
}
|
||||
|
||||
fn get_storage_pubkeys_for_slot(
|
||||
@ -736,7 +917,7 @@ impl RpcSol for RpcSolImpl {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_log_filter(&self, _: Self::Metadata, filter: String) -> Result<()> {
|
||||
fn set_log_filter(&self, _meta: Self::Metadata, filter: String) -> Result<()> {
|
||||
solana_logger::setup_with_filter(&filter);
|
||||
Ok(())
|
||||
}
|
||||
@ -863,7 +1044,7 @@ pub mod tests {
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
assert_eq!(request_processor.get_transaction_count().unwrap(), 1);
|
||||
assert_eq!(request_processor.get_transaction_count(None).unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -221,7 +221,7 @@ mod tests {
|
||||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_balance(&mint_keypair.pubkey())
|
||||
.get_balance(&mint_keypair.pubkey(), None)
|
||||
);
|
||||
rpc_service.exit();
|
||||
rpc_service.join().unwrap();
|
||||
|
@ -511,7 +511,7 @@ pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
|
||||
let GenesisBlockInfo {
|
||||
mut genesis_block,
|
||||
mint_keypair,
|
||||
..
|
||||
voting_keypair,
|
||||
} = create_genesis_block_with_leader(10_000, &contact_info.id, 42);
|
||||
genesis_block
|
||||
.native_instruction_processors
|
||||
@ -522,14 +522,14 @@ pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
|
||||
|
||||
let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block);
|
||||
|
||||
let voting_keypair = Arc::new(Keypair::new());
|
||||
let leader_voting_keypair = Arc::new(voting_keypair);
|
||||
let storage_keypair = Arc::new(Keypair::new());
|
||||
let node = Validator::new(
|
||||
node,
|
||||
&node_keypair,
|
||||
&ledger_path,
|
||||
&voting_keypair.pubkey(),
|
||||
&voting_keypair,
|
||||
&leader_voting_keypair.pubkey(),
|
||||
&leader_voting_keypair,
|
||||
&storage_keypair,
|
||||
None,
|
||||
true,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use rand::{thread_rng, Rng};
|
||||
use solana_client::thin_client::create_client;
|
||||
/// Cluster independant integration tests
|
||||
///
|
||||
/// All tests must start from an entry point and a funding keypair and
|
||||
/// discover the rest of the network.
|
||||
use rand::{thread_rng, Rng};
|
||||
use solana_client::thin_client::create_client;
|
||||
use solana_core::{
|
||||
cluster_info::VALIDATOR_PORT_RANGE, consensus::VOTE_THRESHOLD_DEPTH, contact_info::ContactInfo,
|
||||
gossip_service::discover_cluster,
|
||||
@ -15,6 +15,7 @@ use solana_ledger::{
|
||||
use solana_sdk::{
|
||||
client::SyncClient,
|
||||
clock::{Slot, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT, NUM_CONSECUTIVE_LEADER_SLOTS},
|
||||
commitment_config::CommitmentConfig,
|
||||
epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
|
||||
hash::Hash,
|
||||
poh_config::PohConfig,
|
||||
@ -49,10 +50,12 @@ pub fn spend_and_verify_all_nodes<S: ::std::hash::BuildHasher>(
|
||||
let random_keypair = Keypair::new();
|
||||
let client = create_client(ingress_node.client_facing_addr(), VALIDATOR_PORT_RANGE);
|
||||
let bal = client
|
||||
.poll_get_balance(&funding_keypair.pubkey())
|
||||
.poll_get_balance_with_commitment(&funding_keypair.pubkey(), CommitmentConfig::recent())
|
||||
.expect("balance in source");
|
||||
assert!(bal > 0);
|
||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap();
|
||||
let mut transaction =
|
||||
system_transaction::transfer(&funding_keypair, &random_keypair.pubkey(), 1, blockhash);
|
||||
let confs = VOTE_THRESHOLD_DEPTH + 1;
|
||||
@ -75,7 +78,9 @@ pub fn verify_balances<S: ::std::hash::BuildHasher>(
|
||||
) {
|
||||
let client = create_client(node.client_facing_addr(), VALIDATOR_PORT_RANGE);
|
||||
for (pk, b) in expected_balances {
|
||||
let bal = client.poll_get_balance(&pk).expect("balance in source");
|
||||
let bal = client
|
||||
.poll_get_balance_with_commitment(&pk, CommitmentConfig::recent())
|
||||
.expect("balance in source");
|
||||
assert_eq!(bal, b);
|
||||
}
|
||||
}
|
||||
@ -91,10 +96,12 @@ pub fn send_many_transactions(
|
||||
for _ in 0..num_txs {
|
||||
let random_keypair = Keypair::new();
|
||||
let bal = client
|
||||
.poll_get_balance(&funding_keypair.pubkey())
|
||||
.poll_get_balance_with_commitment(&funding_keypair.pubkey(), CommitmentConfig::recent())
|
||||
.expect("balance in source");
|
||||
assert!(bal > 0);
|
||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap();
|
||||
let transfer_amount = thread_rng().gen_range(1, max_tokens_per_transfer);
|
||||
|
||||
let mut transaction = system_transaction::transfer(
|
||||
@ -188,7 +195,7 @@ pub fn kill_entry_and_spend_and_verify_rest(
|
||||
|
||||
for ingress_node in &cluster_nodes {
|
||||
client
|
||||
.poll_get_balance(&ingress_node.id)
|
||||
.poll_get_balance_with_commitment(&ingress_node.id, CommitmentConfig::recent())
|
||||
.unwrap_or_else(|err| panic!("Node {} has no balance: {}", ingress_node.id, err));
|
||||
}
|
||||
|
||||
@ -212,7 +219,7 @@ pub fn kill_entry_and_spend_and_verify_rest(
|
||||
|
||||
let client = create_client(ingress_node.client_facing_addr(), VALIDATOR_PORT_RANGE);
|
||||
let balance = client
|
||||
.poll_get_balance(&funding_keypair.pubkey())
|
||||
.poll_get_balance_with_commitment(&funding_keypair.pubkey(), CommitmentConfig::recent())
|
||||
.expect("balance in source");
|
||||
assert_ne!(balance, 0);
|
||||
|
||||
@ -225,7 +232,9 @@ pub fn kill_entry_and_spend_and_verify_rest(
|
||||
}
|
||||
|
||||
let random_keypair = Keypair::new();
|
||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap();
|
||||
let mut transaction = system_transaction::transfer(
|
||||
&funding_keypair,
|
||||
&random_keypair.pubkey(),
|
||||
|
@ -13,6 +13,7 @@ use solana_ledger::blocktree::create_new_tmp_ledger;
|
||||
use solana_sdk::{
|
||||
client::SyncClient,
|
||||
clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT},
|
||||
commitment_config::CommitmentConfig,
|
||||
epoch_schedule::EpochSchedule,
|
||||
genesis_block::{GenesisBlock, OperatingMode},
|
||||
message::Message,
|
||||
@ -386,6 +387,7 @@ impl LocalCluster {
|
||||
self.entry_point_info.clone(),
|
||||
archiver_keypair,
|
||||
storage_keypair,
|
||||
CommitmentConfig::recent(),
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("Archiver::new() failed: {:?}", err));
|
||||
|
||||
@ -424,7 +426,9 @@ impl LocalCluster {
|
||||
lamports: u64,
|
||||
) -> u64 {
|
||||
trace!("getting leader blockhash");
|
||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
||||
let (blockhash, _fee_calculator) = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap();
|
||||
let mut tx =
|
||||
system_transaction::transfer(&source_keypair, dest_pubkey, lamports, blockhash);
|
||||
info!(
|
||||
@ -437,7 +441,11 @@ impl LocalCluster {
|
||||
.retry_transfer(&source_keypair, &mut tx, 10)
|
||||
.expect("client transfer");
|
||||
client
|
||||
.wait_for_balance(dest_pubkey, Some(lamports))
|
||||
.wait_for_balance_with_commitment(
|
||||
dest_pubkey,
|
||||
Some(lamports),
|
||||
CommitmentConfig::recent(),
|
||||
)
|
||||
.expect("get balance")
|
||||
}
|
||||
|
||||
@ -453,7 +461,11 @@ impl LocalCluster {
|
||||
let stake_account_pubkey = stake_account_keypair.pubkey();
|
||||
|
||||
// Create the vote account if necessary
|
||||
if client.poll_get_balance(&vote_account_pubkey).unwrap_or(0) == 0 {
|
||||
if client
|
||||
.poll_get_balance_with_commitment(&vote_account_pubkey, CommitmentConfig::recent())
|
||||
.unwrap_or(0)
|
||||
== 0
|
||||
{
|
||||
// 1) Create vote account
|
||||
|
||||
let mut transaction = Transaction::new_signed_instructions(
|
||||
@ -469,13 +481,20 @@ impl LocalCluster {
|
||||
},
|
||||
amount,
|
||||
),
|
||||
client.get_recent_blockhash().unwrap().0,
|
||||
client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap()
|
||||
.0,
|
||||
);
|
||||
client
|
||||
.retry_transfer(&from_account, &mut transaction, 10)
|
||||
.expect("fund vote");
|
||||
client
|
||||
.wait_for_balance(&vote_account_pubkey, Some(amount))
|
||||
.wait_for_balance_with_commitment(
|
||||
&vote_account_pubkey,
|
||||
Some(amount),
|
||||
CommitmentConfig::recent(),
|
||||
)
|
||||
.expect("get balance");
|
||||
|
||||
let mut transaction = Transaction::new_signed_instructions(
|
||||
@ -487,7 +506,10 @@ impl LocalCluster {
|
||||
&StakeAuthorized::auto(&stake_account_pubkey),
|
||||
amount,
|
||||
),
|
||||
client.get_recent_blockhash().unwrap().0,
|
||||
client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap()
|
||||
.0,
|
||||
);
|
||||
|
||||
client
|
||||
@ -499,7 +521,11 @@ impl LocalCluster {
|
||||
)
|
||||
.expect("delegate stake");
|
||||
client
|
||||
.wait_for_balance(&stake_account_pubkey, Some(amount))
|
||||
.wait_for_balance_with_commitment(
|
||||
&stake_account_pubkey,
|
||||
Some(amount),
|
||||
CommitmentConfig::recent(),
|
||||
)
|
||||
.expect("get balance");
|
||||
} else {
|
||||
warn!(
|
||||
@ -509,8 +535,8 @@ impl LocalCluster {
|
||||
}
|
||||
info!("Checking for vote account registration of {}", node_pubkey);
|
||||
match (
|
||||
client.get_account(&stake_account_pubkey),
|
||||
client.get_account(&vote_account_pubkey),
|
||||
client.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent()),
|
||||
client.get_account_with_commitment(&vote_account_pubkey, CommitmentConfig::recent()),
|
||||
) {
|
||||
(Ok(Some(stake_account)), Ok(Some(vote_account))) => {
|
||||
match (
|
||||
@ -568,7 +594,10 @@ impl LocalCluster {
|
||||
Some(&from_keypair.pubkey()),
|
||||
);
|
||||
let signer_keys = vec![from_keypair.as_ref()];
|
||||
let blockhash = client.get_recent_blockhash().unwrap().0;
|
||||
let blockhash = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
.unwrap()
|
||||
.0;
|
||||
let mut transaction = Transaction::new(&signer_keys, message, blockhash);
|
||||
client
|
||||
.retry_transfer(&from_keypair, &mut transaction, 10)
|
||||
|
@ -1,17 +1,24 @@
|
||||
use crate::local_cluster::{ClusterConfig, LocalCluster};
|
||||
use serial_test_derive::serial;
|
||||
use solana_client::thin_client::create_client;
|
||||
use solana_core::archiver::Archiver;
|
||||
use solana_core::cluster_info::{ClusterInfo, Node, VALIDATOR_PORT_RANGE};
|
||||
use solana_core::contact_info::ContactInfo;
|
||||
use solana_core::gossip_service::discover_cluster;
|
||||
use solana_core::storage_stage::SLOTS_PER_TURN_TEST;
|
||||
use solana_core::validator::ValidatorConfig;
|
||||
use solana_core::{
|
||||
archiver::Archiver,
|
||||
cluster_info::{ClusterInfo, Node, VALIDATOR_PORT_RANGE},
|
||||
contact_info::ContactInfo,
|
||||
gossip_service::discover_cluster,
|
||||
storage_stage::SLOTS_PER_TURN_TEST,
|
||||
validator::ValidatorConfig,
|
||||
};
|
||||
use solana_ledger::blocktree::{create_new_tmp_ledger, get_tmp_ledger_path, Blocktree};
|
||||
use solana_sdk::genesis_block::create_genesis_block;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use std::fs::remove_dir_all;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig,
|
||||
genesis_block::create_genesis_block,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
};
|
||||
use std::{
|
||||
fs::remove_dir_all,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
/// Start the cluster with the given configuration and wait till the archivers are discovered
|
||||
/// Then download blobs from one of them.
|
||||
@ -99,6 +106,7 @@ fn test_archiver_startup_leader_hang() {
|
||||
leader_info,
|
||||
archiver_keypair,
|
||||
storage_keypair,
|
||||
CommitmentConfig::recent(),
|
||||
);
|
||||
|
||||
assert!(archiver_res.is_err());
|
||||
@ -134,6 +142,7 @@ fn test_archiver_startup_ledger_hang() {
|
||||
cluster.entry_point_info.clone(),
|
||||
bad_keys,
|
||||
storage_keypair,
|
||||
CommitmentConfig::recent(),
|
||||
);
|
||||
|
||||
assert!(archiver_res.is_err());
|
||||
@ -168,7 +177,10 @@ fn test_account_setup() {
|
||||
cluster.archiver_infos.iter().for_each(|(_, value)| {
|
||||
assert_eq!(
|
||||
client
|
||||
.poll_get_balance(&value.archiver_storage_pubkey)
|
||||
.poll_get_balance_with_commitment(
|
||||
&value.archiver_storage_pubkey,
|
||||
CommitmentConfig::recent()
|
||||
)
|
||||
.unwrap(),
|
||||
1
|
||||
);
|
||||
|
@ -15,14 +15,15 @@ use solana_runtime::accounts_db::AccountsDB;
|
||||
use solana_sdk::{
|
||||
client::SyncClient,
|
||||
clock,
|
||||
commitment_config::CommitmentConfig,
|
||||
epoch_schedule::{EpochSchedule, MINIMUM_SLOTS_PER_EPOCH},
|
||||
genesis_block::OperatingMode,
|
||||
poh_config::PohConfig,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
@ -329,7 +330,12 @@ fn test_softlaunch_operating_mode() {
|
||||
.iter()
|
||||
{
|
||||
assert_eq!(
|
||||
(program_id, client.get_account(program_id).unwrap()),
|
||||
(
|
||||
program_id,
|
||||
client
|
||||
.get_account_with_commitment(program_id, CommitmentConfig::recent())
|
||||
.unwrap()
|
||||
),
|
||||
(program_id, None)
|
||||
);
|
||||
}
|
||||
@ -460,7 +466,7 @@ fn test_snapshots_blocktree_floor() {
|
||||
let target_slot = slot_floor + 40;
|
||||
while current_slot <= target_slot {
|
||||
trace!("current_slot: {}", current_slot);
|
||||
if let Ok(slot) = validator_client.get_slot() {
|
||||
if let Ok(slot) = validator_client.get_slot_with_commitment(CommitmentConfig::recent()) {
|
||||
current_slot = slot;
|
||||
} else {
|
||||
continue;
|
||||
@ -751,7 +757,7 @@ fn run_repairman_catchup(num_repairmen: u64) {
|
||||
let target_slot = (num_warmup_epochs) * num_slots_per_epoch + 1;
|
||||
while current_slot <= target_slot {
|
||||
trace!("current_slot: {}", current_slot);
|
||||
if let Ok(slot) = repairee_client.get_slot() {
|
||||
if let Ok(slot) = repairee_client.get_slot_with_commitment(CommitmentConfig::recent()) {
|
||||
current_slot = slot;
|
||||
} else {
|
||||
continue;
|
||||
@ -765,7 +771,9 @@ fn wait_for_next_snapshot<P: AsRef<Path>>(cluster: &LocalCluster, tar: P) {
|
||||
let client = cluster
|
||||
.get_validator_client(&cluster.entry_point_info.id)
|
||||
.unwrap();
|
||||
let last_slot = client.get_slot().expect("Couldn't get slot");
|
||||
let last_slot = client
|
||||
.get_slot_with_commitment(CommitmentConfig::recent())
|
||||
.expect("Couldn't get slot");
|
||||
|
||||
// Wait for a snapshot for a bank >= last_slot to be made so we know that the snapshot
|
||||
// must include the transactions just pushed
|
||||
|
@ -1,22 +1,27 @@
|
||||
use crate::bank::Bank;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::client::{AsyncClient, Client, SyncClient};
|
||||
use solana_sdk::fee_calculator::FeeCalculator;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::instruction::Instruction;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::Signature;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::transaction::{self, Transaction};
|
||||
use solana_sdk::transport::{Result, TransportError};
|
||||
use std::io;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::thread::{sleep, Builder};
|
||||
use std::time::{Duration, Instant};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
client::{AsyncClient, Client, SyncClient},
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
instruction::Instruction,
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil, Signature},
|
||||
system_instruction,
|
||||
transaction::{self, Transaction},
|
||||
transport::{Result, TransportError},
|
||||
};
|
||||
use std::{
|
||||
io,
|
||||
sync::{
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
Arc, Mutex,
|
||||
},
|
||||
thread::{sleep, Builder},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub struct BankClient {
|
||||
bank: Arc<Bank>,
|
||||
@ -100,14 +105,37 @@ impl SyncClient for BankClient {
|
||||
Ok(self.bank.get_account(pubkey))
|
||||
}
|
||||
|
||||
fn get_account_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
_commitment_config: CommitmentConfig,
|
||||
) -> Result<Option<Account>> {
|
||||
Ok(self.bank.get_account(pubkey))
|
||||
}
|
||||
|
||||
fn get_balance(&self, pubkey: &Pubkey) -> Result<u64> {
|
||||
Ok(self.bank.get_balance(pubkey))
|
||||
}
|
||||
|
||||
fn get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
_commitment_config: CommitmentConfig,
|
||||
) -> Result<u64> {
|
||||
Ok(self.bank.get_balance(pubkey))
|
||||
}
|
||||
|
||||
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> {
|
||||
Ok(self.bank.last_blockhash_with_fee_calculator())
|
||||
}
|
||||
|
||||
fn get_recent_blockhash_with_commitment(
|
||||
&self,
|
||||
_commitment_config: CommitmentConfig,
|
||||
) -> Result<(Hash, FeeCalculator)> {
|
||||
Ok(self.bank.last_blockhash_with_fee_calculator())
|
||||
}
|
||||
|
||||
fn get_signature_status(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
@ -115,14 +143,33 @@ impl SyncClient for BankClient {
|
||||
Ok(self.bank.get_signature_status(signature))
|
||||
}
|
||||
|
||||
fn get_signature_status_with_commitment(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
_commitment_config: CommitmentConfig,
|
||||
) -> Result<Option<transaction::Result<()>>> {
|
||||
Ok(self.bank.get_signature_status(signature))
|
||||
}
|
||||
|
||||
fn get_slot(&self) -> Result<u64> {
|
||||
Ok(self.bank.slot())
|
||||
}
|
||||
|
||||
fn get_slot_with_commitment(&self, _commitment_config: CommitmentConfig) -> Result<u64> {
|
||||
Ok(self.bank.slot())
|
||||
}
|
||||
|
||||
fn get_transaction_count(&self) -> Result<u64> {
|
||||
Ok(self.bank.transaction_count())
|
||||
}
|
||||
|
||||
fn get_transaction_count_with_commitment(
|
||||
&self,
|
||||
_commitment_config: CommitmentConfig,
|
||||
) -> Result<u64> {
|
||||
Ok(self.bank.transaction_count())
|
||||
}
|
||||
|
||||
fn poll_for_signature_confirmation(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
|
@ -10,6 +10,7 @@
|
||||
use crate::{
|
||||
account::Account,
|
||||
clock::Slot,
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
instruction::Instruction,
|
||||
@ -44,24 +45,60 @@ pub trait SyncClient {
|
||||
/// Get an account or None if not found.
|
||||
fn get_account(&self, pubkey: &Pubkey) -> Result<Option<Account>>;
|
||||
|
||||
/// Get an account or None if not found. Uses explicit commitment configuration.
|
||||
fn get_account_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<Option<Account>>;
|
||||
|
||||
/// Get account balance or 0 if not found.
|
||||
fn get_balance(&self, pubkey: &Pubkey) -> Result<u64>;
|
||||
|
||||
/// Get account balance or 0 if not found. Uses explicit commitment configuration.
|
||||
fn get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<u64>;
|
||||
|
||||
/// Get recent blockhash
|
||||
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>;
|
||||
|
||||
/// Get recent blockhash. Uses explicit commitment configuration.
|
||||
fn get_recent_blockhash_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<(Hash, FeeCalculator)>;
|
||||
|
||||
/// Get signature status.
|
||||
fn get_signature_status(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
) -> Result<Option<transaction::Result<()>>>;
|
||||
|
||||
/// Get signature status. Uses explicit commitment configuration.
|
||||
fn get_signature_status_with_commitment(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<Option<transaction::Result<()>>>;
|
||||
|
||||
/// Get last known slot
|
||||
fn get_slot(&self) -> Result<Slot>;
|
||||
|
||||
/// Get last known slot. Uses explicit commitment configuration.
|
||||
fn get_slot_with_commitment(&self, commitment_config: CommitmentConfig) -> Result<u64>;
|
||||
|
||||
/// Get transaction count
|
||||
fn get_transaction_count(&self) -> Result<u64>;
|
||||
|
||||
/// Get transaction count. Uses explicit commitment configuration.
|
||||
fn get_transaction_count_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<u64>;
|
||||
|
||||
/// Poll until the signature has been confirmed by at least `min_confirmed_blocks`
|
||||
fn poll_for_signature_confirmation(
|
||||
&self,
|
||||
|
36
sdk/src/commitment_config.rs
Normal file
36
sdk/src/commitment_config.rs
Normal file
@ -0,0 +1,36 @@
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CommitmentConfig {
|
||||
pub commitment: CommitmentLevel,
|
||||
}
|
||||
|
||||
impl Default for CommitmentConfig {
|
||||
fn default() -> Self {
|
||||
CommitmentConfig {
|
||||
commitment: CommitmentLevel::Max,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CommitmentConfig {
|
||||
pub fn recent() -> Self {
|
||||
Self {
|
||||
commitment: CommitmentLevel::Recent,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ok(&self) -> Option<Self> {
|
||||
if self == &Self::default() {
|
||||
None
|
||||
} else {
|
||||
Some(self.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum CommitmentLevel {
|
||||
Max,
|
||||
Recent,
|
||||
}
|
@ -35,6 +35,8 @@ pub mod bank_hash;
|
||||
#[cfg(not(feature = "program"))]
|
||||
pub mod client;
|
||||
#[cfg(not(feature = "program"))]
|
||||
pub mod commitment_config;
|
||||
#[cfg(not(feature = "program"))]
|
||||
pub mod genesis_block;
|
||||
#[cfg(not(feature = "program"))]
|
||||
pub mod packet;
|
||||
|
Loading…
x
Reference in New Issue
Block a user