wheel

package
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2024 License: MIT Imports: 26 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	GlobalGethLogLvlFlag = &cli.GenericFlag{
		Name:    "geth-log-level",
		Usage:   "Set the global geth logging level",
		EnvVars: prefixEnvVars("GETH_LOG_LEVEL"),
		Value:   oplog.NewLevelFlagValue(log.LevelError),
	}
	DataDirFlag = &cli.StringFlag{
		Name:      "data-dir",
		Usage:     "Geth data dir location.",
		Required:  true,
		TakesFile: true,
		EnvVars:   prefixEnvVars("DATA_DIR"),
	}
	EngineEndpoint = &cli.StringFlag{
		Name:     "engine",
		Usage:    "Authenticated Engine API RPC endpoint, can be HTTP/WS/IPC",
		Required: true,
		Value:    "http://localhost:8551/",
		EnvVars:  prefixEnvVars("ENGINE"),
	}
	EngineJWTPath = &cli.StringFlag{
		Name:      "engine.jwt-secret",
		Usage:     "Path to JWT secret file used to authenticate Engine API communication with.",
		Required:  true,
		TakesFile: true,
		EnvVars:   prefixEnvVars("ENGINE_JWT_SECRET"),
	}
	EngineOpenEndpoint = &cli.StringFlag{
		Name:    "engine.open",
		Usage:   "Open Engine API RPC endpoint, can be HTTP/WS/IPC",
		Value:   "http://localhost:8545/",
		EnvVars: prefixEnvVars("ENGINE_OPEN"),
	}
	EngineVersion = &cli.IntFlag{
		Name:    "engine.version",
		Usage:   "Engine API version to use for Engine calls (1, 2, or 3)",
		EnvVars: prefixEnvVars("ENGINE_VERSION"),
		Action: func(ctx *cli.Context, ev int) error {
			if ev < 1 || ev > 3 {
				return fmt.Errorf("invalid Engine API version: %d", ev)
			}
			return nil
		},
	}
	FeeRecipientFlag = &cli.GenericFlag{
		Name:    "fee-recipient",
		Usage:   "fee-recipient of the block building",
		EnvVars: prefixEnvVars("FEE_RECIPIENT"),
		Value:   &TextFlag[*common.Address]{Value: &common.Address{1: 0x13, 2: 0x37}},
	}
	RandaoFlag = &cli.GenericFlag{
		Name:    "randao",
		Usage:   "randao value of the block building",
		EnvVars: prefixEnvVars("RANDAO"),
		Value:   &TextFlag[*common.Hash]{Value: &common.Hash{1: 0x13, 2: 0x37}},
	}
	BlockTimeFlag = &cli.Uint64Flag{
		Name:    "block-time",
		Usage:   "block time, interval of timestamps between blocks to build, in seconds",
		EnvVars: prefixEnvVars("BLOCK_TIME"),
		Value:   12,
	}
	BuildingTime = &cli.DurationFlag{
		Name:    "building-time",
		Usage:   "duration of of block building, this should be set to something lower than the block time.",
		EnvVars: prefixEnvVars("BUILDING_TIME"),
		Value:   time.Second * 6,
	}
	AllowGaps = &cli.BoolFlag{
		Name:    "allow-gaps",
		Usage:   "allow gaps in block building, like missed slots on the beacon chain.",
		EnvVars: prefixEnvVars("ALLOW_GAPS"),
	}
)
View Source
var (
	CheatStorageGetCmd = &cli.Command{
		Name:    "get",
		Aliases: []string{"read"},
		Flags: []cli.Flag{
			DataDirFlag,
			addrFlag("address", "Address to read storage of"),
			hashFlag("key", "key in storage of address to read value"),
		},
		Action: CheatAction(true, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.StorageGet(addrFlagValue("address", ctx), hashFlagValue("key", ctx), ctx.App.Writer))
		}),
	}
	CheatStorageSetCmd = &cli.Command{
		Name:    "set",
		Aliases: []string{"write"},
		Flags: []cli.Flag{
			DataDirFlag,
			addrFlag("address", "Address to write storage of"),
			hashFlag("key", "key in storage of address to set value of"),
			hashFlag("value", "the value to write"),
		},
		Action: CheatAction(false, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.StorageSet(addrFlagValue("address", ctx), hashFlagValue("key", ctx), hashFlagValue("value", ctx)))
		}),
	}
	CheatStorageReadAll = &cli.Command{
		Name:    "read-all",
		Aliases: []string{"get-all"},
		Usage:   "Read all storage of the given account",
		Flags:   []cli.Flag{DataDirFlag, addrFlag("address", "Address to read all storage of")},
		Action: CheatAction(true, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.StorageReadAll(addrFlagValue("address", ctx), ctx.App.Writer))
		}),
	}
	CheatStorageDiffCmd = &cli.Command{
		Name:  "diff",
		Usage: "Diff the storage of accounts A and B",
		Flags: []cli.Flag{DataDirFlag, hashFlag("a", "address of account A"), hashFlag("b", "address of account B")},
		Action: CheatAction(true, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.StorageDiff(ctx.App.Writer, addrFlagValue("a", ctx), addrFlagValue("b", ctx)))
		}),
	}
	CheatStoragePatchCmd = &cli.Command{
		Name:  "patch",
		Usage: "Apply storage patch from STDIN to the given account address",
		Flags: []cli.Flag{DataDirFlag, addrFlag("address", "Address to patch storage of")},
		Action: CheatAction(false, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.StoragePatch(os.Stdin, addrFlagValue("address", ctx)))
		}),
	}
	CheatStorageCmd = &cli.Command{
		Name: "storage",
		Subcommands: []*cli.Command{
			CheatStorageGetCmd,
			CheatStorageSetCmd,
			CheatStorageReadAll,
			CheatStorageDiffCmd,
			CheatStoragePatchCmd,
		},
	}
	CheatSetBalanceCmd = &cli.Command{
		Name: "balance",
		Flags: []cli.Flag{
			DataDirFlag,
			addrFlag("address", "Address to change balance of"),
			bigFlag("balance", "New balance of the account"),
		},
		Action: CheatAction(false, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.SetBalance(addrFlagValue("address", ctx), bigFlagValue("balance", ctx)))
		}),
	}
	CheatSetCodeCmd = &cli.Command{
		Name: "code",
		Flags: []cli.Flag{
			DataDirFlag,
			addrFlag("address", "Address to change code of"),
			bytesFlag("code", "New code of the account"),
		},
		Action: CheatAction(false, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.SetCode(addrFlagValue("address", ctx), bytesFlagValue("code", ctx)))
		}),
	}
	CheatSetNonceCmd = &cli.Command{
		Name: "nonce",
		Flags: []cli.Flag{
			DataDirFlag,
			addrFlag("address", "Address to change nonce of"),
			bigFlag("nonce", "New nonce of the account"),
		},
		Action: CheatAction(false, func(ctx *cli.Context, ch *cheat.Cheater) error {
			return ch.RunAndClose(cheat.SetNonce(addrFlagValue("address", ctx), bigFlagValue("balance", ctx).Uint64()))
		}),
	}
	CheatPrintHeadBlock = &cli.Command{
		Name:  "head-block",
		Usage: "dump head block as JSON",
		Flags: []cli.Flag{
			DataDirFlag,
		},
		Action: CheatRawDBAction(true, func(c *cli.Context, db ethdb.Database) error {
			enc := json.NewEncoder(c.App.Writer)
			enc.SetIndent("  ", "  ")
			block := rawdb.ReadHeadBlock(db)
			if block == nil {
				return enc.Encode(nil)
			}
			return enc.Encode(engine.RPCBlock{
				Header:       *block.Header(),
				Transactions: block.Transactions(),
			})
		}),
	}
	CheatPrintHeadHeader = &cli.Command{
		Name:  "head-header",
		Usage: "dump head header as JSON",
		Flags: []cli.Flag{
			DataDirFlag,
		},
		Action: CheatRawDBAction(true, func(c *cli.Context, db ethdb.Database) error {
			enc := json.NewEncoder(c.App.Writer)
			enc.SetIndent("  ", "  ")
			return enc.Encode(rawdb.ReadHeadHeader(db))
		}),
	}
	EngineBlockCmd = &cli.Command{
		Name:  "block",
		Usage: "build the next block using the Engine API",
		Flags: withEngineFlags(
			FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps,
		),

		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error {
			settings := ParseBuildingArgs(ctx)
			status, err := engine.Status(context.Background(), client.RPC)
			if err != nil {
				return err
			}
			payloadEnv, err := engine.BuildBlock(context.Background(), client, status, settings)
			if err != nil {
				return err
			}
			fmt.Fprintln(ctx.App.Writer, payloadEnv.ExecutionPayload.BlockHash)
			return nil
		}),
	}
	EngineAutoCmd = &cli.Command{
		Name:        "auto",
		Usage:       "Run a proof-of-nothing chain with fixed block time.",
		Description: "The block time can be changed. The execution engine must be synced to a post-Merge state first.",
		Flags: append(withEngineFlags(
			FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps),
			opmetrics.CLIFlags(envVarPrefix)...),
		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, l log.Logger) error {
			settings := ParseBuildingArgs(ctx)

			metricsCfg := opmetrics.ReadCLIConfig(ctx)

			return opservice.CloseAction(func(ctx context.Context, shutdown <-chan struct{}) error {
				registry := opmetrics.NewRegistry()
				metrics := engine.NewMetrics("wheel", registry)
				if metricsCfg.Enabled {
					l.Info("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort)
					metricsSrv, err := opmetrics.StartServer(registry, metricsCfg.ListenAddr, metricsCfg.ListenPort)
					if err != nil {
						return fmt.Errorf("failed to start metrics server: %w", err)
					}
					defer func() {
						if err := metricsSrv.Stop(context.Background()); err != nil {
							l.Error("failed to stop metrics server: %w", err)
						}
					}()
				}
				return engine.Auto(ctx, metrics, client, l, shutdown, settings)
			})
		}),
	}
	EngineStatusCmd = &cli.Command{
		Name:  "status",
		Flags: withEngineFlags(),
		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error {
			stat, err := engine.Status(context.Background(), client.RPC)
			if err != nil {
				return err
			}
			enc := json.NewEncoder(ctx.App.Writer)
			enc.SetIndent("", "  ")
			return enc.Encode(stat)
		}),
	}
	EngineCopyCmd = &cli.Command{
		Name: "copy",
		Flags: withEngineFlags(
			&cli.StringFlag{
				Name:     "source",
				Usage:    "Unauthenticated regular eth JSON RPC to pull block data from, can be HTTP/WS/IPC.",
				Required: true,
				EnvVars:  prefixEnvVars("SOURCE"),
			},
		),
		Action: EngineAction(func(ctx *cli.Context, dest *sources.EngineAPIClient, _ log.Logger) error {
			rpcClient, err := rpc.DialOptions(context.Background(), ctx.String("source"))
			if err != nil {
				return fmt.Errorf("failed to dial engine source endpoint: %w", err)
			}
			source := client.NewBaseRPCClient(rpcClient)
			return engine.Copy(context.Background(), source, dest)
		}),
	}

	EngineCopyPayloadCmd = &cli.Command{
		Name:        "copy-payload",
		Description: "Take the block by number from source and insert it to the engine with NewPayload. No other calls are made.",
		Flags: withEngineFlags(
			&cli.StringFlag{
				Name:     "source",
				Usage:    "Unauthenticated regular eth JSON RPC to pull block data from, can be HTTP/WS/IPC.",
				Required: true,
				EnvVars:  prefixEnvVars("SOURCE"),
			},
			&cli.Uint64Flag{
				Name:     "number",
				Usage:    "Block number to copy from the source",
				Required: true,
				EnvVars:  prefixEnvVars("NUMBER"),
			},
		),
		Action: EngineAction(func(ctx *cli.Context, dest *sources.EngineAPIClient, _ log.Logger) error {
			rpcClient, err := rpc.DialOptions(context.Background(), ctx.String("source"))
			if err != nil {
				return fmt.Errorf("failed to dial engine source endpoint: %w", err)
			}
			source := client.NewBaseRPCClient(rpcClient)
			return engine.CopyPayload(context.Background(), ctx.Uint64("number"), source, dest)
		}),
	}

	EngineSetForkchoiceCmd = &cli.Command{
		Name:        "set-forkchoice",
		Description: "Set forkchoice, specify unsafe, safe and finalized blocks by number",
		Flags: withEngineFlags(
			&cli.Uint64Flag{
				Name:     "unsafe",
				Usage:    "Block number of block to set as latest block",
				Required: true,
				EnvVars:  prefixEnvVars("UNSAFE"),
			},
			&cli.Uint64Flag{
				Name:     "safe",
				Usage:    "Block number of block to set as safe block",
				Required: true,
				EnvVars:  prefixEnvVars("SAFE"),
			},
			&cli.Uint64Flag{
				Name:     "finalized",
				Usage:    "Block number of block to set as finalized block",
				Required: true,
				EnvVars:  prefixEnvVars("FINALIZED"),
			},
		),
		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error {
			return engine.SetForkchoice(ctx.Context, client, ctx.Uint64("finalized"), ctx.Uint64("safe"), ctx.Uint64("unsafe"))
		}),
	}

	EngineSetForkchoiceHashCmd = &cli.Command{
		Name:        "set-forkchoice-by-hash",
		Description: "Set forkchoice, specify unsafe, safe and finalized blocks by hash",
		Flags: withEngineFlags(
			&cli.StringFlag{
				Name:     "unsafe",
				Usage:    "Block hash of block to set as latest block",
				Required: true,
				EnvVars:  prefixEnvVars("UNSAFE"),
			},
			&cli.StringFlag{
				Name:     "safe",
				Usage:    "Block hash of block to set as safe block",
				Required: true,
				EnvVars:  prefixEnvVars("SAFE"),
			},
			&cli.StringFlag{
				Name:     "finalized",
				Usage:    "Block hash of block to set as finalized block",
				Required: true,
				EnvVars:  prefixEnvVars("FINALIZED"),
			},
		),
		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error {
			finalized := common.HexToHash(ctx.String("finalized"))
			safe := common.HexToHash(ctx.String("safe"))
			unsafe := common.HexToHash(ctx.String("unsafe"))
			return engine.SetForkchoiceByHash(ctx.Context, client, finalized, safe, unsafe)
		}),
	}

	EngineRewindCmd = &cli.Command{
		Name:        "rewind",
		Description: "Rewind chain by number (destructive!)",
		Flags: withEngineFlags(
			&cli.Uint64Flag{
				Name:     "to",
				Usage:    "Block number to rewind chain to",
				Required: true,
				EnvVars:  prefixEnvVars("REWIND_TO"),
			},
			&cli.BoolFlag{
				Name:    "set-head",
				Usage:   "Whether to also call debug_setHead when rewinding",
				EnvVars: prefixEnvVars("REWIND_SET_HEAD"),
			},
		),
		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, lgr log.Logger) error {
			open, err := initOpenEngineRPC(ctx, lgr)
			if err != nil {
				return fmt.Errorf("failed to dial open RPC endpoint: %w", err)
			}
			return engine.Rewind(ctx.Context, lgr, client, open, ctx.Uint64("to"), ctx.Bool("set-head"))
		}),
	}

	EngineJSONCmd = &cli.Command{
		Name:        "json",
		Description: "read json values from remaining args, or STDIN, and use them as RPC params to call the engine RPC method (first arg)",
		Flags: withEngineFlags(
			&cli.BoolFlag{
				Name:     "stdin",
				Usage:    "Read params from stdin instead",
				Required: false,
				EnvVars:  prefixEnvVars("STDIN"),
			},
		),
		ArgsUsage: "<rpc-method-name> [params...]",
		Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error {
			if ctx.NArg() == 0 {
				return fmt.Errorf("expected at least 1 argument: RPC method name")
			}
			var r io.Reader
			var args []string
			if ctx.Bool("stdin") {
				r = ctx.App.Reader
			} else {
				args = ctx.Args().Tail()
			}
			return engine.RawJSONInteraction(ctx.Context, client.RPC, ctx.Args().Get(0), args, r, ctx.App.Writer)
		}),
	}
)
View Source
var CheatCmd = &cli.Command{
	Name:  "cheat",
	Usage: "Cheating commands to modify a Geth database.",
	Description: "Each sub-command opens a Geth database, applies the cheat, and then saves and closes the database." +
		"The Geth node will live in its own false reality, other nodes cannot sync the cheated state if they process the blocks.",
	Subcommands: []*cli.Command{
		CheatStorageCmd,
		CheatSetBalanceCmd,
		CheatSetCodeCmd,
		CheatSetNonceCmd,
		CheatPrintHeadBlock,
		CheatPrintHeadHeader,
	},
}
View Source
var EngineCmd = &cli.Command{
	Name:        "engine",
	Usage:       "Engine API commands to build/reorg/rewind/finalize/copy blocks.",
	Description: "Each sub-command dials the engine API endpoint (with provided JWT secret) and then runs the action",
	Subcommands: []*cli.Command{
		EngineBlockCmd,
		EngineAutoCmd,
		EngineStatusCmd,
		EngineCopyCmd,
		EngineCopyPayloadCmd,
		EngineSetForkchoiceCmd,
		EngineSetForkchoiceHashCmd,
		EngineRewindCmd,
		EngineJSONCmd,
	},
}

Functions

func CheatAction

func CheatAction(readOnly bool, fn func(ctx *cli.Context, ch *cheat.Cheater) error) cli.ActionFunc

func CheatRawDBAction

func CheatRawDBAction(readOnly bool, fn func(ctx *cli.Context, db ethdb.Database) error) cli.ActionFunc

func EngineAction

func EngineAction(fn func(ctx *cli.Context, client *sources.EngineAPIClient, lgr log.Logger) error) cli.ActionFunc

func ParseBuildingArgs

func ParseBuildingArgs(ctx *cli.Context) *engine.BlockBuildingSettings

Types

type Text

type Text interface {
	encoding.TextUnmarshaler
	fmt.Stringer
	comparable
}

type TextFlag

type TextFlag[T Text] struct {
	Value T
}

func (*TextFlag[T]) Clone added in v1.2.0

func (a *TextFlag[T]) Clone() any

func (*TextFlag[T]) Get

func (a *TextFlag[T]) Get() T

func (*TextFlag[T]) Set

func (a *TextFlag[T]) Set(value string) error

func (*TextFlag[T]) String

func (a *TextFlag[T]) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL