diff --git a/tools/genx/README.md b/tools/genx/README.md index cd941f5c..1fd83f06 100644 --- a/tools/genx/README.md +++ b/tools/genx/README.md @@ -14,5 +14,51 @@ if they exist on chain ```sh cargo run --release --bin genx test-validator \ --rpc-port 7799 --url 'https://rpc.magicblock.app/mainnet' \ - test-integration/ledgers/ledgers + ledger ``` + +Then you run the script to start a mainnet standin locally. + +Also make sure to update the config with which to start the ephemeral validator that will +replay the ledger to point to the port that it is running on. + +#### Config Example + +```toml +[accounts] +remote = ["http://127.0.0.1:7799", "ws://127.0.0.1:7800"] +lifecycle = "ephemeral" +commit = { frequency_millis = 50_000 } +payer = { init_sol = 1_000 } + +[rpc] +addr = "0.0.0.0" +port = 8899 + +[validator] +millis_per_slot = 50 + +[ledger] +reset = false +path = "./ledger" +``` + +### test-ledger + +Prepares a ledger for replay in a diagnostics/test scenario. At this point it ensures that the +original keypair of the validator operator is not used. Instead it is overwritten with a random +keypair. That keypair is then printed to the terminal so that the `VALIDATOR_KEYPAIR` env var +can be set to it when running the ephemeral validator to replay the ledger. + +One can auto-set that env var using the output of this command as follows: + +```sh +export VALIDATOR_KEYPAIR=$(cargo run --bin genx -- test-ledger ./ledger) +``` + +Then we can just do the following to replay the ledger (i.e. providing the above config): + +```sh +cargo run --release ledger-config.toml +``` + diff --git a/tools/genx/src/ledger_replay_test.rs b/tools/genx/src/ledger_replay_test.rs new file mode 100644 index 00000000..4ef863ab --- /dev/null +++ b/tools/genx/src/ledger_replay_test.rs @@ -0,0 +1,46 @@ +use std::fs; +use std::path::PathBuf; + +use solana_sdk::signature::Keypair; +use solana_sdk::signer::{EncodableKey, Signer}; + +pub(crate) fn ledger_replay_test(ledger_path: &PathBuf) { + match fs::exists(ledger_path) { + Ok(x) if !x => { + panic!("Ledger path does not exist: {}", ledger_path.display()) + } + Err(err) => { + panic!( + "Error looking up ledger path: {} ({})", + ledger_path.display(), + err + ) + } + _ => {} + } + + let keypair_file = ledger_path.join("validator-keypair.json"); + + if let Ok(true) = fs::exists(&keypair_file) { + if let Ok(kp) = Keypair::read_from_file(&keypair_file) { + eprintln!("Overwriting existing keypair: {}", kp.pubkey()); + } + } + + let kp = Keypair::new(); + Keypair::write_to_file(&kp, &keypair_file) + .expect("Failed to write keypair"); + + eprintln!( + "Wrote test validator authority (pubkey: {}) to ledger", + kp.pubkey() + ); + let base58 = kp.to_base58_string(); + eprintln!( + "Add the keypair to your environment via 'export VALIDATOR_KEYPAIR={}'\n", + base58 + ); + + // Print the base58 keypair to stdout for easy copy/paste and output capture + println!("{}", base58); +} diff --git a/tools/genx/src/main.rs b/tools/genx/src/main.rs index 92a6c522..74a58b24 100644 --- a/tools/genx/src/main.rs +++ b/tools/genx/src/main.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; use test_validator::TestValidatorConfig; +mod ledger_replay_test; mod test_validator; #[derive(Debug, Parser)] @@ -29,6 +30,13 @@ enum Commands { #[arg(long)] url: String, }, + /// Prepares the ledger for testing + #[command(name = "test-ledger")] + #[command( + about = "Prepares the ledger for testing", + long_about = "(Over)writes the validator keypair" + )] + LedgerReplayTest { ledger_path: PathBuf }, } fn main() { @@ -45,5 +53,8 @@ fn main() { config, ) } + Commands::LedgerReplayTest { ledger_path } => { + ledger_replay_test::ledger_replay_test(&ledger_path) + } } }