Skip to content

Commit

Permalink
:rolled_up_newspaper: Emit a warning message if Verifier PreCrime opt…
Browse files Browse the repository at this point in the history
…ion is specified in build-lz-options (#391)

Signed-off-by: Ryan Goulding <[email protected]>
  • Loading branch information
ryandgoulding authored Feb 12, 2024
1 parent 91daef3 commit 3fb1788
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/tricky-otters-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"build-lz-options": minor
---

Support to warn if Verifier PreCrime option is specified
9 changes: 7 additions & 2 deletions packages/build-lz-options/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ pnpm build-lz-options
bunx build-lz-options
```

## Warnings
## :warning: Known Warnings

### :warning: Warning: Options do not specify any lzReceive gas
### Options do not specify any lzReceive gas

The default LayerZero ExecutorFeeLib requires the sum of lzReceive gas for all Options for a message is a positive
integer. This is classified as a warning and not an error, as `build-lz-options` tool is not aware of the context in
which the generated Options are used. For example, Options may be combined elsewhere in the application, perhaps with
OApp Enforced Options, and the result will have a positive lzReceive gas sum.

### PreCrime Verifier Option is not supported by the default LayerZero DVN. Please ensure the DVN you have specified supports this option.

The default LayerZero DVN does not currently support the Verifier PreCrime option. If you specify this option, please
ensure that the DVN you are using supports PreCrime.
5 changes: 5 additions & 0 deletions packages/build-lz-options/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ new Command("build-lz-options")
if (!lzReceiveOption || lzReceiveOption.gas < 1) {
warning.push("Options do not specify any lzReceive gas.");
}
if (options.hasVerifierPreCrimeOption()) {
warning.push(
"PreCrime Verifier Option is not supported by the default LayerZero DVN. Please ensure the DVN you have specified supports this option.",
);
}
output = options.toHex();
break;
}
Expand Down
90 changes: 78 additions & 12 deletions packages/build-lz-options/src/utilities/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EXECUTOR_OPTION_TYPE, OPTION_TYPES, WORKER_TYPE } from '@/config'
import { OptionType1Summary, OptionType2Summary } from '@/types'
import { makeBytes32 } from '@layerzerolabs/devtools'
import { ExecutorOptionType, Options, WorkerId } from '@layerzerolabs/lz-v2-utilities'
import { ExecutorOptionType, GasLimit, NativeDrop, Options, WorkerId } from '@layerzerolabs/lz-v2-utilities'
import prompts, { PromptObject } from 'prompts'
import { handlePromptState, promptToContinue } from '@layerzerolabs/io-devtools'

Expand All @@ -12,6 +12,67 @@ const MAX_UINT_16 = 0xffffffff
// Default initial text number.
const DEFAULT_INITIAL_TEXT_NUMBER = BigInt('200000')

/**
* OptionsBuilder class to build Options. This class is a facade around the @layerzerolabs/lz-v2-utilities Options
* builder, purpose built to support an interactive experience.
*/
class OptionsBuilder {
private constructor(
protected options: Options = Options.newOptions(),
protected specifiesVerifierPreCrimeIndex: boolean = false
) {}

/**
* Factory method.
* @returns {OptionsBuilder}
*/
public static newBuilder(): OptionsBuilder {
return new OptionsBuilder()
}

public addExecutorLzReceiveOption(gasLimit: GasLimit, nativeDrop: NativeDrop = 0): OptionsBuilder {
this.options = this.options.addExecutorLzReceiveOption(gasLimit, nativeDrop)
return this
}

public addExecutorNativeDropOption(nativeDrop: NativeDrop, receiver: string): OptionsBuilder {
this.options = this.options.addExecutorNativeDropOption(nativeDrop, receiver)
return this
}

public addExecutorComposeOption(index: number, gasLimit: GasLimit, nativeDrop: NativeDrop = 0): OptionsBuilder {
this.options = this.options.addExecutorComposeOption(index, gasLimit, nativeDrop)
return this
}

public addExecutorOrderedExecutionOption(): OptionsBuilder {
this.options = this.options.addExecutorOrderedExecutionOption()
return this
}

public addVerifierPrecrimeOption(verifierIdx: number): OptionsBuilder {
this.options = this.options.addVerifierPrecrimeOption(verifierIdx)
this.specifiesVerifierPreCrimeIndex = true
return this
}

/**
* Check if the options include Verifier PreCrime.
* @returns {boolean}
*/
public hasVerifierPreCrimeOption(): boolean {
return this.specifiesVerifierPreCrimeIndex
}

public toHex(): string {
return this.options.toHex()
}

public decodeExecutorLzReceiveOption() {
return this.options.decodeExecutorLzReceiveOption()
}
}

/**
* Helper function to validate a string as a bigint.
* @param {string} str input string
Expand Down Expand Up @@ -90,6 +151,11 @@ const promptForIndex: PromptObject<'index'> = {
max: MAX_UINT_16,
}

const promptForVerifierPrecrimeIndex: PromptObject<'index'> = {
...promptForIndex,
message: 'What verifier precrime index (uint16) do you want to use?',
}

const promptForNativeDropAddress: PromptObject<'nativeDropAddress'> = {
onState: handlePromptState,
type: 'text',
Expand Down Expand Up @@ -128,20 +194,20 @@ const promptForExecutorOptionType = () =>
},
])

const promptExecutorLzReceiveOption = async (options: Options): Promise<Options> => {
const promptExecutorLzReceiveOption = async (options: OptionsBuilder): Promise<OptionsBuilder> => {
const { gasLimit, nativeDropAmount } = await prompts([promptForGasLimit, promptForNativeDropAmount])
return options.addExecutorLzReceiveOption(gasLimit, nativeDropAmount)
}

const promptExecutorNativeDropOption = async (options: Options): Promise<Options> => {
const promptExecutorNativeDropOption = async (options: OptionsBuilder): Promise<OptionsBuilder> => {
const { nativeDropAmount, nativeDropAddress } = await prompts([
promptForNativeDropAmount,
promptForNativeDropAddress,
])
return options.addExecutorNativeDropOption(nativeDropAmount, nativeDropAddress)
}

const promptExecutorComposeOption = async (options: Options): Promise<Options> => {
const promptExecutorComposeOption = async (options: OptionsBuilder): Promise<OptionsBuilder> => {
const { index, gasLimit, nativeDropAmount } = await prompts([
promptForIndex,
promptForGasLimit,
Expand All @@ -151,15 +217,15 @@ const promptExecutorComposeOption = async (options: Options): Promise<Options> =
return options.addExecutorComposeOption(index, gasLimit, nativeDropAmount)
}

const promptForExecutorOption = async (options: Options): Promise<Options> => {
const promptForExecutorOption = async (options: OptionsBuilder): Promise<OptionsBuilder> => {
const executorOptionType = await promptForExecutorOptionType()
switch (executorOptionType.type?.id) {
case ExecutorOptionType.LZ_RECEIVE:
return promptExecutorLzReceiveOption(options)
case ExecutorOptionType.NATIVE_DROP:
return await promptExecutorNativeDropOption(options)
return promptExecutorNativeDropOption(options)
case ExecutorOptionType.COMPOSE:
return await promptExecutorComposeOption(options)
return promptExecutorComposeOption(options)
case ExecutorOptionType.ORDERED:
return options.addExecutorOrderedExecutionOption()
default:
Expand All @@ -168,8 +234,8 @@ const promptForExecutorOption = async (options: Options): Promise<Options> => {
}
}

const promptVerifierPrecrimeOption = async (options: Options): Promise<Options> => {
const { index } = await prompts([promptForIndex])
const promptVerifierPrecrimeOption = async (options: OptionsBuilder): Promise<OptionsBuilder> => {
const { index } = await prompts([promptForVerifierPrecrimeIndex])
return options.addVerifierPrecrimeOption(index)
}

Expand All @@ -184,7 +250,7 @@ export const promptForOptionType1 = (): Promise<OptionType1Summary> => prompts(p
export const promptForOptionType2 = (): Promise<OptionType2Summary> =>
prompts([promptForGasLimit, promptForNativeDropAmount, promptForNativeDropAddress])

const determineWorkerType = async (options: Options): Promise<Options> => {
const determineWorkerType = async (options: OptionsBuilder): Promise<OptionsBuilder> => {
const workerType = await promptForWorkerType()
switch (workerType.type?.id) {
case WorkerId.EXECUTOR:
Expand All @@ -200,8 +266,8 @@ const determineWorkerType = async (options: Options): Promise<Options> => {
/**
* Helper function to prompt for OptionType.TYPE_3.
*/
export const promptForOptionType3 = async (): Promise<Options> => {
let options = Options.newOptions()
export const promptForOptionType3 = async (): Promise<OptionsBuilder> => {
let options = OptionsBuilder.newBuilder()
do {
options = await determineWorkerType(options)
} while (await promptToContinue('Would you like to add another option?'))
Expand Down

0 comments on commit 3fb1788

Please sign in to comment.