refactor: break signers out of replicas in rust configs (#381)

* refactor(wip): break signers out of replicas in rust configs

* chore: update configs files with new format
buddies-main-deployment
James Prestwich 4 years ago committed by GitHub
parent be2dbe088d
commit 5489c5f22c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .gitignore
  2. 35
      rust/config/1622504632050-alfajores-goerli/alfajores_config.json
  3. 34
      rust/config/1622504632050-alfajores-goerli/goerli_config.json
  4. 36
      rust/config/1622591031448-alfajores-goerli/alfajores_config.json
  5. 36
      rust/config/1622591031448-alfajores-goerli/goerli_config.json
  6. 34
      rust/config/alfa-goerli/alfa_config.json
  7. 34
      rust/config/alfa-goerli/goerli_config.json
  8. 48
      rust/config/default/base.json
  9. 72
      rust/optics-base/src/settings/chains.rs
  10. 92
      rust/optics-base/src/settings/mod.rs
  11. 5
      rust/optics-ethereum/src/lib.rs
  12. 119
      rust/optics-ethereum/src/settings.rs
  13. 5
      rust/updater/src/settings.rs
  14. 8
      rust/watcher/src/settings.rs
  15. 5
      rust/watcher/src/watcher.rs
  16. 37
      typescript/src/chain.ts

1
.gitignore vendored

@ -2,3 +2,4 @@ node_modules
test_deploy.env
config.json
typescript/tmp.ts
rust/tmp_db

@ -1,19 +1,24 @@
{
"signers": {
"goerli": {
"key": "",
"type": "hexKey"
},
"alfajores": {
"key": "",
"type": "hexKey"
}
},
"replicas": {
"goerli": {
"address": "0x4C2e47cA4Dd7b93A62730e463BE43A0EA01c5A10",
"domain": 2000,
"name": "goerli",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
}
},
@ -22,15 +27,9 @@
"domain": 1000,
"name": "alfajores",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
},
"tracing": {

@ -1,19 +1,23 @@
{
"signers": {
"goerli": {
"key": "",
"type": "hexKey"
},
"alfajores": {
"key": "",
"type": "hexKey"
}
},
"replicas": {
"alfajores": {
"address": "0x0C473afC0cabd469751CBE3Ac08aBac3e40bF586",
"domain": 1000,
"name": "alfajores",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
}
},
@ -22,15 +26,9 @@
"domain": 2000,
"name": "goerli",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
},
"tracing": {

@ -1,19 +1,23 @@
{
"signers": {
"goerli": {
"key": "",
"type": "hexKey"
},
"alfajores": {
"key": "",
"type": "hexKey"
}
},
"replicas": {
"goerli": {
"address": "0x3Ae05E294227356393cEBAe63B6007803D721f97",
"domain": 1000,
"name": "goerli",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
}
},
@ -22,15 +26,9 @@
"domain": 1000,
"name": "alfajores",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
},
"tracing": {
@ -38,4 +36,4 @@
"style": "pretty"
},
"dbPath": "db_path"
}
}

@ -1,19 +1,23 @@
{
"signers": {
"goerli": {
"key": "",
"type": "hexKey"
},
"alfajores": {
"key": "",
"type": "hexKey"
}
},
"replicas": {
"alfajores": {
"address": "0xDf4c0d67489F945C1e52440Ef8F203F4CE6e4176",
"domain": 1000,
"name": "alfajores",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
}
},
@ -22,15 +26,9 @@
"domain": 1000,
"name": "goerli",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
},
"tracing": {
@ -38,4 +36,4 @@
"style": "pretty"
},
"dbPath": "db_path"
}
}

@ -1,19 +1,23 @@
{
"signers": {
"goerli": {
"key": "",
"type": "hexKey"
},
"alfajores": {
"key": "",
"type": "hexKey"
}
},
"replicas": {
"goerli": {
"address": "0x75f5a07e565915442BCC7F98962714Fec4CcF05D",
"domain": 2000,
"name": "goerli",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
}
},
@ -22,15 +26,9 @@
"domain": 1000,
"name": "alfajores",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
},
"tracing": {

@ -1,19 +1,23 @@
{
"signers": {
"goerli": {
"key": "",
"type": "hexKey"
},
"alfajores": {
"key": "",
"type": "hexKey"
}
},
"replicas": {
"alfajores": {
"address": "0x86f3B72441E836B3C05CeBA651dB4785708fc16e",
"domain": 1000,
"name": "alfajores",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
"connection": {
"type": "http",
"url": "https://alfajores-forno.celo-testnet.org"
}
}
},
@ -22,15 +26,9 @@
"domain": 2000,
"name": "goerli",
"rpcStyle": "ethereum",
"config": {
"signer": {
"key": "",
"type": "hexKey"
},
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
"connection": {
"type": "http",
"url": "https://goerli.infura.io/v3/5c456d7844fa40a683e934df60534c60"
}
},
"tracing": {

@ -1,44 +1,40 @@
{
"signers": {
"ethereum": {
"key": "380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc",
"type": "hexKey"
}
},
"replicas": {
"ethereum": {
"address": "0x0000000000000000000000000000000000000000",
"domain": 60,
"name": "ethereum",
"rpcStyle": "ethereum",
"config": {
"connection": {
"type": "ws",
"url": "ws://localhost:8545"
},
"signer": {
"key": "380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc",
"type": "hexKey"
}
}
},
"eth-classic": {
"address": "0x0000000000000000000000000000000000000000",
"domain": 61,
"name": "eth-classic",
"rpcStyle": "ethereum",
"config": {
"connection": {
"type": "ws",
"url": "ws://localhost:8545"
}
"connection": {
"type": "ws",
"url": "ws://localhost:8545"
}
}
},
"eth-classic": {
"address": "0x0000000000000000000000000000000000000000",
"domain": 61,
"name": "eth-classic",
"rpcStyle": "ethereum",
"connection": {
"type": "ws",
"url": "ws://localhost:8545"
}
},
"home": {
"address": "0x0000000000000000000000000000000000000000",
"domain": 52752,
"name": "celo",
"rpcStyle": "ethereum",
"config": {
"connection": {
"type": "http",
"url": "http://localhost:8545"
}
"connection": {
"type": "http",
"url": "http://localhost:8545"
}
},
"tracing": {

@ -0,0 +1,72 @@
use color_eyre::Report;
use optics_core::Signers;
use optics_ethereum::settings::EthereumConnection;
use serde::Deserialize;
use crate::{home::Homes, replica::Replicas, xapp::ConnectionManagers};
/// A connection to _some_ blockchain.
///
/// Specify the chain name (enum variant) in toml under the `chain` key
/// Specify the connection details as a toml object under the `connection` key.
#[derive(Debug, Deserialize)]
#[serde(tag = "rpcStyle", content = "config", rename_all = "camelCase")]
pub enum ChainConf {
/// Ethereum configuration
Ethereum(EthereumConnection),
}
/// A chain setup is a domain ID, an address on that chain (where the home or
/// replica is deployed) and details for connecting to the chain API.
#[derive(Debug, Deserialize)]
pub struct ChainSetup {
/// Chain name
pub name: String,
/// Chain domain identifier
pub domain: u32,
/// Address of contract on the chain
pub address: String,
/// The chain connection details
#[serde(flatten)]
pub chain: ChainConf,
}
impl ChainSetup {
/// Try to convert the chain setting into a Home contract
pub async fn try_into_home(&self, signer: Option<Signers>) -> Result<Homes, Report> {
match &self.chain {
ChainConf::Ethereum(conf) => Ok(Homes::Ethereum(
conf.try_into_home(&self.name, self.domain, self.address.parse()?, signer)
.await?,
)),
}
}
/// Try to convert the chain setting into a replica contract
pub async fn try_into_replica(&self, signer: Option<Signers>) -> Result<Replicas, Report> {
match &self.chain {
ChainConf::Ethereum(conf) => Ok(Replicas::Ethereum(
conf.try_into_replica(&self.name, self.domain, self.address.parse()?, signer)
.await?,
)),
}
}
/// Try to convert chain setting into XAppConnectionManager contract
pub async fn try_into_connection_manager(
&self,
signer: Option<Signers>,
) -> Result<ConnectionManagers, Report> {
match &self.chain {
ChainConf::Ethereum(conf) => Ok(ConnectionManagers::Ethereum(
conf.try_into_connection_manager(
&self.name,
self.domain,
self.address.parse()?,
signer,
)
.await?,
)),
}
}
}

@ -1,68 +1,49 @@
use color_eyre::{eyre::bail, Report};
use config::{Config, ConfigError, Environment, File};
use optics_core::{utils::HexString, Signers};
use serde::Deserialize;
use std::{collections::HashMap, env, sync::Arc};
use crate::{db, home::Homes, replica::Replicas, xapp::ConnectionManagers};
use crate::{agent::AgentCore, db, home::Homes, replica::Replicas};
/// Tracing configuration
pub mod log;
use log::TracingConfig;
use optics_ethereum::settings::EthereumConf;
/// Chain configuartion
pub mod chains;
use crate::agent::AgentCore;
pub use chains::ChainSetup;
/// A connection to _some_ blockchain.
///
/// Specify the chain name (enum variant) in toml under the `chain` key
/// Specify the connection details as a toml object under the `connection` key.
#[derive(Debug, Deserialize)]
#[serde(tag = "rpcStyle", content = "config", rename_all = "camelCase")]
pub enum ChainConf {
/// Ethereum configuration
Ethereum(EthereumConf),
}
use log::TracingConfig;
/// A chain setup is a domain ID, an address on that chain (where the home or
/// replica is deployed) and details for connecting to the chain API.
#[derive(Debug, Deserialize)]
pub struct ChainSetup {
name: String,
domain: u32,
address: String,
#[serde(flatten)]
chain: ChainConf,
// TODO: figure out how to take inputs for Ledger and YubiWallet variants
/// Ethereum signer types
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum SignerConf {
/// A local hex key
HexKey {
/// Hex string of private key, without 0x prefix
key: HexString<64>,
},
#[serde(other)]
/// Assume node will sign on RPC calls
Node,
}
impl ChainSetup {
/// Try to convert the chain setting into a Home contract
pub async fn try_into_home(&self) -> Result<Homes, Report> {
match &self.chain {
ChainConf::Ethereum(conf) => Ok(Homes::Ethereum(
conf.try_into_home(&self.name, self.domain, self.address.parse()?)
.await?,
)),
}
}
/// Try to convert the chain setting into a replica contract
pub async fn try_into_replica(&self) -> Result<Replicas, Report> {
match &self.chain {
ChainConf::Ethereum(conf) => Ok(Replicas::Ethereum(
conf.try_into_replica(&self.name, self.domain, self.address.parse()?)
.await?,
)),
}
impl Default for SignerConf {
fn default() -> Self {
Self::Node
}
}
/// Try to convert chain setting into XAppConnectionManager contract
pub async fn try_into_connection_manager(&self) -> Result<ConnectionManagers, Report> {
match &self.chain {
ChainConf::Ethereum(conf) => Ok(ConnectionManagers::Ethereum(
conf.try_into_connection_manager(&self.name, self.domain, self.address.parse()?)
.await?,
)),
impl SignerConf {
/// Try to convert the ethereum signer to a local wallet
#[tracing::instrument(err)]
pub fn try_into_signer(&self) -> Result<Signers, Report> {
match self {
SignerConf::HexKey { key } => Ok(Signers::Local(key.as_ref().parse()?)),
SignerConf::Node => bail!("Node signer"),
}
}
}
@ -102,9 +83,16 @@ pub struct Settings {
pub replicas: HashMap<String, ChainSetup>,
/// The tracing configuration
pub tracing: TracingConfig,
/// Transaction signers
pub signers: HashMap<String, SignerConf>,
}
impl Settings {
/// Try to get a signer instance by name
pub fn get_signer(&self, name: &str) -> Option<Signers> {
self.signers.get(name)?.try_into_signer().ok()
}
/// Try to get all replicas from this settings object
pub async fn try_replicas(&self) -> Result<HashMap<String, Arc<Replicas>>, Report> {
let mut result = HashMap::default();
@ -116,14 +104,16 @@ impl Settings {
v.name
);
}
result.insert(v.name.clone(), Arc::new(v.try_into_replica().await?));
let signer = self.get_signer(&v.name);
result.insert(v.name.clone(), Arc::new(v.try_into_replica(signer).await?));
}
Ok(result)
}
/// Try to get a home object
pub async fn try_home(&self) -> Result<Homes, Report> {
self.home.try_into_home().await
let signer = self.get_signer(&self.home.name);
self.home.try_into_home(signer).await
}
/// Try to generate an agent core

@ -20,7 +20,4 @@ mod xapp;
pub mod settings;
#[cfg(not(doctest))]
pub use crate::{
home::EthereumHome, replica::EthereumReplica, settings::EthereumSigner,
xapp::EthereumConnectionManager,
};
pub use crate::{home::EthereumHome, replica::EthereumReplica, xapp::EthereumConnectionManager};

@ -1,30 +1,12 @@
use std::convert::TryFrom;
use color_eyre::{eyre::eyre, Report, Result};
use color_eyre::{Report, Result};
use ethers::prelude::{Address, Middleware};
use std::convert::TryFrom;
use optics_core::{
traits::{ConnectionManager, Home, Replica},
utils::HexString,
Signers,
};
/// Ethereum connection configuration
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum EthereumConnection {
/// HTTP connection details
Http {
/// Fully qualified string to connect to
url: String,
},
/// Websocket connection details
Ws {
/// Fully qualified string to connect to
url: String,
},
}
// Construct boxed contracts in a big "if-else" chain to handle multiple
// combinations of middleware.
macro_rules! construct_box_contract {
@ -76,52 +58,23 @@ macro_rules! construct_http_box_contract {
}};
}
// TODO: figure out how to take inputs for Ledger and YubiWallet variants
/// Ethereum signer types
#[derive(Debug, Clone, serde::Deserialize)]
/// Ethereum connection configuration
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum EthereumSigner {
/// A local hex key
HexKey {
/// Hex string of private key, without 0x prefix
key: HexString<64>,
pub enum EthereumConnection {
/// HTTP connection details
Http {
/// Fully qualified string to connect to
url: String,
},
/// Websocket connection details
Ws {
/// Fully qualified string to connect to
url: String,
},
#[serde(other)]
/// Node will sign on RPC calls
Node,
}
impl Default for EthereumSigner {
fn default() -> Self {
Self::Node
}
}
impl EthereumSigner {
/// Try to convert the ethereum signer to a local wallet
#[tracing::instrument(err)]
pub fn try_into_signer(&self) -> Result<Signers> {
match self {
EthereumSigner::HexKey { key } => Ok(Signers::Local(key.as_ref().parse()?)),
EthereumSigner::Node => Err(eyre!("Node signer")),
}
}
}
/// Ethereum configuration
#[derive(Debug, serde::Deserialize)]
pub struct EthereumConf {
connection: EthereumConnection,
#[serde(default)]
signer: EthereumSigner,
}
impl EthereumConf {
/// Try to get a signer from the config
pub fn signer(&self) -> Option<Signers> {
self.signer.try_into_signer().ok()
}
impl EthereumConnection {
/// Try to convert this into a home contract
#[tracing::instrument(err)]
pub async fn try_into_home(
@ -129,20 +82,14 @@ impl EthereumConf {
name: &str,
domain: u32,
address: Address,
signer: Option<Signers>,
) -> Result<Box<dyn Home>, Report> {
let b: Box<dyn Home> = match &self.connection {
let b: Box<dyn Home> = match &self {
EthereumConnection::Http { url } => {
construct_http_box_contract!(
EthereumHome,
name,
domain,
address,
url,
self.signer()
)
construct_http_box_contract!(EthereumHome, name, domain, address, url, signer)
}
EthereumConnection::Ws { url } => {
construct_ws_box_contract!(EthereumHome, name, domain, address, url, self.signer())
construct_ws_box_contract!(EthereumHome, name, domain, address, url, signer)
}
};
Ok(b)
@ -155,27 +102,14 @@ impl EthereumConf {
name: &str,
domain: u32,
address: Address,
signer: Option<Signers>,
) -> Result<Box<dyn Replica>, Report> {
let b: Box<dyn Replica> = match &self.connection {
let b: Box<dyn Replica> = match &self {
EthereumConnection::Http { url } => {
construct_http_box_contract!(
EthereumReplica,
name,
domain,
address,
url,
self.signer()
)
construct_http_box_contract!(EthereumReplica, name, domain, address, url, signer)
}
EthereumConnection::Ws { url } => {
construct_ws_box_contract!(
EthereumReplica,
name,
domain,
address,
url,
self.signer()
)
construct_ws_box_contract!(EthereumReplica, name, domain, address, url, signer)
}
};
Ok(b)
@ -188,8 +122,9 @@ impl EthereumConf {
name: &str,
domain: u32,
address: Address,
signer: Option<Signers>,
) -> Result<Box<dyn ConnectionManager>, Report> {
let b: Box<dyn ConnectionManager> = match &self.connection {
let b: Box<dyn ConnectionManager> = match &self {
EthereumConnection::Http { url } => {
construct_http_box_contract!(
EthereumConnectionManager,
@ -197,7 +132,7 @@ impl EthereumConf {
domain,
address,
url,
self.signer()
signer
)
}
EthereumConnection::Ws { url } => {
@ -207,7 +142,7 @@ impl EthereumConf {
domain,
address,
url,
self.signer()
signer
)
}
};

@ -1,10 +1,9 @@
//! Configuration
use optics_base::decl_settings;
use optics_ethereum::EthereumSigner;
use optics_base::{decl_settings, settings::SignerConf};
decl_settings!(Settings {
agent: "updater",
updater: EthereumSigner,
updater: SignerConf,
polling_interval: u64,
update_pause: u64,
});

@ -1,11 +1,13 @@
//! Configuration
use optics_base::{decl_settings, settings::ChainSetup};
use optics_ethereum::EthereumSigner;
use optics_base::{
decl_settings,
settings::{ChainSetup, SignerConf},
};
decl_settings!(Settings {
agent: "watcher",
watcher: EthereumSigner,
watcher: SignerConf,
connection_managers: Vec<ChainSetup>,
polling_interval: u64,
});

@ -339,7 +339,10 @@ impl OpticsAgent for Watcher {
let connection_manager_futs: Vec<_> = settings
.connection_managers
.iter()
.map(|chain_setup| chain_setup.try_into_connection_manager())
.map(|chain_setup| {
let signer = settings.base.get_signer(&chain_setup.name);
chain_setup.try_into_connection_manager(signer)
})
.collect();
let (connection_managers, errors): (Vec<_>, Vec<_>) = join_all(connection_manager_futs)

@ -104,13 +104,8 @@ type RustSigner = {
};
type RustConnection = {
type: string; // TODO
url: string;
};
type RustChainSetup = {
connection: RustConnection;
signer: RustSigner;
type: string; // TODO
};
type RustContractBlock = {
@ -118,10 +113,11 @@ type RustContractBlock = {
domain: number;
name: string;
rpcStyle: string; // TODO
config: RustChainSetup;
connection: RustConnection;
};
type RustConfig = {
signers: Record<string, RustSigner>;
replicas: Record<string, RustContractBlock>;
home: RustContractBlock;
tracing: {
@ -137,35 +133,24 @@ function buildConfig(left: Deploy, right: Deploy): RustConfig {
domain: right.chain.domain,
name: right.chain.name,
rpcStyle: 'ethereum',
config: {
signer: {
key: '',
type: 'hexKey',
},
connection: {
type: 'http',
url: right.chain.config.rpc,
},
connection: {
type: 'http',
url: right.chain.config.rpc,
},
};
const home = {
address: left.contracts.home!.proxy.address,
domain: left.chain.domain,
name: left.chain.name,
rpcStyle: 'ethereum',
config: {
signer: {
key: '',
type: 'hexKey',
},
connection: {
type: 'http', // TODO
url: left.chain.config.rpc,
},
rpcStyle: 'ethereum', // TODO
connection: {
type: 'http', // TODO
url: left.chain.config.rpc,
},
};
return {
signers: { [replica.name]: { key: '', type: 'hexKey' } },
replicas: { [replica.name]: replica },
home,
tracing: {

Loading…
Cancel
Save