1
1
#[ macro_use]
2
2
extern 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 ,
35
10
} ,
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,
48
55
} ;
49
- use std:: process:: exit;
50
56
51
57
struct Config {
52
58
rpc_client : RpcClient ,
@@ -109,7 +115,7 @@ fn get_authority_accounts(config: &Config, authority: &Pubkey) -> Vec<(Pubkey, A
109
115
. unwrap ( )
110
116
}
111
117
112
- fn command_create_pool ( config : & Config , fee : PoolFee ) -> CommandResult {
118
+ fn command_create_pool ( config : & Config , fee : PoolFee , max_validators : u32 ) -> CommandResult {
113
119
let mint_account = Keypair :: new ( ) ;
114
120
println ! ( "Creating mint {}" , mint_account. pubkey( ) ) ;
115
121
@@ -132,10 +138,12 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
132
138
. get_minimum_balance_for_rent_exemption ( TokenAccount :: LEN ) ?;
133
139
let pool_account_balance = config
134
140
. 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) ?;
136
144
let validator_stake_list_balance = config
137
145
. rpc_client
138
- . get_minimum_balance_for_rent_exemption ( ValidatorStakeList :: LEN ) ?;
146
+ . get_minimum_balance_for_rent_exemption ( validator_stake_list_size ) ?;
139
147
let total_rent_free_balances = mint_account_balance
140
148
+ pool_fee_account_balance
141
149
+ pool_account_balance
@@ -177,15 +185,15 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
177
185
& config. fee_payer . pubkey ( ) ,
178
186
& pool_account. pubkey ( ) ,
179
187
pool_account_balance,
180
- StakePool :: LEN as u64 ,
188
+ get_packed_len :: < StakePool > ( ) as u64 ,
181
189
& spl_stake_pool:: id ( ) ,
182
190
) ,
183
191
// Validator stake account list storage
184
192
system_instruction:: create_account (
185
193
& config. fee_payer . pubkey ( ) ,
186
194
& validator_stake_list. pubkey ( ) ,
187
195
validator_stake_list_balance,
188
- ValidatorStakeList :: LEN as u64 ,
196
+ validator_stake_list_size as u64 ,
189
197
& spl_stake_pool:: id ( ) ,
190
198
) ,
191
199
// Initialize pool token mint account
@@ -212,7 +220,8 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
212
220
& mint_account. pubkey ( ) ,
213
221
& pool_fee_account. pubkey ( ) ,
214
222
& spl_token:: id ( ) ,
215
- PoolInitArgs { fee } ,
223
+ fee,
224
+ max_validators,
216
225
) ?,
217
226
] ,
218
227
Some ( & config. fee_payer . pubkey ( ) ) ,
@@ -274,7 +283,7 @@ fn command_vsa_add(
274
283
) -> CommandResult {
275
284
// Get stake pool state
276
285
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 ( ) ;
278
287
279
288
let mut total_rent_free_balances: u64 = 0 ;
280
289
@@ -365,7 +374,7 @@ fn command_vsa_remove(
365
374
) -> CommandResult {
366
375
// Get stake pool state
367
376
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 ( ) ;
369
378
370
379
let pool_withdraw_authority: Pubkey = PoolProcessor :: authority_id (
371
380
& spl_stake_pool:: id ( ) ,
@@ -495,7 +504,7 @@ fn command_deposit(
495
504
) -> CommandResult {
496
505
// Get stake pool state
497
506
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 ( ) ;
499
508
500
509
// Get stake account data
501
510
let stake_data = config. rpc_client . get_account_data ( & stake) ?;
@@ -514,7 +523,7 @@ fn command_deposit(
514
523
. rpc_client
515
524
. get_account_data ( & pool_data. validator_stake_list ) ?;
516
525
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 ( ) ) ?;
518
527
if !validator_stake_list_data. contains ( & validator) {
519
528
return Err ( "Stake account for this validator does not exist in the pool." . into ( ) ) ;
520
529
}
@@ -617,14 +626,14 @@ fn command_deposit(
617
626
fn command_list ( config : & Config , pool : & Pubkey ) -> CommandResult {
618
627
// Get stake pool state
619
628
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 ( ) ;
621
630
622
631
if config. verbose {
623
632
let validator_list = config
624
633
. rpc_client
625
634
. get_account_data ( & pool_data. validator_stake_list ) ?;
626
635
let validator_stake_list_data =
627
- ValidatorStakeList :: deserialize ( & validator_list. as_slice ( ) ) ?;
636
+ try_from_slice_unchecked :: < ValidatorStakeList > ( & validator_list. as_slice ( ) ) ?;
628
637
println ! ( "Current validator list" ) ;
629
638
for validator in validator_stake_list_data. validators {
630
639
println ! (
@@ -669,12 +678,12 @@ fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
669
678
fn command_update ( config : & Config , pool : & Pubkey ) -> CommandResult {
670
679
// Get stake pool state
671
680
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 ( ) ;
673
682
let validator_stake_list_data = config
674
683
. rpc_client
675
684
. get_account_data ( & pool_data. validator_stake_list ) ?;
676
685
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 ( ) ) ?;
678
687
679
688
let epoch_info = config. rpc_client . get_epoch_info ( ) ?;
680
689
@@ -815,7 +824,7 @@ fn command_withdraw(
815
824
) -> CommandResult {
816
825
// Get stake pool state
817
826
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 ( ) ;
819
828
820
829
let pool_mint_data = config. rpc_client . get_account_data ( & pool_data. pool_mint ) ?;
821
830
let pool_mint = TokenMint :: unpack_from_slice ( pool_mint_data. as_slice ( ) ) . unwrap ( ) ;
@@ -954,7 +963,7 @@ fn command_set_owner(
954
963
new_fee_receiver : & Option < Pubkey > ,
955
964
) -> CommandResult {
956
965
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 ( ) ;
958
967
959
968
// If new accounts are missing in the arguments use the old ones
960
969
let new_owner: Pubkey = match new_owner {
@@ -1088,6 +1097,16 @@ fn main() {
1088
1097
. required ( true )
1089
1098
. help ( "Fee denominator, fee amount is numerator divided by denominator." ) ,
1090
1099
)
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
+ )
1091
1110
)
1092
1111
. subcommand ( SubCommand :: with_name ( "create-validator-stake" ) . about ( "Create a new validator stake account to use with the pool" )
1093
1112
. arg (
@@ -1344,12 +1363,14 @@ fn main() {
1344
1363
( "create-pool" , Some ( arg_matches) ) => {
1345
1364
let numerator = value_t_or_exit ! ( arg_matches, "fee_numerator" , u64 ) ;
1346
1365
let denominator = value_t_or_exit ! ( arg_matches, "fee_denominator" , u64 ) ;
1366
+ let max_validators = value_t_or_exit ! ( arg_matches, "max_validators" , u32 ) ;
1347
1367
command_create_pool (
1348
1368
& config,
1349
1369
PoolFee {
1350
1370
denominator,
1351
1371
numerator,
1352
1372
} ,
1373
+ max_validators,
1353
1374
)
1354
1375
}
1355
1376
( "create-validator-stake" , Some ( arg_matches) ) => {
0 commit comments