Merge pull request #95 from paritytech/snd-integration-tests
fix for #87 & integration tests to prevent regression
This commit is contained in:
commit
7d9a875cab
|
@ -22,3 +22,5 @@ truffle/build
|
|||
node_modules
|
||||
|
||||
compiled_contracts
|
||||
|
||||
integration-tests/tmp
|
||||
|
|
21
.travis.yml
21
.travis.yml
|
@ -13,8 +13,13 @@ 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:
|
||||
- cargo test --all
|
||||
- env BACKTRACE=1 cargo test --all -- --nocapture
|
||||
- language: rust
|
||||
rust: beta
|
||||
cache: cargo
|
||||
|
@ -23,8 +28,13 @@ 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:
|
||||
- cargo test --all
|
||||
- env BACKTRACE=1 cargo test --all -- --nocapture
|
||||
- language: rust
|
||||
rust: nightly
|
||||
cache: cargo
|
||||
|
@ -33,8 +43,13 @@ 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:
|
||||
- cargo test --all
|
||||
- env BACKTRACE=1 cargo test --all -- --nocapture
|
||||
- language: node_js
|
||||
node_js: node
|
||||
cache: yarn
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,2 +1,2 @@
|
|||
[workspace]
|
||||
members = ["tests", "cli", "bridge"]
|
||||
members = ["tests", "cli", "bridge", "integration-tests"]
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -88,9 +90,13 @@ impl<T: Transport> Stream for WithdrawConfirm<T> {
|
|||
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::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let requests = withdraws.clone()
|
||||
|
@ -102,6 +108,7 @@ impl<T: Transport> Stream for WithdrawConfirm<T> {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
info!("signing");
|
||||
WithdrawConfirmState::SignWithdraws {
|
||||
future: join_all(requests),
|
||||
withdraws: withdraws,
|
||||
|
@ -110,13 +117,14 @@ impl<T: Transport> Stream for WithdrawConfirm<T> {
|
|||
},
|
||||
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;
|
||||
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()),
|
||||
|
@ -128,12 +136,14 @@ impl<T: Transport> Stream for WithdrawConfirm<T> {
|
|||
condition: None,
|
||||
})
|
||||
.map(|request| {
|
||||
info!("submitting signature");
|
||||
app.timer.timeout(
|
||||
api::send_transaction(&app.connections.foreign, request),
|
||||
app.config.foreign.request_timeout)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
info!("submitting {} signatures", confirmations.len());
|
||||
WithdrawConfirmState::ConfirmWithdraws {
|
||||
future: join_all(confirmations),
|
||||
block,
|
||||
|
@ -141,10 +151,14 @@ impl<T: Transport> Stream for WithdrawConfirm<T> {
|
|||
},
|
||||
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()),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
@ -37,6 +38,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);
|
||||
|
@ -90,7 +92,10 @@ fn withdraw_relay_payload(home: &home::HomeBridge, signatures: &[Bytes], message
|
|||
pub enum WithdrawRelayState<T: Transport> {
|
||||
Wait,
|
||||
FetchMessagesSignatures {
|
||||
future: Join<JoinAll<Vec<Timeout<ApiCall<Bytes, T::Out>>>>, JoinAll<Vec<JoinAll<Vec<Timeout<ApiCall<Bytes, T::Out>>>>>>>,
|
||||
future: Join<
|
||||
JoinAll<Vec<Timeout<ApiCall<Bytes, T::Out>>>>,
|
||||
JoinAll<Vec<JoinAll<Vec<Timeout<ApiCall<Bytes, T::Out>>>>>>
|
||||
>,
|
||||
block: u64,
|
||||
},
|
||||
FetchMessageValueSufficient {
|
||||
|
@ -141,13 +146,17 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
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::<error::Result<Vec<_>>>()?;
|
||||
|
||||
let (signatures, messages): (Vec<_>, Vec<_>) = assignments.into_iter()
|
||||
|
@ -176,19 +185,41 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
.map(|calls| join_all(calls))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// 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,
|
||||
}
|
||||
},
|
||||
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::<ethabi::Result<Vec<_>>>()
|
||||
.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::<ethabi::Result<Vec<_>>>()
|
||||
.map_err(error::Error::from)
|
||||
)
|
||||
.collect::<error::Result<Vec<_>>>()?;
|
||||
|
||||
let message_value_sufficient_payloads = messages
|
||||
.iter()
|
||||
.map(|message| {
|
||||
|
@ -204,6 +235,7 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
info!("fetching whether message values are sufficent");
|
||||
WithdrawRelayState::FetchMessageValueSufficient {
|
||||
future: join_all(message_value_sufficient_payloads),
|
||||
messages,
|
||||
|
@ -218,6 +250,7 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
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 +260,16 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
.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 +288,7 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
app.config.home.request_timeout)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// wait for relays to complete
|
||||
info!("relaying {} withdraws", relays.len());
|
||||
WithdrawRelayState::RelayWithdraws {
|
||||
future: join_all(relays),
|
||||
block,
|
||||
|
@ -259,10 +296,14 @@ impl<T: Transport> Stream for WithdrawRelay<T> {
|
|||
},
|
||||
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()),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "integration-tests"
|
||||
version = "0.1.0"
|
||||
authors = ["snd <kruemaxi@gmail.com>"]
|
||||
|
||||
[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" }
|
||||
tokio-core = "0.1.8"
|
|
@ -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 }
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,238 @@
|
|||
/// spins up two parity nodes with the dev chain.
|
||||
/// 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;
|
||||
extern crate web3;
|
||||
extern crate tokio_core;
|
||||
extern crate bridge;
|
||||
|
||||
use std::process::Command;
|
||||
use std::time::Duration;
|
||||
use std::thread;
|
||||
use std::path::Path;
|
||||
|
||||
use tokio_core::reactor::Core;
|
||||
|
||||
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("dev")
|
||||
.arg("--ipc-path").arg("home.ipc")
|
||||
.arg("--logging").arg("rpc=trace")
|
||||
.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("dev")
|
||||
.arg("--ipc-path").arg("foreign.ipc")
|
||||
.arg("--logging").arg("rpc=trace")
|
||||
.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
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
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")
|
||||
.env("RUST_BACKTRACE", "1")
|
||||
.current_dir("../cli")
|
||||
.arg("build")
|
||||
.status()
|
||||
.expect("failed to build bridge cli")
|
||||
.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));
|
||||
|
||||
// start bridge authority 1
|
||||
let mut bridge1 = Command::new("env")
|
||||
.arg("RUST_BACKTRACE=1")
|
||||
.arg("../target/debug/bridge")
|
||||
.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));
|
||||
|
||||
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":[{
|
||||
"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. 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");
|
||||
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_eth = web3::api::Eth::new(home_transport);
|
||||
|
||||
// balance on ForeignBridge should have increased
|
||||
let balance_payload = foreign.functions().balances().input(Address::from("0x00a329c0648769a73afac7f9381e08fb43dbea72"));
|
||||
|
||||
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 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");
|
||||
|
||||
println!("\nconfirmed that deposit reached foreign\n");
|
||||
|
||||
// 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,
|
||||
});
|
||||
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));
|
||||
|
||||
// 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();
|
||||
}
|
|
@ -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""#;
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue