poa-bridge/bridge/src/config.rs

336 lines
9.0 KiB
Rust
Raw Normal View History

2017-06-25 04:21:13 -07:00
use std::path::{PathBuf, Path};
use std::fs;
use std::io::Read;
2017-08-01 02:36:48 -07:00
use std::time::Duration;
use rustc_hex::FromHex;
2017-08-10 08:55:46 -07:00
use web3::types::{Address, Bytes};
2017-08-02 03:45:15 -07:00
use error::{ResultExt, Error};
use {toml};
2017-06-13 01:28:04 -07:00
2017-08-01 02:36:48 -07:00
const DEFAULT_POLL_INTERVAL: u64 = 1;
const DEFAULT_CONFIRMATIONS: usize = 12;
2017-08-31 08:32:34 -07:00
const DEFAULT_TIMEOUT: u64 = 5;
2017-08-01 02:36:48 -07:00
2017-06-25 04:21:13 -07:00
/// Application config.
2017-08-13 11:44:41 -07:00
#[derive(Debug, PartialEq, Clone)]
2017-06-13 01:28:04 -07:00
pub struct Config {
2017-10-10 02:02:46 -07:00
pub home: Node,
pub foreign: Node,
pub authorities: Authorities,
pub txs: Transactions,
pub estimated_gas_cost_of_withdraw: u32,
2017-06-25 04:21:13 -07:00
}
impl Config {
2017-08-02 03:45:15 -07:00
pub fn load<P: AsRef<Path>>(path: P) -> Result<Config, Error> {
let mut file = fs::File::open(path).chain_err(|| "Cannot open config")?;
2017-06-25 04:21:13 -07:00
let mut buffer = String::new();
2017-08-13 04:09:50 -07:00
file.read_to_string(&mut buffer).expect("TODO");
2017-06-25 04:21:13 -07:00
Self::load_from_str(&buffer)
}
2017-08-02 03:45:15 -07:00
fn load_from_str(s: &str) -> Result<Config, Error> {
let config: load::Config = toml::from_str(s).chain_err(|| "Cannot parse config")?;
2017-08-10 08:55:46 -07:00
Config::from_load_struct(config)
}
fn from_load_struct(config: load::Config) -> Result<Config, Error> {
let result = Config {
2017-10-10 02:02:46 -07:00
home: Node::from_load_struct(config.home)?,
foreign: Node::from_load_struct(config.foreign)?,
authorities: Authorities {
accounts: config.authorities.accounts,
required_signatures: config.authorities.required_signatures,
},
txs: config.transactions.map(Transactions::from_load_struct).unwrap_or_default(),
estimated_gas_cost_of_withdraw: config.estimated_gas_cost_of_withdraw,
2017-08-10 08:55:46 -07:00
};
Ok(result)
2017-06-25 04:21:13 -07:00
}
}
2017-08-13 11:44:41 -07:00
#[derive(Debug, PartialEq, Clone)]
2017-08-01 02:36:48 -07:00
pub struct Node {
2017-08-03 15:48:12 -07:00
pub account: Address,
2017-08-10 08:55:46 -07:00
pub contract: ContractConfig,
2017-08-01 02:36:48 -07:00
pub ipc: PathBuf,
2017-08-31 08:32:34 -07:00
pub request_timeout: Duration,
2017-08-01 02:36:48 -07:00
pub poll_interval: Duration,
pub required_confirmations: usize,
2017-06-25 04:21:13 -07:00
}
2017-08-10 08:55:46 -07:00
impl Node {
2017-08-24 09:38:56 -07:00
fn from_load_struct(node: load::Node) -> Result<Node, Error> {
2017-08-10 08:55:46 -07:00
let result = Node {
account: node.account,
contract: ContractConfig {
bin: {
let mut read = String::new();
let mut file = fs::File::open(node.contract.bin)?;
file.read_to_string(&mut read)?;
Bytes(read.from_hex()?)
}
2017-08-10 08:55:46 -07:00
},
2017-08-24 09:38:56 -07:00
ipc: node.ipc,
2017-08-31 08:32:34 -07:00
request_timeout: Duration::from_secs(node.request_timeout.unwrap_or(DEFAULT_TIMEOUT)),
2017-08-10 08:55:46 -07:00
poll_interval: Duration::from_secs(node.poll_interval.unwrap_or(DEFAULT_POLL_INTERVAL)),
required_confirmations: node.required_confirmations.unwrap_or(DEFAULT_CONFIRMATIONS),
};
2017-08-24 09:38:56 -07:00
2017-08-10 08:55:46 -07:00
Ok(result)
}
}
2017-08-13 11:44:41 -07:00
#[derive(Debug, PartialEq, Default, Clone)]
2017-08-12 11:03:48 -07:00
pub struct Transactions {
2017-10-10 02:02:46 -07:00
pub home_deploy: TransactionConfig,
pub foreign_deploy: TransactionConfig,
pub deposit_relay: TransactionConfig,
pub withdraw_confirm: TransactionConfig,
pub withdraw_relay: TransactionConfig,
2017-08-12 11:03:48 -07:00
}
impl Transactions {
fn from_load_struct(cfg: load::Transactions) -> Self {
Transactions {
2017-10-10 02:02:46 -07:00
home_deploy: cfg.home_deploy.map(TransactionConfig::from_load_struct).unwrap_or_default(),
foreign_deploy: cfg.foreign_deploy.map(TransactionConfig::from_load_struct).unwrap_or_default(),
deposit_relay: cfg.deposit_relay.map(TransactionConfig::from_load_struct).unwrap_or_default(),
withdraw_confirm: cfg.withdraw_confirm.map(TransactionConfig::from_load_struct).unwrap_or_default(),
withdraw_relay: cfg.withdraw_relay.map(TransactionConfig::from_load_struct).unwrap_or_default(),
2017-08-12 11:03:48 -07:00
}
}
}
2017-08-13 11:44:41 -07:00
#[derive(Debug, PartialEq, Default, Clone)]
2017-08-01 02:36:48 -07:00
pub struct TransactionConfig {
pub gas: u64,
pub gas_price: u64,
}
2017-08-12 11:03:48 -07:00
impl TransactionConfig {
fn from_load_struct(cfg: load::TransactionConfig) -> Self {
TransactionConfig {
gas: cfg.gas.unwrap_or_default(),
gas_price: cfg.gas_price.unwrap_or_default(),
}
}
}
2017-08-13 11:44:41 -07:00
#[derive(Debug, PartialEq, Clone)]
2017-08-10 08:55:46 -07:00
pub struct ContractConfig {
pub bin: Bytes,
2017-06-25 04:21:13 -07:00
}
#[derive(Debug, PartialEq, Clone)]
pub struct Authorities {
pub accounts: Vec<Address>,
pub required_signatures: u32,
}
2017-06-25 04:21:13 -07:00
/// Some config values may not be defined in `toml` file, but they should be specified at runtime.
2017-08-24 09:38:56 -07:00
/// `load` module separates `Config` representation in file with optional from the one used
2017-06-25 04:21:13 -07:00
/// in application.
mod load {
use std::path::PathBuf;
2017-08-03 15:48:12 -07:00
use web3::types::Address;
2017-06-25 04:21:13 -07:00
#[derive(Deserialize)]
2017-08-03 15:48:12 -07:00
#[serde(deny_unknown_fields)]
2017-06-25 04:21:13 -07:00
pub struct Config {
2017-10-10 02:02:46 -07:00
pub home: Node,
pub foreign: Node,
pub authorities: Authorities,
pub transactions: Option<Transactions>,
pub estimated_gas_cost_of_withdraw: u32,
2017-06-25 04:21:13 -07:00
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
2017-06-25 04:21:13 -07:00
pub struct Node {
2017-08-03 15:48:12 -07:00
pub account: Address,
2017-08-10 08:55:46 -07:00
pub contract: ContractConfig,
2017-08-24 09:38:56 -07:00
pub ipc: PathBuf,
2017-08-31 08:32:34 -07:00
pub request_timeout: Option<u64>,
2017-08-01 02:36:48 -07:00
pub poll_interval: Option<u64>,
pub required_confirmations: Option<usize>,
2017-08-01 02:36:48 -07:00
}
2017-08-12 11:03:48 -07:00
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
2017-08-12 11:03:48 -07:00
pub struct Transactions {
2017-10-10 02:02:46 -07:00
pub home_deploy: Option<TransactionConfig>,
pub foreign_deploy: Option<TransactionConfig>,
pub deposit_relay: Option<TransactionConfig>,
pub withdraw_confirm: Option<TransactionConfig>,
pub withdraw_relay: Option<TransactionConfig>,
2017-08-12 11:03:48 -07:00
}
2017-08-01 02:36:48 -07:00
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
2017-08-01 02:36:48 -07:00
pub struct TransactionConfig {
pub gas: Option<u64>,
pub gas_price: Option<u64>,
2017-06-25 04:21:13 -07:00
}
2017-08-10 08:55:46 -07:00
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
2017-08-10 08:55:46 -07:00
pub struct ContractConfig {
pub bin: PathBuf,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Authorities {
pub accounts: Vec<Address>,
pub required_signatures: u32,
}
2017-06-25 04:21:13 -07:00
}
#[cfg(test)]
mod tests {
2017-08-01 02:36:48 -07:00
use std::time::Duration;
use rustc_hex::FromHex;
use super::{Config, Node, ContractConfig, Transactions, Authorities, TransactionConfig};
2017-06-25 04:21:13 -07:00
#[test]
fn load_full_setup_from_str() {
let toml = r#"
estimated_gas_cost_of_withdraw = 100000
2017-10-10 02:02:46 -07:00
[home]
2017-08-03 15:48:12 -07:00
account = "0x1B68Cb0B50181FC4006Ce572cF346e596E51818b"
2017-10-10 02:02:46 -07:00
ipc = "/home.ipc"
2017-08-01 02:36:48 -07:00
poll_interval = 2
required_confirmations = 100
2017-06-25 04:21:13 -07:00
2017-10-10 02:02:46 -07:00
[home.contract]
bin = "../compiled_contracts/HomeBridge.bin"
2017-08-10 08:55:46 -07:00
2017-10-10 02:02:46 -07:00
[foreign]
2017-08-01 02:36:48 -07:00
account = "0x0000000000000000000000000000000000000001"
2017-10-10 02:02:46 -07:00
ipc = "/foreign.ipc"
2017-08-12 11:03:48 -07:00
2017-10-10 02:02:46 -07:00
[foreign.contract]
bin = "../compiled_contracts/ForeignBridge.bin"
[authorities]
accounts = [
"0x0000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000003"
]
required_signatures = 2
[transactions]
2017-10-10 02:02:46 -07:00
home_deploy = { gas = 20 }
2017-06-25 04:21:13 -07:00
"#;
2017-08-01 02:36:48 -07:00
let mut expected = Config {
txs: Transactions::default(),
2017-10-10 02:02:46 -07:00
home: Node {
account: "1B68Cb0B50181FC4006Ce572cF346e596E51818b".into(),
2017-10-10 02:02:46 -07:00
ipc: "/home.ipc".into(),
2017-08-10 08:55:46 -07:00
contract: ContractConfig {
bin: include_str!("../../compiled_contracts/HomeBridge.bin").from_hex().unwrap().into(),
2017-08-10 08:55:46 -07:00
},
2017-08-01 02:36:48 -07:00
poll_interval: Duration::from_secs(2),
2017-08-31 08:32:34 -07:00
request_timeout: Duration::from_secs(5),
2017-08-01 02:36:48 -07:00
required_confirmations: 100,
2017-06-25 04:21:13 -07:00
},
2017-10-10 02:02:46 -07:00
foreign: Node {
account: "0000000000000000000000000000000000000001".into(),
2017-08-10 08:55:46 -07:00
contract: ContractConfig {
bin: include_str!("../../compiled_contracts/ForeignBridge.bin").from_hex().unwrap().into(),
2017-08-10 08:55:46 -07:00
},
2017-10-10 02:02:46 -07:00
ipc: "/foreign.ipc".into(),
2017-08-01 02:36:48 -07:00
poll_interval: Duration::from_secs(1),
2017-08-31 08:32:34 -07:00
request_timeout: Duration::from_secs(5),
2017-08-01 02:36:48 -07:00
required_confirmations: 12,
},
authorities: Authorities {
accounts: vec![
"0000000000000000000000000000000000000001".into(),
"0000000000000000000000000000000000000002".into(),
"0000000000000000000000000000000000000003".into(),
],
required_signatures: 2,
},
estimated_gas_cost_of_withdraw: 100_000,
2017-06-25 04:21:13 -07:00
};
2017-08-01 02:36:48 -07:00
2017-10-10 02:02:46 -07:00
expected.txs.home_deploy = TransactionConfig {
gas: 20,
gas_price: 0,
};
2017-06-25 04:21:13 -07:00
let config = Config::load_from_str(toml).unwrap();
assert_eq!(expected, config);
}
#[test]
2017-09-28 15:59:19 -07:00
fn load_minimal_setup_from_str() {
2017-06-25 04:21:13 -07:00
let toml = r#"
estimated_gas_cost_of_withdraw = 200000000
2017-10-10 02:02:46 -07:00
[home]
2017-08-03 15:48:12 -07:00
account = "0x1B68Cb0B50181FC4006Ce572cF346e596E51818b"
2017-08-24 09:38:56 -07:00
ipc = ""
2017-08-10 08:55:46 -07:00
2017-10-10 02:02:46 -07:00
[home.contract]
bin = "../compiled_contracts/HomeBridge.bin"
2017-08-10 08:55:46 -07:00
2017-10-10 02:02:46 -07:00
[foreign]
2017-08-03 15:48:12 -07:00
account = "0x0000000000000000000000000000000000000001"
2017-08-24 09:38:56 -07:00
ipc = ""
2017-08-10 08:55:46 -07:00
2017-10-10 02:02:46 -07:00
[foreign.contract]
bin = "../compiled_contracts/ForeignBridge.bin"
[authorities]
accounts = [
"0x0000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000003"
]
required_signatures = 2
2017-06-25 04:21:13 -07:00
"#;
2017-08-10 08:55:46 -07:00
let expected = Config {
txs: Transactions::default(),
2017-10-10 02:02:46 -07:00
home: Node {
account: "1B68Cb0B50181FC4006Ce572cF346e596E51818b".into(),
2017-08-10 08:55:46 -07:00
ipc: "".into(),
contract: ContractConfig {
bin: include_str!("../../compiled_contracts/HomeBridge.bin").from_hex().unwrap().into(),
2017-08-10 08:55:46 -07:00
},
poll_interval: Duration::from_secs(1),
2017-08-31 08:32:34 -07:00
request_timeout: Duration::from_secs(5),
2017-08-10 08:55:46 -07:00
required_confirmations: 12,
},
2017-10-10 02:02:46 -07:00
foreign: Node {
account: "0000000000000000000000000000000000000001".into(),
2017-08-10 08:55:46 -07:00
ipc: "".into(),
contract: ContractConfig {
bin: include_str!("../../compiled_contracts/ForeignBridge.bin").from_hex().unwrap().into(),
2017-08-10 08:55:46 -07:00
},
poll_interval: Duration::from_secs(1),
2017-08-31 08:32:34 -07:00
request_timeout: Duration::from_secs(5),
2017-08-10 08:55:46 -07:00
required_confirmations: 12,
},
authorities: Authorities {
accounts: vec![
"0000000000000000000000000000000000000001".into(),
"0000000000000000000000000000000000000002".into(),
"0000000000000000000000000000000000000003".into(),
],
required_signatures: 2,
},
estimated_gas_cost_of_withdraw: 200_000_000,
2017-08-10 08:55:46 -07:00
};
2017-06-25 04:21:13 -07:00
let config = Config::load_from_str(toml).unwrap();
assert_eq!(expected, config);
}
2017-06-13 01:28:04 -07:00
}