Skip to content

Commit 4bf33bf

Browse files
improve: refactor event config search (#988)
Signed-off-by: james-a-morris <[email protected]>
1 parent ff3aa9d commit 4bf33bf

20 files changed

+143
-206
lines changed

src/arch/evm/SpokeUtils.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -290,20 +290,20 @@ export async function findFillEvent(
290290
if (!blockNumber) return undefined;
291291

292292
// We can hardcode this to 0 to instruct paginatedEventQuery to make a single request for the same block number.
293-
const maxBlockLookBack = 0;
294-
const [fromBlock, toBlock] = [blockNumber, blockNumber];
293+
const maxLookBack = 0;
294+
const [from, to] = [blockNumber, blockNumber];
295295

296296
const query = (
297297
await Promise.all([
298298
paginatedEventQuery(
299299
spokePool,
300300
spokePool.filters.FilledRelay(null, null, null, null, null, relayData.originChainId, relayData.depositId),
301-
{ fromBlock, toBlock, maxBlockLookBack }
301+
{ from, to, maxLookBack }
302302
),
303303
paginatedEventQuery(
304304
spokePool,
305305
spokePool.filters.FilledV3Relay(null, null, null, null, null, relayData.originChainId, relayData.depositId),
306-
{ fromBlock, toBlock, maxBlockLookBack }
306+
{ from, to, maxLookBack }
307307
),
308308
])
309309
).flat();

src/arch/svm/SpokeUtils.ts

+5-49
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ export function getTimeAt(_spokePool: unknown, _blockNumber: number): Promise<nu
3030
}
3131

3232
/**
33-
* Retrieves the chain time at a particular block.
33+
* Retrieves the chain time at a particular slot.
3434
* @note This should be the same as getTimeAt() but can differ in test. These two functions should be consolidated.
35-
* @returns The chain time at the specified block tag.
35+
* @returns The chain time at the specified slot.
3636
*/
37-
export async function getTimestampForBlock(provider: Provider, blockNumber: number): Promise<number> {
38-
const block = await provider.getBlock(BigInt(blockNumber)).send();
37+
export async function getTimestampForSlot(provider: Provider, slotNumber: number): Promise<number> {
38+
const block = await provider.getBlock(BigInt(slotNumber)).send();
3939
let timestamp: number;
4040
if (!block?.blockTime) {
41-
console.error(`Unable to resolve svm block ${blockNumber}`);
41+
console.error(`Unable to resolve svm block ${slotNumber}`);
4242
timestamp = 0; // @todo: How to handle this?
4343
} else {
4444
timestamp = Number(block.blockTime); // Unix timestamps fit within number.
@@ -67,50 +67,6 @@ export function getDepositIdAtBlock(_contract: unknown, _blockTag: number): Prom
6767
throw new Error("getDepositIdAtBlock: not implemented");
6868
}
6969

70-
/**
71-
* xxx todo
72-
*/
73-
export async function getSlotForBlock(
74-
provider: Provider,
75-
blockNumber: bigint,
76-
lowSlot: bigint,
77-
_highSlot?: bigint
78-
): Promise<bigint | undefined> {
79-
// @todo: Factor getBlock out to SlotFinder ??
80-
const getBlockNumber = async (slot: bigint): Promise<bigint> => {
81-
const block = await provider
82-
.getBlock(slot, { transactionDetails: "none", maxSupportedTransactionVersion: 0 })
83-
.send();
84-
return block?.blockHeight ?? BigInt(0); // @xxx Handle undefined here!
85-
};
86-
87-
let highSlot = _highSlot ?? (await provider.getSlot().send());
88-
const [blockLow = 0, blockHigh = 1_000_000_000] = await Promise.all([
89-
getBlockNumber(lowSlot),
90-
getBlockNumber(highSlot),
91-
]);
92-
93-
if (blockLow > blockNumber || blockHigh < blockNumber) {
94-
return undefined; // blockNumber did not occur within the specified block range.
95-
}
96-
97-
// Find the lowest slot number where blockHeight is greater than the requested blockNumber.
98-
do {
99-
const midSlot = (highSlot + lowSlot) / BigInt(2);
100-
const midBlock = await getBlockNumber(midSlot);
101-
102-
if (midBlock < blockNumber) {
103-
lowSlot = midSlot + BigInt(1);
104-
} else if (midBlock > blockNumber) {
105-
highSlot = midSlot + BigInt(1); // blockNumber occurred at or earlier than midBlock.
106-
} else {
107-
return midSlot;
108-
}
109-
} while (lowSlot <= highSlot);
110-
111-
return undefined;
112-
}
113-
11470
export function findDepositBlock(
11571
_spokePool: unknown,
11672
depositId: BigNumber,

src/arch/svm/eventsClient.ts

+9-23
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import web3, {
1111
import { bs58 } from "../../utils";
1212
import { EventData, EventName, EventWithData } from "./types";
1313
import { decodeEvent, isDevnet } from "./utils";
14-
import { getSlotForBlock } from "./SpokeUtils";
1514

1615
// Utility type to extract the return type for the JSON encoding overload. We only care about the overload where the
1716
// configuration parameter (C) has the optional property 'encoding' set to 'json'.
@@ -65,51 +64,38 @@ export class SvmSpokeEventsClient {
6564
* Queries events for the SvmSpoke program filtered by event name.
6665
*
6766
* @param eventName - The name of the event to filter by.
68-
* @param fromBlock - Optional starting block.
69-
* @param toBlock - Optional ending block.
67+
* @param fromSlot - Optional starting slot.
68+
* @param toSlot - Optional ending slot.
7069
* @param options - Options for fetching signatures.
7170
* @returns A promise that resolves to an array of events matching the eventName.
7271
*/
7372
public async queryEvents<T extends EventData>(
7473
eventName: EventName,
75-
fromBlock?: bigint,
76-
toBlock?: bigint,
74+
fromSlot?: bigint,
75+
toSlot?: bigint,
7776
options: GetSignaturesForAddressConfig = { limit: 1000, commitment: "confirmed" }
7877
): Promise<EventWithData<T>[]> {
79-
const events = await this.queryAllEvents(fromBlock, toBlock, options);
78+
const events = await this.queryAllEvents(fromSlot, toSlot, options);
8079
return events.filter((event) => event.name === eventName) as EventWithData<T>[];
8180
}
8281

8382
/**
8483
* Queries all events for a specific program.
8584
*
86-
* @param fromBlock - Optional starting block.
87-
* @param toBlock - Optional ending block.
85+
* @param fromSlot - Optional starting slot.
86+
* @param toSlot - Optional ending slot.
8887
* @param options - Options for fetching signatures.
8988
* @returns A promise that resolves to an array of all events with additional metadata.
9089
*/
9190
private async queryAllEvents(
92-
fromBlock?: bigint,
93-
toBlock?: bigint,
91+
fromSlot?: bigint,
92+
toSlot?: bigint,
9493
options: GetSignaturesForAddressConfig = { limit: 1000, commitment: "confirmed" }
9594
): Promise<EventWithData<EventData>[]> {
9695
const allSignatures: GetSignaturesForAddressTransaction[] = [];
9796
let hasMoreSignatures = true;
9897
let currentOptions = options;
9998

100-
let fromSlot: bigint | undefined;
101-
let toSlot: bigint | undefined;
102-
103-
if (fromBlock) {
104-
const slot = await getSlotForBlock(this.rpc, fromBlock, BigInt(0));
105-
fromSlot = slot;
106-
}
107-
108-
if (toBlock) {
109-
const slot = await getSlotForBlock(this.rpc, toBlock, BigInt(0));
110-
toSlot = slot;
111-
}
112-
11399
while (hasMoreSignatures) {
114100
const signatures: GetSignaturesForAddressApiResponse = await this.rpc
115101
.getSignaturesForAddress(this.svmSpokeAddress, currentOptions)

src/clients/AcrossConfigStoreClient/AcrossConfigStoreClient.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ export class AcrossConfigStoreClient extends BaseAbstractClient {
9999
constructor(
100100
readonly logger: winston.Logger,
101101
readonly configStore: Contract,
102-
eventSearchConfig: MakeOptional<EventSearchConfig, "toBlock"> = { fromBlock: 0, maxBlockLookBack: 0 },
102+
eventSearchConfig: MakeOptional<EventSearchConfig, "to"> = { from: 0, maxLookBack: 0 },
103103
readonly configStoreVersion: number
104104
) {
105105
super(eventSearchConfig);
106-
this.firstBlockToSearch = eventSearchConfig.fromBlock;
107-
this.latestBlockSearched = 0;
106+
this.firstHeightToSearch = eventSearchConfig.from;
107+
this.latestHeightSearched = 0;
108108
}
109109

110110
getRateModelForBlockNumber(
@@ -351,7 +351,7 @@ export class AcrossConfigStoreClient extends BaseAbstractClient {
351351
return {
352352
success: true,
353353
chainId,
354-
searchEndBlock: searchConfig.toBlock,
354+
searchEndBlock: searchConfig.to,
355355
events: {
356356
updatedTokenConfigEvents,
357357
updatedGlobalConfigEvents,
@@ -548,9 +548,9 @@ export class AcrossConfigStoreClient extends BaseAbstractClient {
548548
}
549549

550550
this.hasLatestConfigStoreVersion = this.hasValidConfigStoreVersionForTimestamp();
551-
this.latestBlockSearched = result.searchEndBlock;
552-
this.firstBlockToSearch = result.searchEndBlock + 1; // Next iteration should start off from where this one ended.
553-
this.eventSearchConfig.toBlock = undefined; // Caller can re-set on subsequent updates if necessary
551+
this.latestHeightSearched = result.searchEndBlock;
552+
this.firstHeightToSearch = result.searchEndBlock + 1; // Next iteration should start off from where this one ended.
553+
this.eventSearchConfig.to = undefined; // Caller can re-set on subsequent updates if necessary
554554
this.chainId = this.chainId ?? chainId; // Update on the first run only.
555555
this.isUpdated = true;
556556

src/clients/BaseAbstractClient.ts

+13-13
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ export function isUpdateFailureReason(x: EventSearchConfig | UpdateFailureReason
1919
*/
2020
export abstract class BaseAbstractClient {
2121
protected _isUpdated: boolean;
22-
public firstBlockToSearch = 0;
23-
public latestBlockSearched = 0;
22+
public firstHeightToSearch = 0;
23+
public latestHeightSearched = 0;
2424

2525
/**
2626
* Creates a new client.
2727
* @param cachingMechanism The caching mechanism to use for this client. If not provided, the client will not rely on an external cache.
2828
*/
2929
constructor(
30-
readonly eventSearchConfig: MakeOptional<EventSearchConfig, "toBlock"> = { fromBlock: 0, maxBlockLookBack: 0 },
30+
readonly eventSearchConfig: MakeOptional<EventSearchConfig, "to"> = { from: 0, maxLookBack: 0 },
3131
protected cachingMechanism?: CachingMechanismInterface
3232
) {
3333
this._isUpdated = false;
@@ -62,25 +62,25 @@ export abstract class BaseAbstractClient {
6262
public async updateSearchConfig(
6363
provider: providers.Provider | SVMProvider
6464
): Promise<EventSearchConfig | UpdateFailureReason> {
65-
const fromBlock = this.firstBlockToSearch;
66-
let { toBlock } = this.eventSearchConfig;
67-
if (isDefined(toBlock)) {
68-
if (fromBlock > toBlock) {
69-
throw new Error(`Invalid event search config fromBlock (${fromBlock}) > toBlock (${toBlock})`);
65+
const from = this.firstHeightToSearch;
66+
let { to } = this.eventSearchConfig;
67+
if (isDefined(to)) {
68+
if (from > to) {
69+
throw new Error(`Invalid event search config from (${from}) > to (${to})`);
7070
}
7171
} else {
7272
if (provider instanceof providers.Provider) {
73-
toBlock = await provider.getBlockNumber();
73+
to = await provider.getBlockNumber();
7474
} else {
75-
toBlock = Number(await provider.getBlockHeight({ commitment: "confirmed" }).send());
75+
to = Number(await provider.getSlot({ commitment: "confirmed" }).send());
7676
}
77-
if (toBlock < fromBlock) {
77+
if (to < from) {
7878
return UpdateFailureReason.AlreadyUpdated;
7979
}
8080
}
8181

82-
const { maxBlockLookBack } = this.eventSearchConfig;
83-
return { fromBlock, toBlock, maxBlockLookBack };
82+
const { maxLookBack } = this.eventSearchConfig;
83+
return { from, to, maxLookBack };
8484
}
8585

8686
/**

src/clients/BundleDataClient/BundleDataClient.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ export class BundleDataClient {
304304
}
305305

306306
const bundle = this.clients.hubPoolClient.getLatestFullyExecutedRootBundle(
307-
this.clients.hubPoolClient.latestBlockSearched
307+
this.clients.hubPoolClient.latestHeightSearched
308308
);
309309
if (bundle !== undefined) {
310310
refunds.push(await this.getPendingRefundsFromBundle(bundle));
@@ -317,7 +317,7 @@ export class BundleDataClient {
317317
async getPendingRefundsFromBundle(bundle: ProposedRootBundle): Promise<CombinedRefunds> {
318318
const nextBundleMainnetStartBlock = this.clients.hubPoolClient.getNextBundleStartBlockNumber(
319319
this.chainIdListForBundleEvaluationBlockNumbers,
320-
this.clients.hubPoolClient.latestBlockSearched,
320+
this.clients.hubPoolClient.latestHeightSearched,
321321
this.clients.hubPoolClient.chainId
322322
);
323323
const chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(nextBundleMainnetStartBlock);
@@ -447,7 +447,7 @@ export class BundleDataClient {
447447
const hubPoolClient = this.clients.hubPoolClient;
448448
const nextBundleMainnetStartBlock = hubPoolClient.getNextBundleStartBlockNumber(
449449
this.chainIdListForBundleEvaluationBlockNumbers,
450-
hubPoolClient.latestBlockSearched,
450+
hubPoolClient.latestHeightSearched,
451451
hubPoolClient.chainId
452452
);
453453
const chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(nextBundleMainnetStartBlock);
@@ -460,8 +460,8 @@ export class BundleDataClient {
460460
this.spokePoolClients,
461461
getEndBlockBuffers(chainIds, this.blockRangeEndBlockBuffer),
462462
this.clients,
463-
this.clients.hubPoolClient.latestBlockSearched,
464-
this.clients.configStoreClient.getEnabledChains(this.clients.hubPoolClient.latestBlockSearched)
463+
this.clients.hubPoolClient.latestHeightSearched,
464+
this.clients.configStoreClient.getEnabledChains(this.clients.hubPoolClient.latestHeightSearched)
465465
);
466466
// Return block ranges for blocks after _pendingBlockRanges and up to widestBlockRanges.
467467
// If a chain is disabled or doesn't have a spoke pool client, return a range of 0
@@ -728,7 +728,7 @@ export class BundleDataClient {
728728
// hasn't queried. This is because this function will usually be called
729729
// in production with block ranges that were validated by
730730
// DataworkerUtils.blockRangesAreInvalidForSpokeClients.
731-
Math.min(queryBlock, spokePoolClients[deposit.destinationChainId].latestBlockSearched)
731+
Math.min(queryBlock, spokePoolClients[deposit.destinationChainId].latestHeightSearched)
732732
);
733733
};
734734

@@ -1542,7 +1542,7 @@ export class BundleDataClient {
15421542
spokePoolClient.spokePool,
15431543
deposit,
15441544
spokePoolClient.deploymentBlock,
1545-
spokePoolClient.latestBlockSearched
1545+
spokePoolClient.latestHeightSearched
15461546
);
15471547
}
15481548

@@ -1570,13 +1570,13 @@ export class BundleDataClient {
15701570
// contain blocks where the spoke pool client hasn't queried. This is because this function
15711571
// will usually be called in production with block ranges that were validated by
15721572
// DataworkerUtils.blockRangesAreInvalidForSpokeClients.
1573-
const startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestBlockSearched);
1573+
const startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestHeightSearched);
15741574
// @dev Add 1 to the bundle end block. The thinking here is that there can be a gap between
15751575
// block timestamps in subsequent blocks. The bundle data client assumes that fill deadlines expire
15761576
// in exactly one bundle, therefore we must make sure that the bundle block timestamp for one bundle's
15771577
// end block is exactly equal to the bundle block timestamp for the next bundle's start block. This way
15781578
// there are no gaps in block timestamps between bundles.
1579-
const endBlockForChain = Math.min(_endBlockForChain + 1, spokePoolClient.latestBlockSearched);
1579+
const endBlockForChain = Math.min(_endBlockForChain + 1, spokePoolClient.latestHeightSearched);
15801580
const [startTime, _endTime] = [
15811581
await spokePoolClient.getTimestampForBlock(startBlockForChain),
15821582
await spokePoolClient.getTimestampForBlock(endBlockForChain),

src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function getWidestPossibleExpectedBlockRange(
3131
// filled during the challenge period.
3232
const latestPossibleBundleEndBlockNumbers = chainIdListForBundleEvaluationBlockNumbers.map(
3333
(chainId: number, index) =>
34-
spokeClients[chainId] && Math.max(spokeClients[chainId].latestBlockSearched - endBlockBuffers[index], 0)
34+
spokeClients[chainId] && Math.max(spokeClients[chainId].latestHeightSearched - endBlockBuffers[index], 0)
3535
);
3636
return chainIdListForBundleEvaluationBlockNumbers.map((chainId: number, index) => {
3737
const lastEndBlockForChain = clients.hubPoolClient.getLatestBundleEndBlockForChain(

0 commit comments

Comments
 (0)