Skip to content

Commit

Permalink
Implement gorc orchestrator (#74)
Browse files Browse the repository at this point in the history
* wip: scaffolding for `gorc orchestrator start`

* wip: centralize loading deep_space private keys

* wip: centralize loading clarity private keys

* gorc orchestrator start; parse gravity contract

* gorc orchestrator start; read fees_denom from config

* gorc orchestrator start that might even work (about to prove with integration tests)

* cleanup warnings

* gorc: abscissa_tokio::run_with_actix

* make gorc a default member too
  • Loading branch information
levicook authored Jul 19, 2021
1 parent 577319e commit 2102174
Show file tree
Hide file tree
Showing 17 changed files with 184 additions and 179 deletions.
8 changes: 6 additions & 2 deletions orchestrator/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 orchestrator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
default-members = ["gorc", "orchestrator", "test_runner"]
members = [
"orchestrator",
"cosmos_gravity",
Expand All @@ -12,4 +13,3 @@ members = [
"register_delegate_keys",
"gorc",
]
default-members = ["orchestrator", "test_runner"]
10 changes: 7 additions & 3 deletions orchestrator/gorc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ serde = { version = "1", features = ["serde_derive"] }
thiserror = "1"
regex = "1.5.4"

ethereum_gravity = { path = "../ethereum_gravity" }
cosmos_gravity = { path = "../cosmos_gravity" }
ethereum_gravity = { path = "../ethereum_gravity" }
gravity_proto = { path = "../gravity_proto" }
gravity_utils = { path = "../gravity_utils" }
gravity_proto = { path = "../gravity_proto/" }
orchestrator = { path = "../orchestrator" }
relayer = { path = "../relayer" }

deep_space = "2.4.3"
clarity = "0.4.12"
actix-rt = "2.2"
Expand All @@ -24,9 +27,10 @@ pkcs8 = { version = "0.7", features = ["pem"] }
signatory = "0.23.0-pre"
rand_core = { version = "0.6", features = ["std"] }

abscissa_tokio = "0.6.0-pre.1"
abscissa_tokio = { version = "0.6.0-pre.2", features = ["actix"] }
web30 = "0.14"
tokio = "1"
tonic = "0.4"

[dependencies.abscissa_core]
version = "0.6.0-pre.1"
Expand Down
1 change: 1 addition & 0 deletions orchestrator/gorc/gorc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ keystore = "/tmp/keystore"

[gravity]
contract = "0x6b175474e89094c44da98b954eedeac495271d0f"
fees_denom = "stake"

[ethereum]
key_derivation_path = "m/44'/60'/0'/0/0"
Expand Down
2 changes: 1 addition & 1 deletion orchestrator/gorc/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,4 @@ impl Application for GorcApp {
trace::Config::default()
}
}
}
}
28 changes: 13 additions & 15 deletions orchestrator/gorc/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@
mod deploy;
mod keys;
mod orchestrator;
mod query;
mod start;
mod tests;
mod tx;
mod version;

use self::{
keys::KeysCmd, query::QueryCmd, start::StartCmd, tests::TestsCmd, tx::TxCmd,
keys::KeysCmd, orchestrator::OrchestratorCmd, query::QueryCmd, tests::TestsCmd, tx::TxCmd,
version::VersionCmd,
};
use crate::config::GorcConfig;
use abscissa_core::{
Command, Configurable, Help, Options, Runnable,
};
use abscissa_core::{Command, Configurable, Help, Options, Runnable};
use std::path::PathBuf;

