From e6e245c537cef9cbc3dbc8ff9f4a01995295d3cc Mon Sep 17 00:00:00 2001 From: "James Morris, MS" <96435344+james-a-morris@users.noreply.github.com> Date: Tue, 19 Sep 2023 09:57:40 -0400 Subject: [PATCH] feat: add dataworker force bundle range (#912) * feat: add dataworker force bundle range * docs: add documentation to example env * improve: allow for boba * improve: allow forced proposal range with sending --------- Co-authored-by: Paul <108695806+pxrl@users.noreply.github.com> --- .env.example | 6 ++++++ src/dataworker/Dataworker.ts | 9 +++++++-- src/dataworker/DataworkerConfig.ts | 30 ++++++++++++++++++++++++++++++ src/dataworker/index.ts | 3 ++- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index 91e84b724..df9cc7f98 100644 --- a/.env.example +++ b/.env.example @@ -252,3 +252,9 @@ RELAYER_TOKENS='["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0xA0b86991c6218b # Note: This logic ONLY works if `SEND_PROPOSALS` is set to false. #FORCE_PROPOSAL=false +# This variable can be used to simulate a bundle range that a proposal will be created for. +# This is useful for testing the disputer and proposer logic. The format is: +# [number, number][] where the two numbers are the start and end bundle ranges and the array +# represents the bundle ranges that will be proposed per the chain id indices. +# Note: This logic ONLY works if `SEND_PROPOSALS` and `SEND_DISPUTES` are BOTH set to false. +# FORCE_PROPOSAL_BUNDLE_RANGE = [[1, 2], [1, 3], ...] \ No newline at end of file diff --git a/src/dataworker/Dataworker.ts b/src/dataworker/Dataworker.ts index 0f9bc6dde..c8edf5183 100644 --- a/src/dataworker/Dataworker.ts +++ b/src/dataworker/Dataworker.ts @@ -96,7 +96,8 @@ export class Dataworker { readonly blockRangeEndBlockBuffer: { [chainId: number]: number } = {}, readonly spokeRootsLookbackCount = 0, readonly bufferToPropose = 0, - readonly forceProposal = false + readonly forceProposal = false, + readonly forceBundleRange?: [number, number][] ) { if ( maxRefundCountOverride !== undefined || @@ -344,7 +345,11 @@ export class Dataworker { // For now, we assume that if one blockchain fails to return data, then this entire function will fail. This is a // safe strategy but could lead to new roots failing to be proposed until ALL networks are healthy. - const blockRangesForProposal = this._getNextProposalBlockRanges(spokePoolClients, earliestBlocksInSpokePoolClients); + // If we are forcing a bundle range, then we should use that instead of the next proposal block ranges. + const blockRangesForProposal = isDefined(this.forceBundleRange) + ? this.forceBundleRange + : this._getNextProposalBlockRanges(spokePoolClients, earliestBlocksInSpokePoolClients); + if (!blockRangesForProposal) { return; } diff --git a/src/dataworker/DataworkerConfig.ts b/src/dataworker/DataworkerConfig.ts index a587eb8bf..5deb39e8c 100644 --- a/src/dataworker/DataworkerConfig.ts +++ b/src/dataworker/DataworkerConfig.ts @@ -18,6 +18,12 @@ export class DataworkerConfig extends CommonConfig { // a bundle. This is useful for testing the disputer logic. readonly forcePropose: boolean; + // This variable can be used to simulate a bundle range that a proposal will be created for. + // This is useful for testing the disputer and proposer logic. The format is: + // [number, number][] where the two numbers are the start and end bundle ranges and the array + // represents the bundle ranges that will be proposed per the chain id indices. + readonly forceProposalBundleRange?: [number, number][]; + // These variables can be toggled to choose whether the bot will submit transactions created // by each function. For example, setting `sendingDisputesEnabled=false` but `disputerEnabled=true` // means that the disputer logic will be run but won't send disputes on-chain. @@ -51,6 +57,7 @@ export class DataworkerConfig extends CommonConfig { DATAWORKER_FAST_LOOKBACK_COUNT, DATAWORKER_FAST_START_BUNDLE, FORCE_PROPOSAL, + FORCE_PROPOSAL_BUNDLE_RANGE, } = env; super(env); @@ -91,6 +98,29 @@ export class DataworkerConfig extends CommonConfig { this.forcePropose = FORCE_PROPOSAL === "true"; + // If FORCE_PROPOSAL_BUNDLE_RANGE is set, then we want to force a specific bundle range. + if (FORCE_PROPOSAL_BUNDLE_RANGE) { + // The format is [number, number][] where the two numbers are the start and end bundle ranges and the array + // represents the bundle ranges that will be proposed per the chain id indices. + this.forceProposalBundleRange = JSON.parse(FORCE_PROPOSAL_BUNDLE_RANGE); + // We need to ensure that the bundle ranges are valid. A valid bundle range + // is an array of [start, end] where both start and end are numeric and + // positive whole numbers and start < end. + this.forceProposalBundleRange.forEach((bundleRange, index) => { + assert(Array.isArray(bundleRange), `forceProposalBundleRange[${index}] is not an array`); + assert(bundleRange.length === 2, `forceProposalBundleRange[${index}] does not have length 2`); + const [start, end] = bundleRange; + assert(typeof start === "number", `forceProposalBundleRange[${index}][start] is not a number`); + assert(typeof end === "number", `forceProposalBundleRange[${index}][end] is not a number`); + assert(start > 0, `forceProposalBundleRange[${index}][start] is not positive`); + assert(end > 0, `forceProposalBundleRange[${index}][end] is not positive`); + assert(start <= end, `forceProposalBundleRange[${index}][start] >= forceProposalBundleRange[${index}][end]`); + }); + } else { + // If FORCE_PROPOSAL_BUNDLE_RANGE is not set, then we don't want to force a specific bundle range. + this.forceProposalBundleRange = undefined; + } + // We NEVER want to force propose if the proposer is enabled. if (this.sendingProposalsEnabled) { assert(!this.forcePropose, "Cannot force propose if sending proposals is enabled"); diff --git a/src/dataworker/index.ts b/src/dataworker/index.ts index c2bd53025..affea84ab 100644 --- a/src/dataworker/index.ts +++ b/src/dataworker/index.ts @@ -36,7 +36,8 @@ export async function createDataworker( config.blockRangeEndBlockBuffer, config.spokeRootsLookbackCount, config.bufferToPropose, - config.forcePropose + config.forcePropose, + config.forceProposalBundleRange ); return {