diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 85b61ba79..accf82ec2 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1 @@ -* @prestwich @anna-carroll @erinhales -rust/ @prestwich @emberian @ltchang +* @asaj @mattiecnvr @nambrot @tkporter @webbhorn @yorhodes @zmanian diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e4f62fbd7..383cbcbad 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -66,7 +66,7 @@ jobs: with: working-directory: ./rust - name: Rustfmt - run: cargo fmt -- --check + run: cargo fmt --all -- --check - name: Check run: cargo check --all-features --all-targets --verbose - name: Clippy diff --git a/rust/.gitignore b/rust/.gitignore index 8c4034a8a..68e46ea8a 100644 --- a/rust/.gitignore +++ b/rust/.gitignore @@ -1,5 +1,4 @@ target -processordb validatordb relayerdb kathydb \ No newline at end of file diff --git a/rust/.vscode/settings.json b/rust/.vscode/settings.json index b661ecf65..9a8085c23 100644 --- a/rust/.vscode/settings.json +++ b/rust/.vscode/settings.json @@ -1,6 +1,5 @@ { "files.exclude": { "target": true, - "**/bin": true, }, } diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 829ec8ef2..8262528aa 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -158,17 +158,6 @@ dependencies = [ "opaque-debug 0.3.0", ] -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.3", - "once_cell", - "version_check", -] - [[package]] name = "aho-corasick" version = "0.7.18" @@ -178,15 +167,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -304,22 +284,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "balance-exporter" -version = "0.1.0" -dependencies = [ - "abacus-base", - "abacus-ethereum", - "clap 3.1.18", - "color-eyre", - "futures", - "human-panic", - "metrics", - "serde 1.0.130", - "serde_json", - "tokio", -] - [[package]] name = "base16ct" version = "0.1.1" @@ -610,32 +574,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "checkpointer" -version = "0.1.0" -dependencies = [ - "abacus-base", - "abacus-core", - "abacus-ethereum", - "abacus-test", - "async-trait", - "color-eyre", - "config", - "ethers", - "eyre", - "futures-util", - "prometheus", - "rocksdb", - "serde 1.0.130", - "serde_json", - "thiserror", - "tokio", - "tokio-test", - "tracing", - "tracing-futures", - "tracing-subscriber", -] - [[package]] name = "chrono" version = "0.4.19" @@ -671,58 +609,19 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "atty", "bitflags", - "strsim 0.8.0", - "textwrap 0.11.0", + "strsim", + "textwrap", "unicode-width", "vec_map", ] -[[package]] -name = "clap" -version = "3.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "clap_lex", - "indexmap", - "lazy_static", - "strsim 0.10.0", - "termcolor", - "textwrap 0.15.0", -] - -[[package]] -name = "clap_derive" -version = "3.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" -dependencies = [ - "heck 0.4.0", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "coins-bip32" version = "0.6.0" @@ -1757,12 +1656,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -1840,21 +1733,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" -[[package]] -name = "human-panic" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f357a500abcbd7c5f967c1d45c8838585b36743823b9d43488f24850534e36" -dependencies = [ - "backtrace", - "os_type", - "serde 1.0.130", - "serde_derive", - "termcolor", - "toml", - "uuid", -] - [[package]] name = "hyper" version = "0.14.14" @@ -2084,22 +1962,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -[[package]] -name = "kms-cli" -version = "0.1.0" -dependencies = [ - "clap 3.1.18", - "color-eyre", - "ethers", - "ethers-signers", - "hex", - "once_cell", - "rusoto_core", - "rusoto_kms", - "serde_json", - "tokio", -] - [[package]] name = "lalrpop" version = "0.19.7" @@ -2259,27 +2121,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "metrics" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e52eb6380b6d2a10eb3434aec0885374490f5b82c8aaf5cd487a183c98be834" -dependencies = [ - "ahash", - "metrics-macros", -] - -[[package]] -name = "metrics-macros" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e30813093f757be5cf21e50389a24dc7dbb22c49f23b7e8f51d69b508a5ffa" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "mime" version = "0.3.16" @@ -2664,21 +2505,6 @@ dependencies = [ "num-traits 0.2.14", ] -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" - -[[package]] -name = "os_type" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eaebe22d9f12429b1af6a0b5dd411ccfc5cb5968710abbb8c512046be9df90" -dependencies = [ - "regex", -] - [[package]] name = "owo-colors" version = "3.2.0" @@ -3921,19 +3747,13 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "structopt" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap 2.33.3", + "clap", "lazy_static", "structopt-derive", ] @@ -3944,7 +3764,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck 0.3.3", + "heck", "proc-macro-error", "proc-macro2", "quote", @@ -3999,15 +3819,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - [[package]] name = "termtree" version = "0.2.3" @@ -4023,12 +3834,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - [[package]] name = "thiserror" version = "1.0.30" @@ -4331,7 +4136,7 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "serde 1.0.130", "serde_json", "sharded-slab", @@ -4452,9 +4257,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f142ff356..63465c5a8 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -5,13 +5,10 @@ cargo-features = ["edition2021"] members = [ "abacus-core", "abacus-base", + "abacus-cli", "abacus-test", "chains/abacus-ethereum", "agents/kathy", - "agents/checkpointer", "agents/validator", "agents/relayer", - "tools/kms-cli", - "tools/abacus-cli", - "tools/balance-exporter" ] diff --git a/rust/Dockerfile b/rust/Dockerfile index f2e38972d..202d0c4cd 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -12,8 +12,8 @@ RUN apt-get update && \ # Add workspace to workdir COPY agents ./agents COPY chains ./chains -COPY tools ./tools COPY abacus-base ./abacus-base +COPY abacus-cli ./abacus-cli COPY abacus-core ./abacus-core COPY abacus-test ./abacus-test @@ -29,9 +29,7 @@ RUN \ mkdir -p /release && \ cp /usr/src/target/release/validator /release && \ cp /usr/src/target/release/relayer /release && \ - cp /usr/src/target/release/checkpointer /release && \ cp /usr/src/target/release/kathy /release && \ - cp /usr/src/target/release/kms-cli /release && \ cp /usr/src/target/release/abacus-cli /release ## 2: Copy the binaries to release image diff --git a/rust/README.md b/rust/README.md index acaaae193..c972cd5f3 100644 --- a/rust/README.md +++ b/rust/README.md @@ -53,27 +53,6 @@ easily described. Each of these agents will connect to a home chain and any number of replicas. They need to be configured with chain connection details and have access to a reliable node for each chain. -Some agent sketches: - -- `updater` - - Needs only a connection to the home chain - - Signs update attestations and submits them to the home chain -- `watcher` - - Observe the home chain - - Observe as many replicas as possible - - Cache updates - - Check for fraud - - Submit fraud to the home chain - - if configured, issue emergency stop transactions -- `relayer` - - Relays signed updates from the home to the replica -- `processor` - - retrieve leaves from home chain - - observe >=1 replica - - generate proofs for the messages - - submit messages and proofs to the replica for processing - - config option: gas params - For Ethereum and Celo connections we use [ethers-rs](https://github.com/gakonst/ethers-rs). Please see the docs [here](https://docs.rs/ethers/0.2.0/ethers/). @@ -83,43 +62,28 @@ We use the tokio async runtime environment. Please see the docs ### Repo layout -- `abacus-core` - - contains implementations of core primitives - - this includes - - traits (interfaces) for the on-chain contracts - - model implementations of the contracts in rust - - merkle tree implementations (for provers) - `abacus-base` + - lowest dependency abacus utilities - contains shared utilities for building off-chain agents - this includes - trait implementations for different chains - shared configuration file formats - basic setup for an off-chain agent +- `abacus-core` + - depends on abacus-base + - contains implementations of core primitives + - this includes + - traits (interfaces) for the on-chain contracts + - model implementations of the contracts in rust + - merkle tree implementations (for provers) - `chains/abacus-ethereum` + - depends on abacus-core (and transitively abacus-base) - interfaces to the ethereum contracts - `agents` - each of the off-chain agents implemented thus far -### High-level guide to building an agent - -- `cargo new $AGENT_NAME` -- add the new directory name to the workspace `Cargo.toml` -- add dependencies to the new directory's `Cargo.toml` - - copy most of the dependencies from `abacus-base` -- create a new module in `src/$AGENT_NAME.rs` - - add a new struct - - implement `abacus_base::AbacusAgent` for your struct - - your `run` function is the business logic of your agent -- create a new settings module `src/settings.rs` - - reuse the `Settings` objects from `abacus_base::settings` - - make sure to read the docs :) - - add your own new settings -- in `$AGENT_NAME/src/main.rs` - - add `mod _____` declarations for your agent and settings modules - - create `main` and `setup` functions - - follow the pattern in `abacus-base/src/main.rs` -- make a `config` folder and a toml file - - Make sure to include your own settings from above - ### Running Locally -See the guide [here](./running-locally.md) to run the agents locally. + +```bash +./rust/run-locally.sh +``` diff --git a/rust/abacus-base/Cargo.toml b/rust/abacus-base/Cargo.toml index 8cb981e7f..177a854c5 100644 --- a/rust/abacus-base/Cargo.toml +++ b/rust/abacus-base/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "abacus-base" version = "0.1.0" -authors = ["James Prestwich "] edition = "2021" @@ -53,7 +52,3 @@ color-eyre = "0.6" [features] oneline-eyre = [] - -[[example]] -name = "example" -path = "./bin/example.rs" diff --git a/rust/abacus-base/bin/example.rs b/rust/abacus-base/bin/example.rs deleted file mode 100644 index 35aaef2cc..000000000 --- a/rust/abacus-base/bin/example.rs +++ /dev/null @@ -1,42 +0,0 @@ -use color_eyre::Result; - -use abacus_base::{Agent, Settings}; - -/// An example main function for any agent that implemented Default -async fn _example_main(settings: Settings) -> Result<()> -where - OA: Agent + Sized + 'static, -{ - // Instantiate an agent - let oa = OA::from_settings(settings).await?; - oa.as_ref() - .settings - .tracing - .start_tracing(oa.metrics().span_duration())?; - - // Run the agent - oa.run_all(vec![]).await? -} - -/// Read settings from the config file and set up reporting and logging based -/// on the settings -#[allow(dead_code)] -fn setup() -> Result { - color_eyre::install()?; - - let settings = Settings::new()?; - - Ok(settings) -} - -#[allow(dead_code)] -fn main() -> Result<()> { - let _settings = setup()?; - // tokio::runtime::Builder::new_current_thread() - // .enable_all() - // .build() - // .unwrap() - // .block_on(_example_main(settings))?; - - Ok(()) -} diff --git a/rust/abacus-base/src/macros.rs b/rust/abacus-base/src/macros.rs index 0cf035951..cc48a9cbb 100644 --- a/rust/abacus-base/src/macros.rs +++ b/rust/abacus-base/src/macros.rs @@ -55,7 +55,7 @@ pub use paste; /// /// Please note that integers must be specified as `String` in order to allow /// them to be configured via env var. They must then be parsed in the -/// [`AbacusAgent::from_settings`](crate::agent::AbacusAgent::from_settings) +/// [`Agent::from_settings`](crate::agent::Agent::from_settings) /// method. /// /// ### Usage diff --git a/rust/tools/abacus-cli/Cargo.toml b/rust/abacus-cli/Cargo.toml similarity index 79% rename from rust/tools/abacus-cli/Cargo.toml rename to rust/abacus-cli/Cargo.toml index 3e39c21b4..1025499cc 100644 --- a/rust/tools/abacus-cli/Cargo.toml +++ b/rust/abacus-cli/Cargo.toml @@ -15,5 +15,5 @@ tokio = "1" serde_json = "1.0" structopt = "0.3.23" -abacus-ethereum = { path = "../../chains/abacus-ethereum" } -abacus-core = { path = "../../abacus-core" } +abacus-ethereum = { path = "../chains/abacus-ethereum" } +abacus-core = { path = "../abacus-core" } diff --git a/rust/tools/abacus-cli/README.md b/rust/abacus-cli/README.md similarity index 100% rename from rust/tools/abacus-cli/README.md rename to rust/abacus-cli/README.md diff --git a/rust/tools/abacus-cli/src/commands.rs b/rust/abacus-cli/src/commands.rs similarity index 100% rename from rust/tools/abacus-cli/src/commands.rs rename to rust/abacus-cli/src/commands.rs diff --git a/rust/tools/abacus-cli/src/inboxes.rs b/rust/abacus-cli/src/inboxes.rs similarity index 100% rename from rust/tools/abacus-cli/src/inboxes.rs rename to rust/abacus-cli/src/inboxes.rs diff --git a/rust/tools/abacus-cli/src/main.rs b/rust/abacus-cli/src/main.rs similarity index 100% rename from rust/tools/abacus-cli/src/main.rs rename to rust/abacus-cli/src/main.rs diff --git a/rust/tools/abacus-cli/src/rpc.rs b/rust/abacus-cli/src/rpc.rs similarity index 100% rename from rust/tools/abacus-cli/src/rpc.rs rename to rust/abacus-cli/src/rpc.rs diff --git a/rust/tools/abacus-cli/src/subcommands/mod.rs b/rust/abacus-cli/src/subcommands/mod.rs similarity index 100% rename from rust/tools/abacus-cli/src/subcommands/mod.rs rename to rust/abacus-cli/src/subcommands/mod.rs diff --git a/rust/tools/abacus-cli/src/subcommands/prove.rs b/rust/abacus-cli/src/subcommands/prove.rs similarity index 100% rename from rust/tools/abacus-cli/src/subcommands/prove.rs rename to rust/abacus-cli/src/subcommands/prove.rs diff --git a/rust/abacus-core/Cargo.toml b/rust/abacus-core/Cargo.toml index 122c87b8e..d5373ced6 100644 --- a/rust/abacus-core/Cargo.toml +++ b/rust/abacus-core/Cargo.toml @@ -31,15 +31,3 @@ color-eyre = "0.6" [features] output = [] - -[[bin]] -name = "proof_output" -path = "bin/proof_output.rs" - -[[bin]] -name = "lib_test_output" -path = "bin/lib_test_output.rs" - -[[bin]] -name = "utils_test_output" -path = "bin/utils_test_output.rs" diff --git a/rust/abacus-core/bin/lib_test_output.rs b/rust/abacus-core/bin/lib_test_output.rs deleted file mode 100644 index 30dad0b30..000000000 --- a/rust/abacus-core/bin/lib_test_output.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[cfg(feature = "output")] -use abacus_core::test_output::output_functions::*; - -fn main() { - #[cfg(feature = "output")] - { - output_signed_checkpoints(); - output_message_and_leaf(); - } -} diff --git a/rust/abacus-core/bin/proof_output.rs b/rust/abacus-core/bin/proof_output.rs deleted file mode 100644 index cf1558a40..000000000 --- a/rust/abacus-core/bin/proof_output.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[cfg(feature = "output")] -use abacus_core::test_output::output_functions::*; - -fn main() { - #[cfg(feature = "output")] - { - output_merkle_proof(); - } -} diff --git a/rust/abacus-core/bin/utils_test_output.rs b/rust/abacus-core/bin/utils_test_output.rs deleted file mode 100644 index 2d37a9d00..000000000 --- a/rust/abacus-core/bin/utils_test_output.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[cfg(feature = "output")] -use abacus_core::test_output::output_functions::*; - -fn main() { - #[cfg(feature = "output")] - { - output_domain_hashes(); - output_destination_and_nonces(); - } -} diff --git a/rust/abacus-test/Cargo.toml b/rust/abacus-test/Cargo.toml index 1fa4baace..7c9bd21de 100644 --- a/rust/abacus-test/Cargo.toml +++ b/rust/abacus-test/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "abacus-test" version = "0.1.0" -authors = ["Luke Tchang "] edition = "2021" [dependencies] diff --git a/rust/agents/checkpointer/Cargo.toml b/rust/agents/checkpointer/Cargo.toml deleted file mode 100644 index 8ead557d7..000000000 --- a/rust/agents/checkpointer/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "checkpointer" -version = "0.1.0" -authors = ["Abacus Team"] -edition = "2021" - -[dependencies] -tokio = { version = "1", features = ["rt", "macros"] } -config = "0.10" -serde = "1.0" -serde_json = { version = "1.0", default-features = false } -ethers = { git = "https://github.com/gakonst/ethers-rs", branch = "master" } -thiserror = { version = "1.0.22", default-features = false } -async-trait = { version = "0.1.42", default-features = false } -futures-util = "0.3.12" -eyre = "0.6" -color-eyre = { version = "0.6", optional = true } -tracing = "0.1" -tracing-futures = "0.2" -tracing-subscriber = "0.3" -rocksdb = { git = "https://github.com/rust-rocksdb/rust-rocksdb" } - -abacus-core = { path = "../../abacus-core" } -abacus-base = { path = "../../abacus-base" } -abacus-ethereum = { path = "../../chains/abacus-ethereum" } - -[dev-dependencies] -tokio-test = "0.4" -abacus-test = { path = "../../abacus-test" } -prometheus = "0.12" - -[features] -default = ["color-eyre"] -oneline-errors = ["abacus-base/oneline-eyre"] diff --git a/rust/agents/checkpointer/src/checkpointer.rs b/rust/agents/checkpointer/src/checkpointer.rs deleted file mode 100644 index e897c13c0..000000000 --- a/rust/agents/checkpointer/src/checkpointer.rs +++ /dev/null @@ -1,74 +0,0 @@ -use async_trait::async_trait; -use eyre::Result; -use tokio::task::JoinHandle; -use tracing::instrument::Instrumented; - -use abacus_base::{AbacusAgentCore, Agent}; - -use crate::{settings::CheckpointerSettings as Settings, submit::CheckpointSubmitter}; - -/// A checkpointer agent -#[derive(Debug)] -pub struct Checkpointer { - /// The polling interval (in seconds) - polling_interval: u64, - /// The minimum period between created checkpoints (in seconds) - creation_latency: u64, - pub(crate) core: AbacusAgentCore, -} - -impl AsRef for Checkpointer { - fn as_ref(&self) -> &AbacusAgentCore { - &self.core - } -} - -impl Checkpointer { - /// Instantiate a new checkpointer - pub fn new(polling_interval: u64, creation_latency: u64, core: AbacusAgentCore) -> Self { - Self { - polling_interval, - creation_latency, - core, - } - } -} - -#[async_trait] -impl Agent for Checkpointer { - const AGENT_NAME: &'static str = "checkpointer"; - - type Settings = Settings; - - async fn from_settings(settings: Self::Settings) -> Result - where - Self: Sized, - { - let polling_interval = settings - .pollinginterval - .parse() - .expect("invalid pollinginterval uint"); - let creation_latency = settings - .creationlatency - .parse() - .expect("invalid creationlatency uint"); - let core = settings - .as_ref() - .try_into_abacus_core(Self::AGENT_NAME) - .await?; - Ok(Self::new(polling_interval, creation_latency, core)) - } -} - -impl Checkpointer { - pub fn run(&self) -> Instrumented>> { - let outbox = self.outbox(); - - let submit = CheckpointSubmitter::new(outbox, self.polling_interval, self.creation_latency); - - self.run_all(vec![submit.spawn()]) - } -} - -#[cfg(test)] -mod test {} diff --git a/rust/agents/checkpointer/src/main.rs b/rust/agents/checkpointer/src/main.rs deleted file mode 100644 index a1244c99c..000000000 --- a/rust/agents/checkpointer/src/main.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! The checkpointer observes the Outbox contract and calls checkpoint. - -#![forbid(unsafe_code)] -#![warn(missing_docs)] -#![warn(unused_extern_crates)] - -use eyre::Result; - -use abacus_base::Agent; - -use crate::{checkpointer::Checkpointer, settings::CheckpointerSettings as Settings}; - -mod checkpointer; -mod settings; -mod submit; - -async fn _main() -> Result<()> { - #[cfg(feature = "oneline-errors")] - abacus_base::oneline_eyre::install()?; - #[cfg(not(feature = "oneline-errors"))] - color_eyre::install()?; - - let settings = Settings::new()?; - - let agent = Checkpointer::from_settings(settings).await?; - - agent - .as_ref() - .settings - .tracing - .start_tracing(agent.metrics().span_duration())?; - let _ = agent.metrics().run_http_server(); - - agent.run().await??; - Ok(()) -} - -fn main() -> Result<()> { - tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap() - .block_on(_main()) -} diff --git a/rust/agents/checkpointer/src/settings.rs b/rust/agents/checkpointer/src/settings.rs deleted file mode 100644 index cc95c78bc..000000000 --- a/rust/agents/checkpointer/src/settings.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Configuration - -use abacus_base::decl_settings; - -decl_settings!(Checkpointer { - /// The polling interval (in seconds) - pollinginterval: String, - /// The minimum period between submitted checkpoints (in seconds) - creationlatency: String, -}); diff --git a/rust/agents/checkpointer/src/submit.rs b/rust/agents/checkpointer/src/submit.rs deleted file mode 100644 index 694479cbc..000000000 --- a/rust/agents/checkpointer/src/submit.rs +++ /dev/null @@ -1,65 +0,0 @@ -use std::{sync::Arc, time::Duration}; - -use eyre::Result; -use tokio::{task::JoinHandle, time::sleep}; -use tracing::{debug, info, info_span, instrument::Instrumented, Instrument}; - -use abacus_base::CachingOutbox; -use abacus_core::{AbacusCommon, Checkpoint, Outbox}; - -pub(crate) struct CheckpointSubmitter { - outbox: Arc, - /// The polling interval - polling_interval: Duration, - /// The minimum period between submitted checkpoints - creation_latency: Duration, -} - -impl CheckpointSubmitter { - pub(crate) fn new( - outbox: Arc, - polling_interval: u64, - creation_latency: u64, - ) -> Self { - Self { - outbox, - polling_interval: Duration::from_secs(polling_interval), - creation_latency: Duration::from_secs(creation_latency), - } - } - - pub(crate) fn spawn(self) -> Instrumented>> { - let span = info_span!("CheckpointSubmitter"); - - tokio::spawn(async move { - loop { - sleep(self.polling_interval).await; - - // Check the latest checkpointed index - let Checkpoint { - index: latest_checkpoint_index, - .. - } = self.outbox.latest_checkpoint(None).await?; - // Get the current count of the tree - let count = self.outbox.count().await?; - - info!( - latest_checkpoint_index=?latest_checkpoint_index, - count=?count, - "Got latest checkpoint and count" - ); - // If there are any new messages, the count will be greater than - // the latest checkpoint index + 1. Don't checkpoint for count < 2 - // since checkpoints with index 0 are disallowed - if count > latest_checkpoint_index + 1 && count > 1 { - debug!("Creating checkpoint"); - self.outbox.create_checkpoint().await?; - // Sleep to ensure that another checkpoint isn't made until - // creation_latency has passed - sleep(self.creation_latency).await; - } - } - }) - .instrument(span) - } -} diff --git a/rust/agents/kathy/Cargo.toml b/rust/agents/kathy/Cargo.toml index a6b53a6c7..799d0d068 100644 --- a/rust/agents/kathy/Cargo.toml +++ b/rust/agents/kathy/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "kathy" version = "0.1.0" -authors = ["James Prestwich "] edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/rust/agents/relayer/Cargo.toml b/rust/agents/relayer/Cargo.toml index f212068f8..cbc09b236 100644 --- a/rust/agents/relayer/Cargo.toml +++ b/rust/agents/relayer/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "relayer" version = "0.1.0" -authors = ["ltchang "] edition = "2021" [dependencies] diff --git a/rust/agents/validator/Cargo.toml b/rust/agents/validator/Cargo.toml index 7ff3c8c6e..0bf0d9ff0 100644 --- a/rust/agents/validator/Cargo.toml +++ b/rust/agents/validator/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "validator" version = "0.1.0" -authors = ["Abacus Team"] edition = "2021" [dependencies] diff --git a/rust/chains/abacus-ethereum/Cargo.toml b/rust/chains/abacus-ethereum/Cargo.toml index 1a323d3d6..cd21699af 100644 --- a/rust/chains/abacus-ethereum/Cargo.toml +++ b/rust/chains/abacus-ethereum/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "abacus-ethereum" version = "0.1.0" -authors = ["Erin Hales "] edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/rust/release.sh b/rust/release.sh deleted file mode 100755 index 0105a8340..000000000 --- a/rust/release.sh +++ /dev/null @@ -1 +0,0 @@ -docker push gcr.io/clabs-optics/optics-agent:$1 \ No newline at end of file diff --git a/rust/tools/balance-exporter/Cargo.toml b/rust/tools/balance-exporter/Cargo.toml deleted file mode 100644 index b274740c6..000000000 --- a/rust/tools/balance-exporter/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "balance-exporter" -version = "0.1.0" -edition = "2021" -description = "Polls chains for optics contract wallet balances and reports them in OpenMetrics format" -authors = ["ember arlynx "] -license = "Apache-2.0" - -[dependencies] -tokio = "1" -futures = "0.3" - -metrics = "0.18" -serde_json = "1.0" -serde = "1.0" -color-eyre = "0.6" -clap = { version = "3.1", features = ["cargo", "derive"] } -human-panic = "1.0" - -abacus-base = { path = "../../abacus-base" } - -# SMELL: reaching into the implementation details. abstract eventually. -abacus-ethereum = { path = "../../chains/abacus-ethereum" } diff --git a/rust/tools/balance-exporter/src/main.rs b/rust/tools/balance-exporter/src/main.rs deleted file mode 100644 index a9a41572d..000000000 --- a/rust/tools/balance-exporter/src/main.rs +++ /dev/null @@ -1,161 +0,0 @@ -use std::{path::PathBuf, time::Duration}; - -use abacus_base::ChainSetup; -use clap::Arg; -use color_eyre::eyre::anyhow; -use futures::StreamExt; -use human_panic::setup_panic; -use tokio::time::Instant; - -#[derive(serde::Deserialize, Debug)] -struct Contract(String); - -#[derive(serde::Deserialize, Debug)] -struct Input { - contracts: Vec>, -} - -struct Sample { - balances: Vec>, -} - -async fn poll_once(input: &Input, timeout: Duration) -> Sample { - // does this open a new ws connection for each query? probably. - let (send, mut recv) = tokio::sync::mpsc::unbounded_channel(); - - // moves `send` into the subtask executor. by the time it is complete, - // `recv` will complete to exhaustion, due to `send` clones being dropped - futures::stream::iter( - input - .contracts - .iter() - .enumerate() - .zip(std::iter::repeat(send)), - ) - .for_each_concurrent(None, |((ix, _cs), send)| async move { - let sub_result = - tokio::time::timeout(timeout, std::future::ready(Err(anyhow!("WIP")))).await; - send.send((ix, sub_result)) - .expect("channel closed before we're done?"); - }) - .await; - - let mut balances: Vec>> = - input.contracts.iter().map(|_| None).collect(); - - while let Some((ix, sub_result)) = recv.recv().await { - match sub_result { - Ok(Ok(v)) => balances[ix] = Some(Ok(v)), - Ok(Err(e)) => balances[ix] = Some(Err(e)), - Err(_) => balances[ix] = Some(Err(anyhow!("timeout expired"))), - } - } - - assert!(balances.iter().all(Option::is_some)); - - Sample { - balances: balances.into_iter().map(Option::unwrap).collect(), - } -} - -#[tokio::main] -async fn main() -> color_eyre::Result<()> { - setup_panic!(); - color_eyre::install()?; - - let args = clap::command!() - .arg( - Arg::new("polling-interval") - .validator(|s| { - str::parse::(s).map_err(|_| anyhow!("polling interval must be u64!")) - }) - .help("Minimum number of seconds to wait between poll attempts") - .default_value("120"), - ) - .arg( - Arg::new("stdin") - .help("Read configuration JSON from stdin") - .required_unless_present("file"), - ) - .arg( - Arg::new("file") - .takes_value(true) - .help("Path to configuration JSON file"), - ) - .get_matches(); - - eprintln!("Hello, world!"); - - eprintln!("You asked me to do this: {:?}", args); - - eprintln!("Loading up the input..."); - - let setup: Input = if !args.is_present("stdin") { - serde_json::from_reader(std::fs::File::open(PathBuf::from( - args.value_of_os("file").expect("malformed --file"), - ))?)? - } else { - serde_json::from_reader(std::io::stdin())? - }; - - let interval = Duration::from_secs( - args.value_of_t("polling-interval") - .expect("malformed --polling-interval"), - ); - - println!("Going to start exporting these:"); - setup.contracts.iter().for_each(|s| println!("\t {:?}", s)); - - loop { - let start = Instant::now(); - let results = poll_once(&setup, interval).await; - - for (ix, res) in results.balances.into_iter().enumerate() { - let ChainSetup { - name: network, - addresses, - .. - } = &setup.contracts[ix]; - match res { - Ok(s) => { - // TODO: export metric - println!("{} {} = {}", network, addresses.0, s); - } - Err(e) => { - eprintln!("Error while querying {:?}: {}", setup.contracts[ix], e); - } - } - } - - tokio::time::sleep_until(start + interval).await; - } -} - -impl Sample { - #[allow(dead_code)] - fn record(_m: impl metrics::Recorder) {} -} - -#[tokio::test] -#[should_panic] -async fn mainnet_works() { - // query ethereum instance of AbacusConnectionManager and asserts the balance is nonzero. - let sample = poll_once( - &Input { - contracts: vec![ChainSetup { - name: "ethereum".into(), - domain: "6648936".into(), - // i would love for this to just be ChainConf::ethereum() - chain: abacus_base::chains::ChainConf::Ethereum(abacus_ethereum::Connection::Ws { - url: "wss://main-light.eth.linkpool.io/ws".into(), - }), - addresses: Contract("0xcEc158A719d11005Bd9339865965bed938BEafA3".into()), - disabled: None, - }], - }, - Duration::from_secs(120), - ) - .await; - let only_balance = sample.balances[0].as_ref(); - assert!(only_balance.expect("failed to query chain!") != "0"); -} diff --git a/rust/tools/kms-cli/Cargo.toml b/rust/tools/kms-cli/Cargo.toml deleted file mode 100644 index f238ee460..000000000 --- a/rust/tools/kms-cli/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "kms-cli" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -clap = "3.0.0-beta.5" -color-eyre = "0.6" -ethers = { git = "https://github.com/gakonst/ethers-rs", branch = "master" } -ethers-signers = { git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["aws"] } -hex = "0.4.3" -once_cell = "1.8.0" -rusoto_core = "0.47.0" -rusoto_kms = "0.47.0" -tokio = "1" -serde_json = "1.0" diff --git a/rust/tools/kms-cli/src/main.rs b/rust/tools/kms-cli/src/main.rs deleted file mode 100644 index 71258d455..000000000 --- a/rust/tools/kms-cli/src/main.rs +++ /dev/null @@ -1,218 +0,0 @@ -use std::convert::TryFrom; - -use color_eyre::Result; - -use ethers::{ - core::types::{transaction::eip2718::TypedTransaction, Address, TransactionRequest, U256}, - providers::{Http, Middleware, Provider}, - signers::{AwsSigner, Signer}, -}; -use once_cell::sync::OnceCell; -use rusoto_core::{credential::EnvironmentProvider, HttpClient}; -use rusoto_kms::KmsClient; - -use clap::Parser; - -static KMS_CLIENT: OnceCell = OnceCell::new(); - -fn init_kms(region: String) { - let client = - rusoto_core::Client::new_with(EnvironmentProvider::default(), HttpClient::new().unwrap()); - if KMS_CLIENT - .set(KmsClient::new_with_client( - client, - region.parse().expect("invalid region"), - )) - .is_err() - { - panic!("couldn't set cell") - } -} - -#[derive(Parser)] -pub struct Tx { - // TX - /// The TX value (in wei) - #[clap(short, long)] - value: Option, - /// The TX nonce (pulled from RPC if omitted) - #[clap(long)] - nonce: Option, - /// The TX gas price (pulled from RPC if omitted) - #[clap(long)] - gas_price: Option, - /// The TX gas limit (estimated from RPC if omitted) - #[clap(long)] - gas: Option, - /// The TX data body (omit for simple sends) - #[clap(short, long)] - data: Option, - /// The recipient/contract address - #[clap(short, long)] - to: Address, - /// The chain_id. see https://chainlist.org - #[clap(short, long)] - chain_id: Option, - - // RPC - /// RPC connection details - #[clap(long)] - rpc: String, -} - -#[derive(Parser)] -pub struct Info {} - -#[derive(Parser)] -/// Subcommands -#[allow(clippy::large_enum_variant)] -pub enum SubCommands { - /// Send a tx signed by the KMS key - Transaction(Tx), - /// Print the key info (region, id, address) - Info(Info), -} - -#[derive(Parser)] -#[clap(version = "0.1", author = "James Prestwich")] -pub struct Opts { - #[clap(subcommand)] - sub: SubCommands, - - // AWS - /// AWS Key ID - #[clap(short, long)] - key_id: String, - /// AWS Region string - #[clap(long)] - region: String, - - // Behavior - /// Print the tx req and signature instead of broadcasting - #[clap(short, long)] - print_only: bool, -} - -macro_rules! apply_if { - ($tx_req:ident, $method:ident, $prop:expr) => {{ - if let Some(prop) = $prop { - $tx_req.$method(prop) - } else { - $tx_req - } - }}; - - ($tx_req:ident, $opts:ident.$prop:ident) => {{ - let prop = $opts.$prop; - apply_if!($tx_req, $prop, prop) - }}; -} - -fn prep_tx_request(opts: &Tx) -> TransactionRequest { - let tx_req = TransactionRequest::default().to(opts.to); - - // These swallow parse errors - let tx_req = apply_if!( - tx_req, - data, - opts.data.clone().and_then(|data| hex::decode(&data).ok()) - ); - let tx_req = apply_if!( - tx_req, - value, - opts.value - .clone() - .and_then(|value| U256::from_dec_str(&value).ok()) - ); - - let tx_req = apply_if!(tx_req, opts.nonce); - let tx_req = apply_if!(tx_req, opts.gas); - - let data = opts - .data - .clone() - .and_then(|s| hex::decode(s).ok()) - .unwrap_or_default(); - - let tx_req = tx_req.data(data); - - apply_if!(tx_req, opts.gas_price) -} - -async fn _send_tx(signer: &AwsSigner<'_>, opts: &Opts) -> Result<()> { - let tx: &Tx = match opts.sub { - SubCommands::Transaction(ref tx) => tx, - SubCommands::Info(_) => unreachable!(), - }; - - let provider = Provider::::try_from(tx.rpc.clone())?; - - let tx_req = prep_tx_request(tx); - - let mut typed_tx: TypedTransaction = tx_req.clone().into(); - typed_tx.set_from(signer.address()); - typed_tx.set_nonce( - provider - .get_transaction_count(signer.address(), None) - .await?, - ); - - // TODO: remove this these ethers is fixed - typed_tx.set_gas(21000); - typed_tx.set_gas_price(20_000_000_000u64); // 20 gwei - typed_tx.set_chain_id(signer.chain_id()); - - let sig = signer.sign_transaction(&typed_tx).await?; - - let rlp = typed_tx.rlp_signed(&sig); - println!( - "Tx request details:\n{}", - serde_json::to_string_pretty(&typed_tx)? - ); - - println!("\nSigned Tx:\n 0x{}", hex::encode(&rlp)); - if !opts.print_only { - let res = provider.send_raw_transaction(rlp).await?; - println!("Broadcast tx with hash {:?}", *res); - println!("Awaiting confirmation. Ctrl+c to exit"); - dbg!(res.await?); - } - - Ok(()) -} - -async fn _print_info(signer: &AwsSigner<'_>, opts: &Opts) -> Result<()> { - println!("Key ID: {}", opts.key_id); - println!("Region: {}", opts.region); - println!("Address: {}", signer.address()); - - Ok(()) -} - -async fn _main() -> Result<()> { - let opts: Opts = Opts::parse(); - init_kms(opts.region.to_owned()); - let chain_id = match opts.sub { - SubCommands::Transaction(ref tx) => tx.chain_id.unwrap_or(1), - SubCommands::Info(_) => 1, - }; - - let signer = AwsSigner::new(KMS_CLIENT.get().unwrap(), opts.key_id.clone(), 0) - .await? - .with_chain_id(chain_id); - - match opts.sub { - SubCommands::Transaction(_) => _send_tx(&signer, &opts).await, - SubCommands::Info(_) => _print_info(&signer, &opts).await, - } -} - -fn main() -> Result<()> { - color_eyre::install()?; - - tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap() - .block_on(_main()) -}