Misc. agent cleanup and dead code deletion (#470)

* Fix path to agent::Agent in comment.

Otherwise `cargo doc` emits a rustdoc::broken_intra_doc_links warning.

* Use automatic link in comment for rustdoc.

Otherwise 'cargo doc' emits a warning.

* Delete checkpointer agent.

It is not used in current deployment.

* Delete kms-cli.

Not used in current deployment (no references).

* Include "--all" in precommit cargo fmt -- --check invocation.

* Delete unused and hidden src/bin programs.

These appear to have been introduced over a year ago and appear to be dead
code now.

Unhide them from vscode workspace too -- since they were hidden, automated
refactoring tools wouldn't find them until compiler failed.

* Update github CODEOWNERS to current Abacus team.

Drop optional authors field from Cargo.tomls.

* Drop processordb from .gitignore.

Processor crate has been deleted.

* Delete balance-exporter crate.

It is not used / no references.

* Hoist abacus-cli into its own top-level crate.

It is the only tool now, no reason to hide it inside
of a tools directory.

* Delete old relaese.sh, which only relates to Celo Optics.

* Cleanup top-level rust README.md.

-  Architecture paragraphs outdated, delete.
-  Point to run-locally.sh instead of documentation.

* Explain a bit more about crate deps in README.

* Dockerfile fix after tools directory restructuring.

We had previously hoisted abacus-cli out since it
was the only remaining tool.

* Fix path to agent::Agent in comment.

Otherwise `cargo doc` emits a rustdoc::broken_intra_doc_links warning.

* Use automatic link in coment for rustdoc.

Otherwise 'cargo doc' emits a warning.

* Delete checkpointer agent.

It is not used in current deployment.

* Delete kms-cli.

Not used in current deployment (no references).

* Include "--all" in precommit cargo fmt -- --check invocation.

* Delete unused and hidden src/bin programs.

These appear to have been introduced over a year ago and appear to be dead
code now.

Unhide them from vscode workspace too -- since they were hidden, automated
refactoring tools wouldn't find them until compiler failed.

* Update github CODEOWNERS to current Abacus team.

Drop optional authors field from Cargo.tomls.

* Drop processordb from .gitignore.

Processor crate has been deleted.

* Delete balance-exporter crate.

It is not used / no references.

* Hoist abacus-cli into its own top-level crate.

It is the only tool now, no reason to hide it inside
of a tools directory.

* Delete old relaese.sh, which only relates to Celo Optics.

* Cleanup top-level rust README.md.

-  Architecture paragraphs outdated, delete.
-  Point to run-locally.sh instead of documentation.

* Explain a bit more about crate deps in README.

* Dockerfile fix after tools directory restructuring.

We had previously hoisted abacus-cli out since it
was the only remaining tool.
pull/498/head
webbhorn 3 years ago committed by GitHub
parent 87ee40ec3d
commit 6b3822f664
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .github/CODEOWNERS
  2. 2
      .github/workflows/rust.yml
  3. 1
      rust/.gitignore
  4. 1
      rust/.vscode/settings.json
  5. 219
      rust/Cargo.lock
  6. 5
      rust/Cargo.toml
  7. 4
      rust/Dockerfile
  8. 62
      rust/README.md
  9. 5
      rust/abacus-base/Cargo.toml
  10. 42
      rust/abacus-base/bin/example.rs
  11. 2
      rust/abacus-base/src/macros.rs
  12. 4
      rust/abacus-cli/Cargo.toml
  13. 0
      rust/abacus-cli/README.md
  14. 0
      rust/abacus-cli/src/commands.rs
  15. 0
      rust/abacus-cli/src/inboxes.rs
  16. 0
      rust/abacus-cli/src/main.rs
  17. 0
      rust/abacus-cli/src/rpc.rs
  18. 0
      rust/abacus-cli/src/subcommands/mod.rs
  19. 0
      rust/abacus-cli/src/subcommands/prove.rs
  20. 12
      rust/abacus-core/Cargo.toml
  21. 10
      rust/abacus-core/bin/lib_test_output.rs
  22. 9
      rust/abacus-core/bin/proof_output.rs
  23. 10
      rust/abacus-core/bin/utils_test_output.rs
  24. 1
      rust/abacus-test/Cargo.toml
  25. 34
      rust/agents/checkpointer/Cargo.toml
  26. 74
      rust/agents/checkpointer/src/checkpointer.rs
  27. 44
      rust/agents/checkpointer/src/main.rs
  28. 10
      rust/agents/checkpointer/src/settings.rs
  29. 65
      rust/agents/checkpointer/src/submit.rs
  30. 1
      rust/agents/kathy/Cargo.toml
  31. 1
      rust/agents/relayer/Cargo.toml
  32. 1
      rust/agents/validator/Cargo.toml
  33. 1
      rust/chains/abacus-ethereum/Cargo.toml
  34. 1
      rust/release.sh
  35. 23
      rust/tools/balance-exporter/Cargo.toml
  36. 161
      rust/tools/balance-exporter/src/main.rs
  37. 18
      rust/tools/kms-cli/Cargo.toml
  38. 218
      rust/tools/kms-cli/src/main.rs

@ -1,2 +1 @@
* @prestwich @anna-carroll @erinhales
rust/ @prestwich @emberian @ltchang
* @asaj @mattiecnvr @nambrot @tkporter @webbhorn @yorhodes @zmanian

@ -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

1
rust/.gitignore vendored

@ -1,5 +1,4 @@
target
processordb
validatordb
relayerdb
kathydb

@ -1,6 +1,5 @@
{
"files.exclude": {
"target": true,
"**/bin": true,
},
}

219
rust/Cargo.lock generated

@ -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"

@ -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"
]

