Skip to content

Commit 8d889ae

Browse files
authored
Fix TODO #396 and #397: safe stream handling & receipt handling (#740)
* Fix TODO #396 and #397: safe stream handling & receipt handling * Fix TODOs #396 & #397 and format code with rustfmt
1 parent 3b01caf commit 8d889ae

File tree

1 file changed

+25
-16
lines changed

1 file changed

+25
-16
lines changed

src/confirm.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,27 @@ where
4444
F: Future<Output = error::Result<Option<U64>>>,
4545
{
4646
let filter = eth_filter.create_blocks_filter().await?;
47-
// TODO #396: The stream should have additional checks.
48-
// * We should not continue calling next on a stream that has completed (has returned None). We expect this to never
49-
// happen for the blocks filter but to be safe we should handle this case for example by `fuse`ing the stream or
50-
// erroring when it does complete.
51-
// * We do not handle the case where the stream returns an error which means we are wrongly counting it as a
52-
// confirmation.
5347
let filter_stream = filter.stream(poll_interval).skip(confirmations);
5448
futures::pin_mut!(filter_stream);
5549
loop {
56-
let _ = filter_stream.next().await;
57-
if let Some(confirmation_block_number) = check.check().await? {
58-
let block_number = eth.block_number().await?;
59-
if confirmation_block_number.low_u64() + confirmations as u64 <= block_number.low_u64() {
60-
return Ok(());
50+
match filter_stream.next().await {
51+
Some(Ok(_)) => {
52+
if let Some(confirmation_block_number) = check.check().await? {
53+
let block_number = eth.block_number().await?;
54+
if confirmation_block_number.low_u64() + confirmations as u64 <= block_number.low_u64() {
55+
return Ok(());
56+
}
57+
}
58+
}
59+
Some(Err(e)) => {
60+
return Err(error::Error::Transport(error::TransportError::Message(
61+
format!("Stream error: {e}").into(),
62+
)));
63+
}
64+
None => {
65+
return Err(error::Error::Transport(error::TransportError::Message(
66+
"Stream ended unexpectedly".into(),
67+
)));
6168
}
6269
}
6370
}
@@ -81,11 +88,13 @@ async fn send_transaction_with_confirmation_<T: Transport>(
8188
let eth = eth.clone();
8289
wait_for_confirmations(eth, eth_filter, poll_interval, confirmations, confirmation_check).await?;
8390
}
84-
// TODO #397: We should remove this `expect`. No matter what happens inside the node, this shouldn't be a panic.
85-
let receipt = eth
86-
.transaction_receipt(hash)
87-
.await?
88-
.expect("receipt can't be null after wait for confirmations; qed");
91+
92+
let receipt = eth.transaction_receipt(hash).await?.ok_or_else(|| {
93+
error::Error::Transport(error::TransportError::Message(format!(
94+
"Transaction receipt not found for hash {:?} after {} confirmations",
95+
hash, confirmations
96+
)))
97+
})?;
8998

9099
Ok(receipt)
91100
}

0 commit comments

Comments
 (0)