/// Gorc Configuration Filename
Expand All @@ -34,23 +32,23 @@ pub const CONFIG_FILE: &str = "gorc.toml";
/// Gorc Subcommands
#[derive(Command, Debug, Options, Runnable)]
pub enum GorcCmd {
#[options(help = "create transactions on either ethereum or cosmos chains")]
Tx(TxCmd),
#[options(help = "get usage information")]
Help(Help<Self>),

#[options(help = "key management commands")]
Keys(KeysCmd),

#[options(help = "orchestrator")]
Orchestrator(OrchestratorCmd),

#[options(help = "query state on either ethereum or cosmos chains")]
Query(QueryCmd),

#[options(help = "run tests against configured chains")]
Tests(TestsCmd),

#[options(help = "start the application")]
Start(StartCmd),

#[options(help = "key management commands")]
Keys(KeysCmd),

#[options(help = "get usage information")]
Help(Help<Self>),
#[options(help = "create transactions on either ethereum or cosmos chains")]
Tx(TxCmd),

#[options(help = "display version information")]
Version(VersionCmd),
Expand Down
2 changes: 1 addition & 1 deletion orchestrator/gorc/src/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use clarity::Address as EthAddress;
use clarity::PrivateKey as EthPrivateKey;
use ethereum_gravity::deploy_erc20::deploy_erc20;
use gravity_proto::gravity::DenomToErc20Request;
use gravity_utils::connection_prep::{create_rpc_connections};
use gravity_utils::connection_prep::create_rpc_connections;
use std::time::Instant;
use std::{process::exit, time::Duration};
use tokio::time::sleep as delay_for;
Expand Down
2 changes: 0 additions & 2 deletions orchestrator/gorc/src/commands/keys.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//! `keys` subcommand
mod cosmos;
mod eth;

Expand Down
20 changes: 2 additions & 18 deletions orchestrator/gorc/src/commands/keys/cosmos/show.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
use crate::application::APP;
use abscissa_core::{Application, Command, Options, Runnable};
use deep_space;
use signatory::FsKeyStore;
use std::path::Path;

#[derive(Command, Debug, Default, Options)]
pub struct ShowCosmosKeyCmd {
#[options(free, help = "delete [name]")]
#[options(free, help = "show [name]")]
pub args: Vec<String>,
}

// Entry point for `gorc keys cosmos show [name]`
impl Runnable for ShowCosmosKeyCmd {
fn run(&self) {
let config = APP.config();
let keystore = Path::new(&config.keystore);
let keystore = FsKeyStore::create_or_open(keystore).unwrap();
let name = self.args.get(0).expect("name is required");
let name = name.parse().expect("Could not parse name");

let key = keystore.load(&name).expect("Could not load key");
let key = key
.to_pem()
.parse::<k256::elliptic_curve::SecretKey<k256::Secp256k1>>()
.expect("Could not parse key");

let key = deep_space::utils::bytes_to_hex_str(&key.to_bytes());
let key = key
.parse::<deep_space::private_key::PrivateKey>()
.expect("Could not parse private key");
let key = config.load_deep_space_key(name.clone());

let address = key
.to_address(config.cosmos.prefix.trim())
Expand Down
16 changes: 1 addition & 15 deletions orchestrator/gorc/src/commands/keys/eth/show.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::application::APP;
use abscissa_core::{Application, Command, Options, Runnable};
use clarity;
use signatory::FsKeyStore;
use std::path;

#[derive(Command, Debug, Default, Options)]
pub struct ShowEthKeyCmd {
Expand All @@ -14,19 +11,8 @@ pub struct ShowEthKeyCmd {
impl Runnable for ShowEthKeyCmd {
fn run(&self) {
let config = APP.config();
let keystore = path::Path::new(&config.keystore);
let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore");

let name = self.args.get(0).expect("name is required");
let name = name.parse().expect("Could not parse name");

let key = keystore.load(&name).expect("Could not load key");
let key = key
.to_pem()
.parse::<k256::elliptic_curve::SecretKey<k256::Secp256k1>>()
.expect("Could not parse key");

let key = clarity::PrivateKey::from_slice(&key.to_bytes()).expect("Could not convert key");
let key = config.load_clarity_key(name.clone());

let pub_key = key.to_public_key().expect("Could not build public key");

Expand Down
16 changes: 16 additions & 0 deletions orchestrator/gorc/src/commands/orchestrator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
mod start;

use abscissa_core::{Command, Options, Runnable};

/// `orchestator` subcommand
///
/// The `Options` proc macro generates an option parser based on the struct
/// definition, and is defined in the `gumdrop` crate. See their documentation
/// for a more comprehensive example:
///
/// <https://docs.rs/gumdrop/>
#[derive(Command, Debug, Options, Runnable)]
pub enum OrchestratorCmd {
#[options(name = "start")]
Start(start::StartCommand),
}
98 changes: 98 additions & 0 deletions orchestrator/gorc/src/commands/orchestrator/start.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use crate::{application::APP, prelude::*};
use abscissa_core::{Command, Options, Runnable};
use clarity::address::Address as EthAddress;
use gravity_utils::connection_prep::{
check_delegate_addresses, check_for_eth, check_for_fee_denom, create_rpc_connections,
wait_for_cosmos_node_ready,
};
use orchestrator::main_loop::{
orchestrator_main_loop, ETH_ORACLE_LOOP_SPEED, ETH_SIGNER_LOOP_SPEED,
};
use relayer::main_loop::LOOP_SPEED as RELAYER_LOOP_SPEED;
use std::cmp::min;

#[derive(Command, Debug, Options)]
pub struct StartCommand {
#[options(help = "cosmos key name")]
cosmos_key: String,

#[options(help = "ethereum key name")]
ethereum_key: String,
}

impl Runnable for StartCommand {
fn run(&self) {
let config = APP.config();
let cosmos_prefix = config.cosmos.prefix.clone();

let cosmos_key = config.load_deep_space_key(self.cosmos_key.clone());
let cosmos_address = cosmos_key.to_address(&cosmos_prefix).unwrap();

let ethereum_key = config.load_clarity_key(self.ethereum_key.clone());
let ethereum_address = ethereum_key.to_public_key().unwrap();

let contract_address: EthAddress = config
.gravity
.contract
.parse()
.expect("Could not parse gravity contract address");

let fees_denom = config.gravity.fees_denom.clone();

let timeout = min(
min(ETH_SIGNER_LOOP_SPEED, ETH_ORACLE_LOOP_SPEED),
RELAYER_LOOP_SPEED,
);

abscissa_tokio::run_with_actix(&APP, async {
let connections = create_rpc_connections(
cosmos_prefix,
Some(config.cosmos.grpc.clone()),
Some(config.ethereum.rpc.clone()),
timeout,
)
.await;

let mut grpc = connections.grpc.clone().unwrap();
let contact = connections.contact.clone().unwrap();
let web3 = connections.web3.clone().unwrap();

info!("Starting Relayer + Oracle + Ethereum Signer");
info!("Ethereum Address: {}", ethereum_address);
info!("Cosmos Address {}", cosmos_address);

// check if the cosmos node is syncing, if so wait for it
// we can't move any steps above this because they may fail on an incorrect
// historic chain state while syncing occurs
wait_for_cosmos_node_ready(&contact).await;

// check if the delegate addresses are correctly configured
check_delegate_addresses(
&mut grpc,
ethereum_address,
cosmos_address,
&contact.get_prefix(),
)
.await;

// check if we actually have the promised balance of tokens to pay fees
check_for_fee_denom(&fees_denom, cosmos_address, &contact).await;
check_for_eth(ethereum_address, &web3).await;

orchestrator_main_loop(
cosmos_key,
ethereum_key,
web3,
contact,
grpc,
contract_address,
fees_denom,
)
.await;
})
.unwrap_or_else(|e| {
status_err!("executor exited with error: {}", e);
std::process::exit(1);
});
}
}
Loading

0 comments on commit 2102174

Please sign in to comment.