Skip to content

Commit

Permalink
feat(eth-se): fixed ethereum settlement engine to take environment va…
Browse files Browse the repository at this point in the history
…riables

Signed-off-by: Taiga Nakayama <dora@dora-gt.jp>

interledger#194
  • Loading branch information
dora-gt committed Aug 23, 2019
1 parent dcaa195 commit 4599019
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 97 deletions.
2 changes: 2 additions & 0 deletions crates/interledger-settlement-engines/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ sha3 = "0.8.2"
num-bigint = "0.2.2"
num-traits = "0.2.8"
lazy_static = "1.3.0"
config = "0.9.3"
structopt = "0.2.18"

[dev-dependencies]
lazy_static = "1.3"
Expand Down
289 changes: 196 additions & 93 deletions crates/interledger-settlement-engines/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,106 +1,209 @@
use clap::{value_t, App, Arg, SubCommand};
use config::{Source, Value, *};
use std::collections::{hash_map::RandomState, HashMap};
use std::str::FromStr;
use structopt::StructOpt;
use tokio;
use url::Url;

use interledger_settlement_engines::engines::ethereum_ledger::{run_ethereum_engine, EthAddress};

#[allow(clippy::cognitive_complexity)]
pub fn main() {
env_logger::init();
let opt = CliOpt::from_args();
opt.execute();
}

// The commands structure
// interledger-settlement-engines
// - ethereum-ledger

impl CliOpt {
fn execute(&self) {
match &self.sub_command {
TopSubCommands::EthereumLedger(opt) => opt.execute(),
};
}
}

impl EthereumLedgerOpt {
fn execute(&self) {
let mut config = config::Config::new();
config.merge(self.clone()).unwrap();
config
.merge(config::Environment::with_prefix("ILP"))
.unwrap();

let mut app = App::new("interledger-settlement-engines")
.about("Interledger Settlement Engines CLI")
.subcommands(vec![
SubCommand::with_name("ethereum-ledger")
.about("Ethereum settlement engine which performs ledger (layer 1) transactions")
.args(&[
Arg::with_name("port")
.long("port")
.help("Port to listen for settlement requests on")
.default_value("3000"),
Arg::with_name("key")
.long("key")
.help("private key for settlement account")
.takes_value(true)
.required(true),
Arg::with_name("ethereum_endpoint")
.long("ethereum_endpoint")
.help("Ethereum node endpoint")
.default_value("http://127.0.0.1:8545"),
Arg::with_name("token_address")
.long("token_address")
.help("The address of the ERC20 token to be used for settlement (defaults to sending ETH if no token address is provided)")
.default_value(""),
Arg::with_name("connector_url")
.long("connector_url")
.help("Connector Settlement API endpoint")
.default_value("http://127.0.0.1:7771"),
Arg::with_name("redis_uri")
.long("redis_uri")
.help("Redis database to add the account to")
.default_value("redis://127.0.0.1:6379"),
Arg::with_name("chain_id")
.long("chain_id")
.help("The chain id so that the signer calculates the v value of the sig appropriately")
.default_value("1"),
Arg::with_name("confirmations")
.long("confirmations")
.help("The number of confirmations the engine will wait for a transaction's inclusion before it notifies the node of its success")
.default_value("6"),
Arg::with_name("asset_scale")
.long("asset_scale")
.help("The asset scale you want to use for your payments (default: 18)")
.default_value("18"),
Arg::with_name("poll_frequency")
.long("poll_frequency")
.help("The frequency in milliseconds at which the engine will check the blockchain about the confirmation status of a tx")
.default_value("5000"),
Arg::with_name("watch_incoming")
.long("watch_incoming")
.help("Launch a blockchain watcher that listens for incoming transactions and notifies the connector upon sufficient confirmations")
.default_value("true"),
])
]
);
let settlement_port = config.get("port").unwrap();
// TODO make compatible with
// https://github.com/tendermint/signatory to have HSM sigs
let private_key: String = config.get("key").unwrap();
let ethereum_endpoint: String = config.get("ethereum_endpoint").unwrap();
let token_address: String = config.get("token_address").unwrap();
let token_address = if token_address.len() == 20 {
Some(EthAddress::from_str(&token_address).unwrap())
} else {
None
};
let connector_url: String = config.get("connector_url").unwrap();
let redis_uri: String = config.get("redis_uri").unwrap();
let redis_uri = Url::parse(&redis_uri).expect("redis_uri is not a valid URI");
let chain_id = config.get("chain_id").unwrap();
let confirmations = config.get("confirmations").unwrap();
let asset_scale = config.get("asset_scale").unwrap();
let poll_frequency = config.get("poll_frequency").unwrap();
let watch_incoming = !config.get::<bool>("without_incoming_watcher").unwrap();

tokio::run(run_ethereum_engine(
redis_uri,
ethereum_endpoint,
settlement_port,
private_key,
chain_id,
confirmations,
asset_scale,
poll_frequency,
connector_url,
token_address,
watch_incoming,
));
}
}

