Add ability to clone accounts from an RPC endpoint
This commit is contained in:
parent
c3548f790c
commit
cbb9ac19b9
|
@ -164,8 +164,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normalize_to_url_if_moniker(url_or_moniker: &str) -> String {
|
pub fn normalize_to_url_if_moniker<T: AsRef<str>>(url_or_moniker: T) -> String {
|
||||||
match url_or_moniker {
|
match url_or_moniker.as_ref() {
|
||||||
"m" | "mainnet-beta" => "https://api.mainnet-beta.solana.com",
|
"m" | "mainnet-beta" => "https://api.mainnet-beta.solana.com",
|
||||||
"t" | "testnet" => "https://testnet.solana.com",
|
"t" | "testnet" => "https://testnet.solana.com",
|
||||||
"d" | "devnet" => "https://devnet.solana.com",
|
"d" | "devnet" => "https://devnet.solana.com",
|
||||||
|
|
|
@ -84,6 +84,30 @@ impl TestValidatorGenesis {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_accounts<T>(&mut self, accounts: T) -> &mut Self
|
||||||
|
where
|
||||||
|
T: IntoIterator<Item = (Pubkey, Account)>,
|
||||||
|
{
|
||||||
|
for (address, account) in accounts {
|
||||||
|
self.add_account(address, account);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_accounts<T>(&mut self, addresses: T, rpc_client: &RpcClient) -> &mut Self
|
||||||
|
where
|
||||||
|
T: IntoIterator<Item = Pubkey>,
|
||||||
|
{
|
||||||
|
for address in addresses {
|
||||||
|
info!("Fetching {}...", address);
|
||||||
|
let account = rpc_client.get_account(&address).unwrap_or_else(|err| {
|
||||||
|
panic!("Failed to fetch {}: {}", address, err);
|
||||||
|
});
|
||||||
|
self.add_account(address, account);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Add an account to the test environment with the account data in the provided `filename`
|
/// Add an account to the test environment with the account data in the provided `filename`
|
||||||
pub fn add_account_with_file_data(
|
pub fn add_account_with_file_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
use {
|
use {
|
||||||
clap::{value_t_or_exit, App, Arg},
|
clap::{value_t, value_t_or_exit, App, Arg},
|
||||||
console::style,
|
console::style,
|
||||||
fd_lock::FdLock,
|
fd_lock::FdLock,
|
||||||
indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle},
|
indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle},
|
||||||
solana_clap_utils::{input_parsers::pubkey_of, input_validators::is_pubkey},
|
solana_clap_utils::{
|
||||||
|
input_parsers::{pubkey_of, pubkeys_of},
|
||||||
|
input_validators::{
|
||||||
|
is_pubkey, is_pubkey_or_keypair, is_url_or_moniker, normalize_to_url_if_moniker,
|
||||||
|
},
|
||||||
|
},
|
||||||
solana_client::{client_error, rpc_client::RpcClient, rpc_request},
|
solana_client::{client_error, rpc_client::RpcClient, rpc_request},
|
||||||
solana_core::rpc::JsonRpcConfig,
|
solana_core::rpc::JsonRpcConfig,
|
||||||
solana_faucet::faucet::{run_local_faucet_with_port, FAUCET_PORT},
|
solana_faucet::faucet::{run_local_faucet_with_port, FAUCET_PORT},
|
||||||
|
@ -19,6 +24,7 @@ use {
|
||||||
},
|
},
|
||||||
solana_validator::{start_logger, test_validator::*},
|
solana_validator::{start_logger, test_validator::*},
|
||||||
std::{
|
std::{
|
||||||
|
collections::HashSet,
|
||||||
fs, io,
|
fs, io,
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
@ -70,6 +76,18 @@ fn main() {
|
||||||
arg
|
arg
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("json_rpc_url")
|
||||||
|
.short("u")
|
||||||
|
.long("url")
|
||||||
|
.value_name("URL_OR_MONIKER")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(is_url_or_moniker)
|
||||||
|
.help(
|
||||||
|
"URL for Solana's JSON RPC or moniker (or their first letter): \
|
||||||
|
[mainnet-beta, testnet, devnet, localhost]",
|
||||||
|
),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("mint_address")
|
Arg::with_name("mint_address")
|
||||||
.long("mint")
|
.long("mint")
|
||||||
|
@ -78,7 +96,8 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help(
|
.help(
|
||||||
"Address of the mint account that will receive tokens \
|
"Address of the mint account that will receive tokens \
|
||||||
created at genesis [default: client keypair]",
|
created at genesis. If the ledger already exists then \
|
||||||
|
this parameter is silently ignored [default: client keypair]",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -132,7 +151,25 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.number_of_values(2)
|
.number_of_values(2)
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.help("Add a BPF program to the genesis configuration"),
|
.help(
|
||||||
|
"Add a BPF program to the genesis configuration. \
|
||||||
|
If the ledger already exists then this parameter is silently ignored",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("clone_account")
|
||||||
|
.long("clone")
|
||||||
|
.short("c")
|
||||||
|
.value_name("ADDRESS")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
|
.multiple(true)
|
||||||
|
.requires("json_rpc_url")
|
||||||
|
.help(
|
||||||
|
"Copy an account from the cluster referenced by the --url argument the \
|
||||||
|
genesis configuration. \
|
||||||
|
If the ledger already exists then this parameter is silently ignored",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
|
@ -142,6 +179,8 @@ fn main() {
|
||||||
solana_cli_config::Config::default()
|
solana_cli_config::Config::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let json_rpc_url = value_t!(matches, "json_rpc_url", String).map(normalize_to_url_if_moniker);
|
||||||
|
|
||||||
let mint_address = pubkey_of(&matches, "mint_address").unwrap_or_else(|| {
|
let mint_address = pubkey_of(&matches, "mint_address").unwrap_or_else(|| {
|
||||||
read_keypair_file(&cli_config.keypair_path)
|
read_keypair_file(&cli_config.keypair_path)
|
||||||
.unwrap_or_else(|_| Keypair::new())
|
.unwrap_or_else(|_| Keypair::new())
|
||||||
|
@ -194,6 +233,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let clone_accounts: HashSet<_> = pubkeys_of(&matches, "clone_account")
|
||||||
|
.map(|v| v.into_iter().collect())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
if !ledger_path.exists() {
|
if !ledger_path.exists() {
|
||||||
fs::create_dir(&ledger_path).unwrap_or_else(|err| {
|
fs::create_dir(&ledger_path).unwrap_or_else(|err| {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
@ -285,7 +328,8 @@ fn main() {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
TestValidatorGenesis::default()
|
let mut genesis = TestValidatorGenesis::default();
|
||||||
|
genesis
|
||||||
.ledger_path(&ledger_path)
|
.ledger_path(&ledger_path)
|
||||||
.add_account(
|
.add_account(
|
||||||
faucet_keypair.pubkey(),
|
faucet_keypair.pubkey(),
|
||||||
|
@ -298,8 +342,13 @@ fn main() {
|
||||||
..JsonRpcConfig::default()
|
..JsonRpcConfig::default()
|
||||||
})
|
})
|
||||||
.rpc_port(rpc_port)
|
.rpc_port(rpc_port)
|
||||||
.add_programs_with_path(&programs)
|
.add_programs_with_path(&programs);
|
||||||
.start_with_mint_address(mint_address)
|
|
||||||
|
if !clone_accounts.is_empty() {
|
||||||
|
let rpc_client = RpcClient::new(json_rpc_url.unwrap());
|
||||||
|
genesis.clone_accounts(clone_accounts, &rpc_client);
|
||||||
|
}
|
||||||
|
genesis.start_with_mint_address(mint_address)
|
||||||
}
|
}
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
eprintln!("Error: failed to start validator: {}", err);
|
eprintln!("Error: failed to start validator: {}", err);
|
||||||
|
|
Loading…
Reference in New Issue