@ -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

@ -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
```

@ -1,7 +1,6 @@
[package]
name = "abacus-base"
version = "0.1.0"
authors = ["James Prestwich <prestwich@clabs.co>"]
edition = "2021"
@ -53,7 +52,3 @@ color-eyre = "0.6"
[features]
oneline-eyre = []
[[example]]
name = "example"
path = "./bin/example.rs"

@ -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<OA>(settings: Settings) -> Result<()>
where
OA: Agent<Settings = Settings> + 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<Settings> {
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(())
}

@ -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

@ -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" }

@ -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"

@ -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();
}
}

@ -1,9 +0,0 @@
#[cfg(feature = "output")]
use abacus_core::test_output::output_functions::*;
fn main() {
#[cfg(feature = "output")]
{
output_merkle_proof();
}
}

@ -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();
}
}

@ -1,7 +1,6 @@
[package]
name = "abacus-test"
version = "0.1.0"
authors = ["Luke Tchang <ltchang@stanford.edu>"]
edition = "2021"
[dependencies]

@ -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"]

@ -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<AbacusAgentCore> 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<Self>
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<JoinHandle<Result<()>>> {
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 {}

@ -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())
}

@ -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,
});

@ -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<CachingOutbox>,
/// The polling interval
polling_interval: Duration,
/// The minimum period between submitted checkpoints
creation_latency: Duration,
}
impl CheckpointSubmitter {
pub(crate) fn new(
outbox: Arc<CachingOutbox>,
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<JoinHandle<Result<()>>> {
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)
}
}

@ -1,7 +1,6 @@
[package]
name = "kathy"
version = "0.1.0"
authors = ["James Prestwich <james@prestwi.ch>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,7 +1,6 @@
[package]
name = "relayer"
version = "0.1.0"
authors = ["ltchang <ltchang@stanford.edu>"]
edition = "2021"
[dependencies]

@ -1,7 +1,6 @@
[package]
name = "validator"
version = "0.1.0"
authors = ["Abacus Team"]
edition = "2021"
[dependencies]

@ -1,7 +1,6 @@
[package]
name = "abacus-ethereum"
version = "0.1.0"
authors = ["Erin Hales <mcbridee093@gmail.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1 +0,0 @@
docker push gcr.io/clabs-optics/optics-agent:$1

@ -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 <ember.arlynx@clabs.co>"]
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" }

@ -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<ChainSetup<Contract>>,
}
struct Sample {
balances: Vec<color_eyre::Result<String>>,
}
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<Option<color_eyre::Result<String>>> =
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::<u64>(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");
}

@ -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"

@ -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<KmsClient> = 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<String>,
/// The TX nonce (pulled from RPC if omitted)
#[clap(long)]
nonce: Option<U256>,
/// The TX gas price (pulled from RPC if omitted)
#[clap(long)]
gas_price: Option<U256>,
/// The TX gas limit (estimated from RPC if omitted)
#[clap(long)]
gas: Option<U256>,
/// The TX data body (omit for simple sends)
#[clap(short, long)]
data: Option<String>,
/// The recipient/contract address
#[clap(short, long)]
to: Address,
/// The chain_id. see https://chainlist.org
#[clap(short, long)]
chain_id: Option<u64>,
// 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::<Http>::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())
}
Loading…
Cancel
Save