Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/witty-horses-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@confio/relayer': minor
---

Support for packet level filtering
2 changes: 1 addition & 1 deletion src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { AckWithMetadata, Endpoint } from './endpoint';
export { IbcClient } from './ibcclient';
export { Link, RelayInfo, RelayedHeights } from './link';
export { Link, RelayInfo, RelayedHeights, PacketFilter } from './link';
export { Logger, NoopLogger } from './logger';
export * as testutils from './helpers';
export { CosmWasmSigner } from './helpers';
36 changes: 31 additions & 5 deletions src/lib/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export function otherSide(side: Side): Side {
}
}

/**
* PacketFilter is the type for a function that accepts a Packet and returns a boolean defining whether to relay the packet or not
*/
export type PacketFilter = (packet: Packet) => boolean;
Comment thread
clockworkgr marked this conversation as resolved.

// This records the block heights from the last point where we successfully relayed packets.
// This can be used to optimize the next round of relaying
export interface RelayedHeights {
Expand Down Expand Up @@ -69,6 +74,7 @@ export class Link {

private readonly chainA: string;
private readonly chainB: string;
private packetFilter: PacketFilter | null = null;

private chain(side: Side): string {
if (side === 'A') {
Expand All @@ -78,6 +84,14 @@ export class Link {
}
}

public setFilter(filter: PacketFilter): void {
this.packetFilter = filter;
}

public clearFilter(): void {
this.packetFilter = null;
}

private otherChain(side: Side): string {
if (side === 'A') {
return this.chainB;
Expand Down Expand Up @@ -506,6 +520,15 @@ export class Link {
this.getPendingPackets('B', { minHeight: relayFrom.packetHeightB }),
]);

const filteredPacketsA =
this.packetFilter !== null
? packetsA.filter((packet) => this.packetFilter?.(packet.packet))
: packetsA;
const filteredPacketsB =
this.packetFilter !== null
? packetsB.filter((packet) => this.packetFilter?.(packet.packet))
: packetsB;

const cutoffHeightA = await this.endB.client.timeoutHeight(
timedoutThresholdBlocks
);
Expand All @@ -515,7 +538,7 @@ export class Link {
const { toSubmit: submitA, toTimeout: timeoutA } = splitPendingPackets(
cutoffHeightA,
cutoffTimeA,
packetsA
filteredPacketsA
);

const cutoffHeightB = await this.endA.client.timeoutHeight(
Expand All @@ -527,7 +550,7 @@ export class Link {
const { toSubmit: submitB, toTimeout: timeoutB } = splitPendingPackets(
cutoffHeightB,
cutoffTimeB,
packetsB
filteredPacketsB
);

// FIXME: use the returned acks first? Then query for others?
Expand Down Expand Up @@ -628,8 +651,11 @@ export class Link {
this.logger.verbose(`Get pending acks on ${this.chain(source)}`);
const { src, dest } = this.getEnds(source);
const allAcks = await src.queryWrittenAcks(opts);

const toFilter = allAcks.map(({ originalPacket }) => originalPacket);
const filteredAcks =
this.packetFilter !== null
? allAcks.filter((ack) => this.packetFilter?.(ack.originalPacket))
: allAcks;
const toFilter = filteredAcks.map(({ originalPacket }) => originalPacket);
const query = async (
port: string,
channel: string,
Expand All @@ -644,7 +670,7 @@ export class Link {
};
const unreceived = await this.filterUnreceived(toFilter, query, ackId);

return allAcks.filter(({ originalPacket: packet }) =>
return filteredAcks.filter(({ originalPacket: packet }) =>
unreceived[ackId(packet)].has(Number(packet.sequence))
);
}
Expand Down