Cli refactor: vote and storage program functionalities (#6242)
automerge
This commit is contained in:
parent
7f53737000
commit
0c3ff6b75c
|
@ -6,6 +6,7 @@ pub mod display;
|
|||
pub mod input_parsers;
|
||||
pub mod input_validators;
|
||||
pub mod stake;
|
||||
pub mod storage;
|
||||
pub mod validator_info;
|
||||
pub mod vote;
|
||||
pub mod wallet;
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
use crate::{
|
||||
input_parsers::*,
|
||||
input_validators::*,
|
||||
wallet::{
|
||||
check_account_for_fee, check_unique_pubkeys, log_instruction_custom_error, ProcessResult,
|
||||
WalletCommand, WalletConfig, WalletError,
|
||||
},
|
||||
};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_sdk::{
|
||||
account_utils::State, message::Message, pubkey::Pubkey, signature::KeypairUtil,
|
||||
system_instruction::SystemError, transaction::Transaction,
|
||||
};
|
||||
use solana_storage_api::storage_instruction::{self, StorageAccountType};
|
||||
|
||||
pub trait StorageSubCommands {
|
||||
fn storage_subcommands(self) -> Self;
|
||||
}
|
||||
|
||||
impl StorageSubCommands for App<'_, '_> {
|
||||
fn storage_subcommands(self) -> Self {
|
||||
self.subcommand(
|
||||
SubCommand::with_name("create-replicator-storage-account")
|
||||
.about("Create a replicator storage account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_owner")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT OWNER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("create-validator-storage-account")
|
||||
.about("Create a validator storage account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_owner")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT OWNER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("claim-storage-reward")
|
||||
.about("Redeem storage reward credits")
|
||||
.arg(
|
||||
Arg::with_name("node_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("NODE PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("The node account to credit the rewards to"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Storage account address to redeem credits for"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-storage-account")
|
||||
.about("Show the contents of a storage account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Storage account pubkey"),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_storage_create_replicator_account(
|
||||
matches: &ArgMatches<'_>,
|
||||
) -> Result<WalletCommand, WalletError> {
|
||||
let account_owner = pubkey_of(matches, "storage_account_owner").unwrap();
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::CreateStorageAccount {
|
||||
account_owner,
|
||||
storage_account_pubkey,
|
||||
account_type: StorageAccountType::Replicator,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_storage_create_validator_account(
|
||||
matches: &ArgMatches<'_>,
|
||||
) -> Result<WalletCommand, WalletError> {
|
||||
let account_owner = pubkey_of(matches, "storage_account_owner").unwrap();
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::CreateStorageAccount {
|
||||
account_owner,
|
||||
storage_account_pubkey,
|
||||
account_type: StorageAccountType::Validator,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_storage_claim_reward(matches: &ArgMatches<'_>) -> Result<WalletCommand, WalletError> {
|
||||
let node_account_pubkey = pubkey_of(matches, "node_account_pubkey").unwrap();
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::ClaimStorageReward {
|
||||
node_account_pubkey,
|
||||
storage_account_pubkey,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_storage_get_account_command(
|
||||
matches: &ArgMatches<'_>,
|
||||
) -> Result<WalletCommand, WalletError> {
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::ShowStorageAccount(storage_account_pubkey))
|
||||
}
|
||||
|
||||
pub fn process_create_storage_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
account_owner: &Pubkey,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
account_type: StorageAccountType,
|
||||
) -> ProcessResult {
|
||||
check_unique_pubkeys(
|
||||
(&config.keypair.pubkey(), "wallet keypair".to_string()),
|
||||
(
|
||||
&storage_account_pubkey,
|
||||
"storage_account_pubkey".to_string(),
|
||||
),
|
||||
)?;
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
let ixs = storage_instruction::create_storage_account(
|
||||
&config.keypair.pubkey(),
|
||||
&account_owner,
|
||||
storage_account_pubkey,
|
||||
1,
|
||||
account_type,
|
||||
);
|
||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
|
||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
}
|
||||
|
||||
pub fn process_claim_storage_reward(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
node_account_pubkey: &Pubkey,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
|
||||
let instruction =
|
||||
storage_instruction::claim_reward(node_account_pubkey, storage_account_pubkey);
|
||||
let signers = [&config.keypair];
|
||||
let message = Message::new_with_payer(vec![instruction], Some(&signers[0].pubkey()));
|
||||
|
||||
let mut tx = Transaction::new(&signers, message, recent_blockhash);
|
||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &signers)?;
|
||||
Ok(signature_str.to_string())
|
||||
}
|
||||
|
||||
pub fn process_show_storage_account(
|
||||
rpc_client: &RpcClient,
|
||||
_config: &WalletConfig,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
let account = rpc_client.get_account(storage_account_pubkey)?;
|
||||
|
||||
if account.owner != solana_storage_api::id() {
|
||||
return Err(WalletError::RpcRequestError(
|
||||
format!("{:?} is not a storage account", storage_account_pubkey).to_string(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
use solana_storage_api::storage_contract::StorageContract;
|
||||
let storage_contract: StorageContract = account.state().map_err(|err| {
|
||||
WalletError::RpcRequestError(
|
||||
format!("Unable to deserialize storage account: {:?}", err).to_string(),
|
||||
)
|
||||
})?;
|
||||
println!("{:#?}", storage_contract);
|
||||
println!("account lamports: {}", account.lamports);
|
||||
Ok("".to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::wallet::{app, parse_command};
|
||||
|
||||
#[test]
|
||||
fn test_parse_command() {
|
||||
let test_commands = app("test", "desc", "version");
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey_string = pubkey.to_string();
|
||||
let storage_account_pubkey = Pubkey::new_rand();
|
||||
let storage_account_string = storage_account_pubkey.to_string();
|
||||
|
||||
let test_create_replicator_storage_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"create-replicator-storage-account",
|
||||
&pubkey_string,
|
||||
&storage_account_string,
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(&pubkey, &test_create_replicator_storage_account).unwrap(),
|
||||
WalletCommand::CreateStorageAccount {
|
||||
account_owner: pubkey,
|
||||
storage_account_pubkey,
|
||||
account_type: StorageAccountType::Replicator,
|
||||
}
|
||||
);
|
||||
|
||||
let test_create_validator_storage_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"create-validator-storage-account",
|
||||
&pubkey_string,
|
||||
&storage_account_string,
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(&pubkey, &test_create_validator_storage_account).unwrap(),
|
||||
WalletCommand::CreateStorageAccount {
|
||||
account_owner: pubkey,
|
||||
storage_account_pubkey,
|
||||
account_type: StorageAccountType::Validator,
|
||||
}
|
||||
);
|
||||
|
||||
let test_claim_storage_reward = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"claim-storage-reward",
|
||||
&pubkey_string,
|
||||
&storage_account_string,
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(&pubkey, &test_claim_storage_reward).unwrap(),
|
||||
WalletCommand::ClaimStorageReward {
|
||||
node_account_pubkey: pubkey,
|
||||
storage_account_pubkey,
|
||||
}
|
||||
);
|
||||
}
|
||||
// TODO: Add process tests
|
||||
}
|
175
cli/src/vote.rs
175
cli/src/vote.rs
|
@ -1,11 +1,12 @@
|
|||
use crate::{
|
||||
input_parsers::*,
|
||||
input_validators::*,
|
||||
wallet::{
|
||||
build_balance_message, check_account_for_fee, check_unique_pubkeys,
|
||||
log_instruction_custom_error, ProcessResult, WalletCommand, WalletConfig, WalletError,
|
||||
},
|
||||
};
|
||||
use clap::{value_t_or_exit, ArgMatches};
|
||||
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_sdk::{
|
||||
pubkey::Pubkey, signature::KeypairUtil, system_instruction::SystemError,
|
||||
|
@ -16,6 +17,148 @@ use solana_vote_api::{
|
|||
vote_state::{VoteAuthorize, VoteInit, VoteState},
|
||||
};
|
||||
|
||||
pub trait VoteSubCommands {
|
||||
fn vote_subcommands(self) -> Self;
|
||||
}
|
||||
|
||||
impl VoteSubCommands for App<'_, '_> {
|
||||
fn vote_subcommands(self) -> Self {
|
||||
self.subcommand(
|
||||
SubCommand::with_name("create-vote-account")
|
||||
.about("Create a vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account address to fund"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("node_pubkey")
|
||||
.index(2)
|
||||
.value_name("VALIDATOR PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Validator that will vote with this account"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("commission")
|
||||
.long("commission")
|
||||
.value_name("NUM")
|
||||
.takes_value(true)
|
||||
.help("The commission taken on reward redemption (0-255), default: 0"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_voter")
|
||||
.long("authorized-voter")
|
||||
.value_name("PUBKEY")
|
||||
.takes_value(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Public key of the authorized voter (defaults to vote account)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_withdrawer")
|
||||
.long("authorized-withdrawer")
|
||||
.value_name("PUBKEY")
|
||||
.takes_value(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Public key of the authorized withdrawer (defaults to wallet)"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("vote-authorize-voter")
|
||||
.about("Authorize a new vote signing keypair for the given vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account in which to set the authorized voter"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("new_authorized_pubkey")
|
||||
.index(2)
|
||||
.value_name("NEW VOTER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("New vote signer to authorize"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("vote-authorize-withdrawer")
|
||||
.about("Authorize a new withdraw signing keypair for the given vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account in which to set the authorized withdrawer"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("new_authorized_pubkey")
|
||||
.index(2)
|
||||
.value_name("NEW WITHDRAWER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("New withdrawer to authorize"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-vote-account")
|
||||
.about("Show the contents of a vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account pubkey"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("lamports")
|
||||
.long("lamports")
|
||||
.takes_value(false)
|
||||
.help("Display balance in lamports instead of SOL"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("uptime")
|
||||
.about("Show the uptime of a validator, based on epoch voting history")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account pubkey"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("span")
|
||||
.long("span")
|
||||
.value_name("NUM OF EPOCHS")
|
||||
.takes_value(true)
|
||||
.help("Number of recent epochs to examine"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("aggregate")
|
||||
.long("aggregate")
|
||||
.help("Aggregate uptime data across span"),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_vote_create_account(
|
||||
pubkey: &Pubkey,
|
||||
matches: &ArgMatches<'_>,
|
||||
|
@ -62,6 +205,21 @@ pub fn parse_vote_get_account_command(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn parse_vote_uptime_command(matches: &ArgMatches<'_>) -> Result<WalletCommand, WalletError> {
|
||||
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
||||
let aggregate = matches.is_present("aggregate");
|
||||
let span = if matches.is_present("span") {
|
||||
Some(value_t_or_exit!(matches, "span", u64))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(WalletCommand::Uptime {
|
||||
pubkey: vote_account_pubkey,
|
||||
aggregate,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_create_vote_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
|
@ -121,21 +279,6 @@ pub fn process_vote_authorize(
|
|||
log_instruction_custom_error::<VoteError>(result)
|
||||
}
|
||||
|
||||
pub fn parse_vote_uptime_command(matches: &ArgMatches<'_>) -> Result<WalletCommand, WalletError> {
|
||||
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
||||
let aggregate = matches.is_present("aggregate");
|
||||
let span = if matches.is_present("span") {
|
||||
Some(value_t_or_exit!(matches, "span", u64))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(WalletCommand::Uptime {
|
||||
pubkey: vote_account_pubkey,
|
||||
aggregate,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_show_vote_account(
|
||||
rpc_client: &RpcClient,
|
||||
_config: &WalletConfig,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
display::println_name_value, input_parsers::*, input_validators::*, stake::*,
|
||||
display::println_name_value, input_parsers::*, input_validators::*, stake::*, storage::*,
|
||||
validator_info::*, vote::*,
|
||||
};
|
||||
use chrono::prelude::*;
|
||||
|
@ -15,7 +15,6 @@ use solana_drone::drone::request_airdrop_transaction;
|
|||
#[cfg(test)]
|
||||
use solana_drone::drone_mock::request_airdrop_transaction;
|
||||
use solana_sdk::{
|
||||
account_utils::State,
|
||||
bpf_loader, clock,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
|
@ -31,7 +30,7 @@ use solana_sdk::{
|
|||
transaction::{Transaction, TransactionError},
|
||||
};
|
||||
use solana_stake_api::stake_state::{Authorized, Lockup, StakeAuthorize};
|
||||
use solana_storage_api::storage_instruction;
|
||||
use solana_storage_api::storage_instruction::StorageAccountType;
|
||||
use solana_vote_api::vote_state::{VoteAuthorize, VoteInit};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
|
@ -51,21 +50,46 @@ static CROSS_MARK: Emoji = Emoji("❌ ", "");
|
|||
#[derive(Debug, PartialEq)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum WalletCommand {
|
||||
Address,
|
||||
// Cluster Info Commands
|
||||
Fees,
|
||||
Airdrop {
|
||||
drone_host: Option<IpAddr>,
|
||||
drone_port: u16,
|
||||
lamports: u64,
|
||||
use_lamports_unit: bool,
|
||||
GetGenesisBlockhash,
|
||||
GetSlot,
|
||||
GetEpochInfo,
|
||||
GetTransactionCount,
|
||||
GetVersion,
|
||||
Ping {
|
||||
interval: Duration,
|
||||
count: Option<u64>,
|
||||
timeout: Duration,
|
||||
},
|
||||
Balance {
|
||||
// Program Deployment
|
||||
Deploy(String),
|
||||
// Stake Commands
|
||||
CreateStakeAccount(Pubkey, Authorized, Lockup, u64),
|
||||
DelegateStake(Pubkey, Pubkey, bool),
|
||||
DeactivateStake(Pubkey, Pubkey),
|
||||
RedeemVoteCredits(Pubkey, Pubkey),
|
||||
ShowStakeAccount {
|
||||
pubkey: Pubkey,
|
||||
use_lamports_unit: bool,
|
||||
},
|
||||
Cancel(Pubkey),
|
||||
Confirm(Signature),
|
||||
VoteAuthorize(Pubkey, Pubkey, VoteAuthorize),
|
||||
StakeAuthorize(Pubkey, Pubkey, StakeAuthorize),
|
||||
WithdrawStake(Pubkey, Pubkey, u64),
|
||||
// Storage Commands
|
||||
CreateStorageAccount {
|
||||
account_owner: Pubkey,
|
||||
storage_account_pubkey: Pubkey,
|
||||
account_type: StorageAccountType,
|
||||
},
|
||||
ClaimStorageReward {
|
||||
node_account_pubkey: Pubkey,
|
||||
storage_account_pubkey: Pubkey,
|
||||
},
|
||||
ShowStorageAccount(Pubkey),
|
||||
// Validator Info Commands
|
||||
GetValidatorInfo(Option<Pubkey>),
|
||||
SetValidatorInfo(ValidatorInfo, Option<Pubkey>),
|
||||
// Vote Commands
|
||||
CreateVoteAccount(Pubkey, VoteInit),
|
||||
ShowAccount {
|
||||
pubkey: Pubkey,
|
||||
|
@ -81,26 +105,21 @@ pub enum WalletCommand {
|
|||
aggregate: bool,
|
||||
span: Option<u64>,
|
||||
},
|
||||
CreateStakeAccount(Pubkey, Authorized, Lockup, u64),
|
||||
StakeAuthorize(Pubkey, Pubkey, StakeAuthorize),
|
||||
DelegateStake(Pubkey, Pubkey, bool),
|
||||
WithdrawStake(Pubkey, Pubkey, u64),
|
||||
DeactivateStake(Pubkey, Pubkey),
|
||||
RedeemVoteCredits(Pubkey, Pubkey),
|
||||
ShowStakeAccount {
|
||||
VoteAuthorize(Pubkey, Pubkey, VoteAuthorize),
|
||||
// Wallet Commands
|
||||
Address,
|
||||
Airdrop {
|
||||
drone_host: Option<IpAddr>,
|
||||
drone_port: u16,
|
||||
lamports: u64,
|
||||
use_lamports_unit: bool,
|
||||
},
|
||||
Balance {
|
||||
pubkey: Pubkey,
|
||||
use_lamports_unit: bool,
|
||||
},
|
||||
CreateReplicatorStorageAccount(Pubkey, Pubkey),
|
||||
CreateValidatorStorageAccount(Pubkey, Pubkey),
|
||||
ClaimStorageReward(Pubkey, Pubkey),
|
||||
ShowStorageAccount(Pubkey),
|
||||
Deploy(String),
|
||||
GetGenesisBlockhash,
|
||||
GetSlot,
|
||||
GetEpochInfo,
|
||||
GetTransactionCount,
|
||||
GetVersion,
|
||||
Cancel(Pubkey),
|
||||
Confirm(Signature),
|
||||
Pay {
|
||||
lamports: u64,
|
||||
to: Pubkey,
|
||||
|
@ -109,15 +128,8 @@ pub enum WalletCommand {
|
|||
witnesses: Option<Vec<Pubkey>>,
|
||||
cancelable: Option<Pubkey>,
|
||||
},
|
||||
Ping {
|
||||
interval: Duration,
|
||||
count: Option<u64>,
|
||||
timeout: Duration,
|
||||
},
|
||||
TimeElapsed(Pubkey, Pubkey, DateTime<Utc>), // TimeElapsed(to, process_id, timestamp)
|
||||
Witness(Pubkey, Pubkey), // Witness(to, process_id)
|
||||
GetValidatorInfo(Option<Pubkey>),
|
||||
SetValidatorInfo(ValidatorInfo, Option<Pubkey>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -265,33 +277,13 @@ pub fn parse_command(
|
|||
("redeem-vote-credits", Some(matches)) => parse_redeem_vote_credits(matches),
|
||||
("show-stake-account", Some(matches)) => parse_show_stake_account(matches),
|
||||
("create-replicator-storage-account", Some(matches)) => {
|
||||
let account_owner = pubkey_of(matches, "storage_account_owner").unwrap();
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::CreateReplicatorStorageAccount(
|
||||
account_owner,
|
||||
storage_account_pubkey,
|
||||
))
|
||||
parse_storage_create_replicator_account(matches)
|
||||
}
|
||||
("create-validator-storage-account", Some(matches)) => {
|
||||
let account_owner = pubkey_of(matches, "storage_account_owner").unwrap();
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::CreateValidatorStorageAccount(
|
||||
account_owner,
|
||||
storage_account_pubkey,
|
||||
))
|
||||
}
|
||||
("claim-storage-reward", Some(matches)) => {
|
||||
let node_account_pubkey = pubkey_of(matches, "node_account_pubkey").unwrap();
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::ClaimStorageReward(
|
||||
node_account_pubkey,
|
||||
storage_account_pubkey,
|
||||
))
|
||||
}
|
||||
("show-storage-account", Some(matches)) => {
|
||||
let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap();
|
||||
Ok(WalletCommand::ShowStorageAccount(storage_account_pubkey))
|
||||
parse_storage_create_validator_account(matches)
|
||||
}
|
||||
("claim-storage-reward", Some(matches)) => parse_storage_claim_reward(matches),
|
||||
("show-storage-account", Some(matches)) => parse_storage_get_account_command(matches),
|
||||
("deploy", Some(deploy_matches)) => Ok(WalletCommand::Deploy(
|
||||
deploy_matches
|
||||
.value_of("program_location")
|
||||
|
@ -543,102 +535,6 @@ fn process_show_account(
|
|||
Ok("".to_string())
|
||||
}
|
||||
|
||||
fn process_create_replicator_storage_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
account_owner: &Pubkey,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
check_unique_pubkeys(
|
||||
(&config.keypair.pubkey(), "wallet keypair".to_string()),
|
||||
(
|
||||
&storage_account_pubkey,
|
||||
"storage_account_pubkey".to_string(),
|
||||
),
|
||||
)?;
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
let ixs = storage_instruction::create_replicator_storage_account(
|
||||
&config.keypair.pubkey(),
|
||||
&account_owner,
|
||||
storage_account_pubkey,
|
||||
1,
|
||||
);
|
||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
|
||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
}
|
||||
|
||||
fn process_create_validator_storage_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
account_owner: &Pubkey,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
check_unique_pubkeys(
|
||||
(&config.keypair.pubkey(), "wallet keypair".to_string()),
|
||||
(
|
||||
&storage_account_pubkey,
|
||||
"storage_account_pubkey".to_string(),
|
||||
),
|
||||
)?;
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
let ixs = storage_instruction::create_validator_storage_account(
|
||||
&config.keypair.pubkey(),
|
||||
account_owner,
|
||||
storage_account_pubkey,
|
||||
1,
|
||||
);
|
||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
|
||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
}
|
||||
|
||||
fn process_claim_storage_reward(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
node_account_pubkey: &Pubkey,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
|
||||
let instruction =
|
||||
storage_instruction::claim_reward(node_account_pubkey, storage_account_pubkey);
|
||||
let signers = [&config.keypair];
|
||||
let message = Message::new_with_payer(vec![instruction], Some(&signers[0].pubkey()));
|
||||
|
||||
let mut tx = Transaction::new(&signers, message, recent_blockhash);
|
||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &signers)?;
|
||||
Ok(signature_str.to_string())
|
||||
}
|
||||
|
||||
fn process_show_storage_account(
|
||||
rpc_client: &RpcClient,
|
||||
_config: &WalletConfig,
|
||||
storage_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
let account = rpc_client.get_account(storage_account_pubkey)?;
|
||||
|
||||
if account.owner != solana_storage_api::id() {
|
||||
return Err(WalletError::RpcRequestError(
|
||||
format!("{:?} is not a storage account", storage_account_pubkey).to_string(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
use solana_storage_api::storage_contract::StorageContract;
|
||||
let storage_contract: StorageContract = account.state().map_err(|err| {
|
||||
WalletError::RpcRequestError(
|
||||
format!("Unable to deserialize storage account: {:?}", err).to_string(),
|
||||
)
|
||||
})?;
|
||||
println!("{:#?}", storage_contract);
|
||||
println!("account lamports: {}", account.lamports);
|
||||
Ok("".to_string())
|
||||
}
|
||||
|
||||
fn process_deploy(
|
||||
rpc_client: &RpcClient,
|
||||
config: &WalletConfig,
|
||||
|
@ -1211,33 +1107,27 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult {
|
|||
*use_lamports_unit,
|
||||
),
|
||||
|
||||
WalletCommand::CreateReplicatorStorageAccount(
|
||||
storage_account_owner,
|
||||
WalletCommand::CreateStorageAccount {
|
||||
account_owner,
|
||||
storage_account_pubkey,
|
||||
) => process_create_replicator_storage_account(
|
||||
account_type,
|
||||
} => process_create_storage_account(
|
||||
&rpc_client,
|
||||
config,
|
||||
&storage_account_owner,
|
||||
&account_owner,
|
||||
&storage_account_pubkey,
|
||||
*account_type,
|
||||
),
|
||||
|
||||
WalletCommand::CreateValidatorStorageAccount(account_owner, storage_account_pubkey) => {
|
||||
process_create_validator_storage_account(
|
||||
&rpc_client,
|
||||
config,
|
||||
&account_owner,
|
||||
&storage_account_pubkey,
|
||||
)
|
||||
}
|
||||
|
||||
WalletCommand::ClaimStorageReward(node_account_pubkey, storage_account_pubkey) => {
|
||||
process_claim_storage_reward(
|
||||
&rpc_client,
|
||||
config,
|
||||
node_account_pubkey,
|
||||
&storage_account_pubkey,
|
||||
)
|
||||
}
|
||||
WalletCommand::ClaimStorageReward {
|
||||
node_account_pubkey,
|
||||
storage_account_pubkey,
|
||||
} => process_claim_storage_reward(
|
||||
&rpc_client,
|
||||
config,
|
||||
node_account_pubkey,
|
||||
&storage_account_pubkey,
|
||||
),
|
||||
|
||||
WalletCommand::ShowStorageAccount(storage_account_pubkey) => {
|
||||
process_show_storage_account(&rpc_client, config, &storage_account_pubkey)
|
||||
|
@ -1482,95 +1372,6 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||
.help("The transaction signature to confirm"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("vote-authorize-voter")
|
||||
.about("Authorize a new vote signing keypair for the given vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account in which to set the authorized voter"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("new_authorized_pubkey")
|
||||
.index(2)
|
||||
.value_name("NEW VOTER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("New vote signer to authorize"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("vote-authorize-withdrawer")
|
||||
.about("Authorize a new withdraw signing keypair for the given vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account in which to set the authorized withdrawer"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("new_authorized_pubkey")
|
||||
.index(2)
|
||||
.value_name("NEW WITHDRAWER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("New withdrawer to authorize"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("create-vote-account")
|
||||
.about("Create a vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account address to fund"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("node_pubkey")
|
||||
.index(2)
|
||||
.value_name("VALIDATOR PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Validator that will vote with this account"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("commission")
|
||||
.long("commission")
|
||||
.value_name("NUM")
|
||||
.takes_value(true)
|
||||
.help("The commission taken on reward redemption (0-255), default: 0"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_voter")
|
||||
.long("authorized-voter")
|
||||
.value_name("PUBKEY")
|
||||
.takes_value(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Public key of the authorized voter (defaults to vote account)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_withdrawer")
|
||||
.long("authorized-withdrawer")
|
||||
.value_name("PUBKEY")
|
||||
.takes_value(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Public key of the authorized withdrawer (defaults to wallet)"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-account")
|
||||
.about("Show the contents of an account")
|
||||
|
@ -1598,154 +1399,9 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||
.help("Display balance in lamports instead of SOL"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-vote-account")
|
||||
.about("Show the contents of a vote account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account pubkey"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("lamports")
|
||||
.long("lamports")
|
||||
.takes_value(false)
|
||||
.help("Display balance in lamports instead of SOL"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("uptime")
|
||||
.about("Show the uptime of a validator, based on epoch voting history")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account pubkey"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("span")
|
||||
.long("span")
|
||||
.value_name("NUM OF EPOCHS")
|
||||
.takes_value(true)
|
||||
.help("Number of recent epochs to examine")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("aggregate")
|
||||
.long("aggregate")
|
||||
.help("Aggregate uptime data across span")
|
||||
),
|
||||
)
|
||||
.vote_subcommands()
|
||||
.stake_subcommands()
|
||||
.subcommand(
|
||||
SubCommand::with_name("create-storage-mining-pool-account")
|
||||
.about("Create mining pool account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Storage mining pool account address to fund"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("amount")
|
||||
.index(2)
|
||||
.value_name("AMOUNT")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("The amount to assign to the storage mining pool account (default unit SOL)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("unit")
|
||||
.index(3)
|
||||
.value_name("UNIT")
|
||||
.takes_value(true)
|
||||
.possible_values(&["SOL", "lamports"])
|
||||
.help("Specify unit to use for request"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("create-replicator-storage-account")
|
||||
.about("Create a replicator storage account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_owner")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT OWNER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("create-validator-storage-account")
|
||||
.about("Create a validator storage account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_owner")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT OWNER PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("claim-storage-reward")
|
||||
.about("Redeem storage reward credits")
|
||||
.arg(
|
||||
Arg::with_name("node_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("NODE PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("The node account to credit the rewards to"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Storage account address to redeem credits for"),
|
||||
))
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-storage-account")
|
||||
.about("Show the contents of a storage account")
|
||||
.arg(
|
||||
Arg::with_name("storage_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("STORAGE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Storage account pubkey"),
|
||||
)
|
||||
)
|
||||
.storage_subcommands()
|
||||
.subcommand(
|
||||
SubCommand::with_name("deploy")
|
||||
.about("Deploy a program")
|
||||
|
|
|
@ -35,7 +35,7 @@ use solana_sdk::timing::timestamp;
|
|||
use solana_sdk::transaction::Transaction;
|
||||
use solana_sdk::transport::TransportError;
|
||||
use solana_storage_api::storage_contract::StorageContract;
|
||||
use solana_storage_api::storage_instruction;
|
||||
use solana_storage_api::storage_instruction::{self, StorageAccountType};
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufReader, ErrorKind, Read, Seek, SeekFrom};
|
||||
use std::mem::size_of;
|
||||
|
@ -600,11 +600,12 @@ impl Replicator {
|
|||
}
|
||||
};
|
||||
|
||||
let ix = storage_instruction::create_replicator_storage_account(
|
||||
let ix = storage_instruction::create_storage_account(
|
||||
&keypair.pubkey(),
|
||||
&keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
StorageAccountType::Replicator,
|
||||
);
|
||||
let tx = Transaction::new_signed_instructions(&[keypair], ix, blockhash);
|
||||
let signature = client.async_send_transaction(tx)?;
|
||||
|
|
|
@ -641,6 +641,7 @@ mod tests {
|
|||
use solana_sdk::hash::{Hash, Hasher};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_storage_api::storage_instruction::StorageAccountType;
|
||||
use std::cmp::{max, min};
|
||||
use std::fs::remove_dir_all;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
|
@ -822,11 +823,12 @@ mod tests {
|
|||
|
||||
// create accounts
|
||||
let bank = Arc::new(Bank::new_from_parent(&bank, &keypair.pubkey(), 1));
|
||||
let account_ix = storage_instruction::create_replicator_storage_account(
|
||||
let account_ix = storage_instruction::create_storage_account(
|
||||
&mint_keypair.pubkey(),
|
||||
&Pubkey::new_rand(),
|
||||
&replicator_keypair.pubkey(),
|
||||
1,
|
||||
StorageAccountType::Replicator,
|
||||
);
|
||||
let account_tx = Transaction::new_signed_instructions(
|
||||
&[&mint_keypair],
|
||||
|
|
|
@ -25,7 +25,10 @@ use solana_stake_api::{
|
|||
config as stake_config, stake_instruction,
|
||||
stake_state::{Authorized as StakeAuthorized, StakeState},
|
||||
};
|
||||
use solana_storage_api::{storage_contract, storage_instruction};
|
||||
use solana_storage_api::{
|
||||
storage_contract,
|
||||
storage_instruction::{self, StorageAccountType},
|
||||
};
|
||||
use solana_vote_api::{
|
||||
vote_instruction,
|
||||
vote_state::{VoteInit, VoteState},
|
||||
|
@ -532,22 +535,19 @@ impl LocalCluster {
|
|||
from_keypair: &Arc<Keypair>,
|
||||
replicator: bool,
|
||||
) -> Result<()> {
|
||||
let storage_account_type = if replicator {
|
||||
StorageAccountType::Replicator
|
||||
} else {
|
||||
StorageAccountType::Validator
|
||||
};
|
||||
let message = Message::new_with_payer(
|
||||
if replicator {
|
||||
storage_instruction::create_replicator_storage_account(
|
||||
&from_keypair.pubkey(),
|
||||
&from_keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
)
|
||||
} else {
|
||||
storage_instruction::create_validator_storage_account(
|
||||
&from_keypair.pubkey(),
|
||||
&from_keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
)
|
||||
},
|
||||
storage_instruction::create_storage_account(
|
||||
&from_keypair.pubkey(),
|
||||
&from_keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
storage_account_type,
|
||||
),
|
||||
Some(&from_keypair.pubkey()),
|
||||
);
|
||||
let signer_keys = vec![from_keypair.as_ref()];
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::storage_instruction::StorageAccountType;
|
||||
use log::*;
|
||||
use num_derive::FromPrimitive;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
@ -130,30 +131,27 @@ impl<'a> StorageAccount<'a> {
|
|||
Self { id, account }
|
||||
}
|
||||
|
||||
pub fn initialize_replicator_storage(&mut self, owner: Pubkey) -> Result<(), InstructionError> {
|
||||
pub fn initialize_storage(
|
||||
&mut self,
|
||||
owner: Pubkey,
|
||||
account_type: StorageAccountType,
|
||||
) -> Result<(), InstructionError> {
|
||||
let storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Uninitialized = storage_contract {
|
||||
*storage_contract = StorageContract::ReplicatorStorage {
|
||||
owner,
|
||||
proofs: BTreeMap::new(),
|
||||
validations: BTreeMap::new(),
|
||||
credits: Credits::default(),
|
||||
};
|
||||
self.account.set_state(storage_contract)
|
||||
} else {
|
||||
Err(InstructionError::AccountAlreadyInitialized)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_validator_storage(&mut self, owner: Pubkey) -> Result<(), InstructionError> {
|
||||
let storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Uninitialized = storage_contract {
|
||||
*storage_contract = StorageContract::ValidatorStorage {
|
||||
owner,
|
||||
segment: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: BTreeMap::new(),
|
||||
credits: Credits::default(),
|
||||
*storage_contract = match account_type {
|
||||
StorageAccountType::Replicator => StorageContract::ReplicatorStorage {
|
||||
owner,
|
||||
proofs: BTreeMap::new(),
|
||||
validations: BTreeMap::new(),
|
||||
credits: Credits::default(),
|
||||
},
|
||||
StorageAccountType::Validator => StorageContract::ValidatorStorage {
|
||||
owner,
|
||||
segment: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: BTreeMap::new(),
|
||||
credits: Credits::default(),
|
||||
},
|
||||
};
|
||||
self.account.set_state(storage_contract)
|
||||
} else {
|
||||
|
|
|
@ -8,17 +8,21 @@ use solana_sdk::signature::Signature;
|
|||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::sysvar::{clock, rewards};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
|
||||
pub enum StorageAccountType {
|
||||
Replicator,
|
||||
Validator,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum StorageInstruction {
|
||||
/// Initialize the account as a validator or replicator
|
||||
///
|
||||
/// Expects 1 Account:
|
||||
/// 0 - Account to be initialized
|
||||
InitializeValidatorStorage {
|
||||
owner: Pubkey,
|
||||
},
|
||||
InitializeReplicatorStorage {
|
||||
InitializeStorage {
|
||||
owner: Pubkey,
|
||||
account_type: StorageAccountType,
|
||||
},
|
||||
|
||||
SubmitMiningProof {
|
||||
|
@ -81,11 +85,12 @@ pub fn proof_mask_limit() -> u64 {
|
|||
bytes - ratio
|
||||
}
|
||||
|
||||
pub fn create_validator_storage_account(
|
||||
pub fn create_storage_account(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_owner: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
account_type: StorageAccountType,
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::create_account(
|
||||
|
@ -97,32 +102,9 @@ pub fn create_validator_storage_account(
|
|||
),
|
||||
Instruction::new(
|
||||
id(),
|
||||
&StorageInstruction::InitializeValidatorStorage {
|
||||
owner: *storage_owner,
|
||||
},
|
||||
vec![AccountMeta::new(*storage_pubkey, false)],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn create_replicator_storage_account(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_owner: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::create_account(
|
||||
from_pubkey,
|
||||
storage_pubkey,
|
||||
lamports,
|
||||
STORAGE_ACCOUNT_SPACE,
|
||||
&id(),
|
||||
),
|
||||
Instruction::new(
|
||||
id(),
|
||||
&StorageInstruction::InitializeReplicatorStorage {
|
||||
&StorageInstruction::InitializeStorage {
|
||||
owner: *storage_owner,
|
||||
account_type,
|
||||
},
|
||||
vec![AccountMeta::new(*storage_pubkey, false)],
|
||||
),
|
||||
|
|
|
@ -20,17 +20,14 @@ pub fn process_instruction(
|
|||
let mut storage_account = StorageAccount::new(*me[0].unsigned_key(), &mut me[0].account);
|
||||
|
||||
match bincode::deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
||||
StorageInstruction::InitializeReplicatorStorage { owner } => {
|
||||
StorageInstruction::InitializeStorage {
|
||||
owner,
|
||||
account_type,
|
||||
} => {
|
||||
if !rest.is_empty() {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
storage_account.initialize_replicator_storage(owner)
|
||||
}
|
||||
StorageInstruction::InitializeValidatorStorage { owner } => {
|
||||
if !rest.is_empty() {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
storage_account.initialize_validator_storage(owner)
|
||||
storage_account.initialize_storage(owner, account_type)
|
||||
}
|
||||
StorageInstruction::SubmitMiningProof {
|
||||
sha_state,
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
use assert_matches::assert_matches;
|
||||
use bincode::deserialize;
|
||||
use log::*;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_client::BankClient;
|
||||
use solana_runtime::genesis_utils::{create_genesis_block, GenesisBlockInfo};
|
||||
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
|
||||
use solana_sdk::account_utils::State;
|
||||
use solana_sdk::client::SyncClient;
|
||||
use solana_sdk::clock::{get_segment_from_slot, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::instruction::{Instruction, InstructionError};
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::sysvar::clock::{self, Clock};
|
||||
use solana_sdk::sysvar::rewards::{self, Rewards};
|
||||
use solana_storage_api::id;
|
||||
use solana_storage_api::storage_contract::StorageAccount;
|
||||
use solana_storage_api::storage_contract::{ProofStatus, StorageContract, STORAGE_ACCOUNT_SPACE};
|
||||
use solana_storage_api::storage_instruction;
|
||||
use solana_storage_api::storage_processor::process_instruction;
|
||||
use solana_runtime::{
|
||||
bank::Bank,
|
||||
bank_client::BankClient,
|
||||
genesis_utils::{create_genesis_block, GenesisBlockInfo},
|
||||
};
|
||||
use solana_sdk::{
|
||||
account::{create_keyed_accounts, Account, KeyedAccount},
|
||||
account_utils::State,
|
||||
client::SyncClient,
|
||||
clock::{get_segment_from_slot, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT},
|
||||
hash::{hash, Hash},
|
||||
instruction::{Instruction, InstructionError},
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil, Signature},
|
||||
system_instruction,
|
||||
sysvar::clock::{self, Clock},
|
||||
sysvar::rewards::{self, Rewards},
|
||||
};
|
||||
use solana_storage_api::{
|
||||
id,
|
||||
storage_contract::StorageAccount,
|
||||
storage_contract::{ProofStatus, StorageContract, STORAGE_ACCOUNT_SPACE},
|
||||
storage_instruction::{self, StorageAccountType},
|
||||
storage_processor::process_instruction,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -61,11 +67,12 @@ fn test_account_owner() {
|
|||
let bank = Arc::new(bank);
|
||||
let bank_client = BankClient::new_shared(&bank);
|
||||
|
||||
let message = Message::new(storage_instruction::create_validator_storage_account(
|
||||
let message = Message::new(storage_instruction::create_storage_account(
|
||||
&mint_pubkey,
|
||||
&account_owner,
|
||||
&validator_storage_pubkey,
|
||||
1,
|
||||
StorageAccountType::Validator,
|
||||
));
|
||||
bank_client
|
||||
.send_message(&[&mint_keypair], message)
|
||||
|
@ -80,11 +87,12 @@ fn test_account_owner() {
|
|||
assert!(false, "wrong account type found")
|
||||
}
|
||||
|
||||
let message = Message::new(storage_instruction::create_replicator_storage_account(
|
||||
let message = Message::new(storage_instruction::create_storage_account(
|
||||
&mint_pubkey,
|
||||
&account_owner,
|
||||
&replicator_storage_pubkey,
|
||||
1,
|
||||
StorageAccountType::Replicator,
|
||||
));
|
||||
bank_client
|
||||
.send_message(&[&mint_keypair], message)
|
||||
|
@ -111,7 +119,7 @@ fn test_proof_bounds() {
|
|||
{
|
||||
let mut storage_account = StorageAccount::new(pubkey, &mut account);
|
||||
storage_account
|
||||
.initialize_replicator_storage(account_owner)
|
||||
.initialize_storage(account_owner, StorageAccountType::Replicator)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -224,7 +232,7 @@ fn test_submit_mining_ok() {
|
|||
{
|
||||
let mut storage_account = StorageAccount::new(pubkey, &mut account);
|
||||
storage_account
|
||||
.initialize_replicator_storage(account_owner)
|
||||
.initialize_storage(account_owner, StorageAccountType::Replicator)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -473,11 +481,12 @@ fn init_storage_accounts(
|
|||
&mut validator_accounts_to_create
|
||||
.into_iter()
|
||||
.flat_map(|account| {
|
||||
storage_instruction::create_validator_storage_account(
|
||||
storage_instruction::create_storage_account(
|
||||
&mint.pubkey(),
|
||||
owner,
|
||||
account,
|
||||
lamports,
|
||||
StorageAccountType::Validator,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
|
@ -485,11 +494,12 @@ fn init_storage_accounts(
|
|||
replicator_accounts_to_create
|
||||
.into_iter()
|
||||
.for_each(|account| {
|
||||
ixs.append(&mut storage_instruction::create_replicator_storage_account(
|
||||
ixs.append(&mut storage_instruction::create_storage_account(
|
||||
&mint.pubkey(),
|
||||
owner,
|
||||
account,
|
||||
lamports,
|
||||
StorageAccountType::Replicator,
|
||||
))
|
||||
});
|
||||
let message = Message::new(ixs);
|
||||
|
@ -590,19 +600,21 @@ fn test_bank_storage() {
|
|||
.transfer(10, &mint_keypair, &replicator_pubkey)
|
||||
.unwrap();
|
||||
|
||||
let message = Message::new(storage_instruction::create_replicator_storage_account(
|
||||
let message = Message::new(storage_instruction::create_storage_account(
|
||||
&mint_pubkey,
|
||||
&Pubkey::default(),
|
||||
&replicator_pubkey,
|
||||
1,
|
||||
StorageAccountType::Replicator,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
let message = Message::new(storage_instruction::create_validator_storage_account(
|
||||
let message = Message::new(storage_instruction::create_storage_account(
|
||||
&mint_pubkey,
|
||||
&Pubkey::default(),
|
||||
&validator_pubkey,
|
||||
1,
|
||||
StorageAccountType::Validator,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
|
|
|
@ -86,8 +86,11 @@ pub(crate) mod tests {
|
|||
use solana_sdk::genesis_block::create_genesis_block;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_storage_api::storage_contract::{StorageAccount, STORAGE_ACCOUNT_SPACE};
|
||||
use solana_storage_api::{storage_instruction, storage_processor};
|
||||
use solana_storage_api::{
|
||||
storage_contract::{StorageAccount, STORAGE_ACCOUNT_SPACE},
|
||||
storage_instruction::{self, StorageAccountType},
|
||||
storage_processor,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
|
@ -110,22 +113,24 @@ pub(crate) mod tests {
|
|||
bank_client
|
||||
.transfer(10, &mint_keypair, &replicator_pubkey)
|
||||
.unwrap();
|
||||
let message = Message::new(storage_instruction::create_replicator_storage_account(
|
||||
let message = Message::new(storage_instruction::create_storage_account(
|
||||
&mint_pubkey,
|
||||
&Pubkey::default(),
|
||||
&replicator_pubkey,
|
||||
1,
|
||||
StorageAccountType::Replicator,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
bank_client
|
||||
.transfer(10, &mint_keypair, &validator_pubkey)
|
||||
.unwrap();
|
||||
let message = Message::new(storage_instruction::create_validator_storage_account(
|
||||
let message = Message::new(storage_instruction::create_storage_account(
|
||||
&mint_pubkey,
|
||||
&Pubkey::default(),
|
||||
&validator_pubkey,
|
||||
1,
|
||||
StorageAccountType::Validator,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
|
@ -192,7 +197,7 @@ pub(crate) mod tests {
|
|||
Account::new(1, STORAGE_ACCOUNT_SPACE as usize, &solana_storage_api::id());
|
||||
let mut validator = StorageAccount::new(validator_pubkey, &mut validator_account);
|
||||
validator
|
||||
.initialize_validator_storage(validator_pubkey)
|
||||
.initialize_storage(validator_pubkey, StorageAccountType::Validator)
|
||||
.unwrap();
|
||||
let storage_contract = &mut validator_account.state().unwrap();
|
||||
if let StorageContract::ValidatorStorage {
|
||||
|
@ -208,7 +213,7 @@ pub(crate) mod tests {
|
|||
Account::new(1, STORAGE_ACCOUNT_SPACE as usize, &solana_storage_api::id());
|
||||
let mut replicator = StorageAccount::new(replicator_pubkey, &mut replicator_account);
|
||||
replicator
|
||||
.initialize_replicator_storage(replicator_pubkey)
|
||||
.initialize_storage(replicator_pubkey, StorageAccountType::Replicator)
|
||||
.unwrap();
|
||||
let storage_contract = &mut replicator_account.state().unwrap();
|
||||
if let StorageContract::ReplicatorStorage {
|
||||
|
|
Loading…
Reference in New Issue