match app.clone().get_matches().subcommand() {
("ethereum-ledger", Some(matches)) => {
let settlement_port =
value_t!(matches, "port", u16).expect("port for settlement engine required");
// TODO make compatible with
// https://github.com/tendermint/signatory to have HSM sigs
let private_key: String = value_t!(matches, "key", String).unwrap();
let ethereum_endpoint: String = value_t!(matches, "ethereum_endpoint", String).unwrap();
let token_address = value_t!(matches, "token_address", String).unwrap();
let token_address = if token_address.len() == 20 {
Some(EthAddress::from_str(&token_address).unwrap())
} else {
None
};
let connector_url: String = value_t!(matches, "connector_url", String).unwrap();
let redis_uri = value_t!(matches, "redis_uri", String).expect("redis_uri is required");
let redis_uri = Url::parse(&redis_uri).expect("redis_uri is not a valid URI");
let chain_id = value_t!(matches, "chain_id", u8).unwrap();
let confirmations = value_t!(matches, "confirmations", u8).unwrap();
let asset_scale = value_t!(matches, "asset_scale", u8).unwrap();
let poll_frequency = value_t!(matches, "poll_frequency", u64).unwrap();
let watch_incoming = value_t!(matches, "watch_incoming", bool).unwrap();
impl Source for EthereumLedgerOpt {
fn clone_into_box(&self) -> Box<Source + Send + Sync> {
Box::new(self.clone())
}

tokio::run(run_ethereum_engine(
redis_uri,
ethereum_endpoint,
settlement_port,
private_key,
chain_id,
confirmations,
asset_scale,
poll_frequency,
connector_url,
token_address,
watch_incoming,
));
}
_ => app.print_help().unwrap(),
fn collect(&self) -> Result<HashMap<String, Value, RandomState>, ConfigError> {
let mut hash_map = HashMap::new();
hash_map.insert("port".to_string(), Value::new(None, self.port as i64));
hash_map.insert(
"key".to_string(),
Value::new(None, self.key.clone().unwrap_or(String::new())),
);
hash_map.insert(
"ethereum_endpoint".to_string(),
Value::new(None, self.ethereum_endpoint.to_string()),
);
hash_map.insert(
"token_address".to_string(),
Value::new(None, self.token_address.to_string()),
);
hash_map.insert(
"connector_url".to_string(),
Value::new(None, self.connector_url.to_string()),
);
hash_map.insert(
"redis_uri".to_string(),
Value::new(None, self.redis_uri.to_string()),
);
hash_map.insert(
"chain_id".to_string(),
Value::new(None, self.chain_id as i64),
);
hash_map.insert(
"confirmations".to_string(),
Value::new(None, self.confirmations as i64),
);
hash_map.insert(
"asset_scale".to_string(),
Value::new(None, self.asset_scale as i64),
);
hash_map.insert(
"poll_frequency".to_string(),
Value::new(None, self.poll_frequency as i64),
);
hash_map.insert(
"without_incoming_watcher".to_string(),
Value::new(None, self.without_incoming_watcher),
);
Ok(hash_map)
}
}

#[derive(Debug, StructOpt)]
#[structopt(
name = "interledger-settlement-engines",
about = "Interledger Settlement Engines CLI"
)]
struct CliOpt {
#[structopt(subcommand)]
sub_command: TopSubCommands,
}

