Skip to content

Commit

Permalink
CLI + FIXES: Steward CLI (#49)
Browse files Browse the repository at this point in the history
This PR adds the Steward CLI that can create and crank through the
entire Steward state machine.

It also introduces some fixes to the Steward program.
  • Loading branch information
coachchucksol authored and ebatsell committed Jun 24, 2024
1 parent d3d3d87 commit 2124bbe
Show file tree
Hide file tree
Showing 34 changed files with 2,815 additions and 23 deletions.
35 changes: 33 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
members = [
"keepers/*",
"programs/*",
"utils/*",
"tests",
"utils/*"
]

[profile.release]
Expand Down
1 change: 1 addition & 0 deletions keepers/keeper-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ pub async fn parallel_execute_transactions(
// Future optimization: submit these in parallel batches and refresh blockhash for every batch
match client.send_transaction(tx).await {
Ok(signature) => {
println!("Submitted transaction: {:?}", signature);
submitted_signatures.insert(signature, idx);
}
Err(e) => match e.get_transaction_error() {
Expand Down
1 change: 1 addition & 0 deletions programs/steward/src/instructions/epoch_maintenance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub fn handler(
if okay_to_update {
state_account.state.current_epoch = clock.epoch;
state_account.state.checked_validators_removed_from_list = false.into();
state_account.state.rebalance_completed = false.into();
}
}

Expand Down
5 changes: 1 addition & 4 deletions programs/steward/src/score.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,7 @@ pub fn instant_unstake_validator(
.checked_sub(epoch_start_slot)
.ok_or(StewardError::ArithmeticError)?;

let vote_credits_rate = validator
.history
.epoch_credits_latest()
.ok_or(StewardError::VoteHistoryNotRecentEnough)? as f64
let vote_credits_rate = validator.history.epoch_credits_latest().unwrap_or(0) as f64
/ validator_history_slot_index as f64;

let delinquency_check = if blocks_produced_rate > 0. {
Expand Down
37 changes: 21 additions & 16 deletions programs/steward/src/state/steward_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ impl StewardState {
} else if (!self.rebalance_completed).into()
&& epoch_progress >= min_epoch_progress_for_instant_unstake
{
//NOTE: rebalance_completed is cleared on epoch change in `epoch_maintenance`

self.state_tag = StewardStateEnum::ComputeInstantUnstake;
self.instant_unstake = BitMask::default();
self.progress = BitMask::default();
Expand Down Expand Up @@ -546,22 +548,6 @@ impl StewardState {
let current_epoch = clock.epoch;
let current_slot = clock.slot;

// Check that latest_update_slot is within the current epoch to guarantee previous epoch data is complete
let last_update_slot = validator
.history
.vote_account_last_update_slot_latest()
.ok_or(StewardError::VoteHistoryNotRecentEnough)?;
if last_update_slot < epoch_schedule.get_first_slot_in_epoch(current_epoch) {
return Err(StewardError::VoteHistoryNotRecentEnough.into());
}

// Check that cluster history is within current epoch to guarantee previous epoch data is complete
if cluster.cluster_history_last_update_slot
< epoch_schedule.get_first_slot_in_epoch(current_epoch)
{
return Err(StewardError::ClusterHistoryNotRecentEnough.into());
}

/* Reset common state if:
- it's a new delegation cycle
- it's been more than `compute_score_slot_range` slots since compute scores started
Expand Down Expand Up @@ -615,9 +601,28 @@ impl StewardState {
self.yield_scores[index],
num_scores_calculated,
)?;

self.progress.set(index, true)?;

return Ok(());
}

// Check that latest_update_slot is within the current epoch to guarantee previous epoch data is complete
let last_update_slot = validator
.history
.vote_account_last_update_slot_latest()
.ok_or(StewardError::VoteHistoryNotRecentEnough)?;
if last_update_slot < epoch_schedule.get_first_slot_in_epoch(current_epoch) {
return Err(StewardError::VoteHistoryNotRecentEnough.into());
}

// Check that cluster history is within current epoch to guarantee previous epoch data is complete
if cluster.cluster_history_last_update_slot
< epoch_schedule.get_first_slot_in_epoch(current_epoch)
{
return Err(StewardError::ClusterHistoryNotRecentEnough.into());
}

let score = validator_score(validator, index, cluster, config, current_epoch as u16)?;
emit!(score);

Expand Down
26 changes: 26 additions & 0 deletions utils/steward-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "steward-cli"
version = "0.1.0"
edition = "2021"
description = "CLI to manage the steward program"

[dependencies]
anchor-lang = "0.30.0"
clap = { version = "4.3.0", features = ["derive", "env"] }
futures = "0.3.21"
futures-util = "0.3.21"
log = "0.4.18"
solana-account-decoder = "1.18"
solana-clap-utils = "1.18"
solana-client = "1.18"
solana-metrics = "1.18"
solana-program = "1.18"
solana-sdk = "1.18"
thiserror = "1.0.37"
spl-stake-pool = { features = ["no-entrypoint"], version = "1.0.0" }
tokio = { version = "1.36.0", features = ["full"] }
validator-history = { features = ["no-entrypoint"], path = "../../programs/validator-history" }
jito-steward = { features = ["no-entrypoint"], path = "../../programs/steward" }
keeper-core = { path = "../../keepers/keeper-core" }
dotenv = "0.15.0"
anyhow = "1.0.86"
160 changes: 160 additions & 0 deletions utils/steward-cli/initial_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@

# Accounts

**Authority**
`aaaDerwdMyzNkoX1aSoTi3UtFe2W45vh5wCgQNhsjF8`

**Steward Config**
`6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5`

**Stake Pool**
`3DuPtyTAKrxKfHkSPZ5fqCayMcGru1BarAKKTfGDeo2j`

**Staker**
`4m64H5TbwAGtZVnxaGAVoTSwjZGV8BCLKRPr8agKQv4Z`

**State**
`6SJrBTYSSu3jWmsPWWhMMHvrPxqKWXtLe9tRfYpU8EZa`

# Initial Commands

## Create Config
```bash
cargo run init-config \
--authority-keypair-path ../../credentials/stakenet_test.json \
--steward-config-keypair-path ../../credentials/steward_config.json \
--stake-pool 3DuPtyTAKrxKfHkSPZ5fqCayMcGru1BarAKKTfGDeo2j \
--mev-commission-range 10 \
--epoch-credits-range 30 \
--commission-range 30 \
--mev-commission-bps-threshold 1000 \
--commission-threshold 5 \
--historical-commission-threshold 50 \
--scoring-delinquency-threshold-ratio 0.85 \
--instant-unstake-delinquency-threshold-ratio 0.70 \
--num-delegation-validators 200 \
--scoring-unstake-cap-bps 750 \
--instant-unstake-cap-bps 1000 \
--stake-deposit-unstake-cap-bps 1000 \
--compute-score-slot-range 50000 \
--instant-unstake-epoch-progress 0.50 \
--instant-unstake-inputs-epoch-progress 0.50 \
--num-epochs-between-scoring 3 \
--minimum-stake-lamports 100000000000 \
--minimum-voting-epochs 5
```

## Update Config
```bash
cargo run update-config \
--authority-keypair-path ../../credentials/stakenet_test.json \
--steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 \
--instant-unstake-inputs-epoch-progress 0.10 \
--instant-unstake-epoch-progress 0.10
```

## Create State
```bash
cargo run init-state --authority-keypair-path ../../credentials/stakenet_test.json --stake-pool 3DuPtyTAKrxKfHkSPZ5fqCayMcGru1BarAKKTfGDeo2j --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5
```

## View Config
```bash
cargo run view-config --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5
```

## View State
```bash
cargo run view-state --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5
```

## View State Per Validator
```bash
cargo run view-state-per-validator --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5
```

## View Next Index To Remove
```bash
cargo run view-next-index-to-remove --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5
```

## Auto Remove Validator
```bash
cargo run auto-remove-validator-from-pool --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json --validator-index-to-remove 1397
```

## Auto Add Validator
```bash
cargo run auto-add-validator-from-pool --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json --vote-account 4m64H5TbwAGtZVnxaGAVoTSwjZGV8BCLKRPr8agKQv4Z
```

## Remove Bad Validators
```bash
cargo run remove-bad-validators --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

## Crank Epoch Maintenance
```bash
cargo run crank-epoch-maintenance --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

## Crank Compute Score
```bash
cargo run crank-compute-score --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

## Crank Compute Delegations
```bash
cargo run crank-compute-delegations --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

## Crank Idle
```bash
cargo run crank-idle --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

## Crank Compute Instant Unstake
```bash
cargo run crank-compute-instant-unstake --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

## Crank Rebalance
```bash
cargo run crank-rebalance --steward-config 6auT7Q91SSgAoYLAnu449DK1MK9skDmtiLmtkCECP1b5 --payer-keypair-path ../../credentials/stakenet_test.json
```

# Deploy and Upgrade

- upgrade solana cli to 1.18.16
- make sure your configured keypair is `aaaDerwdMyzNkoX1aSoTi3UtFe2W45vh5wCgQNhsjF8`
- create a new keypair: `solana-keygen new -o credentials/temp-buffer.json`
- use anchor `0.30.0`: `avm install 0.30.0 && avm use 0.30.0`
- build .so file: `anchor build --no-idl`
- Write to buffer: `solana program write-buffer --use-rpc --buffer credentials/temp-buffer.json --url $(solana config get | grep "RPC URL" | awk '{print $3}') --with-compute-unit-price 10000 --max-sign-attempts 10000 target/deploy/jito_steward.so --keypair credentials/stakenet_test.json`
- Upgrade: `solana program upgrade $(solana address --keypair credentials/temp-buffer.json) sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP --keypair credentials/stakenet_test.json --url $(solana config get | grep "RPC URL" | awk '{print $3}')`
- Close Buffers: `solana program close --buffers --keypair credentials/stakenet_test.json`
- Upgrade Program Size: `solana program extend sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP 1000000 --keypair credentials/stakenet_test.json --url $(solana config get | grep "RPC URL" | awk '{print $3}')`

# Initial Parameters

```env
# Note - Do not use this .env when updating the parameters - this will update them all
MEV_COMMISSION_RANGE=10
EPOCH_CREDITS_RANGE=30
COMMISSION_RANGE=30
MEV_COMMISSION_BPS_THRESHOLD=1000
COMMISSION_THRESHOLD=5
HISTORICAL_COMMISSION_THRESHOLD=50
SCORING_DELINQUENCY_THRESHOLD_RATIO=0.85
INSTANT_UNSTAKE_DELINQUENCY_THRESHOLD_RATIO=0.70
NUM_DELEGATION_VALIDATORS=200
SCORING_UNSTAKE_CAP_BPS=750
INSTANT_UNSTAKE_CAP_BPS=1000
STAKE_DEPOSIT_UNSTAKE_CAP_BPS=1000
COMPUTE_SCORE_SLOT_RANGE=1000
INSTANT_UNSTAKE_EPOCH_PROGRESS=0.50
INSTANT_UNSTAKE_INPUTS_EPOCH_PROGRESS=0.50
NUM_EPOCHS_BETWEEN_SCORING=3
MINIMUM_STAKE_LAMPORTS=100000000000
MINIMUM_VOTING_EPOCHS=5
```
Loading

0 comments on commit 2124bbe

Please sign in to comment.