Skip to content

Commit

Permalink
Finalize keeper, improve tx confirmation (#76)
Browse files Browse the repository at this point in the history
* use \_with\_history for confirmation otherwise txs expire after 300
blocks
* Touch up keeper README
* Rename keeper
  • Loading branch information
ebatsell authored Aug 13, 2024
1 parent 9336c4b commit 70ca7e3
Show file tree
Hide file tree
Showing 32 changed files with 154 additions and 113 deletions.
64 changes: 32 additions & 32 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ COPY . .

RUN --mount=type=cache,mode=0777,target=/home/root/app/target \
--mount=type=cache,mode=0777,target=/usr/local/cargo/registry \
cargo build --release --bin validator-keeper
cargo build --release --bin stakenet-keeper

#########

FROM debian:buster as validator-history
RUN apt-get update && apt-get install -y ca-certificates
ENV APP="validator-keeper"
ENV APP="stakenet-keeper"

COPY --from=builder /usr/src/app/target/release/$APP ./$APP

Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
version: "3"
services:
validator-keeper:
stakenet-keeper:
build:
context: .
target: validator-history
container_name: validator-keeper
container_name: stakenet-keeper
environment:
- RUST_LOG=${RUST_LOG:-info}
- SOLANA_METRICS_CONFIG=${SOLANA_METRICS_CONFIG}
Expand Down
90 changes: 50 additions & 40 deletions keeper-bot-quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,25 @@ solana-keygen new -o ./credentials/keypair.json

### ENV

In the root directory create a new folder named `config` and create a `.env` file inside of it
In the root directory create `.env` file

```bash
mkdir config
touch ./config/.env
touch .env
```

Then copy into the `.env` file the contents below. Everything should be set as-is, however consider replacing the `JSON_RPC_URL` and adjusting the `PRIORITY_FEES`
Then copy into the `.env` file the contents below. Everything should be set as-is, however you will need to include a `JSON_RPC_URL` that can handle getProgramAccounts calls.

```.env
```bash
# RPC URL for the cluster
JSON_RPC_URL=https://api.mainnet-beta.solana.com
JSON_RPC_URL="INCLUDE YOUR RPC URL HERE"

# Cluster to specify (mainnet, testnet, devnet)
CLUSTER=mainnet

# Log levels
RUST_LOG="info,solana_gossip=error,solana_metrics=info"

# Path to keypair used to pay for account creation and execute transactions
# Path to keypair used to execute tranasactions
KEYPAIR=./credentials/keypair.json

# Validator history program ID (Pubkey as base58 string)
Expand All @@ -46,59 +45,56 @@ TIP_DISTRIBUTION_PROGRAM_ID=4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7
# Steward program ID
STEWARD_PROGRAM_ID=Stewardf95sJbmtcZsyagb2dg4Mo8eVQho8gpECvLx8

# Steward config account
# Steward config account for JitoSOL
STEWARD_CONFIG=jitoVjT9jRUyeXHzvCwzPgHj7yWNRhLcUoXtes4wtjv

# Priority Fees in microlamports
PRIORITY_FEES=20000

# Retry count
TX_RETRY_COUNT=100

# Confirmation time after submission
TX_CONFIRMATION_SECONDS=30

# Run flags (true/false)
RUN_CLUSTER_HISTORY=true
RUN_COPY_VOTE_ACCOUNTS=true
RUN_MEV_COMMISSION=true
RUN_MEV_EARNED=true
RUN_STEWARD=true
RUN_EMIT_METRICS=true
################# DEBUGGING AND ORACLE USE ONLY #################
RUN_EMIT_METRICS=false

# Interval to update Validator History Accounts (in seconds)
# VALIDATOR_HISTORY_INTERVAL=300
VALIDATOR_HISTORY_INTERVAL=300

# Interval to run steward (in seconds)
# STEWARD_INTERVAL=301
STEWARD_INTERVAL=301

# Interval to emit metrics (in seconds)
# METRICS_INTERVAL=60
METRICS_INTERVAL=60

# For ORACLE_AUTHORITY operator
# RUN_STAKE_UPLOAD=false
# RUN_GOSSIP_UPLOAD=false
# For Oracle Authority Only
RUN_STAKE_UPLOAD=false
RUN_GOSSIP_UPLOAD=false

# Run with the startup flag set to true
# FULL_STARTUP=true
FULL_STARTUP=true

# Running with no_pack set to true skips packing the instructions and will cost more
# NO_PACK=false
NO_PACK=false

# Pay for new accounts when necessary
# PAY_FOR_NEW_ACCOUNTS=false
PAY_FOR_NEW_ACCOUNTS=false

# Max time in minutes to wait after any fire cycle
# COOL_DOWN_RANGE=20
COOL_DOWN_RANGE=20

# Gossip entrypoint in the form of URL:PORT
# GOSSIP_ENTRYPOINT=
# Metrics upload config
# For uploading metrics to your private InfluxDB instance
# SOLANA_METRICS_CONFIG=
# Path to keypair used specifically for submitting permissioned transactions
# ORACLE_AUTHORITY_KEYPAIR=
# Metrics upload influx server (optional)
SOLANA_METRICS_CONFIG=""
```

## Running Docker
## Running Docker image from source

Once the setup is complete use the following commands to run/manage the docker container:

Expand All @@ -107,39 +103,53 @@ Once the setup is complete use the following commands to run/manage the docker c
### Start Docker

```bash
docker compose --env-file config/.env up -d --build validator-keeper --remove-orphans
docker compose --env-file .env up -d --build stakenet-keeper --remove-orphans
```

### Stop Docker**
### View Logs

```bash
docker stop validator-keeper; docker rm validator-keeper;
docker logs stakenet-keeper -f
```

### View Logs
### Stop Docker\*\*

```bash
docker stop stakenet-keeper; docker rm stakenet-keeper;
```

## Run from Dockerhub

This image is available on Dockerhub at: https://hub.docker.com/r/jitolabs/stakenet-keeper

```bash
docker logs validator-keeper -f
docker pull jitolabs/stakenet-keeper:latest
docker run -d \
--name stakenet-keeper \
--env-file .env \
-v $(pwd)/credentials:/credentials \
--restart on-failure:5 \
jitolabs/stakenet-keeper:latest
```

## Running Raw
## Running as Binary

To run the keeper in terminal, build for release and run the program.

### Build for Release

```bash
cargo build --release --bin validator-keeper
cargo build --release --bin stakenet-keeper
```

### Run Keeper

```bash
RUST_LOG=info cargo run --bin validator-keeper --
RUST_LOG=info ./target/release/stakenet-keeper
```

To see all available parameters run:

```bash
RUST_LOG=info cargo run --bin validator-keeper -- -h
RUST_LOG=info ./target/release/stakenet-keeper -h
```
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "validator-keeper"
name = "stakenet-keeper"
version = "0.1.0"
edition = "2021"
description = "Script to keep validator history accounts up to date"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,70 @@
## Keeper State
# StakeNet Keeper Bot

## Overview

This is a service that permissionlessly maintains the StakeNet Validator History and Steward programs. It ensures that Validator History data is kept up to date, and that the Steward program is properly moving through its regular operations to maintain the targeted stake pool. Operations, program addresses, and transaction submission details, can be configured via arguments or environment variables.

## Usage

See [keeper-bot-quick-start.md](../../keeper-bot-quick-start.md) for instructions on how to build and run this service.

## Program Layout

### Keeper State

The `KeeperState` keeps track of:

- current epoch data
- running tally of all operations successes and failures for the given epoch
- all accounts fetched from the RPC that are needed downstream

Note: All maps are key'd by the `vote_account`

## Program

### Initialize
Gather all needed arguments, and initialize the global `KeeperState`.

Gather all needed arguments, and initialize the global `KeeperState`.

### Loop
The forever loop consists of three parts: **Fetch**, **Fire** and **Emit**. There is only ever one **Fetch** and **Emit** section, and there can be several **Fire** sections.

The forever loop consists of three parts: **Fetch**, **Fire** and **Emit**. There is only ever one **Fetch** and **Emit** section, and there can be several **Fire** sections.

The **Fire** sections can run on independent cadences - say we want the Validator History functions to run every 300sec and we want to emit metrics every 60sec.

The **Fetch** section is run _before_ and **Fire** section.
The **Emit** section is *one tick* after any **Fire** section.
The **Fetch** section is run _before_ and **Fire** section.
The **Emit** section is _one tick_ after any **Fire** section.

#### Fetch

The **Fetch** section is in charge of three operations:

- Keeping track of the current epoch and resetting the runs and error counts for each operation
- Creating any missing accounts needed for the downstream **Fires** to run
- Fetching and updating all of the needed accounts needed downstream

This is accomplished is by running three functions within the **Fetch** section

- `pre_create_update` - Updates epoch, and fetches all needed accounts that are not dependant on any missing accounts.
- `create_missing_accounts` - Creates the missing accounts, which can be determined by the accounts fetched in the previous step
- `post_create_update` - Fetches any last accounts that needed the missing accounts
- `post_create_update` - Fetches any last accounts that needed the missing accounts

Since this is run before every **FIRE** section, some accounts will be fetched that are not needed. This may seem wasteful but the simplicity of having a synchronized global is worth the cost.

Notes:
- The **Fetch** section is the only section that will mutate the `KeeperState`.
Notes:

- The **Fetch** section is the only section that will mutate the `KeeperState`.
- If anything in the **Fetch** section fails, no **Fires** will run

#### Fire

There are several **Fire** sections running at their own cadence. Before any **Fire** section is run, the **Fetch** section will be called.

Each **Fire** is a call to `operations::operation_name::fire` which will fire off the operation and return the new count of runs and errors for that operation to be saved in the `KeeperState`

Notes:
- Each **Fire** is self contained, one should not be dependant on another.
- No **Fire* will fetch any accounts, if there are needs for them, they should be added to the `KeeperState`
Notes:

- Each **Fire** is self contained, one should not be dependant on another.
- No \*_Fire_ will fetch any accounts, if there are needs for them, they should be added to the `KeeperState`

#### Emit
This section emits the state of the Keeper one tick after any operation has been called. This is because we want to emit a failure of any **Fetch** operation, which on failure advances the tick.



This section emits the state of the Keeper one tick after any operation has been called. This is because we want to emit a failure of any **Fetch** operation, which on failure advances the tick.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 70ca7e3

Please sign in to comment.