#[derive(Debug, StructOpt)]
enum TopSubCommands {
#[structopt(
name = "ethereum-ledger",
about = "Ethereum settlement engine which performs ledger (layer 1) transactions"
)]
EthereumLedger(EthereumLedgerOpt),
}

#[derive(Debug, StructOpt, Clone)]
struct EthereumLedgerOpt {
#[structopt(
short = "p",
long = "port",
default_value = "3000",
help = "Port to listen for settlement requests on"
)]
port: u16,
#[structopt(long = "key", help = "private key for settlement account")]
key: Option<String>,
#[structopt(
long = "ethereum_endpoint",
default_value = "http://127.0.0.1:8545",
help = "Ethereum node endpoint"
)]
ethereum_endpoint: String,
#[structopt(
long = "token_address",
default_value = "",
help = "The address of the ERC20 token to be used for settlement (defaults to sending ETH if no token address is provided)"
)]
token_address: String,
#[structopt(
long = "connector_url",
default_value = "http://127.0.0.1:7771",
help = "Connector Settlement API endpoint"
)]
connector_url: String,
#[structopt(
long = "redis_uri",
default_value = "redis://127.0.0.1:6379",
help = "Redis database to add the account to"
)]
redis_uri: String,
// Although the length of `chain_id` seems to be not limited on its specs,
// u8 seems sufficient at this point.
#[structopt(
long = "chain_id",
default_value = "1",
help = "The chain id so that the signer calculates the v value of the sig appropriately"
)]
chain_id: u8,
#[structopt(
long = "confirmations",
default_value = "6",
help = "The number of confirmations the engine will wait for a transaction's inclusion before it notifies the node of its success"
)]
confirmations: u8,
#[structopt(
long = "asset_scale",
default_value = "18",
help = "The asset scale you want to use for your payments (default: 18)"
)]
asset_scale: u8,
#[structopt(
long = "poll_frequency",
default_value = "5000",
help = "The frequency in milliseconds at which the engine will check the blockchain about the confirmation status of a tx"
)]
poll_frequency: u64,
#[structopt(
long = "without_incoming_watcher",
help = "Not launch a blockchain watcher that listens for incoming transactions and notifies the connector upon sufficient confirmations"
)]
without_incoming_watcher: bool,
}
2 changes: 0 additions & 2 deletions examples/eth-settlement/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ cargo run --package interledger-settlement-engines -- ethereum-ledger \
--ethereum_endpoint http://127.0.0.1:8545 \
--connector_url http://127.0.0.1:7771 \
--redis_uri redis://127.0.0.1:6379/0 \
--watch_incoming true \
--port 3000 \
&> logs/node-alice-settlement-engine.log &

Expand All @@ -143,7 +142,6 @@ cargo run --package interledger-settlement-engines -- ethereum-ledger \
--ethereum_endpoint http://127.0.0.1:8545 \
--connector_url http://127.0.0.1:8771 \
--redis_uri redis://127.0.0.1:6379/1 \
--watch_incoming true \
--port 3001 \
&> logs/node-bob-settlement-engine.log &
```
Expand Down
2 changes: 0 additions & 2 deletions examples/eth_xrp_three_nodes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ cargo run --package interledger-settlement-engines -- ethereum-ledger \
--connector_url http://127.0.0.1:7771 \
--redis_uri redis://127.0.0.1:6379/0 \
--asset_scale 6 \
--watch_incoming true \
--port 3000 \
&> logs/node-alice-settlement-engine-eth.log &

Expand All @@ -206,7 +205,6 @@ cargo run --package interledger-settlement-engines -- ethereum-ledger \
--connector_url http://127.0.0.1:8771 \
--redis_uri redis://127.0.0.1:6380/0 \
--asset_scale 6 \
--watch_incoming true \
--port 3001 \
&> logs/node-bob-settlement-engine-eth.log &

Expand Down

0 comments on commit 4599019

Please sign in to comment.