From 295aa1cfef3df6fb6757eaa798cbe88b1d09afcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:39:27 +0100 Subject: [PATCH 001/152] add integration tests to workspace --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bf900f8..df522cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["tests", "cli", "bridge"] +members = ["tests", "cli", "bridge", "integration-tests"] From e6f6797ac76e8844fe986bed4ab50d5646a171f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:43:28 +0100 Subject: [PATCH 002/152] add first rough integration test --- .gitignore | 2 + integration-tests/Cargo.toml | 16 ++ integration-tests/bridge_config.toml | 30 +++ integration-tests/home_chain.json | 31 +++ integration-tests/password.txt | 1 + integration-tests/src/main.rs | 289 +++++++++++++++++++++++++++ 6 files changed, 369 insertions(+) create mode 100644 integration-tests/Cargo.toml create mode 100644 integration-tests/bridge_config.toml create mode 100644 integration-tests/home_chain.json create mode 100644 integration-tests/password.txt create mode 100644 integration-tests/src/main.rs diff --git a/.gitignore b/.gitignore index 0b914ec..2b1a4a2 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ truffle/build node_modules compiled_contracts + +integration_tests/tmp diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml new file mode 100644 index 0000000..e7c686b --- /dev/null +++ b/integration-tests/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "integration-tests" +version = "0.1.0" +authors = ["snd "] + +[dependencies] +bridge = { path = "../bridge" } +futures = "0.1" +jsonrpc-core = "7.0" +web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } +serde_json = "1.0" +pretty_assertions = "0.2.1" +tempdir = "0.3.5" +ethereum-types = { git = "https://github.com/paritytech/primitives.git" } +rustc-hex = "1.0" +tokio-core = "0.1.8" diff --git a/integration-tests/bridge_config.toml b/integration-tests/bridge_config.toml new file mode 100644 index 0000000..c1d2979 --- /dev/null +++ b/integration-tests/bridge_config.toml @@ -0,0 +1,30 @@ +estimated_gas_cost_of_withdraw = 0 + +[home] +account = "0x00bd138abd70e2f00903268f3db08f2d25677c9e" +ipc = "./home.ipc" +required_confirmations = 0 + +[home.contract] +bin = "../compiled_contracts/HomeBridge.bin" + +[foreign] +account = "0x00bd138abd70e2f00903268f3db08f2d25677c9e" +ipc = "./foreign.ipc" +required_confirmations = 0 + +[foreign.contract] +bin = "../compiled_contracts/ForeignBridge.bin" + +[authorities] +accounts = [ + "0x00bd138abd70e2f00903268f3db08f2d25677c9e", +] +required_signatures = 1 + +[transactions] +home_deploy = { gas = 1000000 } +foreign_deploy = { gas = 3000000 } +deposit_relay = { gas = 100000 } +withdraw_relay = { gas = 3000000 } +withdraw_confirm = { gas = 3000000 } diff --git a/integration-tests/home_chain.json b/integration-tests/home_chain.json new file mode 100644 index 0000000..70d0cbb --- /dev/null +++ b/integration-tests/home_chain.json @@ -0,0 +1,31 @@ +{ + "name": "BridgeIntegrationTestHomeChain", + "engine": { + "instantSeal": null + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x11" + }, + "genesis": { + "seal": { + "generic": "0x0" + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x5B8D80" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0x006e27b6a72e1f34c626762f3c4761547aff1421": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } + } +} diff --git a/integration-tests/password.txt b/integration-tests/password.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/integration-tests/password.txt @@ -0,0 +1 @@ + diff --git a/integration-tests/src/main.rs b/integration-tests/src/main.rs new file mode 100644 index 0000000..561f96c --- /dev/null +++ b/integration-tests/src/main.rs @@ -0,0 +1,289 @@ +/// spins up two parity nodes with the dev chain. +/// starts bridge that connects the two. + +extern crate tempdir; +extern crate ethereum_types; +extern crate rustc_hex; +extern crate web3; +extern crate tokio_core; +extern crate bridge; +extern crate futures; + +use std::process::{Command, Child}; +use std::time::Duration; +use std::thread; +use std::path::Path; +use futures::Future; + +use tokio_core::reactor::Core; +use rustc_hex::ToHex; + +use web3::transports::ipc::Ipc; +use web3::api::Namespace; +use ethereum_types::{Address, U256}; + +const TMP_PATH: &str = "tmp"; + +fn parity_home_command() -> Command { + let mut command = Command::new("parity"); + command + .arg("--base-path").arg(format!("{}/home", TMP_PATH)) + // .arg("--chain").arg("home_chain.json") + .arg("--chain").arg("dev") + // .arg("--config").arg("parity_home_config.toml") + .arg("--ipc-path").arg("home.ipc") + // .arg("--db-path").arg("tmp/home_chain") + .arg("--logging").arg("rpc=trace") + // .arg("--no-jsonrpc") + .arg("--jsonrpc-port").arg("8550") + .arg("--jsonrpc-apis").arg("all") + .arg("--port").arg("30310") + .arg("--gasprice").arg("0") + .arg("--reseal-min-period").arg("0") + .arg("--no-ws") + .arg("--no-dapps") + .arg("--no-ui"); + command +} + +fn parity_foreign_command() -> Command { + let mut command = Command::new("parity"); + command + .arg("--base-path").arg(format!("{}/foreign", TMP_PATH)) + // .arg("--chain").arg("home_chain.json") + .arg("--chain").arg("dev") + // .arg("--config").arg("parity_home_config.toml") + .arg("--ipc-path").arg("foreign.ipc") + // .arg("--db-path").arg("tmp/home_chain") + .arg("--logging").arg("rpc=trace") + // .arg("--no-jsonrpc") + .arg("--jsonrpc-port").arg("8551") + .arg("--jsonrpc-apis").arg("all") + .arg("--port").arg("30311") + .arg("--gasprice").arg("0") + .arg("--reseal-min-period").arg("0") + .arg("--no-ws") + .arg("--no-dapps") + .arg("--no-ui"); + command +} + +fn main() { + if Path::new(TMP_PATH).exists() { + std::fs::remove_dir_all(TMP_PATH).expect("failed to remove tmp dir"); + } + let tmp_dir = tempdir::TempDir::new(TMP_PATH).expect("failed to create tmp dir"); + + // TODO home_base + // TODO foreign_base + + // build the bridge cli process + let exit_status = Command::new("cargo") + .env("RUST_BACKTRACE", "1") + .current_dir("../cli") + .arg("build") + .status() + .expect("failed to compile bridge cli"); + assert!(exit_status.success()); + + // start a parity node that represents the home chain + let mut parity_home = parity_home_command() + .spawn() + .expect("failed to spawn parity home node"); + + // start a parity node that represents the foreign chain + let mut parity_foreign = parity_foreign_command() + .spawn() + .expect("failed to spawn parity foreign node"); + + // give the clients time to start up + thread::sleep(Duration::from_millis(3000)); + + // create authority account on home + let exit_status = Command::new("curl") + .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) + .arg("-H").arg("Content-Type: application/json") + .arg("-X").arg("POST") + .arg("localhost:8550") + .status() + .expect("failed to create authority account on home"); + assert!(exit_status.success()); + + // create authority account on foreign + let exit_status = Command::new("curl") + .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) + .arg("-H").arg("Content-Type: application/json") + .arg("-X").arg("POST") + .arg("localhost:8551") + .status() + .expect("failed to create/unlock authority account on foreign"); + assert!(exit_status.success()); + + // give the operations time to complete + thread::sleep(Duration::from_millis(5000)); + + // kill the clients so we can restart them with the accounts unlocked + parity_home.kill().unwrap(); + parity_foreign.kill().unwrap(); + + // wait for clients to shut down + thread::sleep(Duration::from_millis(5000)); + + // start a parity node that represents the home chain with accounts unlocked + let mut parity_home = parity_home_command() + .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") + .arg("--password").arg("password.txt") + .spawn() + .expect("failed to spawn parity home node"); + + // start a parity node that represents the foreign chain with accounts unlocked + let mut parity_foreign = parity_foreign_command() + .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") + .arg("--password").arg("password.txt") + .spawn() + .expect("failed to spawn parity foreign node"); + + // give nodes time to start up + thread::sleep(Duration::from_millis(10000)); + + // unlock authority account on home so bridge can connect later + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8550") + // .status() + // .expect("failed to unlock authority account on home"); + // assert!(exit_status.success()); + + // unlock authority account on home so bridge can connect later + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8551") + // .status() + // .expect("failed to unlock authority account on foreign"); + // assert!(exit_status.success()); + + // unlock user account which has a lot of ether on dev chain + // on home and foreign + // so we can make transactions + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8550") + // .status() + // .expect("failed to unlock user account on home"); + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8551") + // .status() + // .expect("failed to unlock user account on foreign"); + + // start bridge authority 1 + let mut bridge1 = Command::new("env") + .arg("RUST_BACKTRACE=1") + .arg("../target/debug/bridge") + // .env("RUST_BACKTRACE", "1") + .env("RUST_LOG", "info") + .arg("--config").arg("bridge_config.toml") + .arg("--database").arg("tmp/bridge1_db.txt") + .spawn() + .expect("failed to spawn bridge process"); + + // give the bridge time to start up and deploy the contracts + thread::sleep(Duration::from_millis(10000)); + + // user deposits into HomeBridge + let exit_status = Command::new("curl") + .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ + "from": "0x00a329c0648769a73afac7f9381e08fb43dbea72", + "to": "0xebd3944af37ccc6b67ff61239ac4fef229c8f69f", + "value": "0x186a0" + }],"id":0}"#) + .arg("-H").arg("Content-Type: application/json") + .arg("-X").arg("POST") + .arg("localhost:8550") + .status() + .expect("failed to deposit into HomeBridge"); + assert!(exit_status.success()); + + println!("\ndeposit into home sent\n"); + + // wait for it to be mined + thread::sleep(Duration::from_millis(10000)); + + let mut event_loop = Core::new().unwrap(); + let foreign_transport = Ipc::with_event_loop("foreign.ipc", &event_loop.handle()) + .expect("failed to connect to foreign.ipc"); + let foreign = bridge::contracts::foreign::ForeignBridge::default(); + let foreign_eth = web3::api::Eth::new(foreign_transport); + let home_transport = Ipc::with_event_loop("home.ipc", &event_loop.handle()) + .expect("failed to connect to home.ipc"); + let home = bridge::contracts::home::HomeBridge::default(); + let home_eth = web3::api::Eth::new(home_transport); + + // balance on ForeignBridge should have increased + let balance_payload = foreign.functions().balances().input(Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72")); + println!("balance_payload: {}", balance_payload.to_hex()); + + let future = foreign_eth.call(web3::types::CallRequest{ + from: None, + to: web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..]), + gas: None, + gas_price: None, + value: None, + data: Some(web3::types::Bytes(balance_payload)), + }, None); + + println!("waiting for future"); + let response = event_loop.run(future).unwrap(); + let balance = U256::from(response.0.as_slice()); + assert_eq!(balance, U256::from(100000)); + + println!("\nconfirmed that deposit reached foreign\n"); + + thread::sleep(Duration::from_millis(10000)); + + // withdraw + let transfer_payload = foreign.functions() + .transfer_home_via_relay() + .input( + Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2"), + U256::from(100000)); + let future = foreign_eth.send_transaction(web3::types::TransactionRequest{ + from: web3::types::Address::from(&Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72").0[..]), + to: Some(web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..])), + gas: None, + gas_price: None, + value: None, + data: Some(web3::types::Bytes(transfer_payload)), + condition: None, + nonce: None, + }); + let response = event_loop.run(future).unwrap(); + + println!("\ntransfer to home transaction sent\n"); + + thread::sleep(Duration::from_millis(10000)); + + // test that withdraw completed + let future = home_eth.balance(web3::types::Address::from(&Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2").0[..]), None); + println!("waiting for future"); + let balance = event_loop.run(future).unwrap(); + assert!(balance > web3::types::U256::from(0)); + + println!("\nconfirmed that withdraw reached home\n"); + + bridge1.kill().unwrap(); + + // wait for bridge to shut down + thread::sleep(Duration::from_millis(1000)); + + parity_home.kill().unwrap(); + parity_foreign.kill().unwrap(); +} From adc4a0a1ebcb45f5457ac9df1a6f7f33ef3f1a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:45:11 +0100 Subject: [PATCH 003/152] integration-tests: indent with tabs --- integration-tests/src/main.rs | 418 +++++++++++++++++----------------- 1 file changed, 209 insertions(+), 209 deletions(-) diff --git a/integration-tests/src/main.rs b/integration-tests/src/main.rs index 561f96c..f5ee09c 100644 --- a/integration-tests/src/main.rs +++ b/integration-tests/src/main.rs @@ -25,265 +25,265 @@ use ethereum_types::{Address, U256}; const TMP_PATH: &str = "tmp"; fn parity_home_command() -> Command { - let mut command = Command::new("parity"); - command - .arg("--base-path").arg(format!("{}/home", TMP_PATH)) - // .arg("--chain").arg("home_chain.json") - .arg("--chain").arg("dev") - // .arg("--config").arg("parity_home_config.toml") - .arg("--ipc-path").arg("home.ipc") - // .arg("--db-path").arg("tmp/home_chain") - .arg("--logging").arg("rpc=trace") - // .arg("--no-jsonrpc") - .arg("--jsonrpc-port").arg("8550") - .arg("--jsonrpc-apis").arg("all") - .arg("--port").arg("30310") - .arg("--gasprice").arg("0") - .arg("--reseal-min-period").arg("0") - .arg("--no-ws") - .arg("--no-dapps") - .arg("--no-ui"); - command + let mut command = Command::new("parity"); + command + .arg("--base-path").arg(format!("{}/home", TMP_PATH)) + // .arg("--chain").arg("home_chain.json") + .arg("--chain").arg("dev") + // .arg("--config").arg("parity_home_config.toml") + .arg("--ipc-path").arg("home.ipc") + // .arg("--db-path").arg("tmp/home_chain") + .arg("--logging").arg("rpc=trace") + // .arg("--no-jsonrpc") + .arg("--jsonrpc-port").arg("8550") + .arg("--jsonrpc-apis").arg("all") + .arg("--port").arg("30310") + .arg("--gasprice").arg("0") + .arg("--reseal-min-period").arg("0") + .arg("--no-ws") + .arg("--no-dapps") + .arg("--no-ui"); + command } fn parity_foreign_command() -> Command { - let mut command = Command::new("parity"); - command - .arg("--base-path").arg(format!("{}/foreign", TMP_PATH)) - // .arg("--chain").arg("home_chain.json") - .arg("--chain").arg("dev") - // .arg("--config").arg("parity_home_config.toml") - .arg("--ipc-path").arg("foreign.ipc") - // .arg("--db-path").arg("tmp/home_chain") - .arg("--logging").arg("rpc=trace") - // .arg("--no-jsonrpc") - .arg("--jsonrpc-port").arg("8551") - .arg("--jsonrpc-apis").arg("all") - .arg("--port").arg("30311") - .arg("--gasprice").arg("0") - .arg("--reseal-min-period").arg("0") - .arg("--no-ws") - .arg("--no-dapps") - .arg("--no-ui"); - command + let mut command = Command::new("parity"); + command + .arg("--base-path").arg(format!("{}/foreign", TMP_PATH)) + // .arg("--chain").arg("home_chain.json") + .arg("--chain").arg("dev") + // .arg("--config").arg("parity_home_config.toml") + .arg("--ipc-path").arg("foreign.ipc") + // .arg("--db-path").arg("tmp/home_chain") + .arg("--logging").arg("rpc=trace") + // .arg("--no-jsonrpc") + .arg("--jsonrpc-port").arg("8551") + .arg("--jsonrpc-apis").arg("all") + .arg("--port").arg("30311") + .arg("--gasprice").arg("0") + .arg("--reseal-min-period").arg("0") + .arg("--no-ws") + .arg("--no-dapps") + .arg("--no-ui"); + command } fn main() { - if Path::new(TMP_PATH).exists() { - std::fs::remove_dir_all(TMP_PATH).expect("failed to remove tmp dir"); - } - let tmp_dir = tempdir::TempDir::new(TMP_PATH).expect("failed to create tmp dir"); + if Path::new(TMP_PATH).exists() { + std::fs::remove_dir_all(TMP_PATH).expect("failed to remove tmp dir"); + } + let tmp_dir = tempdir::TempDir::new(TMP_PATH).expect("failed to create tmp dir"); - // TODO home_base - // TODO foreign_base + // TODO home_base + // TODO foreign_base - // build the bridge cli process - let exit_status = Command::new("cargo") - .env("RUST_BACKTRACE", "1") - .current_dir("../cli") - .arg("build") - .status() + // build the bridge cli process + let exit_status = Command::new("cargo") + .env("RUST_BACKTRACE", "1") + .current_dir("../cli") + .arg("build") + .status() .expect("failed to compile bridge cli"); assert!(exit_status.success()); - // start a parity node that represents the home chain - let mut parity_home = parity_home_command() - .spawn() - .expect("failed to spawn parity home node"); + // start a parity node that represents the home chain + let mut parity_home = parity_home_command() + .spawn() + .expect("failed to spawn parity home node"); - // start a parity node that represents the foreign chain - let mut parity_foreign = parity_foreign_command() - .spawn() - .expect("failed to spawn parity foreign node"); + // start a parity node that represents the foreign chain + let mut parity_foreign = parity_foreign_command() + .spawn() + .expect("failed to spawn parity foreign node"); - // give the clients time to start up - thread::sleep(Duration::from_millis(3000)); + // give the clients time to start up + thread::sleep(Duration::from_millis(3000)); - // create authority account on home - let exit_status = Command::new("curl") - .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) - .arg("-H").arg("Content-Type: application/json") - .arg("-X").arg("POST") - .arg("localhost:8550") - .status() + // create authority account on home + let exit_status = Command::new("curl") + .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) + .arg("-H").arg("Content-Type: application/json") + .arg("-X").arg("POST") + .arg("localhost:8550") + .status() .expect("failed to create authority account on home"); assert!(exit_status.success()); - // create authority account on foreign - let exit_status = Command::new("curl") - .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) - .arg("-H").arg("Content-Type: application/json") - .arg("-X").arg("POST") - .arg("localhost:8551") - .status() + // create authority account on foreign + let exit_status = Command::new("curl") + .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) + .arg("-H").arg("Content-Type: application/json") + .arg("-X").arg("POST") + .arg("localhost:8551") + .status() .expect("failed to create/unlock authority account on foreign"); assert!(exit_status.success()); - // give the operations time to complete - thread::sleep(Duration::from_millis(5000)); + // give the operations time to complete + thread::sleep(Duration::from_millis(5000)); - // kill the clients so we can restart them with the accounts unlocked - parity_home.kill().unwrap(); - parity_foreign.kill().unwrap(); + // kill the clients so we can restart them with the accounts unlocked + parity_home.kill().unwrap(); + parity_foreign.kill().unwrap(); - // wait for clients to shut down - thread::sleep(Duration::from_millis(5000)); + // wait for clients to shut down + thread::sleep(Duration::from_millis(5000)); - // start a parity node that represents the home chain with accounts unlocked - let mut parity_home = parity_home_command() - .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") - .arg("--password").arg("password.txt") - .spawn() - .expect("failed to spawn parity home node"); + // start a parity node that represents the home chain with accounts unlocked + let mut parity_home = parity_home_command() + .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") + .arg("--password").arg("password.txt") + .spawn() + .expect("failed to spawn parity home node"); - // start a parity node that represents the foreign chain with accounts unlocked - let mut parity_foreign = parity_foreign_command() - .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") - .arg("--password").arg("password.txt") - .spawn() - .expect("failed to spawn parity foreign node"); + // start a parity node that represents the foreign chain with accounts unlocked + let mut parity_foreign = parity_foreign_command() + .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") + .arg("--password").arg("password.txt") + .spawn() + .expect("failed to spawn parity foreign node"); - // give nodes time to start up - thread::sleep(Duration::from_millis(10000)); + // give nodes time to start up + thread::sleep(Duration::from_millis(10000)); - // unlock authority account on home so bridge can connect later - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8550") - // .status() - // .expect("failed to unlock authority account on home"); + // unlock authority account on home so bridge can connect later + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8550") + // .status() + // .expect("failed to unlock authority account on home"); // assert!(exit_status.success()); - // unlock authority account on home so bridge can connect later - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8551") - // .status() - // .expect("failed to unlock authority account on foreign"); + // unlock authority account on home so bridge can connect later + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8551") + // .status() + // .expect("failed to unlock authority account on foreign"); // assert!(exit_status.success()); - // unlock user account which has a lot of ether on dev chain - // on home and foreign - // so we can make transactions - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8550") - // .status() - // .expect("failed to unlock user account on home"); - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8551") - // .status() - // .expect("failed to unlock user account on foreign"); + // unlock user account which has a lot of ether on dev chain + // on home and foreign + // so we can make transactions + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8550") + // .status() + // .expect("failed to unlock user account on home"); + // let exit_status = Command::new("curl") + // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) + // .arg("-H").arg("Content-Type: application/json") + // .arg("-X").arg("POST") + // .arg("localhost:8551") + // .status() + // .expect("failed to unlock user account on foreign"); - // start bridge authority 1 - let mut bridge1 = Command::new("env") - .arg("RUST_BACKTRACE=1") - .arg("../target/debug/bridge") - // .env("RUST_BACKTRACE", "1") - .env("RUST_LOG", "info") - .arg("--config").arg("bridge_config.toml") - .arg("--database").arg("tmp/bridge1_db.txt") - .spawn() - .expect("failed to spawn bridge process"); + // start bridge authority 1 + let mut bridge1 = Command::new("env") + .arg("RUST_BACKTRACE=1") + .arg("../target/debug/bridge") + // .env("RUST_BACKTRACE", "1") + .env("RUST_LOG", "info") + .arg("--config").arg("bridge_config.toml") + .arg("--database").arg("tmp/bridge1_db.txt") + .spawn() + .expect("failed to spawn bridge process"); - // give the bridge time to start up and deploy the contracts - thread::sleep(Duration::from_millis(10000)); + // give the bridge time to start up and deploy the contracts + thread::sleep(Duration::from_millis(10000)); - // user deposits into HomeBridge - let exit_status = Command::new("curl") - .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ - "from": "0x00a329c0648769a73afac7f9381e08fb43dbea72", - "to": "0xebd3944af37ccc6b67ff61239ac4fef229c8f69f", - "value": "0x186a0" - }],"id":0}"#) - .arg("-H").arg("Content-Type: application/json") - .arg("-X").arg("POST") - .arg("localhost:8550") - .status() + // user deposits into HomeBridge + let exit_status = Command::new("curl") + .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ + "from": "0x00a329c0648769a73afac7f9381e08fb43dbea72", + "to": "0xebd3944af37ccc6b67ff61239ac4fef229c8f69f", + "value": "0x186a0" + }],"id":0}"#) + .arg("-H").arg("Content-Type: application/json") + .arg("-X").arg("POST") + .arg("localhost:8550") + .status() .expect("failed to deposit into HomeBridge"); assert!(exit_status.success()); - println!("\ndeposit into home sent\n"); + println!("\ndeposit into home sent\n"); - // wait for it to be mined - thread::sleep(Duration::from_millis(10000)); + // wait for it to be mined + thread::sleep(Duration::from_millis(10000)); let mut event_loop = Core::new().unwrap(); - let foreign_transport = Ipc::with_event_loop("foreign.ipc", &event_loop.handle()) - .expect("failed to connect to foreign.ipc"); - let foreign = bridge::contracts::foreign::ForeignBridge::default(); - let foreign_eth = web3::api::Eth::new(foreign_transport); - let home_transport = Ipc::with_event_loop("home.ipc", &event_loop.handle()) - .expect("failed to connect to home.ipc"); - let home = bridge::contracts::home::HomeBridge::default(); - let home_eth = web3::api::Eth::new(home_transport); + let foreign_transport = Ipc::with_event_loop("foreign.ipc", &event_loop.handle()) + .expect("failed to connect to foreign.ipc"); + let foreign = bridge::contracts::foreign::ForeignBridge::default(); + let foreign_eth = web3::api::Eth::new(foreign_transport); + let home_transport = Ipc::with_event_loop("home.ipc", &event_loop.handle()) + .expect("failed to connect to home.ipc"); + let home = bridge::contracts::home::HomeBridge::default(); + let home_eth = web3::api::Eth::new(home_transport); - // balance on ForeignBridge should have increased - let balance_payload = foreign.functions().balances().input(Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72")); - println!("balance_payload: {}", balance_payload.to_hex()); + // balance on ForeignBridge should have increased + let balance_payload = foreign.functions().balances().input(Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72")); + println!("balance_payload: {}", balance_payload.to_hex()); - let future = foreign_eth.call(web3::types::CallRequest{ - from: None, - to: web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..]), - gas: None, - gas_price: None, - value: None, - data: Some(web3::types::Bytes(balance_payload)), - }, None); + let future = foreign_eth.call(web3::types::CallRequest{ + from: None, + to: web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..]), + gas: None, + gas_price: None, + value: None, + data: Some(web3::types::Bytes(balance_payload)), + }, None); - println!("waiting for future"); - let response = event_loop.run(future).unwrap(); - let balance = U256::from(response.0.as_slice()); - assert_eq!(balance, U256::from(100000)); + println!("waiting for future"); + let response = event_loop.run(future).unwrap(); + let balance = U256::from(response.0.as_slice()); + assert_eq!(balance, U256::from(100000)); - println!("\nconfirmed that deposit reached foreign\n"); + println!("\nconfirmed that deposit reached foreign\n"); - thread::sleep(Duration::from_millis(10000)); + thread::sleep(Duration::from_millis(10000)); - // withdraw - let transfer_payload = foreign.functions() - .transfer_home_via_relay() - .input( - Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2"), - U256::from(100000)); - let future = foreign_eth.send_transaction(web3::types::TransactionRequest{ - from: web3::types::Address::from(&Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72").0[..]), - to: Some(web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..])), - gas: None, - gas_price: None, - value: None, - data: Some(web3::types::Bytes(transfer_payload)), - condition: None, - nonce: None, - }); - let response = event_loop.run(future).unwrap(); + // withdraw + let transfer_payload = foreign.functions() + .transfer_home_via_relay() + .input( + Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2"), + U256::from(100000)); + let future = foreign_eth.send_transaction(web3::types::TransactionRequest{ + from: web3::types::Address::from(&Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72").0[..]), + to: Some(web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..])), + gas: None, + gas_price: None, + value: None, + data: Some(web3::types::Bytes(transfer_payload)), + condition: None, + nonce: None, + }); + let response = event_loop.run(future).unwrap(); - println!("\ntransfer to home transaction sent\n"); + println!("\ntransfer to home transaction sent\n"); - thread::sleep(Duration::from_millis(10000)); + thread::sleep(Duration::from_millis(10000)); - // test that withdraw completed - let future = home_eth.balance(web3::types::Address::from(&Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2").0[..]), None); - println!("waiting for future"); - let balance = event_loop.run(future).unwrap(); - assert!(balance > web3::types::U256::from(0)); + // test that withdraw completed + let future = home_eth.balance(web3::types::Address::from(&Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2").0[..]), None); + println!("waiting for future"); + let balance = event_loop.run(future).unwrap(); + assert!(balance > web3::types::U256::from(0)); - println!("\nconfirmed that withdraw reached home\n"); + println!("\nconfirmed that withdraw reached home\n"); - bridge1.kill().unwrap(); + bridge1.kill().unwrap(); - // wait for bridge to shut down - thread::sleep(Duration::from_millis(1000)); + // wait for bridge to shut down + thread::sleep(Duration::from_millis(1000)); - parity_home.kill().unwrap(); - parity_foreign.kill().unwrap(); + parity_home.kill().unwrap(); + parity_foreign.kill().unwrap(); } From 0a27da3c33a7ab21168aefaa33025e0418b24aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:47:13 +0100 Subject: [PATCH 004/152] withdraw_confirm.rs: add some info level logging --- bridge/src/bridge/withdraw_confirm.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index ccf9bdf..84e6577 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -88,9 +88,13 @@ impl Stream for WithdrawConfirm { let next_state = match self.state { WithdrawConfirmState::Wait => { let item = try_stream!(self.logs.poll()); + info!("got {} new withdraws to sign", item.logs.len()); let withdraws = item.logs .into_iter() - .map(|log| withdraw_confirm_sign_payload(&self.app.foreign_bridge, log)) + .map(|log| { + info!("withdraw is ready for signature submission. tx hash {}", log.transaction_hash.unwrap()); + withdraw_confirm_sign_payload(&self.app.foreign_bridge, log) + }) .collect::, _>>()?; let requests = withdraws.clone() @@ -102,6 +106,7 @@ impl Stream for WithdrawConfirm { }) .collect::>(); + info!("signing"); WithdrawConfirmState::SignWithdraws { future: join_all(requests), withdraws: withdraws, @@ -110,6 +115,7 @@ impl Stream for WithdrawConfirm { }, WithdrawConfirmState::SignWithdraws { ref mut future, ref mut withdraws, block } => { let signatures = try_ready!(future.poll()); + info!("signing complete"); // borrow checker... let app = &self.app; let foreign_contract = &self.foreign_contract; @@ -128,12 +134,14 @@ impl Stream for WithdrawConfirm { condition: None, }) .map(|request| { + info!("submitting signature"); app.timer.timeout( api::send_transaction(&app.connections.foreign, request), app.config.foreign.request_timeout) }) .collect::>(); + info!("submitting {} signatures", confirmations.len()); WithdrawConfirmState::ConfirmWithdraws { future: join_all(confirmations), block, @@ -141,10 +149,14 @@ impl Stream for WithdrawConfirm { }, WithdrawConfirmState::ConfirmWithdraws { ref mut future, block } => { let _ = try_ready!(future.poll()); + info!("submitting signatures complete"); WithdrawConfirmState::Yield(Some(block)) }, WithdrawConfirmState::Yield(ref mut block) => match block.take() { - None => WithdrawConfirmState::Wait, + None => { + info!("waiting for new withdraws that should get signed"); + WithdrawConfirmState::Wait + }, some => return Ok(some.into()), } }; From e07485a792a2e6d6795f0a85486cb8a65d934e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:47:54 +0100 Subject: [PATCH 005/152] withdraw_confirm.rs: fn withdraw_submit_signature_payload: assert lengths --- bridge/src/bridge/withdraw_confirm.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 84e6577..e5e99b8 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -32,8 +32,10 @@ fn withdraw_confirm_sign_payload(foreign: &foreign::ForeignBridge, log: Log) -> Ok(result.into()) } -fn withdraw_submit_signature_payload(foreign: &foreign::ForeignBridge, withdraw_payload: Bytes, signature: H520) -> Bytes { - foreign.functions().submit_signature().input(signature.to_vec(), withdraw_payload.0).into() +fn withdraw_submit_signature_payload(foreign: &foreign::ForeignBridge, withdraw_message: Bytes, signature: H520) -> Bytes { + assert_eq!(signature.0.len(), 65); + assert_eq!(withdraw_message.0.len(), 84, "ForeignBridge never accepts messages with len != 84 bytes; qed"); + foreign.functions().submit_signature().input(signature.0.to_vec(), withdraw_message.0).into() } /// State of withdraw confirmation. From 798755db8935a5b094f8e4292775a575268e659d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:48:18 +0100 Subject: [PATCH 006/152] withdraw_confirm.rs: withdraw -> withdraw_message --- bridge/src/bridge/withdraw_confirm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index e5e99b8..f5aac9f 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -124,7 +124,7 @@ impl Stream for WithdrawConfirm { let confirmations = withdraws .drain(ops::RangeFull) .zip(signatures.into_iter()) - .map(|(withdraw, signature)| withdraw_submit_signature_payload(&app.foreign_bridge, withdraw, signature)) + .map(|(withdraw_message, signature)| withdraw_submit_signature_payload(&app.foreign_bridge, withdraw_message, signature)) .map(|payload| TransactionRequest { from: app.config.foreign.account.clone(), to: Some(foreign_contract.clone()), From ee786ccd2c572927dbb8e494a6cd699785c5c177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:49:54 +0100 Subject: [PATCH 007/152] withdraw_relay.rs: add some info level logging to ease troubleshooting --- bridge/src/bridge/withdraw_relay.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index bfce4a5..e37894b 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -37,6 +37,7 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 }; let collected_signatures = foreign.events().collected_signatures().parse_log(raw_log)?; if collected_signatures.authority != my_address.0 { + info!("bridge not responsible for relaying transaction to home. tx hash: {}", log.transaction_hash.unwrap()); // this authority is not responsible for relaying this transaction. // someone else will relay this transaction to home. return Ok(None); @@ -141,13 +142,17 @@ impl Stream for WithdrawRelay { let next_state = match self.state { WithdrawRelayState::Wait => { let item = try_stream!(self.logs.poll()); + info!("got {} new signed withdraws to relay", item.logs.len()); let assignments = item.logs .into_iter() - .map(|log| signatures_payload( + .map(|log| { + info!("collected signature is ready for relay: tx hash: {}", log.transaction_hash.unwrap()); + signatures_payload( &self.app.foreign_bridge, self.app.config.authorities.required_signatures, self.app.config.foreign.account.clone(), - log)) + log) + }) .collect::>>()?; let (signatures, messages): (Vec<_>, Vec<_>) = assignments.into_iter() @@ -176,7 +181,7 @@ impl Stream for WithdrawRelay { .map(|calls| join_all(calls)) .collect::>(); - // wait for fetching of messages and signatures to complete + info!("fetching messages and signatures"); WithdrawRelayState::FetchMessagesSignatures { future: join_all(message_calls).join(join_all(signature_calls)), block: item.to, @@ -204,6 +209,7 @@ impl Stream for WithdrawRelay { }) .collect::>(); + info!("fetching whether message values are sufficent"); WithdrawRelayState::FetchMessageValueSufficient { future: join_all(message_value_sufficient_payloads), messages, @@ -218,6 +224,7 @@ impl Stream for WithdrawRelay { block } => { let message_value_sufficient = try_ready!(future.poll()); + info!("fetching whether message values are sufficent complete"); let app = &self.app; let home_contract = &self.home_contract; @@ -227,12 +234,16 @@ impl Stream for WithdrawRelay { .zip(message_value_sufficient.into_iter()) // ignore those messages that don't have sufficient // value to pay for the relay gas cost - .filter(|&(_, ref is_message_value_sufficient)| { + .filter(|&((ref message, _), ref is_message_value_sufficient)| { // TODO [snd] this is ugly. // in the future ethabi should return a bool // for `is_message_value_sufficient` // since the contract function returns a bool - U256::from(is_message_value_sufficient.0.as_slice()) == U256::from(1) + let is_sufficient = U256::from(is_message_value_sufficient.0.as_slice()) == U256::from(1); + if !is_sufficient { + info!("value in message is not sufficient to cover relay costs. ignoring. message: {}", message.0.to_hex()); + } + is_sufficient }) .map(|((message, signatures), _)| withdraw_relay_payload(&app.home_bridge, &signatures, message)) .map(|payload| TransactionRequest { @@ -251,7 +262,7 @@ impl Stream for WithdrawRelay { app.config.home.request_timeout) }) .collect::>(); - // wait for relays to complete + info!("relaying {} withdraws", relays.len()); WithdrawRelayState::RelayWithdraws { future: join_all(relays), block, @@ -259,10 +270,14 @@ impl Stream for WithdrawRelay { }, WithdrawRelayState::RelayWithdraws { ref mut future, block } => { let _ = try_ready!(future.poll()); + info!("relaying withdraws complete"); WithdrawRelayState::Yield(Some(block)) }, WithdrawRelayState::Yield(ref mut block) => match block.take() { - None => WithdrawRelayState::Wait, + None => { + info!("waiting for signed withdraws to relay"); + WithdrawRelayState::Wait + }, some => return Ok(some.into()), } }; From 303cf4ed84aedd81308ce673d90c552f9e3e9732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:55:14 +0100 Subject: [PATCH 008/152] .travis.yml: run integration test on travis --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 484b204..28df0c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,17 @@ matrix: - sudo apt-get install solc -y script: - cargo test --all + - language: rust + rust: stable + cache: cargo + fast_finish: false + before_script: + - sudo add-apt-repository ppa:ethereum/ethereum -y + - sudo apt-get update -y + - sudo apt-get install solc -y + - cd integration-tests + script: + - cargo run - language: node_js node_js: node cache: yarn From 60a1eeaf081db6642a8715052e48e725d8112ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 14:59:28 +0100 Subject: [PATCH 009/152] .travis.yml: install parity for integration tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 28df0c2..b376fe6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,7 @@ matrix: - sudo add-apt-repository ppa:ethereum/ethereum -y - sudo apt-get update -y - sudo apt-get install solc -y + - bash <(curl https://get.parity.io -kL) - cd integration-tests script: - cargo run From a3148bc90e4d3987861d12c514b87299ff3b8f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 15:01:51 +0100 Subject: [PATCH 010/152] Cargo.lock: update --- Cargo.lock | 684 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 402 insertions(+), 282 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 393a672..7c4a84d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,10 @@ name = "tests" version = "0.1.0" dependencies = [ "bridge 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] @@ -20,74 +20,72 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "arrayvec" -version = "0.3.23" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "0.7.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bridge" version = "0.1.0" dependencies = [ - "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", @@ -98,55 +96,43 @@ name = "bridge-cli" version = "0.1.0" dependencies = [ "bridge 0.1.0", - "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "byteorder" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cc" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "conv" -version = "0.3.3" +name = "crunchy" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "custom_derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "dbghelp-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "difference" @@ -155,13 +141,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "docopt" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -175,29 +161,29 @@ name = "env_logger" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.11.0-rc.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethabi" -version = "4.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -207,33 +193,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ethabi-derive" -version = "4.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ethabi 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethbloom" +version = "0.3.0" +source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)", + "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethereum-types" +version = "0.1.4" +source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom 0.3.0 (git+https://github.com/paritytech/primitives.git)", + "fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", +] + +[[package]] +name = "fixed-hash" +version = "0.1.1" +source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +dependencies = [ + "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-cpupool" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "gcc" -version = "0.3.53" +name = "heapsize" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "heck" @@ -245,55 +281,72 @@ dependencies = [ [[package]] name = "httparse" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.11.2" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "integration-tests" +version = "0.1.0" +dependencies = [ + "bridge 0.1.0", + "ethereum-types 0.1.4 (git+https://github.com/paritytech/primitives.git)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] [[package]] name = "iovec" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -312,39 +365,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "0.2.8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazycell" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.30" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "magenta" -version = "0.1.1" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "magenta-sys" -version = "0.1.1" +name = "log" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -352,37 +399,37 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "1.0.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.10" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -394,8 +441,8 @@ name = "mio-uds" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -416,35 +463,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nodrop" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "num-traits" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.6.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "odds" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -457,28 +501,27 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.4.5" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.2.4" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "percent-encoding" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -496,16 +539,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.3.16" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.31" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -522,13 +575,13 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -539,9 +592,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex-syntax" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "relay" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.5" @@ -559,10 +620,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc_version" -version = "0.1.7" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -577,27 +638,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "semver" -version = "0.1.20" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.11" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.11" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -606,13 +675,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.2" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -620,6 +689,11 @@ name = "slab" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "slab" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smallvec" version = "0.2.1" @@ -627,7 +701,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.4.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -668,7 +742,7 @@ name = "tempdir" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -677,7 +751,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -690,52 +764,51 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.38" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny-keccak" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tokio-core" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -743,15 +816,15 @@ name = "tokio-proto" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -760,7 +833,7 @@ name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -768,24 +841,24 @@ name = "tokio-timer" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -793,15 +866,26 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "uint" +version = "0.1.0" +source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicase" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -832,6 +916,11 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -842,21 +931,21 @@ name = "web3" version = "0.0.5" source = "git+https://github.com/tomusdrw/rust-web3?branch=bridge#0205d57b5e9734049cdbd570c431c3ad35b106fb" dependencies = [ - "arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.14 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -864,11 +953,30 @@ name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -880,80 +988,87 @@ dependencies = [ [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "699e63a93b79d717e8c3b5eb1b28b7780d0d6d9e59a72eb769291c83b0c8dc67" -"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" -"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" -"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" -"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" -"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" +"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" -"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" +"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38d3a55d9a7a456748f2a3912c0941a5d9a68006eb15b3c3c9836b8420dc102d" -"checksum ethabi 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56418d314deb23ce7b7b261ea53c50c98844989604a84bf410ff743c9fe08afd" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c49de42ee3e3e4734bd847d015e7c55b7855ab978800795c4f032772573d077" "checksum ethabi-contract 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98f8b3887766d303f17e9bcdf45ccce9588f428f0028d83a73b7a03da7c22757" -"checksum ethabi-derive 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7161ab469518bf5f90d8c3227526ab38d88f4d871923c62026b8b23565e23ad8" -"checksum futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a82bdc62350ca9d7974c760e9665102fc9d740992a528c2254aa930e53b783c4" -"checksum futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a283c84501e92cade5ea673a2a7ca44f71f209ccdd302a3e0896f50083d2c5ff" -"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" +"checksum ethabi-derive 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e17e3321853503b3eed691a660a92bc750da614bdd1eb39a0ecad4f0cd7a7a1c" +"checksum ethbloom 0.3.0 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum ethereum-types 0.1.4 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54fab2624374e5137ae4df13bf32b0b269cb804df42d13a51221bbd431d1a237" "checksum heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e0db42a2924a5d7d628685e7a8cf9a2edd628650a9d01efc3dde35d3cdd22451" -"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07" -"checksum hyper 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "641abc3e3fcf0de41165595f801376e01106bca1fd876dda937730e477ca004c" -"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be" -"checksum itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac17257442c2ed77dbc9fd555cf83c58b0c7f7d0e8f2ae08c0ac05c72842e1f6" -"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf" +"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" +"checksum hyper 0.11.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f57f74deb81fb91b776012ed7605e96b1ffb88c4fd5c031ce5c90534b604a6e0" +"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" -"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" -"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" -"checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527" -"checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" +"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum mime 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "153f98dde2b135dece079e5478ee400ae1bab13afa52d66590eacfc40e912435" -"checksum mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dbd91d3bfbceb13897065e97b2ef177a09a438cb33612b2d371bf568819a9313" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" +"checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0" "checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" -"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" -"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" -"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" +"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f213159e512f8376b31539ff28708164963357c59394747aa24c82a12633dca" -"checksum parking_lot_core 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a25dd36576d01cca115881dc920b1f0dd0037303ed8cfa0c5d0a4966151757f7" -"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" +"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" +"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d510007841e87c7a6d829a36f7f0acb72aef12e38cc89073fe39810c1d976ac" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf" -"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" +"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" +"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" +"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" -"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" -"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" -"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" +"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d" +"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" @@ -962,24 +1077,29 @@ dependencies = [ "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" -"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" -"checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292" -"checksum tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e85d419699ec4b71bfe35bbc25bb8771e52eff0471a7f75c853ad06e200b4f86" -"checksum tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ab83e7adb5677e42e405fa4ceff75659d93c4d7d7dd22f52fcec59ee9f02af" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" +"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" +"checksum tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "52b4e32d8edbf29501aabb3570f027c6ceb00ccef6538f4bddba0200503e74e8" +"checksum tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "514aae203178929dbf03318ad7c683126672d4d96eccb77b29603d33c9e25743" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" -"checksum tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6116c71be48f8f1656551fd16458247fdd6c03201d7893ad81189055fcde03e8" +"checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e01da42520092d0cd2d6ac3ae69eb21a22ad43ff195676b86f8c37f487d6b80" +"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)" = "" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" From b8fc1cd55c0a555e9f35c129ae49249368917305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 19 Jan 2018 15:11:21 +0100 Subject: [PATCH 011/152] withdraw_relay.rs: use rustc_hex::ToHex --- bridge/src/bridge/withdraw_relay.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index e37894b..8bc1fc9 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -11,6 +11,7 @@ use contracts::{home, foreign}; use util::web3_filter; use database::Database; use error::{self, Error}; +use rustc_hex::ToHex; /// returns a filter for `ForeignBridge.CollectedSignatures` events fn collected_signatures_filter(foreign: &foreign::ForeignBridge, address: Address) -> FilterBuilder { From 241f4a87b33313b83850236fbe77b624ccde4697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Sat, 20 Jan 2018 13:56:05 +0100 Subject: [PATCH 012/152] .travis.yml: one line parity installer fails. trying binary --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b376fe6..b11917e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,8 @@ matrix: - sudo add-apt-repository ppa:ethereum/ethereum -y - sudo apt-get update -y - sudo apt-get install solc -y - - bash <(curl https://get.parity.io -kL) + - wget https://parity-downloads-mirror.parity.io/v1.8.6/x86_64-unknown-linux-gnu/parity + - sudo cp parity /usr/local/bin - cd integration-tests script: - cargo run From 3bbebd208f023bc98a722d3371b367c7b64fabcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Sat, 20 Jan 2018 14:09:39 +0100 Subject: [PATCH 013/152] .travis.yml: copy to $HOME/bin instead of /usr/local/bin --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b11917e..5fd855f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,8 @@ matrix: - sudo apt-get update -y - sudo apt-get install solc -y - wget https://parity-downloads-mirror.parity.io/v1.8.6/x86_64-unknown-linux-gnu/parity - - sudo cp parity /usr/local/bin + - cp parity ${HOME}/bin + - export PATH=${HOME}/bin:${PATH} - cd integration-tests script: - cargo run From 27eaa45a29bcd3f4e870dd4d1a0c76bde56a22d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Sat, 20 Jan 2018 14:15:51 +0100 Subject: [PATCH 014/152] .travis.yml: grant executable rights on downloaded parity binary --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5fd855f..c528749 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,7 @@ matrix: - sudo apt-get update -y - sudo apt-get install solc -y - wget https://parity-downloads-mirror.parity.io/v1.8.6/x86_64-unknown-linux-gnu/parity + - chmod +x parity - cp parity ${HOME}/bin - export PATH=${HOME}/bin:${PATH} - cd integration-tests From ab094d6fa00aa3705c704695eae21242554cd7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Sat, 20 Jan 2018 17:46:21 +0100 Subject: [PATCH 015/152] gitignore: integration_tests/tmp -> integration-tests/tmp --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2b1a4a2..e62007d 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,4 @@ node_modules compiled_contracts -integration_tests/tmp +integration-tests/tmp From 5c565fd69db64c51a4717cd6552ffef57a1a9625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 09:23:52 +0100 Subject: [PATCH 016/152] .travis.yml: run cargo tests with backtrace for more context on failure --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c528749..b346adc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ matrix: - sudo apt-get update -y - sudo apt-get install solc -y script: - - cargo test --all + - env BACKTRACE=1 cargo test --all - language: rust rust: beta cache: cargo @@ -24,7 +24,7 @@ matrix: - sudo apt-get update -y - sudo apt-get install solc -y script: - - cargo test --all + - env BACKTRACE=1 cargo test --all - language: rust rust: nightly cache: cargo @@ -34,7 +34,7 @@ matrix: - sudo apt-get update -y - sudo apt-get install solc -y script: - - cargo test --all + - env BACKTRACE=1 cargo test --all - language: rust rust: stable cache: cargo @@ -49,7 +49,7 @@ matrix: - export PATH=${HOME}/bin:${PATH} - cd integration-tests script: - - cargo run + - env BACKTRACE=1 cargo run - language: node_js node_js: node cache: yarn From 9f5ff425de44dc346a0e9d9dd72456ed72c4010d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 09:44:09 +0100 Subject: [PATCH 017/152] make integration test a proper rust test --- .travis.yml | 2 +- .../{src/main.rs => tests/basic_deposit_then_withdraw.rs} | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename integration-tests/{src/main.rs => tests/basic_deposit_then_withdraw.rs} (99%) diff --git a/.travis.yml b/.travis.yml index b346adc..c77a566 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ matrix: - export PATH=${HOME}/bin:${PATH} - cd integration-tests script: - - env BACKTRACE=1 cargo run + - env BACKTRACE=1 cargo test -- --nocapture - language: node_js node_js: node cache: yarn diff --git a/integration-tests/src/main.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs similarity index 99% rename from integration-tests/src/main.rs rename to integration-tests/tests/basic_deposit_then_withdraw.rs index f5ee09c..9be1894 100644 --- a/integration-tests/src/main.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -68,7 +68,8 @@ fn parity_foreign_command() -> Command { command } -fn main() { +#[test] +fn test_basic_deposit_then_withdraw() { if Path::new(TMP_PATH).exists() { std::fs::remove_dir_all(TMP_PATH).expect("failed to remove tmp dir"); } From 2a65d52de2f4a20312712edf2f8449053c660bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 10:01:24 +0100 Subject: [PATCH 018/152] clean up integration test a bit --- .../tests/basic_deposit_then_withdraw.rs | 76 ++++--------------- 1 file changed, 13 insertions(+), 63 deletions(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index 9be1894..26e72c0 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -28,13 +28,9 @@ fn parity_home_command() -> Command { let mut command = Command::new("parity"); command .arg("--base-path").arg(format!("{}/home", TMP_PATH)) - // .arg("--chain").arg("home_chain.json") .arg("--chain").arg("dev") - // .arg("--config").arg("parity_home_config.toml") .arg("--ipc-path").arg("home.ipc") - // .arg("--db-path").arg("tmp/home_chain") .arg("--logging").arg("rpc=trace") - // .arg("--no-jsonrpc") .arg("--jsonrpc-port").arg("8550") .arg("--jsonrpc-apis").arg("all") .arg("--port").arg("30310") @@ -50,13 +46,9 @@ fn parity_foreign_command() -> Command { let mut command = Command::new("parity"); command .arg("--base-path").arg(format!("{}/foreign", TMP_PATH)) - // .arg("--chain").arg("home_chain.json") .arg("--chain").arg("dev") - // .arg("--config").arg("parity_home_config.toml") .arg("--ipc-path").arg("foreign.ipc") - // .arg("--db-path").arg("tmp/home_chain") .arg("--logging").arg("rpc=trace") - // .arg("--no-jsonrpc") .arg("--jsonrpc-port").arg("8551") .arg("--jsonrpc-apis").arg("all") .arg("--port").arg("30311") @@ -75,17 +67,14 @@ fn test_basic_deposit_then_withdraw() { } let tmp_dir = tempdir::TempDir::new(TMP_PATH).expect("failed to create tmp dir"); - // TODO home_base - // TODO foreign_base - - // build the bridge cli process - let exit_status = Command::new("cargo") + println!("\nbuild the bridge cli executable so we can run it later\n"); + assert!(Command::new("cargo") .env("RUST_BACKTRACE", "1") .current_dir("../cli") .arg("build") .status() - .expect("failed to compile bridge cli"); - assert!(exit_status.success()); + .expect("failed to build bridge cli") + .success()); // start a parity node that represents the home chain let mut parity_home = parity_home_command() @@ -147,44 +136,6 @@ fn test_basic_deposit_then_withdraw() { // give nodes time to start up thread::sleep(Duration::from_millis(10000)); - // unlock authority account on home so bridge can connect later - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8550") - // .status() - // .expect("failed to unlock authority account on home"); - // assert!(exit_status.success()); - - // unlock authority account on home so bridge can connect later - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00bd138abd70e2f00903268f3db08f2d25677c9e", "node0", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8551") - // .status() - // .expect("failed to unlock authority account on foreign"); - // assert!(exit_status.success()); - - // unlock user account which has a lot of ether on dev chain - // on home and foreign - // so we can make transactions - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8550") - // .status() - // .expect("failed to unlock user account on home"); - // let exit_status = Command::new("curl") - // .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x00a329c0648769a73afac7f9381e08fb43dbea72", "", "0x0"],"id":0}"#) - // .arg("-H").arg("Content-Type: application/json") - // .arg("-X").arg("POST") - // .arg("localhost:8551") - // .status() - // .expect("failed to unlock user account on foreign"); - // start bridge authority 1 let mut bridge1 = Command::new("env") .arg("RUST_BACKTRACE=1") @@ -199,6 +150,8 @@ fn test_basic_deposit_then_withdraw() { // give the bridge time to start up and deploy the contracts thread::sleep(Duration::from_millis(10000)); + println!("\ndeposit ether into HomeBridge\n"); + // user deposits into HomeBridge let exit_status = Command::new("curl") .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ @@ -213,11 +166,10 @@ fn test_basic_deposit_then_withdraw() { .expect("failed to deposit into HomeBridge"); assert!(exit_status.success()); - println!("\ndeposit into home sent\n"); - - // wait for it to be mined + println!("\ndeposit into home sent. give it plenty of time to get mined and relayed\n"); thread::sleep(Duration::from_millis(10000)); + // connect for foreign and home via IPC let mut event_loop = Core::new().unwrap(); let foreign_transport = Ipc::with_event_loop("foreign.ipc", &event_loop.handle()) .expect("failed to connect to foreign.ipc"); @@ -230,7 +182,6 @@ fn test_basic_deposit_then_withdraw() { // balance on ForeignBridge should have increased let balance_payload = foreign.functions().balances().input(Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72")); - println!("balance_payload: {}", balance_payload.to_hex()); let future = foreign_eth.call(web3::types::CallRequest{ from: None, @@ -241,15 +192,15 @@ fn test_basic_deposit_then_withdraw() { data: Some(web3::types::Bytes(balance_payload)), }, None); - println!("waiting for future"); let response = event_loop.run(future).unwrap(); let balance = U256::from(response.0.as_slice()); - assert_eq!(balance, U256::from(100000)); + assert_eq!( + balance, + U256::from(100000), + "balance on ForeignBridge should have increased"); println!("\nconfirmed that deposit reached foreign\n"); - thread::sleep(Duration::from_millis(10000)); - // withdraw let transfer_payload = foreign.functions() .transfer_home_via_relay() @@ -268,8 +219,7 @@ fn test_basic_deposit_then_withdraw() { }); let response = event_loop.run(future).unwrap(); - println!("\ntransfer to home transaction sent\n"); - + println!("\nForeignBridge.transferHomeViaRelay transaction sent. give it plenty of time to get mined and relayed\n"); thread::sleep(Duration::from_millis(10000)); // test that withdraw completed From 1691841c3c697974426122232c64952e2fcc0c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 10:57:42 +0100 Subject: [PATCH 019/152] use just released ethabi 5.0 which fixes the InvalidData issue --- Cargo.lock | 30 ++++++++++++++++++++++-------- bridge/Cargo.toml | 6 +++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c4a84d..b6a6cff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ name = "bridge" version = "0.1.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -186,17 +186,30 @@ dependencies = [ "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethabi" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethabi-contract" -version = "4.0.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ethabi-derive" -version = "4.2.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1005,8 +1018,9 @@ dependencies = [ "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c49de42ee3e3e4734bd847d015e7c55b7855ab978800795c4f032772573d077" -"checksum ethabi-contract 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98f8b3887766d303f17e9bcdf45ccce9588f428f0028d83a73b7a03da7c22757" -"checksum ethabi-derive 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e17e3321853503b3eed691a660a92bc750da614bdd1eb39a0ecad4f0cd7a7a1c" +"checksum ethabi 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "14ba36002cd4f12531f868f285e22e9dd81bbb2cc564663e5a4202e6290e07f9" +"checksum ethabi-contract 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "875ee2bf76d6dbfae9682457c41b1debc994812419132815263b215262f6940e" +"checksum ethabi-derive 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb6482d54b628bd883b0fd9007a3f0d85e2df372f0f1bc33bab7417cad1ed4c4" "checksum ethbloom 0.3.0 (git+https://github.com/paritytech/primitives.git)" = "" "checksum ethereum-types 0.1.4 (git+https://github.com/paritytech/primitives.git)" = "" "checksum fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)" = "" diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index 6eb4245..55c1323 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -13,9 +13,9 @@ tokio-timer = "0.1.2" toml = "0.4.2" web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } error-chain = "0.11.0-rc.2" -ethabi = "4.0" -ethabi-derive = "4.0" -ethabi-contract = "4.0" +ethabi = "5.0" +ethabi-derive = "5.0" +ethabi-contract = "5.0" rustc-hex = "1.0" log = "0.3" From c558ab5e63b871076f8bf3221bdaf4be9d0381c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 11:01:10 +0100 Subject: [PATCH 020/152] remove home_chain.json - no longer needed. we use the dev chain now --- integration-tests/home_chain.json | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 integration-tests/home_chain.json diff --git a/integration-tests/home_chain.json b/integration-tests/home_chain.json deleted file mode 100644 index 70d0cbb..0000000 --- a/integration-tests/home_chain.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "BridgeIntegrationTestHomeChain", - "engine": { - "instantSeal": null - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "accountStartNonce": "0x0", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID" : "0x11" - }, - "genesis": { - "seal": { - "generic": "0x0" - }, - "difficulty": "0x20000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x", - "gasLimit": "0x5B8D80" - }, - "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0x006e27b6a72e1f34c626762f3c4761547aff1421": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } - } -} From c9aeba358634f08e709fb9cb2db2d57abd0fd8ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 11:28:49 +0100 Subject: [PATCH 021/152] .travis.yml: run integration tests as part of stable, beta and nightly --- .travis.yml | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index c77a566..86c26ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,32 +13,17 @@ matrix: - sudo add-apt-repository ppa:ethereum/ethereum -y - sudo apt-get update -y - sudo apt-get install solc -y + - wget https://parity-downloads-mirror.parity.io/v1.8.6/x86_64-unknown-linux-gnu/parity + - chmod +x parity + - cp parity ${HOME}/bin + - export PATH=${HOME}/bin:${PATH} + - cd integration-tests script: - - env BACKTRACE=1 cargo test --all + - env BACKTRACE=1 cargo test --all -- --nocapture - language: rust rust: beta cache: cargo fast_finish: false - before_script: - - sudo add-apt-repository ppa:ethereum/ethereum -y - - sudo apt-get update -y - - sudo apt-get install solc -y - script: - - env BACKTRACE=1 cargo test --all - - language: rust - rust: nightly - cache: cargo - fast_finish: false - before_script: - - sudo add-apt-repository ppa:ethereum/ethereum -y - - sudo apt-get update -y - - sudo apt-get install solc -y - script: - - env BACKTRACE=1 cargo test --all - - language: rust - rust: stable - cache: cargo - fast_finish: false before_script: - sudo add-apt-repository ppa:ethereum/ethereum -y - sudo apt-get update -y @@ -49,7 +34,22 @@ matrix: - export PATH=${HOME}/bin:${PATH} - cd integration-tests script: - - env BACKTRACE=1 cargo test -- --nocapture + - env BACKTRACE=1 cargo test --all -- --nocapture + - language: rust + rust: nightly + cache: cargo + fast_finish: false + before_script: + - sudo add-apt-repository ppa:ethereum/ethereum -y + - sudo apt-get update -y + - sudo apt-get install solc -y + - wget https://parity-downloads-mirror.parity.io/v1.8.6/x86_64-unknown-linux-gnu/parity + - chmod +x parity + - cp parity ${HOME}/bin + - export PATH=${HOME}/bin:${PATH} + - cd integration-tests + script: + - env BACKTRACE=1 cargo test --all -- --nocapture - language: node_js node_js: node cache: yarn From c33126b961cc356aa15ae794038d5d059e4f720b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 14:33:53 +0100 Subject: [PATCH 022/152] withdraw_relay: break long type into several lines --- bridge/src/bridge/withdraw_relay.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 8bc1fc9..91b43a6 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -92,7 +92,10 @@ fn withdraw_relay_payload(home: &home::HomeBridge, signatures: &[Bytes], message pub enum WithdrawRelayState { Wait, FetchMessagesSignatures { - future: Join>>>, JoinAll>>>>>>, + future: Join< + JoinAll>>>, + JoinAll>>>>> + >, block: u64, }, FetchMessageValueSufficient { From ddc5ffcfd4b97e068ba627a81d6cc93893755fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 15:10:57 +0100 Subject: [PATCH 023/152] fix #87 by parsing rpc outputs with ethabi --- bridge/src/bridge/withdraw_relay.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 91b43a6..1fe36f3 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -192,12 +192,34 @@ impl Stream for WithdrawRelay { } }, WithdrawRelayState::FetchMessagesSignatures { ref mut future, block } => { - let (messages, signatures) = try_ready!(future.poll()); - assert_eq!(messages.len(), signatures.len()); + let (messages_raw, signatures_raw) = try_ready!(future.poll()); + info!("fetching messages and signatures complete"); + assert_eq!(messages_raw.len(), signatures_raw.len()); let app = &self.app; let home_contract = &self.home_contract; + let messages = messages_raw + .iter() + .map(|message| { + app.foreign_bridge.functions().message().output(message.0.as_slice()).map(Bytes) + }) + .collect::>>() + .map_err(error::Error::from)?; + + let signatures = signatures_raw + .iter() + .map(|signatures| + signatures.iter().map( + |signature| { + app.foreign_bridge.functions().signature().output(signature.0.as_slice()).map(Bytes) + } + ) + .collect::>>() + .map_err(error::Error::from) + ) + .collect::>>()?; + let message_value_sufficient_payloads = messages .iter() .map(|message| { From 92c7e794ecf94c99f84ee2b8da4eebcc37604ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 16:14:53 +0100 Subject: [PATCH 024/152] tests/withdraw_relay.rs: adapt responses to fix for 87 --- tests/tests/withdraw_relay.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/tests/withdraw_relay.rs b/tests/tests/withdraw_relay.rs index 46caa90..63ab88b 100644 --- a/tests/tests/withdraw_relay.rs +++ b/tests/tests/withdraw_relay.rs @@ -118,14 +118,14 @@ test_app_stream! { // call to `message` "eth_call" => req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; // calls to `signature` "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; ] } @@ -168,14 +168,14 @@ test_app_stream! { // call to `message` "eth_call" => req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; // calls to `signature` "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; ] } @@ -226,14 +226,14 @@ test_app_stream! { // call to `message` "eth_call" => req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; // calls to `signature` "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; ] } @@ -282,13 +282,13 @@ test_app_stream! { // call to `message` "eth_call" => req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x00000000000000000000000000000000000000ee"},"latest"]"#, - res => r#""0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; // calls to `signature` "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x00000000000000000000000000000000000000ee"},"latest"]"#, - res => r#""0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; "eth_call" => req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x00000000000000000000000000000000000000ee"},"latest"]"#, - res => r#""0x2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222""#; + res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; ] } From 0db863d5de3c65938830c95fc7dcbead83013d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 16:30:01 +0100 Subject: [PATCH 025/152] integration-tests: resolve rust compiler warnings --- .../tests/basic_deposit_then_withdraw.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index 26e72c0..2088631 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -3,20 +3,16 @@ extern crate tempdir; extern crate ethereum_types; -extern crate rustc_hex; extern crate web3; extern crate tokio_core; extern crate bridge; -extern crate futures; -use std::process::{Command, Child}; +use std::process::Command; use std::time::Duration; use std::thread; use std::path::Path; -use futures::Future; use tokio_core::reactor::Core; -use rustc_hex::ToHex; use web3::transports::ipc::Ipc; use web3::api::Namespace; @@ -65,7 +61,7 @@ fn test_basic_deposit_then_withdraw() { if Path::new(TMP_PATH).exists() { std::fs::remove_dir_all(TMP_PATH).expect("failed to remove tmp dir"); } - let tmp_dir = tempdir::TempDir::new(TMP_PATH).expect("failed to create tmp dir"); + let _tmp_dir = tempdir::TempDir::new(TMP_PATH).expect("failed to create tmp dir"); println!("\nbuild the bridge cli executable so we can run it later\n"); assert!(Command::new("cargo") @@ -177,7 +173,6 @@ fn test_basic_deposit_then_withdraw() { let foreign_eth = web3::api::Eth::new(foreign_transport); let home_transport = Ipc::with_event_loop("home.ipc", &event_loop.handle()) .expect("failed to connect to home.ipc"); - let home = bridge::contracts::home::HomeBridge::default(); let home_eth = web3::api::Eth::new(home_transport); // balance on ForeignBridge should have increased @@ -217,7 +212,7 @@ fn test_basic_deposit_then_withdraw() { condition: None, nonce: None, }); - let response = event_loop.run(future).unwrap(); + event_loop.run(future).unwrap(); println!("\nForeignBridge.transferHomeViaRelay transaction sent. give it plenty of time to get mined and relayed\n"); thread::sleep(Duration::from_millis(10000)); From 9aa26ea39053ce51066f9f10e826b1ef493d5b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 16:48:30 +0100 Subject: [PATCH 026/152] remove unused dependency --- integration-tests/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index e7c686b..172b297 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -12,5 +12,4 @@ serde_json = "1.0" pretty_assertions = "0.2.1" tempdir = "0.3.5" ethereum-types = { git = "https://github.com/paritytech/primitives.git" } -rustc-hex = "1.0" tokio-core = "0.1.8" From ff7acc3f4a7c2a7c4bd34e88236cb51a4168b2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 16:48:41 +0100 Subject: [PATCH 027/152] remove outcommented code --- integration-tests/tests/basic_deposit_then_withdraw.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index 2088631..1688070 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -136,7 +136,6 @@ fn test_basic_deposit_then_withdraw() { let mut bridge1 = Command::new("env") .arg("RUST_BACKTRACE=1") .arg("../target/debug/bridge") - // .env("RUST_BACKTRACE", "1") .env("RUST_LOG", "info") .arg("--config").arg("bridge_config.toml") .arg("--database").arg("tmp/bridge1_db.txt") From b6a34c6252c053422fb0652437ca02a0a6290e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 22 Jan 2018 20:56:02 +0100 Subject: [PATCH 028/152] integration-tests/tests/basic_deposit_then_withdraw.rs: add module docstring [ci skip] --- integration-tests/tests/basic_deposit_then_withdraw.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index 1688070..df51f4e 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -1,5 +1,9 @@ /// spins up two parity nodes with the dev chain. -/// starts bridge that connects the two. +/// starts one bridge authority that connects the two. +/// does a deposit by sending ether to the HomeBridge. +/// asserts that the deposit got relayed to foreign chain. +/// does a withdraw by executing ForeignBridge.transferToHomeBridge. +/// asserts that the withdraw got relayed to home chain. extern crate tempdir; extern crate ethereum_types; From 8a8380e7a88023fd50b03c8895636710d5bde134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 25 Jan 2018 09:51:22 +0100 Subject: [PATCH 029/152] bridge/build.rs: make error messages helpful. resolves #98 --- bridge/build.rs | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/bridge/build.rs b/bridge/build.rs index 3d5b83a..30168db 100644 --- a/bridge/build.rs +++ b/bridge/build.rs @@ -1,18 +1,35 @@ use std::process::Command; fn main() { - // rerun build script if bridge contract has changed. - // without this cargo doesn't since the bridge contract - // is outside the crate directories - println!("cargo:rerun-if-changed=../contracts/bridge.sol"); - let exit_status = Command::new("solc") - .arg("--abi") - .arg("--bin") - .arg("--optimize") - .arg("--output-dir").arg("../compiled_contracts") - .arg("--overwrite") - .arg("../contracts/bridge.sol") - .status() - .unwrap_or_else(|e| panic!("Error compiling solidity contracts: {}", e)); - assert!(exit_status.success(), "There was an error while compiling contracts code."); + // rerun build script if bridge contract has changed. + // without this cargo doesn't since the bridge contract + // is outside the crate directories + println!("cargo:rerun-if-changed=../contracts/bridge.sol"); + + match Command::new("solc") + .arg("--abi") + .arg("--bin") + .arg("--optimize") + .arg("--output-dir").arg("../compiled_contracts") + .arg("--overwrite") + .arg("../contracts/bridge.sol") + .status() + { + Ok(exit_status) => { + if !exit_status.success() { + if let Some(code) = exit_status.code() { + panic!("`solc` exited with error exit status code `{}`", code); + } else { + panic!("`solc` exited because it was terminated by a signal"); + } + } + }, + Err(err) => { + if let std::io::ErrorKind::NotFound = err.kind() { + panic!("`solc` executable not found in `$PATH`. `solc` is required to compile the bridge contracts. please install it: https://solidity.readthedocs.io/en/develop/installing-solidity.html"); + } else { + panic!("an error occurred when trying to spawn `solc`: {}", err); + } + } + } } From 1b51837f78bab735638e6ae65ddbe11f4345ea8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 25 Jan 2018 09:52:10 +0100 Subject: [PATCH 030/152] README.md: tell that solc must be in path for build --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 68b4055..e76ffe5 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ by `value`. ### build +requires `solc` to be in `$PATH`. [installation instructions](https://solidity.readthedocs.io/en/develop/installing-solidity.html) + ``` cargo build -p bridge-cli --release ``` From bc0ebb8a158ffd3ca209cf5e128f2e39946d436d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 25 Jan 2018 09:52:43 +0100 Subject: [PATCH 031/152] README.md: consistency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e76ffe5..993325c 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ checked_withdraw_confirm = 121 ### truffle tests -[requires yarn to be installed](https://yarnpkg.com/lang/en/docs/install/) +requires `yarn` to be `$PATH`. [installation instructions](https://yarnpkg.com/lang/en/docs/install/) ``` cd truffle From 2ec0b2d23c5b8a56ab617be1a8c822b1bbddc38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:10:51 +0100 Subject: [PATCH 032/152] bridge.sol: add function ForeignBridge.totalSupply --- contracts/bridge.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index f01334f..d8dbdb6 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -273,6 +273,9 @@ contract ForeignBridge { /// Must be lesser than number of authorities. uint public requiredSignatures; + // part of ERC20 spec + uint public totalSupply; + /// Contract authorities. address[] public authorities; @@ -331,6 +334,7 @@ contract ForeignBridge { // TODO: this may cause troubles if requriedSignatures len is changed if (deposits[hash].length == requiredSignatures) { balances[recipient] += value; + totalSupply += value; Deposit(recipient, value); } } @@ -350,6 +354,7 @@ contract ForeignBridge { require(balances[recipient] + value > balances[recipient]); balances[msg.sender] -= value; + totalSupply -= value; Withdraw(recipient, value); } From 25b92a17e0feb3676b68ca7f5976fb2fb9426740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:11:32 +0100 Subject: [PATCH 033/152] bridge.sol: fix typo --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index d8dbdb6..6f277fd 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -331,7 +331,7 @@ contract ForeignBridge { require(!Helpers.addressArrayContains(deposits[hash], msg.sender)); deposits[hash].push(msg.sender); - // TODO: this may cause troubles if requriedSignatures len is changed + // TODO: this may cause troubles if requiredSignatures len is changed if (deposits[hash].length == requiredSignatures) { balances[recipient] += value; totalSupply += value; From ee37db7c93454023ac72d1675e05b8067a1ff305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:16:08 +0100 Subject: [PATCH 034/152] bridge.sol: add function ForeignBridge.balanceOf --- contracts/bridge.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 6f277fd..059a048 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -312,6 +312,11 @@ contract ForeignBridge { authorities = authoritiesParam; } + // part of ERC20 spec + function balanceOf(address tokenOwner) public constant returns (uint) { + return balances[tokenOwner]; + } + /// Multisig authority validation modifier onlyAuthority() { require(Helpers.addressArrayContains(authorities, msg.sender)); From 64b0a5ae271fc8d4f89a9d12718cb97ed38d3c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:26:37 +0100 Subject: [PATCH 035/152] bridge.sol: constant -> view --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 059a048..3801831 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -313,7 +313,7 @@ contract ForeignBridge { } // part of ERC20 spec - function balanceOf(address tokenOwner) public constant returns (uint) { + function balanceOf(address tokenOwner) public view returns (uint) { return balances[tokenOwner]; } From cdcb33641f082bec8b0d4cc6c6cc912c5155e971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:27:24 +0100 Subject: [PATCH 036/152] bridge.sol: add function ForeignBridge.name --- contracts/bridge.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 3801831..bf47c6a 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -312,6 +312,11 @@ contract ForeignBridge { authorities = authoritiesParam; } + // part of ERC20 spec + function name() public pure returns (string) { + return "ParityBridgeForeignBridge"; + } + // part of ERC20 spec function balanceOf(address tokenOwner) public view returns (uint) { return balances[tokenOwner]; From ffc0b31eb34a58ba11263266ff487ccd227d2237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:27:44 +0100 Subject: [PATCH 037/152] ForeignBridge.transferLocal -> transfer to conform to ERC20 --- contracts/bridge.sol | 15 ++++++++------- truffle/test/foreign.js | 14 +++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index bf47c6a..324fe82 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -371,14 +371,15 @@ contract ForeignBridge { /// Transfer `value` to `recipient` on this `foreign` chain. /// /// does not affect `home` chain. does not do a relay. - function transferLocal(address recipient, uint value) public { - require(balances[msg.sender] >= value); - // fails if value == 0, or if there is an overflow - require(balances[recipient] + value > balances[recipient]); + function transfer(address recipient, uint tokens) public returns (bool) { + require(balances[msg.sender] >= tokens); + // fails if tokens == 0, or if there is an overflow + require(balances[recipient] + tokens > balances[recipient]); - balances[msg.sender] -= value; - balances[recipient] += value; - Transfer(msg.sender, recipient, value); + balances[msg.sender] -= tokens; + balances[recipient] += tokens; + Transfer(msg.sender, recipient, tokens); + return true; } /// Should be used as sync tool diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 2e51207..950b250 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -165,7 +165,7 @@ contract('ForeignBridge', function(accounts) { // top up balance so we can transfer return meta.deposit(userAccount, user1InitialValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferLocal(userAccount2, transferedValue, { from: userAccount }); + return meta.transfer(userAccount2, transferedValue, { from: userAccount }); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); @@ -195,9 +195,9 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferLocal(recipientAccount, transferedValue, { from: userAccount }); + return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { - assert(false, "transferLocal should fail"); + assert(false, "transfer should fail"); }, function(err) { return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { @@ -219,9 +219,9 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferLocal(recipientAccount, transferedValue, { from: userAccount }); + return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { - assert(false, "transferLocal should fail"); + assert(false, "transfer should fail"); }, function(err) { return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { @@ -243,9 +243,9 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferLocal(recipientAccount, transferedValue, { from: userAccount }); + return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { - assert(false, "transferLocal should fail"); + assert(false, "transfer should fail"); }, function(err) { return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { From ea18c198b46143500c8bcfae5cd110fd24a0d231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 11:35:04 +0100 Subject: [PATCH 038/152] make ForeignBridge.Transfer event conform to ERC20 --- contracts/bridge.sol | 2 +- truffle/test/foreign.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 324fe82..d687d7e 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -295,7 +295,7 @@ contract ForeignBridge { event Withdraw(address recipient, uint value); /// Event created on money transfer - event Transfer(address from, address to, uint value); + event Transfer(address indexed from, address indexed to, uint tokens); /// Collected signatures which should be relayed to home chain. event CollectedSignatures(address authority, bytes32 messageHash); diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 950b250..f7397f6 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -171,7 +171,7 @@ contract('ForeignBridge', function(accounts) { assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); assert.equal(userAccount, result.logs[0].args.from, "Event from should be transaction sender"); assert.equal(userAccount2, result.logs[0].args.to, "Event from should be transaction recipient"); - assert.equal(transferedValue, result.logs[0].args.value, "Event value should match transaction value"); + assert.equal(transferedValue, result.logs[0].args.tokens, "Event tokens should match transaction value"); return Promise.all([ meta.balances.call(userAccount), meta.balances.call(userAccount2) From e6db3476ca4804418be73d32de50f1b942454137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 15:26:49 +0100 Subject: [PATCH 039/152] bridge.sol: fix typo --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index d687d7e..400a300 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -264,7 +264,7 @@ contract ForeignBridge { bytes message; /// Authorities who signed the message. address[] signed; - /// Signaturs + /// Signatures bytes[] signatures; } From 9b9d109f572831ade64b2d2eb9faea74a3689610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 15:29:08 +0100 Subject: [PATCH 040/152] bridge.sol: fix typo --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 400a300..4c5c27f 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -270,7 +270,7 @@ contract ForeignBridge { /// Number of authorities signatures required to withdraw the money. /// - /// Must be lesser than number of authorities. + /// Must be less than number of authorities. uint public requiredSignatures; // part of ERC20 spec From 10cfea8172f1b2c82d33474d15814d4d7be11806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 15:29:51 +0100 Subject: [PATCH 041/152] bridge.sol: improve docstring --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 4c5c27f..d10bf2b 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -288,7 +288,7 @@ contract ForeignBridge { /// Pending signatures and authorities who confirmed them mapping (bytes32 => SignaturesCollection) signatures; - /// Event created on money deposit. + /// triggered when relay of deposit from HomeBridge is complete event Deposit(address recipient, uint value); /// Event created on money withdraw. From 73dd502b88725867b9776790e536caa6f9f3c887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 15:30:59 +0100 Subject: [PATCH 042/152] bridge.sol: authority -> authorityResponsibleForRelay --- bridge/src/bridge/withdraw_relay.rs | 2 +- contracts/bridge.sol | 2 +- truffle/test/foreign.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 1fe36f3..4bd269f 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -37,7 +37,7 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 data: log.data.0, }; let collected_signatures = foreign.events().collected_signatures().parse_log(raw_log)?; - if collected_signatures.authority != my_address.0 { + if collected_signatures.authority_responsible_for_relay != my_address.0 { info!("bridge not responsible for relaying transaction to home. tx hash: {}", log.transaction_hash.unwrap()); // this authority is not responsible for relaying this transaction. // someone else will relay this transaction to home. diff --git a/contracts/bridge.sol b/contracts/bridge.sol index d10bf2b..1c2b0f5 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -298,7 +298,7 @@ contract ForeignBridge { event Transfer(address indexed from, address indexed to, uint tokens); /// Collected signatures which should be relayed to home chain. - event CollectedSignatures(address authority, bytes32 messageHash); + event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash); /// Constructor. function ForeignBridge( diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index f7397f6..7c30f49 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -299,7 +299,7 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("CollectedSignatures", result.logs[0].event, "Event name should be CollectedSignatures"); - assert.equal(authorities[0], result.logs[0].args.authority, "Event authority should be equal to transaction sender"); + assert.equal(authorities[0], result.logs[0].args.authorityResponsibleForRelay, "Event authority should be equal to transaction sender"); return Promise.all([ meta.signature.call(result.logs[0].args.messageHash, 0), meta.message(result.logs[0].args.messageHash), @@ -356,7 +356,7 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("CollectedSignatures", result.logs[0].event, "Event name should be CollectedSignatures"); - assert.equal(authorities[0], result.logs[0].args.authority, "Event authority should be equal to transaction sender"); + assert.equal(authorities[0], result.logs[0].args.authorityResponsibleForRelay, "Event authority should be equal to transaction sender"); return Promise.all([ meta.signature.call(result.logs[0].args.messageHash, 0), meta.signature.call(result.logs[0].args.messageHash, 1), @@ -370,7 +370,7 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("CollectedSignatures", result.logs[0].event, "Event name should be CollectedSignatures"); - assert.equal(authorities[1], result.logs[0].args.authority, "Event authority should be equal to transaction sender"); + assert.equal(authorities[1], result.logs[0].args.authorityResponsibleForRelay, "Event authority should be equal to transaction sender"); return Promise.all([ meta.signature.call(result.logs[0].args.messageHash, 0), meta.signature.call(result.logs[0].args.messageHash, 1), From 292891ed967a2532c5ff3c77ed8d8071a9bd4f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 16:22:01 +0100 Subject: [PATCH 043/152] bridge.sol: improve docstring --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 1c2b0f5..8becab8 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -322,7 +322,7 @@ contract ForeignBridge { return balances[tokenOwner]; } - /// Multisig authority validation + /// require that sender is an authority modifier onlyAuthority() { require(Helpers.addressArrayContains(authorities, msg.sender)); _; From 856f34032794cf4087e48b30c7f1c5b9731b0be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 16:22:17 +0100 Subject: [PATCH 044/152] bridge.sol: fix typo --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 8becab8..b9874bb 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -334,7 +334,7 @@ contract ForeignBridge { /// deposit value (uint) /// mainnet transaction hash (bytes32) // to avoid transaction duplication function deposit(address recipient, uint value, bytes32 transactionHash) public onlyAuthority() { - // Protection from misbehaing authority + // Protection from misbehaving authority var hash = keccak256(recipient, value, transactionHash); // Duplicated deposits From d8e81a8593f53d44602725d608dd89b616cfe8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 17 Jan 2018 16:22:57 +0100 Subject: [PATCH 045/152] bridge.sol: first rough full implementation of ERC20 for ForeignBridge --- contracts/bridge.sol | 115 ++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 40 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index b9874bb..6df8335 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -259,6 +259,75 @@ contract HomeBridge { contract ForeignBridge { + // following is the part of ForeignBridge that implements an ERC20 token + // ERC20 spec: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md + + uint public totalSupply; + + /// maps addresses to their token balances + mapping (address => uint) public balances; + + // Owner of account approves the transfer of an amount by another account + mapping(address => mapping (address => uint)) allowed; + + /// Event created on money transfer + event Transfer(address indexed from, address indexed to, uint tokens); + + event Approval(address indexed tokenOwner, address indexed spender, uint tokens); + + function name() public pure returns (string) { + return "ParityBridgeForeignBridge"; + } + + function balanceOf(address tokenOwner) public view returns (uint) { + return balances[tokenOwner]; + } + + function transferFrom(address from, address to, uint tokens) public returns (bool) { + // `from` has enough tokens + require(balances[from] >= tokens); + // `sender` is allowed to move `tokens` from `from` + require(allowed[from][msg.sender] >= tokens); + + balances[to] += tokens; + balances[from] -= tokens; + allowed[from][msg.sender] -= tokens; + + Transfer(from, to, tokens); + return true; + } + + // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. + // If this function is called again it overwrites the current allowance with _value. + function approve(address spender, uint tokens) public returns (bool) { + allowed[msg.sender][spender] = tokens; + Approval(msg.sender, spender, tokens); + return true; + } + + // returns how much `spender` is allowed to spend of `owner`s tokens + function allowance(address owner, address spender) public view returns (uint256) { + return allowed[owner][spender]; + } + + /// Transfer `value` to `recipient` on this `foreign` chain. + /// + /// does not affect `home` chain. does not do a relay. + /// note that t + function transfer(address recipient, uint tokens) public returns (bool) { + require(balances[msg.sender] >= tokens); + // fails if there is an overflow + require(balances[recipient] + tokens >= balances[recipient]); + + balances[msg.sender] -= tokens; + balances[recipient] += tokens; + Transfer(msg.sender, recipient, tokens); + return true; + } + + + // following is the part of ForeignBridge that is concerned with moving tokens from and to HomeBridge + struct SignaturesCollection { /// Signed message. bytes message; @@ -273,15 +342,9 @@ contract ForeignBridge { /// Must be less than number of authorities. uint public requiredSignatures; - // part of ERC20 spec - uint public totalSupply; - /// Contract authorities. address[] public authorities; - /// Ether balances - mapping (address => uint) public balances; - /// Pending deposits and authorities who confirmed them mapping (bytes32 => address[]) deposits; @@ -294,32 +357,18 @@ contract ForeignBridge { /// Event created on money withdraw. event Withdraw(address recipient, uint value); - /// Event created on money transfer - event Transfer(address indexed from, address indexed to, uint tokens); - /// Collected signatures which should be relayed to home chain. event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash); - /// Constructor. function ForeignBridge( - uint requiredSignaturesParam, - address[] authoritiesParam + uint _requiredSignatures, + address[] _authorities ) public { - require(requiredSignaturesParam != 0); - require(requiredSignaturesParam <= authoritiesParam.length); - requiredSignatures = requiredSignaturesParam; - authorities = authoritiesParam; - } - - // part of ERC20 spec - function name() public pure returns (string) { - return "ParityBridgeForeignBridge"; - } - - // part of ERC20 spec - function balanceOf(address tokenOwner) public view returns (uint) { - return balances[tokenOwner]; + require(_requiredSignatures != 0); + require(_requiredSignatures <= _authorities.length); + requiredSignatures = _requiredSignatures; + authorities = _authorities; } /// require that sender is an authority @@ -368,20 +417,6 @@ contract ForeignBridge { Withdraw(recipient, value); } - /// Transfer `value` to `recipient` on this `foreign` chain. - /// - /// does not affect `home` chain. does not do a relay. - function transfer(address recipient, uint tokens) public returns (bool) { - require(balances[msg.sender] >= tokens); - // fails if tokens == 0, or if there is an overflow - require(balances[recipient] + tokens > balances[recipient]); - - balances[msg.sender] -= tokens; - balances[recipient] += tokens; - Transfer(msg.sender, recipient, tokens); - return true; - } - /// Should be used as sync tool /// /// Message is a message that should be relayed to main chain once authorities sign it. From a73c64a446482a5e9b3a8743f842776a1cc81aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 12:14:25 +0100 Subject: [PATCH 046/152] bridge.sol: more sensible grouping and add comments --- contracts/bridge.sol | 64 +++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 6df8335..292b5c2 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -273,8 +273,6 @@ contract ForeignBridge { /// Event created on money transfer event Transfer(address indexed from, address indexed to, uint tokens); - event Approval(address indexed tokenOwner, address indexed spender, uint tokens); - function name() public pure returns (string) { return "ParityBridgeForeignBridge"; } @@ -283,33 +281,6 @@ contract ForeignBridge { return balances[tokenOwner]; } - function transferFrom(address from, address to, uint tokens) public returns (bool) { - // `from` has enough tokens - require(balances[from] >= tokens); - // `sender` is allowed to move `tokens` from `from` - require(allowed[from][msg.sender] >= tokens); - - balances[to] += tokens; - balances[from] -= tokens; - allowed[from][msg.sender] -= tokens; - - Transfer(from, to, tokens); - return true; - } - - // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. - // If this function is called again it overwrites the current allowance with _value. - function approve(address spender, uint tokens) public returns (bool) { - allowed[msg.sender][spender] = tokens; - Approval(msg.sender, spender, tokens); - return true; - } - - // returns how much `spender` is allowed to spend of `owner`s tokens - function allowance(address owner, address spender) public view returns (uint256) { - return allowed[owner][spender]; - } - /// Transfer `value` to `recipient` on this `foreign` chain. /// /// does not affect `home` chain. does not do a relay. @@ -325,8 +296,39 @@ contract ForeignBridge { return true; } + // part of ERC20 standard responsible for giving others spending rights - // following is the part of ForeignBridge that is concerned with moving tokens from and to HomeBridge + event Approval(address indexed tokenOwner, address indexed spender, uint tokens); + + // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. + // If this function is called again it overwrites the current allowance with _value. + function approve(address spender, uint tokens) public returns (bool) { + allowed[msg.sender][spender] = tokens; + Approval(msg.sender, spender, tokens); + return true; + } + + // returns how much `spender` is allowed to spend of `owner`s tokens + function allowance(address owner, address spender) public view returns (uint256) { + return allowed[owner][spender]; + } + + function transferFrom(address from, address to, uint tokens) public returns (bool) { + // `from` has enough tokens + require(balances[from] >= tokens); + // `sender` is allowed to move `tokens` from `from` + require(allowed[from][msg.sender] >= tokens); + + balances[to] += tokens; + balances[from] -= tokens; + allowed[from][msg.sender] -= tokens; + + Transfer(from, to, tokens); + return true; + } + + // following is the part of ForeignBridge that is concerned + // with moving tokens from and to HomeBridge struct SignaturesCollection { /// Signed message. @@ -393,6 +395,7 @@ contract ForeignBridge { // TODO: this may cause troubles if requiredSignatures len is changed if (deposits[hash].length == requiredSignatures) { balances[recipient] += value; + // mints tokens totalSupply += value; Deposit(recipient, value); } @@ -413,6 +416,7 @@ contract ForeignBridge { require(balances[recipient] + value > balances[recipient]); balances[msg.sender] -= value; + // burns tokens totalSupply -= value; Withdraw(recipient, value); } From 8a3a42a93af174effc3961c647c844fb2494a0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 12:15:08 +0100 Subject: [PATCH 047/152] add incomplete truffle/test/foreign-erc20.js --- truffle/test/foreign-erc20.js | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 truffle/test/foreign-erc20.js diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js new file mode 100644 index 0000000..b8c1cd7 --- /dev/null +++ b/truffle/test/foreign-erc20.js @@ -0,0 +1,72 @@ +var ForeignBridge = artifacts.require("ForeignBridge"); +var helpers = require("./helpers/helpers"); + +contract('ForeignBridge', function(accounts) { + it("totalSupply", function() { + var contract; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var owner = accounts[2]; + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + var value = web3.toWei(3, "ether"); + + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + contract = instance; + + return contract.totalSupply(); + }).then(function(result) { + assert.equal(0, result, "initial supply should be 0"); + + return contract.deposit(owner, value, hash, {from: authorities[0]}); + }).then(function(result) { + + return contract.totalSupply(); + }).then(function(result) { + console.log(result); + assert(result.equals(value), "deposit should increase supply"); + + return contract.transferHomeViaRelay(owner, value, {from: owner}); + }).then(function() { + + return contract.totalSupply(); + }).then(function(result) { + assert.equal(0, result, "home transfer should decrease supply"); + }) + }) + + it("should be able to approve others to spend tokens in their name", function() { + var contract; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var owner = accounts[2]; + var approved = accounts[3]; + var receiver = accounts[4]; + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + contract = instance; + + // deposit something so we can use it + return contract.deposit(owner, web3.toWei(3, "ether"), hash, {from: authorities[0]}); + }).then(function(result) { + + return contract.allowance(owner, approved); + }).then(function(result) { + assert.equal(0, result, "user should have 0 allowance initially"); + + return contract.transferFrom(owner, receiver, web3.toWei(1, "ether")); + }).then(function(result) { + assert(false, "transfer without allowance should fail"); + + }, function(err) { + return contract.approve(approved, web3.toWei(2, "ether"), {from: owner}); + }).then(function(result) { + console.log(result); + assert.equal(1, result.logs.length, "Exactly one event should be created"); + assert.equal("Approval", result.logs[0].event, "Event name should be Approval"); + assert.equal(owner, result.logs[0].args.tokenOwner); + assert.equal(approved, result.logs[0].args.spender); + assert.equal(web3.toWei(2, "ether"), result.logs[0].args.tokens); + }) + }) +}) From 810f01314045b7ad7136592561b80de1d16afec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 12:49:01 +0100 Subject: [PATCH 048/152] foreign-erc20.js: more test cases --- truffle/test/foreign-erc20.js | 55 +++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index b8c1cd7..961636e 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -39,7 +39,7 @@ contract('ForeignBridge', function(accounts) { var requiredSignatures = 1; var authorities = [accounts[0], accounts[1]]; var owner = accounts[2]; - var approved = accounts[3]; + var spender = accounts[3]; var receiver = accounts[4]; var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; @@ -50,23 +50,66 @@ contract('ForeignBridge', function(accounts) { return contract.deposit(owner, web3.toWei(3, "ether"), hash, {from: authorities[0]}); }).then(function(result) { - return contract.allowance(owner, approved); + return contract.allowance(owner, spender); }).then(function(result) { - assert.equal(0, result, "user should have 0 allowance initially"); + assert.equal(0, result, "initial allowance should be 0"); - return contract.transferFrom(owner, receiver, web3.toWei(1, "ether")); + return contract.transferFrom(owner, receiver, web3.toWei(1, "ether"), {from: spender}); }).then(function(result) { assert(false, "transfer without allowance should fail"); }, function(err) { - return contract.approve(approved, web3.toWei(2, "ether"), {from: owner}); + return contract.approve(spender, web3.toWei(4, "ether"), {from: owner}); + }).then(function(result) { + assert.equal(1, result.logs.length, "Exactly one event should be created"); + assert.equal("Approval", result.logs[0].event, "Event name should be Approval"); + assert.equal(owner, result.logs[0].args.tokenOwner); + assert.equal(spender, result.logs[0].args.spender); + assert.equal(web3.toWei(4, "ether"), result.logs[0].args.tokens); + + return contract.allowance(owner, spender); + }).then(function(result) { + assert.equal(web3.toWei(4, "ether"), result, "approval should set allowance"); + + return contract.transferFrom(owner, receiver, web3.toWei(4, "ether"), {from: spender}); + }).then(function(result) { + assert(false, "transferring more than balance should fail"); + }, function(err) { + return contract.approve(spender, web3.toWei(2, "ether"), {from: owner}); }).then(function(result) { console.log(result); assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("Approval", result.logs[0].event, "Event name should be Approval"); assert.equal(owner, result.logs[0].args.tokenOwner); - assert.equal(approved, result.logs[0].args.spender); + assert.equal(spender, result.logs[0].args.spender); assert.equal(web3.toWei(2, "ether"), result.logs[0].args.tokens); + + return contract.allowance(owner, spender); + }).then(function(result) { + assert.equal(web3.toWei(2, "ether"), result, "approval should update allowance"); + + return contract.transferFrom(owner, receiver, web3.toWei(2, "ether") + 2, {from: spender}); + }).then(function(result) { + assert(false, "transferring more than allowance should fail"); + }, function(err) { + return contract.transferFrom(owner, receiver, web3.toWei(2, "ether"), {from: spender}); + }).then(function(result) { + + return contract.balanceOf(owner); + }).then(function(result) { + assert.equal(web3.toWei(1, "ether"), result, "transferring should reduce owners balance"); + + return contract.balanceOf(receiver); + }).then(function(result) { + assert.equal(web3.toWei(2, "ether"), result, "transferring should increase receivers balance"); + + return contract.balanceOf(spender); + }).then(function(result) { + assert.equal(0, result, "transferring should not modify spenders balance"); + + return contract.allowance(owner, spender); + }).then(function(result) { + assert.equal(0, result, "transferring whole allowance should set allowance to 0"); }) }) }) From 334a7535b8063d4992b6411a3f56a3eb61fe6bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 13:29:32 +0100 Subject: [PATCH 049/152] bridge.sol: make name a public var instead of a function --- contracts/bridge.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 292b5c2..57d3ccb 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -264,6 +264,8 @@ contract ForeignBridge { uint public totalSupply; + string public name = "ParityBridgeForeignBridge"; + /// maps addresses to their token balances mapping (address => uint) public balances; @@ -273,10 +275,6 @@ contract ForeignBridge { /// Event created on money transfer event Transfer(address indexed from, address indexed to, uint tokens); - function name() public pure returns (string) { - return "ParityBridgeForeignBridge"; - } - function balanceOf(address tokenOwner) public view returns (uint) { return balances[tokenOwner]; } From e084966f25d8599e30f1bf9cb98988c51c8114e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 13:29:50 +0100 Subject: [PATCH 050/152] bridge.sol: comments --- contracts/bridge.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 57d3ccb..a609029 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -294,7 +294,9 @@ contract ForeignBridge { return true; } - // part of ERC20 standard responsible for giving others spending rights + // following is the part of ForeignBridge that is concerned + // with the part of the ERC20 standard responsible for giving others spending rights + // and spending others tokens event Approval(address indexed tokenOwner, address indexed spender, uint tokens); @@ -325,7 +327,8 @@ contract ForeignBridge { return true; } - // following is the part of ForeignBridge that is concerned + // following is the part of ForeignBridge that is + // no longer part of ERC20 and is concerned with // with moving tokens from and to HomeBridge struct SignaturesCollection { From 1c66c591a9228221875eb2d44bf21c5d0ccf27bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 13:45:17 +0100 Subject: [PATCH 051/152] bridge.sol: fix docstring --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index a609029..22dbb7a 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -282,7 +282,7 @@ contract ForeignBridge { /// Transfer `value` to `recipient` on this `foreign` chain. /// /// does not affect `home` chain. does not do a relay. - /// note that t + /// note that as specificed in ERC20 this doesn't fail if tokens == 0 function transfer(address recipient, uint tokens) public returns (bool) { require(balances[msg.sender] >= tokens); // fails if there is an overflow From 1ae92517a37d80249b5f853cd660cbc54164ef83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 13:45:39 +0100 Subject: [PATCH 052/152] more truffle tests --- truffle/test/foreign-erc20.js | 100 ++++++++++++++++++++++++++++++++++ truffle/test/foreign.js | 49 +---------------- 2 files changed, 103 insertions(+), 46 deletions(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index 961636e..4bc8f5d 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -112,4 +112,104 @@ contract('ForeignBridge', function(accounts) { assert.equal(0, result, "transferring whole allowance should set allowance to 0"); }) }) + + it("should allow user to transfer value locally", function() { + var meta; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var userAccount2 = accounts[3]; + var user1InitialValue = web3.toWei(3, "ether"); + var transferedValue = web3.toWei(1, "ether"); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + meta = instance; + // top up balance so we can transfer + return meta.deposit(userAccount, user1InitialValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transfer(userAccount2, transferedValue, { from: userAccount }); + }).then(function(result) { + assert.equal(1, result.logs.length, "Exactly one event should be created"); + assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); + assert.equal(userAccount, result.logs[0].args.from, "Event from should be transaction sender"); + assert.equal(userAccount2, result.logs[0].args.to, "Event from should be transaction recipient"); + assert.equal(transferedValue, result.logs[0].args.tokens, "Event tokens should match transaction value"); + return Promise.all([ + meta.balances.call(userAccount), + meta.balances.call(userAccount2) + ]) + }).then(function(result) { + assert.equal(web3.toWei(2, "ether"), result[0]); + assert.equal(transferedValue, result[1]); + }) + }) + + it("should not allow user to transfer value they don't have", function() { + var meta; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var recipientAccount = accounts[3]; + var userValue = web3.toWei(3, "ether"); + var transferedValue = web3.toWei(4, "ether"); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + meta = instance; + return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); + }).then(function(result) { + assert(false, "transfer should fail"); + }, function(err) { + }) + }) + + it("should allow transfer of 0 value according to ERC20", function() { + var meta; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var recipientAccount = accounts[3]; + var userValue = web3.toWei(3, "ether"); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + meta = instance; + return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transfer(recipientAccount, 0, { from: userAccount }); + }).then(function(result) { + assert.equal(1, result.logs.length, "Exactly one event should be created"); + assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); + assert.equal(userAccount, result.logs[0].args.from, "Event from should be transaction sender"); + assert.equal(recipientAccount, result.logs[0].args.to, "Event from should be transaction recipient"); + assert.equal(0, result.logs[0].args.tokens, "Event tokens should match transaction value"); + return Promise.all([ + meta.balances.call(userAccount), + meta.balances.call(recipientAccount) + ]) + }).then(function(result) { + assert.equal(userValue, result[0]); + assert.equal(0, result[1]); + }) + }) + + it("should fail to transfer with value overflow", function() { + var meta; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var recipientAccount = accounts[3]; + var userValue = web3.toWei(3, "ether"); + var transferedvalue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + meta = instance; + return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); + }).then(function(result) { + assert(false, "transfer should fail"); + }, function(err) { + }) + }) }) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 7c30f49..c125dd4 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -151,38 +151,7 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should allow user to transfer value locally", function() { - var meta; - var requiredSignatures = 1; - var authorities = [accounts[0], accounts[1]]; - var userAccount = accounts[2]; - var userAccount2 = accounts[3]; - var user1InitialValue = web3.toWei(3, "ether"); - var transferedValue = web3.toWei(1, "ether"); - var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { - meta = instance; - // top up balance so we can transfer - return meta.deposit(userAccount, user1InitialValue, hash, { from: authorities[0] }); - }).then(function(result) { - return meta.transfer(userAccount2, transferedValue, { from: userAccount }); - }).then(function(result) { - assert.equal(1, result.logs.length, "Exactly one event should be created"); - assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); - assert.equal(userAccount, result.logs[0].args.from, "Event from should be transaction sender"); - assert.equal(userAccount2, result.logs[0].args.to, "Event from should be transaction recipient"); - assert.equal(transferedValue, result.logs[0].args.tokens, "Event tokens should match transaction value"); - return Promise.all([ - meta.balances.call(userAccount), - meta.balances.call(userAccount2) - ]) - }).then(function(result) { - assert.equal(web3.toWei(2, "ether"), result[0]); - assert.equal(transferedValue, result[1]); - }) - }) - - it("should not allow user to transfer value they don't have either locally or to home", function() { + it("should not allow user to transfer value they don't have to home", function() { var meta; var requiredSignatures = 1; var authorities = [accounts[0], accounts[1]]; @@ -195,10 +164,6 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transfer should fail"); - }, function(err) { return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { assert(false, "transferHomeViaRelay should fail"); @@ -206,7 +171,7 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should fail to transfer 0 value both locally and to home", function() { + it("should fail to transfer 0 value to home", function() { var meta; var requiredSignatures = 1; var authorities = [accounts[0], accounts[1]]; @@ -219,10 +184,6 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transfer should fail"); - }, function(err) { return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { assert(false, "transferHomeViaRelay should fail"); @@ -230,7 +191,7 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should fail to transfer with value overflow both locally and to home", function() { + it("should fail to transfer with value overflow to home", function() { var meta; var requiredSignatures = 1; var authorities = [accounts[0], accounts[1]]; @@ -243,10 +204,6 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transfer should fail"); - }, function(err) { return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); }).then(function(result) { assert(false, "transferHomeViaRelay should fail"); From b8bf9bee54e0332657fa4ad00ba15b7e5e5f8cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 14:07:06 +0100 Subject: [PATCH 053/152] remove unnecessary check for overflow in transferHomeViaRelay resolve #88 --- contracts/bridge.sol | 4 ++-- truffle/test/foreign.js | 20 -------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 22dbb7a..e118d37 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -413,8 +413,8 @@ contract ForeignBridge { /// which transfers `value - relayCost` to `recipient` completing the transfer. function transferHomeViaRelay(address recipient, uint value) public { require(balances[msg.sender] >= value); - // fails if value == 0, or if there is an overflow - require(balances[recipient] + value > balances[recipient]); + // fails if value == 0 + require(value > 0); balances[msg.sender] -= value; // burns tokens diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index c125dd4..99f805b 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -191,26 +191,6 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should fail to transfer with value overflow to home", function() { - var meta; - var requiredSignatures = 1; - var authorities = [accounts[0], accounts[1]]; - var userAccount = accounts[2]; - var recipientAccount = accounts[3]; - var userValue = web3.toWei(3, "ether"); - var transferedvalue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); - var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { - meta = instance; - return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); - }).then(function(result) { - return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transferHomeViaRelay should fail"); - }, function(err) { - }) - }) - it("should allow user to trigger withdraw", function() { var meta; var requiredSignatures = 1; From 9fee20e0261060f20fafe9dbb82cff1bb61559c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 14:12:08 +0100 Subject: [PATCH 054/152] test/foreign-erc20.js: fix test for transfer with overflow --- truffle/test/foreign-erc20.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index 4bc8f5d..b44a02b 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -193,20 +193,21 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should fail to transfer with value overflow", function() { + it("transfer that results in overflow should fail", function() { var meta; var requiredSignatures = 1; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var recipientAccount = accounts[3]; - var userValue = web3.toWei(3, "ether"); - var transferedvalue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); + var maxValue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { meta = instance; - return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); + return meta.deposit(recipientAccount, maxValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); + return meta.deposit(userAccount, 1, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transfer(recipientAccount, 1, { from: userAccount }); }).then(function(result) { assert(false, "transfer should fail"); }, function(err) { From 37af2d1c986567ba674473b8dd231f55211ef8fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 14:27:31 +0100 Subject: [PATCH 055/152] test/foreign-erc20.js: test that transferFrom(0) succeeds and add more assertions --- truffle/test/foreign-erc20.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index b44a02b..c529642 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -58,6 +58,15 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert(false, "transfer without allowance should fail"); + // transfer 0 without allowance should work + return contract.transferFrom(owner, receiver, 0, {from: spender}); + }).then(function(result) { + assert.equal(1, result.logs.length, "Exactly one event should be created"); + assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); + assert.equal(owner, result.logs[0].args.from); + assert.equal(receiver, result.logs[0].args.to); + assert.equal(0, result.logs[0].args.tokens); + }, function(err) { return contract.approve(spender, web3.toWei(4, "ether"), {from: owner}); }).then(function(result) { @@ -77,7 +86,6 @@ contract('ForeignBridge', function(accounts) { }, function(err) { return contract.approve(spender, web3.toWei(2, "ether"), {from: owner}); }).then(function(result) { - console.log(result); assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("Approval", result.logs[0].event, "Event name should be Approval"); assert.equal(owner, result.logs[0].args.tokenOwner); @@ -94,6 +102,11 @@ contract('ForeignBridge', function(accounts) { }, function(err) { return contract.transferFrom(owner, receiver, web3.toWei(2, "ether"), {from: spender}); }).then(function(result) { + assert.equal(1, result.logs.length, "Exactly one event should be created"); + assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); + assert.equal(owner, result.logs[0].args.from); + assert.equal(receiver, result.logs[0].args.to); + assert.equal(web3.toWei(2, "ether"), result.logs[0].args.tokens); return contract.balanceOf(owner); }).then(function(result) { From 08d481206d3d768a95420d134c38ed5f1e05006c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 15:27:10 +0100 Subject: [PATCH 056/152] bridge.sol: improve comment --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index e118d37..9e8561e 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -413,7 +413,7 @@ contract ForeignBridge { /// which transfers `value - relayCost` to `recipient` completing the transfer. function transferHomeViaRelay(address recipient, uint value) public { require(balances[msg.sender] >= value); - // fails if value == 0 + // don't allow 0 value transfers to home require(value > 0); balances[msg.sender] -= value; From 2f75f3683f5a3095da42107bd6b63df4085f6916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 15:34:16 +0100 Subject: [PATCH 057/152] bridge.sol: emit Transfer from 0x0 on token creation as laid out in ERC20 --- contracts/bridge.sol | 4 ++++ truffle/test/foreign.js | 44 ++++++++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 9e8561e..bd3f4a7 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -398,6 +398,10 @@ contract ForeignBridge { balances[recipient] += value; // mints tokens totalSupply += value; + // ERC20 specifies: a token contract which creates new tokens + // SHOULD trigger a Transfer event with the _from address + // set to 0x0 when tokens are created. + Transfer(0x0, recipient, value); Deposit(recipient, value); } } diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 99f805b..5b6d6da 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -48,10 +48,17 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { - assert.equal(1, result.logs.length, "Exactly one event should be created"); - assert.equal("Deposit", result.logs[0].event, "Event name should be Deposit"); - assert.equal(userAccount, result.logs[0].args.recipient, "Event recipient should be transaction sender"); - assert.equal(value, result.logs[0].args.value, "Event value should match deposited ether"); + assert.equal(2, result.logs.length) + + assert.equal("Transfer", result.logs[0].event); + assert.equal("0x0000000000000000000000000000000000000000", result.logs[0].args.from); + assert.equal(userAccount, result.logs[0].args.to); + assert.equal(value, result.logs[0].args.tokens); + + assert.equal("Deposit", result.logs[1].event); + assert.equal(userAccount, result.logs[1].args.recipient); + assert.equal(value, result.logs[1].args.value); + return meta.balances.call(userAccount); }).then(function(result) { assert.equal(value, result, "Contract balance should change"); @@ -76,10 +83,16 @@ contract('ForeignBridge', function(accounts) { assert.equal(web3.toWei(0, "ether"), result, "Contract balance should not change yet"); return meta.deposit(userAccount, value, hash, { from: authorities[1] }); }).then(function(result) { - assert.equal(1, result.logs.length, "Exactly one event should be created"); - assert.equal("Deposit", result.logs[0].event, "Event name should be Deposit"); - assert.equal(userAccount, result.logs[0].args.recipient, "Event recipient should be transaction sender"); - assert.equal(value, result.logs[0].args.value, "Event value should match deposited ether"); + assert.equal(2, result.logs.length) + + assert.equal("Transfer", result.logs[0].event); + assert.equal("0x0000000000000000000000000000000000000000", result.logs[0].args.from); + assert.equal(userAccount, result.logs[0].args.to); + assert.equal(value, result.logs[0].args.tokens); + + assert.equal("Deposit", result.logs[1].event, "Event name should be Deposit"); + assert.equal(userAccount, result.logs[1].args.recipient, "Event recipient should be transaction sender"); + assert.equal(value, result.logs[1].args.value, "Event value should match deposited ether"); return meta.balances.call(userAccount); }).then(function(result) { assert.equal(value, result, "Contract balance should change"); @@ -141,10 +154,17 @@ contract('ForeignBridge', function(accounts) { assert.equal(0, result.logs.length, "Misbehaving authority should be ignored"); return meta.deposit(userAccount, value, hash, { from: authorities[2] }) }).then(function(result) { - assert.equal(1, result.logs.length, "Exactly one event should be created"); - assert.equal("Deposit", result.logs[0].event, "Event name should be Deposit"); - assert.equal(userAccount, result.logs[0].args.recipient, "Event recipient should be transaction sender"); - assert.equal(value, result.logs[0].args.value, "Event value should match transaction value"); + assert.equal(2, result.logs.length) + + assert.equal("Transfer", result.logs[0].event); + assert.equal("0x0000000000000000000000000000000000000000", result.logs[0].args.from); + assert.equal(userAccount, result.logs[0].args.to); + assert.equal(value, result.logs[0].args.tokens); + + assert.equal("Deposit", result.logs[1].event, "Event name should be Deposit"); + assert.equal(userAccount, result.logs[1].args.recipient, "Event recipient should be transaction sender"); + assert.equal(value, result.logs[1].args.value, "Event value should match transaction value"); + return meta.balances.call(userAccount); }).then(function(result) { assert.equal(value, result, "Contract balance should change"); From 0e13ed406b6c4f27d587b45c866a9cd692db91d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 15:35:17 +0100 Subject: [PATCH 058/152] bridge.sol: emit Tranfer to 0x0 if tokens are destroyed --- contracts/bridge.sol | 4 ++++ truffle/test/foreign.js | 15 +++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index bd3f4a7..0b99061 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -423,6 +423,10 @@ contract ForeignBridge { balances[msg.sender] -= value; // burns tokens totalSupply -= value; + // in line with the transfer event from `0x0` on token creation + // recommended by ERC20 (see implementation of `deposit` above) + // we trigger a Transfer event to `0x0` on token destruction + Transfer(msg.sender, 0x0, value); Withdraw(recipient, value); } diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 5b6d6da..4d5792e 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -227,10 +227,17 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { return meta.transferHomeViaRelay(userAccount2, value2, { from: userAccount }); }).then(function(result) { - assert.equal(1, result.logs.length, "Exactly one event should be created"); - assert.equal("Withdraw", result.logs[0].event, "Event name should be Withdraw"); - assert.equal(userAccount2, result.logs[0].args.recipient, "Event recipient should be equal to transaction recipient"); - assert.equal(value2, result.logs[0].args.value, "Event value should match transaction value"); + assert.equal(2, result.logs.length) + + assert.equal("Transfer", result.logs[0].event); + assert.equal(userAccount, result.logs[0].args.from); + assert.equal("0x0000000000000000000000000000000000000000", result.logs[0].args.to); + assert.equal(value2, result.logs[0].args.tokens); + + assert.equal("Withdraw", result.logs[1].event, "Event name should be Withdraw"); + assert.equal(userAccount2, result.logs[1].args.recipient, "Event recipient should be equal to transaction recipient"); + assert.equal(value2, result.logs[1].args.value, "Event value should match transaction value"); + return Promise.all([ meta.balances.call(userAccount), meta.balances.call(userAccount2) From 4900eeb2956fde436580dcaf534bd5da3d7a80a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 15:35:51 +0100 Subject: [PATCH 059/152] improve comment --- truffle/test/foreign-erc20.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index c529642..aab6b72 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -46,7 +46,7 @@ contract('ForeignBridge', function(accounts) { return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { contract = instance; - // deposit something so we can use it + // deposit something so we can transfer it return contract.deposit(owner, web3.toWei(3, "ether"), hash, {from: authorities[0]}); }).then(function(result) { From 165e822c31780f9d65fff0e2792fec7a92c7d772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 23 Jan 2018 15:36:59 +0100 Subject: [PATCH 060/152] bridge.sol: improve name --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 0b99061..2bd1c02 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -264,7 +264,7 @@ contract ForeignBridge { uint public totalSupply; - string public name = "ParityBridgeForeignBridge"; + string public name = "ForeignBridge"; /// maps addresses to their token balances mapping (address => uint) public balances; From 3db1a1abf352d56386b706f9d009ba906119168f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 11:03:33 +0100 Subject: [PATCH 061/152] README.md: mention ERC20 --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 993325c..2c21ea2 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,12 @@ [coveralls-image]: https://coveralls.io/repos/github/paritytech/parity-bridge/badge.svg?branch=master [coveralls-url]: https://coveralls.io/github/paritytech/parity-bridge?branch=master -bridge between two ethereum blockchains, `home` and `foreign`. +the parity bridge connects two ethereum blockchains, `home` and `foreign`. ### current functionality -the bridge allows users to deposit ether into a smart contract on `home` and get it on `foreign` in form of a token balance. +the bridge allows users to deposit ether into a smart contract on `home` +and get it on `foreign` in form of an ERC20 token. it also allows users to withdraw their tokens on `foreign` and get the equivalent ether on `home`. on `foreign` users can freely transfer tokens between each other. From 5ef7c895ece606d4ff6a39e3a4b4213e61d6b42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 11:03:48 +0100 Subject: [PATCH 062/152] bridge.sol: add period to comment --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 2bd1c02..ee3c801 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -259,7 +259,7 @@ contract HomeBridge { contract ForeignBridge { - // following is the part of ForeignBridge that implements an ERC20 token + // following is the part of ForeignBridge that implements an ERC20 token. // ERC20 spec: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md uint public totalSupply; From a2dcbecd1bf4cee532b0fa812734244e3ccbadce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 11:35:55 +0100 Subject: [PATCH 063/152] Cargo.lock: update --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b6a6cff..26ca6eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,7 +329,6 @@ dependencies = [ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", From 66a45f24e2a58c8c15f26bcd06056c1ba6439501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 15:01:10 +0100 Subject: [PATCH 064/152] integration tests bridge config: give deposit more gas so it succeeds --- integration-tests/bridge_config.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/bridge_config.toml b/integration-tests/bridge_config.toml index c1d2979..511aa8a 100644 --- a/integration-tests/bridge_config.toml +++ b/integration-tests/bridge_config.toml @@ -23,8 +23,8 @@ accounts = [ required_signatures = 1 [transactions] -home_deploy = { gas = 1000000 } +home_deploy = { gas = 3000000 } foreign_deploy = { gas = 3000000 } -deposit_relay = { gas = 100000 } +deposit_relay = { gas = 3000000 } withdraw_relay = { gas = 3000000 } withdraw_confirm = { gas = 3000000 } From 60130d0d6f41f4f7fede76570ec6fe02c717e661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 15:07:05 +0100 Subject: [PATCH 065/152] bridge.sol: improve comment --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index ee3c801..942835f 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -389,7 +389,7 @@ contract ForeignBridge { // Protection from misbehaving authority var hash = keccak256(recipient, value, transactionHash); - // Duplicated deposits + // don't allow authority to confirm deposit twice require(!Helpers.addressArrayContains(deposits[hash], msg.sender)); deposits[hash].push(msg.sender); From c91eae631fce1471abf435899c7220b02d5cbee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 15:07:22 +0100 Subject: [PATCH 066/152] deposit_relay.rs: add info level logging --- bridge/src/bridge/deposit_relay.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bridge/src/bridge/deposit_relay.rs b/bridge/src/bridge/deposit_relay.rs index 1a83cf2..ae25695 100644 --- a/bridge/src/bridge/deposit_relay.rs +++ b/bridge/src/bridge/deposit_relay.rs @@ -73,6 +73,7 @@ impl Stream for DepositRelay { let next_state = match self.state { DepositRelayState::Wait => { let item = try_stream!(self.logs.poll()); + info!("got {} new deposits to relay", item.logs.len()); let deposits = item.logs .into_iter() .map(|log| deposit_relay_payload(&self.app.home_bridge, &self.app.foreign_bridge, log)) @@ -95,6 +96,7 @@ impl Stream for DepositRelay { }) .collect::>(); + info!("relaying {} deposits", deposits.len()); DepositRelayState::RelayDeposits { future: join_all(deposits), block: item.to, @@ -102,6 +104,7 @@ impl Stream for DepositRelay { }, DepositRelayState::RelayDeposits { ref mut future, block } => { let _ = try_ready!(future.poll()); + info!("deposit relay completed"); DepositRelayState::Yield(Some(block)) }, DepositRelayState::Yield(ref mut block) => match block.take() { From 1b454204c502833c1664a2cd2a2e2b3faf682d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 24 Jan 2018 15:09:31 +0100 Subject: [PATCH 067/152] integration tests: various improvements. reduce duplication --- .../tests/basic_deposit_then_withdraw.rs | 76 ++++++++++++++----- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index df51f4e..773894e 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -60,6 +60,10 @@ fn parity_foreign_command() -> Command { command } +fn address_from_str(string: &'static str) -> web3::types::Address { + web3::types::Address::from(&Address::from(string).0[..]) +} + #[test] fn test_basic_deposit_then_withdraw() { if Path::new(TMP_PATH).exists() { @@ -74,7 +78,7 @@ fn test_basic_deposit_then_withdraw() { .arg("build") .status() .expect("failed to build bridge cli") - .success()); + .success()); // start a parity node that represents the home chain let mut parity_home = parity_home_command() @@ -89,6 +93,13 @@ fn test_basic_deposit_then_withdraw() { // give the clients time to start up thread::sleep(Duration::from_millis(3000)); + // A address containing a lot of tokens (0x00a329c0648769a73afac7f9381e08fb43dbea72) should be + // automatically added with a password being an empty string. + // source: https://paritytech.github.io/wiki/Private-development-chain.html + let user_address = "0x00a329c0648769a73afac7f9381e08fb43dbea72"; + + let authority_address = "0x00bd138abd70e2f00903268f3db08f2d25677c9e"; + // create authority account on home let exit_status = Command::new("curl") .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["node0", ""],"id":0}"#) @@ -98,6 +109,7 @@ fn test_basic_deposit_then_withdraw() { .status() .expect("failed to create authority account on home"); assert!(exit_status.success()); + // TODO [snd] assert that created address matches authority_address // create authority account on foreign let exit_status = Command::new("curl") @@ -108,6 +120,7 @@ fn test_basic_deposit_then_withdraw() { .status() .expect("failed to create/unlock authority account on foreign"); assert!(exit_status.success()); + // TODO [snd] assert that created address matches authority_address // give the operations time to complete thread::sleep(Duration::from_millis(5000)); @@ -121,14 +134,14 @@ fn test_basic_deposit_then_withdraw() { // start a parity node that represents the home chain with accounts unlocked let mut parity_home = parity_home_command() - .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") + .arg("--unlock").arg(format!("{},{}", user_address, authority_address)) .arg("--password").arg("password.txt") .spawn() .expect("failed to spawn parity home node"); // start a parity node that represents the foreign chain with accounts unlocked let mut parity_foreign = parity_foreign_command() - .arg("--unlock").arg("0x00a329c0648769a73afac7f9381e08fb43dbea72,0x00bd138abd70e2f00903268f3db08f2d25677c9e") + .arg("--unlock").arg(format!("{},{}", user_address, authority_address)) .arg("--password").arg("password.txt") .spawn() .expect("failed to spawn parity foreign node"); @@ -149,15 +162,18 @@ fn test_basic_deposit_then_withdraw() { // give the bridge time to start up and deploy the contracts thread::sleep(Duration::from_millis(10000)); - println!("\ndeposit ether into HomeBridge\n"); + let home_contract_address = "0xebd3944af37ccc6b67ff61239ac4fef229c8f69f"; + let foreign_contract_address = "0xebd3944af37ccc6b67ff61239ac4fef229c8f69f"; - // user deposits into HomeBridge + println!("\nuser deposits ether into HomeBridge\n"); + + // TODO [snd] use rpc client here instead of curl let exit_status = Command::new("curl") - .arg("--data").arg(r#"{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ - "from": "0x00a329c0648769a73afac7f9381e08fb43dbea72", - "to": "0xebd3944af37ccc6b67ff61239ac4fef229c8f69f", + .arg("--data").arg(format!(r#"{{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{{ + "from": "{}", + "to": "{}", "value": "0x186a0" - }],"id":0}"#) + }}],"id":0}}"#, user_address, home_contract_address)) .arg("-H").arg("Content-Type: application/json") .arg("-X").arg("POST") .arg("localhost:8550") @@ -168,7 +184,7 @@ fn test_basic_deposit_then_withdraw() { println!("\ndeposit into home sent. give it plenty of time to get mined and relayed\n"); thread::sleep(Duration::from_millis(10000)); - // connect for foreign and home via IPC + // connect to foreign and home via IPC let mut event_loop = Core::new().unwrap(); let foreign_transport = Ipc::with_event_loop("foreign.ipc", &event_loop.handle()) .expect("failed to connect to foreign.ipc"); @@ -178,12 +194,30 @@ fn test_basic_deposit_then_withdraw() { .expect("failed to connect to home.ipc"); let home_eth = web3::api::Eth::new(home_transport); - // balance on ForeignBridge should have increased - let balance_payload = foreign.functions().balances().input(Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72")); + // totalSupply on ForeignBridge should have increased + let total_supply_payload = foreign.functions().total_supply().input(); let future = foreign_eth.call(web3::types::CallRequest{ from: None, - to: web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..]), + to: address_from_str(foreign_contract_address), + gas: None, + gas_price: None, + value: None, + data: Some(web3::types::Bytes(total_supply_payload)), + }, None); + + let response = event_loop.run(future).unwrap(); + assert_eq!( + U256::from(response.0.as_slice()), + U256::from(100000), + "totalSupply on ForeignBridge should have increased"); + + // balance on ForeignBridge should have increased + let balance_payload = foreign.functions().balance_of().input(Address::from(user_address)); + + let future = foreign_eth.call(web3::types::CallRequest{ + from: None, + to: address_from_str(foreign_contract_address), gas: None, gas_price: None, value: None, @@ -193,21 +227,21 @@ fn test_basic_deposit_then_withdraw() { let response = event_loop.run(future).unwrap(); let balance = U256::from(response.0.as_slice()); assert_eq!( - balance, - U256::from(100000), - "balance on ForeignBridge should have increased"); + balance, + U256::from(100000), + "balance on ForeignBridge should have increased"); println!("\nconfirmed that deposit reached foreign\n"); - // withdraw + println!("\nuser executes ForeignBridge.transferHomeViaRelay\n"); let transfer_payload = foreign.functions() .transfer_home_via_relay() .input( - Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2"), + Address::from(user_address), U256::from(100000)); let future = foreign_eth.send_transaction(web3::types::TransactionRequest{ - from: web3::types::Address::from(&Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72").0[..]), - to: Some(web3::types::Address::from(&Address::from("0xebd3944af37ccc6b67ff61239ac4fef229c8f69f").0[..])), + from: address_from_str(user_address), + to: Some(address_from_str(foreign_contract_address)), gas: None, gas_price: None, value: None, @@ -221,7 +255,7 @@ fn test_basic_deposit_then_withdraw() { thread::sleep(Duration::from_millis(10000)); // test that withdraw completed - let future = home_eth.balance(web3::types::Address::from(&Address::from("0x00aa39d30f0d20ff03a22ccfc30b7efbfca597c2").0[..]), None); + let future = home_eth.balance(address_from_str(user_address), None); println!("waiting for future"); let balance = event_loop.run(future).unwrap(); assert!(balance > web3::types::U256::from(0)); From fbefc5e9ecd9d9d8be7f6a14cfd6ea625ba0e204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 26 Jan 2018 09:43:21 +0100 Subject: [PATCH 068/152] README.md: improve explanation and update for ERC20 --- README.md | 63 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2c21ea2..30b540b 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,27 @@ [coveralls-image]: https://coveralls.io/repos/github/paritytech/parity-bridge/badge.svg?branch=master [coveralls-url]: https://coveralls.io/github/paritytech/parity-bridge?branch=master -the parity bridge connects two ethereum blockchains, `home` and `foreign`. +the bridge is an +[ERC20 token](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md) +contract that is backed by ether on **another** ethereum blockchain. -### current functionality +given a bridge between two chains +users can freely convert any amount of ether +one one chain into the same amount of ERC20 tokens on the other and back. +the bridge securely relays these conversions. -the bridge allows users to deposit ether into a smart contract on `home` -and get it on `foreign` in form of an ERC20 token. -it also allows users to withdraw their tokens on `foreign` and get the equivalent ether on `home`. -on `foreign` users can freely transfer tokens between each other. +**the bridge can solve scaling issues:** +by deploying a [proof-of-authority](https://paritytech.github.io/wiki/Proof-of-Authority-Chains.html) +network and bridging it to mainnet users can convert their mainnet ether +into ERC20 tokens on the PoA chain +and there transfer them with much lower transaction fees, +faster block times and unaffected by mainnet congestion. -`foreign` is assumed to use PoA (proof of authority) consensus. -relays between the chains happen in a byzantine fault tolerant way using the authorities of `foreign`. +at any point can the users withdraw their tokens worth of ether on the mainnet. + +parity is using the bridge project to prototype +the system that will eventually connect ethereum and other non-parachains to +[polkadot](https://polkadot.io/) ### next steps @@ -26,43 +36,52 @@ relays between the chains happen in a byzantine fault tolerant way using the aut 2. make bridge work with contract-based dynamic validator set 3. after kovan hardfork 2: deploy to kovan again with dynamic validator set -### eventual goals +### current functionality -connect ethereum to polkadot +the bridge connects two chains `home` and `foreign`. -### deposit ether into `HomeBridge` and get it in form of a token balance on `ForeignBridge` +when users deposit ether into the `HomeBridge` contract on `home` +they get the same amount of ERC20 tokens on `foreign`. + +they can use `ForeignBridge` as they would use any ERC20 token. + +to convert their `foreign` ERC20 into ether on `home` +users can always call `ForeignBridge.transferHomeViaRelay(homeRecipientAddress, value)`. + +`foreign` is assumed to use PoA (proof of authority) consensus. +relays between the chains happen in a byzantine fault tolerant way using the authorities of `foreign`. + +### `home` ether -> `foreign` ERC20 `sender` deposits `value` into `HomeBridge`. the `HomeBridge` fallback function emits `Deposit(sender, value)`. -for each `Deposit` event on `HomeBridge` every authority makes a transaction + +for each `Deposit` event on `HomeBridge` every authority executes `ForeignBridge.deposit(sender, value, transactionHash)`. + once there are `ForeignBridge.requiredSignatures` such transactions with identical arguments and from distinct authorities then -`ForeignBridge.balances(sender)` is increased by `value` and -`ForeignBridge.Deposit(sender, value)` is emitted. +`ForeignBridge.balanceOf(sender)` is increased by `value`. -### withdraw balance on `ForeignBridge` and get it as ether on `home` chain +### `foreign` ERC20 -> `home` ether `sender` executes `ForeignBridge.transferHomeViaRelay(recipient, value)` which checks and reduces `ForeignBridge.balances(sender)` by `value` and emits `ForeignBridge.Withdraw(recipient, value)`. + for each `ForeignBridge.Withdraw` every bridge authority creates a message containg `value`, `recipient` and the `transactionHash` of the transaction containing the `ForeignBridge.Withdraw` event, -signs the message and makes a transaction `ForeignBridge.submitSignature(signature, message)`. +signs the message and executes `ForeignBridge.submitSignature(signature, message)`. this collection of signatures on `foreign` is necessary because transactions are free for authorities on `foreign`, since they are the authorities of `foreign`, but not free on `home`. + once `ForeignBridge.requiredSignatures` signatures by distinct authorities are collected a `ForeignBridge.CollectedSignatures(authorityThatSubmittedLastSignature, messageHash)` event is emitted. + everyone (usually `authorityThatSubmittedLastSignature`) can then call `ForeignBridge.message(messageHash)` and `ForeignBridge.signature(messageHash, 0..requiredSignatures)` to look up the message and signatures and execute `HomeBridge.withdraw(vs, rs, ss, message)` and complete the withdraw. -### transfer on `foreign` - -`sender` executes `ForeignBridge.transferLocal(recipient, value)` -which checks and reduces `ForeignBridge.balances(sender)` and increases `ForeignBridge.balances(recipient)` -by `value`. - ### build requires `solc` to be in `$PATH`. [installation instructions](https://solidity.readthedocs.io/en/develop/installing-solidity.html) From e0d4c52fd6d1476bed702472eaacabafef2517fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 26 Jan 2018 09:44:16 +0100 Subject: [PATCH 069/152] bridge.sol: improve docstrings and comments --- contracts/bridge.sol | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 942835f..5a5ebe7 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -269,12 +269,13 @@ contract ForeignBridge { /// maps addresses to their token balances mapping (address => uint) public balances; - // Owner of account approves the transfer of an amount by another account + // owner of account approves the transfer of an amount by another account mapping(address => mapping (address => uint)) allowed; /// Event created on money transfer event Transfer(address indexed from, address indexed to, uint tokens); + // returns the ERC20 token balance of the given address function balanceOf(address tokenOwner) public view returns (uint) { return balances[tokenOwner]; } @@ -282,7 +283,7 @@ contract ForeignBridge { /// Transfer `value` to `recipient` on this `foreign` chain. /// /// does not affect `home` chain. does not do a relay. - /// note that as specificed in ERC20 this doesn't fail if tokens == 0 + /// as specificed in ERC20 this doesn't fail if tokens == 0. function transfer(address recipient, uint tokens) public returns (bool) { require(balances[msg.sender] >= tokens); // fails if there is an overflow @@ -298,10 +299,12 @@ contract ForeignBridge { // with the part of the ERC20 standard responsible for giving others spending rights // and spending others tokens + // created when `approve` is executed to mark that + // `tokenOwner` has approved `spender` to spend `tokens` of his tokens event Approval(address indexed tokenOwner, address indexed spender, uint tokens); - // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. - // If this function is called again it overwrites the current allowance with _value. + // allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. + // calling this function repeatedly overwrites the current allowance. function approve(address spender, uint tokens) public returns (bool) { allowed[msg.sender][spender] = tokens; Approval(msg.sender, spender, tokens); From 05664c701b9619b725d9498b79bd0d6db4d0bd31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 26 Jan 2018 09:54:44 +0100 Subject: [PATCH 070/152] README.md: various improvements --- README.md | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 30b540b..3ca1d28 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [coveralls-url]: https://coveralls.io/github/paritytech/parity-bridge?branch=master the bridge is an -[ERC20 token](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md) +[ERC20 token](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) contract that is backed by ether on **another** ethereum blockchain. given a bridge between two chains @@ -24,16 +24,16 @@ into ERC20 tokens on the PoA chain and there transfer them with much lower transaction fees, faster block times and unaffected by mainnet congestion. -at any point can the users withdraw their tokens worth of ether on the mainnet. +the users can withdraw their tokens worth of ether on the mainnet at any point. parity is using the bridge project to prototype the system that will eventually connect ethereum and other non-parachains to -[polkadot](https://polkadot.io/) +[polkadot](https://polkadot.io/). ### next steps -1. deploy to bridge **ethereum** and **kovan** with the kovan authorities being the immutable set of bridge authorities -2. make bridge work with contract-based dynamic validator set +1. deploy to bridge **ethereum** and **kovan** with the kovan authorities being the fixed set of bridge authorities +2. make the bridge work with contract-based dynamic validator sets 3. after kovan hardfork 2: deploy to kovan again with dynamic validator set ### current functionality @@ -43,7 +43,7 @@ the bridge connects two chains `home` and `foreign`. when users deposit ether into the `HomeBridge` contract on `home` they get the same amount of ERC20 tokens on `foreign`. -they can use `ForeignBridge` as they would use any ERC20 token. +[they can use `ForeignBridge` as they would use any ERC20 token.](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) to convert their `foreign` ERC20 into ether on `home` users can always call `ForeignBridge.transferHomeViaRelay(homeRecipientAddress, value)`. @@ -51,7 +51,7 @@ users can always call `ForeignBridge.transferHomeViaRelay(homeRecipientAddress, `foreign` is assumed to use PoA (proof of authority) consensus. relays between the chains happen in a byzantine fault tolerant way using the authorities of `foreign`. -### `home` ether -> `foreign` ERC20 +### highlevel explanation of home ether -> foreign ERC20 relay `sender` deposits `value` into `HomeBridge`. the `HomeBridge` fallback function emits `Deposit(sender, value)`. @@ -63,7 +63,7 @@ once there are `ForeignBridge.requiredSignatures` such transactions with identical arguments and from distinct authorities then `ForeignBridge.balanceOf(sender)` is increased by `value`. -### `foreign` ERC20 -> `home` ether +### highlevel explanation of foreign ERC20 -> home ether relay `sender` executes `ForeignBridge.transferHomeViaRelay(recipient, value)` which checks and reduces `ForeignBridge.balances(sender)` by `value` and emits `ForeignBridge.Withdraw(recipient, value)`. @@ -82,6 +82,20 @@ everyone (usually `authorityThatSubmittedLastSignature`) can then call `ForeignB to look up the message and signatures and execute `HomeBridge.withdraw(vs, rs, ss, message)` and complete the withdraw. +`HomeBridge.withdraw(vs, rs, ss, message)` recovers the addresses for the signatures, +checks that enough authorities in its authority list have signed and +finally transfers `value` ether ([minus the relay gas costs](#recipient-pays-relay-cost-to-relaying-authority)) +to `recipient`. + +### run truffle smart contract tests + +requires `yarn` to be `$PATH`. [installation instructions](https://yarnpkg.com/lang/en/docs/install/) + +``` +cd truffle +yarn test +``` + ### build requires `solc` to be in `$PATH`. [installation instructions](https://solidity.readthedocs.io/en/develop/installing-solidity.html) @@ -227,15 +241,6 @@ checked_withdraw_confirm = 121 ![withdraw](./res/withdraw.png) -### truffle tests - -requires `yarn` to be `$PATH`. [installation instructions](https://yarnpkg.com/lang/en/docs/install/) - -``` -cd truffle -yarn test -``` - ### recipient pays relay cost to relaying authority a bridge `authority` has to pay for gas (`cost`) to execute `HomeBridge.withdraw` when From 1daa7bb6add92dda1f900800bd3bc8ac8a04814e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 26 Jan 2018 09:58:58 +0100 Subject: [PATCH 071/152] README.md: wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ca1d28..4e1c8e7 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ everyone (usually `authorityThatSubmittedLastSignature`) can then call `ForeignB to look up the message and signatures and execute `HomeBridge.withdraw(vs, rs, ss, message)` and complete the withdraw. -`HomeBridge.withdraw(vs, rs, ss, message)` recovers the addresses for the signatures, +`HomeBridge.withdraw(vs, rs, ss, message)` recovers the addresses from the signatures, checks that enough authorities in its authority list have signed and finally transfers `value` ether ([minus the relay gas costs](#recipient-pays-relay-cost-to-relaying-authority)) to `recipient`. From ddc54802dd73a4f210c0ba20b7c6206c18d70615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 26 Jan 2018 10:23:05 +0100 Subject: [PATCH 072/152] bridge.sol: check for overflow in transferFrom --- contracts/bridge.sol | 2 ++ truffle/.node-xmlhttprequest-content-37792 | 1 + truffle/.node-xmlhttprequest-sync-37792 | 0 truffle/test/foreign-erc20.js | 24 ++++++++++++++++++++++ 4 files changed, 27 insertions(+) create mode 100644 truffle/.node-xmlhttprequest-content-37792 create mode 100644 truffle/.node-xmlhttprequest-sync-37792 diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 5a5ebe7..bb743ba 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -321,6 +321,8 @@ contract ForeignBridge { require(balances[from] >= tokens); // `sender` is allowed to move `tokens` from `from` require(allowed[from][msg.sender] >= tokens); + // fails if there is an overflow + require(balances[to] + tokens >= balances[to]); balances[to] += tokens; balances[from] -= tokens; diff --git a/truffle/.node-xmlhttprequest-content-37792 b/truffle/.node-xmlhttprequest-content-37792 new file mode 100644 index 0000000..6551190 --- /dev/null +++ b/truffle/.node-xmlhttprequest-content-37792 @@ -0,0 +1 @@ +{"err":null,"data":{"statusCode":200,"headers":{"access-control-allow-headers":"Origin, X-Requested-With, Content-Type, Accept","access-control-allow-origin":"*","access-control-allow-methods":"*","content-type":"application/json","date":"Fri, 26 Jan 2018 09:06:17 GMT","connection":"close","transfer-encoding":"chunked"},"text":"{\"id\":723,\"jsonrpc\":\"2.0\",\"result\":\"0x00000000000000056bc75e2d63100000\"}"}} \ No newline at end of file diff --git a/truffle/.node-xmlhttprequest-sync-37792 b/truffle/.node-xmlhttprequest-sync-37792 new file mode 100644 index 0000000..e69de29 diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index aab6b72..0691b7c 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -226,4 +226,28 @@ contract('ForeignBridge', function(accounts) { }, function(err) { }) }) + + it("transferFrom that results in overflow should fail", function() { + var meta; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var spenderAccount = accounts[3]; + var recipientAccount = accounts[4]; + var maxValue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + meta = instance; + return meta.deposit(recipientAccount, maxValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.deposit(userAccount, 1, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.approve(spenderAccount, 1, {from: userAccount}); + }).then(function(result) { + return meta.transferFrom(userAccount, recipientAccount, 1, { from: spenderAccount }); + }).then(function(result) { + assert(false, "transfer should fail"); + }, function(err) { + }) + }) }) From 6dc9ec827c5a003ddeb48ccd2112c6f77718d6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 26 Jan 2018 13:47:53 +0100 Subject: [PATCH 073/152] README.md: update build and run instructions --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4e1c8e7..466da65 100644 --- a/README.md +++ b/README.md @@ -98,28 +98,29 @@ yarn test ### build -requires `solc` to be in `$PATH`. [installation instructions](https://solidity.readthedocs.io/en/develop/installing-solidity.html) +requires `rust` and `cargo`: [installation instructions.](https://www.rust-lang.org/en-US/install.html) + +requires `solc` to be in `$PATH`: [installation instructions.](https://solidity.readthedocs.io/en/develop/installing-solidity.html) + +assuming you've cloned the bridge (`git clone git@github.com:paritytech/parity-bridge.git`) +and are in the project directory (`cd parity-bridge`) run: ``` cargo build -p bridge-cli --release ``` -### cli options +to install copy `../target/release/bridge` into a folder that's in your `$PATH`. + +### run ``` -Ethereum-Kovan bridge. - Copyright 2017 Parity Technologies (UK) Limited - -Usage: - bridge --config --database - bridge -h | --help - -Options: - -h, --help Display help message and exit. +bridge --config config.toml --database db.toml ``` - `--config` - location of the configuration file. configuration file must exist -- `--database` - location of the database file. if there is no file at specified location, new bridge contracts will be deployed and new database will be created +- `--database` - location of the database file. + if there is no file at specified location, new bridge contracts will be deployed + and new database will be created ### configuration [file example](./examples/config.toml) From d94e5cb322b6d3978186aab46d7a57f037064cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 29 Jan 2018 09:28:07 +0100 Subject: [PATCH 074/152] README.md: wording --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 466da65..9f8cae1 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,7 @@ the bridge is an [ERC20 token](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) contract that is backed by ether on **another** ethereum blockchain. -given a bridge between two chains -users can freely convert any amount of ether +users can convert ether one one chain into the same amount of ERC20 tokens on the other and back. the bridge securely relays these conversions. From dc999eaa9aa0f3b67e2e2ae50e02b4348646cb6c Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Tue, 30 Jan 2018 11:36:22 +0000 Subject: [PATCH 075/152] Add Gitter badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9f8cae1..7b24c9b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # bridge +[![Join the chat at https://gitter.im/paritytech/parity-bridge](https://badges.gitter.im/paritytech/parity-bridge.svg)](https://gitter.im/paritytech/parity-bridge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + [![Build Status][travis-image]][travis-url] [![Solidity Coverage Status][coveralls-image]][coveralls-url] (contracts only) From 2acd8b0697931617a5f931ae885cbc537efba614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wagner?= Date: Tue, 30 Jan 2018 13:29:41 +0100 Subject: [PATCH 076/152] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9f8cae1..7fc793f 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,15 @@ the bridge is an [ERC20 token](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) -contract that is backed by ether on **another** ethereum blockchain. +contract on one ethereum-based blockchain that is backed by ether on **another** ethereum-based blockchain. users can convert ether -one one chain into the same amount of ERC20 tokens on the other and back. +on one chain into the same amount of ERC20 tokens on the other and back. the bridge securely relays these conversions. -**the bridge can solve scaling issues:** +**the bridge can mitigate scaling issues:** by deploying a [proof-of-authority](https://paritytech.github.io/wiki/Proof-of-Authority-Chains.html) -network and bridging it to mainnet users can convert their mainnet ether +network and bridging it to the Ethereum Foundation network ('mainnet') users can convert their mainnet ether into ERC20 tokens on the PoA chain and there transfer them with much lower transaction fees, faster block times and unaffected by mainnet congestion. From 90068a8ae45304be76b50e4ae590a46f4d026686 Mon Sep 17 00:00:00 2001 From: Griff Green Date: Tue, 30 Jan 2018 20:45:32 +0700 Subject: [PATCH 077/152] Fixed some typos and made a section more coherent --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 7fc793f..d67534d 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ users can always call `ForeignBridge.transferHomeViaRelay(homeRecipientAddress, `foreign` is assumed to use PoA (proof of authority) consensus. relays between the chains happen in a byzantine fault tolerant way using the authorities of `foreign`. -### highlevel explanation of home ether -> foreign ERC20 relay +### high level explanation of home ether -> foreign ERC20 relay `sender` deposits `value` into `HomeBridge`. the `HomeBridge` fallback function emits `Deposit(sender, value)`. @@ -62,16 +62,16 @@ once there are `ForeignBridge.requiredSignatures` such transactions with identical arguments and from distinct authorities then `ForeignBridge.balanceOf(sender)` is increased by `value`. -### highlevel explanation of foreign ERC20 -> home ether relay +### high level explanation of foreign ERC20 -> home ether relay `sender` executes `ForeignBridge.transferHomeViaRelay(recipient, value)` which checks and reduces `ForeignBridge.balances(sender)` by `value` and emits `ForeignBridge.Withdraw(recipient, value)`. -for each `ForeignBridge.Withdraw` every bridge authority creates a message containg -`value`, `recipient` and the `transactionHash` of the transaction containing the `ForeignBridge.Withdraw` event, -signs the message and executes `ForeignBridge.submitSignature(signature, message)`. -this collection of signatures on `foreign` is necessary because transactions are free -for authorities on `foreign`, since they are the authorities of `foreign`, but not free on `home`. +for every `ForeignBridge.Withdraw`, every bridge authority creates a message containing +`value`, `recipient` and the `transactionHash` of the transaction referenced by the `ForeignBridge.Withdraw` event; +signs that message and executes `ForeignBridge.submitSignature(signature, message)`. +this collection of signatures is on `foreign` because transactions are free for the authorities on `foreign`, +but not free on `home`. once `ForeignBridge.requiredSignatures` signatures by distinct authorities are collected a `ForeignBridge.CollectedSignatures(authorityThatSubmittedLastSignature, messageHash)` event is emitted. @@ -144,9 +144,9 @@ bin = "contracts/KovanBridge.bin" [authorities] accounts = [ - "0x006e27b6a72e1f34c626762f3c4761547aff1421", - "0x006e27b6a72e1f34c626762f3c4761547aff1421", - "0x006e27b6a72e1f34c626762f3c4761547aff1421" + "0x006e27b6a72e1f34c626762f3c4761547aff1421", + "0x006e27b6a72e1f34c626762f3c4761547aff1421", + "0x006e27b6a72e1f34c626762f3c4761547aff1421" ] required_signatures = 2 @@ -219,7 +219,7 @@ checked_withdraw_confirm = 121 - `foreign_deploy` - block number at which foreign contract has been deployed - `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 authirty has confirmed withdraw +- `checked_withdraw_confirm` - number of the last block for which an authority has confirmed withdraw ### example run @@ -253,8 +253,8 @@ that shuts down an attack that enabled exhaustion of authorities funds on `home` read on for a more thorough explanation. parity-bridge connects a value-bearing ethereum blockchain `home` -(initally the ethereum foundation chain) -to a non-value-bearing PoA ethereum blockchain `foreign` (initally the kovan testnet). +(initially the ethereum foundation chain) +to a non-value-bearing PoA ethereum blockchain `foreign` (initially the kovan testnet). value-bearing means that the ether on that chain has usable value in the sense that in order to obtain it one has to either mine it (trade in electricity) From 88a17e3d71f32bc8dcf976e3d4c6e8f8548e240a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wagner?= Date: Wed, 31 Jan 2018 17:18:44 +0100 Subject: [PATCH 078/152] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f63be71..ae5b626 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ the system that will eventually connect ethereum and other non-parachains to ### next steps -1. deploy to bridge **ethereum** and **kovan** with the kovan authorities being the fixed set of bridge authorities +1. deploy to bridge **ethereum** and **kovan** (bridge authorities TBD) 2. make the bridge work with contract-based dynamic validator sets 3. after kovan hardfork 2: deploy to kovan again with dynamic validator set From cc2c3fea9b720ee422dbe337a3595c03540ff464 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 6 Feb 2018 22:57:06 +0100 Subject: [PATCH 079/152] bump ethabi and ethereum-types to latest versions --- Cargo.lock | 90 ++++++++++++++++----------- bridge/Cargo.toml | 2 +- bridge/src/bridge/deploy.rs | 8 +-- bridge/src/bridge/deposit_relay.rs | 2 +- bridge/src/bridge/withdraw_confirm.rs | 8 +-- bridge/src/bridge/withdraw_relay.rs | 9 ++- bridge/src/util.rs | 2 +- integration-tests/Cargo.toml | 2 +- 8 files changed, 68 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26ca6eb..46aab90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,15 +1,3 @@ -[root] -name = "tests" -version = "0.1.0" -dependencies = [ - "bridge 0.1.0", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", -] - [[package]] name = "aho-corasick" version = "0.5.3" @@ -75,9 +63,9 @@ name = "bridge" version = "0.1.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -188,10 +176,11 @@ dependencies = [ [[package]] name = "ethabi" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -201,15 +190,15 @@ dependencies = [ [[package]] name = "ethabi-contract" -version = "5.0.0" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ethabi-derive" -version = "5.0.0" +version = "5.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ethabi 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -217,30 +206,42 @@ dependencies = [ [[package]] name = "ethbloom" -version = "0.3.0" -source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)", + "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethereum-types" -version = "0.1.4" -source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ethbloom 0.3.0 (git+https://github.com/paritytech/primitives.git)", - "fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)", + "ethbloom 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethereum-types-serialize" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fixed-hash" -version = "0.1.1" -source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -325,7 +326,7 @@ name = "integration-tests" version = "0.1.0" dependencies = [ "bridge 0.1.0", - "ethereum-types 0.1.4 (git+https://github.com/paritytech/primitives.git)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -757,6 +758,18 @@ dependencies = [ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tests" +version = "0.1.0" +dependencies = [ + "bridge 0.1.0", + "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", +] + [[package]] name = "thread-id" version = "2.0.0" @@ -884,7 +897,7 @@ dependencies = [ [[package]] name = "uint" version = "0.1.0" -source = "git+https://github.com/paritytech/primitives.git#2a737bb75078d252837277bd642fa0bc805ba5ed" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1017,12 +1030,13 @@ dependencies = [ "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c49de42ee3e3e4734bd847d015e7c55b7855ab978800795c4f032772573d077" -"checksum ethabi 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "14ba36002cd4f12531f868f285e22e9dd81bbb2cc564663e5a4202e6290e07f9" -"checksum ethabi-contract 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "875ee2bf76d6dbfae9682457c41b1debc994812419132815263b215262f6940e" -"checksum ethabi-derive 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb6482d54b628bd883b0fd9007a3f0d85e2df372f0f1bc33bab7417cad1ed4c4" -"checksum ethbloom 0.3.0 (git+https://github.com/paritytech/primitives.git)" = "" -"checksum ethereum-types 0.1.4 (git+https://github.com/paritytech/primitives.git)" = "" -"checksum fixed-hash 0.1.1 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8385a48c8ed984778dcca27efc0de162a191a14ed733a41a07d9b0cfaa999e" +"checksum ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2263c24359e827348ac99aa1f2e28ba5bab0d6c0b83941fa252de8a9e9c073" +"checksum ethabi-derive 5.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9a357d3f4f249408af8d8b241b53b39a419328606825d3bb3fef841bb9d8ba13" +"checksum ethbloom 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f240172b976e2421fa5485e45cd45287bbdb56d742aa3a1d77005c49071a8518" +"checksum ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bad6fb0e4ab648f4d8d8314c340c47f9e805b085b78be1b8da4676534cb419df" +"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" +"checksum fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21c520ebc46522d519aec9cba2b7115d49cea707d771b772c46bec61aa0daeb8" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" @@ -1100,7 +1114,7 @@ dependencies = [ "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" "checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum uint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91ed1e25ded4e37e0967b1f12d5f910b32f979768d4f48e2f6ca7b6e7130b44e" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index 55c1323..a9e0369 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -13,7 +13,7 @@ tokio-timer = "0.1.2" toml = "0.4.2" web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } error-chain = "0.11.0-rc.2" -ethabi = "5.0" +ethabi = "5.1" ethabi-derive = "5.0" ethabi-contract = "5.0" rustc-hex = "1.0" diff --git a/bridge/src/bridge/deploy.rs b/bridge/src/bridge/deploy.rs index 840b9b5..e12597c 100644 --- a/bridge/src/bridge/deploy.rs +++ b/bridge/src/bridge/deploy.rs @@ -6,7 +6,7 @@ use web3::types::{TransactionRequest}; use app::App; use database::Database; use error::{Error, ErrorKind}; -use {api, ethabi}; +use api; pub enum Deployed { /// No existing database found. Deployed new contracts. @@ -44,13 +44,13 @@ impl Future for Deploy { Err(ErrorKind::MissingFile(_)) => { let main_data = self.app.home_bridge.constructor( self.app.config.home.contract.bin.clone().0, - ethabi::util::pad_u32(self.app.config.authorities.required_signatures), + self.app.config.authorities.required_signatures, self.app.config.authorities.accounts.iter().map(|a| a.0.clone()).collect::>(), - ethabi::util::pad_u32(self.app.config.estimated_gas_cost_of_withdraw) + self.app.config.estimated_gas_cost_of_withdraw ); let test_data = self.app.foreign_bridge.constructor( self.app.config.foreign.contract.bin.clone().0, - ethabi::util::pad_u32(self.app.config.authorities.required_signatures), + self.app.config.authorities.required_signatures, self.app.config.authorities.accounts.iter().map(|a| a.0.clone()).collect::>() ); diff --git a/bridge/src/bridge/deposit_relay.rs b/bridge/src/bridge/deposit_relay.rs index ae25695..03918e0 100644 --- a/bridge/src/bridge/deposit_relay.rs +++ b/bridge/src/bridge/deposit_relay.rs @@ -19,7 +19,7 @@ fn deposits_filter(home: &home::HomeBridge, address: Address) -> FilterBuilder { fn deposit_relay_payload(home: &home::HomeBridge, foreign: &foreign::ForeignBridge, log: Log) -> Result { let raw_log = RawLog { - topics: log.topics.into_iter().map(|t| t.0).collect(), + topics: log.topics.into_iter().map(|t| t.0.into()).collect(), data: log.data.0, }; let deposit_log = home.events().deposit().parse_log(raw_log)?; diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index f5aac9f..011525d 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -3,7 +3,7 @@ use std::ops; use futures::{Future, Stream, Poll}; use futures::future::{JoinAll, join_all}; use tokio_timer::Timeout; -use ethabi::RawLog; +use ethabi::{RawLog, Hash}; use web3::Transport; use web3::types::{H256, H520, Address, TransactionRequest, Log, Bytes, FilterBuilder}; use api::{self, LogStream, ApiCall}; @@ -20,14 +20,14 @@ fn withdraws_filter(foreign: &foreign::ForeignBridge, address: Address) -> Filte fn withdraw_confirm_sign_payload(foreign: &foreign::ForeignBridge, log: Log) -> Result { let raw_log = RawLog { - topics: log.topics.into_iter().map(|t| t.0).collect(), + topics: log.topics.into_iter().map(|t| t.0.into()).collect(), data: log.data.0, }; let withdraw_log = foreign.events().withdraw().parse_log(raw_log)?; let hash = log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); let mut result = vec![0u8; 84]; result[0..20].copy_from_slice(&withdraw_log.recipient); - result[20..52].copy_from_slice(&withdraw_log.value); + result[20..52].copy_from_slice(&Hash::from(withdraw_log.value)); result[52..84].copy_from_slice(&hash); Ok(result.into()) } @@ -126,7 +126,7 @@ impl Stream for WithdrawConfirm { .zip(signatures.into_iter()) .map(|(withdraw_message, signature)| withdraw_submit_signature_payload(&app.foreign_bridge, withdraw_message, signature)) .map(|payload| TransactionRequest { - from: app.config.foreign.account.clone(), + from: app.config.foreign.account, to: Some(foreign_contract.clone()), gas: Some(app.config.txs.withdraw_confirm.gas.into()), gas_price: Some(app.config.txs.withdraw_confirm.gas_price.into()), diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 4bd269f..ee0c327 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -33,18 +33,17 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 // convert web3::Log to ethabi::RawLog since ethabi events can // only be parsed from the latter let raw_log = RawLog { - topics: log.topics.into_iter().map(|t| t.0).collect(), + topics: log.topics.into_iter().map(|t| t.0.into()).collect(), data: log.data.0, }; let collected_signatures = foreign.events().collected_signatures().parse_log(raw_log)?; - if collected_signatures.authority_responsible_for_relay != my_address.0 { + if collected_signatures.authority_responsible_for_relay != my_address.0.into() { info!("bridge not responsible for relaying transaction to home. tx hash: {}", log.transaction_hash.unwrap()); // this authority is not responsible for relaying this transaction. // someone else will relay this transaction to home. return Ok(None); } let signature_payloads = (0..required_signatures).into_iter() - .map(|index| ethabi::util::pad_u32(index)) .map(|index| foreign.functions().signature().input(collected_signatures.message_hash, index)) .map(Into::into) .collect(); @@ -117,7 +116,7 @@ pub fn create_withdraw_relay(app: Arc>, init: &Data request_timeout: app.config.foreign.request_timeout, poll_interval: app.config.foreign.poll_interval, confirmations: app.config.foreign.required_confirmations, - filter: collected_signatures_filter(&app.foreign_bridge, init.foreign_contract_address.clone()), + filter: collected_signatures_filter(&app.foreign_bridge, init.foreign_contract_address), }; WithdrawRelay { @@ -273,7 +272,7 @@ impl Stream for WithdrawRelay { }) .map(|((message, signatures), _)| withdraw_relay_payload(&app.home_bridge, &signatures, message)) .map(|payload| TransactionRequest { - from: app.config.home.account.clone(), + from: app.config.home.account, to: Some(home_contract.clone()), gas: Some(app.config.txs.withdraw_relay.gas.into()), gas_price: Some(app.config.txs.withdraw_relay.gas_price.into()), diff --git a/bridge/src/util.rs b/bridge/src/util.rs index 0004a7b..5ad7738 100644 --- a/bridge/src/util.rs +++ b/bridge/src/util.rs @@ -7,7 +7,7 @@ fn web3_topic(topic: ethabi::Topic) -> Option> { if t.is_empty() { None } else { - Some(t.into_iter().map(|x| H256(x)).collect()) + Some(t.into_iter().map(|x| H256(x.0)).collect()) } } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 172b297..0ff8fbb 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -11,5 +11,5 @@ web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } serde_json = "1.0" pretty_assertions = "0.2.1" tempdir = "0.3.5" -ethereum-types = { git = "https://github.com/paritytech/primitives.git" } +ethereum-types = "0.2" tokio-core = "0.1.8" From 5e90f850fdfb815fe69cd1fd4beb3ff46e143424 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 7 Feb 2018 14:50:49 +0100 Subject: [PATCH 080/152] updated web3 to latest version and resolved build issues --- Cargo.lock | 69 +++++++++------------------ bridge/src/api.rs | 6 +-- bridge/src/bridge/deposit_relay.rs | 4 +- bridge/src/bridge/withdraw_confirm.rs | 6 +-- bridge/src/bridge/withdraw_relay.rs | 12 ++--- bridge/src/config.rs | 26 +++++----- bridge/src/database.rs | 4 +- integration-tests/Cargo.toml | 2 +- tests/Cargo.toml | 2 +- tests/src/lib.rs | 2 + tests/tests/deposit_relay.rs | 56 +++++++++++----------- tests/tests/log_stream.rs | 8 ++-- tests/tests/withdraw_confirm.rs | 52 ++++++++++---------- tests/tests/withdraw_relay.rs | 52 ++++++++++---------- 14 files changed, 139 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46aab90..e707e1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,11 +16,10 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.3.25" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -76,7 +75,7 @@ dependencies = [ "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", + "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] [[package]] @@ -161,19 +160,6 @@ dependencies = [ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ethabi" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ethabi" version = "5.1.0" @@ -328,12 +314,12 @@ dependencies = [ "bridge 0.1.0", "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", + "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] [[package]] @@ -352,7 +338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "7.1.1" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -499,11 +485,6 @@ dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "odds" -version = "0.2.26" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.3.3" @@ -514,7 +495,7 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.4.8" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -626,11 +607,6 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc_version" version = "0.2.1" @@ -764,10 +740,10 @@ version = "0.1.0" dependencies = [ "bridge 0.1.0", "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", + "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] [[package]] @@ -953,17 +929,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "web3" -version = "0.0.5" -source = "git+https://github.com/tomusdrw/rust-web3?branch=bridge#0205d57b5e9734049cdbd570c431c3ad35b106fb" +version = "0.2.0" +source = "git+https://github.com/tomusdrw/rust-web3?branch=bridge#aad14c09b38453933c9059b601c77e8763618674" dependencies = [ - "arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.14 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1014,7 +992,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" -"checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" +"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" @@ -1029,7 +1007,6 @@ dependencies = [ "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum ethabi 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c49de42ee3e3e4734bd847d015e7c55b7855ab978800795c4f032772573d077" "checksum ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8385a48c8ed984778dcca27efc0de162a191a14ed733a41a07d9b0cfaa999e" "checksum ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2263c24359e827348ac99aa1f2e28ba5bab0d6c0b83941fa252de8a9e9c073" "checksum ethabi-derive 5.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9a357d3f4f249408af8d8b241b53b39a419328606825d3bb3fef841bb9d8ba13" @@ -1047,7 +1024,7 @@ dependencies = [ "checksum hyper 0.11.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f57f74deb81fb91b776012ed7605e96b1ffb88c4fd5c031ce5c90534b604a6e0" "checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" -"checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515" +"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" @@ -1065,9 +1042,8 @@ dependencies = [ "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" +"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" "checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d510007841e87c7a6d829a36f7f0acb72aef12e38cc89073fe39810c1d976ac" @@ -1082,7 +1058,6 @@ dependencies = [ "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" @@ -1123,7 +1098,7 @@ dependencies = [ "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum web3 0.0.5 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)" = "" +"checksum web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)" = "" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/bridge/src/api.rs b/bridge/src/api.rs index c91d039..4699ef5 100644 --- a/bridge/src/api.rs +++ b/bridge/src/api.rs @@ -88,7 +88,7 @@ pub struct LogStreamInit { pub filter: FilterBuilder, pub request_timeout: Duration, pub poll_interval: Duration, - pub confirmations: u64, + pub confirmations: usize, } /// Contains all logs matching `LogStream` filter in inclusive range `[from, to]`. @@ -137,7 +137,7 @@ pub struct LogStream { state: LogStreamState, after: u64, filter: FilterBuilder, - confirmations: u64, + confirmations: usize, request_timeout: Duration, } @@ -154,7 +154,7 @@ impl Stream for LogStream { }, LogStreamState::FetchBlockNumber(ref mut future) => { let last_block = try_ready!(future.poll()).low_u64(); - let last_confirmed_block = last_block.saturating_sub(self.confirmations); + let last_confirmed_block = last_block.saturating_sub(self.confirmations as u64); if last_confirmed_block > self.after { let from = self.after + 1; let filter = self.filter.clone() diff --git a/bridge/src/bridge/deposit_relay.rs b/bridge/src/bridge/deposit_relay.rs index 03918e0..33dc41a 100644 --- a/bridge/src/bridge/deposit_relay.rs +++ b/bridge/src/bridge/deposit_relay.rs @@ -132,8 +132,8 @@ mod tests { let data = "000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0".from_hex().unwrap(); let log = Log { data: data.into(), - topics: vec!["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c".parse().unwrap()], - transaction_hash: Some("0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".parse().unwrap()), + topics: vec!["e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c".into()], + transaction_hash: Some("884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()), ..Default::default() }; diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 011525d..0e4399a 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -181,8 +181,8 @@ mod tests { let data = "000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0".from_hex().unwrap(); let log = Log { data: data.into(), - topics: vec!["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".parse().unwrap()], - transaction_hash: Some("0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".parse().unwrap()), + topics: vec!["884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()], + transaction_hash: Some("884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()), ..Default::default() }; @@ -196,7 +196,7 @@ mod tests { let foreign = foreign::ForeignBridge::default(); let message: Bytes = "aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".from_hex().unwrap().into(); - let signature = "0x8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc".parse().unwrap(); + let signature = "8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc".into(); let payload = withdraw_submit_signature_payload(&foreign, message, signature); let expected: Bytes = "630cea8e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000418697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364000000000000000000000000".from_hex().unwrap().into(); diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index ee0c327..d860f87 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -321,14 +321,14 @@ mod tests { #[test] fn test_signatures_payload() { let foreign = foreign::ForeignBridge::default(); - let my_address = "0xaff3454fce5edbc8cca8697c15331677e6ebcccc".parse().unwrap(); + let my_address = "aff3454fce5edbc8cca8697c15331677e6ebcccc".into(); let data = "000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0".from_hex().unwrap(); let log = Log { data: data.into(), - topics: vec!["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c".parse().unwrap()], - transaction_hash: Some("0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".parse().unwrap()), + topics: vec!["eb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c".into()], + transaction_hash: Some("884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()), ..Default::default() }; @@ -345,14 +345,14 @@ mod tests { #[test] fn test_signatures_payload_not_ours() { let foreign = foreign::ForeignBridge::default(); - let my_address = "0xaff3454fce5edbc8cca8697c15331677e6ebcccd".parse().unwrap(); + let my_address = "aff3454fce5edbc8cca8697c15331677e6ebcccd".into(); let data = "000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0".from_hex().unwrap(); let log = Log { data: data.into(), - topics: vec!["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c".parse().unwrap()], - transaction_hash: Some("0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".parse().unwrap()), + topics: vec!["eb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c".into()], + transaction_hash: Some("884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()), ..Default::default() }; diff --git a/bridge/src/config.rs b/bridge/src/config.rs index eeec8b1..712cde4 100644 --- a/bridge/src/config.rs +++ b/bridge/src/config.rs @@ -8,7 +8,7 @@ use error::{ResultExt, Error}; use {toml}; const DEFAULT_POLL_INTERVAL: u64 = 1; -const DEFAULT_CONFIRMATIONS: u64 = 12; +const DEFAULT_CONFIRMATIONS: usize = 12; const DEFAULT_TIMEOUT: u64 = 5; /// Application config. @@ -57,7 +57,7 @@ pub struct Node { pub ipc: PathBuf, pub request_timeout: Duration, pub poll_interval: Duration, - pub required_confirmations: u64, + pub required_confirmations: usize, } impl Node { @@ -154,7 +154,7 @@ mod load { pub ipc: PathBuf, pub request_timeout: Option, pub poll_interval: Option, - pub required_confirmations: Option, + pub required_confirmations: Option, } #[derive(Deserialize)] @@ -230,7 +230,7 @@ home_deploy = { gas = 20 } let mut expected = Config { txs: Transactions::default(), home: Node { - account: "0x1B68Cb0B50181FC4006Ce572cF346e596E51818b".parse().unwrap(), + account: "1B68Cb0B50181FC4006Ce572cF346e596E51818b".into(), ipc: "/home.ipc".into(), contract: ContractConfig { bin: include_str!("../../compiled_contracts/HomeBridge.bin").from_hex().unwrap().into(), @@ -240,7 +240,7 @@ home_deploy = { gas = 20 } required_confirmations: 100, }, foreign: Node { - account: "0x0000000000000000000000000000000000000001".parse().unwrap(), + account: "0000000000000000000000000000000000000001".into(), contract: ContractConfig { bin: include_str!("../../compiled_contracts/ForeignBridge.bin").from_hex().unwrap().into(), }, @@ -251,9 +251,9 @@ home_deploy = { gas = 20 } }, authorities: Authorities { accounts: vec![ - "0x0000000000000000000000000000000000000001".parse().unwrap(), - "0x0000000000000000000000000000000000000002".parse().unwrap(), - "0x0000000000000000000000000000000000000003".parse().unwrap(), + "0000000000000000000000000000000000000001".into(), + "0000000000000000000000000000000000000002".into(), + "0000000000000000000000000000000000000003".into(), ], required_signatures: 2, }, @@ -299,7 +299,7 @@ required_signatures = 2 let expected = Config { txs: Transactions::default(), home: Node { - account: "0x1B68Cb0B50181FC4006Ce572cF346e596E51818b".parse().unwrap(), + account: "1B68Cb0B50181FC4006Ce572cF346e596E51818b".into(), ipc: "".into(), contract: ContractConfig { bin: include_str!("../../compiled_contracts/HomeBridge.bin").from_hex().unwrap().into(), @@ -309,7 +309,7 @@ required_signatures = 2 required_confirmations: 12, }, foreign: Node { - account: "0x0000000000000000000000000000000000000001".parse().unwrap(), + account: "0000000000000000000000000000000000000001".into(), ipc: "".into(), contract: ContractConfig { bin: include_str!("../../compiled_contracts/ForeignBridge.bin").from_hex().unwrap().into(), @@ -320,9 +320,9 @@ required_signatures = 2 }, authorities: Authorities { accounts: vec![ - "0x0000000000000000000000000000000000000001".parse().unwrap(), - "0x0000000000000000000000000000000000000002".parse().unwrap(), - "0x0000000000000000000000000000000000000003".parse().unwrap(), + "0000000000000000000000000000000000000001".into(), + "0000000000000000000000000000000000000002".into(), + "0000000000000000000000000000000000000003".into(), ], required_signatures: 2, }, diff --git a/bridge/src/database.rs b/bridge/src/database.rs index 836e03d..a53e832 100644 --- a/bridge/src/database.rs +++ b/bridge/src/database.rs @@ -74,8 +74,8 @@ checked_withdraw_confirm = 121 "#; let expected = Database { - home_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7".parse().unwrap(), - foreign_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8".parse().unwrap(), + home_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db7".into(), + foreign_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db8".into(), home_deploy: 100, foreign_deploy: 101, checked_deposit_relay: 120, diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 0ff8fbb..b07b3fb 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -6,7 +6,7 @@ authors = ["snd "] [dependencies] bridge = { path = "../bridge" } futures = "0.1" -jsonrpc-core = "7.0" +jsonrpc-core = "8.0" web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } serde_json = "1.0" pretty_assertions = "0.2.1" diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 8b754c3..a77ddb8 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -6,7 +6,7 @@ authors = ["debris "] [dependencies] bridge = { path = "../bridge" } futures = "0.1" -jsonrpc-core = "7.0" +jsonrpc-core = "8.0" web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } serde_json = "1.0" pretty_assertions = "0.2.1" diff --git a/tests/src/lib.rs b/tests/src/lib.rs index edf3e0c..6e5bcfc 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -9,6 +9,7 @@ extern crate pretty_assertions; use std::cell::Cell; use web3::Transport; +#[derive(Debug, Clone)] pub struct MockedRequest { pub method: String, pub params: Vec, @@ -23,6 +24,7 @@ impl From<(&'static str, &'static str)> for MockedRequest { } } +#[derive(Debug, Clone)] pub struct MockedTransport { pub requests: Cell, pub expected_requests: Vec, diff --git a/tests/tests/deposit_relay.rs b/tests/tests/deposit_relay.rs index cba6bf3..d7aa9ca 100644 --- a/tests/tests/deposit_relay.rs +++ b/tests/tests/deposit_relay.rs @@ -9,15 +9,15 @@ test_app_stream! { name => deposit_relay_basic, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -47,15 +47,15 @@ test_app_stream! { ..Default::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -89,15 +89,15 @@ test_app_stream! { ..Default::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions { @@ -127,20 +127,20 @@ test_app_stream! { test_app_stream! { name => deposit_relay_contract_address, database => Database { - home_contract_address: "0x0000000000000000000000000000000000000cc1".parse().unwrap(), - foreign_contract_address: "0x0000000000000000000000000000000000000dd1".parse().unwrap(), + home_contract_address: "0000000000000000000000000000000000000cc1".into(), + foreign_contract_address: "0000000000000000000000000000000000000dd1".into(), ..Default::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -164,20 +164,20 @@ test_app_stream! { test_app_stream! { name => deposit_relay_accounts, database => Database { - home_contract_address: "0x0000000000000000000000000000000000000cc1".parse().unwrap(), - foreign_contract_address: "0x0000000000000000000000000000000000000dd1".parse().unwrap(), + home_contract_address: "0000000000000000000000000000000000000cc1".into(), + foreign_contract_address: "0000000000000000000000000000000000000dd1".into(), ..Default::default() }, home => - account => "0x00000000000000000000000000000000000000ff", + account => "00000000000000000000000000000000000000ff", confirmations => 12; foreign => - account => "0x00000000000000000000000000000000000000ee", + account => "00000000000000000000000000000000000000ee", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -202,15 +202,15 @@ test_app_stream! { name => deposit_relay_multiple_logs, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), diff --git a/tests/tests/log_stream.rs b/tests/tests/log_stream.rs index ac8b7f2..1df919c 100644 --- a/tests/tests/log_stream.rs +++ b/tests/tests/log_stream.rs @@ -259,7 +259,7 @@ test_transport_stream! { from: 0xb, to: 0x1006, logs: vec![Log { - address: "0x0000000000000000000000000000000000000001".parse().unwrap(), + address: "0000000000000000000000000000000000000001".into(), topics: vec![], data: vec![0x10].into(), log_type: "".into(), @@ -292,7 +292,7 @@ test_transport_stream! { from: 0xb, to: 0x1006, logs: vec![Log { - address: "0x0000000000000000000000000000000000000001".parse().unwrap(), + address: "0000000000000000000000000000000000000001".into(), topics: vec![], data: vec![0x10].into(), log_type: "".into(), @@ -306,13 +306,13 @@ test_transport_stream! { from: 0x1008, to: 0x1008, logs: vec![Log { - address: "0x0000000000000000000000000000000000000002".parse().unwrap(), + address: "0000000000000000000000000000000000000002".into(), topics: vec![], data: vec![0x20].into(), log_type: "".into(), ..Default::default() }, Log { - address: "0x0000000000000000000000000000000000000002".parse().unwrap(), + address: "0000000000000000000000000000000000000002".into(), topics: vec![], data: vec![0x30].into(), log_type: "".into(), diff --git a/tests/tests/withdraw_confirm.rs b/tests/tests/withdraw_confirm.rs index eeaf57f..d8a3f9f 100644 --- a/tests/tests/withdraw_confirm.rs +++ b/tests/tests/withdraw_confirm.rs @@ -9,15 +9,15 @@ test_app_stream! { name => withdraw_confirm_basic, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -47,15 +47,15 @@ test_app_stream! { ..Database::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 1; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -85,20 +85,20 @@ test_app_stream! { name => withdraw_confirm_contract_address, database => Database { checked_withdraw_confirm: 0x00F5, - home_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7".parse().unwrap(), - foreign_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8".parse().unwrap(), + home_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db7".into(), + foreign_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db8".into(), ..Database::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -128,20 +128,20 @@ test_app_stream! { name => withdraw_confirm_payload_gas, database => Database { checked_withdraw_confirm: 0x00F5, - home_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7".parse().unwrap(), - foreign_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8".parse().unwrap(), + home_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db7".into(), + foreign_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db8".into(), ..Database::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x00000000000000000000000000000000000000F1", - "0x00000000000000000000000000000000000000F2", + "00000000000000000000000000000000000000F1", + "00000000000000000000000000000000000000F2", ], signatures => 1; txs => Transactions { @@ -182,20 +182,20 @@ test_app_stream! { test_app_stream! { name => withdraw_confirm_payload_multiple, database => Database { - home_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7".parse().unwrap(), - foreign_contract_address: "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8".parse().unwrap(), + home_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db7".into(), + foreign_contract_address: "49edf201c1e139282643d5e7c6fb0c7219ad1db8".into(), ..Database::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x00000000000000000000000000000000000000F1", - "0x00000000000000000000000000000000000000F2", + "00000000000000000000000000000000000000F1", + "00000000000000000000000000000000000000F2", ], signatures => 1; txs => Transactions { diff --git a/tests/tests/withdraw_relay.rs b/tests/tests/withdraw_relay.rs index 63ab88b..084ea7b 100644 --- a/tests/tests/withdraw_relay.rs +++ b/tests/tests/withdraw_relay.rs @@ -12,15 +12,15 @@ test_app_stream! { name => withdraw_relay_no_log_no_relay, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -51,15 +51,15 @@ test_app_stream! { name => withdraw_relay_single_log_authority_not_responsible_no_relay, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 1; txs => Transactions::default(), @@ -83,15 +83,15 @@ test_app_stream! { name => withdraw_relay_single_log_sufficient_value_relay, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0xaff3454fce5edbc8cca8697c15331677e6ebcccc", + account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 2; txs => Transactions::default(), @@ -136,15 +136,15 @@ test_app_stream! { name => withdraw_relay_single_log_insufficient_value_no_relay, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0xaff3454fce5edbc8cca8697c15331677e6ebcccc", + account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 2; txs => Transactions::default(), @@ -185,15 +185,15 @@ test_app_stream! { name => withdraw_relay_explicit_gas, database => Database::default(), home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0xaff3454fce5edbc8cca8697c15331677e6ebcccc", + account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 2; txs => Transactions { @@ -242,20 +242,20 @@ test_app_stream! { test_app_stream! { name => withdraw_relay_single_explicit_contract_addresses, database => Database { - home_contract_address: "0x00000000000000000000000000000000000000dd".parse().unwrap(), - foreign_contract_address: "0x00000000000000000000000000000000000000ee".parse().unwrap(), + home_contract_address: "00000000000000000000000000000000000000dd".into(), + foreign_contract_address: "00000000000000000000000000000000000000ee".into(), ..Default::default() }, home => - account => "0x0000000000000000000000000000000000000001", + account => "0000000000000000000000000000000000000001", confirmations => 12; foreign => - account => "0xaff3454fce5edbc8cca8697c15331677e6ebcccc", + account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", confirmations => 12; authorities => accounts => [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000002", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", ], signatures => 2; txs => Transactions::default(), From f0dcb70cf387da7656f89555e82fd7edb78d48ab Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 7 Feb 2018 14:58:50 +0100 Subject: [PATCH 081/152] remove redundant conversions between types --- bridge/src/bridge/deploy.rs | 4 ++-- bridge/src/bridge/deposit_relay.rs | 8 ++++---- bridge/src/bridge/withdraw_confirm.rs | 10 +++++----- bridge/src/bridge/withdraw_relay.rs | 6 +++--- bridge/src/util.rs | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bridge/src/bridge/deploy.rs b/bridge/src/bridge/deploy.rs index e12597c..d69a78b 100644 --- a/bridge/src/bridge/deploy.rs +++ b/bridge/src/bridge/deploy.rs @@ -45,13 +45,13 @@ impl Future for 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.iter().map(|a| a.0.clone()).collect::>(), + 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.iter().map(|a| a.0.clone()).collect::>() + self.app.config.authorities.accounts.clone(), ); let main_tx_request = TransactionRequest { diff --git a/bridge/src/bridge/deposit_relay.rs b/bridge/src/bridge/deposit_relay.rs index 33dc41a..b2f2bf6 100644 --- a/bridge/src/bridge/deposit_relay.rs +++ b/bridge/src/bridge/deposit_relay.rs @@ -19,7 +19,7 @@ fn deposits_filter(home: &home::HomeBridge, address: Address) -> FilterBuilder { fn deposit_relay_payload(home: &home::HomeBridge, foreign: &foreign::ForeignBridge, log: Log) -> Result { let raw_log = RawLog { - topics: log.topics.into_iter().map(|t| t.0.into()).collect(), + topics: log.topics, data: log.data.0, }; let deposit_log = home.events().deposit().parse_log(raw_log)?; @@ -47,11 +47,11 @@ pub fn create_deposit_relay(app: Arc>, init: &Datab request_timeout: app.config.home.request_timeout, poll_interval: app.config.home.poll_interval, confirmations: app.config.home.required_confirmations, - filter: deposits_filter(&app.home_bridge, init.home_contract_address.clone()), + filter: deposits_filter(&app.home_bridge, init.home_contract_address), }; DepositRelay { logs: api::log_stream(app.connections.home.clone(), app.timer.clone(), logs_init), - foreign_contract: init.foreign_contract_address.clone(), + foreign_contract: init.foreign_contract_address, state: DepositRelayState::Wait, app, } @@ -80,7 +80,7 @@ impl Stream for DepositRelay { .collect::>>()? .into_iter() .map(|payload| TransactionRequest { - from: self.app.config.foreign.account.clone(), + from: self.app.config.foreign.account, to: Some(self.foreign_contract.clone()), gas: Some(self.app.config.txs.deposit_relay.gas.into()), gas_price: Some(self.app.config.txs.deposit_relay.gas_price.into()), diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 0e4399a..97c4385 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -3,7 +3,7 @@ use std::ops; use futures::{Future, Stream, Poll}; use futures::future::{JoinAll, join_all}; use tokio_timer::Timeout; -use ethabi::{RawLog, Hash}; +use ethabi::RawLog; use web3::Transport; use web3::types::{H256, H520, Address, TransactionRequest, Log, Bytes, FilterBuilder}; use api::{self, LogStream, ApiCall}; @@ -20,14 +20,14 @@ fn withdraws_filter(foreign: &foreign::ForeignBridge, address: Address) -> Filte fn withdraw_confirm_sign_payload(foreign: &foreign::ForeignBridge, log: Log) -> Result { let raw_log = RawLog { - topics: log.topics.into_iter().map(|t| t.0.into()).collect(), + topics: log.topics, data: log.data.0, }; let withdraw_log = foreign.events().withdraw().parse_log(raw_log)?; let hash = log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); let mut result = vec![0u8; 84]; result[0..20].copy_from_slice(&withdraw_log.recipient); - result[20..52].copy_from_slice(&Hash::from(withdraw_log.value)); + result[20..52].copy_from_slice(&H256::from(withdraw_log.value)); result[52..84].copy_from_slice(&hash); Ok(result.into()) } @@ -68,7 +68,7 @@ pub fn create_withdraw_confirm(app: Arc>, init: &Da WithdrawConfirm { logs: api::log_stream(app.connections.foreign.clone(), app.timer.clone(), logs_init), - foreign_contract: init.foreign_contract_address.clone(), + foreign_contract: init.foreign_contract_address, state: WithdrawConfirmState::Wait, app, } @@ -103,7 +103,7 @@ impl Stream for WithdrawConfirm { .into_iter() .map(|bytes| { self.app.timer.timeout( - api::sign(&self.app.connections.foreign, self.app.config.foreign.account.clone(), bytes), + api::sign(&self.app.connections.foreign, self.app.config.foreign.account, bytes), self.app.config.foreign.request_timeout) }) .collect::>(); diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index d860f87..27c64b6 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -121,8 +121,8 @@ pub fn create_withdraw_relay(app: Arc>, init: &Data WithdrawRelay { logs: api::log_stream(app.connections.foreign.clone(), app.timer.clone(), logs_init), - home_contract: init.home_contract_address.clone(), - foreign_contract: init.foreign_contract_address.clone(), + home_contract: init.home_contract_address, + foreign_contract: init.foreign_contract_address, state: WithdrawRelayState::Wait, app, } @@ -153,7 +153,7 @@ impl Stream for WithdrawRelay { signatures_payload( &self.app.foreign_bridge, self.app.config.authorities.required_signatures, - self.app.config.foreign.account.clone(), + self.app.config.foreign.account, log) }) .collect::>>()?; diff --git a/bridge/src/util.rs b/bridge/src/util.rs index 5ad7738..dcdb2a4 100644 --- a/bridge/src/util.rs +++ b/bridge/src/util.rs @@ -7,7 +7,7 @@ fn web3_topic(topic: ethabi::Topic) -> Option> { if t.is_empty() { None } else { - Some(t.into_iter().map(|x| H256(x.0)).collect()) + Some(t) } } From 0a02e461b9c1a6dadbe6743823e5b088c4ee8107 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 7 Feb 2018 17:23:49 +0100 Subject: [PATCH 082/152] bump dependencies --- Cargo.lock | 140 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e707e1b..05499c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,13 +65,13 @@ dependencies = [ "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -85,7 +85,7 @@ dependencies = [ "bridge 0.1.0", "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -103,7 +103,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -166,7 +166,7 @@ version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -204,7 +204,7 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -213,7 +213,7 @@ dependencies = [ "fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -229,7 +229,7 @@ name = "fixed-hash" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -251,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -259,16 +259,16 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "heapsize" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -286,19 +286,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.11.14" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -312,19 +313,19 @@ name = "integration-tests" version = "0.1.0" dependencies = [ "bridge 0.1.0", - "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] [[package]] name = "iovec" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -341,7 +342,7 @@ name = "jsonrpc-core" version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -419,12 +420,12 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -441,7 +442,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -474,7 +475,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num-traits" -version = "0.1.41" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -508,7 +517,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -533,11 +542,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -591,10 +601,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "relay" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,7 +688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -728,10 +747,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tempdir" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -739,7 +759,7 @@ name = "tests" version = "0.1.0" dependencies = [ "bridge 0.1.0", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -793,10 +813,10 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -808,7 +828,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -817,10 +837,10 @@ name = "tokio-proto" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -834,7 +854,7 @@ name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -842,7 +862,7 @@ name = "tokio-timer" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -852,11 +872,11 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -872,11 +892,11 @@ dependencies = [ [[package]] name = "uint" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -935,9 +955,9 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.14 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1011,18 +1031,18 @@ dependencies = [ "checksum ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2263c24359e827348ac99aa1f2e28ba5bab0d6c0b83941fa252de8a9e9c073" "checksum ethabi-derive 5.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9a357d3f4f249408af8d8b241b53b39a419328606825d3bb3fef841bb9d8ba13" "checksum ethbloom 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f240172b976e2421fa5485e45cd45287bbdb56d742aa3a1d77005c49071a8518" -"checksum ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bad6fb0e4ab648f4d8d8314c340c47f9e805b085b78be1b8da4676534cb419df" +"checksum ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5cff74129deda8a155b729cad1a22dc3cdd08115abd1165079c519d0cab6917a" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" "checksum fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21c520ebc46522d519aec9cba2b7115d49cea707d771b772c46bec61aa0daeb8" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" +"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54fab2624374e5137ae4df13bf32b0b269cb804df42d13a51221bbd431d1a237" +"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e0db42a2924a5d7d628685e7a8cf9a2edd628650a9d01efc3dde35d3cdd22451" "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" -"checksum hyper 0.11.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f57f74deb81fb91b776012ed7605e96b1ffb88c4fd5c031ce5c90534b604a6e0" -"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7" +"checksum hyper 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4de6edd503089841ebfa88341e1c00fb19b6bf93d820d908db15960fd31226" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -1035,12 +1055,13 @@ dependencies = [ "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" -"checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0" +"checksum mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7da01a5e23070d92d99b1ecd1cd0af36447c6fd44b0fe283c2db199fa136724f" "checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +"checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" @@ -1048,14 +1069,15 @@ dependencies = [ "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d510007841e87c7a6d829a36f7f0acb72aef12e38cc89073fe39810c1d976ac" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" -"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" +"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" +"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" @@ -1076,7 +1098,7 @@ dependencies = [ "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" -"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" +"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" @@ -1089,7 +1111,7 @@ dependencies = [ "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" "checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum uint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91ed1e25ded4e37e0967b1f12d5f910b32f979768d4f48e2f6ca7b6e7130b44e" +"checksum uint 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53a4340c35703f926ec365c6797bb4a7a10bb6b9affe29ca385c9d804401f5e3" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" From c7ef6bfd65d9e2b64284b47732e19b797a40f79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 31 Jan 2018 14:23:11 +0100 Subject: [PATCH 083/152] bridge.sol: improve docstring of withdraw --- contracts/bridge.sol | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index bb743ba..f85fffd 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -217,14 +217,17 @@ contract HomeBridge { return estimatedGasCostOfWithdraw * tx.gasprice; } - /// Used to withdraw money from the contract. - /// - /// message contains: - /// withdrawal recipient (bytes20) - /// withdrawal value (uint) - /// foreign transaction hash (bytes32) // to avoid transaction duplication - /// - /// NOTE that anyone can call withdraw provided they have the message and required signatures! + /// final step of a withdraw. + /// checks that `requiredSignatures` `authorities` have signed of on the `message`. + /// then transfers `value` to `recipient` (both extracted from `message`). + /// see message library above for a breakdown of the `message` contents. + /// `vs`, `rs`, `ss` are the components of the signatures. + + /// anyone can call this, provided they have the message and required signatures! + /// only the `authorities` can create these signatures. + /// `requiredSignatures` authorities can sign arbitrary `message`s + /// transfering any ether `value` out of this contract to `recipient`. + /// bridge users must trust a majority of `requiredSignatures` of the `authorities`. function withdraw(uint8[] v, bytes32[] r, bytes32[] s, bytes message) public allAuthorities(v, r, s, message) { require(message.length == 84); address recipient = Message.getRecipient(message); From f7587409f9c01e8e171956cb09c59601623a5c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 31 Jan 2018 14:29:18 +0100 Subject: [PATCH 084/152] bridge.sol: improve param names --- contracts/bridge.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index f85fffd..29b2aaf 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -171,14 +171,14 @@ contract HomeBridge { event Withdraw (address recipient, uint value); /// Multisig authority validation - modifier allAuthorities(uint8[] v, bytes32[] r, bytes32[] s, bytes message) { + modifier allAuthorities(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) { var hash = MessageSigning.hashMessage(message); var used = new address[](requiredSignatures); - require(requiredSignatures <= v.length); + require(requiredSignatures <= vs.length); for (uint i = 0; i < requiredSignatures; i++) { - var a = ecrecover(hash, v[i], r[i], s[i]); + var a = ecrecover(hash, vs[i], rs[i], ss[i]); require(Helpers.addressArrayContains(authorities, a)); require(!Helpers.addressArrayContains(used, a)); used[i] = a; @@ -228,7 +228,7 @@ contract HomeBridge { /// `requiredSignatures` authorities can sign arbitrary `message`s /// transfering any ether `value` out of this contract to `recipient`. /// bridge users must trust a majority of `requiredSignatures` of the `authorities`. - function withdraw(uint8[] v, bytes32[] r, bytes32[] s, bytes message) public allAuthorities(v, r, s, message) { + function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) public allAuthorities(vs, rs, ss, message) { require(message.length == 84); address recipient = Message.getRecipient(message); uint value = Message.getValue(message); From 36c0859d78e3ff62f67b819d4bc32177313645ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 31 Jan 2018 16:27:12 +0100 Subject: [PATCH 085/152] bridge.sol: move withdraw sig verify from modifier into function more explicit, easier to test in isolation --- contracts/bridge.sol | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 29b2aaf..ba8fff8 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -35,6 +35,25 @@ library Helpers { } while (currentValue != 0); return string(result); } + + /// Multisig authority validation + function verifySignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) internal pure { + // not enough signatures + require(requiredSignatures <= vs.length); + + var hash = MessageSigning.hashMessage(message); + var encountered = new address[](addresses.length); + + for (uint i = 0; i < requiredSignatures; i++) { + var a = ecrecover(hash, vs[i], rs[i], ss[i]); + // only signatures by addresses in `addresses` are allowed + require(addressArrayContains(addresses, a)); + // duplicate signatures are not allowed + require(!addressArrayContains(encountered, a)); + encountered[i] = a; + } + } + } @@ -170,22 +189,6 @@ contract HomeBridge { /// Event created on money withdraw. event Withdraw (address recipient, uint value); - /// Multisig authority validation - modifier allAuthorities(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) { - var hash = MessageSigning.hashMessage(message); - var used = new address[](requiredSignatures); - - require(requiredSignatures <= vs.length); - - for (uint i = 0; i < requiredSignatures; i++) { - var a = ecrecover(hash, vs[i], rs[i], ss[i]); - require(Helpers.addressArrayContains(authorities, a)); - require(!Helpers.addressArrayContains(used, a)); - used[i] = a; - } - _; - } - /// Constructor. function HomeBridge( uint requiredSignaturesParam, @@ -228,8 +231,12 @@ contract HomeBridge { /// `requiredSignatures` authorities can sign arbitrary `message`s /// transfering any ether `value` out of this contract to `recipient`. /// bridge users must trust a majority of `requiredSignatures` of the `authorities`. - function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) public allAuthorities(vs, rs, ss, message) { + function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) public { require(message.length == 84); + + // check that at least `requiredSignatures` `authorities` have signed `message` + Helpers.verifySignatures(message, vs, rs, ss, authorities, requiredSignatures); + address recipient = Message.getRecipient(message); uint value = Message.getValue(message); bytes32 hash = Message.getTransactionHash(message); From 41543ca40e510070f77f975c1a69d4b253fd38fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 31 Jan 2018 16:30:01 +0100 Subject: [PATCH 086/152] user explicitely specifies homeGasPrice on withdraw. resolves #112 --- bridge/src/bridge/deploy.rs | 1 + bridge/src/bridge/withdraw_confirm.rs | 6 +-- bridge/src/bridge/withdraw_relay.rs | 4 +- contracts/bridge.sol | 54 ++++++++++++++++++++------- 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/bridge/src/bridge/deploy.rs b/bridge/src/bridge/deploy.rs index d69a78b..8f47437 100644 --- a/bridge/src/bridge/deploy.rs +++ b/bridge/src/bridge/deploy.rs @@ -52,6 +52,7 @@ impl Future for Deploy { 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 main_tx_request = TransactionRequest { diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 97c4385..eb4dc88 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -25,16 +25,16 @@ fn withdraw_confirm_sign_payload(foreign: &foreign::ForeignBridge, log: Log) -> }; let withdraw_log = foreign.events().withdraw().parse_log(raw_log)?; let hash = log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); - let mut result = vec![0u8; 84]; + let mut result = vec![0u8; 116]; result[0..20].copy_from_slice(&withdraw_log.recipient); result[20..52].copy_from_slice(&H256::from(withdraw_log.value)); result[52..84].copy_from_slice(&hash); + result[84..116].copy_from_slice(&withdraw_log.home_gas_price); Ok(result.into()) } fn withdraw_submit_signature_payload(foreign: &foreign::ForeignBridge, withdraw_message: Bytes, signature: H520) -> Bytes { - assert_eq!(signature.0.len(), 65); - assert_eq!(withdraw_message.0.len(), 84, "ForeignBridge never accepts messages with len != 84 bytes; qed"); + assert_eq!(withdraw_message.0.len(), 116, "ForeignBridge never accepts messages with len != 116 bytes; qed"); foreign.functions().submit_signature().input(signature.0.to_vec(), withdraw_message.0).into() } diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 27c64b6..c6ec332 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -58,7 +58,7 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 /// returns the payload for a call to `HomeBridge.isMessageValueSufficientToCoverRelay(message)` /// for the given `message` fn message_value_sufficient_payload(home: &home::HomeBridge, message: &Bytes) -> Bytes { - assert_eq!(message.0.len(), 84, "ForeignBridge never accepts messages with len != 84 bytes; qed"); + assert_eq!(message.0.len(), 116, "ForeignBridge never accepts messages with len != 116 bytes; qed"); home .functions() .is_message_value_sufficient_to_cover_relay() @@ -68,7 +68,7 @@ fn message_value_sufficient_payload(home: &home::HomeBridge, message: &Bytes) -> /// returns the payload for a transaction to `HomeBridge.withdraw(r, s, v, message)` /// for the given `signatures` (r, s, v) and `message` fn withdraw_relay_payload(home: &home::HomeBridge, signatures: &[Bytes], message: &Bytes) -> Bytes { - assert_eq!(message.0.len(), 84, "ForeignBridge never accepts messages with len != 84 bytes; qed"); + assert_eq!(message.0.len(), 116, "ForeignBridge never accepts messages with len != 116 bytes; qed"); let mut v_vec = Vec::new(); let mut r_vec = Vec::new(); let mut s_vec = Vec::new(); diff --git a/contracts/bridge.sol b/contracts/bridge.sol index ba8fff8..2ff7e98 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -107,6 +107,7 @@ library Message { // offset 32: 20 bytes :: address - recipient address // offset 52: 32 bytes :: uint (little endian) - value // offset 84: 32 bytes :: bytes32 - transaction hash + // offset 116: 32 bytes :: uint (little endian) - home gas price // bytes 1 to 32 are 0 because message length is stored as little endian. // mload always reads 32 bytes. @@ -145,6 +146,15 @@ library Message { } return hash; } + + function getHomeGasPrice(bytes message) internal pure returns (uint) { + uint gasPrice; + // solium-disable-next-line security/no-inline-assembly + assembly { + gasPrice := mload(add(message, 116)) + } + return gasPrice; + } } @@ -161,6 +171,10 @@ library MessageTest { function getTransactionHash(bytes message) public pure returns (bytes32) { return Message.getTransactionHash(message); } + + function getHomeGasPrice(bytes message) public pure returns (uint) { + return Message.getHomeGasPrice(message); + } } @@ -232,7 +246,7 @@ contract HomeBridge { /// transfering any ether `value` out of this contract to `recipient`. /// bridge users must trust a majority of `requiredSignatures` of the `authorities`. function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) public { - require(message.length == 84); + require(message.length == 116); // check that at least `requiredSignatures` `authorities` have signed `message` Helpers.verifySignatures(message, vs, rs, ss, authorities, requiredSignatures); @@ -240,6 +254,17 @@ contract HomeBridge { address recipient = Message.getRecipient(message); uint value = Message.getValue(message); bytes32 hash = Message.getTransactionHash(message); + uint homeGasPrice = Message.getHomeGasPrice(message); + + // if the recipient calls `withdraw` they can choose the gas price freely. + // if anyone else calls `withdraw` they have to use the gas price + // `homeGasPrice` specified by the user initiating the withdraw. + // this is a security mechanism designed to shut down + // malicious senders setting extremely high gas prices + // and effectively burning recipients withdrawn value. + // see https://github.com/paritytech/parity-bridge/issues/112 + // for further explanation. + require((recipient == msg.sender) || (tx.gasprice == homeGasPrice)); // The following two statements guard against reentry into this function. // Duplicated withdraw or reentry. @@ -247,12 +272,7 @@ contract HomeBridge { // Order of operations below is critical to avoid TheDAO-like re-entry bug withdraws[hash] = true; - // this fails if `value` is not even enough to cover the relay cost. - // Authorities simply IGNORE withdraws where `value` can’t relay cost. - // Think of it as `value` getting burned entirely on the relay with no value left to pay out the recipient. - require(isMessageValueSufficientToCoverRelay(message)); - - uint estimatedWeiCostOfWithdraw = getWithdrawRelayCost(); + uint estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; // charge recipient for relay cost uint valueRemainingAfterSubtractingCost = value - estimatedWeiCostOfWithdraw; @@ -360,6 +380,8 @@ contract ForeignBridge { /// Must be less than number of authorities. uint public requiredSignatures; + uint public estimatedGasCostOfWithdraw; + /// Contract authorities. address[] public authorities; @@ -373,20 +395,22 @@ contract ForeignBridge { event Deposit(address recipient, uint value); /// Event created on money withdraw. - event Withdraw(address recipient, uint value); + event Withdraw(address recipient, uint value, uint homeGasPrice); /// Collected signatures which should be relayed to home chain. event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash); function ForeignBridge( uint _requiredSignatures, - address[] _authorities + address[] _authorities, + uint _estimatedGasCostOfWithdraw ) public { require(_requiredSignatures != 0); require(_requiredSignatures <= _authorities.length); requiredSignatures = _requiredSignatures; authorities = _authorities; + estimatedGasCostOfWithdraw = _estimatedGasCostOfWithdraw; } /// require that sender is an authority @@ -430,11 +454,14 @@ contract ForeignBridge { /// once `requiredSignatures` are collected a `CollectedSignatures` event will be emitted. /// an authority will pick up `CollectedSignatures` an call `HomeBridge.withdraw` /// which transfers `value - relayCost` to `recipient` completing the transfer. - function transferHomeViaRelay(address recipient, uint value) public { + function transferHomeViaRelay(address recipient, uint value, uint homeGasPrice) public { require(balances[msg.sender] >= value); // don't allow 0 value transfers to home require(value > 0); + uint estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; + require(value >= estimatedWeiCostOfWithdraw); + balances[msg.sender] -= value; // burns tokens totalSupply -= value; @@ -442,7 +469,7 @@ contract ForeignBridge { // recommended by ERC20 (see implementation of `deposit` above) // we trigger a Transfer event to `0x0` on token destruction Transfer(msg.sender, 0x0, value); - Withdraw(recipient, value); + Withdraw(recipient, value, homeGasPrice); } /// Should be used as sync tool @@ -457,8 +484,9 @@ contract ForeignBridge { // Validate submited signatures require(MessageSigning.recoverAddressFromSignedMessage(signature, message) == msg.sender); - // Valid withdraw message must have 84 bytes - require(message.length == 84); + require(signature.length == 65); + // Valid withdraw message must have 116 bytes + require(message.length == 116); var hash = keccak256(message); // Duplicated signatures From 8f1f8cae3e061706d6bee6e3efd471efbb9d1e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 31 Jan 2018 16:30:50 +0100 Subject: [PATCH 087/152] adapt integration tests to #112 --- integration-tests/tests/basic_deposit_then_withdraw.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index 773894e..6f4efcd 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -238,7 +238,8 @@ fn test_basic_deposit_then_withdraw() { .transfer_home_via_relay() .input( Address::from(user_address), - U256::from(100000)); + U256::from(100000), + U256::from(1)); let future = foreign_eth.send_transaction(web3::types::TransactionRequest{ from: address_from_str(user_address), to: Some(address_from_str(foreign_contract_address)), From f2e29764c260df8a868f5f3331e23dd1705e10b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 31 Jan 2018 16:31:39 +0100 Subject: [PATCH 088/152] make existing truffle tests run again after 112 --- truffle/test/foreign-erc20.js | 100 +++++++++++++++++--------------- truffle/test/foreign.js | 69 ++++++++++++++-------- truffle/test/helpers/helpers.js | 14 +++-- truffle/test/home.js | 27 ++++----- 4 files changed, 122 insertions(+), 88 deletions(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index 0691b7c..1e3e838 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -3,73 +3,76 @@ var helpers = require("./helpers/helpers"); contract('ForeignBridge', function(accounts) { it("totalSupply", function() { - var contract; + var contract; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var owner = accounts[2]; + var owner = accounts[2]; var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; var value = web3.toWei(3, "ether"); - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { - contract = instance; + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { + contract = instance; return contract.totalSupply(); }).then(function(result) { - assert.equal(0, result, "initial supply should be 0"); + assert.equal(0, result, "initial supply should be 0"); - return contract.deposit(owner, value, hash, {from: authorities[0]}); - }).then(function(result) { + return contract.deposit(owner, value, hash, {from: authorities[0]}); + }).then(function(result) { return contract.totalSupply(); }).then(function(result) { - console.log(result); - assert(result.equals(value), "deposit should increase supply"); + console.log(result); + assert(result.equals(value), "deposit should increase supply"); - return contract.transferHomeViaRelay(owner, value, {from: owner}); - }).then(function() { + var homeGasPrice = 1000; + return contract.transferHomeViaRelay(owner, value, homeGasPrice, {from: owner}); + }).then(function() { return contract.totalSupply(); }).then(function(result) { - assert.equal(0, result, "home transfer should decrease supply"); - }) + assert.equal(0, result, "home transfer should decrease supply"); + }) }) it("should be able to approve others to spend tokens in their name", function() { - var contract; + var contract; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var owner = accounts[2]; - var spender = accounts[3]; - var receiver = accounts[4]; + var owner = accounts[2]; + var spender = accounts[3]; + var receiver = accounts[4]; var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { - contract = instance; + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { + contract = instance; // deposit something so we can transfer it - return contract.deposit(owner, web3.toWei(3, "ether"), hash, {from: authorities[0]}); - }).then(function(result) { + return contract.deposit(owner, web3.toWei(3, "ether"), hash, {from: authorities[0]}); + }).then(function(result) { return contract.allowance(owner, spender); }).then(function(result) { - assert.equal(0, result, "initial allowance should be 0"); + assert.equal(0, result, "initial allowance should be 0"); return contract.transferFrom(owner, receiver, web3.toWei(1, "ether"), {from: spender}); }).then(function(result) { - assert(false, "transfer without allowance should fail"); + assert(false, "transfer without allowance should fail"); // transfer 0 without allowance should work return contract.transferFrom(owner, receiver, 0, {from: spender}); - }).then(function(result) { + }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("Transfer", result.logs[0].event, "Event name should be Transfer"); assert.equal(owner, result.logs[0].args.from); assert.equal(receiver, result.logs[0].args.to); assert.equal(0, result.logs[0].args.tokens); - }, function(err) { - return contract.approve(spender, web3.toWei(4, "ether"), {from: owner}); - }).then(function(result) { + }, function(err) { + return contract.approve(spender, web3.toWei(4, "ether"), {from: owner}); + }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("Approval", result.logs[0].event, "Event name should be Approval"); assert.equal(owner, result.logs[0].args.tokenOwner); @@ -78,14 +81,14 @@ contract('ForeignBridge', function(accounts) { return contract.allowance(owner, spender); }).then(function(result) { - assert.equal(web3.toWei(4, "ether"), result, "approval should set allowance"); + assert.equal(web3.toWei(4, "ether"), result, "approval should set allowance"); return contract.transferFrom(owner, receiver, web3.toWei(4, "ether"), {from: spender}); }).then(function(result) { - assert(false, "transferring more than balance should fail"); - }, function(err) { - return contract.approve(spender, web3.toWei(2, "ether"), {from: owner}); - }).then(function(result) { + assert(false, "transferring more than balance should fail"); + }, function(err) { + return contract.approve(spender, web3.toWei(2, "ether"), {from: owner}); + }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); assert.equal("Approval", result.logs[0].event, "Event name should be Approval"); assert.equal(owner, result.logs[0].args.tokenOwner); @@ -94,12 +97,12 @@ contract('ForeignBridge', function(accounts) { return contract.allowance(owner, spender); }).then(function(result) { - assert.equal(web3.toWei(2, "ether"), result, "approval should update allowance"); + assert.equal(web3.toWei(2, "ether"), result, "approval should update allowance"); return contract.transferFrom(owner, receiver, web3.toWei(2, "ether") + 2, {from: spender}); }).then(function(result) { - assert(false, "transferring more than allowance should fail"); - }, function(err) { + assert(false, "transferring more than allowance should fail"); + }, function(err) { return contract.transferFrom(owner, receiver, web3.toWei(2, "ether"), {from: spender}); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -110,32 +113,33 @@ contract('ForeignBridge', function(accounts) { return contract.balanceOf(owner); }).then(function(result) { - assert.equal(web3.toWei(1, "ether"), result, "transferring should reduce owners balance"); + assert.equal(web3.toWei(1, "ether"), result, "transferring should reduce owners balance"); return contract.balanceOf(receiver); }).then(function(result) { - assert.equal(web3.toWei(2, "ether"), result, "transferring should increase receivers balance"); + assert.equal(web3.toWei(2, "ether"), result, "transferring should increase receivers balance"); return contract.balanceOf(spender); }).then(function(result) { - assert.equal(0, result, "transferring should not modify spenders balance"); + assert.equal(0, result, "transferring should not modify spenders balance"); return contract.allowance(owner, spender); }).then(function(result) { - assert.equal(0, result, "transferring whole allowance should set allowance to 0"); - }) + assert.equal(0, result, "transferring whole allowance should set allowance to 0"); + }) }) it("should allow user to transfer value locally", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var userAccount2 = accounts[3]; var user1InitialValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; // top up balance so we can transfer return meta.deposit(userAccount, user1InitialValue, hash, { from: authorities[0] }); @@ -160,13 +164,14 @@ contract('ForeignBridge', function(accounts) { it("should not allow user to transfer value they don't have", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(4, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { @@ -180,12 +185,13 @@ contract('ForeignBridge', function(accounts) { it("should allow transfer of 0 value according to ERC20", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { @@ -209,12 +215,13 @@ contract('ForeignBridge', function(accounts) { it("transfer that results in overflow should fail", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var recipientAccount = accounts[3]; var maxValue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(recipientAccount, maxValue, hash, { from: authorities[0] }); }).then(function(result) { @@ -230,13 +237,14 @@ contract('ForeignBridge', function(accounts) { it("transferFrom that results in overflow should fail", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; - var spenderAccount = accounts[3]; + var spenderAccount = accounts[3]; var recipientAccount = accounts[4]; var maxValue = web3.toWei("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "wei"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(recipientAccount, maxValue, hash, { from: authorities[0] }); }).then(function(result) { diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 4d5792e..b02eebe 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -5,9 +5,10 @@ contract('ForeignBridge', function(accounts) { it("should deploy contract", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.requiredSignatures.call(); }).then(function(result) { @@ -20,7 +21,7 @@ contract('ForeignBridge', function(accounts) { it("should fail to deploy contract with not enough required signatures", function() { var authorities = [accounts[0], accounts[1]]; - return ForeignBridge.new(0, authorities).then(function(_) { + return ForeignBridge.new(0, authorities, 0).then(function(_) { assert(false, "Contract should fail to deploy"); }, function(err) { // do nothing @@ -29,7 +30,7 @@ contract('ForeignBridge', function(accounts) { it("should fail to deploy contract with to many signatures", function() { var authorities = [accounts[0], accounts[1]]; - return ForeignBridge.new(3, authorities).then(function(_) { + return ForeignBridge.new(3, authorities, 0).then(function(_) { assert(false, "Contract should fail to deploy"); }, function(err) { // do nothing @@ -39,12 +40,13 @@ contract('ForeignBridge', function(accounts) { it("should allow a single authority to confirm a deposit", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var value = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { @@ -68,12 +70,13 @@ contract('ForeignBridge', function(accounts) { it("should require 2 authorities to confirm deposit", function() { var meta; var requiredSignatures = 2; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var value = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { @@ -102,12 +105,13 @@ contract('ForeignBridge', function(accounts) { it("should not be possible to do same deposit twice for same authority", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var value = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(_) { @@ -121,12 +125,13 @@ contract('ForeignBridge', function(accounts) { it("should not allow non-authorities to execute deposit", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var value = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, value, hash, { from: userAccount }); }).then(function(result) { @@ -138,13 +143,14 @@ contract('ForeignBridge', function(accounts) { it("should ignore misbehaving authority when confirming deposit", function() { var meta; var requiredSignatures = 2; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1], accounts[2]]; var userAccount = accounts[3]; var invalidValue = web3.toWei(2, "ether"); var value = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { @@ -174,13 +180,14 @@ contract('ForeignBridge', function(accounts) { it("should not allow user to transfer value they don't have to home", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(4, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { @@ -194,13 +201,14 @@ contract('ForeignBridge', function(accounts) { it("should fail to transfer 0 value to home", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(0, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { @@ -214,18 +222,20 @@ contract('ForeignBridge', function(accounts) { it("should allow user to trigger withdraw", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var userAccount2 = accounts[3]; var value = web3.toWei(3, "ether"); var value2 = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; // top up balance so we can transfer return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(userAccount2, value2, { from: userAccount }); + var homeGasPrice = 1000; + return meta.transferHomeViaRelay(userAccount2, value2, homeGasPrice, { from: userAccount }); }).then(function(result) { assert.equal(2, result.logs.length) @@ -252,9 +262,12 @@ contract('ForeignBridge', function(accounts) { var meta; var signature; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, web3.toBigNumber(1000)); + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { @@ -277,9 +290,12 @@ contract('ForeignBridge', function(accounts) { it("should successfully submit signature but not trigger CollectedSignatures event", function() { var meta; var requiredSignatures = 2; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, web3.toBigNumber(1000)); + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { @@ -294,10 +310,13 @@ contract('ForeignBridge', function(accounts) { var signatures_for_message = []; var signatures_for_message2 = []; var requiredSignatures = 2; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - var message2 = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, web3.toBigNumber(1000)); + var message2 = helpers.createMessage(recipientAccount, web3.toBigNumber(2000), transactionHash, web3.toBigNumber(2000)); + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return Promise.all([ helpers.sign(authorities[0], message), @@ -350,9 +369,10 @@ contract('ForeignBridge', function(accounts) { it("should not be possible to submit to short message", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var message = "0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { @@ -367,10 +387,11 @@ contract('ForeignBridge', function(accounts) { it("should not be possible to submit different message then the signed one", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; var message2 = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { @@ -385,9 +406,10 @@ contract('ForeignBridge', function(accounts) { it("should not be possible to submit signature signed by different authority", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { @@ -402,10 +424,11 @@ contract('ForeignBridge', function(accounts) { it("should not be possible to submit signature twice", function() { var meta; var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; var signature; - return ForeignBridge.new(requiredSignatures, authorities).then(function(instance) { + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { diff --git a/truffle/test/helpers/helpers.js b/truffle/test/helpers/helpers.js index 3ad8ee0..5ebafc5 100644 --- a/truffle/test/helpers/helpers.js +++ b/truffle/test/helpers/helpers.js @@ -77,17 +77,23 @@ module.exports.getBalances = getBalances; // composed from `recipient`, `value` and `transactionHash` // that is relayed from `foreign` to `home` on withdraw function createMessage(recipient, value, transactionHash) { + var homeGasPrice = web3.toBigNumber(1000); + web3._extend.utils.isBigNumber(value); recipient = strip0x(recipient); assert.equal(recipient.length, 20 * 2); + var value = strip0x(bigNumberToPaddedBytes32(value)); + assert.equal(value.length, 64); + transactionHash = strip0x(transactionHash); assert.equal(transactionHash.length, 32 * 2); - var value = strip0x(bigNumberToPaddedBytes32(value)); - assert.equal(value.length, 64); - var message = "0x" + recipient + value + transactionHash; - var expectedMessageLength = (20 + 32 + 32) * 2 + 2; + homeGasPrice = strip0x(bigNumberToPaddedBytes32(homeGasPrice)); + assert.equal(homeGasPrice.length, 64); + + var message = "0x" + recipient + value + transactionHash + homeGasPrice; + var expectedMessageLength = (20 + 32 + 32 + 32) * 2 + 2; assert.equal(message.length, expectedMessageLength); return message; } diff --git a/truffle/test/home.js b/truffle/test/home.js index 19f635d..f7882a6 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -149,7 +149,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - {from: authorities[0]} + {from: userAccount, gasPrice: 1000} ); }).then(function(result) { console.log("estimated gas cost of HomeBridge.withdraw =", result); @@ -160,8 +160,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount} + {from: userAccount, gasPrice: 1000} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -215,8 +214,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - // anyone can call withdraw (provided they have the message and required signatures) - { from: relayerAccount } + { from: relayerAccount, gasPrice: 1000 } ); }).then(function(result) { transactionResult = result; @@ -291,8 +289,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - // anyone can call withdraw (provided they have the message and required signatures) - { from: relayerAccount } + { from: relayerAccount, gasPrice: 1000 } ); }).then(function(result) { assert(false, "withdraw if value <= estimatedGasCostOfWithdraw should fail"); @@ -332,7 +329,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message1, - {from: authorities[0]} + {from: authorities[0], gasPrice: 1000} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -348,7 +345,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message2, - {from: authorities[0]} + {from: authorities[0], gasPrice: 1000} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -389,7 +386,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message1, - {from: authorities[0]} + {from: authorities[0], gasPrice: 1000} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -405,7 +402,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message2, - {from: authorities[0]} + {from: authorities[0], gasPrice: 1000} ); }).then(function(result) { assert(false, "should fail"); @@ -440,7 +437,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message.substr(0, 83), - {from: authorities[0]} + {from: authorities[0], gasPrice: 1000} ); }).then(function(result) { assert(false, "should fail"); @@ -486,7 +483,7 @@ contract('HomeBridge', function(accounts) { [vrs.s], message, // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount} + {from: userAccount, gasPrice: 1000} ); }).then(function(result) { assert(false, "withdraw should fail"); @@ -529,7 +526,7 @@ contract('HomeBridge', function(accounts) { [vrs.s], message, // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount} + {from: userAccount, gasPrice: 1000} ); }).then(function(result) { assert(false, "should fail"); @@ -572,7 +569,7 @@ contract('HomeBridge', function(accounts) { [vrs.s, vrs.s], message, // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount} + {from: userAccount, gasPrice: 1000} ); }).then(function(result) { assert(false, "should fail"); From c0d87f19c0bf3972d516dc379314157ddbaf0a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 1 Feb 2018 10:02:57 +0100 Subject: [PATCH 089/152] magic numbers -> constants --- bridge/src/bridge/withdraw_confirm.rs | 8 ++++---- bridge/src/bridge/withdraw_relay.rs | 14 +++++++------- bridge/src/contracts.rs | 3 +++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index eb4dc88..3f0acf2 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -8,7 +8,7 @@ use web3::Transport; use web3::types::{H256, H520, Address, TransactionRequest, Log, Bytes, FilterBuilder}; use api::{self, LogStream, ApiCall}; use app::App; -use contracts::foreign; +use contracts::{foreign, MESSAGE_LENGTH}; use util::web3_filter; use database::Database; use error::Error; @@ -25,16 +25,16 @@ fn withdraw_confirm_sign_payload(foreign: &foreign::ForeignBridge, log: Log) -> }; let withdraw_log = foreign.events().withdraw().parse_log(raw_log)?; let hash = log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); - let mut result = vec![0u8; 116]; + let mut result = vec![0u8; MESSAGE_LENGTH]; result[0..20].copy_from_slice(&withdraw_log.recipient); result[20..52].copy_from_slice(&H256::from(withdraw_log.value)); result[52..84].copy_from_slice(&hash); - result[84..116].copy_from_slice(&withdraw_log.home_gas_price); + result[84..MESSAGE_LENGTH].copy_from_slice(&withdraw_log.home_gas_price); Ok(result.into()) } fn withdraw_submit_signature_payload(foreign: &foreign::ForeignBridge, withdraw_message: Bytes, signature: H520) -> Bytes { - assert_eq!(withdraw_message.0.len(), 116, "ForeignBridge never accepts messages with len != 116 bytes; qed"); + assert_eq!(withdraw_message.0.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); foreign.functions().submit_signature().input(signature.0.to_vec(), withdraw_message.0).into() } diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index c6ec332..3321af7 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -7,7 +7,7 @@ use web3::types::{U256, H256, Address, FilterBuilder, Log, Bytes, TransactionReq use ethabi::{RawLog, self}; use app::App; use api::{self, LogStream, ApiCall}; -use contracts::{home, foreign}; +use contracts::{home, foreign, MESSAGE_LENGTH, SIGNATURE_LENGTH}; use util::web3_filter; use database::Database; use error::{self, Error}; @@ -58,7 +58,7 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 /// returns the payload for a call to `HomeBridge.isMessageValueSufficientToCoverRelay(message)` /// for the given `message` fn message_value_sufficient_payload(home: &home::HomeBridge, message: &Bytes) -> Bytes { - assert_eq!(message.0.len(), 116, "ForeignBridge never accepts messages with len != 116 bytes; qed"); + assert_eq!(message.0.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); home .functions() .is_message_value_sufficient_to_cover_relay() @@ -68,12 +68,12 @@ fn message_value_sufficient_payload(home: &home::HomeBridge, message: &Bytes) -> /// returns the payload for a transaction to `HomeBridge.withdraw(r, s, v, message)` /// for the given `signatures` (r, s, v) and `message` fn withdraw_relay_payload(home: &home::HomeBridge, signatures: &[Bytes], message: &Bytes) -> Bytes { - assert_eq!(message.0.len(), 116, "ForeignBridge never accepts messages with len != 116 bytes; qed"); + assert_eq!(message.0.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); let mut v_vec = Vec::new(); let mut r_vec = Vec::new(); let mut s_vec = Vec::new(); for signature in signatures { - assert_eq!(signature.0.len(), 65, "ForeignBridge never accepts signatures with len != 65 bytes; qed"); + assert_eq!(signature.0.len(), SIGNATURE_LENGTH, "ForeignBridge never accepts signatures with len != {} bytes; qed", SIGNATURE_LENGTH); let mut r = [0u8; 32]; let mut s= [0u8; 32]; let mut v = [0u8; 32]; @@ -364,10 +364,10 @@ mod tests { fn test_withdraw_relay_payload() { let home = home::HomeBridge::default(); let signatures: Vec = vec![ - vec![0x11; 65].into(), - vec![0x22; 65].into(), + vec![0x11; SIGNATURE_LENGTH].into(), + vec![0x22; SIGNATURE_LENGTH].into(), ]; - let message: Bytes = vec![0x33; 84].into(); + let message: Bytes = vec![0x33; MESSAGE_LENGTH].into(); let payload = withdraw_relay_payload(&home, &signatures, &message); let expected: Bytes = "9ce318f6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000".from_hex().unwrap().into(); diff --git a/bridge/src/contracts.rs b/bridge/src/contracts.rs index cf41f82..ab727e4 100644 --- a/bridge/src/contracts.rs +++ b/bridge/src/contracts.rs @@ -1,2 +1,5 @@ use_contract!(home, "HomeBridge", "../compiled_contracts/HomeBridge.abi"); use_contract!(foreign, "ForeignBridge", "../compiled_contracts/ForeignBridge.abi"); + +pub const MESSAGE_LENGTH: usize = 116; +pub const SIGNATURE_LENGTH: usize = 65; From ef2a4bca425e2cde4cb9889dfba2dfb8214d5dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 1 Feb 2018 13:53:40 +0100 Subject: [PATCH 090/152] make rpc stream tests more readable/modifiable by using json! instead of strings --- tests/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 6e5bcfc..3c3dd5a 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -15,11 +15,11 @@ pub struct MockedRequest { pub params: Vec, } -impl From<(&'static str, &'static str)> for MockedRequest { - fn from(a: (&'static str, &'static str)) -> Self { +impl From<(&'static str, serde_json::Value)> for MockedRequest { + fn from(a: (&'static str, serde_json::Value)) -> Self { MockedRequest { method: a.0.to_owned(), - params: serde_json::from_str(a.1).unwrap(), + params: a.1.as_array().unwrap().clone() } } } @@ -28,7 +28,7 @@ impl From<(&'static str, &'static str)> for MockedRequest { pub struct MockedTransport { pub requests: Cell, pub expected_requests: Vec, - pub mocked_responses: Vec<&'static str>, + pub mocked_responses: Vec, } impl Transport for MockedTransport { @@ -46,7 +46,7 @@ impl Transport for MockedTransport { fn send(&self, _id: usize, _request: rpc::Call) -> web3::Result { let response = self.mocked_responses.iter().nth(self.requests.get() - 1).expect("missing response"); - let f = futures::finished(serde_json::from_str(response).expect("invalid response")); + let f = futures::finished(response.clone()); Box::new(f) } } From b16644578f30dbc9b2cd285e6448c198b8dd0a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 1 Feb 2018 13:55:08 +0100 Subject: [PATCH 091/152] tests/tests/deposit_relay.rs: &str -> json! --- tests/tests/deposit_relay.rs | 213 +++++++++++++++++++++++++++-------- 1 file changed, 169 insertions(+), 44 deletions(-) diff --git a/tests/tests/deposit_relay.rs b/tests/tests/deposit_relay.rs index d7aa9ca..32dffd9 100644 --- a/tests/tests/deposit_relay.rs +++ b/tests/tests/deposit_relay.rs @@ -1,10 +1,14 @@ extern crate futures; +#[macro_use] +extern crate serde_json; extern crate bridge; #[macro_use] extern crate tests; use bridge::bridge::create_deposit_relay; +const DEPOSIT_TOPIC: &str = "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"; + test_app_stream! { name => deposit_relay_basic, database => Database::default(), @@ -25,17 +29,29 @@ test_app_stream! { expected => vec![0x1005, 0x1006], home_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([]); ], foreign_transport => [] } @@ -63,22 +79,46 @@ test_app_stream! { expected => vec![0x1005, 0x1006], home_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x6","limit":null,"toBlock":"0x1005","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x6", + "limit": null, + "toBlock":"0x1005", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000000", + "topics": [DEPOSIT_TOPIC], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics":[[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([]); ], foreign_transport => [ "eth_sendTransaction" => - req => r#"[{"data":"0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364","from":"0x0000000000000000000000000000000000000001","gas":"0x0","gasPrice":"0x0","to":"0x0000000000000000000000000000000000000000"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": "0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364", + "from": "0x0000000000000000000000000000000000000001", + "gas": "0x0", + "gasPrice": "0x0", + "to": "0x0000000000000000000000000000000000000000" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); ] } @@ -111,16 +151,32 @@ test_app_stream! { expected => vec![0x1005], home_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x6","limit":null,"toBlock":"0x1005","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x6", + "limit": null, + "toBlock": "0x1005", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000000", + "topics": [DEPOSIT_TOPIC], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); ], foreign_transport => [ "eth_sendTransaction" => - req => r#"[{"data":"0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364","from":"0x0000000000000000000000000000000000000001","gas":"0xfd","gasPrice":"0xa0","to":"0x0000000000000000000000000000000000000000"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": "0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364", + "from": "0x0000000000000000000000000000000000000001", + "gas": "0xfd", + "gasPrice": "0xa0", + "to": "0x0000000000000000000000000000000000000000" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); ] } @@ -148,16 +204,34 @@ test_app_stream! { expected => vec![0x1005], home_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000cc1"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000cc1","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000cc1"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000cc1", + "topics": ["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); ], foreign_transport => [ "eth_sendTransaction" => - req => r#"[{"data":"0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364","from":"0x0000000000000000000000000000000000000001","gas":"0x0","gasPrice":"0x0","to":"0x0000000000000000000000000000000000000dd1"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": "0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364", + "from": "0x0000000000000000000000000000000000000001", + "gas": "0x0", + "gasPrice": "0x0", + "to": "0x0000000000000000000000000000000000000dd1" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); ] } @@ -185,16 +259,34 @@ test_app_stream! { expected => vec![0x1005], home_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000cc1"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000cc1","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000cc1"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000cc1", + "topics": [DEPOSIT_TOPIC], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); ], foreign_transport => [ "eth_sendTransaction" => - req => r#"[{"data":"0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364","from":"0x00000000000000000000000000000000000000ee","gas":"0x0","gasPrice":"0x0","to":"0x0000000000000000000000000000000000000dd1"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": "0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364", + "from": "0x00000000000000000000000000000000000000ee", + "gas": "0x0", + "gasPrice": "0x0", + "to":"0x0000000000000000000000000000000000000dd1" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); ] } @@ -218,18 +310,51 @@ test_app_stream! { expected => vec![0x1005], home_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"},{"address":"0x0000000000000000000000000000000000000000","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436f"}]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[DEPOSIT_TOPIC], null, null, null] + }]), + res => json!([ + { + "address": "0x0000000000000000000000000000000000000000", + "topics": ["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }, + { + "address":"0x0000000000000000000000000000000000000000", + "topics": ["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436f" + } + ]); ], foreign_transport => [ "eth_sendTransaction" => - req => r#"[{"data":"0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364","from":"0x0000000000000000000000000000000000000001","gas":"0x0","gasPrice":"0x0","to":"0x0000000000000000000000000000000000000000"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": "0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364", + "from": "0x0000000000000000000000000000000000000001", + "gas": "0x0", + "gasPrice": "0x0", + "to": "0x0000000000000000000000000000000000000000" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); "eth_sendTransaction" => - req => r#"[{"data":"0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436f","from":"0x0000000000000000000000000000000000000001","gas":"0x0","gasPrice":"0x0","to":"0x0000000000000000000000000000000000000000"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": "0x26b3293f000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436f", + "from": "0x0000000000000000000000000000000000000001", + "gas": "0x0", + "gasPrice": "0x0", + "to": "0x0000000000000000000000000000000000000000" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); ] } From 793029974df4bf279a5fd1a04790de9fbb8e1825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 1 Feb 2018 15:03:47 +0100 Subject: [PATCH 092/152] tests/tests/log_stream.rs: &str -> json! --- tests/tests/log_stream.rs | 274 +++++++++++++++++++++++++++----------- 1 file changed, 197 insertions(+), 77 deletions(-) diff --git a/tests/tests/log_stream.rs b/tests/tests/log_stream.rs index 1df919c..0e79b53 100644 --- a/tests/tests/log_stream.rs +++ b/tests/tests/log_stream.rs @@ -1,4 +1,6 @@ extern crate futures; +#[macro_use] +extern crate serde_json; extern crate web3; extern crate bridge; #[macro_use] @@ -31,20 +33,32 @@ test_transport_stream! { logs: vec![], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1010""#; + req => json!([]), + res => json!("0x1010"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xb","limit":null,"toBlock":"0x1006","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0xb", + "limit": null, + "toBlock": "0x1006", + "topics": null + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1010""#; + req => json!([]), + res => json!("0x1010"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0x1007","limit":null,"toBlock":"0x1007","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0x1007", + "limit": null, + "toBlock": "0x1007", + "topics": null + }]), + res => json!([]); } test_transport_stream! { @@ -70,23 +84,35 @@ test_transport_stream! { logs: vec![], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x17""#; + req => json!([]), + res => json!("0x17"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xb","limit":null,"toBlock":"0xd","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0xb", + "limit": null, + "toBlock": "0xd", + "topics": null + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x16""#; + req => json!([]), + res => json!("0x16"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x17""#; + req => json!([]), + res => json!("0x17"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x19""#; + req => json!([]), + res => json!("0x19"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xe","limit":null,"toBlock":"0xf","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0xe", + "limit": null, + "toBlock": "0xf", + "topics": null + }]), + res => json!([]); } test_transport_stream! { @@ -108,17 +134,23 @@ test_transport_stream! { logs: vec![], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x13""#; + req => json!([]), + res => json!("0x13"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x14""#; + req => json!([]), + res => json!("0x14"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x17""#; + req => json!([]), + res => json!("0x17"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xb","limit":null,"toBlock":"0xd","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0xb", + "limit": null, + "toBlock": "0xd", + "topics": null + }]), + res => json!([]); } test_transport_stream! { @@ -148,26 +180,44 @@ test_transport_stream! { logs: vec![], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x13""#; + req => json!([]), + res => json!("0x13"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xb","limit":null,"toBlock":"0x13","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0xb", + "limit": null, + "toBlock": "0x13", + "topics": null + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x14""#; + req => json!([]), + res => json!("0x14"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0x14","limit":null,"toBlock":"0x14","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0x14", + "limit": null, + "toBlock": "0x14", + "topics": null + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x14""#; + req => json!([]), + res => json!("0x14"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x17""#; + req => json!([]), + res => json!("0x17"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0x15","limit":null,"toBlock":"0x17","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0x15", + "limit": null, + "toBlock": "0x17", + "topics": null + }]), + res => json!([]); } test_transport_stream! { @@ -193,17 +243,29 @@ test_transport_stream! { logs: vec![], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x13""#; + req => json!([]), + res => json!("0x13"); "eth_getLogs" => - req => r#"[{"address":["0x1111111111111111111111111111111111111111"],"fromBlock":"0xc","limit":null,"toBlock":"0x13","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x1111111111111111111111111111111111111111"], + "fromBlock": "0xc", + "limit": null, + "toBlock": "0x13", + "topics": null + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x14""#; + req => json!([]), + res => json!("0x14"); "eth_getLogs" => - req => r#"[{"address":["0x1111111111111111111111111111111111111111"],"fromBlock":"0x14","limit":null,"toBlock":"0x14","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address":["0x1111111111111111111111111111111111111111"], + "fromBlock": "0x14", + "limit": null, + "toBlock": "0x14", + "topics": null + }]), + res => json!([]); } test_transport_stream! { @@ -229,17 +291,29 @@ test_transport_stream! { logs: vec![], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x13""#; + req => json!([]), + res => json!("0x13"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xc","limit":null,"toBlock":"0x13","topics":[["0x2222222222222222222222222222222222222222222222222222222222222222"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0xc", + "limit": null, + "toBlock": "0x13", + "topics":[["0x2222222222222222222222222222222222222222222222222222222222222222"], null, null, null] + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x14""#; + req => json!([]), + res => json!("0x14"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0x14","limit":null,"toBlock":"0x14","topics":[["0x2222222222222222222222222222222222222222222222222222222222222222"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0x14", + "limit": null, + "toBlock": "0x14", + "topics": [["0x2222222222222222222222222222222222222222222222222222222222222222"], null, null, null] + }]), + res => json!([]); } test_transport_stream! { @@ -267,12 +341,22 @@ test_transport_stream! { }], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1010""#; + req => json!([]), + res => json!("0x1010"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xb","limit":null,"toBlock":"0x1006","topics":null}]"#, - res => - r#"[{"address":"0x0000000000000000000000000000000000000001","topics":[],"data":"0x10","type":""}]"#; + req => json!([{ + "address": null, + "fromBlock": "0xb", + "limit": null, + "toBlock": "0x1006", + "topics": null + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000001", + "topics": [], + "data": "0x10", + "type": "" + }]); } test_transport_stream! { @@ -320,21 +404,57 @@ test_transport_stream! { }], }], "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1010""#; + req => json!([]), + res => json!("0x1010"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0xb","limit":null,"toBlock":"0x1006","topics":null}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000001","topics":[],"data":"0x10","type":""}]"#; + req => json!([{ + "address": null, + "fromBlock": "0xb", + "limit": null, + "toBlock": "0x1006", + "topics": null + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000001", + "topics": [], + "data": "0x10", + "type": "" + }]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0x1007","limit":null,"toBlock":"0x1007","topics":null}]"#, - res => r#"[]"#; + req => json!([{ + "address": null, + "fromBlock": "0x1007", + "limit": null, + "toBlock": "0x1007", + "topics": null + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":null,"fromBlock":"0x1008","limit":null,"toBlock":"0x1008","topics":null}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000002","topics":[],"data":"0x20","type":""},{"address":"0x0000000000000000000000000000000000000002","topics":[],"data":"0x30","type":""}]"#; + req => json!([{ + "address": null, + "fromBlock": "0x1008", + "limit": null, + "toBlock": "0x1008", + "topics": null + }]), + res => json!([ + { + "address": "0x0000000000000000000000000000000000000002", + "topics": [], + "data": "0x20", + "type":"" + }, + { + "address":"0x0000000000000000000000000000000000000002", + "topics": [], + "data": "0x30", + "type": "" + } + ]); } From 500004393033fe03c995363e086c5679a6caebf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 2 Feb 2018 15:59:54 +0100 Subject: [PATCH 093/152] extract code dealing with Withdraw message remove ignoring of messages with insufficient value because no longer needed. use user specified gas price on withdraw. --- bridge/Cargo.toml | 2 + bridge/src/bridge/withdraw_confirm.rs | 48 +++++------- bridge/src/bridge/withdraw_relay.rs | 103 ++++++-------------------- bridge/src/contracts.rs | 1 - bridge/src/helpers.rs | 10 +++ bridge/src/lib.rs | 6 +- bridge/src/message_to_mainnet.rs | 60 +++++++++++++++ 7 files changed, 118 insertions(+), 112 deletions(-) create mode 100644 bridge/src/helpers.rs create mode 100644 bridge/src/message_to_mainnet.rs diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index a9e0369..bc15435 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -18,6 +18,8 @@ ethabi-derive = "5.0" ethabi-contract = "5.0" rustc-hex = "1.0" log = "0.3" +ethereum-types = { git = "https://github.com/paritytech/primitives.git" } +pretty_assertions = "0.2.1" [dev-dependencies] tempdir = "0.3" diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 3f0acf2..782b7b8 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -8,34 +8,20 @@ use web3::Transport; use web3::types::{H256, H520, Address, TransactionRequest, Log, Bytes, FilterBuilder}; use api::{self, LogStream, ApiCall}; use app::App; -use contracts::{foreign, MESSAGE_LENGTH}; +use contracts::foreign; use util::web3_filter; use database::Database; use error::Error; +use message_to_mainnet::{MessageToMainnet, MESSAGE_LENGTH}; fn withdraws_filter(foreign: &foreign::ForeignBridge, address: Address) -> FilterBuilder { let filter = foreign.events().withdraw().create_filter(); web3_filter(filter, address) } -fn withdraw_confirm_sign_payload(foreign: &foreign::ForeignBridge, log: Log) -> Result { - let raw_log = RawLog { - topics: log.topics, - data: log.data.0, - }; - let withdraw_log = foreign.events().withdraw().parse_log(raw_log)?; - let hash = log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); - let mut result = vec![0u8; MESSAGE_LENGTH]; - result[0..20].copy_from_slice(&withdraw_log.recipient); - result[20..52].copy_from_slice(&H256::from(withdraw_log.value)); - result[52..84].copy_from_slice(&hash); - result[84..MESSAGE_LENGTH].copy_from_slice(&withdraw_log.home_gas_price); - Ok(result.into()) -} - -fn withdraw_submit_signature_payload(foreign: &foreign::ForeignBridge, withdraw_message: Bytes, signature: H520) -> Bytes { - assert_eq!(withdraw_message.0.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); - foreign.functions().submit_signature().input(signature.0.to_vec(), withdraw_message.0).into() +fn withdraw_submit_signature_payload(foreign: &foreign::ForeignBridge, withdraw_message: Vec, signature: H520) -> Bytes { + assert_eq!(withdraw_message.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); + foreign.functions().submit_signature().input(signature.0.to_vec(), withdraw_message).into() } /// State of withdraw confirmation. @@ -44,7 +30,7 @@ enum WithdrawConfirmState { Wait, /// Signing withdraws. SignWithdraws { - withdraws: Vec, + messages: Vec>, future: JoinAll>>>, block: u64, }, @@ -91,19 +77,19 @@ impl Stream for WithdrawConfirm { WithdrawConfirmState::Wait => { let item = try_stream!(self.logs.poll()); info!("got {} new withdraws to sign", item.logs.len()); - let withdraws = item.logs + let withdraw_messages = item.logs .into_iter() .map(|log| { info!("withdraw is ready for signature submission. tx hash {}", log.transaction_hash.unwrap()); - withdraw_confirm_sign_payload(&self.app.foreign_bridge, log) + Ok(MessageToMainnet::from_log(log)?.to_bytes()) }) - .collect::, _>>()?; + .collect::, Error>>()?; - let requests = withdraws.clone() + let requests = withdraw_messages.clone() .into_iter() - .map(|bytes| { + .map(|message| { self.app.timer.timeout( - api::sign(&self.app.connections.foreign, self.app.config.foreign.account, bytes), + api::sign(&self.app.connections.foreign, self.app.config.foreign.account, message), self.app.config.foreign.request_timeout) }) .collect::>(); @@ -111,20 +97,22 @@ impl Stream for WithdrawConfirm { info!("signing"); WithdrawConfirmState::SignWithdraws { future: join_all(requests), - withdraws: withdraws, + messages: withdraw_messages, block: item.to, } }, - WithdrawConfirmState::SignWithdraws { ref mut future, ref mut withdraws, block } => { + WithdrawConfirmState::SignWithdraws { ref mut future, ref mut messages, block } => { let signatures = try_ready!(future.poll()); info!("signing complete"); // borrow checker... let app = &self.app; let foreign_contract = &self.foreign_contract; - let confirmations = withdraws + let confirmations = messages .drain(ops::RangeFull) .zip(signatures.into_iter()) - .map(|(withdraw_message, signature)| withdraw_submit_signature_payload(&app.foreign_bridge, withdraw_message, signature)) + .map(|(withdraw_message, signature)| { + withdraw_submit_signature_payload(&app.foreign_bridge, withdraw_message, signature) + }) .map(|payload| TransactionRequest { from: app.config.foreign.account, to: Some(foreign_contract.clone()), diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 3321af7..d1d9b89 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -7,11 +7,12 @@ use web3::types::{U256, H256, Address, FilterBuilder, Log, Bytes, TransactionReq use ethabi::{RawLog, self}; use app::App; use api::{self, LogStream, ApiCall}; -use contracts::{home, foreign, MESSAGE_LENGTH, SIGNATURE_LENGTH}; +use contracts::{home, foreign, SIGNATURE_LENGTH}; use util::web3_filter; use database::Database; use error::{self, Error}; -use rustc_hex::ToHex; +use message_to_mainnet::{MessageToMainnet, MESSAGE_LENGTH}; +use helpers; /// returns a filter for `ForeignBridge.CollectedSignatures` events fn collected_signatures_filter(foreign: &foreign::ForeignBridge, address: Address) -> FilterBuilder { @@ -55,16 +56,6 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 })) } -/// returns the payload for a call to `HomeBridge.isMessageValueSufficientToCoverRelay(message)` -/// for the given `message` -fn message_value_sufficient_payload(home: &home::HomeBridge, message: &Bytes) -> Bytes { - assert_eq!(message.0.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); - home - .functions() - .is_message_value_sufficient_to_cover_relay() - .input(message.0.clone()).into() -} - /// returns the payload for a transaction to `HomeBridge.withdraw(r, s, v, message)` /// for the given `signatures` (r, s, v) and `message` fn withdraw_relay_payload(home: &home::HomeBridge, signatures: &[Bytes], message: &Bytes) -> Bytes { @@ -97,12 +88,6 @@ pub enum WithdrawRelayState { >, block: u64, }, - FetchMessageValueSufficient { - future: JoinAll>>>, - messages: Vec, - signatures: Vec>, - block: u64, - }, RelayWithdraws { future: JoinAll>>>, block: u64, @@ -219,74 +204,31 @@ impl Stream for WithdrawRelay { ) .collect::>>()?; - let message_value_sufficient_payloads = messages - .iter() - .map(|message| { - message_value_sufficient_payload( - &app.home_bridge, - message - ) - }) - .map(|payload| { - app.timer.timeout( - api::call(&app.connections.home, home_contract.clone(), payload), - app.config.home.request_timeout) - }) - .collect::>(); - - info!("fetching whether message values are sufficent"); - WithdrawRelayState::FetchMessageValueSufficient { - future: join_all(message_value_sufficient_payloads), - messages, - signatures, - block, - } - }, - WithdrawRelayState::FetchMessageValueSufficient { - ref mut future, - ref messages, - ref signatures, - block - } => { - let message_value_sufficient = try_ready!(future.poll()); - info!("fetching whether message values are sufficent complete"); - - let app = &self.app; - let home_contract = &self.home_contract; - let relays = messages.into_iter() .zip(signatures.into_iter()) - .zip(message_value_sufficient.into_iter()) - // ignore those messages that don't have sufficient - // value to pay for the relay gas cost - .filter(|&((ref message, _), ref is_message_value_sufficient)| { - // TODO [snd] this is ugly. - // in the future ethabi should return a bool - // for `is_message_value_sufficient` - // since the contract function returns a bool - let is_sufficient = U256::from(is_message_value_sufficient.0.as_slice()) == U256::from(1); - if !is_sufficient { - info!("value in message is not sufficient to cover relay costs. ignoring. message: {}", message.0.to_hex()); - } - is_sufficient - }) - .map(|((message, signatures), _)| withdraw_relay_payload(&app.home_bridge, &signatures, message)) - .map(|payload| TransactionRequest { - from: app.config.home.account, - to: Some(home_contract.clone()), - gas: Some(app.config.txs.withdraw_relay.gas.into()), - gas_price: Some(app.config.txs.withdraw_relay.gas_price.into()), - value: None, - data: Some(payload), - nonce: None, - condition: None, - }) - .map(|request| { + .map(|(message, signatures)| { + let payload = withdraw_relay_payload( + &app.home_bridge, + &signatures, + &message); + let request = TransactionRequest { + from: app.config.home.account.clone(), + to: Some(home_contract.clone()), + gas: Some(app.config.txs.withdraw_relay.gas.into()), + gas_price: Some( + helpers::u256_to_web3( + MessageToMainnet::from_bytes(message.0.as_slice()).mainnet_gas_price)), + value: None, + data: Some(payload), + nonce: None, + condition: None, + }; app.timer.timeout( api::send_transaction(&app.connections.home, request), app.config.home.request_timeout) }) .collect::>(); + info!("relaying {} withdraws", relays.len()); WithdrawRelayState::RelayWithdraws { future: join_all(relays), @@ -315,7 +257,8 @@ impl Stream for WithdrawRelay { mod tests { use rustc_hex::FromHex; use web3::types::{Log, Bytes}; - use contracts::{home, foreign}; + use contracts::{home, foreign, SIGNATURE_LENGTH}; + use message_to_mainnet::MESSAGE_LENGTH; use super::{signatures_payload, withdraw_relay_payload}; #[test] diff --git a/bridge/src/contracts.rs b/bridge/src/contracts.rs index ab727e4..d18368e 100644 --- a/bridge/src/contracts.rs +++ b/bridge/src/contracts.rs @@ -1,5 +1,4 @@ use_contract!(home, "HomeBridge", "../compiled_contracts/HomeBridge.abi"); use_contract!(foreign, "ForeignBridge", "../compiled_contracts/ForeignBridge.abi"); -pub const MESSAGE_LENGTH: usize = 116; pub const SIGNATURE_LENGTH: usize = 65; diff --git a/bridge/src/helpers.rs b/bridge/src/helpers.rs new file mode 100644 index 0000000..e573ef7 --- /dev/null +++ b/bridge/src/helpers.rs @@ -0,0 +1,10 @@ +use ethereum_types; +use web3; + +pub fn u256_to_web3(value: ethereum_types::U256) -> web3::types::U256 { + let mut bytes = [0u8; 32]; + value.to_little_endian(&mut bytes[..]); + web3::types::U256::from(&bytes[..]) +} + +// TODO test this diff --git a/bridge/src/lib.rs b/bridge/src/lib.rs index 3b8a7cf..fe30fca 100644 --- a/bridge/src/lib.rs +++ b/bridge/src/lib.rs @@ -18,6 +18,9 @@ extern crate ethabi_contract; extern crate rustc_hex; #[macro_use] extern crate log; +extern crate ethereum_types; +#[macro_use] +extern crate pretty_assertions; #[macro_use] mod macros; @@ -30,4 +33,5 @@ pub mod contracts; pub mod database; pub mod error; pub mod util; - +pub mod message_to_mainnet; +pub mod helpers; diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs new file mode 100644 index 0000000..33ce38c --- /dev/null +++ b/bridge/src/message_to_mainnet.rs @@ -0,0 +1,60 @@ +use ethereum_types::{Address, U256, H256}; +use contracts::foreign::events::Withdraw; +use rustc_hex::ToHex; +use web3::types::Log; +use ethabi::RawLog; +use error::Error; + +pub struct MessageToMainnet { + pub recipient: Address, + pub value: U256, + pub sidenet_transaction_hash: H256, + pub mainnet_gas_price: U256, +} + +pub const MESSAGE_LENGTH: usize = 116; + +impl MessageToMainnet { + pub fn from_bytes(bytes: &[u8]) -> Self { + assert_eq!(bytes.len(), MESSAGE_LENGTH); + + MessageToMainnet { + recipient: bytes[0..20].into(), + value: bytes[20..52].into(), + sidenet_transaction_hash: bytes[52..84].into(), + mainnet_gas_price: bytes[84..MESSAGE_LENGTH].into(), + } + } + + /// construct a message from a `Withdraw` that was logged on `foreign` + pub fn from_log(web3_log: Log) -> Result { + let ethabi_raw_log = RawLog { + topics: web3_log.topics.into_iter().map(|t| t.0).collect(), + data: web3_log.data.0, + }; + let withdraw_log = Withdraw::default().parse_log(ethabi_raw_log)?; + // TODO [snd] replace expect by result + let hash = web3_log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); + Ok(Self { + recipient: withdraw_log.recipient.into(), + value: withdraw_log.value.into(), + sidenet_transaction_hash: hash.to_vec().as_slice().into(), + mainnet_gas_price: withdraw_log.home_gas_price.into(), + }) + } + + /// mainly used to construct the message to be passed to + /// `submitSignature` + pub fn to_bytes(&self) -> Vec { + let mut result = vec![0u8; MESSAGE_LENGTH]; + result[0..20].copy_from_slice(&self.recipient.0[..]); + self.value.to_little_endian(&mut result[20..52]); + result[52..84].copy_from_slice(&self.sidenet_transaction_hash.0[..]); + self.mainnet_gas_price.to_little_endian(&mut result[84..MESSAGE_LENGTH]); + return result; + } + + pub fn to_hex(&self) -> String { + format!("0x{}", self.to_bytes().to_hex()) + } +} From 467c5dc2f27cce9b5e9081eb4a2a78b583d469fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 2 Feb 2018 17:14:20 +0100 Subject: [PATCH 094/152] remove contract code that dealt with removed ignoring of insufficient value withdraws --- contracts/bridge.sol | 12 ----------- truffle/test/home.js | 48 -------------------------------------------- 2 files changed, 60 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 2ff7e98..25fe679 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -222,18 +222,6 @@ contract HomeBridge { Deposit(msg.sender, msg.value); } - /// to be called by authorities to check - /// whether they withdraw message should be relayed or whether it - /// is too low to cover the cost of calling withdraw and can be ignored - function isMessageValueSufficientToCoverRelay(bytes message) public view returns (bool) { - return Message.getValue(message) > getWithdrawRelayCost(); - } - - /// an upper bound to the cost of relaying a withdraw by calling HomeBridge.withdraw - function getWithdrawRelayCost() public view returns (uint) { - return estimatedGasCostOfWithdraw * tx.gasprice; - } - /// final step of a withdraw. /// checks that `requiredSignatures` `authorities` have signed of on the `message`. /// then transfers `value` to `recipient` (both extracted from `message`). diff --git a/truffle/test/home.js b/truffle/test/home.js index f7882a6..babe95c 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -67,54 +67,6 @@ contract('HomeBridge', function(accounts) { }) }) - it("isMessageValueSufficientToCoverRelay should work correctly", function() { - var homeBridge; - var gasPrice; - var requiredSignatures = 1; - var authorities = [accounts[0], accounts[1]]; - var estimatedGasCostOfWithdraw = web3.toBigNumber(100000); - var userAccount = accounts[2]; - var recipientAccount = accounts[3]; - var estimatedWeiCostOfWithdraw; - var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; - - return HomeBridge.new( - requiredSignatures, - authorities, - estimatedGasCostOfWithdraw - ).then(function(instance) { - homeBridge = instance; - // do a test transaction so we can figure out the gasPrice - return homeBridge.sendTransaction({ - value: 1, - from: userAccount - }) - }).then(function(result) { - return web3.eth.getTransaction(result.tx); - }).then(function(tx) { - // getting the gas price dynamically instead of hardcoding it - // (which would require less code) - // is required because solidity-coverage sets it to 1 - // and the usual default is 100000000000 - gasPrice = tx.gasPrice; - estimatedWeiCostOfWithdraw = gasPrice.times(estimatedGasCostOfWithdraw); - - return homeBridge.getWithdrawRelayCost(); - }).then(function(result) { - assert(result.equals(estimatedWeiCostOfWithdraw), "getWithdrawRelayCost should return correct value"); - - var message = helpers.createMessage(recipientAccount, estimatedWeiCostOfWithdraw, transactionHash); - return homeBridge.isMessageValueSufficientToCoverRelay(message); - }).then(function(result) { - assert.equal(result, false, "exactly estimatedWeiCostOfWithdraw is not sufficient value"); - - var message = helpers.createMessage(recipientAccount, estimatedWeiCostOfWithdraw.plus(1), transactionHash); - return homeBridge.isMessageValueSufficientToCoverRelay(message); - }).then(function(result) { - assert.equal(result, true, "estimatedWeiCostOfWithdraw + 1 is sufficient value"); - }) - }) - it("should allow correct withdraw without recipient paying for gas", function() { var homeBridge; var signature; From 88a117a5ba091cea4b008f2bc6f75ba2272ea22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 2 Feb 2018 17:39:18 +0100 Subject: [PATCH 095/152] fix test helpers.createMessage: allow setting of homeGasPrice --- truffle/test/foreign.js | 12 ++++--- truffle/test/helpers/helpers.js | 5 ++- truffle/test/home.js | 55 +++++++++++++++++++-------------- truffle/test/message.js | 3 +- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index b02eebe..094cde2 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -234,7 +234,6 @@ contract('ForeignBridge', function(accounts) { // top up balance so we can transfer return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { - var homeGasPrice = 1000; return meta.transferHomeViaRelay(userAccount2, value2, homeGasPrice, { from: userAccount }); }).then(function(result) { assert.equal(2, result.logs.length) @@ -266,7 +265,8 @@ contract('ForeignBridge', function(accounts) { var authorities = [accounts[0], accounts[1]]; var recipientAccount = accounts[2]; var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; - var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, web3.toBigNumber(1000)); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); @@ -294,7 +294,8 @@ contract('ForeignBridge', function(accounts) { var authorities = [accounts[0], accounts[1]]; var recipientAccount = accounts[2]; var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; - var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, web3.toBigNumber(1000)); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); @@ -314,8 +315,9 @@ contract('ForeignBridge', function(accounts) { var authorities = [accounts[0], accounts[1]]; var recipientAccount = accounts[2]; var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; - var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, web3.toBigNumber(1000)); - var message2 = helpers.createMessage(recipientAccount, web3.toBigNumber(2000), transactionHash, web3.toBigNumber(2000)); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); + var message2 = helpers.createMessage(recipientAccount, web3.toBigNumber(2000), transactionHash, homeGasPrice); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return Promise.all([ diff --git a/truffle/test/helpers/helpers.js b/truffle/test/helpers/helpers.js index 5ebafc5..d2b44b6 100644 --- a/truffle/test/helpers/helpers.js +++ b/truffle/test/helpers/helpers.js @@ -76,9 +76,7 @@ module.exports.getBalances = getBalances; // returns hex string of the bytes of the message // composed from `recipient`, `value` and `transactionHash` // that is relayed from `foreign` to `home` on withdraw -function createMessage(recipient, value, transactionHash) { - var homeGasPrice = web3.toBigNumber(1000); - +function createMessage(recipient, value, transactionHash, homeGasPrice) { web3._extend.utils.isBigNumber(value); recipient = strip0x(recipient); assert.equal(recipient.length, 20 * 2); @@ -89,6 +87,7 @@ function createMessage(recipient, value, transactionHash) { transactionHash = strip0x(transactionHash); assert.equal(transactionHash.length, 32 * 2); + web3._extend.utils.isBigNumber(homeGasPrice); homeGasPrice = strip0x(bigNumberToPaddedBytes32(homeGasPrice)); assert.equal(homeGasPrice.length, 64); diff --git a/truffle/test/home.js b/truffle/test/home.js index babe95c..5cb8517 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -76,7 +76,8 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -101,7 +102,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - {from: userAccount, gasPrice: 1000} + {from: userAccount, gasPrice: homeGasPrice} ); }).then(function(result) { console.log("estimated gas cost of HomeBridge.withdraw =", result); @@ -112,7 +113,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - {from: userAccount, gasPrice: 1000} + {from: userAccount, gasPrice: homeGasPrice} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -137,7 +138,8 @@ contract('HomeBridge', function(accounts) { var recipientAccount = accounts[3]; var chargerAccount = accounts[4]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -166,7 +168,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - { from: relayerAccount, gasPrice: 1000 } + { from: relayerAccount, gasPrice: homeGasPrice } ); }).then(function(result) { transactionResult = result; @@ -212,7 +214,8 @@ contract('HomeBridge', function(accounts) { var recipientAccount = accounts[3]; var chargerAccount = accounts[4]; var value = estimatedGasCostOfWithdraw; - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -241,7 +244,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message, - { from: relayerAccount, gasPrice: 1000 } + { from: relayerAccount, gasPrice: homeGasPrice } ); }).then(function(result) { assert(false, "withdraw if value <= estimatedGasCostOfWithdraw should fail"); @@ -258,8 +261,9 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message1 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); - var message2 = helpers.createMessage(recipientAccount, value, "0x038c79eb958a13aa71996bac27c628f33f227288bd27d5e157b97e55e08fd2b3"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message1 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + var message2 = helpers.createMessage(recipientAccount, value, "0x038c79eb958a13aa71996bac27c628f33f227288bd27d5e157b97e55e08fd2b3", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -281,7 +285,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message1, - {from: authorities[0], gasPrice: 1000} + {from: authorities[0], gasPrice: homeGasPrice} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -297,7 +301,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message2, - {from: authorities[0], gasPrice: 1000} + {from: authorities[0], gasPrice: homeGasPrice} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -315,8 +319,9 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message1 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); - var message2 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message1 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + var message2 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -338,7 +343,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message1, - {from: authorities[0], gasPrice: 1000} + {from: authorities[0], gasPrice: homeGasPrice} ); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -354,7 +359,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message2, - {from: authorities[0], gasPrice: 1000} + {from: authorities[0], gasPrice: homeGasPrice} ); }).then(function(result) { assert(false, "should fail"); @@ -372,7 +377,8 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -389,7 +395,7 @@ contract('HomeBridge', function(accounts) { [vrs.r], [vrs.s], message.substr(0, 83), - {from: authorities[0], gasPrice: 1000} + {from: authorities[0], gasPrice: homeGasPrice} ); }).then(function(result) { assert(false, "should fail"); @@ -407,7 +413,8 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); // make message too short message = message.substr(0, 83); @@ -435,7 +442,7 @@ contract('HomeBridge', function(accounts) { [vrs.s], message, // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount, gasPrice: 1000} + {from: userAccount, gasPrice: homeGasPrice} ); }).then(function(result) { assert(false, "withdraw should fail"); @@ -452,7 +459,8 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -478,7 +486,7 @@ contract('HomeBridge', function(accounts) { [vrs.s], message, // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount, gasPrice: 1000} + {from: userAccount, gasPrice: homeGasPrice} ); }).then(function(result) { assert(false, "should fail"); @@ -495,7 +503,8 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( requiredSignatures, @@ -521,7 +530,7 @@ contract('HomeBridge', function(accounts) { [vrs.s, vrs.s], message, // anyone can call withdraw (provided they have the message and required signatures) - {from: userAccount, gasPrice: 1000} + {from: userAccount, gasPrice: homeGasPrice} ); }).then(function(result) { assert(false, "should fail"); diff --git a/truffle/test/message.js b/truffle/test/message.js index bd631db..77aeb71 100644 --- a/truffle/test/message.js +++ b/truffle/test/message.js @@ -5,7 +5,8 @@ contract("Message", function() { var recipientAccount = "0x006e27b6a72e1f34c626762f3c4761547aff1421"; var value = web3.toBigNumber(web3.toWei(1, "ether")); var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; - var message = helpers.createMessage(recipientAccount, value, transactionHash); + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, value, transactionHash, homeGasPrice); it("should extract value", function() { return Message.new().then(function(instance) { From e3bbe9eda3695d8f3fa60f0a1b4512a92c092441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 2 Feb 2018 17:39:42 +0100 Subject: [PATCH 096/152] truffle test for message: should extract homeGasPrice --- truffle/test/message.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/truffle/test/message.js b/truffle/test/message.js index 77aeb71..c782f49 100644 --- a/truffle/test/message.js +++ b/truffle/test/message.js @@ -31,4 +31,12 @@ contract("Message", function() { assert.equal(result, transactionHash); }) }) + + it("should extract homeGasPrice", function() { + return Message.new().then(function(instance) { + return instance.getHomeGasPrice.call(message) + }).then(function(result) { + assert(result.equals(homeGasPrice)); + }) + }) }) From b3760ec322134902303a605a0016cc7d4495eba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 9 Feb 2018 09:35:22 +0100 Subject: [PATCH 097/152] tests/src/lib.rs: change order of assertions to see most meaningful failure first --- tests/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 3c3dd5a..3b0ca18 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -157,6 +157,8 @@ macro_rules! test_app_stream { let stream = $init_stream(app, &$db); let res = stream.collect().wait(); + assert_eq!($expected, res.unwrap()); + assert_eq!( home.expected_requests.len(), home.requests.get(), @@ -172,8 +174,6 @@ macro_rules! test_app_stream { foreign.expected_requests.len(), foreign.requests.get() ); - - assert_eq!($expected, res.unwrap()); } } } From 9df576739b03e4771770302b3aca942d9ba9613f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 9 Feb 2018 09:36:59 +0100 Subject: [PATCH 098/152] tests/Cargo.toml: add more required deps --- tests/Cargo.toml | 3 +++ tests/tests/withdraw_relay.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/tests/Cargo.toml b/tests/Cargo.toml index a77ddb8..1dd4ca8 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -10,3 +10,6 @@ jsonrpc-core = "8.0" web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } serde_json = "1.0" pretty_assertions = "0.2.1" +ethabi = "5.0" +ethereum-types = { git = "https://github.com/paritytech/primitives.git" } +rustc-hex = "1.0" diff --git a/tests/tests/withdraw_relay.rs b/tests/tests/withdraw_relay.rs index 084ea7b..1cdddc3 100644 --- a/tests/tests/withdraw_relay.rs +++ b/tests/tests/withdraw_relay.rs @@ -1,10 +1,14 @@ extern crate futures; +#[macro_use] +extern crate serde_json; extern crate bridge; #[macro_use] extern crate tests; use bridge::bridge::create_withdraw_relay; +const COLLECTED_SIGNATURES_TOPIC: &str = "0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"; + // 1 signature required. relay polled twice. // no CollectedSignatures on ForeignBridge. // no relay. From 42993089f5c71d01f677923e51fe5a8f0f101590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 10:11:39 +0100 Subject: [PATCH 099/152] adapt to ethabi version bump --- bridge/src/bridge/withdraw_confirm.rs | 2 +- bridge/src/message_to_mainnet.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 782b7b8..887f899 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -89,7 +89,7 @@ impl Stream for WithdrawConfirm { .into_iter() .map(|message| { self.app.timer.timeout( - api::sign(&self.app.connections.foreign, self.app.config.foreign.account, message), + api::sign(&self.app.connections.foreign, self.app.config.foreign.account, Bytes(message)), self.app.config.foreign.request_timeout) }) .collect::>(); diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index 33ce38c..c2850d4 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -29,17 +29,17 @@ impl MessageToMainnet { /// construct a message from a `Withdraw` that was logged on `foreign` pub fn from_log(web3_log: Log) -> Result { let ethabi_raw_log = RawLog { - topics: web3_log.topics.into_iter().map(|t| t.0).collect(), + topics: web3_log.topics, data: web3_log.data.0, }; let withdraw_log = Withdraw::default().parse_log(ethabi_raw_log)?; // TODO [snd] replace expect by result let hash = web3_log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); Ok(Self { - recipient: withdraw_log.recipient.into(), - value: withdraw_log.value.into(), + recipient: withdraw_log.recipient.0.into(), + value: U256(withdraw_log.value.0), sidenet_transaction_hash: hash.to_vec().as_slice().into(), - mainnet_gas_price: withdraw_log.home_gas_price.into(), + mainnet_gas_price: U256(withdraw_log.home_gas_price.0), }) } From 999a4a7a7ef6ed3cccad1d654b52b4bf1f671e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:50:44 +0100 Subject: [PATCH 100/152] use ethereum_types 0.2 everywhere --- bridge/Cargo.toml | 2 +- tests/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index bc15435..fa42da4 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -18,7 +18,7 @@ ethabi-derive = "5.0" ethabi-contract = "5.0" rustc-hex = "1.0" log = "0.3" -ethereum-types = { git = "https://github.com/paritytech/primitives.git" } +ethereum-types = "0.2" pretty_assertions = "0.2.1" [dev-dependencies] diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 1dd4ca8..616d644 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -11,5 +11,5 @@ web3 = { git = "https://github.com/tomusdrw/rust-web3", branch = "bridge" } serde_json = "1.0" pretty_assertions = "0.2.1" ethabi = "5.0" -ethereum-types = { git = "https://github.com/paritytech/primitives.git" } +ethereum-types = "0.2" rustc-hex = "1.0" From 465e2d88e82b8f1d4e5756a08c4812372815de18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:51:02 +0100 Subject: [PATCH 101/152] update Cargo.lock --- Cargo.lock | 65 +++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05499c0..503ddc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,18 @@ +[root] +name = "tests" +version = "0.1.0" +dependencies = [ + "bridge 0.1.0", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", +] + [[package]] name = "aho-corasick" version = "0.5.3" @@ -65,8 +80,10 @@ dependencies = [ "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -132,7 +149,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -286,7 +303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.11.17" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -302,7 +319,7 @@ dependencies = [ "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -508,16 +525,16 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -579,7 +596,7 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -754,18 +771,6 @@ dependencies = [ "remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tests" -version = "0.1.0" -dependencies = [ - "bridge 0.1.0", - "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", -] - [[package]] name = "thread-id" version = "2.0.0" @@ -819,17 +824,17 @@ dependencies = [ "mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -845,7 +850,7 @@ dependencies = [ "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -879,7 +884,7 @@ dependencies = [ "mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -957,7 +962,7 @@ dependencies = [ "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.18 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -966,7 +971,7 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1041,7 +1046,7 @@ dependencies = [ "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e0db42a2924a5d7d628685e7a8cf9a2edd628650a9d01efc3dde35d3cdd22451" "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" -"checksum hyper 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4de6edd503089841ebfa88341e1c00fb19b6bf93d820d908db15960fd31226" +"checksum hyper 0.11.18 (registry+https://github.com/rust-lang/crates.io-index)" = "c4f9b276c87e3fc1902a8bdfcce264c3f7c8a1c35e5e0c946062739f55026664" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" @@ -1065,7 +1070,7 @@ dependencies = [ "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" -"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" +"checksum parking_lot_core 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8c47785371ae3ca397fe9eb2350e5a3ac5cfd7d329f3d9ea8375e39f1a55f377" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d510007841e87c7a6d829a36f7f0acb72aef12e38cc89073fe39810c1d976ac" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -1073,7 +1078,7 @@ dependencies = [ "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" @@ -1105,7 +1110,7 @@ dependencies = [ "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" "checksum tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "52b4e32d8edbf29501aabb3570f027c6ceb00ccef6538f4bddba0200503e74e8" -"checksum tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "514aae203178929dbf03318ad7c683126672d4d96eccb77b29603d33c9e25743" +"checksum tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b9532748772222bf70297ec0e2ad0f17213b4a7dd0e6afb68e0a0768f69f4e4f" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" From 78c6cf4472b6753f450620bb056dbc13191c3b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:51:16 +0100 Subject: [PATCH 102/152] bridge/src/helpers.rs: no longer needed --- bridge/src/helpers.rs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 bridge/src/helpers.rs diff --git a/bridge/src/helpers.rs b/bridge/src/helpers.rs deleted file mode 100644 index e573ef7..0000000 --- a/bridge/src/helpers.rs +++ /dev/null @@ -1,10 +0,0 @@ -use ethereum_types; -use web3; - -pub fn u256_to_web3(value: ethereum_types::U256) -> web3::types::U256 { - let mut bytes = [0u8; 32]; - value.to_little_endian(&mut bytes[..]); - web3::types::U256::from(&bytes[..]) -} - -// TODO test this From ed060ae85bb50dc5df411935ca018935225e6898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:54:46 +0100 Subject: [PATCH 103/152] message_to_mainnet.rs: remove to_hex, add to_payload --- bridge/src/message_to_mainnet.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index c2850d4..56cdb7e 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -1,8 +1,7 @@ use ethereum_types::{Address, U256, H256}; use contracts::foreign::events::Withdraw; -use rustc_hex::ToHex; use web3::types::Log; -use ethabi::RawLog; +use ethabi; use error::Error; pub struct MessageToMainnet { @@ -28,7 +27,7 @@ impl MessageToMainnet { /// construct a message from a `Withdraw` that was logged on `foreign` pub fn from_log(web3_log: Log) -> Result { - let ethabi_raw_log = RawLog { + let ethabi_raw_log = ethabi::RawLog { topics: web3_log.topics, data: web3_log.data.0, }; @@ -54,7 +53,7 @@ impl MessageToMainnet { return result; } - pub fn to_hex(&self) -> String { - format!("0x{}", self.to_bytes().to_hex()) + pub fn to_payload(&self) -> Vec { + ethabi::encode(&[ethabi::Token::Bytes(self.to_bytes())]) } } From b28944511c6e7b3a428f67fbd17099d259bbb0c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:55:02 +0100 Subject: [PATCH 104/152] message_to_mainnet.rs: fix from_bytes (respect little endian) --- bridge/src/message_to_mainnet.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index 56cdb7e..63bcc92 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -17,11 +17,11 @@ impl MessageToMainnet { pub fn from_bytes(bytes: &[u8]) -> Self { assert_eq!(bytes.len(), MESSAGE_LENGTH); - MessageToMainnet { + Self { recipient: bytes[0..20].into(), - value: bytes[20..52].into(), + value: U256::from_little_endian(&bytes[20..52]), sidenet_transaction_hash: bytes[52..84].into(), - mainnet_gas_price: bytes[84..MESSAGE_LENGTH].into(), + mainnet_gas_price: U256::from_little_endian(&bytes[84..MESSAGE_LENGTH]), } } From 87c57c99638fc611fa614a6db58b3cdec8174ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:57:57 +0100 Subject: [PATCH 105/152] extract code dealing with signatures into module --- bridge/src/bridge/withdraw_relay.rs | 35 ++++---------------- bridge/src/contracts.rs | 2 -- bridge/src/lib.rs | 2 +- bridge/src/signature.rs | 50 +++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 bridge/src/signature.rs diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index d1d9b89..29deed1 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -7,12 +7,12 @@ use web3::types::{U256, H256, Address, FilterBuilder, Log, Bytes, TransactionReq use ethabi::{RawLog, self}; use app::App; use api::{self, LogStream, ApiCall}; -use contracts::{home, foreign, SIGNATURE_LENGTH}; +use contracts::{home, foreign}; use util::web3_filter; use database::Database; use error::{self, Error}; use message_to_mainnet::{MessageToMainnet, MESSAGE_LENGTH}; -use helpers; +use signature::{Signature, SIGNATURE_LENGTH}; /// returns a filter for `ForeignBridge.CollectedSignatures` events fn collected_signatures_filter(foreign: &foreign::ForeignBridge, address: Address) -> FilterBuilder { @@ -56,28 +56,6 @@ fn signatures_payload(foreign: &foreign::ForeignBridge, required_signatures: u32 })) } -/// returns the payload for a transaction to `HomeBridge.withdraw(r, s, v, message)` -/// for the given `signatures` (r, s, v) and `message` -fn withdraw_relay_payload(home: &home::HomeBridge, signatures: &[Bytes], message: &Bytes) -> Bytes { - assert_eq!(message.0.len(), MESSAGE_LENGTH, "ForeignBridge never accepts messages with len != {} bytes; qed", MESSAGE_LENGTH); - let mut v_vec = Vec::new(); - let mut r_vec = Vec::new(); - let mut s_vec = Vec::new(); - for signature in signatures { - assert_eq!(signature.0.len(), SIGNATURE_LENGTH, "ForeignBridge never accepts signatures with len != {} bytes; qed", SIGNATURE_LENGTH); - let mut r = [0u8; 32]; - let mut s= [0u8; 32]; - let mut v = [0u8; 32]; - r.copy_from_slice(&signature.0[0..32]); - s.copy_from_slice(&signature.0[32..64]); - v[31] = signature.0[64]; - v_vec.push(v); - s_vec.push(s); - r_vec.push(r); - } - home.functions().withdraw().input(v_vec, r_vec, s_vec, message.0.clone()).into() -} - /// state of the withdraw relay state machine pub enum WithdrawRelayState { Wait, @@ -207,10 +185,11 @@ impl Stream for WithdrawRelay { let relays = messages.into_iter() .zip(signatures.into_iter()) .map(|(message, signatures)| { - let payload = withdraw_relay_payload( - &app.home_bridge, - &signatures, - &message); + let payload: Bytes = app.home_bridge.functions().withdraw().input( + signatures.iter().map(|x| Signature::v_from_bytes(x.0.as_slice())), + signatures.iter().map(|x| Signature::r_from_bytes(x.0.as_slice()).0), + signatures.iter().map(|x| Signature::s_from_bytes(x.0.as_slice()).0), + message.clone().0).into(); let request = TransactionRequest { from: app.config.home.account.clone(), to: Some(home_contract.clone()), diff --git a/bridge/src/contracts.rs b/bridge/src/contracts.rs index d18368e..cf41f82 100644 --- a/bridge/src/contracts.rs +++ b/bridge/src/contracts.rs @@ -1,4 +1,2 @@ use_contract!(home, "HomeBridge", "../compiled_contracts/HomeBridge.abi"); use_contract!(foreign, "ForeignBridge", "../compiled_contracts/ForeignBridge.abi"); - -pub const SIGNATURE_LENGTH: usize = 65; diff --git a/bridge/src/lib.rs b/bridge/src/lib.rs index fe30fca..61f14bc 100644 --- a/bridge/src/lib.rs +++ b/bridge/src/lib.rs @@ -34,4 +34,4 @@ pub mod database; pub mod error; pub mod util; pub mod message_to_mainnet; -pub mod helpers; +pub mod signature; diff --git a/bridge/src/signature.rs b/bridge/src/signature.rs new file mode 100644 index 0000000..0304fcc --- /dev/null +++ b/bridge/src/signature.rs @@ -0,0 +1,50 @@ +/// ECDSA signatures: +/// conversion from/to byte vectors. +/// from/to v, r, s components. + +use ethereum_types::{Address, U256, H256}; +use ethabi; + +pub const SIGNATURE_LENGTH: usize = 65; + +pub struct Signature { + pub v: u8, + pub r: H256, + pub s: H256, +} + +impl Signature { + pub fn from_bytes(bytes: &[u8]) -> Self { + assert_eq!(bytes.len(), SIGNATURE_LENGTH); + + Self { + v: Self::v_from_bytes(bytes), + r: Self::r_from_bytes(bytes), + s: Self::s_from_bytes(bytes), + } + } + + pub fn v_from_bytes(bytes: &[u8]) -> u8 { + bytes[64] + } + + pub fn r_from_bytes(bytes: &[u8]) -> H256 { + bytes[0..32].into() + } + + pub fn s_from_bytes(bytes: &[u8]) -> H256 { + bytes[32..64].into() + } + + pub fn to_bytes(&self) -> Vec { + let mut result = vec![0u8; SIGNATURE_LENGTH]; + result[0..32].copy_from_slice(&self.r.0[..]); + result[32..64].copy_from_slice(&self.s.0[..]); + result[64] = self.v; + return result; + } + + pub fn to_payload(&self) -> Vec { + ethabi::encode(&[ethabi::Token::Bytes(self.to_bytes())]) + } +} From be18c96d3124a24b5d42a4982997f4a2d7748264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 14:58:14 +0100 Subject: [PATCH 106/152] remove conversion (web3 -> ethabi) that is no longer needed (ethereum-types) --- bridge/src/bridge/withdraw_relay.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 29deed1..6f58537 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -194,9 +194,7 @@ impl Stream for WithdrawRelay { from: app.config.home.account.clone(), to: Some(home_contract.clone()), gas: Some(app.config.txs.withdraw_relay.gas.into()), - gas_price: Some( - helpers::u256_to_web3( - MessageToMainnet::from_bytes(message.0.as_slice()).mainnet_gas_price)), + gas_price: Some(MessageToMainnet::from_bytes(message.0.as_slice()).mainnet_gas_price), value: None, data: Some(payload), nonce: None, From d7928c22cc7a2b5c92f692d48967ebab7b09ff74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 15:09:38 +0100 Subject: [PATCH 107/152] tests/tests/withdraw_relay.rs: refactor: replace opaque data strings by something easily modifiable (json, ethabi use) --- tests/tests/withdraw_relay.rs | 297 ++++++++++++---------------------- 1 file changed, 106 insertions(+), 191 deletions(-) diff --git a/tests/tests/withdraw_relay.rs b/tests/tests/withdraw_relay.rs index 1cdddc3..b7661e7 100644 --- a/tests/tests/withdraw_relay.rs +++ b/tests/tests/withdraw_relay.rs @@ -1,11 +1,22 @@ +/// test interactions of withdraw_relay state machine with RPC + extern crate futures; #[macro_use] extern crate serde_json; extern crate bridge; #[macro_use] extern crate tests; +extern crate ethabi; +extern crate ethereum_types; +extern crate rustc_hex; + +use ethereum_types::{U256, H256}; +use rustc_hex::ToHex; use bridge::bridge::create_withdraw_relay; +use bridge::message_to_mainnet::MessageToMainnet; +use bridge::signature::Signature; +use bridge::contracts; const COLLECTED_SIGNATURES_TOPIC: &str = "0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"; @@ -33,17 +44,29 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[COLLECTED_SIGNATURES_TOPIC], null, null, null] + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics": [[COLLECTED_SIGNATURES_TOPIC], null, null, null] + }]), + res => json!([]); ] } @@ -72,179 +95,31 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[COLLECTED_SIGNATURES_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x0000000000000000000000000000000000000000", + "topics": [COLLECTED_SIGNATURES_TOPIC], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); ] } // 2 signatures required. relay polled twice. -// single CollectedSignatures log present. message value covers relay cost. +// single CollectedSignatures log present. // message gets relayed. test_app_stream! { name => withdraw_relay_single_log_sufficient_value_relay, - database => Database::default(), - home => - account => "0000000000000000000000000000000000000001", - confirmations => 12; - foreign => - account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", - confirmations => 12; - authorities => - accounts => [ - "0000000000000000000000000000000000000001", - "0000000000000000000000000000000000000002", - ], - signatures => 2; - txs => Transactions::default(), - init => |app, db| create_withdraw_relay(app, db).take(1), - expected => vec![0x1005], - home_transport => [ - // call to `isValueInMessageLargeEnoughToCoverWithdrawCost` - "eth_call" => - req => r#"[{"data":"0x6498d59000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - // respond with `true` - res => r#""0x0000000000000000000000000000000000000000000000000000000000000001""#; - // `withdraw` - "eth_sendTransaction" => - req => r#"[{"data":"0x9ce318f6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","from":"0x0000000000000000000000000000000000000001","gas":"0x0","gasPrice":"0x0","to":"0x0000000000000000000000000000000000000000"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; - ], - foreign_transport => [ - "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; - "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; - // call to `message` - "eth_call" => - req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; - // calls to `signature` - "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; - "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; - ] -} - -// 2 signatures required. relay polled twice. -// single CollectedSignatures log present. message value doesn't cover cost. -// message is ignored. -test_app_stream! { - name => withdraw_relay_single_log_insufficient_value_no_relay, - database => Database::default(), - home => - account => "0000000000000000000000000000000000000001", - confirmations => 12; - foreign => - account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", - confirmations => 12; - authorities => - accounts => [ - "0000000000000000000000000000000000000001", - "0000000000000000000000000000000000000002", - ], - signatures => 2; - txs => Transactions::default(), - init => |app, db| create_withdraw_relay(app, db).take(1), - expected => vec![0x1005], - home_transport => [ - // call to `isValueInMessageLargeEnoughToCoverWithdrawCost` - "eth_call" => - req => r#"[{"data":"0x6498d59000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - // respond with `false` - res => r#""0x0000000000000000000000000000000000000000000000000000000000000000""#; - // no `withdraw` - ], - foreign_transport => [ - "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; - "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; - // call to `message` - "eth_call" => - req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; - // calls to `signature` - "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; - "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; - ] -} - -// like `withdraw_relay_single_log_sufficient_value_relay` -// but with explicit gas -test_app_stream! { - name => withdraw_relay_explicit_gas, - database => Database::default(), - home => - account => "0000000000000000000000000000000000000001", - confirmations => 12; - foreign => - account => "aff3454fce5edbc8cca8697c15331677e6ebcccc", - confirmations => 12; - authorities => - accounts => [ - "0000000000000000000000000000000000000001", - "0000000000000000000000000000000000000002", - ], - signatures => 2; - txs => Transactions { - withdraw_relay: TransactionConfig { - gas: 0x10, - gas_price: 0x20, - }, - ..Default::default() - }, - init => |app, db| create_withdraw_relay(app, db).take(1), - expected => vec![0x1005], - home_transport => [ - // call to `isValueInMessageLargeEnoughToCoverWithdrawCost` - "eth_call" => - req => r#"[{"data":"0x6498d59000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - // true - res => r#""0x0000000000000000000000000000000000000000000000000000000000000001""#; - // `withdraw` - "eth_sendTransaction" => - req => r#"[{"data":"0x9ce318f6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","from":"0x0000000000000000000000000000000000000001","gas":"0x10","gasPrice":"0x20","to":"0x0000000000000000000000000000000000000000"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; - ], - foreign_transport => [ - "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; - "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[{"address":"0x0000000000000000000000000000000000000000","topics":["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; - // call to `message` - "eth_call" => - req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; - // calls to `signature` - "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; - "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000000"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; - ] -} - -// like `withdraw_relay_single_log_sufficient_value_relay` -// but with explicit contract addresses -test_app_stream! { - name => withdraw_relay_single_explicit_contract_addresses, database => Database { home_contract_address: "00000000000000000000000000000000000000dd".into(), foreign_contract_address: "00000000000000000000000000000000000000ee".into(), @@ -266,33 +141,73 @@ test_app_stream! { init => |app, db| create_withdraw_relay(app, db).take(1), expected => vec![0x1005], home_transport => [ - // call to `isValueInMessageLargeEnoughToCoverWithdrawCost` - "eth_call" => - req => r#"[{"data":"0x6498d59000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","to":"0x00000000000000000000000000000000000000dd"},"latest"]"#, - // true - res => r#""0x0000000000000000000000000000000000000000000000000000000000000001""#; - // `withdraw` + // `HomeBridge.withdraw` "eth_sendTransaction" => - req => r#"[{"data":"0x9ce318f6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000","from":"0x0000000000000000000000000000000000000001","gas":"0x0","gasPrice":"0x0","to":"0x00000000000000000000000000000000000000dd"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": format!("0x{}", contracts::home::HomeBridge::default() + .functions() + .withdraw() + .input( + vec![U256::from(1), U256::from(4)], + vec![H256::from(2), H256::from(5)], + vec![H256::from(3), H256::from(6)], + MessageToMainnet { + recipient: [1u8; 20].into(), + value: 10000.into(), + sidenet_transaction_hash: "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 1000.into(), + }.to_bytes() + ).to_hex()), + "from": "0x0000000000000000000000000000000000000001", + "gas": "0x0", + "gasPrice": "0x3e8", + "to": "0x00000000000000000000000000000000000000dd" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); ], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x00000000000000000000000000000000000000ee"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],null,null,null]}]"#, - res => r#"[{"address":"0x00000000000000000000000000000000000000ee","topics":["0xeb043d149eedb81369bec43d4c3a3a53087debc88d2525f13bfaa3eecda28b5c"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x00000000000000000000000000000000000000ee"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[COLLECTED_SIGNATURES_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x00000000000000000000000000000000000000ee", + "topics": [COLLECTED_SIGNATURES_TOPIC], + "data": "0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0", + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); // call to `message` "eth_call" => - req => r#"[{"data":"0x490a32c600000000000000000000000000000000000000000000000000000000000000f0","to":"0x00000000000000000000000000000000000000ee"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000""#; + req => json!([{ + "data": "0x490a32c600000000000000000000000000000000000000000000000000000000000000f0", + "to": "0x00000000000000000000000000000000000000ee" + }, "latest"]), + res => json!(format!("0x{}", MessageToMainnet { + recipient: [1u8; 20].into(), + value: 10000.into(), + sidenet_transaction_hash: "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 1000.into(), + }.to_payload().to_hex())); // calls to `signature` "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000","to":"0x00000000000000000000000000000000000000ee"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000""#; + req => json!([{ + "data": "0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000", + "to": "0x00000000000000000000000000000000000000ee" + },"latest"]), + res => json!(format!("0x{}", Signature { v: 1, r: 2.into(), s: 3.into() }.to_payload().to_hex())); "eth_call" => - req => r#"[{"data":"0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001","to":"0x00000000000000000000000000000000000000ee"},"latest"]"#, - res => r#""0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000""#; + req => json!([{ + "data": "0x1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001", + "to": "0x00000000000000000000000000000000000000ee" + },"latest"]), + res => json!(format!("0x{}", Signature { v: 4, r: 5.into(), s: 6.into() }.to_payload().to_hex())); ] } From 4a3b4ba1f005fdc336ef76e4df80a6bcf7e7acd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 15:23:41 +0100 Subject: [PATCH 108/152] remove test for function that doesn't exist anymore --- bridge/src/bridge/withdraw_relay.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 6f58537..18f9766 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -279,18 +279,4 @@ mod tests { let assignment = signatures_payload(&foreign, 2, my_address, log).unwrap(); assert_eq!(None, assignment); } - - #[test] - fn test_withdraw_relay_payload() { - let home = home::HomeBridge::default(); - let signatures: Vec = vec![ - vec![0x11; SIGNATURE_LENGTH].into(), - vec![0x22; SIGNATURE_LENGTH].into(), - ]; - let message: Bytes = vec![0x33; MESSAGE_LENGTH].into(); - - let payload = withdraw_relay_payload(&home, &signatures, &message); - let expected: Bytes = "9ce318f6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000002111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000054333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333000000000000000000000000".from_hex().unwrap().into(); - assert_eq!(expected, payload); - } } From c887668edae5a4d60a4b70d452ccf75163ebe297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 15:24:23 +0100 Subject: [PATCH 109/152] remove tests for withdraw confirm payloads - they test against raw hex strings - hard to modify - if we me it easier to modify by using ethabi to assemble data the tests essentially become useless - logic should already be covered by both integration test and RPC tests --- bridge/src/bridge/withdraw_confirm.rs | 37 --------------------------- 1 file changed, 37 deletions(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 887f899..96ca465 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -154,40 +154,3 @@ impl Stream for WithdrawConfirm { } } } - -#[cfg(test)] -mod tests { - use rustc_hex::FromHex; - use web3::types::{Log, Bytes}; - use contracts::foreign; - use super::{withdraw_confirm_sign_payload, withdraw_submit_signature_payload}; - - #[test] - fn test_withdraw_confirm_sign_payload() { - let foreign = foreign::ForeignBridge::default(); - - let data = "000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0".from_hex().unwrap(); - let log = Log { - data: data.into(), - topics: vec!["884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()], - transaction_hash: Some("884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into()), - ..Default::default() - }; - - let payload = withdraw_confirm_sign_payload(&foreign, log).unwrap(); - let expected: Bytes = "aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".from_hex().unwrap().into(); - assert_eq!(expected, payload); - } - - #[test] - fn test_withdraw_submit_signature_payload() { - let foreign = foreign::ForeignBridge::default(); - - let message: Bytes = "aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".from_hex().unwrap().into(); - let signature = "8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc".into(); - - let payload = withdraw_submit_signature_payload(&foreign, message, signature); - let expected: Bytes = "630cea8e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000418697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364000000000000000000000000".from_hex().unwrap().into(); - assert_eq!(expected, payload); - } -} From 8ab895664a1645e01e1634645c21281701f2eb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 15:35:06 +0100 Subject: [PATCH 110/152] integration-tests: set home_gas_price to 0 to make it pass for now --- integration-tests/tests/basic_deposit_then_withdraw.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/tests/basic_deposit_then_withdraw.rs b/integration-tests/tests/basic_deposit_then_withdraw.rs index 6f4efcd..13f3752 100644 --- a/integration-tests/tests/basic_deposit_then_withdraw.rs +++ b/integration-tests/tests/basic_deposit_then_withdraw.rs @@ -239,7 +239,7 @@ fn test_basic_deposit_then_withdraw() { .input( Address::from(user_address), U256::from(100000), - U256::from(1)); + U256::from(0)); let future = foreign_eth.send_transaction(web3::types::TransactionRequest{ from: address_from_str(user_address), to: Some(address_from_str(foreign_contract_address)), From 3cc6b294385c4c8a4abc0f66efc12acc2fc9f497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 16:15:19 +0100 Subject: [PATCH 111/152] tests/tests/withdraw_confirm.rs: refactor: replace opaque data strings by something easily modifiable (json, ethabi use) --- tests/tests/withdraw_confirm.rs | 305 ++++++++++++++++++++++++++------ 1 file changed, 247 insertions(+), 58 deletions(-) diff --git a/tests/tests/withdraw_confirm.rs b/tests/tests/withdraw_confirm.rs index d8a3f9f..d48ae67 100644 --- a/tests/tests/withdraw_confirm.rs +++ b/tests/tests/withdraw_confirm.rs @@ -1,9 +1,22 @@ +/// test interactions of withdraw_confirm state machine with RPC + extern crate futures; +#[macro_use] +extern crate serde_json; extern crate bridge; #[macro_use] extern crate tests; +extern crate ethabi; +extern crate rustc_hex; +extern crate ethereum_types; +use rustc_hex::{ToHex, FromHex}; use bridge::bridge::create_withdraw_confirm; +use bridge::message_to_mainnet::MessageToMainnet; +use bridge::contracts; +use ethabi::{encode, Token}; + +const WITHDRAW_TOPIC: &str = "0xf279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568"; test_app_stream! { name => withdraw_confirm_basic, @@ -26,17 +39,29 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1","limit":null,"toBlock":"0x1005","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x1005", + "topics": [[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics":[[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([]); ] } @@ -64,20 +89,31 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x0100""#; + req => json!([]), + res => json!("0x0100"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0xf6","limit":null,"toBlock":"0x1005","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address":["0x0000000000000000000000000000000000000000"], + "fromBlock": "0xf6", + "limit": null, "toBlock": "0x1005", + "topics": [[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x0000000000000000000000000000000000000000"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address":["0x0000000000000000000000000000000000000000"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics":[[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([]); ] } @@ -107,20 +143,32 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x0100""#; + req => json!([]), + res => json!("0x0100"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"],"fromBlock":"0xf6","limit":null,"toBlock":"0x1005","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"], + "fromBlock": "0xf6", + "limit": null, + "toBlock": "0x1005", + "topics":[[WITHDRAW_TOPIC],null,null,null] + }]), + res => json!([]); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics":[[WITHDRAW_TOPIC],null,null,null] + }]), + res => json!([]); ] } @@ -156,26 +204,77 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x0100""#; + req => json!([]), + res => json!("0x0100"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1011""#; + req => json!([]), + res => json!("0x1011"); "eth_getLogs" => - req => r#"[{"address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"],"fromBlock":"0xf6","limit":null,"toBlock":"0x1005","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[{"address":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8","topics":["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}]"#; + req => json!([{ + "address": ["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"], + "fromBlock": "0xf6", + "limit": null, + "toBlock": "0x1005", + "topics": [[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8", + "topics": [WITHDRAW_TOPIC], + "data": format!("0x{}", encode(&[ + Token::Address([1u8; 20].into()), + Token::Uint(10000.into()), + Token::Uint(1000.into()), + ]).to_hex()), + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); "eth_sign" => - req => r#"["0x0000000000000000000000000000000000000001","0xaff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"]"#, - res => r#""0x8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc""#; + req => json!([ + "0x0000000000000000000000000000000000000001", + format!("0x{}", MessageToMainnet { + recipient: [1u8; 20].into(), + value: 10000.into(), + sidenet_transaction_hash: "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 1000.into(), + } + .to_bytes() + .to_hex()) + ]), + res => json!("0x8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc"); + // `submitSignature` "eth_sendTransaction" => - req => r#"[{"data":"0x630cea8e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000418697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364000000000000000000000000","from":"0x0000000000000000000000000000000000000001","gas":"0xfe","gasPrice":"0xa1","to":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": format!("0x{}", contracts::foreign::ForeignBridge::default() + .functions() + .submit_signature() + .input( + "8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc".from_hex().unwrap(), + MessageToMainnet { + recipient: [1u8; 20].into(), + value: 10000.into(), + sidenet_transaction_hash: "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 1000.into(), + }.to_bytes() + ) + .to_hex()), + "from": "0x0000000000000000000000000000000000000001", + "gas": "0xfe", + "gasPrice": "0xa1", + "to":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"],"fromBlock":"0x1006","limit":null,"toBlock":"0x1006","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"], + "fromBlock": "0x1006", + "limit": null, + "toBlock": "0x1006", + "topics":[[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([]); ] } @@ -210,28 +309,118 @@ test_app_stream! { home_transport => [], foreign_transport => [ "eth_blockNumber" => - req => r#"[]"#, - res => r#""0xe""#; + req => json!([]), + res => json!("0xe"); "eth_getLogs" => - req => r#"[{"address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"],"fromBlock":"0x1","limit":null,"toBlock":"0x2","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[{"address":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8","topics":["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],"data":"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"},{"address":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8","topics":["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],"data":"0x000000000000000000000000001da5bcab735024168f00b43abcc9ef522392e90000000000000000000000000000000000000000000000000000000000000099","type":"","transactionHash":"0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424399"}]"#; + req => json!([{ + "address": ["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"], + "fromBlock": "0x1", + "limit": null, + "toBlock": "0x2", + "topics": [[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([{ + "address": "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8", + "topics": [WITHDRAW_TOPIC], + "data": format!("0x{}", encode(&[ + Token::Address([1u8; 20].into()), + Token::Uint(10000.into()), + Token::Uint(1000.into()), + ]).to_hex()), + "type": "", + "transactionHash": "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"}, + { + "address":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8", + "topics": [WITHDRAW_TOPIC], + "data": format!("0x{}", encode(&[ + Token::Address([2u8; 20].into()), + Token::Uint(42.into()), + Token::Uint(100.into()), + ]).to_hex()), + "type":"", + "transactionHash":"0xfffedad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364" + }]); "eth_sign" => - req => r#"["0x0000000000000000000000000000000000000001","0xaff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"]"#, - res => r#""0x8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc""#; + req => json!([ + "0x0000000000000000000000000000000000000001", + format!("0x{}", MessageToMainnet { + recipient: [1u8; 20].into(), + value: 10000.into(), + sidenet_transaction_hash: "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 1000.into(), + } + .to_bytes() + .to_hex()) + ]), + res => json!("0x8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc"); "eth_sign" => - req => r#"["0x0000000000000000000000000000000000000001","0x001da5bcab735024168f00b43abcc9ef522392e90000000000000000000000000000000000000000000000000000000000000099884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424399"]"#, - res => r#""0x8a3b24c56e46f6fc9fa7ed14795745348059b8ac84d6ee93323e83a429e760ae6e89510834ee4d65eefacd74cddca53df61b5eba1c3007ed88d2eebff2e0e2151b""#; + req => json!([ + "0x0000000000000000000000000000000000000001", + format!("0x{}", MessageToMainnet { + recipient: [2u8; 20].into(), + value: 42.into(), + sidenet_transaction_hash: "0xfffedad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 100.into(), + } + .to_bytes() + .to_hex()) + ]), + res => json!("0x8a3b24c56e46f6fc9fa7ed14795745348059b8ac84d6ee93323e83a429e760ae6e89510834ee4d65eefacd74cddca53df61b5eba1c3007ed88d2eebff2e0e2151b"); + // `submitSignature` "eth_sendTransaction" => - req => r#"[{"data":"0x630cea8e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000418697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364000000000000000000000000","from":"0x0000000000000000000000000000000000000001","gas":"0xff","gasPrice":"0xaa","to":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b""#; + req => json!([{ + "data": format!("0x{}", contracts::foreign::ForeignBridge::default() + .functions() + .submit_signature() + .input( + "8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677aff3454fce5edbc8cca8697c15331677e6ebccccaff3454fce5edbc8cca8697c15331677e6ebc".from_hex().unwrap(), + MessageToMainnet { + recipient: [1u8; 20].into(), + value: 10000.into(), + sidenet_transaction_hash: "0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 1000.into(), + }.to_bytes() + ) + .to_hex()), + "from": "0x0000000000000000000000000000000000000001", + "gas": "0xff", + "gasPrice": "0xaa", + "to":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0b"); + // `submitSignature` "eth_sendTransaction" => - req => r#"[{"data":"0x630cea8e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000418a3b24c56e46f6fc9fa7ed14795745348059b8ac84d6ee93323e83a429e760ae6e89510834ee4d65eefacd74cddca53df61b5eba1c3007ed88d2eebff2e0e2151b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054001da5bcab735024168f00b43abcc9ef522392e90000000000000000000000000000000000000000000000000000000000000099884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424399000000000000000000000000","from":"0x0000000000000000000000000000000000000001","gas":"0xff","gasPrice":"0xaa","to":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"}]"#, - res => r#""0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0c""#; + req => json!([{ + "data": format!("0x{}", contracts::foreign::ForeignBridge::default() + .functions() + .submit_signature() + .input( + "8a3b24c56e46f6fc9fa7ed14795745348059b8ac84d6ee93323e83a429e760ae6e89510834ee4d65eefacd74cddca53df61b5eba1c3007ed88d2eebff2e0e2151b".from_hex().unwrap(), + MessageToMainnet { + recipient: [2u8; 20].into(), + value: 42.into(), + sidenet_transaction_hash: "0xfffedad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364".into(), + mainnet_gas_price: 100.into(), + }.to_bytes() + ) + .to_hex()), + "from": "0x0000000000000000000000000000000000000001", + "gas": "0xff", + "gasPrice": "0xaa", + "to":"0x49edf201c1e139282643d5e7c6fb0c7219ad1db8" + }]), + res => json!("0x1db8f385535c0d178b8f40016048f3a3cffee8f94e68978ea4b277f57b638f0c"); "eth_blockNumber" => - req => r#"[]"#, - res => r#""0x1012""#; + req => json!([]), + res => json!("0x1012"); "eth_getLogs" => - req => r#"[{"address":["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"],"fromBlock":"0x3","limit":null,"toBlock":"0x1006","topics":[["0x884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364"],null,null,null]}]"#, - res => r#"[]"#; + req => json!([{ + "address": ["0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"], + "fromBlock": "0x3", + "limit": null, + "toBlock": "0x1006", + "topics":[[WITHDRAW_TOPIC], null, null, null] + }]), + res => json!([]); ] } From 5b446b48a3f70690fe9c00f766b9d243d095b882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 16:35:36 +0100 Subject: [PATCH 112/152] remove `use` of symbols that no longer exist --- bridge/src/bridge/withdraw_relay.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 18f9766..fb7850a 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -234,9 +234,9 @@ impl Stream for WithdrawRelay { mod tests { use rustc_hex::FromHex; use web3::types::{Log, Bytes}; - use contracts::{home, foreign, SIGNATURE_LENGTH}; + use contracts::{home, foreign}; use message_to_mainnet::MESSAGE_LENGTH; - use super::{signatures_payload, withdraw_relay_payload}; + use super::signatures_payload; #[test] fn test_signatures_payload() { From a3740a567295d09a1561faa68f28a145e02493d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 16:39:59 +0100 Subject: [PATCH 113/152] test/foreign: add missing variable homeGasPrice --- truffle/test/foreign.js | 1 + 1 file changed, 1 insertion(+) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 094cde2..d564ad6 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -229,6 +229,7 @@ contract('ForeignBridge', function(accounts) { var value = web3.toWei(3, "ether"); var value2 = web3.toWei(1, "ether"); var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; // top up balance so we can transfer From e667321760b6a0b68498d2eea62ecd15e1b0e264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 17:17:05 +0100 Subject: [PATCH 114/152] truffle tests fail on travis only :/ trying something --- truffle/test/home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/test/home.js b/truffle/test/home.js index 5cb8517..875e55c 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -76,7 +76,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(0); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( From 71fed91200aa072752544a08cb00319ac793da99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 17:39:56 +0100 Subject: [PATCH 115/152] test/home: trying lower gas price in to not fail when computing coverage --- truffle/test/home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/test/home.js b/truffle/test/home.js index 875e55c..7a91f46 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -138,7 +138,7 @@ contract('HomeBridge', function(accounts) { var recipientAccount = accounts[3]; var chargerAccount = accounts[4]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( From 4c63d4469e1a748c6d093b378454824abb67ecc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 17:55:07 +0100 Subject: [PATCH 116/152] test/home: reduce homeGasPrice everywhere to keep coverage test from failing --- truffle/test/home.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/truffle/test/home.js b/truffle/test/home.js index 7a91f46..bf0cd2d 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -214,7 +214,7 @@ contract('HomeBridge', function(accounts) { var recipientAccount = accounts[3]; var chargerAccount = accounts[4]; var value = estimatedGasCostOfWithdraw; - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( @@ -261,7 +261,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message1 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); var message2 = helpers.createMessage(recipientAccount, value, "0x038c79eb958a13aa71996bac27c628f33f227288bd27d5e157b97e55e08fd2b3", homeGasPrice); @@ -319,7 +319,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message1 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); var message2 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); @@ -377,7 +377,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( @@ -413,7 +413,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); // make message too short message = message.substr(0, 83); @@ -459,7 +459,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( @@ -503,7 +503,7 @@ contract('HomeBridge', function(accounts) { var userAccount = accounts[2]; var recipientAccount = accounts[3]; var value = web3.toBigNumber(web3.toWei(1, "ether")); - var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice = web3.toBigNumber(10000); var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); return HomeBridge.new( From dfb7fef654a28174f945743f9fb4fa96e9947950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 19:14:57 +0100 Subject: [PATCH 117/152] bridge/src/signature.rs: 100% test coverage with quickcheck --- Cargo.lock | 22 ++++++++++++++++++++++ bridge/Cargo.toml | 1 + bridge/src/lib.rs | 3 +++ bridge/src/signature.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 503ddc3..323b240 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,6 +84,7 @@ dependencies = [ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -169,6 +170,15 @@ dependencies = [ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.11.0" @@ -552,6 +562,16 @@ dependencies = [ "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quickcheck" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.3.15" @@ -1031,6 +1051,7 @@ dependencies = [ "checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8385a48c8ed984778dcca27efc0de162a191a14ed733a41a07d9b0cfaa999e" "checksum ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2263c24359e827348ac99aa1f2e28ba5bab0d6c0b83941fa252de8a9e9c073" @@ -1073,6 +1094,7 @@ dependencies = [ "checksum parking_lot_core 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8c47785371ae3ca397fe9eb2350e5a3ac5cfd7d329f3d9ea8375e39f1a55f377" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d510007841e87c7a6d829a36f7f0acb72aef12e38cc89073fe39810c1d976ac" +"checksum quickcheck 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15cda2c09a11b72e8563c57760dd5cf8b1fb3bb595df5759b5653048ab04e030" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index fa42da4..5e9120a 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -23,3 +23,4 @@ pretty_assertions = "0.2.1" [dev-dependencies] tempdir = "0.3" +quickcheck = "0.6.1" diff --git a/bridge/src/lib.rs b/bridge/src/lib.rs index 61f14bc..aa1b0df 100644 --- a/bridge/src/lib.rs +++ b/bridge/src/lib.rs @@ -21,6 +21,9 @@ extern crate log; extern crate ethereum_types; #[macro_use] extern crate pretty_assertions; +#[cfg(test)] +#[macro_use] +extern crate quickcheck; #[macro_use] mod macros; diff --git a/bridge/src/signature.rs b/bridge/src/signature.rs index 0304fcc..e41c488 100644 --- a/bridge/src/signature.rs +++ b/bridge/src/signature.rs @@ -7,6 +7,8 @@ use ethabi; pub const SIGNATURE_LENGTH: usize = 65; +/// an ECDSA signature consisting of `v`, `r` and `s` +#[derive(PartialEq, Debug)] pub struct Signature { pub v: u8, pub r: H256, @@ -48,3 +50,41 @@ impl Signature { ethabi::encode(&[ethabi::Token::Bytes(self.to_bytes())]) } } + +#[cfg(test)] +mod test { + use quickcheck::TestResult; + use super::*; + + quickcheck! { + fn quickcheck_signature_roundtrips(v: u8, r_raw: Vec, s_raw: Vec) -> TestResult { + if r_raw.len() != 32 || s_raw.len() != 32 { + return TestResult::discard(); + } + + let r: H256 = r_raw.as_slice().into(); + let s: H256 = s_raw.as_slice().into(); + let signature = Signature { v, r, s }; + assert_eq!(v, signature.v); + assert_eq!(r, signature.r); + assert_eq!(s, signature.s); + + let bytes = signature.to_bytes(); + assert_eq!(v, Signature::v_from_bytes(bytes.as_slice())); + assert_eq!(r, Signature::r_from_bytes(bytes.as_slice())); + assert_eq!(s, Signature::s_from_bytes(bytes.as_slice())); + + let signature2 = Signature::from_bytes(bytes.as_slice()); + assert_eq!(signature, signature2); + + let payload = signature.to_payload(); + let mut tokens = ethabi::decode(&[ethabi::ParamType::Bytes], payload.as_slice()) + .unwrap(); + let decoded = tokens.pop().unwrap().to_bytes().unwrap(); + + assert_eq!(signature, Signature::from_bytes(decoded.as_slice())); + + TestResult::passed() + } + } +} From 1de9a53d1e0b6a5b5ccf45dc7de2850e9f4227ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 19:31:46 +0100 Subject: [PATCH 118/152] slightly simplify test for signature roundtrips --- bridge/src/signature.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bridge/src/signature.rs b/bridge/src/signature.rs index e41c488..55e99e5 100644 --- a/bridge/src/signature.rs +++ b/bridge/src/signature.rs @@ -74,14 +74,12 @@ mod test { assert_eq!(r, Signature::r_from_bytes(bytes.as_slice())); assert_eq!(s, Signature::s_from_bytes(bytes.as_slice())); - let signature2 = Signature::from_bytes(bytes.as_slice()); - assert_eq!(signature, signature2); + assert_eq!(signature, Signature::from_bytes(bytes.as_slice())); let payload = signature.to_payload(); let mut tokens = ethabi::decode(&[ethabi::ParamType::Bytes], payload.as_slice()) .unwrap(); let decoded = tokens.pop().unwrap().to_bytes().unwrap(); - assert_eq!(signature, Signature::from_bytes(decoded.as_slice())); TestResult::passed() From 12eea5053f5ecd4f34ee586d53756ebb660d235c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Mon, 12 Feb 2018 19:32:09 +0100 Subject: [PATCH 119/152] quickcheck test that MessageToMainnet roundtrips from/to bytes and payload --- bridge/src/message_to_mainnet.rs | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index 63bcc92..fc2c37f 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -4,6 +4,7 @@ use web3::types::Log; use ethabi; use error::Error; +#[derive(PartialEq, Debug)] pub struct MessageToMainnet { pub recipient: Address, pub value: U256, @@ -57,3 +58,45 @@ impl MessageToMainnet { ethabi::encode(&[ethabi::Token::Bytes(self.to_bytes())]) } } + +#[cfg(test)] +mod test { + use quickcheck::TestResult; + use super::*; + + quickcheck! { + fn quickcheck_message_to_mainnet_roundtrips_to_bytes( + recipient_raw: Vec, + value_raw: u64, + sidenet_transaction_hash_raw: Vec, + mainnet_gas_price_raw: u64 + ) -> TestResult { + if recipient_raw.len() != 20 || sidenet_transaction_hash_raw.len() != 32 { + return TestResult::discard(); + } + + let recipient: Address = recipient_raw.as_slice().into(); + let value: U256 = value_raw.into(); + let sidenet_transaction_hash: H256 = sidenet_transaction_hash_raw.as_slice().into(); + let mainnet_gas_price: U256 = mainnet_gas_price_raw.into(); + + let message = MessageToMainnet { + recipient, + value, + sidenet_transaction_hash, + mainnet_gas_price + }; + + let bytes = message.to_bytes(); + assert_eq!(message, MessageToMainnet::from_bytes(bytes.as_slice())); + + let payload = message.to_payload(); + let mut tokens = ethabi::decode(&[ethabi::ParamType::Bytes], payload.as_slice()) + .unwrap(); + let decoded = tokens.pop().unwrap().to_bytes().unwrap(); + assert_eq!(message, MessageToMainnet::from_bytes(decoded.as_slice())); + + TestResult::passed() + } + } +} From d42f4b959054edd38ee53d3238d73e85c60aa5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 09:23:48 +0100 Subject: [PATCH 120/152] Cargo.lock: use newest cargo which doesn't add `root` addresses https://github.com/paritytech/parity-bridge/pull/114#discussion_r167784460 --- Cargo.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 323b240..9809c48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,3 @@ -[root] -name = "tests" -version = "0.1.0" -dependencies = [ - "bridge 0.1.0", - "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", -] - [[package]] name = "aho-corasick" version = "0.5.3" @@ -791,6 +776,21 @@ dependencies = [ "remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tests" +version = "0.1.0" +dependencies = [ + "bridge 0.1.0", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", +] + [[package]] name = "thread-id" version = "2.0.0" From d9090d9cde32d6cd1308fa59a86318311344f6f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 10:24:21 +0100 Subject: [PATCH 121/152] add ignoreExpectedError to test helpers --- truffle/test/helpers/helpers.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/truffle/test/helpers/helpers.js b/truffle/test/helpers/helpers.js index d2b44b6..0c6bc50 100644 --- a/truffle/test/helpers/helpers.js +++ b/truffle/test/helpers/helpers.js @@ -107,3 +107,8 @@ function range(start, end) { return result; } module.exports.range = range; + +// just used to signal/document that we're explicitely ignoring/expecting an error +function ignoreExpectedError() { +} +module.exports.ignoreExpectedError = ignoreExpectedError; From 49c7a11fdfdaa6e127fb417743892d0e9d3552cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 10:57:07 +0100 Subject: [PATCH 122/152] tests: fix indentation --- truffle/test/foreign-erc20.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index 1e3e838..86c4ea9 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -3,11 +3,11 @@ var helpers = require("./helpers/helpers"); contract('ForeignBridge', function(accounts) { it("totalSupply", function() { - var contract; + var contract; var requiredSignatures = 1; var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var owner = accounts[2]; + var owner = accounts[2]; var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; var value = web3.toWei(3, "ether"); @@ -49,7 +49,7 @@ contract('ForeignBridge', function(accounts) { return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { contract = instance; - // deposit something so we can transfer it + // deposit something so we can transfer it return contract.deposit(owner, web3.toWei(3, "ether"), hash, {from: authorities[0]}); }).then(function(result) { @@ -61,7 +61,7 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert(false, "transfer without allowance should fail"); - // transfer 0 without allowance should work + // transfer 0 without allowance should work return contract.transferFrom(owner, receiver, 0, {from: spender}); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); From ff9f7bb7f68de192bfbc0a9a6c2cb7b6dc5b83e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 11:00:09 +0100 Subject: [PATCH 123/152] fix error handling in truffle tests only catch/ignore such errors that we want to happen. propagate all other errors correctly and don't ignore them. --- truffle/test/foreign-erc20.js | 58 ++++++++++++++++-------------- truffle/test/foreign.js | 59 +++++++++++++++--------------- truffle/test/home.js | 63 ++++++++++++++------------------- truffle/test/message_signing.js | 9 ++--- 4 files changed, 91 insertions(+), 98 deletions(-) diff --git a/truffle/test/foreign-erc20.js b/truffle/test/foreign-erc20.js index 86c4ea9..de75675 100644 --- a/truffle/test/foreign-erc20.js +++ b/truffle/test/foreign-erc20.js @@ -57,9 +57,11 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert.equal(0, result, "initial allowance should be 0"); - return contract.transferFrom(owner, receiver, web3.toWei(1, "ether"), {from: spender}); - }).then(function(result) { - assert(false, "transfer without allowance should fail"); + return contract.transferFrom(owner, receiver, web3.toWei(1, "ether"), {from: spender}) + .then(function() { + assert(false, "transfer without allowance should fail"); + }, helpers.ignoreExpectedError) + }).then(function() { // transfer 0 without allowance should work return contract.transferFrom(owner, receiver, 0, {from: spender}); @@ -70,7 +72,7 @@ contract('ForeignBridge', function(accounts) { assert.equal(receiver, result.logs[0].args.to); assert.equal(0, result.logs[0].args.tokens); - }, function(err) { + // transfer should work return contract.approve(spender, web3.toWei(4, "ether"), {from: owner}); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -83,10 +85,12 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert.equal(web3.toWei(4, "ether"), result, "approval should set allowance"); - return contract.transferFrom(owner, receiver, web3.toWei(4, "ether"), {from: spender}); - }).then(function(result) { - assert(false, "transferring more than balance should fail"); - }, function(err) { + return contract.transferFrom(owner, receiver, web3.toWei(4, "ether"), {from: spender}) + .then(function() { + assert(false, "transferring more than balance should fail"); + }, helpers.ignoreExpectedError) + }).then(function() { + return contract.approve(spender, web3.toWei(2, "ether"), {from: owner}); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -99,10 +103,12 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { assert.equal(web3.toWei(2, "ether"), result, "approval should update allowance"); - return contract.transferFrom(owner, receiver, web3.toWei(2, "ether") + 2, {from: spender}); - }).then(function(result) { - assert(false, "transferring more than allowance should fail"); - }, function(err) { + return contract.transferFrom(owner, receiver, web3.toWei(2, "ether") + 2, {from: spender}) + .then(function() { + assert(false, "transferring more than allowance should fail"); + }, helpers.ignoreExpectedError) + }).then(function() { + return contract.transferFrom(owner, receiver, web3.toWei(2, "ether"), {from: spender}); }).then(function(result) { assert.equal(1, result.logs.length, "Exactly one event should be created"); @@ -175,11 +181,11 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transfer(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transfer should fail"); - }, function(err) { - }) + return meta.transfer(recipientAccount, transferedValue, { from: userAccount }) + .then(function() { + assert(false, "transfer should fail"); + }, helpers.ignoreExpectedError) + }) }) it("should allow transfer of 0 value according to ERC20", function() { @@ -227,10 +233,10 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { return meta.deposit(userAccount, 1, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transfer(recipientAccount, 1, { from: userAccount }); - }).then(function(result) { - assert(false, "transfer should fail"); - }, function(err) { + return meta.transfer(recipientAccount, 1, { from: userAccount }) + .then(function() { + assert(false, "transfer should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -250,12 +256,12 @@ contract('ForeignBridge', function(accounts) { }).then(function(result) { return meta.deposit(userAccount, 1, hash, { from: authorities[0] }); }).then(function(result) { - return meta.approve(spenderAccount, 1, {from: userAccount}); + return meta.approve(spenderAccount, 1, {from: userAccount}); }).then(function(result) { - return meta.transferFrom(userAccount, recipientAccount, 1, { from: spenderAccount }); - }).then(function(result) { - assert(false, "transfer should fail"); - }, function(err) { + return meta.transferFrom(userAccount, recipientAccount, 1, { from: spenderAccount }) + .then(function() { + assert(false, "transfer should fail"); + }, helpers.ignoreExpectedError) }) }) }) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index d564ad6..9c203fe 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -21,20 +21,18 @@ contract('ForeignBridge', function(accounts) { it("should fail to deploy contract with not enough required signatures", function() { var authorities = [accounts[0], accounts[1]]; - return ForeignBridge.new(0, authorities, 0).then(function(_) { - assert(false, "Contract should fail to deploy"); - }, function(err) { - // do nothing - }) + return ForeignBridge.new(0, authorities, 0) + .then(function() { + assert(false, "Contract should fail to deploy"); + }, helpers.ignoreExpectedError) }) it("should fail to deploy contract with to many signatures", function() { var authorities = [accounts[0], accounts[1]]; - return ForeignBridge.new(3, authorities, 0).then(function(_) { - assert(false, "Contract should fail to deploy"); - }, function(err) { - // do nothing - }) + return ForeignBridge.new(3, authorities, 0) + .then(function() { + assert(false, "Contract should fail to deploy"); + }, helpers.ignoreExpectedError) }) it("should allow a single authority to confirm a deposit", function() { @@ -115,10 +113,10 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(_) { - return meta.deposit(userAccount, value, hash, { from: authorities[0] }); - }).then(function(result) { - assert(false, "doing same deposit twice from same authority should fail"); - }, function(err) { + return meta.deposit(userAccount, value, hash, { from: authorities[0] }) + .then(function() { + assert(false, "doing same deposit twice from same authority should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -133,10 +131,10 @@ contract('ForeignBridge', function(accounts) { return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; - return meta.deposit(userAccount, value, hash, { from: userAccount }); - }).then(function(result) { - assert(false, "should fail"); - }, function(err) { + return meta.deposit(userAccount, value, hash, { from: userAccount }) + .then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -191,10 +189,10 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transferHomeViaRelay should fail"); - }, function(err) { + return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }) + .then(function() { + assert(false, "transferHomeViaRelay should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -212,10 +210,10 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }); - }).then(function(result) { - assert(false, "transferHomeViaRelay should fail"); - }, function(err) { + return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }) + .then(function() { + assert(false, "transferHomeViaRelay should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -438,11 +436,10 @@ contract('ForeignBridge', function(accounts) { signature = result; return meta.submitSignature(signature, message, { from: authorities[0] }); }).then(function(_) { - return meta.submitSignature(signature, message, { from: authorities[0] }); - }).then(function(_) { - assert(false, "submitSignature should fail"); - }, function (_) { - // nothing + return meta.submitSignature(signature, message, { from: authorities[0] }) + .then(function() { + assert(false, "submitSignature should fail"); + }, helpers.ignoreExpectedError) }) }) }) diff --git a/truffle/test/home.js b/truffle/test/home.js index bf0cd2d..38bb13c 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -25,20 +25,18 @@ contract('HomeBridge', function(accounts) { it("should fail to deploy contract with not enough required signatures", function() { var authorities = [accounts[0], accounts[1]]; - return HomeBridge.new(0, authorities).then(function(_) { - assert(false, "Contract should fail to deploy"); - }, function(err) { - // do nothing - }) + return HomeBridge.new(0, authorities) + .then(function() { + assert(false, "Contract should fail to deploy"); + }, helpers.ignoreExpectedError) }) it("should fail to deploy contract with too many signatures", function() { var authorities = [accounts[0], accounts[1]]; - return HomeBridge.new(3, authorities, 0).then(function(_) { - assert(false, "Contract should fail to deploy"); - }, function(err) { - // do nothing - }) + return HomeBridge.new(3, authorities, 0) + .then(function() { + assert(false, "Contract should fail to deploy"); + }, helpers.ignoreExpectedError) }) it("should create deposit event", function() { @@ -245,11 +243,9 @@ contract('HomeBridge', function(accounts) { [vrs.s], message, { from: relayerAccount, gasPrice: homeGasPrice } - ); - }).then(function(result) { - assert(false, "withdraw if value <= estimatedGasCostOfWithdraw should fail"); - }, function (err) { - // nothing + ).then(function() { + assert(false, "withdraw if value <= estimatedGasCostOfWithdraw should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -360,11 +356,9 @@ contract('HomeBridge', function(accounts) { [vrs.s], message2, {from: authorities[0], gasPrice: homeGasPrice} - ); - }).then(function(result) { - assert(false, "should fail"); - }, function (err) { - // nothing + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -396,11 +390,9 @@ contract('HomeBridge', function(accounts) { [vrs.s], message.substr(0, 83), {from: authorities[0], gasPrice: homeGasPrice} - ); - }).then(function(result) { - assert(false, "should fail"); - }, function (err) { - // nothing + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -443,10 +435,9 @@ contract('HomeBridge', function(accounts) { message, // anyone can call withdraw (provided they have the message and required signatures) {from: userAccount, gasPrice: homeGasPrice} - ); - }).then(function(result) { - assert(false, "withdraw should fail"); - }, function(err) { + ).then(function() { + assert(false, "withdraw should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -487,10 +478,9 @@ contract('HomeBridge', function(accounts) { message, // anyone can call withdraw (provided they have the message and required signatures) {from: userAccount, gasPrice: homeGasPrice} - ); - }).then(function(result) { - assert(false, "should fail"); - }, function(err) { + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -531,10 +521,9 @@ contract('HomeBridge', function(accounts) { message, // anyone can call withdraw (provided they have the message and required signatures) {from: userAccount, gasPrice: homeGasPrice} - ); - }).then(function(result) { - assert(false, "should fail"); - }, function(err) { + ).then(function(result) { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) }) }) }) diff --git a/truffle/test/message_signing.js b/truffle/test/message_signing.js index 0c255fa..374490c 100644 --- a/truffle/test/message_signing.js +++ b/truffle/test/message_signing.js @@ -1,4 +1,5 @@ var MessageSigning = artifacts.require("MessageSigningTest"); +var helpers = require("./helpers/helpers"); contract("MessageSigning", function() { it("should recover address from signed message", function() { @@ -32,9 +33,9 @@ contract("MessageSigning", function() { return MessageSigning.new().then(function(instance) { return instance.recoverAddressFromSignedMessage.call(signature, message) - }).then(function(result) { - assert(false, "should fail because signature is too short"); - }, function(err) { - }) + .then(function() { + assert(false, "should fail because signature is too short"); + }, helpers.ignoreExpectedError) + }) }) }) From edd691672a6da7859eeb7d2f2d9a9bd59757f77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 11:01:05 +0100 Subject: [PATCH 124/152] fix broken truffle tests that passed because error handling was broken --- truffle/test/foreign.js | 52 +++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 9c203fe..19317b6 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -372,16 +372,18 @@ contract('ForeignBridge', function(accounts) { var requiredSignatures = 1; var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { - return meta.submitSignature(result, message, { from: authorities[0] }); - }).then(function(result) { - assert(false, "submitSignature should fail"); - }, function (err) { - // nothing + return meta.submitSignature(result, message.substr(0, 84), { from: authorities[0] }) + .then(function() { + assert(false, "submitSignature should fail for message that is too short"); + }, helpers.ignoreExpectedError) }) }) @@ -390,17 +392,20 @@ contract('ForeignBridge', function(accounts) { var requiredSignatures = 1; var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - var message2 = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112"; + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice2 = web3.toBigNumber(web3.toWei(2, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); + var message2 = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice2); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { - return meta.submitSignature(result, message2, { from: authorities[0] }); - }).then(function(result) { - assert(false, "submitSignature should fail"); - }, function (err) { - // nothing + return meta.submitSignature(result, message2, { from: authorities[0] }) + .then(function() { + assert(false, "submitSignature should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -409,16 +414,20 @@ contract('ForeignBridge', function(accounts) { var requiredSignatures = 1; var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var homeGasPrice2 = web3.toBigNumber(web3.toWei(2, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); + var message2 = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice2); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; return helpers.sign(authorities[0], message); }).then(function(result) { - return meta.submitSignature(result, message, { from: authorities[1] }); - }).then(function(result) { - assert(false, "submitSignature should fail"); - }, function (err) { - // nothing + return meta.submitSignature(result, message, { from: authorities[1] }) + .then(function() { + assert(false, "submitSignature should fail"); + }, helpers.ignoreExpectedError) }) }) @@ -427,7 +436,10 @@ contract('ForeignBridge', function(accounts) { var requiredSignatures = 1; var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; - var message = "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; + var recipientAccount = accounts[2]; + var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); var signature; return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; From a1dc3bcb050d3c6ac706b408c00a3453f9ee78ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 14:25:00 +0100 Subject: [PATCH 125/152] bridge.sol: improve docstring for verifySignatures --- contracts/bridge.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 25fe679..b7c65da 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -36,7 +36,10 @@ library Helpers { return string(result); } - /// Multisig authority validation + /// reverts unless signatures (whose components are in `vs`, `rs`, `ss`) + /// contain `requiredSignatures` distinct correct signatures + /// where signer is in `addresses` + /// that signed `message` function verifySignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) internal pure { // not enough signatures require(requiredSignatures <= vs.length); From 76c85e6f8439889bc7d71b666d20b5279630474a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 14:25:11 +0100 Subject: [PATCH 126/152] bridge.sol: add HelpersTest.verifySignatures --- contracts/bridge.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index b7c65da..9e5eae6 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -69,6 +69,10 @@ library HelpersTest { function uintToString(uint256 inputValue) public pure returns (string str) { return Helpers.uintToString(inputValue); } + + function verifySignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) public pure { + return Helpers.verifySignatures(message, vs, rs, ss, addresses, requiredSignatures); + } } From bd20896deb97b8748603286b0a3c4c9617e2b889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 14:25:43 +0100 Subject: [PATCH 127/152] use `accounts` in more truffle tests --- truffle/test/helpers.js | 10 +++------- truffle/test/message.js | 4 ++-- truffle/test/message_signing.js | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/truffle/test/helpers.js b/truffle/test/helpers.js index 04c37be..a6912c6 100644 --- a/truffle/test/helpers.js +++ b/truffle/test/helpers.js @@ -3,14 +3,10 @@ var Helpers = artifacts.require("HelpersTest"); // testing helpers var helpers = require("./helpers/helpers"); -contract("Helpers", function() { +contract("Helpers", function(accounts) { it("`addressArrayContains` should function correctly", function() { - var addresses = [ - "0xd4f04f18d253f831e5b9bcfde7f20450562e03da", - "0x46ee1abbcd7215364174f84c3cbc4770d45966e9", - "0x5ef98710ff315ded660fe757bf7a861114287c1e", - ]; - var otherAddress = "0x006e27b6a72e1f34c626762f3c4761547aff1421"; + var addresses = accounts.slice(0, 3); + var otherAddress = accounts[3]; var library; return Helpers.new().then(function(instance) { library = instance; diff --git a/truffle/test/message.js b/truffle/test/message.js index c782f49..6ad994c 100644 --- a/truffle/test/message.js +++ b/truffle/test/message.js @@ -1,8 +1,8 @@ var Message = artifacts.require("MessageTest"); var helpers = require("./helpers/helpers"); -contract("Message", function() { - var recipientAccount = "0x006e27b6a72e1f34c626762f3c4761547aff1421"; +contract("Message", function(accounts) { + var recipientAccount = accounts[0]; var value = web3.toBigNumber(web3.toWei(1, "ether")); var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); diff --git a/truffle/test/message_signing.js b/truffle/test/message_signing.js index 374490c..8570b89 100644 --- a/truffle/test/message_signing.js +++ b/truffle/test/message_signing.js @@ -1,7 +1,7 @@ var MessageSigning = artifacts.require("MessageSigningTest"); var helpers = require("./helpers/helpers"); -contract("MessageSigning", function() { +contract("MessageSigning", function(accounts) { it("should recover address from signed message", function() { var signature = "0xb585c41f3cceb2ff9b5c033f2edbefe93415bde365489c989bad8cef3b18e38148a13e100608a29735d709fe708926d37adcecfffb32b1d598727028a16df5db1b"; var message = "0xdeadbeaf"; From c97785862b2b19a96d22f0bf55ffd25cd9b728d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 14:25:54 +0100 Subject: [PATCH 128/152] remove unused function param --- truffle/test/home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/test/home.js b/truffle/test/home.js index 38bb13c..99085c2 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -521,7 +521,7 @@ contract('HomeBridge', function(accounts) { message, // anyone can call withdraw (provided they have the message and required signatures) {from: userAccount, gasPrice: homeGasPrice} - ).then(function(result) { + ).then(function() { assert(false, "should fail"); }, helpers.ignoreExpectedError) }) From 2165513fdd43521266803541bbf7bc14299dc683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 14:26:11 +0100 Subject: [PATCH 129/152] tests for Helpers.verifySignatures --- truffle/test/helpers.js | 197 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/truffle/test/helpers.js b/truffle/test/helpers.js index a6912c6..a15758b 100644 --- a/truffle/test/helpers.js +++ b/truffle/test/helpers.js @@ -80,4 +80,201 @@ contract("Helpers", function(accounts) { assert.equal(result, "131242344353464564564574574567456"); }) }) + + it("`verifySignatures` should pass for 1 required signature", function() { + var library; + var signature; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var recipientAccount = accounts[2]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var homeGasPrice = web3.toBigNumber(10000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + + return Helpers.new().then(function(instance) { + library = instance; + }).then(function(result) { + return helpers.sign(authorities[0], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return library.verifySignatures.call( + message, + [vrs.v], + [vrs.r], + [vrs.s], + authorities, + requiredSignatures + ) + }) + }) + + it("`verifySignatures` should pass for multiple signatures", function() { + var library; + var signatures = []; + var requiredSignatures = 3; + var authorities = [accounts[0], accounts[1], accounts[2]]; + var recipientAccount = accounts[3]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var homeGasPrice = web3.toBigNumber(10000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + + return Helpers.new().then(function(instance) { + library = instance; + }).then(function(result) { + + return helpers.sign(authorities[0], message); + }).then(function(result) { + signatures[0] = result; + + return helpers.sign(authorities[1], message); + }).then(function(result) { + signatures[1] = result; + + return helpers.sign(authorities[2], message); + }).then(function(result) { + signatures[2] = result; + + var vrs = []; + vrs[0] = helpers.signatureToVRS(signatures[0]); + vrs[1] = helpers.signatureToVRS(signatures[1]); + vrs[2] = helpers.signatureToVRS(signatures[2]); + + return library.verifySignatures.call( + message, + [vrs[0].v, vrs[1].v, vrs[2].v], + [vrs[0].r, vrs[1].r, vrs[2].r], + [vrs[0].s, vrs[1].s, vrs[2].s], + authorities, + requiredSignatures + ) + }) + }) + + it("`verifySignatures` should fail for signature for other message", function() { + var library; + var signature; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var recipientAccount = accounts[2]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var homeGasPrice = web3.toBigNumber(10000); + var homeGasPrice2 = web3.toBigNumber(100); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + var message2 = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice2); + + return Helpers.new().then(function(instance) { + library = instance; + }).then(function(result) { + return helpers.sign(authorities[0], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return library.verifySignatures.call( + message2, + [vrs.v], + [vrs.r], + [vrs.s], + authorities, + requiredSignatures + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) + }) + }) + + it("`verifySignatures` should fail if signer not in addresses", function() { + var library; + var signature; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var recipientAccount = accounts[2]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var homeGasPrice = web3.toBigNumber(10000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + + return Helpers.new().then(function(instance) { + library = instance; + }).then(function(result) { + return helpers.sign(accounts[3], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return library.verifySignatures.call( + message, + [vrs.v], + [vrs.r], + [vrs.s], + authorities, + requiredSignatures + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) + }) + }) + + it("`verifySignatures` should fail for not enough signatures", function() { + var library; + var signature; + var requiredSignatures = 2; + var authorities = [accounts[0], accounts[1]]; + var recipientAccount = accounts[2]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var homeGasPrice = web3.toBigNumber(10000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + + return Helpers.new().then(function(instance) { + library = instance; + }).then(function(result) { + return helpers.sign(authorities[0], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return library.verifySignatures.call( + message, + [vrs.v], + [vrs.r], + [vrs.s], + authorities, + requiredSignatures + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) + }) + }) + + it("`verifySignatures` should fail for duplicated signature", function() { + var library; + var signature; + var requiredSignatures = 2; + var authorities = [accounts[0], accounts[1]]; + var recipientAccount = accounts[2]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var homeGasPrice = web3.toBigNumber(10000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", homeGasPrice); + + return Helpers.new().then(function(instance) { + library = instance; + }).then(function(result) { + return helpers.sign(authorities[0], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return library.verifySignatures.call( + message, + [vrs.v, vrs.v], + [vrs.r, vrs.r], + [vrs.s, vrs.r], + authorities, + requiredSignatures + ).then(function() { + assert(false, "should fail"); + }, helpers.ignoreExpectedError) + }) + }) }) From 52652cb9fc38d7a34ed8e0fd5ebf6f704ef736c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 14:44:55 +0100 Subject: [PATCH 130/152] add truffle test: should fail to transfer more than balance home --- truffle/test/foreign.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 19317b6..5ad5a94 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -217,6 +217,27 @@ contract('ForeignBridge', function(accounts) { }) }) + it("should fail to transfer more than balance home", function() { + var meta; + var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = 0; + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var recipientAccount = accounts[3]; + var userValue = web3.toWei(3, "ether"); + var transferedValue = web3.toWei(4, "ether"); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { + meta = instance; + return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }) + .then(function() { + assert(false, "transferHomeViaRelay should fail"); + }, helpers.ignoreExpectedError) + }) + }) + it("should allow user to trigger withdraw", function() { var meta; var requiredSignatures = 1; From 61bb0b3ffa862b8066781e6fc9c9470be2de58c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 15:11:24 +0100 Subject: [PATCH 131/152] fix truffle tests that failed because of wrong number of args --- truffle/test/foreign.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 5ad5a94..17d62a5 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -181,6 +181,7 @@ contract('ForeignBridge', function(accounts) { var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; + var homeGasPrice = web3.toBigNumber(10000); var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(4, "ether"); @@ -189,7 +190,7 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }) + return meta.transferHomeViaRelay(recipientAccount, transferedValue, homeGasPrice, { from: userAccount }) .then(function() { assert(false, "transferHomeViaRelay should fail"); }, helpers.ignoreExpectedError) @@ -202,6 +203,7 @@ contract('ForeignBridge', function(accounts) { var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; + var homeGasPrice = web3.toBigNumber(10000); var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(0, "ether"); @@ -210,7 +212,7 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }) + return meta.transferHomeViaRelay(recipientAccount, transferedValue, homeGasPrice, { from: userAccount }) .then(function() { assert(false, "transferHomeViaRelay should fail"); }, helpers.ignoreExpectedError) @@ -223,6 +225,7 @@ contract('ForeignBridge', function(accounts) { var estimatedGasCostOfWithdraw = 0; var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; + var homeGasPrice = web3.toBigNumber(10000); var recipientAccount = accounts[3]; var userValue = web3.toWei(3, "ether"); var transferedValue = web3.toWei(4, "ether"); @@ -231,7 +234,7 @@ contract('ForeignBridge', function(accounts) { meta = instance; return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(recipientAccount, transferedValue, { from: userAccount }) + return meta.transferHomeViaRelay(recipientAccount, transferedValue, homeGasPrice, { from: userAccount }) .then(function() { assert(false, "transferHomeViaRelay should fail"); }, helpers.ignoreExpectedError) @@ -266,6 +269,7 @@ contract('ForeignBridge', function(accounts) { assert.equal("Withdraw", result.logs[1].event, "Event name should be Withdraw"); assert.equal(userAccount2, result.logs[1].args.recipient, "Event recipient should be equal to transaction recipient"); assert.equal(value2, result.logs[1].args.value, "Event value should match transaction value"); + assert(homeGasPrice.equals(result.logs[1].args.homeGasPrice)); return Promise.all([ meta.balances.call(userAccount), From 4e56c9ec6540bb3d51c488a8da490210eadc8fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 15:46:51 +0100 Subject: [PATCH 132/152] require value to be greater estimated wei cost for relay --- contracts/bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 9e5eae6..92941aa 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -455,7 +455,7 @@ contract ForeignBridge { require(value > 0); uint estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; - require(value >= estimatedWeiCostOfWithdraw); + require(value > estimatedWeiCostOfWithdraw); balances[msg.sender] -= value; // burns tokens From 85a2e10fcbe6afc29d6c3c604d56a5e87ee94b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 15:47:17 +0100 Subject: [PATCH 133/152] remove redundance require. signatures of wrong length don't pass the address recovery above --- contracts/bridge.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index 92941aa..dcae114 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -479,7 +479,6 @@ contract ForeignBridge { // Validate submited signatures require(MessageSigning.recoverAddressFromSignedMessage(signature, message) == msg.sender); - require(signature.length == 65); // Valid withdraw message must have 116 bytes require(message.length == 116); var hash = keccak256(message); From 50e63db3cd3bb95e68e721548dabb3a1b901f653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 15:48:10 +0100 Subject: [PATCH 134/152] improve truffle tests for ForeignBridge.transferToHome --- truffle/test/foreign.js | 42 +++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index 17d62a5..c16f045 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -241,34 +241,56 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should allow user to trigger withdraw", function() { + it("should fail to transfer home with value that gets entirely burned on gas", function() { var meta; var requiredSignatures = 1; - var estimatedGasCostOfWithdraw = 0; + var estimatedGasCostOfWithdraw = web3.toBigNumber(10000); + var authorities = [accounts[0], accounts[1]]; + var userAccount = accounts[2]; + var homeGasPrice = web3.toBigNumber(10000); + var recipientAccount = accounts[3]; + var userValue = web3.toWei(3, "ether"); + var transferedValue = estimatedGasCostOfWithdraw.times(homeGasPrice); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; + return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { + meta = instance; + return meta.deposit(userAccount, userValue, hash, { from: authorities[0] }); + }).then(function(result) { + return meta.transferHomeViaRelay(recipientAccount, transferedValue, homeGasPrice, { from: userAccount }) + .then(function() { + assert(false, "transferHomeViaRelay should fail"); + }, helpers.ignoreExpectedError) + }) + }) + + it("should allow user to transfer home", function() { + var meta; + var requiredSignatures = 1; + var estimatedGasCostOfWithdraw = web3.toBigNumber(10000); var authorities = [accounts[0], accounts[1]]; var userAccount = accounts[2]; var userAccount2 = accounts[3]; var value = web3.toWei(3, "ether"); - var value2 = web3.toWei(1, "ether"); - var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); + var transferedValue = estimatedGasCostOfWithdraw.times(homeGasPrice).plus(1); + var hash = "0xe55bb43c36cdf79e23b4adc149cdded921f0d482e613c50c6540977c213bc408"; return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; // top up balance so we can transfer return meta.deposit(userAccount, value, hash, { from: authorities[0] }); }).then(function(result) { - return meta.transferHomeViaRelay(userAccount2, value2, homeGasPrice, { from: userAccount }); + return meta.transferHomeViaRelay(userAccount2, transferedValue, homeGasPrice, { from: userAccount }); }).then(function(result) { assert.equal(2, result.logs.length) assert.equal("Transfer", result.logs[0].event); assert.equal(userAccount, result.logs[0].args.from); assert.equal("0x0000000000000000000000000000000000000000", result.logs[0].args.to); - assert.equal(value2, result.logs[0].args.tokens); + assert(transferedValue.equals(result.logs[0].args.tokens)); assert.equal("Withdraw", result.logs[1].event, "Event name should be Withdraw"); assert.equal(userAccount2, result.logs[1].args.recipient, "Event recipient should be equal to transaction recipient"); - assert.equal(value2, result.logs[1].args.value, "Event value should match transaction value"); + assert(transferedValue.equals(result.logs[1].args.value)); assert(homeGasPrice.equals(result.logs[1].args.homeGasPrice)); return Promise.all([ @@ -276,8 +298,8 @@ contract('ForeignBridge', function(accounts) { meta.balances.call(userAccount2) ]) }).then(function(result) { - assert.equal(web3.toWei(2, "ether"), result[0]); - assert.equal(web3.toWei(0, "ether"), result[1]); + assert(web3.toBigNumber(value).minus(transferedValue).equals(result[0])); + assert(web3.toBigNumber(web3.toWei(0, "ether")).equals(result[1])); }) }) @@ -392,7 +414,7 @@ contract('ForeignBridge', function(accounts) { }) }) - it("should not be possible to submit to short message", function() { + it("should not be possible to submit message that is too short", function() { var meta; var requiredSignatures = 1; var estimatedGasCostOfWithdraw = 0; From 0de03845097cd973737b0a9bb4d6fa228c973e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 16:09:57 +0100 Subject: [PATCH 135/152] fix test that submitting signature with too short msg fails --- truffle/test/foreign.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/truffle/test/foreign.js b/truffle/test/foreign.js index c16f045..0daea92 100644 --- a/truffle/test/foreign.js +++ b/truffle/test/foreign.js @@ -423,11 +423,12 @@ contract('ForeignBridge', function(accounts) { var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; var homeGasPrice = web3.toBigNumber(web3.toWei(3, "gwei")); var message = helpers.createMessage(recipientAccount, web3.toBigNumber(1000), transactionHash, homeGasPrice); + var truncatedMessage = message.substr(0, 84); return ForeignBridge.new(requiredSignatures, authorities, estimatedGasCostOfWithdraw).then(function(instance) { meta = instance; - return helpers.sign(authorities[0], message); - }).then(function(result) { - return meta.submitSignature(result, message.substr(0, 84), { from: authorities[0] }) + return helpers.sign(authorities[0], truncatedMessage); + }).then(function(signature) { + return meta.submitSignature(signature, truncatedMessage, { from: authorities[0] }) .then(function() { assert(false, "submitSignature should fail for message that is too short"); }, helpers.ignoreExpectedError) From 22e9b5d69545cef358e73e71f39bc877794ab0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 16:13:58 +0100 Subject: [PATCH 136/152] add test that fails when gas price != requested gas price --- truffle/test/home.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/truffle/test/home.js b/truffle/test/home.js index 99085c2..f530131 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -201,6 +201,49 @@ contract('HomeBridge', function(accounts) { }) }) + it("withdraw should fail if gas price != requested gas price", function() { + var homeBridge; + var signature; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var estimatedGasCostOfWithdraw = 0; + var userAccount = accounts[2]; + var recipientAccount = accounts[3]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var requestedGasPrice = web3.toBigNumber(100); + var usedGasPrice = web3.toBigNumber(1000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", requestedGasPrice); + + return HomeBridge.new( + requiredSignatures, + authorities, + estimatedGasCostOfWithdraw + ).then(function(instance) { + homeBridge = instance; + + // "charge" HomeBridge so we can withdraw later + return homeBridge.sendTransaction({ + value: value, + from: userAccount + }) + }).then(function(result) { + return helpers.sign(authorities[0], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return homeBridge.withdraw( + [vrs.v], + [vrs.r], + [vrs.s], + message, + {from: userAccount, gasPrice: usedGasPrice} + ).then(function() { + assert(false, "withdraw should fail if used gas price != requested gas price" + }, helpers.ignoreExpectedError) + }) + }) + it("should revert withdraw if value is insufficient to cover costs", function() { var homeBridge; var initialBalances; From 845ab3359c0e15523cd5f5b638cc375b740c2ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 16:38:28 +0100 Subject: [PATCH 137/152] fix syntax error --- truffle/test/home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/test/home.js b/truffle/test/home.js index f530131..4b1b257 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -239,7 +239,7 @@ contract('HomeBridge', function(accounts) { message, {from: userAccount, gasPrice: usedGasPrice} ).then(function() { - assert(false, "withdraw should fail if used gas price != requested gas price" + assert(false, "withdraw should fail if used gas price != requested gas price"); }, helpers.ignoreExpectedError) }) }) From 59d354bde0e295163825cf12f5167958212be1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 16:51:24 +0100 Subject: [PATCH 138/152] test: withdraw should succeed if gas price != requested gas price but sender is receiver --- truffle/test/home.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/truffle/test/home.js b/truffle/test/home.js index 4b1b257..5fc6b3d 100644 --- a/truffle/test/home.js +++ b/truffle/test/home.js @@ -244,6 +244,47 @@ contract('HomeBridge', function(accounts) { }) }) + it("withdraw should succeed if gas price != requested gas price but sender is receiver", function() { + var homeBridge; + var signature; + var requiredSignatures = 1; + var authorities = [accounts[0], accounts[1]]; + var estimatedGasCostOfWithdraw = 0; + var userAccount = accounts[2]; + var recipientAccount = accounts[3]; + var value = web3.toBigNumber(web3.toWei(1, "ether")); + var requestedGasPrice = web3.toBigNumber(100); + var usedGasPrice = web3.toBigNumber(1000); + var message = helpers.createMessage(recipientAccount, value, "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80", requestedGasPrice); + + return HomeBridge.new( + requiredSignatures, + authorities, + estimatedGasCostOfWithdraw + ).then(function(instance) { + homeBridge = instance; + + // "charge" HomeBridge so we can withdraw later + return homeBridge.sendTransaction({ + value: value, + from: userAccount + }) + }).then(function(result) { + return helpers.sign(authorities[0], message); + }).then(function(result) { + signature = result; + var vrs = helpers.signatureToVRS(signature); + + return homeBridge.withdraw( + [vrs.v], + [vrs.r], + [vrs.s], + message, + {from: recipientAccount, gasPrice: usedGasPrice} + ) + }) + }) + it("should revert withdraw if value is insufficient to cover costs", function() { var homeBridge; var initialBalances; From d7feac802fef3960e8e4a98bcaa55dece3e81465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Tue, 13 Feb 2018 17:18:24 +0100 Subject: [PATCH 139/152] verifySignatures -> hasEnoughValidSignatures and make it return bool --- contracts/bridge.sol | 31 ++++++++++++++++----------- truffle/test/helpers.js | 46 ++++++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index dcae114..adb3ed5 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -36,25 +36,32 @@ library Helpers { return string(result); } - /// reverts unless signatures (whose components are in `vs`, `rs`, `ss`) + /// returns whether signatures (whose components are in `vs`, `rs`, `ss`) /// contain `requiredSignatures` distinct correct signatures - /// where signer is in `addresses` + /// where signer is in `allowed_signers` /// that signed `message` - function verifySignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) internal pure { + function hasEnoughValidSignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] allowed_signers, uint requiredSignatures) internal pure returns (bool) { // not enough signatures - require(requiredSignatures <= vs.length); + if (vs.length < requiredSignatures) { + return false; + } var hash = MessageSigning.hashMessage(message); - var encountered = new address[](addresses.length); + var encountered_addresses = new address[](allowed_signers.length); for (uint i = 0; i < requiredSignatures; i++) { - var a = ecrecover(hash, vs[i], rs[i], ss[i]); + var recovered_address = ecrecover(hash, vs[i], rs[i], ss[i]); // only signatures by addresses in `addresses` are allowed - require(addressArrayContains(addresses, a)); + if (!addressArrayContains(allowed_signers, recovered_address)) { + return false; + } // duplicate signatures are not allowed - require(!addressArrayContains(encountered, a)); - encountered[i] = a; + if (addressArrayContains(encountered_addresses, recovered_address)) { + return false; + } + encountered_addresses[i] = recovered_address; } + return true; } } @@ -70,8 +77,8 @@ library HelpersTest { return Helpers.uintToString(inputValue); } - function verifySignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) public pure { - return Helpers.verifySignatures(message, vs, rs, ss, addresses, requiredSignatures); + function hasEnoughValidSignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) public pure returns (bool) { + return Helpers.hasEnoughValidSignatures(message, vs, rs, ss, addresses, requiredSignatures); } } @@ -244,7 +251,7 @@ contract HomeBridge { require(message.length == 116); // check that at least `requiredSignatures` `authorities` have signed `message` - Helpers.verifySignatures(message, vs, rs, ss, authorities, requiredSignatures); + require(Helpers.hasEnoughValidSignatures(message, vs, rs, ss, authorities, requiredSignatures)); address recipient = Message.getRecipient(message); uint value = Message.getValue(message); diff --git a/truffle/test/helpers.js b/truffle/test/helpers.js index a15758b..ddd7390 100644 --- a/truffle/test/helpers.js +++ b/truffle/test/helpers.js @@ -81,7 +81,7 @@ contract("Helpers", function(accounts) { }) }) - it("`verifySignatures` should pass for 1 required signature", function() { + it("`hasEnoughValidSignatures` should pass for 1 required signature", function() { var library; var signature; var requiredSignatures = 1; @@ -99,14 +99,16 @@ contract("Helpers", function(accounts) { signature = result; var vrs = helpers.signatureToVRS(signature); - return library.verifySignatures.call( + return library.hasEnoughValidSignatures.call( message, [vrs.v], [vrs.r], [vrs.s], authorities, requiredSignatures - ) + ).then(function(result) { + assert(result, "should return true"); + }) }) }) @@ -141,14 +143,16 @@ contract("Helpers", function(accounts) { vrs[1] = helpers.signatureToVRS(signatures[1]); vrs[2] = helpers.signatureToVRS(signatures[2]); - return library.verifySignatures.call( + return library.hasEnoughValidSignatures.call( message, [vrs[0].v, vrs[1].v, vrs[2].v], [vrs[0].r, vrs[1].r, vrs[2].r], [vrs[0].s, vrs[1].s, vrs[2].s], authorities, requiredSignatures - ) + ).then(function(result) { + assert(result, "should return true"); + }) }) }) @@ -172,16 +176,16 @@ contract("Helpers", function(accounts) { signature = result; var vrs = helpers.signatureToVRS(signature); - return library.verifySignatures.call( + return library.hasEnoughValidSignatures.call( message2, [vrs.v], [vrs.r], [vrs.s], authorities, requiredSignatures - ).then(function() { - assert(false, "should fail"); - }, helpers.ignoreExpectedError) + ).then(function(result) { + assert.equal(result, false, "should return false"); + }) }) }) @@ -203,16 +207,16 @@ contract("Helpers", function(accounts) { signature = result; var vrs = helpers.signatureToVRS(signature); - return library.verifySignatures.call( + return library.hasEnoughValidSignatures.call( message, [vrs.v], [vrs.r], [vrs.s], authorities, requiredSignatures - ).then(function() { - assert(false, "should fail"); - }, helpers.ignoreExpectedError) + ).then(function(result) { + assert.equal(result, false, "should return false"); + }) }) }) @@ -234,16 +238,16 @@ contract("Helpers", function(accounts) { signature = result; var vrs = helpers.signatureToVRS(signature); - return library.verifySignatures.call( + return library.hasEnoughValidSignatures.call( message, [vrs.v], [vrs.r], [vrs.s], authorities, requiredSignatures - ).then(function() { - assert(false, "should fail"); - }, helpers.ignoreExpectedError) + ).then(function(result) { + assert.equal(result, false, "should return false"); + }) }) }) @@ -265,16 +269,16 @@ contract("Helpers", function(accounts) { signature = result; var vrs = helpers.signatureToVRS(signature); - return library.verifySignatures.call( + return library.hasEnoughValidSignatures.call( message, [vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.r], authorities, requiredSignatures - ).then(function() { - assert(false, "should fail"); - }, helpers.ignoreExpectedError) + ).then(function(result) { + assert.equal(result, false, "should return false"); + }) }) }) }) From 107141e0b7e3c44aa4064cba5187fdf07fdac425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 14 Feb 2018 12:13:11 +0100 Subject: [PATCH 140/152] remove unused imports --- bridge/src/bridge/withdraw_confirm.rs | 3 +-- bridge/src/bridge/withdraw_relay.rs | 11 +++++------ bridge/src/signature.rs | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/bridge/src/bridge/withdraw_confirm.rs b/bridge/src/bridge/withdraw_confirm.rs index 96ca465..bf1669d 100644 --- a/bridge/src/bridge/withdraw_confirm.rs +++ b/bridge/src/bridge/withdraw_confirm.rs @@ -3,9 +3,8 @@ use std::ops; use futures::{Future, Stream, Poll}; use futures::future::{JoinAll, join_all}; use tokio_timer::Timeout; -use ethabi::RawLog; use web3::Transport; -use web3::types::{H256, H520, Address, TransactionRequest, Log, Bytes, FilterBuilder}; +use web3::types::{H256, H520, Address, TransactionRequest, Bytes, FilterBuilder}; use api::{self, LogStream, ApiCall}; use app::App; use contracts::foreign; diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index fb7850a..49a46b0 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -3,16 +3,16 @@ use futures::{Future, Stream, Poll}; use futures::future::{JoinAll, join_all, Join}; use tokio_timer::Timeout; use web3::Transport; -use web3::types::{U256, H256, Address, FilterBuilder, Log, Bytes, TransactionRequest}; +use web3::types::{H256, Address, FilterBuilder, Log, Bytes, TransactionRequest}; use ethabi::{RawLog, self}; use app::App; use api::{self, LogStream, ApiCall}; -use contracts::{home, foreign}; +use contracts::foreign; use util::web3_filter; use database::Database; use error::{self, Error}; -use message_to_mainnet::{MessageToMainnet, MESSAGE_LENGTH}; -use signature::{Signature, SIGNATURE_LENGTH}; +use message_to_mainnet::MessageToMainnet; +use signature::Signature; /// returns a filter for `ForeignBridge.CollectedSignatures` events fn collected_signatures_filter(foreign: &foreign::ForeignBridge, address: Address) -> FilterBuilder { @@ -234,8 +234,7 @@ impl Stream for WithdrawRelay { mod tests { use rustc_hex::FromHex; use web3::types::{Log, Bytes}; - use contracts::{home, foreign}; - use message_to_mainnet::MESSAGE_LENGTH; + use contracts::foreign; use super::signatures_payload; #[test] diff --git a/bridge/src/signature.rs b/bridge/src/signature.rs index 55e99e5..85cc358 100644 --- a/bridge/src/signature.rs +++ b/bridge/src/signature.rs @@ -2,7 +2,7 @@ /// conversion from/to byte vectors. /// from/to v, r, s components. -use ethereum_types::{Address, U256, H256}; +use ethereum_types::H256; use ethabi; pub const SIGNATURE_LENGTH: usize = 65; From 53e02f4430763887b12bf41efe509037f078047b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 14 Feb 2018 12:13:40 +0100 Subject: [PATCH 141/152] add docstrings --- bridge/src/message_to_mainnet.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index fc2c37f..fe8e6cd 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -2,8 +2,11 @@ use ethereum_types::{Address, U256, H256}; use contracts::foreign::events::Withdraw; use web3::types::Log; use ethabi; -use error::Error; +use error::{Error, ErrorKind}; +/// the message that is relayed from side to main. +/// contains all the information required for the relay. +/// validators sign off on this message. #[derive(PartialEq, Debug)] pub struct MessageToMainnet { pub recipient: Address, @@ -12,9 +15,11 @@ pub struct MessageToMainnet { pub mainnet_gas_price: U256, } +/// length of a `MessageToMainnet.to_bytes()` in bytes pub const MESSAGE_LENGTH: usize = 116; impl MessageToMainnet { + /// parses message from a byte slice pub fn from_bytes(bytes: &[u8]) -> Self { assert_eq!(bytes.len(), MESSAGE_LENGTH); @@ -26,7 +31,7 @@ impl MessageToMainnet { } } - /// construct a message from a `Withdraw` that was logged on `foreign` + /// construct a message from a `Withdraw` event that was logged on `foreign` pub fn from_log(web3_log: Log) -> Result { let ethabi_raw_log = ethabi::RawLog { topics: web3_log.topics, @@ -43,8 +48,9 @@ impl MessageToMainnet { }) } - /// mainly used to construct the message to be passed to - /// `submitSignature` + /// serializes message to a byte vector. + /// mainly used to construct the message byte vector that is then signed + /// and passed to `ForeignBridge.submitSignature` pub fn to_bytes(&self) -> Vec { let mut result = vec![0u8; MESSAGE_LENGTH]; result[0..20].copy_from_slice(&self.recipient.0[..]); @@ -54,6 +60,7 @@ impl MessageToMainnet { return result; } + /// serializes message to an ethabi payload pub fn to_payload(&self) -> Vec { ethabi::encode(&[ethabi::Token::Bytes(self.to_bytes())]) } From 55192e9830b969588bf2920d518c2046808d1a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Wed, 14 Feb 2018 12:13:49 +0100 Subject: [PATCH 142/152] proper error handling instead of expect --- bridge/src/message_to_mainnet.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index fe8e6cd..f750d19 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -38,8 +38,8 @@ impl MessageToMainnet { data: web3_log.data.0, }; let withdraw_log = Withdraw::default().parse_log(ethabi_raw_log)?; - // TODO [snd] replace expect by result - let hash = web3_log.transaction_hash.expect("log to be mined and contain `transaction_hash`"); + let hash = web3_log.transaction_hash + .ok_or(Error::from_kind(ErrorKind::Msg("`log` must be mined and contain `transaction_hash`".into())))?; Ok(Self { recipient: withdraw_log.recipient.0.into(), value: U256(withdraw_log.value.0), From 189d5b2331b76d84c51951b0d316998e00ba6689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 11:17:42 +0100 Subject: [PATCH 143/152] remove redundant conversions resolves grumbles: https://github.com/paritytech/parity-bridge/pull/114#discussion_r168407959 https://github.com/paritytech/parity-bridge/pull/114#discussion_r168408026 --- bridge/src/message_to_mainnet.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index f750d19..8a80d38 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -41,10 +41,10 @@ impl MessageToMainnet { let hash = web3_log.transaction_hash .ok_or(Error::from_kind(ErrorKind::Msg("`log` must be mined and contain `transaction_hash`".into())))?; Ok(Self { - recipient: withdraw_log.recipient.0.into(), - value: U256(withdraw_log.value.0), - sidenet_transaction_hash: hash.to_vec().as_slice().into(), - mainnet_gas_price: U256(withdraw_log.home_gas_price.0), + recipient: withdraw_log.recipient, + value: withdraw_log.value, + sidenet_transaction_hash: hash, + mainnet_gas_price: withdraw_log.home_gas_price, }) } From ca7f758587b490a610f8548d34294b69bad3a398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 11:18:26 +0100 Subject: [PATCH 144/152] remove unnecessary `.clone()` resolves grumble: https://github.com/paritytech/parity-bridge/pull/114#discussion_r168406837 --- bridge/src/bridge/withdraw_relay.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index 49a46b0..e6f30c9 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -191,7 +191,7 @@ impl Stream for WithdrawRelay { signatures.iter().map(|x| Signature::s_from_bytes(x.0.as_slice()).0), message.clone().0).into(); let request = TransactionRequest { - from: app.config.home.account.clone(), + from: app.config.home.account, to: Some(home_contract.clone()), gas: Some(app.config.txs.withdraw_relay.gas.into()), gas_price: Some(MessageToMainnet::from_bytes(message.0.as_slice()).mainnet_gas_price), From 6f13eb4b05bd8097bc61f7e0eac71500561b4f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 11:33:59 +0100 Subject: [PATCH 145/152] shorten error handling resolve grumble: https://github.com/paritytech/parity-bridge/pull/114#discussion_r168433291 --- bridge/src/message_to_mainnet.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bridge/src/message_to_mainnet.rs b/bridge/src/message_to_mainnet.rs index 8a80d38..749850a 100644 --- a/bridge/src/message_to_mainnet.rs +++ b/bridge/src/message_to_mainnet.rs @@ -2,7 +2,7 @@ use ethereum_types::{Address, U256, H256}; use contracts::foreign::events::Withdraw; use web3::types::Log; use ethabi; -use error::{Error, ErrorKind}; +use error::Error; /// the message that is relayed from side to main. /// contains all the information required for the relay. @@ -38,8 +38,7 @@ impl MessageToMainnet { data: web3_log.data.0, }; let withdraw_log = Withdraw::default().parse_log(ethabi_raw_log)?; - let hash = web3_log.transaction_hash - .ok_or(Error::from_kind(ErrorKind::Msg("`log` must be mined and contain `transaction_hash`".into())))?; + let hash = web3_log.transaction_hash.ok_or_else(|| "`log` must be mined and contain `transaction_hash`")?; Ok(Self { recipient: withdraw_log.recipient, value: withdraw_log.value, From f437a2f2dee236ec019695b037b49763109e8e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 11:38:57 +0100 Subject: [PATCH 146/152] README.md: mention homeGasPrice --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae5b626..191bcf1 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ they get the same amount of ERC20 tokens on `foreign`. [they can use `ForeignBridge` as they would use any ERC20 token.](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) to convert their `foreign` ERC20 into ether on `home` -users can always call `ForeignBridge.transferHomeViaRelay(homeRecipientAddress, value)`. +users can always call `ForeignBridge.transferHomeViaRelay(homeRecipientAddress, value, homeGasPrice)`. `foreign` is assumed to use PoA (proof of authority) consensus. relays between the chains happen in a byzantine fault tolerant way using the authorities of `foreign`. @@ -66,8 +66,8 @@ with identical arguments and from distinct authorities then ### high level explanation of foreign ERC20 -> home ether relay -`sender` executes `ForeignBridge.transferHomeViaRelay(recipient, value)` -which checks and reduces `ForeignBridge.balances(sender)` by `value` and emits `ForeignBridge.Withdraw(recipient, value)`. +`sender` executes `ForeignBridge.transferHomeViaRelay(recipient, value, homeGasPrice)` +which checks and reduces `ForeignBridge.balances(sender)` by `value` and emits `ForeignBridge.Withdraw(recipient, value, homeGasPrice)`. for every `ForeignBridge.Withdraw`, every bridge authority creates a message containing `value`, `recipient` and the `transactionHash` of the transaction referenced by the `ForeignBridge.Withdraw` event; From 763e065b672b6645502715e0b0b6bb62a1a1e572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 11:49:47 +0100 Subject: [PATCH 147/152] update readme --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 191bcf1..d94dd5b 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ pay for the gas. this opened up an attack where a malicious user could deposit a very small amount of wei on `HomeBridge`, get it relayed to `ForeignBridge`, -then spam `ForeignBridge.transfer` with `1` wei withdraws. +then spam `ForeignBridge.transferHomeViaRelay` with `1` wei withdraws. it would cost the attacker very little `home` chain wei and essentially free `foreign` testnet wei to cause the authorities to spend orders of magnitude more wei to relay the withdraw to `home` by executing `HomeBridge.withdraw`. @@ -284,9 +284,13 @@ to shut down this attack `HomeBridge.withdraw` was modified so doing the relay. this way the `recipient` pays the relaying `authority` for the execution of the `withdraw` transaction. -if the value withdrawn is too low to pay for the relay at current gas prices then -bridge authorities will ignore it. one can think of it as value getting -spent entirely on paying the relay with no value left to pay out the recipient. +relayers can set the gas price for `HomeBridge.withdraw`. +they could set a very high gas price resulting in a very high `cost` through which they could large portions of `value`. +to shut down this attack the `homeGasPrice` param was added to `ForeignBridge.transferHomeViaRelay`. +end users have control over the cost/latency tradeoff of their relay transaction through the `homeGasPrice`. +relayers have to set gas price to `homeGasPrice` when calling `HomeBridge.withdraw`. +the `recipient` for `value` is the exception and can freely choose any gas price. +see https://github.com/paritytech/parity-bridge/issues/112 for more details. `HomeBridge.withdraw` is currently the only transaction bridge authorities execute on `home`. care must be taken to secure future functions that bridge authorities will execute From 4226a045cdeefcaae8c2600cc8da670dc48a567e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 12:07:36 +0100 Subject: [PATCH 148/152] README.md: add missing word --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d94dd5b..fca0f16 100644 --- a/README.md +++ b/README.md @@ -285,7 +285,7 @@ doing the relay. this way the `recipient` pays the relaying `authority` for the execution of the `withdraw` transaction. relayers can set the gas price for `HomeBridge.withdraw`. -they could set a very high gas price resulting in a very high `cost` through which they could large portions of `value`. +they could set a very high gas price resulting in a very high `cost` through which they could burn large portions of `value`. to shut down this attack the `homeGasPrice` param was added to `ForeignBridge.transferHomeViaRelay`. end users have control over the cost/latency tradeoff of their relay transaction through the `homeGasPrice`. relayers have to set gas price to `homeGasPrice` when calling `HomeBridge.withdraw`. From 0246119518525bc520fbaa2997cfd730d4e52b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 12:49:12 +0100 Subject: [PATCH 149/152] remove panics. improve error handling for signature. resolves grumble: https://github.com/paritytech/parity-bridge/pull/114#discussion_r168406741 --- bridge/src/bridge/withdraw_relay.rs | 15 ++++++++----- bridge/src/signature.rs | 35 ++++++++++------------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/bridge/src/bridge/withdraw_relay.rs b/bridge/src/bridge/withdraw_relay.rs index e6f30c9..2077fbc 100644 --- a/bridge/src/bridge/withdraw_relay.rs +++ b/bridge/src/bridge/withdraw_relay.rs @@ -174,10 +174,15 @@ impl Stream for WithdrawRelay { .map(|signatures| signatures.iter().map( |signature| { - app.foreign_bridge.functions().signature().output(signature.0.as_slice()).map(Bytes) + Signature::from_bytes( + app.foreign_bridge + .functions() + .signature() + .output(signature.0.as_slice())? + .as_slice()) } ) - .collect::>>() + .collect::, Error>>() .map_err(error::Error::from) ) .collect::>>()?; @@ -186,9 +191,9 @@ impl Stream for WithdrawRelay { .zip(signatures.into_iter()) .map(|(message, signatures)| { let payload: Bytes = app.home_bridge.functions().withdraw().input( - signatures.iter().map(|x| Signature::v_from_bytes(x.0.as_slice())), - signatures.iter().map(|x| Signature::r_from_bytes(x.0.as_slice()).0), - signatures.iter().map(|x| Signature::s_from_bytes(x.0.as_slice()).0), + signatures.iter().map(|x| x.v), + signatures.iter().map(|x| x.r), + signatures.iter().map(|x| x.s), message.clone().0).into(); let request = TransactionRequest { from: app.config.home.account, diff --git a/bridge/src/signature.rs b/bridge/src/signature.rs index 85cc358..9be316c 100644 --- a/bridge/src/signature.rs +++ b/bridge/src/signature.rs @@ -5,6 +5,8 @@ use ethereum_types::H256; use ethabi; +use error::Error; + pub const SIGNATURE_LENGTH: usize = 65; /// an ECDSA signature consisting of `v`, `r` and `s` @@ -16,26 +18,16 @@ pub struct Signature { } impl Signature { - pub fn from_bytes(bytes: &[u8]) -> Self { - assert_eq!(bytes.len(), SIGNATURE_LENGTH); - - Self { - v: Self::v_from_bytes(bytes), - r: Self::r_from_bytes(bytes), - s: Self::s_from_bytes(bytes), + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != SIGNATURE_LENGTH { + bail!("`bytes`.len() must be {}", SIGNATURE_LENGTH); } - } - pub fn v_from_bytes(bytes: &[u8]) -> u8 { - bytes[64] - } - - pub fn r_from_bytes(bytes: &[u8]) -> H256 { - bytes[0..32].into() - } - - pub fn s_from_bytes(bytes: &[u8]) -> H256 { - bytes[32..64].into() + Ok(Self { + v: bytes[64], + r: bytes[0..32].into(), + s: bytes[32..64].into(), + }) } pub fn to_bytes(&self) -> Vec { @@ -70,17 +62,14 @@ mod test { assert_eq!(s, signature.s); let bytes = signature.to_bytes(); - assert_eq!(v, Signature::v_from_bytes(bytes.as_slice())); - assert_eq!(r, Signature::r_from_bytes(bytes.as_slice())); - assert_eq!(s, Signature::s_from_bytes(bytes.as_slice())); - assert_eq!(signature, Signature::from_bytes(bytes.as_slice())); + assert_eq!(signature, Signature::from_bytes(bytes.as_slice()).unwrap()); let payload = signature.to_payload(); let mut tokens = ethabi::decode(&[ethabi::ParamType::Bytes], payload.as_slice()) .unwrap(); let decoded = tokens.pop().unwrap().to_bytes().unwrap(); - assert_eq!(signature, Signature::from_bytes(decoded.as_slice())); + assert_eq!(signature, Signature::from_bytes(decoded.as_slice()).unwrap()); TestResult::passed() } From 9753db7326062521e8f45c9c450d15941c958dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 13:13:59 +0100 Subject: [PATCH 150/152] cli/Cargo.toml: bump `env_logger` to `0.4` --- Cargo.lock | 74 +------------------------------------------------- cli/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9809c48..d999f33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,11 +1,3 @@ -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.4" @@ -87,7 +79,7 @@ version = "0.1.0" dependencies = [ "bridge 0.1.0", "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -146,15 +138,6 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "env_logger" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.4.3" @@ -406,14 +389,6 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.0.1" @@ -587,18 +562,6 @@ name = "redox_syscall" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "0.2.6" @@ -611,11 +574,6 @@ dependencies = [ "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex-syntax" version = "0.4.2" @@ -791,23 +749,6 @@ dependencies = [ "web3 0.2.0 (git+https://github.com/tomusdrw/rust-web3?branch=bridge)", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.5" @@ -952,11 +893,6 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "utf8-ranges" version = "1.0.0" @@ -1035,7 +971,6 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" @@ -1050,7 +985,6 @@ dependencies = [ "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" -"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8385a48c8ed984778dcca27efc0de162a191a14ed733a41a07d9b0cfaa999e" @@ -1078,7 +1012,6 @@ dependencies = [ "checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7da01a5e23070d92d99b1ecd1cd0af36447c6fd44b0fe283c2db199fa136724f" @@ -1099,9 +1032,7 @@ dependencies = [ "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" "checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" @@ -1126,8 +1057,6 @@ dependencies = [ "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" @@ -1143,7 +1072,6 @@ dependencies = [ "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index f97091a..f0bcbac 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -14,5 +14,5 @@ serde_derive = "1.0" tokio-core = "0.1.8" docopt = "0.8.1" log = "0.3" -env_logger = "0.3" +env_logger = "0.4" futures = "0.1.14" From 033a9234320dd1b7fcae889a5417e1562064401f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 14:22:20 +0100 Subject: [PATCH 151/152] make ForeignBridge.submitSignature a bit easier to understand --- contracts/bridge.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index adb3ed5..cd9a7f5 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -483,14 +483,13 @@ contract ForeignBridge { /// withdrawal value (uint) /// foreign transaction hash (bytes32) // to avoid transaction duplication function submitSignature(bytes signature, bytes message) public onlyAuthority() { - // Validate submited signatures - require(MessageSigning.recoverAddressFromSignedMessage(signature, message) == msg.sender); + // ensure that `signature` is really `message` signed by `msg.sender` + require(msg.sender == MessageSigning.recoverAddressFromSignedMessage(signature, message)); - // Valid withdraw message must have 116 bytes require(message.length == 116); var hash = keccak256(message); - // Duplicated signatures + // each authority can only provide one signature per message require(!Helpers.addressArrayContains(signatures[hash].signed, msg.sender)); signatures[hash].message = message; signatures[hash].signed.push(msg.sender); From 586afe8773ff2d7b71f5cc089398e6aa9d8a5670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Thu, 15 Feb 2018 14:27:07 +0100 Subject: [PATCH 152/152] bridge.sol: uint -> uint256: more explicit, clear. seen in many other solidity projects with high code quality --- contracts/bridge.sol | 94 ++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/contracts/bridge.sol b/contracts/bridge.sol index cd9a7f5..2d7af0a 100644 --- a/contracts/bridge.sol +++ b/contracts/bridge.sol @@ -6,7 +6,7 @@ pragma solidity ^0.4.17; library Helpers { /// returns whether `array` contains `value`. function addressArrayContains(address[] array, address value) internal pure returns (bool) { - for (uint i = 0; i < array.length; i++) { + for (uint256 i = 0; i < array.length; i++) { if (array[i] == value) { return true; } @@ -16,10 +16,10 @@ library Helpers { // returns the digits of `inputValue` as a string. // example: `uintToString(12345678)` returns `"12345678"` - function uintToString(uint inputValue) internal pure returns (string) { + function uintToString(uint256 inputValue) internal pure returns (string) { // figure out the length of the resulting string - uint length = 0; - uint currentValue = inputValue; + uint256 length = 0; + uint256 currentValue = inputValue; do { length++; currentValue /= 10; @@ -27,7 +27,7 @@ library Helpers { // allocate enough memory bytes memory result = new bytes(length); // construct the string backwards - uint i = length - 1; + uint256 i = length - 1; currentValue = inputValue; do { result[i--] = byte(48 + currentValue % 10); @@ -40,7 +40,7 @@ library Helpers { /// contain `requiredSignatures` distinct correct signatures /// where signer is in `allowed_signers` /// that signed `message` - function hasEnoughValidSignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] allowed_signers, uint requiredSignatures) internal pure returns (bool) { + function hasEnoughValidSignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] allowed_signers, uint256 requiredSignatures) internal pure returns (bool) { // not enough signatures if (vs.length < requiredSignatures) { return false; @@ -49,7 +49,7 @@ library Helpers { var hash = MessageSigning.hashMessage(message); var encountered_addresses = new address[](allowed_signers.length); - for (uint i = 0; i < requiredSignatures; i++) { + for (uint256 i = 0; i < requiredSignatures; i++) { var recovered_address = ecrecover(hash, vs[i], rs[i], ss[i]); // only signatures by addresses in `addresses` are allowed if (!addressArrayContains(allowed_signers, recovered_address)) { @@ -77,7 +77,7 @@ library HelpersTest { return Helpers.uintToString(inputValue); } - function hasEnoughValidSignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint requiredSignatures) public pure returns (bool) { + function hasEnoughValidSignatures(bytes message, uint8[] vs, bytes32[] rs, bytes32[] ss, address[] addresses, uint256 requiredSignatures) public pure returns (bool) { return Helpers.hasEnoughValidSignatures(message, vs, rs, ss, addresses, requiredSignatures); } } @@ -117,11 +117,11 @@ library MessageSigningTest { library Message { // layout of message :: bytes: - // offset 0: 32 bytes :: uint (little endian) - message length + // offset 0: 32 bytes :: uint256 (little endian) - message length // offset 32: 20 bytes :: address - recipient address - // offset 52: 32 bytes :: uint (little endian) - value + // offset 52: 32 bytes :: uint256 (little endian) - value // offset 84: 32 bytes :: bytes32 - transaction hash - // offset 116: 32 bytes :: uint (little endian) - home gas price + // offset 116: 32 bytes :: uint256 (little endian) - home gas price // bytes 1 to 32 are 0 because message length is stored as little endian. // mload always reads 32 bytes. @@ -143,8 +143,8 @@ library Message { return recipient; } - function getValue(bytes message) internal pure returns (uint) { - uint value; + function getValue(bytes message) internal pure returns (uint256) { + uint256 value; // solium-disable-next-line security/no-inline-assembly assembly { value := mload(add(message, 52)) @@ -161,8 +161,8 @@ library Message { return hash; } - function getHomeGasPrice(bytes message) internal pure returns (uint) { - uint gasPrice; + function getHomeGasPrice(bytes message) internal pure returns (uint256) { + uint256 gasPrice; // solium-disable-next-line security/no-inline-assembly assembly { gasPrice := mload(add(message, 116)) @@ -178,7 +178,7 @@ library MessageTest { return Message.getRecipient(message); } - function getValue(bytes message) public pure returns (uint) { + function getValue(bytes message) public pure returns (uint256) { return Message.getValue(message); } @@ -186,7 +186,7 @@ library MessageTest { return Message.getTransactionHash(message); } - function getHomeGasPrice(bytes message) public pure returns (uint) { + function getHomeGasPrice(bytes message) public pure returns (uint256) { return Message.getHomeGasPrice(message); } } @@ -196,14 +196,14 @@ contract HomeBridge { /// Number of authorities signatures required to withdraw the money. /// /// Must be lesser than number of authorities. - uint public requiredSignatures; + uint256 public requiredSignatures; /// The gas cost of calling `HomeBridge.withdraw`. /// /// Is subtracted from `value` on withdraw. /// recipient pays the relaying authority for withdraw. /// this shuts down attacks that exhaust authorities funds on home chain. - uint public estimatedGasCostOfWithdraw; + uint256 public estimatedGasCostOfWithdraw; /// Contract authorities. address[] public authorities; @@ -212,16 +212,16 @@ contract HomeBridge { mapping (bytes32 => bool) withdraws; /// Event created on money deposit. - event Deposit (address recipient, uint value); + event Deposit (address recipient, uint256 value); /// Event created on money withdraw. - event Withdraw (address recipient, uint value); + event Withdraw (address recipient, uint256 value); /// Constructor. function HomeBridge( - uint requiredSignaturesParam, + uint256 requiredSignaturesParam, address[] authoritiesParam, - uint estimatedGasCostOfWithdrawParam + uint256 estimatedGasCostOfWithdrawParam ) public { require(requiredSignaturesParam != 0); @@ -254,9 +254,9 @@ contract HomeBridge { require(Helpers.hasEnoughValidSignatures(message, vs, rs, ss, authorities, requiredSignatures)); address recipient = Message.getRecipient(message); - uint value = Message.getValue(message); + uint256 value = Message.getValue(message); bytes32 hash = Message.getTransactionHash(message); - uint homeGasPrice = Message.getHomeGasPrice(message); + uint256 homeGasPrice = Message.getHomeGasPrice(message); // if the recipient calls `withdraw` they can choose the gas price freely. // if anyone else calls `withdraw` they have to use the gas price @@ -274,10 +274,10 @@ contract HomeBridge { // Order of operations below is critical to avoid TheDAO-like re-entry bug withdraws[hash] = true; - uint estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; + uint256 estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; // charge recipient for relay cost - uint valueRemainingAfterSubtractingCost = value - estimatedWeiCostOfWithdraw; + uint256 valueRemainingAfterSubtractingCost = value - estimatedWeiCostOfWithdraw; // pay out recipient recipient.transfer(valueRemainingAfterSubtractingCost); @@ -294,21 +294,21 @@ contract ForeignBridge { // following is the part of ForeignBridge that implements an ERC20 token. // ERC20 spec: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md - uint public totalSupply; + uint256 public totalSupply; string public name = "ForeignBridge"; /// maps addresses to their token balances - mapping (address => uint) public balances; + mapping (address => uint256) public balances; // owner of account approves the transfer of an amount by another account - mapping(address => mapping (address => uint)) allowed; + mapping(address => mapping (address => uint256)) allowed; /// Event created on money transfer - event Transfer(address indexed from, address indexed to, uint tokens); + event Transfer(address indexed from, address indexed to, uint256 tokens); // returns the ERC20 token balance of the given address - function balanceOf(address tokenOwner) public view returns (uint) { + function balanceOf(address tokenOwner) public view returns (uint256) { return balances[tokenOwner]; } @@ -316,7 +316,7 @@ contract ForeignBridge { /// /// does not affect `home` chain. does not do a relay. /// as specificed in ERC20 this doesn't fail if tokens == 0. - function transfer(address recipient, uint tokens) public returns (bool) { + function transfer(address recipient, uint256 tokens) public returns (bool) { require(balances[msg.sender] >= tokens); // fails if there is an overflow require(balances[recipient] + tokens >= balances[recipient]); @@ -333,11 +333,11 @@ contract ForeignBridge { // created when `approve` is executed to mark that // `tokenOwner` has approved `spender` to spend `tokens` of his tokens - event Approval(address indexed tokenOwner, address indexed spender, uint tokens); + event Approval(address indexed tokenOwner, address indexed spender, uint256 tokens); // allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. // calling this function repeatedly overwrites the current allowance. - function approve(address spender, uint tokens) public returns (bool) { + function approve(address spender, uint256 tokens) public returns (bool) { allowed[msg.sender][spender] = tokens; Approval(msg.sender, spender, tokens); return true; @@ -380,9 +380,9 @@ contract ForeignBridge { /// Number of authorities signatures required to withdraw the money. /// /// Must be less than number of authorities. - uint public requiredSignatures; + uint256 public requiredSignatures; - uint public estimatedGasCostOfWithdraw; + uint256 public estimatedGasCostOfWithdraw; /// Contract authorities. address[] public authorities; @@ -394,18 +394,18 @@ contract ForeignBridge { mapping (bytes32 => SignaturesCollection) signatures; /// triggered when relay of deposit from HomeBridge is complete - event Deposit(address recipient, uint value); + event Deposit(address recipient, uint256 value); /// Event created on money withdraw. - event Withdraw(address recipient, uint value, uint homeGasPrice); + event Withdraw(address recipient, uint256 value, uint256 homeGasPrice); /// Collected signatures which should be relayed to home chain. event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash); function ForeignBridge( - uint _requiredSignatures, + uint256 _requiredSignatures, address[] _authorities, - uint _estimatedGasCostOfWithdraw + uint256 _estimatedGasCostOfWithdraw ) public { require(_requiredSignatures != 0); @@ -424,9 +424,9 @@ contract ForeignBridge { /// Used to deposit money to the contract. /// /// deposit recipient (bytes20) - /// deposit value (uint) + /// deposit value (uint256) /// mainnet transaction hash (bytes32) // to avoid transaction duplication - function deposit(address recipient, uint value, bytes32 transactionHash) public onlyAuthority() { + function deposit(address recipient, uint256 value, bytes32 transactionHash) public onlyAuthority() { // Protection from misbehaving authority var hash = keccak256(recipient, value, transactionHash); @@ -456,12 +456,12 @@ contract ForeignBridge { /// once `requiredSignatures` are collected a `CollectedSignatures` event will be emitted. /// an authority will pick up `CollectedSignatures` an call `HomeBridge.withdraw` /// which transfers `value - relayCost` to `recipient` completing the transfer. - function transferHomeViaRelay(address recipient, uint value, uint homeGasPrice) public { + function transferHomeViaRelay(address recipient, uint256 value, uint256 homeGasPrice) public { require(balances[msg.sender] >= value); // don't allow 0 value transfers to home require(value > 0); - uint estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; + uint256 estimatedWeiCostOfWithdraw = estimatedGasCostOfWithdraw * homeGasPrice; require(value > estimatedWeiCostOfWithdraw); balances[msg.sender] -= value; @@ -480,7 +480,7 @@ contract ForeignBridge { /// /// for withdraw message contains: /// withdrawal recipient (bytes20) - /// withdrawal value (uint) + /// withdrawal value (uint256) /// foreign transaction hash (bytes32) // to avoid transaction duplication function submitSignature(bytes signature, bytes message) public onlyAuthority() { // ensure that `signature` is really `message` signed by `msg.sender` @@ -502,7 +502,7 @@ contract ForeignBridge { } /// Get signature - function signature(bytes32 hash, uint index) public view returns (bytes) { + function signature(bytes32 hash, uint256 index) public view returns (bytes) { return signatures[hash].signatures[index]; }