Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve the block results that include the event with the exact attributes in query #2870

Merged
merged 11 commits into from
Nov 30, 2022
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Fix an issue where Hermes would sometimes fails to retrieve the
begin/end block events because of a quirk of the Tendermint event indexer
([#2867](https://github.com/informalsystems/ibc-rs/issues/2867))
3 changes: 3 additions & 0 deletions .changelog/unreleased/bug-fixes/2868-clear-begin-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Hermes tx CLIs that use the `packet_data_query_height` option now also clear
begin/end block events ([#2868](https://github.com/informalsystems/ibc-
rs/issues/2868))
33 changes: 22 additions & 11 deletions crates/relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ impl CosmosSdkChain {
.map(|ev| IbcEventWithHeight::new(ev, response_height))
.collect(),
);

Ok((begin_block_events, end_block_events))
}

Expand All @@ -586,22 +587,29 @@ impl CosmosSdkChain {
let mut begin_block_events = vec![];
let mut end_block_events = vec![];

for seq in request.sequences.iter() {
for seq in request.sequences.iter().copied() {
let response = self
.block_on(self.rpc_client.block_search(
packet_query(request, *seq),
packet_query(request, seq),
// We only need the first page
1,
1, // there should only be a single match for this query
Order::Ascending,
// There should only be a single match for this query, but due to
// the fact that the indexer treat the query as a disjunction over
// all events in a block rather than a conjunction over a single event,
// we may end up with partial matches and therefore have to account for
// that by fetching multiple results and filter it down after the fact.
// In the worst case we get N blocks where N is the number of channels,
// but 10 seems to work well enough in practice while keeping the response
// size, and therefore pressure on the node, fairly low.
10,
romac marked this conversation as resolved.
Show resolved Hide resolved
// We could pick either ordering here, since matching blocks may be at pretty
// much any height relative to the target blocks, so we went with most recent
// blocks first.
Order::Descending,
))
.map_err(|e| Error::rpc(self.config.rpc_addr.clone(), e))?;

assert!(
response.blocks.len() <= 1,
"block_search: unexpected number of blocks"
);

if let Some(block) = response.blocks.first().map(|first| &first.block) {
for block in response.blocks.into_iter().map(|response| response.block) {
romac marked this conversation as resolved.
Show resolved Hide resolved
let response_height =
ICSHeight::new(self.id().version(), u64::from(block.header.height))
.map_err(|_| Error::invalid_height_no_source())?;
Expand All @@ -612,13 +620,16 @@ impl CosmosSdkChain {
}
}

// `query_packet_from_block` retrieves the begin and end block events
// and filter them to retain only those matching the query
let (new_begin_block_events, new_end_block_events) =
self.query_packet_from_block(request, &[*seq], &response_height)?;
self.query_packet_from_block(request, &[seq], &response_height)?;

begin_block_events.extend(new_begin_block_events);
end_block_events.extend(new_end_block_events);
}
}

Ok((begin_block_events, end_block_events))
}
}
Expand Down
48 changes: 36 additions & 12 deletions crates/relayer/src/chain/cosmos/query/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@ pub async fn query_packets_from_block(
crate::time!("query_packets_from_block");
crate::telemetry!(query, chain_id, "query_packets_from_block");

let mut result: Vec<IbcEventWithHeight> = vec![];

let tm_height = match request.height.get() {
QueryHeight::Latest => tendermint::block::Height::default(),
QueryHeight::Specific(h) => {
Expand All @@ -163,17 +161,19 @@ pub async fn query_packets_from_block(
let height = Height::new(chain_id.version(), u64::from(tm_height))
.map_err(|_| Error::invalid_height_no_source())?;

let exact_tx_block_results = rpc_client
let block_results = rpc_client
.block_results(tm_height)
.await
.map_err(|e| Error::rpc(rpc_address.clone(), e))?
.txs_results;

if let Some(txs) = exact_tx_block_results {
for tx in txs.iter() {
let tx_copy = tx.clone();
result.append(
&mut tx_copy
.map_err(|e| Error::rpc(rpc_address.clone(), e))?;

let mut tx_events = vec![];
let mut begin_block_events = vec![];
let mut end_block_events = vec![];

if let Some(txs) = block_results.txs_results {
for tx in txs {
tx_events.append(
&mut tx
.events
.into_iter()
.filter_map(|e| filter_matching_event(e, request, &request.sequences))
Expand All @@ -183,7 +183,31 @@ pub async fn query_packets_from_block(
}
}

Ok(result)
begin_block_events.append(
&mut block_results
.begin_block_events
.unwrap_or_default()
.into_iter()
.filter_map(|ev| filter_matching_event(ev, request, &request.sequences))
.map(|ev| IbcEventWithHeight::new(ev, height))
.collect(),
);

end_block_events.append(
&mut block_results
.end_block_events
.unwrap_or_default()
.into_iter()
.filter_map(|ev| filter_matching_event(ev, request, &request.sequences))
.map(|ev| IbcEventWithHeight::new(ev, height))
.collect(),
);

let mut events = begin_block_events;
events.append(&mut tx_events);
events.append(&mut end_block_events);

Ok(events)
adizere marked this conversation as resolved.
Show resolved Hide resolved
}

// Extracts from the Tx the update client event for the requested client and height.
Expand Down