11#[ macro_use]
22extern crate lazy_static;
3- use bincode:: deserialize;
4- use clap:: {
5- crate_description, crate_name, crate_version, value_t, value_t_or_exit, App , AppSettings , Arg ,
6- ArgGroup , SubCommand ,
7- } ;
8- use solana_account_decoder:: UiAccountEncoding ;
9- use solana_clap_utils:: {
10- input_parsers:: pubkey_of,
11- input_validators:: { is_amount, is_keypair, is_parsable, is_pubkey, is_url} ,
12- keypair:: signer_from_path,
13- } ;
14- use solana_client:: {
15- rpc_client:: RpcClient ,
16- rpc_config:: RpcAccountInfoConfig ,
17- rpc_config:: RpcProgramAccountsConfig ,
18- rpc_filter:: { Memcmp , MemcmpEncodedBytes , RpcFilterType } ,
19- } ;
20- use solana_program:: { instruction:: Instruction , program_pack:: Pack , pubkey:: Pubkey } ;
21- use solana_sdk:: {
22- account:: Account ,
23- commitment_config:: CommitmentConfig ,
24- native_token:: { self , Sol } ,
25- signature:: { Keypair , Signer } ,
26- system_instruction,
27- transaction:: Transaction ,
28- } ;
29- use spl_stake_pool:: {
30- instruction:: {
31- add_validator_stake_account, create_validator_stake_account, deposit,
32- initialize as initialize_pool, remove_validator_stake_account, set_owner,
33- update_list_balance, update_pool_balance, withdraw, Fee as PoolFee ,
34- InitArgs as PoolInitArgs ,
3+
4+ use {
5+ bincode:: deserialize,
6+ borsh:: BorshDeserialize ,
7+ clap:: {
8+ crate_description, crate_name, crate_version, value_t, value_t_or_exit, App , AppSettings ,
9+ Arg , ArgGroup , SubCommand ,
3510 } ,
36- processor:: Processor as PoolProcessor ,
37- stake:: authorize as authorize_stake,
38- stake:: id as stake_program_id,
39- stake:: StakeAuthorize ,
40- stake:: StakeState ,
41- state:: StakePool ,
42- state:: ValidatorStakeList ,
43- } ;
44- use spl_token:: {
45- self , instruction:: approve as approve_token, instruction:: initialize_account,
46- instruction:: initialize_mint, native_mint, state:: Account as TokenAccount ,
47- state:: Mint as TokenMint ,
11+ solana_account_decoder:: UiAccountEncoding ,
12+ solana_clap_utils:: {
13+ input_parsers:: pubkey_of,
14+ input_validators:: { is_amount, is_keypair, is_parsable, is_pubkey, is_url} ,
15+ keypair:: signer_from_path,
16+ } ,
17+ solana_client:: {
18+ rpc_client:: RpcClient ,
19+ rpc_config:: RpcAccountInfoConfig ,
20+ rpc_config:: RpcProgramAccountsConfig ,
21+ rpc_filter:: { Memcmp , MemcmpEncodedBytes , RpcFilterType } ,
22+ } ,
23+ solana_program:: {
24+ borsh:: get_packed_len, instruction:: Instruction , program_pack:: Pack , pubkey:: Pubkey ,
25+ } ,
26+ solana_sdk:: {
27+ account:: Account ,
28+ commitment_config:: CommitmentConfig ,
29+ native_token:: { self , Sol } ,
30+ signature:: { Keypair , Signer } ,
31+ system_instruction,
32+ transaction:: Transaction ,
33+ } ,
34+ spl_stake_pool:: {
35+ borsh:: { get_instance_packed_len, try_from_slice_unchecked} ,
36+ instruction:: {
37+ add_validator_stake_account, create_validator_stake_account, deposit,
38+ initialize as initialize_pool, remove_validator_stake_account, set_owner,
39+ update_list_balance, update_pool_balance, withdraw, Fee as PoolFee ,
40+ } ,
41+ processor:: Processor as PoolProcessor ,
42+ stake:: authorize as authorize_stake,
43+ stake:: id as stake_program_id,
44+ stake:: StakeAuthorize ,
45+ stake:: StakeState ,
46+ state:: StakePool ,
47+ state:: ValidatorStakeList ,
48+ } ,
49+ spl_token:: {
50+ self , instruction:: approve as approve_token, instruction:: initialize_account,
51+ instruction:: initialize_mint, native_mint, state:: Account as TokenAccount ,
52+ state:: Mint as TokenMint ,
53+ } ,
54+ std:: process:: exit,
4855} ;
49- use std:: process:: exit;
5056
5157struct Config {
5258 rpc_client : RpcClient ,
@@ -109,7 +115,7 @@ fn get_authority_accounts(config: &Config, authority: &Pubkey) -> Vec<(Pubkey, A
109115 . unwrap ( )
110116}
111117
112- fn command_create_pool ( config : & Config , fee : PoolFee ) -> CommandResult {
118+ fn command_create_pool ( config : & Config , fee : PoolFee , max_validators : u32 ) -> CommandResult {
113119 let mint_account = Keypair :: new ( ) ;
114120 println ! ( "Creating mint {}" , mint_account. pubkey( ) ) ;
115121
@@ -132,10 +138,12 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
132138 . get_minimum_balance_for_rent_exemption ( TokenAccount :: LEN ) ?;
133139 let pool_account_balance = config
134140 . rpc_client
135- . get_minimum_balance_for_rent_exemption ( StakePool :: LEN ) ?;
141+ . get_minimum_balance_for_rent_exemption ( get_packed_len :: < StakePool > ( ) ) ?;
142+ let empty_validator_list = ValidatorStakeList :: new_with_max_validators ( max_validators) ;
143+ let validator_stake_list_size = get_instance_packed_len ( & empty_validator_list) ?;
136144 let validator_stake_list_balance = config
137145 . rpc_client
138- . get_minimum_balance_for_rent_exemption ( ValidatorStakeList :: LEN ) ?;
146+ . get_minimum_balance_for_rent_exemption ( validator_stake_list_size ) ?;
139147 let total_rent_free_balances = mint_account_balance
140148 + pool_fee_account_balance
141149 + pool_account_balance
@@ -177,15 +185,15 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
177185 & config. fee_payer . pubkey ( ) ,
178186 & pool_account. pubkey ( ) ,
179187 pool_account_balance,
180- StakePool :: LEN as u64 ,
188+ get_packed_len :: < StakePool > ( ) as u64 ,
181189 & spl_stake_pool:: id ( ) ,
182190 ) ,
183191 // Validator stake account list storage
184192 system_instruction:: create_account (
185193 & config. fee_payer . pubkey ( ) ,
186194 & validator_stake_list. pubkey ( ) ,
187195 validator_stake_list_balance,
188- ValidatorStakeList :: LEN as u64 ,
196+ validator_stake_list_size as u64 ,
189197 & spl_stake_pool:: id ( ) ,
190198 ) ,
191199 // Initialize pool token mint account
@@ -212,7 +220,8 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
212220 & mint_account. pubkey ( ) ,
213221 & pool_fee_account. pubkey ( ) ,
214222 & spl_token:: id ( ) ,
215- PoolInitArgs { fee } ,
223+ fee,
224+ max_validators,
216225 ) ?,
217226 ] ,
218227 Some ( & config. fee_payer . pubkey ( ) ) ,
@@ -274,7 +283,7 @@ fn command_vsa_add(
274283) -> CommandResult {
275284 // Get stake pool state
276285 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
277- let pool_data: StakePool = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
286+ let pool_data = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
278287
279288 let mut total_rent_free_balances: u64 = 0 ;
280289
@@ -365,7 +374,7 @@ fn command_vsa_remove(
365374) -> CommandResult {
366375 // Get stake pool state
367376 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
368- let pool_data: StakePool = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
377+ let pool_data: StakePool = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
369378
370379 let pool_withdraw_authority: Pubkey = PoolProcessor :: authority_id (
371380 & spl_stake_pool:: id ( ) ,
@@ -495,7 +504,7 @@ fn command_deposit(
495504) -> CommandResult {
496505 // Get stake pool state
497506 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
498- let pool_data: StakePool = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
507+ let pool_data: StakePool = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
499508
500509 // Get stake account data
501510 let stake_data = config. rpc_client . get_account_data ( & stake) ?;
@@ -514,7 +523,7 @@ fn command_deposit(
514523 . rpc_client
515524 . get_account_data ( & pool_data. validator_stake_list ) ?;
516525 let validator_stake_list_data =
517- ValidatorStakeList :: deserialize ( & validator_stake_list_data. as_slice ( ) ) ?;
526+ try_from_slice_unchecked :: < ValidatorStakeList > ( & validator_stake_list_data. as_slice ( ) ) ?;
518527 if !validator_stake_list_data. contains ( & validator) {
519528 return Err ( "Stake account for this validator does not exist in the pool." . into ( ) ) ;
520529 }
@@ -617,14 +626,14 @@ fn command_deposit(
617626fn command_list ( config : & Config , pool : & Pubkey ) -> CommandResult {
618627 // Get stake pool state
619628 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
620- let pool_data = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
629+ let pool_data = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
621630
622631 if config. verbose {
623632 let validator_list = config
624633 . rpc_client
625634 . get_account_data ( & pool_data. validator_stake_list ) ?;
626635 let validator_stake_list_data =
627- ValidatorStakeList :: deserialize ( & validator_list. as_slice ( ) ) ?;
636+ try_from_slice_unchecked :: < ValidatorStakeList > ( & validator_list. as_slice ( ) ) ?;
628637 println ! ( "Current validator list" ) ;
629638 for validator in validator_stake_list_data. validators {
630639 println ! (
@@ -669,12 +678,12 @@ fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
669678fn command_update ( config : & Config , pool : & Pubkey ) -> CommandResult {
670679 // Get stake pool state
671680 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
672- let pool_data = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
681+ let pool_data = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
673682 let validator_stake_list_data = config
674683 . rpc_client
675684 . get_account_data ( & pool_data. validator_stake_list ) ?;
676685 let validator_stake_list_data =
677- ValidatorStakeList :: deserialize ( & validator_stake_list_data. as_slice ( ) ) ?;
686+ try_from_slice_unchecked :: < ValidatorStakeList > ( & validator_stake_list_data. as_slice ( ) ) ?;
678687
679688 let epoch_info = config. rpc_client . get_epoch_info ( ) ?;
680689
@@ -815,7 +824,7 @@ fn command_withdraw(
815824) -> CommandResult {
816825 // Get stake pool state
817826 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
818- let pool_data = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
827+ let pool_data = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
819828
820829 let pool_mint_data = config. rpc_client . get_account_data ( & pool_data. pool_mint ) ?;
821830 let pool_mint = TokenMint :: unpack_from_slice ( pool_mint_data. as_slice ( ) ) . unwrap ( ) ;
@@ -954,7 +963,7 @@ fn command_set_owner(
954963 new_fee_receiver : & Option < Pubkey > ,
955964) -> CommandResult {
956965 let pool_data = config. rpc_client . get_account_data ( & pool) ?;
957- let pool_data: StakePool = StakePool :: deserialize ( pool_data. as_slice ( ) ) . unwrap ( ) ;
966+ let pool_data: StakePool = StakePool :: try_from_slice ( pool_data. as_slice ( ) ) . unwrap ( ) ;
958967
959968 // If new accounts are missing in the arguments use the old ones
960969 let new_owner: Pubkey = match new_owner {
@@ -1088,6 +1097,16 @@ fn main() {
10881097 . required ( true )
10891098 . help ( "Fee denominator, fee amount is numerator divided by denominator." ) ,
10901099 )
1100+ . arg (
1101+ Arg :: with_name ( "max_validators" )
1102+ . long ( "max-validators" )
1103+ . short ( "m" )
1104+ . validator ( is_parsable :: < u32 > )
1105+ . value_name ( "NUMBER" )
1106+ . takes_value ( true )
1107+ . required ( true )
1108+ . help ( "Max number of validators included in the stake pool" ) ,
1109+ )
10911110 )
10921111 . subcommand ( SubCommand :: with_name ( "create-validator-stake" ) . about ( "Create a new validator stake account to use with the pool" )
10931112 . arg (
@@ -1344,12 +1363,14 @@ fn main() {
13441363 ( "create-pool" , Some ( arg_matches) ) => {
13451364 let numerator = value_t_or_exit ! ( arg_matches, "fee_numerator" , u64 ) ;
13461365 let denominator = value_t_or_exit ! ( arg_matches, "fee_denominator" , u64 ) ;
1366+ let max_validators = value_t_or_exit ! ( arg_matches, "max_validators" , u32 ) ;
13471367 command_create_pool (
13481368 & config,
13491369 PoolFee {
13501370 denominator,
13511371 numerator,
13521372 } ,
1373+ max_validators,
13531374 )
13541375 }
13551376 ( "create-validator-stake" , Some ( arg_matches) ) => {
0 commit comments