stake-pool-cli: Add more docs around scripts (#2531)

This commit is contained in:
Jon Cinque 2021-10-20 01:29:00 +02:00 committed by GitHub
parent 203db7bc3f
commit 675d65b965
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 192 additions and 87 deletions

View File

@ -22,6 +22,27 @@ Additional information regarding staking and stake programming is available at:
- https://solana.com/staking
- https://docs.solana.com/staking/stake-programming
## Quick Start
If you're looking to get immediately into creating and running a stake pool,
take a look at the
[reference scripts](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/cli/scripts).
These scripts require the Solana CLI tool suite, which can be downloaded by
following the instructions at (https://docs.solana.com/cli/install-solana-cli-tools).
Additionally, you must have a usable keypair, created at the default location
using `solana-keygen new`.
You'll see the following scripts:
* `setup-local.sh`: sets up a local test validator with validator vote accounts
* `setup-stake-pool.sh`: creates a new stake pool with hardcoded parameters
* `deposit-withdraw.sh`: performs some deposits and withdrawals
The
[CLI README](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/cli)
contains more information about each of these scripts.
## Motivation
This document is intended for the main actors of the stake pool system:
@ -172,7 +193,7 @@ document are available at:
## Source
The Stake Pool Program's source is available on
[github](https://github.com/solana-labs/solana-program-library).
[GitHub](https://github.com/solana-labs/solana-program-library).
For information about the types and instructions, the Stake Pool Rust docs are
available at [docs.rs](https://docs.rs/spl-stake-pool/0.5.0/spl_stake_pool/).
@ -248,7 +269,7 @@ sets the fee on creation. Let's create a pool with a 3% fee and a maximum of 100
validator stake accounts:
```console
$ spl-stake-pool create-pool --fee-numerator 3 --fee-denominator 100 --max-validators 1000
$ spl-stake-pool create-pool --epoch-fee-numerator 3 --epoch-fee-denominator 100 --max-validators 1000
Creating reserve stake DVwDn4LTRztuai4QeenM6fyzgiwUGpVXVNZ1mgKE1Pyc
Creating mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
Creating associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
@ -276,6 +297,31 @@ This account holds onto additional stake used when rebalancing between validator
For a stake pool with 1000 validators, the cost to create a stake pool is less
than 0.5 SOL.
### Create a restricted stake pool
If a manager would like to restrict deposits (stake and SOL) to one key in
particular, they can set a deposit authority at creation:
```console
$ spl-stake-pool create-pool --epoch-fee-numerator 3 --epoch-fee-denominator 100 --max-validators 1000 --deposit-authority authority_keypair.json
Creating reserve stake DVwDn4LTRztuai4QeenM6fyzgiwUGpVXVNZ1mgKE1Pyc
Creating mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
Creating associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
Creating pool fee collection account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ
Signature: qQwqahLuC24wPwVdgVXtd7v5htSSPDAH3JxFNmXCv9aDwjjqygQ64VMg3WdPCiNzc4Bn8vtS3qcnUVHVP5MbKgL
Creating stake pool Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
Deposits will be restricted to 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn only, this can be changed using the set-funding-authority command.
Signature: 5z6uH3EuPcujeWGpAjBtciSUR3TxtMBgWYU4ULagUso4QGzE9JenhYHwYthJ4b3rS57ByUNEXTr2BFyF5PjWC42Y
```
As the output says, the `set-funding-authority` can be used to modify or remove
the deposit authority.
As long as the deposit authority is set, SOL and stake deposits must be signed
by `4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn`, so no one else can participate
in the pool. As mentioned earlier, this feature does not prohibit withdrawals,
so anyone with pool tokens will still be able to withdraw from the pool.
### Set manager
The stake pool manager may pass their administrator privileges to another account.
@ -921,7 +967,7 @@ source the pool tokens. It's possible to specify the SPL token account using
the `--pool-account` flag.
```console
$ spl-stake-pool withdraw Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5 --pool-account 34XMHa3JUPv46ftU4dGHvemZ9oKVjnciRePYMcX3rjEF
$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5 --pool-account 34XMHa3JUPv46ftU4dGHvemZ9oKVjnciRePYMcX3rjEF
Withdrawing ◎5.000000000, or 5 pool tokens, from stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
Creating account to receive stake CZF2z3JJoDmJRcVjtsrz1BKUUGNL3VPW5FPFqge1bzmQ
Signature: 2xBPVPJ749AE4hHNCNYdjuHv1EdMvxm9uvvraWfTA7Urrvecwh9w64URCyLLroLQ2RKDGE2QELM2ZHd8qRkjavJM
@ -932,7 +978,7 @@ accounts in the pool. It's also possible to specify a specific vote account for
the withdraw using the `--vote-account` flag.
```console
$ spl-stake-pool withdraw Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --amount 5 --vote-account EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --amount 5 --vote-account EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
Withdrawing ◎5.000000000, or 5 pool tokens, from stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
Creating account to receive stake CZF2z3JJoDmJRcVjtsrz1BKUUGNL3VPW5FPFqge1bzmQ
Signature: 2xBPVPJ749AE4hHNCNYdjuHv1EdMvxm9uvvraWfTA7Urrvecwh9w64URCyLLroLQ2RKDGE2QELM2ZHd8qRkjavJM
@ -953,7 +999,7 @@ reserve, but only if all of the validator stake accounts are at the minimum amou
`0.001 SOL + stake account rent exemption`.
```console
$ spl-stake-pool withdraw Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5 --use-reserve
$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5 --use-reserve
Withdrawing ◎5.000000000, or 5 pool tokens, from stake account J5XB7mWpeaUZxZ6ogXT57qSCobczx27vLZYSgfSbZoBB
Creating account to receive stake 51XdXiBSsVzeuY79xJwWAGZgeKzzgFKWajkwvWyrRiNE
Signature: yQH9n7Go6iCMEYXqWef38ZYBPwXDmbwKAJFJ4EHD6TusBpusKsfNuT3TV9TL8FmxR2N9ExZTZwbD9Njc3rMvUcf

View File

@ -15,10 +15,11 @@ have a usable keypair, created at the default location using `solana-keygen new`
Builds the stake pool program and sets up a `solana-test-validator` with some
new validator vote accounts.
The only input it accepts is a number, for the number of vote accounts to create, e.g.:
It accepts the number of vote accounts to create and validator list file path to output
vote accounts, e.g.:
```bash
$ ./setup-local.sh 100
$ ./setup-local.sh 100 validator_list.txt
```
#### Important notes on local network
@ -39,13 +40,23 @@ $ solana delegate-stake --force stake.json CzDy6uxLTko5Jjcdm46AozMmrARY6R2aDBagd
Creates a new stake pool with the parameters hardcoded in the script:
* fee numerator
* fee denominator
* epoch fee numerator
* epoch fee denominator
* withdrawal fee numerator
* withdrawal fee denominator
* deposit fee numerator
* deposit fee denominator
* referral fee
* manager
* staker
* maximum number of validators
* list of validator vote accounts
* (Optional) deposit authority, for restricted pools
Modify the parameters to suit your needs, and your pool will be created!
```bash
$ ./setup-stake-pool.sh 100 validator_list.txt
$ ./setup-stake-pool.sh
```
### deposit-withdraw.sh

View File

@ -1,21 +1,12 @@
#!/usr/bin/env bash
# Script to deposit and withdraw stakes from a pool, given stake pool public key
# and a list of validators
# and a path to a file containing a list of validator vote accounts
cd "$(dirname "$0")"
stake_pool_keyfile=$1
validator_list=$2
stake_pool_pubkey=$(solana-keygen pubkey $stake_pool_keyfile)
sol_amount=2
half_sol_amount=1
keys_dir=keys
spl_stake_pool=../../../target/debug/spl-stake-pool
mkdir -p $keys_dir
create_keypair () {
if test ! -f $1
then
@ -26,28 +17,31 @@ create_keypair () {
create_user_stakes () {
validator_list=$1
sol_amount=$2
authority=$3
for validator in $(cat $validator_list)
do
create_keypair $keys_dir/stake_$validator.json
solana create-stake-account $keys_dir/stake_$validator.json $sol_amount
solana create-stake-account $keys_dir/stake_$validator.json $sol_amount --withdraw-authority $authority --stake-authority $authority
done
}
delegate_user_stakes () {
validator_list=$1
authority=$2
for validator in $(cat $validator_list)
do
solana delegate-stake --force $keys_dir/stake_$validator.json $validator
solana delegate-stake --force $keys_dir/stake_$validator.json $validator --stake-authority $authority
done
}
deposit_stakes () {
stake_pool_pubkey=$1
validator_list=$2
authority=$3
for validator in $(cat $validator_list)
do
stake=$(solana-keygen pubkey $keys_dir/stake_$validator.json)
$spl_stake_pool deposit-stake $stake_pool_pubkey $stake
$spl_stake_pool deposit-stake $stake_pool_pubkey $stake --withdraw-authority $authority
done
}
@ -61,16 +55,29 @@ withdraw_stakes () {
done
}
echo "Creating user stake accounts"
create_user_stakes $validator_list $sol_amount
echo "Delegating user stakes"
delegate_user_stakes $validator_list
sol_amount=2
half_sol_amount=1
keys_dir=keys
spl_stake_pool=../../../target/debug/spl-stake-pool
stake_pool_pubkey=$(solana-keygen pubkey $stake_pool_keyfile)
echo "Setting up keys directory $keys_dir"
mkdir -p $keys_dir
authority=$keys_dir/authority.json
echo "Setting up authority for deposited stake accounts at $authority"
create_keypair $authority
echo "Creating user stake accounts to deposit into the pool"
create_user_stakes $validator_list $sol_amount $authority
echo "Delegating user stakes so that deposit will work"
delegate_user_stakes $validator_list $authority
echo "Waiting for stakes to activate, this may take awhile depending on the network!"
echo "If you are running on localnet with 32 slots per epoch, wait 24 seconds..."
sleep 24
echo "If you are running on localnet with 32 slots per epoch, wait 12 seconds..."
sleep 12
echo "Depositing stakes into stake pool"
deposit_stakes $stake_pool_pubkey $validator_list
deposit_stakes $stake_pool_pubkey $validator_list $authority
echo "Withdrawing stakes from stake pool"
withdraw_stakes $stake_pool_pubkey $validator_list $half_sol_amount
echo "Withdrawing sol from stake pool"
$spl_stake_pool withdraw-sol $stake_pool_pubkey $half_sol_amount
echo "Depositing SOL into stake pool to authority"
$spl_stake_pool deposit-sol $stake_pool_pubkey $sol_amount
echo "Withdrawing SOL from stake pool to authority"
$spl_stake_pool withdraw-sol $stake_pool_pubkey $authority $half_sol_amount

View File

@ -1,18 +1,13 @@
#!/usr/bin/env bash
# Script to setup a local solana-test-validator with the stake pool program
# given a maximum number of validators and a file path to store the list of
# test validator vote accounts.
cd "$(dirname "$0")"
max_validators=$1
validator_list=$2
keys_dir=keys
mkdir -p $keys_dir
if test -f $validator_list
then
rm $validator_list
fi
create_keypair () {
if test ! -f $1
then
@ -20,11 +15,11 @@ create_keypair () {
fi
}
build_program () {
build_stake_pool_program () {
cargo build-bpf --manifest-path ../../program/Cargo.toml
}
setup_validator() {
setup_test_validator() {
solana-test-validator --bpf-program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy ../../../target/deploy/spl_stake_pool.so --quiet --reset --slots-per-epoch 32 &
pid=$!
solana config set --url http://127.0.0.1:8899
@ -40,17 +35,27 @@ create_vote_accounts () {
do
create_keypair $keys_dir/identity_$number.json
create_keypair $keys_dir/vote_$number.json
solana create-vote-account $keys_dir/vote_$number.json $keys_dir/identity_$number.json --commission 1
create_keypair $keys_dir/withdrawer_$number.json
solana create-vote-account $keys_dir/vote_$number.json $keys_dir/identity_$number.json $keys_dir/withdrawer_$number.json --commission 1
vote_pubkey=$(solana-keygen pubkey $keys_dir/vote_$number.json)
echo $vote_pubkey >> $validator_list
done
}
echo "Building on-chain program"
build_program
echo "Setting up local validator"
setup_validator
echo "Setup keys directory and clear old validator list file if found"
keys_dir=keys
mkdir -p $keys_dir
if test -f $validator_list
then
rm $validator_list
fi
echo "Creating vote accounts"
echo "Building on-chain stake pool program"
build_stake_pool_program
echo "Setting up local test validator"
setup_test_validator
echo "Creating vote accounts, these accounts be added to the stake pool"
create_vote_accounts $max_validators $validator_list

View File

@ -3,15 +3,50 @@
# Script to setup a stake pool, add new validators from a list
cd "$(dirname "$0")"
max_validators=$1
validator_list=$2
global_args=()
command_args=()
###################################################
### MODIFY PARAMETERS BELOW THIS LINE FOR YOUR POOL
###################################################
global_args+=( --manager keys/new_manager.json ) # Keypair of the manager of the stake pool
global_args+=( --staker keys/new_staker.json ) # Keypair of the staker of the stake pool
# Epoch fee, assessed as a percentage of rewards earned by the pool every epoch,
# represented as `numerator / denominator`
command_args+=( --epoch-fee-numerator 0 )
command_args+=( --epoch-fee-denominator 0 )
# Withdrawal fee for SOL and stake accounts, represented as `numerator / denominator`
command_args+=( --withdrawal-fee-numerator 0 )
command_args+=( --withdrawal-fee-denominator 0 )
# Deposit fee for SOL and stake accounts, represented as `numerator / denominator`
command_args+=( --deposit-fee-numerator 0 )
command_args+=( --deposit-fee-denominator 0 )
command_args+=( --referral-fee 0 ) # Percentage of deposit fee that goes towards the referrer (a number between 0 and 100, inclusive)
command_args+=( --max-validators 3950 ) # Maximum number of validators in the stake pool, 3950 is the current maximum possible
validator_list=validator_list.txt # File containing validator vote account addresses, each will be added to the stake pool after creation
# (Optional) Deposit authority, required to sign all deposits into the pool.
# Setting this variable makes the pool "private" or "restricted".
# Comment it out if you want the pool to be open to all depositors.
command_args+=( --deposit-authority keys/authority.json )
###################################################
### MODIFY PARAMETERS ABOVE THIS LINE FOR YOUR POOL
###################################################
keys_dir=keys
spl_stake_pool=../../../target/debug/spl-stake-pool
mkdir -p $keys_dir
build_cli () {
build_stake_pool_cli () {
cargo build --manifest-path ../Cargo.toml
}
@ -22,37 +57,34 @@ create_keypair () {
fi
}
setup_pool () {
max_validators=$1
stake_pool_keyfile=$2
mint_keyfile=$3
mkdir -p $keys_dir
create_keypair $stake_pool_keyfile
create_keypair $mint_keyfile
$spl_stake_pool create-pool --epoch-fee-numerator 3 --epoch-fee-denominator 100 \
--withdrawal-fee-numerator 5 --withdrawal-fee-denominator 1000 \
--max-validators $max_validators \
--pool-keypair $stake_pool_keyfile \
--mint-keypair $mint_keyfile
}
add_validator_stakes () {
pool=$1
validator_list=$2
for validator in $(cat $validator_list)
do
$spl_stake_pool add-validator $pool $validator
$spl_stake_pool "${global_args[@]}" add-validator $pool $validator
done
}
echo "Building stake pool CLI"
build_stake_pool_cli
echo "Creating pool"
stake_pool_keyfile=$keys_dir/stake-pool.json
mint_keyfile=$keys_dir/mint.json
reserve_keyfile=$keys_dir/reserve.json
create_keypair $stake_pool_keyfile
create_keypair $mint_keyfile
create_keypair $reserve_keyfile
echo "Building CLI"
build_cli
echo "Creating pool"
setup_pool $max_validators $stake_pool_keyfile $mint_keyfile
set -ex
$spl_stake_pool \
"${global_args[@]}" \
create-pool \
"${command_args[@]}" \
--pool-keypair "$stake_pool_keyfile" \
--mint-keypair "$mint_keyfile" \
--reserve-keypair "$reserve_keyfile"
stake_pool_pubkey=$(solana-keygen pubkey $stake_pool_keyfile)

View File

@ -9,7 +9,7 @@ use {
solana_clap_utils::{
input_parsers::{keypair_of, pubkey_of},
input_validators::{
is_amount, is_keypair, is_keypair_or_ask_keyword, is_parsable, is_pubkey, is_url,
is_amount, is_keypair_or_ask_keyword, is_parsable, is_pubkey, is_url,
is_valid_percentage, is_valid_pubkey,
},
keypair::{signer_from_path_with_config, SignerFromPathConfig},
@ -180,7 +180,7 @@ fn new_stake_account(
#[allow(clippy::too_many_arguments)]
fn command_create_pool(
config: &Config,
stake_deposit_authority: Option<Keypair>,
deposit_authority: Option<Keypair>,
epoch_fee: Fee,
stake_withdrawal_fee: Fee,
stake_deposit_fee: Fee,
@ -312,7 +312,7 @@ fn command_create_pool(
&mint_keypair.pubkey(),
&pool_fee_account,
&spl_token::id(),
stake_deposit_authority.as_ref().map(|x| x.pubkey()),
deposit_authority.as_ref().map(|x| x.pubkey()),
epoch_fee,
stake_withdrawal_fee,
stake_deposit_fee,
@ -342,9 +342,13 @@ fn command_create_pool(
&validator_list,
config.manager.as_ref(),
];
if let Some(stake_deposit_authority) = stake_deposit_authority {
if let Some(deposit_authority) = deposit_authority {
println!(
"Deposits will be restricted to {} only, this can be changed using the set-funding-authority command.",
deposit_authority.pubkey()
);
let mut initialize_signers = initialize_signers.clone();
initialize_signers.push(&stake_deposit_authority);
initialize_signers.push(&deposit_authority);
unique_signers!(initialize_signers);
initialize_transaction.sign(&initialize_signers, recent_blockhash);
} else {
@ -1672,7 +1676,7 @@ fn main() {
Arg::with_name("staker")
.long("staker")
.value_name("KEYPAIR")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.takes_value(true)
.help(
"Specify the stake pool staker. \
@ -1684,7 +1688,7 @@ fn main() {
Arg::with_name("manager")
.long("manager")
.value_name("KEYPAIR")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.takes_value(true)
.help(
"Specify the stake pool manager. \
@ -1696,7 +1700,7 @@ fn main() {
Arg::with_name("funding_authority")
.long("funding-authority")
.value_name("KEYPAIR")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.takes_value(true)
.help(
"Specify the stake pool funding authority, for deposits or withdrawals. \
@ -1707,7 +1711,7 @@ fn main() {
Arg::with_name("token_owner")
.long("token-owner")
.value_name("KEYPAIR")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.takes_value(true)
.help(
"Specify the owner of the pool token account. \
@ -1719,7 +1723,7 @@ fn main() {
Arg::with_name("fee_payer")
.long("fee-payer")
.value_name("KEYPAIR")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.takes_value(true)
.help(
"Specify the fee-payer account. \
@ -1802,11 +1806,11 @@ fn main() {
.help("Max number of validators included in the stake pool"),
)
.arg(
Arg::with_name("stake_deposit_authority")
.long("stake-deposit-authority")
Arg::with_name("deposit_authority")
.long("deposit-authority")
.short("a")
.validator(is_keypair_or_ask_keyword)
.value_name("STAKE_DEPOSIT_AUTHORITY_KEYPAIR")
.value_name("DEPOSIT_AUTHORITY_KEYPAIR")
.takes_value(true)
.help("Deposit authority required to sign all deposits into the stake pool"),
)
@ -2016,7 +2020,7 @@ fn main() {
.arg(
Arg::with_name("withdraw_authority")
.long("withdraw-authority")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.value_name("KEYPAIR")
.takes_value(true)
.help("Withdraw authority for the stake account to be deposited. \
@ -2232,7 +2236,7 @@ fn main() {
.arg(
Arg::with_name("new_manager")
.long("new-manager")
.validator(is_keypair)
.validator(is_keypair_or_ask_keyword)
.value_name("KEYPAIR")
.takes_value(true)
.help("Keypair for the new stake pool manager."),
@ -2463,7 +2467,7 @@ fn main() {
let _ = match matches.subcommand() {
("create-pool", Some(arg_matches)) => {
let stake_deposit_authority = keypair_of(arg_matches, "stake_deposit_authority");
let deposit_authority = keypair_of(arg_matches, "deposit_authority");
let e_numerator = value_t_or_exit!(arg_matches, "epoch_fee_numerator", u64);
let e_denominator = value_t_or_exit!(arg_matches, "epoch_fee_denominator", u64);
let w_numerator = value_t!(arg_matches, "withdrawal_fee_numerator", u64);
@ -2477,7 +2481,7 @@ fn main() {
let reserve_keypair = keypair_of(arg_matches, "reserve_keypair");
command_create_pool(
&config,
stake_deposit_authority,
deposit_authority,
Fee {
numerator: e_numerator,
denominator: e_denominator,