Skip to content

Commit

Permalink
getLatestProposedBundleData should never load data from scratch
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholaspai committed Feb 10, 2025
1 parent 55783b7 commit 9850552
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 31 deletions.
75 changes: 45 additions & 30 deletions src/clients/BundleDataClient/BundleDataClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,7 @@ export class BundleDataClient {
);
}

private async loadPersistedDataFromArweave(
blockRangesForChains: number[][]
): Promise<LoadDataReturnValue | undefined> {
if (!isDefined(this.clients?.arweaveClient)) {
return undefined;
}
const start = performance.now();
private async getBundleDataFromArweave(blockRangesForChains: number[][]) {
const persistedData = await this.clients.arweaveClient.getByTopic(
this.getArweaveBundleDataClientKey(blockRangesForChains),
BundleDataSS
Expand All @@ -256,6 +250,20 @@ export class BundleDataClient {
if (!isDefined(persistedData) || persistedData.length < 1) {
return undefined;
}
return persistedData;
}

private async loadPersistedDataFromArweave(
blockRangesForChains: number[][]
): Promise<LoadDataReturnValue | undefined> {
if (!isDefined(this.clients?.arweaveClient)) {
return undefined;
}
const start = performance.now();
const persistedData = await this.getBundleDataFromArweave(blockRangesForChains);
if (!isDefined(persistedData)) {
return undefined;
}

// A converter function to account for the fact that our SuperStruct schema does not support numeric
// keys in records. Fundamentally, this is a limitation of superstruct itself.
Expand Down Expand Up @@ -435,24 +443,39 @@ export class BundleDataClient {
const hubPoolClient = this.clients.hubPoolClient;
// Determine which bundle we should fetch from arweave, either the pending bundle or the latest
// executed one. Both should have arweave data but if for some reason the arweave data is missing,
// this function will have to compute the bundle data from scratch which will be slow. We have to fallback
// to computing the bundle from scratch since this function needs to return the full bundle data so that
// it can be used to get the running balance proposed using its data.
const bundleBlockRanges = getImpliedBundleBlockRanges(
// this function will load the bundle data from the most recent bundle data published to Arweave.

Check warning on line 447 in src/clients/BundleDataClient/BundleDataClient.ts

View workflow job for this annotation

GitHub Actions / Lint

Delete `····`
let bundleBlockRanges = getImpliedBundleBlockRanges(
hubPoolClient,
this.clients.configStoreClient,
hubPoolClient.hasPendingProposal()
? hubPoolClient.getLatestProposedRootBundle()
: hubPoolClient.getLatestFullyExecutedRootBundle(hubPoolClient.latestBlockSearched)! // ! because we know there is a bundle
: hubPoolClient.getNthFullyExecutedRootBundle(-1)!
);
return {
blockRanges: bundleBlockRanges,
bundleData: await this.loadData(
bundleBlockRanges,
this.spokePoolClients,
true // this bundle data should have been published to arweave
),
};
// Check if bundle data exists on arweave, otherwise fallback to last published bundle data. If the
// first bundle block range we are trying is the pending proposal, then we'll grab the most recently
// validated bundle, otherwise we'll grab the second most recently validated bundle.
let n = hubPoolClient.hasPendingProposal() ? 1 : 2;

// eslint-disable-next-line no-constant-condition
while (true) {
const bundleDataOnArweave = await this.getBundleDataFromArweave(bundleBlockRanges);
if (!isDefined(bundleDataOnArweave)) {
// Bundle data is not arweave, try the next most recently validated bundle.
bundleBlockRanges = getImpliedBundleBlockRanges(
hubPoolClient,
this.clients.configStoreClient,
hubPoolClient.getNthFullyExecutedRootBundle(-n)!
);
} else {
return {
blockRanges: bundleBlockRanges,
bundleData: await this.loadData(bundleBlockRanges, this.spokePoolClients, true),
};
}

n++;
}
}

async getLatestPoolRebalanceRoot(): Promise<{ root: PoolRebalanceRoot; blockRanges: number[][] }> {
Expand Down Expand Up @@ -992,11 +1015,7 @@ export class BundleDataClient {
}
}
} else {
this.logger.warn({
at: "BundleDataClient#loadDataFromScratch",
message: "Detected duplicate fill",
fill,
});
throw new Error("Duplicate fill detected");
}
return;
}
Expand Down Expand Up @@ -1119,11 +1138,7 @@ export class BundleDataClient {
validatedBundleSlowFills.push(matchedDeposit);
}
} else {
this.logger.warn({
at: "BundleDataClient#loadDataFromScratch",
message: "Detected duplicate slow fill request",
slowFillRequest,
});
throw new Error("Duplicate slow fill request detected.");
}
return;
}
Expand Down
32 changes: 31 additions & 1 deletion src/clients/SpokePoolClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,13 +726,27 @@ export class SpokePoolClient extends BaseAbstractClient {
const slowFillRequest = {
...spreadEventWithBlockNumber(event),
destinationChainId: this.chainId,
} as SlowFillRequestWithBlock;
} as SlowFillRequestWithBlock;

Check warning on line 729 in src/clients/SpokePoolClient.ts

View workflow job for this annotation

GitHub Actions / Lint

Delete `········`

if (eventName === "RequestedV3SlowFill") {
slowFillRequest.messageHash = getMessageHash(slowFillRequest.message);
}

const depositHash = getRelayEventKey({ ...slowFillRequest, destinationChainId: this.chainId });

Check warning on line 736 in src/clients/SpokePoolClient.ts

View workflow job for this annotation

GitHub Actions / Lint

Delete `········`
// Sanity check that this event is not a duplicate.
if (

Check warning on line 738 in src/clients/SpokePoolClient.ts

View workflow job for this annotation

GitHub Actions / Lint

Replace `⏎··········this.slowFillRequests[depositHash]·!==·undefined⏎········` with `this.slowFillRequests[depositHash]·!==·undefined`
this.slowFillRequests[depositHash] !== undefined
) {
this.logger.warn({
at: "SpokePoolClient#update",
chainId: this.chainId,
message: "Duplicate slow fill request found",
slowFillRequest,
});
continue;
}

Check warning on line 749 in src/clients/SpokePoolClient.ts

View workflow job for this annotation

GitHub Actions / Lint

Delete `········`
this.slowFillRequests[depositHash] ??= slowFillRequest;
}
};
Expand Down Expand Up @@ -766,6 +780,22 @@ export class SpokePoolClient extends BaseAbstractClient {
fill.relayExecutionInfo.updatedMessageHash = getMessageHash(event.args.relayExecutionInfo.updatedMessage);
}

// Sanity check that this event is not a duplicate.
if (
this.fills[fill.originChainId] !== undefined &&
this.fills[fill.originChainId].some(
(f) => f.transactionHash === fill.transactionHash && f.logIndex === fill.logIndex
)
) {
this.logger.warn({
at: "SpokePoolClient#update",
chainId: this.chainId,
message: "Duplicate fill found",
fill,
});
continue;
}

assign(this.fills, [fill.originChainId], [fill]);
assign(this.depositHashesToFills, [this.getDepositHash(fill)], [fill]);
}
Expand Down

0 comments on commit 9850552

Please sign in to comment.