Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move bridge contact addresses to primary configuration file. #109

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ and they can convert them back as well.

![withdraw](./res/withdraw.png)

### How to build
### How to build

Requires `rust` and `cargo`: [installation instructions.](https://www.rust-lang.org/en-US/install.html)

Expand Down Expand Up @@ -83,6 +83,7 @@ keystore = "/path/to/keystore"

[home]
account = "0x006e27b6a72e1f34c626762f3c4761547aff1421"
contract_address = "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7"
rpc_host = "http://localhost"
rpc_port = 8545
required_confirmations = 0
Expand All @@ -91,6 +92,7 @@ default_gas_price = 1_000_000_000 # 1 GWEI

[foreign]
account = "0x006e27b6a72e1f34c626762f3c4761547aff1421"
contract_address = "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"
rpc_host = "http://localhost"
rpc_port = 9545
required_confirmations = 0
Expand All @@ -110,11 +112,12 @@ withdraw_confirm = { gas = 3000000 }

#### Options

- `keystore` - path to a keystore directory with JSON keys
- `keystore` - path to a keystore directory with JSON keys

#### home/foreign options

- `home/foreign.account` - authority address on the home (**required**)
- `home/foreign.contract_address` - The address of the bridge contract on home/foreign chain. (**required** unless the configuration is being used in a deploy build [FIXME: clarify this description]).
- `home/foreign.rpc_host` - RPC host (**required**)
- `home/foreign.rpc_port` - RPC port (**defaults to 8545**)
- `home/foreign.required_confirmations` - number of confirmation required to consider transaction final on home (default: **12**)
Expand All @@ -141,17 +144,13 @@ withdraw_confirm = { gas = 3000000 }
### Database file format

```toml
home_contract_address = "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7"
foreign_contract_address = "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"
checked_deposit_relay = 120
checked_withdraw_relay = 121
checked_withdraw_confirm = 121
```

**all fields are required**

- `home_contract_address` - address of the bridge contract on home chain
- `foreign_contract_address` - address of the bridge contract on foreign chain
- `checked_deposit_relay` - number of the last block for which an authority has relayed deposits to the foreign
- `checked_withdraw_relay` - number of the last block for which an authority has relayed withdraws to the home
- `checked_withdraw_confirm` - number of the last block for which an authority has confirmed withdraw
104 changes: 58 additions & 46 deletions bridge/src/bridge/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum Deployed {
Existing(Database),
}

// FIXME: Needs documentation. What do these states signify?
#[cfg(feature = "deploy")]
enum DeployState<T: Transport + Clone> {
CheckIfNeeded,
Expand Down Expand Up @@ -64,61 +65,72 @@ impl<T: Transport + Clone> Future for Deploy<T> {
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
let _next_state = match self.state {
DeployState::CheckIfNeeded => match Database::load(&self.app.database_path).map_err(ErrorKind::from) {
Ok(database) => return Ok(Deployed::Existing(database).into()),
Err(ErrorKind::MissingFile(_e)) => {
#[cfg(feature = "deploy")] {
println!("deploy");
let main_data = self.app.home_bridge.constructor(
self.app.config.home.contract.bin.clone().0,
self.app.config.authorities.required_signatures,
self.app.config.authorities.accounts.clone(),
self.app.config.estimated_gas_cost_of_withdraw
);
let test_data = self.app.foreign_bridge.constructor(
self.app.config.foreign.contract.bin.clone().0,
self.app.config.authorities.required_signatures,
self.app.config.authorities.accounts.clone(),
self.app.config.estimated_gas_cost_of_withdraw
);
DeployState::CheckIfNeeded => {
let db = Database::load_user_defined(
&self.app.database_path,
self.app.config.home.contract_address.expect("Home contract \
address must be specified within config toml."),
self.app.config.foreign.contract_address.expect("Foreign contract \
address must be specified within config toml."))
.map_err(ErrorKind::from);

let main_tx = Transaction {
nonce: U256::zero(),
gas_price: self.app.config.txs.home_deploy.gas_price.into(),
gas: self.app.config.txs.home_deploy.gas.into(),
action: Action::Create,
value: U256::zero(),
data: main_data.into(),
};
match db {
Ok(database) => return Ok(Deployed::Existing(database).into()),
Err(ErrorKind::MissingFile(_e)) => {
#[cfg(feature = "deploy")] {
println!("deploy");
let main_data = self.app.home_bridge.constructor(
self.app.config.home.contract.bin.clone().0,
self.app.config.authorities.required_signatures,
self.app.config.authorities.accounts.clone(),
self.app.config.estimated_gas_cost_of_withdraw
);
let test_data = self.app.foreign_bridge.constructor(
self.app.config.foreign.contract.bin.clone().0,
self.app.config.authorities.required_signatures,
self.app.config.authorities.accounts.clone(),
self.app.config.estimated_gas_cost_of_withdraw
);

let test_tx = Transaction {
nonce: U256::zero(),
gas_price: self.app.config.txs.foreign_deploy.gas_price.into(),
gas: self.app.config.txs.foreign_deploy.gas.into(),
action: Action::Create,
value: U256::zero(),
data: test_data.into(),
};
let main_tx = Transaction {
nonce: U256::zero(),
gas_price: self.app.config.txs.home_deploy.gas_price.into(),
gas: self.app.config.txs.home_deploy.gas.into(),
action: Action::Create,
value: U256::zero(),
data: main_data.into(),
};

let main_future = api::send_transaction_with_nonce(self.app.connections.home.clone(), self.app.clone(),
self.app.config.home.clone(), main_tx, self.home_chain_id,
TransactionWithConfirmation(self.app.connections.home.clone(), self.app.config.home.poll_interval, self.app.config.home.required_confirmations));
let test_tx = Transaction {
nonce: U256::zero(),
gas_price: self.app.config.txs.foreign_deploy.gas_price.into(),
gas: self.app.config.txs.foreign_deploy.gas.into(),
action: Action::Create,
value: U256::zero(),
data: test_data.into(),
};

let test_future = api::send_transaction_with_nonce(self.app.connections.foreign.clone(), self.app.clone(),
self.app.config.foreign.clone(), test_tx, self.foreign_chain_id,
TransactionWithConfirmation(self.app.connections.foreign.clone(), self.app.config.foreign.poll_interval, self.app.config.foreign.required_confirmations));
let main_future = api::send_transaction_with_nonce(self.app.connections.home.clone(), self.app.clone(),
self.app.config.home.clone(), main_tx, self.home_chain_id,
TransactionWithConfirmation(self.app.connections.home.clone(), self.app.config.home.poll_interval, self.app.config.home.required_confirmations));

DeployState::Deploying(main_future.join(test_future))
}
#[cfg(not(feature = "deploy"))] {
return Err(ErrorKind::MissingFile(_e).into())
}
},
Err(err) => return Err(err.into()),
let test_future = api::send_transaction_with_nonce(self.app.connections.foreign.clone(), self.app.clone(),
self.app.config.foreign.clone(), test_tx, self.foreign_chain_id,
TransactionWithConfirmation(self.app.connections.foreign.clone(), self.app.config.foreign.poll_interval, self.app.config.foreign.required_confirmations));

DeployState::Deploying(main_future.join(test_future))
}
#[cfg(not(feature = "deploy"))] {
return Err(ErrorKind::MissingFile(_e).into())
}
},
Err(err) => return Err(err.into()),
}
},
#[cfg(feature = "deploy")]
DeployState::Deploying(ref mut future) => {
let (main_receipt, test_receipt) = try_ready!(future.poll());

let database = Database {
home_contract_address: main_receipt.contract_address.expect("contract creation receipt must have an address; qed"),
foreign_contract_address: test_receipt.contract_address.expect("contract creation receipt must have an address; qed"),
Expand Down
5 changes: 5 additions & 0 deletions bridge/src/bridge/gas_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ mod tests {
fn errored_request() {
let node = Node {
account: Address::new(),
contract_address: Some("49edf201c1e139282643d5e7c6fb0c7219ad1db7".into()),
request_timeout: Duration::from_secs(5),
poll_interval: Duration::from_secs(1),
required_confirmations: 0,
Expand Down Expand Up @@ -208,6 +209,7 @@ mod tests {
fn bad_json() {
let node = Node {
account: Address::new(),
contract_address: Some("49edf201c1e139282643d5e7c6fb0c7219ad1db7".into()),
request_timeout: Duration::from_secs(5),
poll_interval: Duration::from_secs(1),
required_confirmations: 0,
Expand Down Expand Up @@ -251,6 +253,7 @@ mod tests {
fn unexpected_json() {
let node = Node {
account: Address::new(),
contract_address: Some("49edf201c1e139282643d5e7c6fb0c7219ad1db7".into()),
request_timeout: Duration::from_secs(5),
poll_interval: Duration::from_secs(1),
required_confirmations: 0,
Expand Down Expand Up @@ -293,6 +296,7 @@ mod tests {
fn non_object_json() {
let node = Node {
account: Address::new(),
contract_address: Some("49edf201c1e139282643d5e7c6fb0c7219ad1db7".into()),
request_timeout: Duration::from_secs(5),
poll_interval: Duration::from_secs(1),
required_confirmations: 0,
Expand Down Expand Up @@ -335,6 +339,7 @@ mod tests {
fn correct_json() {
let node = Node {
account: Address::new(),
contract_address: Some("49edf201c1e139282643d5e7c6fb0c7219ad1db7".into()),
request_timeout: Duration::from_secs(5),
poll_interval: Duration::from_secs(1),
required_confirmations: 0,
Expand Down
12 changes: 8 additions & 4 deletions bridge/src/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<ES: Stream<Item = BridgeChecked, Error = Error>> Stream for Bridge<ES> {
.create(true)
.open(&self.path)?;

self.database.save(file)?;
self.database.store(file)?;
Ok(Async::Ready(Some(())))
}
}
Expand Down Expand Up @@ -221,6 +221,7 @@ impl<'a, T: Transport + 'a> Stream for BridgeEventStream<'a, T> {
#[cfg(test)]
mod tests {
extern crate tempdir;

use self::tempdir::TempDir;
use database::Database;
use super::{Bridge, BridgeChecked};
Expand All @@ -243,21 +244,24 @@ mod tests {
let mut event_loop = Core::new().unwrap();
let _ = event_loop.run(bridge.collect());

let db = Database::load(&path).unwrap();
let db = Database::load_stored(&path).unwrap();

assert_eq!(1, db.checked_deposit_relay);
assert_eq!(0, db.checked_withdraw_confirm);
assert_eq!(0, db.checked_withdraw_relay);

let bridge = Bridge {
path: path.clone(),
database: Database::default(),
event_stream: stream::iter_ok::<_, Error>(vec![BridgeChecked::DepositRelay(2), BridgeChecked::WithdrawConfirm(3), BridgeChecked::WithdrawRelay(2)]),
event_stream: stream::iter_ok::<_, Error>(vec![BridgeChecked::DepositRelay(2),
BridgeChecked::WithdrawConfirm(3), BridgeChecked::WithdrawRelay(2)]),
};

let mut event_loop = Core::new().unwrap();
let _ = event_loop.run(bridge.collect());

let db = Database::load(&path).unwrap();
let db = Database::load_stored(&path).unwrap();

assert_eq!(2, db.checked_deposit_relay);
assert_eq!(3, db.checked_withdraw_confirm);
assert_eq!(2, db.checked_withdraw_relay);
Expand Down
Loading