Skip to content

Commit

Permalink
WIP. Reducing eth_getLogs blocks interval.
Browse files Browse the repository at this point in the history
  • Loading branch information
artemii235 committed May 28, 2021
1 parent 6512651 commit 534973c
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 64 deletions.
166 changes: 103 additions & 63 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,11 +402,13 @@ impl EthCoinImpl {
&self,
swap_contract_address: Address,
from_block: u64,
to_block: u64,
) -> Box<dyn Future<Item = Vec<Log>, Error = String> + Send> {
let contract_event = try_fus!(SWAP_CONTRACT.event("ReceiverSpent"));
let filter = FilterBuilder::default()
.topics(Some(vec![contract_event.signature()]), None, None, None)
.from_block(BlockNumber::Number(from_block))
.to_block(BlockNumber::Number(to_block))
.address(vec![swap_contract_address])
.build();

Expand All @@ -418,79 +420,19 @@ impl EthCoinImpl {
&self,
swap_contract_address: Address,
from_block: u64,
to_block: u64,
) -> Box<dyn Future<Item = Vec<Log>, Error = String>> {
let contract_event = try_fus!(SWAP_CONTRACT.event("SenderRefunded"));
let filter = FilterBuilder::default()
.topics(Some(vec![contract_event.signature()]), None, None, None)
.from_block(BlockNumber::Number(from_block))
.to_block(BlockNumber::Number(to_block))
.address(vec![swap_contract_address])
.build();

Box::new(self.web3.eth().logs(filter).map_err(|e| ERRL!("{}", e)))
}

fn search_for_swap_tx_spend(
&self,
tx: &[u8],
swap_contract_address: Address,
search_from_block: u64,
) -> Result<Option<FoundSwapTxSpend>, String> {
let unverified: UnverifiedTransaction = try_s!(rlp::decode(tx));
let tx = try_s!(SignedEthTx::new(unverified));

let func_name = match self.coin_type {
EthCoinType::Eth => "ethPayment",
EthCoinType::Erc20 { .. } => "erc20Payment",
};

let payment_func = try_s!(SWAP_CONTRACT.function(func_name));
let decoded = try_s!(payment_func.decode_input(&tx.data));
let id = match &decoded[0] {
Token::FixedBytes(bytes) => bytes.clone(),
_ => panic!(),
};

let spend_events = try_s!(self.spend_events(swap_contract_address, search_from_block).wait());
let found = spend_events.iter().find(|event| &event.data.0[..32] == id.as_slice());

if let Some(event) = found {
match event.transaction_hash {
Some(tx_hash) => {
let transaction = match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).wait()) {
Some(t) => t,
None => return ERR!("Found ReceiverSpent event, but transaction {:02x} is missing", tx_hash),
};

return Ok(Some(FoundSwapTxSpend::Spent(TransactionEnum::from(try_s!(
signed_tx_from_web3_tx(transaction)
)))));
},
None => return ERR!("Found ReceiverSpent event, but it doesn't have tx_hash"),
}
}

let refund_events = try_s!(self.refund_events(swap_contract_address, search_from_block).wait());
let found = refund_events.iter().find(|event| &event.data.0[..32] == id.as_slice());

if let Some(event) = found {
match event.transaction_hash {
Some(tx_hash) => {
let transaction = match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).wait()) {
Some(t) => t,
None => return ERR!("Found SenderRefunded event, but transaction {:02x} is missing", tx_hash),
};

return Ok(Some(FoundSwapTxSpend::Refunded(TransactionEnum::from(try_s!(
signed_tx_from_web3_tx(transaction)
)))));
},
None => return ERR!("Found SenderRefunded event, but it doesn't have tx_hash"),
}
}

Ok(None)
}

/// Try to parse address from string.
pub fn address_from_str(&self, address: &str) -> Result<Address, String> {
Ok(try_s!(valid_addr_from_str(address)))
Expand Down Expand Up @@ -1029,6 +971,7 @@ impl SwapOps for EthCoin {
}
}

#[cfg_attr(test, mockable)]
impl MarketCoinOps for EthCoin {
fn ticker(&self) -> &str { &self.ticker[..] }

Expand Down Expand Up @@ -1162,7 +1105,20 @@ impl MarketCoinOps for EthCoin {

let fut = async move {
loop {
let events = match selfi.spend_events(swap_contract_address, from_block).compat().await {
let current_block = match selfi.current_block().compat().await {
Ok(b) => b,
Err(e) => {
log!("Error " (e) " getting block number");
Timer::sleep(5.).await;
continue;
},
};

let events = match selfi
.spend_events(swap_contract_address, from_block, current_block)
.compat()
.await
{
Ok(ev) => ev,
Err(e) => {
log!("Error " (e) " getting spend events");
Expand Down Expand Up @@ -2559,6 +2515,90 @@ impl EthCoin {
}
}
}

fn search_for_swap_tx_spend(
&self,
tx: &[u8],
swap_contract_address: Address,
search_from_block: u64,
) -> Result<Option<FoundSwapTxSpend>, String> {
let unverified: UnverifiedTransaction = try_s!(rlp::decode(tx));
let tx = try_s!(SignedEthTx::new(unverified));

let func_name = match self.coin_type {
EthCoinType::Eth => "ethPayment",
EthCoinType::Erc20 { .. } => "erc20Payment",
};

let payment_func = try_s!(SWAP_CONTRACT.function(func_name));
let decoded = try_s!(payment_func.decode_input(&tx.data));
let id = match &decoded[0] {
Token::FixedBytes(bytes) => bytes.clone(),
_ => panic!(),
};

let mut current_block = try_s!(self.current_block().wait());
if current_block < search_from_block {
current_block = search_from_block;
}

let mut from_block = search_from_block;

loop {
let to_block = current_block.max(from_block + 1000);

let spend_events = try_s!(self.spend_events(swap_contract_address, from_block, to_block).wait());
let found = spend_events.iter().find(|event| &event.data.0[..32] == id.as_slice());

if let Some(event) = found {
match event.transaction_hash {
Some(tx_hash) => {
let transaction = match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).wait())
{
Some(t) => t,
None => {
return ERR!("Found ReceiverSpent event, but transaction {:02x} is missing", tx_hash)
},
};

return Ok(Some(FoundSwapTxSpend::Spent(TransactionEnum::from(try_s!(
signed_tx_from_web3_tx(transaction)
)))));
},
None => return ERR!("Found ReceiverSpent event, but it doesn't have tx_hash"),
}
}

let refund_events = try_s!(self.refund_events(swap_contract_address, from_block, to_block).wait());
let found = refund_events.iter().find(|event| &event.data.0[..32] == id.as_slice());

if let Some(event) = found {
match event.transaction_hash {
Some(tx_hash) => {
let transaction = match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).wait())
{
Some(t) => t,
None => {
return ERR!("Found SenderRefunded event, but transaction {:02x} is missing", tx_hash)
},
};

return Ok(Some(FoundSwapTxSpend::Refunded(TransactionEnum::from(try_s!(
signed_tx_from_web3_tx(transaction)
)))));
},
None => return ERR!("Found SenderRefunded event, but it doesn't have tx_hash"),
}
}

if to_block >= current_block {
break;
}
from_block = to_block;
}

Ok(None)
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
Expand Down
10 changes: 9 additions & 1 deletion mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ fn eth_coin_for_test(
web3,
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
}));
(ctx, eth_coin)
}
Expand Down Expand Up @@ -219,6 +220,7 @@ fn send_and_refund_erc20_payment() {
history_sync_state: Mutex::new(HistorySyncState::NotStarted),
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
}));

let payment = coin
Expand Down Expand Up @@ -278,6 +280,7 @@ fn send_and_refund_eth_payment() {
history_sync_state: Mutex::new(HistorySyncState::NotStarted),
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
}));

let payment = coin
Expand Down Expand Up @@ -356,6 +359,7 @@ fn test_nonce_several_urls() {
history_sync_state: Mutex::new(HistorySyncState::NotStarted),
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
}));

log!("My address "[coin.my_address]);
Expand All @@ -371,7 +375,8 @@ fn test_nonce_several_urls() {

#[test]
fn test_wait_for_payment_spend_timeout() {
EthCoinImpl::spend_events.mock_safe(|_, _, _| MockResult::Return(Box::new(futures01::future::ok(vec![]))));
EthCoinImpl::spend_events.mock_safe(|_, _, _, _| MockResult::Return(Box::new(futures01::future::ok(vec![]))));
EthCoin::current_block.mock_safe(|_| MockResult::Return(Box::new(futures01::future::ok(900))));

let key_pair = KeyPair::from_secret_slice(
&hex::decode("809465b17d0a4ddb3e4c69e8f23c2cabad868f51f8bed5c765ad1d6516c3306f").unwrap(),
Expand All @@ -398,6 +403,7 @@ fn test_wait_for_payment_spend_timeout() {
web3,
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
};

let coin = EthCoin(Arc::new(coin));
Expand Down Expand Up @@ -454,6 +460,7 @@ fn test_search_for_swap_tx_spend_was_spent() {
web3,
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
}));

// raw transaction bytes of https://ropsten.etherscan.io/tx/0xb1c987e2ac79581bb8718267b5cb49a18274890494299239d1d0dfdb58d6d76a
Expand Down Expand Up @@ -525,6 +532,7 @@ fn test_search_for_swap_tx_spend_was_refunded() {
web3,
ctx: ctx.weak(),
required_confirmations: 1.into(),
chain_id: None,
}));

// raw transaction bytes of https://ropsten.etherscan.io/tx/0xe18bbca69dea9a4624e1f5b0b2021d5fe4c8daa03f36084a8ba011b08e5cd938
Expand Down

0 comments on commit 534973c

Please sign in to comment.