2018-04-03 23:42:16 -07:00
use std ::sync ::{ Arc , RwLock } ;
2018-06-01 18:31:47 -07:00
use futures ::{ self , Future , Stream , stream ::{ Collect , FuturesUnordered , futures_unordered } , Poll } ;
2017-08-24 05:50:48 -07:00
use futures ::future ::{ JoinAll , join_all , Join } ;
2017-08-31 08:32:34 -07:00
use tokio_timer ::Timeout ;
2017-08-12 11:03:48 -07:00
use web3 ::Transport ;
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
use web3 ::types ::{ U256 , Address , FilterBuilder , Log , Bytes } ;
2018-05-23 00:56:13 -07:00
use ethabi ::{ RawLog , self } ;
2017-08-13 10:28:41 -07:00
use app ::App ;
2017-08-31 08:32:34 -07:00
use api ::{ self , LogStream , ApiCall } ;
2018-02-14 03:13:11 -08:00
use contracts ::foreign ;
2017-08-24 09:42:19 -07:00
use util ::web3_filter ;
2017-08-13 10:28:41 -07:00
use database ::Database ;
2018-04-03 23:42:16 -07:00
use error ::{ self , Error , ErrorKind } ;
2018-02-14 03:13:11 -08:00
use message_to_mainnet ::MessageToMainnet ;
use signature ::Signature ;
2018-04-25 03:12:39 -07:00
use ethcore_transaction ::{ Transaction , Action } ;
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
use super ::nonce ::{ NonceCheck , SendRawTransaction } ;
2018-05-25 00:24:16 -07:00
use super ::BridgeChecked ;
2018-04-25 03:12:39 -07:00
use itertools ::Itertools ;
2017-08-12 11:03:48 -07:00
2018-01-08 02:43:55 -08:00
/// returns a filter for `ForeignBridge.CollectedSignatures` events
2018-05-19 08:25:39 -07:00
fn collected_signatures_filter < I : IntoIterator < Item = Address > > ( foreign : & foreign ::ForeignBridge , addresses : I ) -> FilterBuilder {
2018-05-23 00:56:13 -07:00
let filter = foreign . events ( ) . collected_signatures ( ) . create_filter ( ) ;
2018-05-19 08:25:39 -07:00
web3_filter ( filter , addresses )
2017-08-23 10:09:51 -07:00
}
2018-01-08 05:14:39 -08:00
/// payloads for calls to `ForeignBridge.signature` and `ForeignBridge.message`
/// to retrieve the signatures (v, r, s) and messages
/// which the withdraw relay process should later relay to `HomeBridge`
2018-01-08 02:43:55 -08:00
/// by calling `HomeBridge.withdraw(v, r, s, message)`
2017-08-28 03:28:21 -07:00
#[ derive(Debug, PartialEq) ]
struct RelayAssignment {
signature_payloads : Vec < Bytes > ,
message_payload : Bytes ,
2017-08-23 10:09:51 -07:00
}
2018-05-23 00:56:13 -07:00
fn signatures_payload ( foreign : & foreign ::ForeignBridge , my_address : Address , log : Log ) -> error ::Result < Option < RelayAssignment > > {
2018-01-08 05:12:55 -08:00
// convert web3::Log to ethabi::RawLog since ethabi events can
// only be parsed from the latter
2017-08-23 10:09:51 -07:00
let raw_log = RawLog {
2018-02-06 13:57:06 -08:00
topics : log . topics . into_iter ( ) . map ( | t | t . 0. into ( ) ) . collect ( ) ,
2017-08-23 10:09:51 -07:00
data : log . data . 0 ,
} ;
2017-10-10 02:02:46 -07:00
let collected_signatures = foreign . events ( ) . collected_signatures ( ) . parse_log ( raw_log ) ? ;
2018-02-06 13:57:06 -08:00
if collected_signatures . authority_responsible_for_relay ! = my_address . 0. into ( ) {
2018-01-19 05:49:54 -08:00
info! ( " bridge not responsible for relaying transaction to home. tx hash: {} " , log . transaction_hash . unwrap ( ) ) ;
2018-01-08 05:12:55 -08:00
// this authority is not responsible for relaying this transaction.
// someone else will relay this transaction to home.
2018-05-23 00:56:13 -07:00
return Ok ( None ) ;
2017-08-23 10:09:51 -07:00
}
2018-05-23 00:56:13 -07:00
let required_signatures : U256 = ( & foreign . functions ( ) . message ( ) . input ( collected_signatures . number_of_collected_signatures ) [ 4 .. ] ) . into ( ) ;
let signature_payloads = ( 0 .. required_signatures . low_u32 ( ) ) . into_iter ( )
2017-10-10 02:02:46 -07:00
. map ( | index | foreign . functions ( ) . signature ( ) . input ( collected_signatures . message_hash , index ) )
2017-08-23 10:09:51 -07:00
. map ( Into ::into )
. collect ( ) ;
2017-10-10 02:02:46 -07:00
let message_payload = foreign . functions ( ) . message ( ) . input ( collected_signatures . message_hash ) . into ( ) ;
2017-08-24 05:50:48 -07:00
2018-05-23 00:56:13 -07:00
Ok ( Some ( RelayAssignment {
2017-08-24 05:50:48 -07:00
signature_payloads ,
message_payload ,
2018-05-23 00:56:13 -07:00
} ) )
2017-08-24 05:50:48 -07:00
}
2018-01-08 05:15:41 -08:00
/// state of the withdraw relay state machine
2017-08-12 11:03:48 -07:00
pub enum WithdrawRelayState < T : Transport > {
Wait ,
2018-01-08 02:18:26 -08:00
FetchMessagesSignatures {
2018-01-22 05:33:53 -08:00
future : Join <
JoinAll < Vec < Timeout < ApiCall < Bytes , T ::Out > > > > ,
JoinAll < Vec < JoinAll < Vec < Timeout < ApiCall < Bytes , T ::Out > > > > > >
> ,
2017-08-23 10:09:51 -07:00
block : u64 ,
} ,
2017-08-13 07:13:03 -07:00
RelayWithdraws {
2018-06-01 18:31:47 -07:00
future : Collect < FuturesUnordered < NonceCheck < T , SendRawTransaction < T > > > > ,
2017-08-12 11:03:48 -07:00
block : u64 ,
} ,
Yield ( Option < u64 > ) ,
}
2018-05-23 17:42:13 -07:00
pub fn create_withdraw_relay < T : Transport + Clone > ( app : Arc < App < T > > , init : & Database , home_balance : Arc < RwLock < Option < U256 > > > , home_chain_id : u64 , home_gas_price : Arc < RwLock < u64 > > ) -> WithdrawRelay < T > {
2017-08-13 10:28:41 -07:00
let logs_init = api ::LogStreamInit {
after : init . checked_withdraw_relay ,
2017-10-10 02:02:46 -07:00
request_timeout : app . config . foreign . request_timeout ,
poll_interval : app . config . foreign . poll_interval ,
confirmations : app . config . foreign . required_confirmations ,
2018-05-23 00:56:13 -07:00
filter : collected_signatures_filter ( & app . foreign_bridge , vec! [ init . foreign_contract_address ] ) ,
2017-08-13 10:28:41 -07:00
} ;
WithdrawRelay {
2017-10-10 02:02:46 -07:00
logs : api ::log_stream ( app . connections . foreign . clone ( ) , app . timer . clone ( ) , logs_init ) ,
2018-02-07 05:58:50 -08:00
home_contract : init . home_contract_address ,
foreign_contract : init . foreign_contract_address ,
2018-05-23 00:56:13 -07:00
state : WithdrawRelayState ::Wait ,
2017-08-13 10:28:41 -07:00
app ,
2018-04-03 23:42:16 -07:00
home_balance ,
2018-04-25 03:12:39 -07:00
home_chain_id ,
2018-05-23 17:42:13 -07:00
home_gas_price ,
2017-08-13 10:28:41 -07:00
}
}
2017-08-12 11:03:48 -07:00
pub struct WithdrawRelay < T : Transport > {
2017-08-13 10:28:41 -07:00
app : Arc < App < T > > ,
logs : LogStream < T > ,
2017-08-12 11:03:48 -07:00
state : WithdrawRelayState < T > ,
2017-10-10 02:02:46 -07:00
foreign_contract : Address ,
home_contract : Address ,
2018-04-03 23:42:16 -07:00
home_balance : Arc < RwLock < Option < U256 > > > ,
2018-04-25 03:12:39 -07:00
home_chain_id : u64 ,
2018-05-23 17:42:13 -07:00
home_gas_price : Arc < RwLock < u64 > > ,
2017-08-12 11:03:48 -07:00
}
impl < T : Transport > Stream for WithdrawRelay < T > {
2018-05-25 00:24:16 -07:00
type Item = BridgeChecked ;
2017-08-12 11:03:48 -07:00
type Error = Error ;
fn poll ( & mut self ) -> Poll < Option < Self ::Item > , Self ::Error > {
2018-04-25 03:12:39 -07:00
let app = & self . app ;
let gas = self . app . config . txs . withdraw_relay . gas . into ( ) ;
2018-05-23 17:42:13 -07:00
let gas_price = U256 ::from ( * self . home_gas_price . read ( ) . unwrap ( ) ) ;
2018-04-25 03:12:39 -07:00
let contract = self . home_contract . clone ( ) ;
let home = & self . app . config . home ;
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
let t = & self . app . connections . home ;
2018-05-19 08:25:39 -07:00
let foreign = & self . app . connections . foreign ;
2018-04-25 03:12:39 -07:00
let chain_id = self . home_chain_id ;
2018-05-19 08:25:39 -07:00
let foreign_bridge = & self . app . foreign_bridge ;
let foreign_account = self . app . config . foreign . account ;
let timer = & self . app . timer ;
let foreign_contract = self . foreign_contract ;
let foreign_request_timeout = self . app . config . foreign . request_timeout ;
2018-04-25 03:12:39 -07:00
2017-08-13 10:28:41 -07:00
loop {
let next_state = match self . state {
WithdrawRelayState ::Wait = > {
2018-05-07 16:34:03 -07:00
let item = try_stream! ( self . logs . poll ( ) . map_err ( | e | ErrorKind ::ContextualizedError ( Box ::new ( e ) , " polling foreign for collected signatures " ) ) ) ;
2018-01-19 05:49:54 -08:00
info! ( " got {} new signed withdraws to relay " , item . logs . len ( ) ) ;
2017-08-23 10:09:51 -07:00
let assignments = item . logs
. into_iter ( )
2018-05-23 00:56:13 -07:00
. map ( | log | signatures_payload (
2018-05-19 08:25:39 -07:00
foreign_bridge ,
foreign_account ,
2018-05-23 00:56:13 -07:00
log ) )
. collect ::< error ::Result < Vec < _ > > > ( ) ? ;
2017-08-24 05:50:48 -07:00
let ( signatures , messages ) : ( Vec < _ > , Vec < _ > ) = assignments . into_iter ( )
2017-08-28 03:28:21 -07:00
. filter_map ( | a | a )
. map ( | assignment | ( assignment . signature_payloads , assignment . message_payload ) )
2017-08-24 05:50:48 -07:00
. unzip ( ) ;
2017-08-24 09:42:19 -07:00
2017-08-24 05:50:48 -07:00
let message_calls = messages . into_iter ( )
2017-08-31 08:32:34 -07:00
. map ( | payload | {
2018-05-19 08:25:39 -07:00
timer . timeout (
api ::call ( foreign , foreign_contract . clone ( ) , payload ) ,
foreign_request_timeout )
2017-08-31 08:32:34 -07:00
} )
2017-08-24 05:50:48 -07:00
. collect ::< Vec < _ > > ( ) ;
let signature_calls = signatures . into_iter ( )
2017-08-23 10:09:51 -07:00
. map ( | payloads | {
payloads . into_iter ( )
2017-08-31 08:32:34 -07:00
. map ( | payload | {
2018-05-19 08:25:39 -07:00
timer . timeout (
api ::call ( foreign , foreign_contract . clone ( ) , payload ) ,
foreign_request_timeout )
2017-08-31 08:32:34 -07:00
} )
2017-08-23 10:09:51 -07:00
. collect ::< Vec < _ > > ( )
} )
. map ( | calls | join_all ( calls ) )
. collect ::< Vec < _ > > ( ) ;
2017-08-24 09:42:19 -07:00
2018-01-19 05:49:54 -08:00
info! ( " fetching messages and signatures " ) ;
2018-01-08 02:18:26 -08:00
WithdrawRelayState ::FetchMessagesSignatures {
2017-08-24 05:50:48 -07:00
future : join_all ( message_calls ) . join ( join_all ( signature_calls ) ) ,
2017-08-23 10:09:51 -07:00
block : item . to ,
}
} ,
2018-01-08 02:18:26 -08:00
WithdrawRelayState ::FetchMessagesSignatures { ref mut future , block } = > {
2018-04-03 23:42:16 -07:00
let home_balance = self . home_balance . read ( ) . unwrap ( ) ;
if home_balance . is_none ( ) {
warn! ( " home contract balance is unknown " ) ;
return Ok ( futures ::Async ::NotReady ) ;
}
2018-05-07 16:34:03 -07:00
let ( messages_raw , signatures_raw ) = try_ready! ( future . poll ( ) . map_err ( | e | ErrorKind ::ContextualizedError ( Box ::new ( e ) , " fetching messages and signatures from foreign " ) ) ) ;
2018-01-22 06:10:57 -08:00
info! ( " fetching messages and signatures complete " ) ;
assert_eq! ( messages_raw . len ( ) , signatures_raw . len ( ) ) ;
2018-01-08 05:26:19 -08:00
2018-05-23 17:42:13 -07:00
let balance_required = gas * gas_price * U256 ::from ( messages_raw . len ( ) ) ;
2018-04-03 23:42:16 -07:00
if balance_required > * home_balance . as_ref ( ) . unwrap ( ) {
return Err ( ErrorKind ::InsufficientFunds . into ( ) )
}
2018-01-22 06:10:57 -08:00
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 ) ? ;
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
let len = messages . len ( ) ;
2018-01-22 06:10:57 -08:00
let signatures = signatures_raw
. iter ( )
. map ( | signatures |
signatures . iter ( ) . map (
| signature | {
2018-02-15 03:49:12 -08:00
Signature ::from_bytes (
app . foreign_bridge
. functions ( )
. signature ( )
. output ( signature . 0. as_slice ( ) ) ?
. as_slice ( ) )
2018-01-22 06:10:57 -08:00
}
)
2018-02-15 03:49:12 -08:00
. collect ::< Result < Vec < _ > , Error > > ( )
2018-01-22 06:10:57 -08:00
. map_err ( error ::Error ::from )
)
. collect ::< error ::Result < Vec < _ > > > ( ) ? ;
2018-01-08 05:26:19 -08:00
let relays = messages . into_iter ( )
. zip ( signatures . into_iter ( ) )
2018-02-02 06:59:54 -08:00
. map ( | ( message , signatures ) | {
2018-02-12 05:57:57 -08:00
let payload : Bytes = app . home_bridge . functions ( ) . withdraw ( ) . input (
2018-02-15 03:49:12 -08:00
signatures . iter ( ) . map ( | x | x . v ) ,
signatures . iter ( ) . map ( | x | x . r ) ,
signatures . iter ( ) . map ( | x | x . s ) ,
2018-02-12 05:57:57 -08:00
message . clone ( ) . 0 ) . into ( ) ;
2018-04-25 03:12:39 -07:00
let gas_price = MessageToMainnet ::from_bytes ( message . 0. as_slice ( ) ) . mainnet_gas_price ;
let tx = Transaction {
2018-05-23 17:42:13 -07:00
gas ,
gas_price ,
2018-04-25 03:12:39 -07:00
value : U256 ::zero ( ) ,
data : payload . 0 ,
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
nonce : U256 ::zero ( ) ,
2018-04-25 03:12:39 -07:00
action : Action ::Call ( contract ) ,
} ;
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
api ::send_transaction_with_nonce ( t . clone ( ) , app . clone ( ) , home . clone ( ) , tx , chain_id , SendRawTransaction ( t . clone ( ) ) )
} ) . collect_vec ( ) ;
2018-02-02 06:59:54 -08:00
Problem: nonce reuse
Unfortunately, bridge will still reuse nonce very often.
Specifically when trying to send more than one transaction at
a time, clearly a faulty behaviour.
Solution: chain retrieving a nonce with subsequent sending
of the transaction.
However, chaining these is not enough as it'll still fail.
This is happening because bridge module is polling all its components
(deposit_relay, withdraw_confirm, withdraw_relay) sequentially,
and some of them maybe waiting on their transactions to go through.
However, those transactions are also done as composed futures of nonce
retrieval and transaction sending. This means that it is very often
that first, these futures will go through the nonce acquisition process,
get the same values, and then submit transactions with the same nonce.
This patch makes NonceCheck future check if the transaction failed
with this specific issue of nonce reuse and effectively restarts from
the beginning in that case, repeating nonce acquisition process... until
it succeeeds.
2018-04-29 13:20:42 -07:00
info! ( " relaying {} withdraws " , len ) ;
2017-08-24 05:50:48 -07:00
WithdrawRelayState ::RelayWithdraws {
2018-06-01 18:31:47 -07:00
future : futures_unordered ( relays ) . collect ( ) ,
2017-08-24 05:50:48 -07:00
block ,
}
2017-08-13 10:28:41 -07:00
} ,
WithdrawRelayState ::RelayWithdraws { ref mut future , block } = > {
2018-05-07 16:34:03 -07:00
let _ = try_ready! ( future . poll ( ) . map_err ( | e | ErrorKind ::ContextualizedError ( Box ::new ( e ) , " sending withdrawal to home " ) ) ) ;
2018-01-19 05:49:54 -08:00
info! ( " relaying withdraws complete " ) ;
2017-08-13 10:28:41 -07:00
WithdrawRelayState ::Yield ( Some ( block ) )
} ,
WithdrawRelayState ::Yield ( ref mut block ) = > match block . take ( ) {
2018-01-19 05:49:54 -08:00
None = > {
info! ( " waiting for signed withdraws to relay " ) ;
WithdrawRelayState ::Wait
} ,
2018-05-25 00:24:16 -07:00
Some ( v ) = > return Ok ( Some ( BridgeChecked ::WithdrawRelay ( v ) ) . into ( ) ) ,
2017-08-13 10:28:41 -07:00
}
} ;
self . state = next_state ;
}
2017-08-12 11:03:48 -07:00
}
}
2017-08-28 03:28:21 -07:00
#[ cfg(test) ]
mod tests {
2017-08-28 07:48:01 -07:00
use rustc_hex ::FromHex ;
2018-05-01 10:02:01 -07:00
use web3 ::types ::{ Log , Bytes , Address } ;
2018-02-14 03:13:11 -08:00
use contracts ::foreign ;
2018-02-12 07:35:36 -08:00
use super ::signatures_payload ;
2017-08-28 03:28:21 -07:00
#[ test ]
fn test_signatures_payload ( ) {
2017-10-10 02:02:46 -07:00
let foreign = foreign ::ForeignBridge ::default ( ) ;
2018-02-07 05:50:49 -08:00
let my_address = " aff3454fce5edbc8cca8697c15331677e6ebcccc " . into ( ) ;
2017-08-28 03:28:21 -07:00
2018-05-23 00:56:13 -07:00
let data = " 000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000002 " . from_hex ( ) . unwrap ( ) ;
2017-08-28 03:28:21 -07:00
let log = Log {
data : data . into ( ) ,
2018-05-23 00:56:13 -07:00
topics : vec ! [ " 415557404d88a0c0b8e3b16967cafffc511213fd9c465c16832ee17ed57d7237 " . into ( ) ] ,
2018-02-07 05:50:49 -08:00
transaction_hash : Some ( " 884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364 " . into ( ) ) ,
2018-05-01 10:02:01 -07:00
address : Address ::zero ( ) ,
block_hash : None ,
transaction_index : None ,
log_index : None ,
transaction_log_index : None ,
log_type : None ,
block_number : None ,
removed : None ,
2017-08-28 03:28:21 -07:00
} ;
2018-05-23 00:56:13 -07:00
let assignment = signatures_payload ( & foreign , my_address , log ) . unwrap ( ) . unwrap ( ) ;
2017-08-28 03:28:21 -07:00
let expected_message : Bytes = " 490a32c600000000000000000000000000000000000000000000000000000000000000f0 " . from_hex ( ) . unwrap ( ) . into ( ) ;
let expected_signatures : Vec < Bytes > = vec! [
" 1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000 " . from_hex ( ) . unwrap ( ) . into ( ) ,
" 1812d99600000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000001 " . from_hex ( ) . unwrap ( ) . into ( ) ,
] ;
assert_eq! ( expected_message , assignment . message_payload ) ;
assert_eq! ( expected_signatures , assignment . signature_payloads ) ;
}
#[ test ]
fn test_signatures_payload_not_ours ( ) {
2017-10-10 02:02:46 -07:00
let foreign = foreign ::ForeignBridge ::default ( ) ;
2018-02-07 05:50:49 -08:00
let my_address = " aff3454fce5edbc8cca8697c15331677e6ebcccd " . into ( ) ;
2017-08-28 03:28:21 -07:00
2018-05-23 00:56:13 -07:00
let data = " 000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc00000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000002 " . from_hex ( ) . unwrap ( ) ;
2017-08-28 03:28:21 -07:00
let log = Log {
data : data . into ( ) ,
2018-05-23 00:56:13 -07:00
topics : vec ! [ " 415557404d88a0c0b8e3b16967cafffc511213fd9c465c16832ee17ed57d7237 " . into ( ) ] ,
2018-02-07 05:50:49 -08:00
transaction_hash : Some ( " 884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364 " . into ( ) ) ,
2018-05-01 10:02:01 -07:00
address : Address ::zero ( ) ,
block_hash : None ,
transaction_index : None ,
log_index : None ,
transaction_log_index : None ,
log_type : None ,
block_number : None ,
removed : None ,
2017-08-28 03:28:21 -07:00
} ;
2018-05-23 00:56:13 -07:00
let assignment = signatures_payload ( & foreign , my_address , log ) . unwrap ( ) ;
assert_eq! ( None , assignment ) ;
2017-08-28 03:28:21 -07:00
}
}