diff --git a/build/ci.go b/build/ci.go index 680bdc9a9c..754d88a86a 100644 --- a/build/ci.go +++ b/build/ci.go @@ -53,6 +53,7 @@ import ( "path" "path/filepath" "runtime" + "slices" "strings" "time" @@ -226,8 +227,7 @@ func doInstall(cmdline []string) { // Do the build! for _, pkg := range packages { - args := make([]string, len(gobuild.Args)) - copy(args, gobuild.Args) + args := slices.Clone(gobuild.Args) args = append(args, "-o", executablePath(path.Base(pkg))) args = append(args, pkg) build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env}) diff --git a/cmd/blsync/main.go b/cmd/blsync/main.go index 586f1b79cf..6a35e9d16a 100644 --- a/cmd/blsync/main.go +++ b/cmd/blsync/main.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "os" + "slices" "github.com/ethereum/go-ethereum/beacon/blsync" "github.com/ethereum/go-ethereum/cmd/utils" @@ -33,7 +34,7 @@ import ( func main() { app := flags.NewApp("beacon light syncer tool") - app.Flags = flags.Merge([]cli.Flag{ + app.Flags = slices.Concat([]cli.Flag{ utils.BeaconApiFlag, utils.BeaconApiHeaderFlag, utils.BeaconThresholdFlag, diff --git a/cmd/devp2p/discv4cmd.go b/cmd/devp2p/discv4cmd.go index 3b5400ca3a..8c48b3a557 100644 --- a/cmd/devp2p/discv4cmd.go +++ b/cmd/devp2p/discv4cmd.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "net/http" + "slices" "strconv" "strings" "time" @@ -28,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" @@ -83,7 +83,7 @@ var ( Name: "listen", Usage: "Runs a discovery node", Action: discv4Listen, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{ + Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{ httpAddrFlag, }), } @@ -91,7 +91,7 @@ var ( Name: "crawl", Usage: "Updates a nodes.json file with random nodes found in the DHT", Action: discv4Crawl, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}), + Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}), } discv4TestCommand = &cli.Command{ Name: "test", diff --git a/cmd/devp2p/discv5cmd.go b/cmd/devp2p/discv5cmd.go index 0dac945269..2422ef6644 100644 --- a/cmd/devp2p/discv5cmd.go +++ b/cmd/devp2p/discv5cmd.go @@ -19,11 +19,11 @@ package main import ( "errors" "fmt" + "slices" "time" "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/urfave/cli/v2" ) @@ -56,7 +56,7 @@ var ( Name: "crawl", Usage: "Updates a nodes.json file with random nodes found in the DHT", Action: discv5Crawl, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{ + Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{ crawlTimeoutFlag, }), } diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 994684ab22..0d4471b8d5 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -21,6 +21,7 @@ import ( "fmt" "math/big" "os" + "slices" "github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool" "github.com/ethereum/go-ethereum/internal/debug" @@ -254,7 +255,7 @@ var traceFlags = []cli.Flag{ var app = flags.NewApp("the evm command line interface") func init() { - app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags) + app.Flags = slices.Concat(vmFlags, traceFlags, debug.Flags) app.Commands = []*cli.Command{ compileCommand, disasmCommand, diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 235fed6630..3f82deaf70 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -24,6 +24,7 @@ import ( "math/big" "os" goruntime "runtime" + "slices" "testing" "time" @@ -50,7 +51,7 @@ var runCommand = &cli.Command{ Usage: "Run arbitrary evm binary", ArgsUsage: "", Description: `The run command runs arbitrary EVM code.`, - Flags: flags.Merge(vmFlags, traceFlags), + Flags: slices.Concat(vmFlags, traceFlags), } // readGenesis will read the given JSON format genesis file and return diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index d85e4a83c8..f6dc1cf4bf 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "runtime" + "slices" "strconv" "sync/atomic" "time" @@ -36,7 +37,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/era" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" @@ -49,7 +49,7 @@ var ( Name: "init", Usage: "Bootstrap and initialize a new genesis block", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CachePreimagesFlag, utils.OverrideCancun, utils.OverrideVerkle, @@ -76,7 +76,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`, Name: "import", Usage: "Import a blockchain file", ArgsUsage: " ( ... ) ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, utils.GCModeFlag, @@ -115,7 +115,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`, Name: "export", Usage: "Export blockchain into file", ArgsUsage: " [ ]", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, }, utils.DatabaseFlags), @@ -131,7 +131,7 @@ be gzipped.`, Name: "import-history", Usage: "Import an Era archive", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.TxLookupLimitFlag, }, utils.DatabaseFlags, @@ -147,7 +147,7 @@ from Era archives. Name: "export-history", Usage: "Export blockchain history to Era archives", ArgsUsage: " ", - Flags: flags.Merge(utils.DatabaseFlags), + Flags: slices.Concat(utils.DatabaseFlags), Description: ` The export-history command will export blocks and their corresponding receipts into Era archives. Eras are typically packaged in steps of 8192 blocks. @@ -158,7 +158,7 @@ into Era archives. Eras are typically packaged in steps of 8192 blocks. Name: "import-preimages", Usage: "Import the preimage database from an RLP stream", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, }, utils.DatabaseFlags), @@ -173,7 +173,7 @@ It's deprecated, please use "geth db import" instead. Name: "dump", Usage: "Dump a specific block from storage", ArgsUsage: "[? | ]", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.IterativeOutputFlag, utils.ExcludeCodeFlag, diff --git a/cmd/geth/config.go b/cmd/geth/config.go index a7f894ab37..842c1c2347 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -23,6 +23,7 @@ import ( "os" "reflect" "runtime" + "slices" "strings" "unicode" @@ -53,7 +54,7 @@ var ( Name: "dumpconfig", Usage: "Export configuration values in a TOML format", ArgsUsage: "", - Flags: flags.Merge(nodeFlags, rpcFlags), + Flags: slices.Concat(nodeFlags, rpcFlags), Description: `Export configuration values in TOML format (to stdout by default).`, } diff --git a/cmd/geth/consolecmd.go b/cmd/geth/consolecmd.go index 2a59f0052f..bf38c86349 100644 --- a/cmd/geth/consolecmd.go +++ b/cmd/geth/consolecmd.go @@ -18,11 +18,11 @@ package main import ( "fmt" + "slices" "strings" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/console" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/urfave/cli/v2" ) @@ -33,7 +33,7 @@ var ( Action: localConsole, Name: "console", Usage: "Start an interactive JavaScript environment", - Flags: flags.Merge(nodeFlags, rpcFlags, consoleFlags), + Flags: slices.Concat(nodeFlags, rpcFlags, consoleFlags), Description: ` The Geth console is an interactive shell for the JavaScript runtime environment which exposes a node admin interface as well as the Ðapp JavaScript API. @@ -45,7 +45,7 @@ See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console.`, Name: "attach", Usage: "Start an interactive JavaScript environment (connect to node)", ArgsUsage: "[endpoint]", - Flags: flags.Merge([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags), + Flags: slices.Concat([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags), Description: ` The Geth console is an interactive shell for the JavaScript runtime environment which exposes a node admin interface as well as the Ðapp JavaScript API. @@ -58,7 +58,7 @@ This command allows to open a console on a running geth node.`, Name: "js", Usage: "(DEPRECATED) Execute the specified JavaScript files", ArgsUsage: " [jsfile...]", - Flags: flags.Merge(nodeFlags, consoleFlags), + Flags: slices.Concat(nodeFlags, consoleFlags), Description: ` The JavaScript VM exposes a node admin interface as well as the Ðapp JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`, diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 052ae0eab2..7622246050 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -22,6 +22,7 @@ import ( "os" "os/signal" "path/filepath" + "slices" "strconv" "strings" "syscall" @@ -36,7 +37,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -60,7 +60,7 @@ var ( Name: "removedb", Usage: "Remove blockchain and state databases", ArgsUsage: "", - Flags: flags.Merge(utils.DatabaseFlags, + Flags: slices.Concat(utils.DatabaseFlags, []cli.Flag{removeStateDataFlag, removeChainDataFlag}), Description: ` Remove blockchain and state databases`, @@ -89,7 +89,7 @@ Remove blockchain and state databases`, Action: inspect, Name: "inspect", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Usage: "Inspect the storage size for each type of data in the database", @@ -99,7 +99,7 @@ Remove blockchain and state databases`, Action: checkStateContent, Name: "check-state-content", ArgsUsage: "", - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Usage: "Verify that state data is cryptographically correct", Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes. For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates @@ -109,7 +109,7 @@ a data corruption.`, Action: dbStats, Name: "stats", Usage: "Print leveldb statistics", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), } @@ -117,7 +117,7 @@ a data corruption.`, Action: dbCompact, Name: "compact", Usage: "Compact leveldb database. WARNING: May take a very long time", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, utils.CacheFlag, utils.CacheDatabaseFlag, @@ -131,7 +131,7 @@ corruption if it is aborted during execution'!`, Name: "get", Usage: "Show the value of a database key", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command looks up the specified database key from the database.", @@ -141,7 +141,7 @@ corruption if it is aborted during execution'!`, Name: "delete", Usage: "Delete a database key (WARNING: may corrupt your database)", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command deletes the specified database key from the database. @@ -152,7 +152,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "put", Usage: "Set the value of a database key (WARNING: may corrupt your database)", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command sets a given database key to the given value. @@ -163,7 +163,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "dumptrie", Usage: "Show the storage key/values of a given storage trie", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command looks up the specified database key from the database.", @@ -173,7 +173,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "freezer-index", Usage: "Dump out the index of a specific freezer table", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command displays information about the freezer index.", @@ -183,7 +183,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "import", Usage: "Imports leveldb-data from an exported RLP dump.", ArgsUsage: " has .gz suffix, gzip compression will be used.", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.", @@ -202,7 +202,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Action: showMetaData, Name: "metadata", Usage: "Shows metadata about the chain status.", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "Shows metadata about the chain status.", @@ -212,7 +212,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "inspect-history", Usage: "Inspect the state history within block range", ArgsUsage: "
[OPTIONAL ]", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, &cli.Uint64Flag{ Name: "start", diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 2675a61675..10d4052737 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -20,6 +20,7 @@ package main import ( "fmt" "os" + "slices" "sort" "strconv" "strings" @@ -53,7 +54,7 @@ const ( var ( // flags that configure the node - nodeFlags = flags.Merge([]cli.Flag{ + nodeFlags = slices.Concat([]cli.Flag{ utils.IdentityFlag, utils.UnlockedAccountFlag, utils.PasswordFileFlag, @@ -66,7 +67,7 @@ var ( utils.SmartCardDaemonPathFlag, utils.OverrideCancun, utils.OverrideVerkle, - utils.EnablePersonal, + utils.EnablePersonal, // deprecated utils.TxPoolLocalsFlag, utils.TxPoolNoLocalsFlag, utils.TxPoolJournalFlag, @@ -251,7 +252,7 @@ func init() { } sort.Sort(cli.CommandsByName(app.Commands)) - app.Flags = flags.Merge( + app.Flags = slices.Concat( nodeFlags, rpcFlags, consoleFlags, diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 14c6826e1d..f0be52a0df 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "os" + "slices" "time" "github.com/ethereum/go-ethereum/cmd/utils" @@ -32,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -50,7 +50,7 @@ var ( Usage: "Prune stale ethereum state data based on the snapshot", ArgsUsage: "", Action: pruneState, - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.BloomFilterSizeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: ` @@ -70,7 +70,7 @@ WARNING: it's only supported in hash mode(--state.scheme=hash)". Usage: "Recalculate state hash based on the snapshot for verification", ArgsUsage: "", Action: verifyState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot verify-state will traverse the whole accounts and storages set based on the specified @@ -83,7 +83,7 @@ In other words, this command does the snapshot to trie conversion. Usage: "Check that there is no 'dangling' snap storage", ArgsUsage: "", Action: checkDanglingStorage, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot check-dangling-storage traverses the snap storage data, and verifies that all snapshot storage data has a corresponding account. @@ -94,7 +94,7 @@ data, and verifies that all snapshot storage data has a corresponding account. Usage: "Check all snapshot layers for the specific account", ArgsUsage: "
", Action: checkAccount, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot inspect-account
checks all snapshot layers and prints out information about the specified address. @@ -105,7 +105,7 @@ information about the specified address. Usage: "Traverse the state with given root hash and perform quick verification", ArgsUsage: "", Action: traverseState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot traverse-state will traverse the whole state from the given state root and will abort if any @@ -120,7 +120,7 @@ It's also usable without snapshot enabled. Usage: "Traverse the state with given root hash and perform detailed verification", ArgsUsage: "", Action: traverseRawState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot traverse-rawstate will traverse the whole state from the given root and will abort if any referenced @@ -136,7 +136,7 @@ It's also usable without snapshot enabled. Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)", ArgsUsage: "[? | ]", Action: dumpState, - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.ExcludeCodeFlag, utils.ExcludeStorageFlag, utils.StartKeyFlag, diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 9eb37fb5a8..6490f832af 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -22,11 +22,11 @@ import ( "errors" "fmt" "os" + "slices" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-verkle" "github.com/urfave/cli/v2" @@ -45,7 +45,7 @@ var ( Usage: "verify the conversion of a MPT into a verkle tree", ArgsUsage: "", Action: verifyVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth verkle verify This command takes a root commitment and attempts to rebuild the tree. @@ -56,7 +56,7 @@ This command takes a root commitment and attempts to rebuild the tree. Usage: "Dump a verkle tree to a DOT file", ArgsUsage: " [ ...]", Action: expandVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth verkle dump [ ...] This command will produce a dot file representing the tree, rooted at . diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e98d5cc8e3..f083a25f90 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -176,12 +176,6 @@ var ( Usage: "Custom node name", Category: flags.NetworkingCategory, } - DocRootFlag = &flags.DirectoryFlag{ - Name: "docroot", - Usage: "Document Root for HTTPClient file scheme", - Value: flags.DirectoryString(flags.HomeDir()), - Category: flags.APICategory, - } ExitWhenSyncedFlag = &cli.BoolFlag{ Name: "exitwhensynced", Usage: "Exits after block synchronisation completes", @@ -217,8 +211,7 @@ var ( Value: 0, } - defaultSyncMode = ethconfig.Defaults.SyncMode - SnapshotFlag = &cli.BoolFlag{ + SnapshotFlag = &cli.BoolFlag{ Name: "snapshot", Usage: `Enables snapshot-database mode (default = enable)`, Value: true, @@ -250,10 +243,10 @@ var ( Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } - SyncModeFlag = &flags.TextMarshalerFlag{ + SyncModeFlag = &cli.StringFlag{ Name: "syncmode", Usage: `Blockchain sync mode ("snap" or "full")`, - Value: &defaultSyncMode, + Value: ethconfig.Defaults.SyncMode.String(), Category: flags.StateCategory, } GCModeFlag = &cli.StringFlag{ @@ -741,11 +734,6 @@ var ( Value: node.DefaultConfig.BatchResponseMaxSize, Category: flags.APICategory, } - EnablePersonal = &cli.BoolFlag{ - Name: "rpc.enabledeprecatedpersonal", - Usage: "Enables the (deprecated) personal namespace", - Category: flags.APICategory, - } // Network Settings MaxPeersFlag = &cli.IntFlag{ @@ -1399,9 +1387,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { if ctx.IsSet(JWTSecretFlag.Name) { cfg.JWTSecret = ctx.String(JWTSecretFlag.Name) } - if ctx.IsSet(EnablePersonal.Name) { - cfg.EnablePersonal = true + log.Warn(fmt.Sprintf("Option --%s is deprecated. The 'personal' RPC namespace has been removed.", EnablePersonal.Name)) } if ctx.IsSet(ExternalSignerFlag.Name) { @@ -1675,7 +1662,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.IsSet(SyncTargetFlag.Name) { cfg.SyncMode = downloader.FullSync // dev sync target forces full sync } else if ctx.IsSet(SyncModeFlag.Name) { - cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) + if err = cfg.SyncMode.UnmarshalText([]byte(ctx.String(SyncModeFlag.Name))); err != nil { + Fatalf("invalid --syncmode flag: %v", err) + } } if ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name) @@ -1755,9 +1744,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.SnapshotCache = 0 // Disabled } } - if ctx.IsSet(DocRootFlag.Name) { - cfg.DocRoot = ctx.String(DocRootFlag.Name) - } if ctx.IsSet(VMEnableDebugFlag.Name) { // TODO(fjl): force-enable this in --dev mode cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index f145f605d6..6209516e05 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -153,6 +153,12 @@ var ( Usage: "Enable expensive metrics collection and reporting (deprecated)", Category: flags.DeprecatedCategory, } + // Deprecated Oct 2024 + EnablePersonal = &cli.BoolFlag{ + Name: "rpc.enabledeprecatedpersonal", + Usage: "This used to enable the 'personal' namespace.", + Category: flags.DeprecatedCategory, + } ) // showDeprecated displays deprecated flags that will be soon removed from the codebase. diff --git a/console/bridge.go b/console/bridge.go index 37578041ca..c1d7746c02 100644 --- a/console/bridge.go +++ b/console/bridge.go @@ -19,15 +19,12 @@ package console import ( "encoding/json" "errors" - "fmt" "io" "reflect" "strings" "time" "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/accounts/scwallet" - "github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/console/prompt" "github.com/ethereum/go-ethereum/internal/jsre" @@ -51,268 +48,6 @@ func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writ } } -func getJeth(vm *goja.Runtime) *goja.Object { - jeth := vm.Get("jeth") - if jeth == nil { - panic(vm.ToValue("jeth object does not exist")) - } - return jeth.ToObject(vm) -} - -// NewAccount is a wrapper around the personal.newAccount RPC method that uses a -// non-echoing password prompt to acquire the passphrase and executes the original -// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call. -func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) { - var ( - password string - confirm string - err error - ) - switch { - // No password was specified, prompt the user for it - case len(call.Arguments) == 0: - if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil { - return nil, err - } - if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil { - return nil, err - } - if password != confirm { - return nil, errors.New("passwords don't match") - } - // A single string password was specified, use that - case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil: - password = call.Argument(0).ToString().String() - default: - return nil, errors.New("expected 0 or 1 string argument") - } - // Password acquired, execute the call and return - newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount")) - if !callable { - return nil, errors.New("jeth.newAccount is not callable") - } - ret, err := newAccount(goja.Null(), call.VM.ToValue(password)) - if err != nil { - return nil, err - } - return ret, nil -} - -// OpenWallet is a wrapper around personal.openWallet which can interpret and -// react to certain error messages, such as the Trezor PIN matrix request. -func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) { - // Make sure we have a wallet specified to open - if call.Argument(0).ToObject(call.VM).ClassName() != "String" { - return nil, errors.New("first argument must be the wallet URL to open") - } - wallet := call.Argument(0) - - var passwd goja.Value - if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { - passwd = call.VM.ToValue("") - } else { - passwd = call.Argument(1) - } - // Open the wallet and return if successful in itself - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - val, err := openWallet(goja.Null(), wallet, passwd) - if err == nil { - return val, nil - } - - // Wallet open failed, report error unless it's a PIN or PUK entry - switch { - case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()): - val, err = b.readPinAndReopenWallet(call) - if err == nil { - return val, nil - } - val, err = b.readPassphraseAndReopenWallet(call) - if err != nil { - return nil, err - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()): - // PUK input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter the pairing password: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - if val, err = openWallet(goja.Null(), wallet, passwd); err != nil { - if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) { - return nil, err - } - // PIN input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil { - return nil, err - } - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPINUnblockNeeded.Error()): - // PIN unblock requested, fetch PUK and new PIN from the user - var pukpin string - input, err := b.prompter.PromptPassword("Please enter current PUK: ") - if err != nil { - return nil, err - } - pukpin = input - input, err = b.prompter.PromptPassword("Please enter new PIN: ") - if err != nil { - return nil, err - } - pukpin += input - - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(pukpin)); err != nil { - return nil, err - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()): - // PIN input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil { - return nil, err - } - - default: - // Unknown error occurred, drop to the user - return nil, err - } - return val, nil -} - -func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) { - wallet := call.Argument(0) - input, err := b.prompter.PromptPassword("Please enter your passphrase: ") - if err != nil { - return nil, err - } - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) -} - -func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) { - wallet := call.Argument(0) - // Trezor PIN matrix input requested, display the matrix to the user and fetch the data - fmt.Fprintf(b.printer, "Look at the device for number positions\n\n") - fmt.Fprintf(b.printer, "7 | 8 | 9\n") - fmt.Fprintf(b.printer, "--+---+--\n") - fmt.Fprintf(b.printer, "4 | 5 | 6\n") - fmt.Fprintf(b.printer, "--+---+--\n") - fmt.Fprintf(b.printer, "1 | 2 | 3\n\n") - - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) -} - -// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that -// uses a non-echoing password prompt to acquire the passphrase and executes the -// original RPC method (saved in jeth.unlockAccount) with it to actually execute -// the RPC call. -func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) { - if len(call.Arguments) < 1 { - return nil, errors.New("usage: unlockAccount(account, [ password, duration ])") - } - - account := call.Argument(0) - // Make sure we have an account specified to unlock. - if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String { - return nil, errors.New("first argument must be the account to unlock") - } - - // If password is not given or is the null value, prompt the user for it. - var passwd goja.Value - if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { - fmt.Fprintf(b.printer, "Unlock account %s\n", account) - input, err := b.prompter.PromptPassword("Passphrase: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - } else { - if call.Argument(1).ExportType().Kind() != reflect.String { - return nil, errors.New("password must be a string") - } - passwd = call.Argument(1) - } - - // Third argument is the duration how long the account should be unlocked. - duration := goja.Null() - if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) { - if !isNumber(call.Argument(2)) { - return nil, errors.New("unlock duration must be a number") - } - duration = call.Argument(2) - } - - // Send the request to the backend and return. - unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount")) - if !callable { - return nil, errors.New("jeth.unlockAccount is not callable") - } - return unlockAccount(goja.Null(), account, passwd, duration) -} - -// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password -// prompt to acquire the passphrase and executes the original RPC method (saved in -// jeth.sign) with it to actually execute the RPC call. -func (b *bridge) Sign(call jsre.Call) (goja.Value, error) { - if nArgs := len(call.Arguments); nArgs < 2 { - return nil, errors.New("usage: sign(message, account, [ password ])") - } - var ( - message = call.Argument(0) - account = call.Argument(1) - passwd = call.Argument(2) - ) - - if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String { - return nil, errors.New("first argument must be the message to sign") - } - if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String { - return nil, errors.New("second argument must be the account to sign with") - } - - // if the password is not given or null ask the user and ensure password is a string - if goja.IsUndefined(passwd) || goja.IsNull(passwd) { - fmt.Fprintf(b.printer, "Give password for account %s\n", account) - input, err := b.prompter.PromptPassword("Password: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - } else if passwd.ExportType().Kind() != reflect.String { - return nil, errors.New("third argument must be the password to unlock the account") - } - - // Send the request to the backend and return - sign, callable := goja.AssertFunction(getJeth(call.VM).Get("sign")) - if !callable { - return nil, errors.New("jeth.sign is not callable") - } - return sign(goja.Null(), message, account, passwd) -} - // Sleep will block the console for the specified number of seconds. func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) { if nArgs := len(call.Arguments); nArgs < 1 { diff --git a/console/bridge_test.go b/console/bridge_test.go deleted file mode 100644 index e57e294fc5..0000000000 --- a/console/bridge_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package console - -import ( - "testing" - - "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/internal/jsre" -) - -// TestUndefinedAsParam ensures that personal functions can receive -// `undefined` as a parameter. -func TestUndefinedAsParam(t *testing.T) { - b := bridge{} - call := jsre.Call{} - call.Arguments = []goja.Value{goja.Undefined()} - - b.UnlockAccount(call) - b.Sign(call) - b.Sleep(call) -} - -// TestNullAsParam ensures that personal functions can receive -// `null` as a parameter. -func TestNullAsParam(t *testing.T) { - b := bridge{} - call := jsre.Call{} - call.Arguments = []goja.Value{goja.Null()} - - b.UnlockAccount(call) - b.Sign(call) - b.Sleep(call) -} diff --git a/console/console.go b/console/console.go index 5acb4cdccb..b5c77bd78f 100644 --- a/console/console.go +++ b/console/console.go @@ -142,7 +142,6 @@ func (c *Console) init(preload []string) error { // Add bridge overrides for web3.js functionality. c.jsre.Do(func(vm *goja.Runtime) { c.initAdmin(vm, bridge) - c.initPersonal(vm, bridge) }) // Preload JavaScript files. @@ -249,30 +248,6 @@ func (c *Console) initAdmin(vm *goja.Runtime, bridge *bridge) { } } -// initPersonal redirects account-related API methods through the bridge. -// -// If the console is in interactive mode and the 'personal' API is available, override -// the openWallet, unlockAccount, newAccount and sign methods since these require user -// interaction. The original web3 callbacks are stored in 'jeth'. These will be called -// by the bridge after the prompt and send the original web3 request to the backend. -func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) { - personal := getObject(vm, "personal") - if personal == nil || c.prompter == nil { - return - } - log.Warn("Enabling deprecated personal namespace") - jeth := vm.NewObject() - vm.Set("jeth", jeth) - jeth.Set("openWallet", personal.Get("openWallet")) - jeth.Set("unlockAccount", personal.Get("unlockAccount")) - jeth.Set("newAccount", personal.Get("newAccount")) - jeth.Set("sign", personal.Get("sign")) - personal.Set("openWallet", jsre.MakeCallback(vm, bridge.OpenWallet)) - personal.Set("unlockAccount", jsre.MakeCallback(vm, bridge.UnlockAccount)) - personal.Set("newAccount", jsre.MakeCallback(vm, bridge.NewAccount)) - personal.Set("sign", jsre.MakeCallback(vm, bridge.Sign)) -} - func (c *Console) clearHistory() { c.history = nil c.prompter.ClearHistory() diff --git a/core/state/statedb.go b/core/state/statedb.go index 0183c14480..775a224af9 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -341,6 +341,9 @@ func (s *StateDB) TxIndex() int { func (s *StateDB) GetCode(addr common.Address) []byte { stateObject := s.getStateObject(addr) if stateObject != nil { + if s.witness != nil { + s.witness.AddCode(stateObject.Code()) + } return stateObject.Code() } return nil @@ -349,6 +352,9 @@ func (s *StateDB) GetCode(addr common.Address) []byte { func (s *StateDB) GetCodeSize(addr common.Address) int { stateObject := s.getStateObject(addr) if stateObject != nil { + if s.witness != nil { + s.witness.AddCode(stateObject.Code()) + } return stateObject.CodeSize() } return 0 diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 363fa29c02..54ae3be569 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -358,7 +358,7 @@ func (p *TxPool) Add(txs []*types.Transaction, local bool, sync bool) []error { for i, split := range splits { // If the transaction was rejected by all subpools, mark it unsupported if split == -1 { - errs[i] = core.ErrTxTypeNotSupported + errs[i] = fmt.Errorf("%w: received type %d", core.ErrTxTypeNotSupported, txs[i].Type()) continue } // Find which subpool handled it and pull in the corresponding error diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 7fd5f8bc79..5ff92d71c2 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -99,7 +99,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types } // Make sure the transaction is signed properly if _, err := types.Sender(signer, tx); err != nil { - return ErrInvalidSender + return fmt.Errorf("%w: %v", ErrInvalidSender, err) } // Ensure the transaction has more gas than the bare minimum needed to cover // the transaction metadata diff --git a/core/vm/evm.go b/core/vm/evm.go index 26ff495579..0593a32a3e 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -213,9 +213,6 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. code := evm.StateDB.GetCode(addr) - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(code) - } if len(code) == 0 { ret, err = nil, nil // gas is unchanged } else { @@ -283,9 +280,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := NewContract(caller, AccountRef(caller.Address()), value, gas) - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(evm.StateDB.GetCode(addrCopy)) - } contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas @@ -333,9 +327,6 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by addrCopy := addr // Initialise a new contract and make initialise the delegate values contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(evm.StateDB.GetCode(addrCopy)) - } contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas @@ -391,9 +382,6 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(evm.StateDB.GetCode(addrCopy)) - } contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 427eb3bab5..47eb62be08 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -340,10 +340,6 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.peek() - address := slot.Bytes20() - if witness := interpreter.evm.StateDB.Witness(); witness != nil { - witness.AddCode(interpreter.evm.StateDB.GetCode(address)) - } slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20()))) return nil, nil } @@ -383,9 +379,6 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) } addr := common.Address(a.Bytes20()) code := interpreter.evm.StateDB.GetCode(addr) - if witness := interpreter.evm.StateDB.Witness(); witness != nil { - witness.AddCode(code) - } codeCopy := getData(code, uint64CodeOffset, length.Uint64()) scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 2ad991ee41..2243e14b65 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -142,13 +142,16 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { // set the receiver's (the executing contract) code for execution. cfg.State.SetCode(address, code) // Call the code with the given configuration. - ret, _, err := vmenv.Call( + ret, leftOverGas, err := vmenv.Call( sender, common.BytesToAddress([]byte("contract")), input, cfg.GasLimit, uint256.MustFromBig(cfg.Value), ) + if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil { + cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err) + } return ret, cfg.State, err } @@ -181,6 +184,9 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { cfg.GasLimit, uint256.MustFromBig(cfg.Value), ) + if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil { + cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err) + } return code, address, leftOverGas, err } @@ -214,5 +220,8 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er cfg.GasLimit, uint256.MustFromBig(cfg.Value), ) + if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil { + cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err) + } return ret, leftOverGas, err } diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 7bb31329c6..3ac719c23e 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -208,7 +208,6 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { t.Fatalf("error preparing payload, err=%v", err) } // give the payload some time to be built - time.Sleep(100 * time.Millisecond) payloadID := (&miner.BuildPayloadArgs{ Parent: fcState.HeadBlockHash, Timestamp: blockParams.Timestamp, @@ -217,12 +216,12 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { BeaconRoot: blockParams.BeaconRoot, Version: engine.PayloadV1, }).Id() - execData, err := api.GetPayloadV1(payloadID) + execData, err := api.getPayload(payloadID, true) if err != nil { t.Fatalf("error getting payload, err=%v", err) } - if len(execData.Transactions) != blocks[9].Transactions().Len() { - t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions)) + if len(execData.ExecutionPayload.Transactions) != blocks[9].Transactions().Len() { + t.Fatalf("invalid number of transactions %d != 1", len(execData.ExecutionPayload.Transactions)) } // Test invalid payloadID var invPayload engine.PayloadID @@ -453,7 +452,6 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) } mcfg := miner.DefaultConfig - mcfg.PendingFeeRecipient = testAddr ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg} ethservice, err := eth.New(n, ethcfg) if err != nil { @@ -628,7 +626,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { SafeBlockHash: common.Hash{}, FinalizedBlockHash: common.Hash{}, } - payload *engine.ExecutableData + payload *engine.ExecutionPayloadEnvelope resp engine.ForkChoiceResponse err error ) @@ -640,11 +638,10 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { t.Fatalf("error preparing payload, invalid status: %v", resp.PayloadStatus.Status) } // give the payload some time to be built - time.Sleep(50 * time.Millisecond) - if payload, err = api.GetPayloadV1(*resp.PayloadID); err != nil { + if payload, err = api.getPayload(*resp.PayloadID, true); err != nil { t.Fatalf("can't get payload: %v", err) } - if len(payload.Transactions) > 0 { + if len(payload.ExecutionPayload.Transactions) > 0 { break } // No luck this time we need to update the params and try again. @@ -653,7 +650,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { t.Fatalf("payload should not be empty") } } - execResp, err := api.NewPayloadV1(*payload) + execResp, err := api.NewPayloadV1(*payload.ExecutionPayload) if err != nil { t.Fatalf("can't execute payload: %v", err) } @@ -661,14 +658,14 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { t.Fatalf("invalid status: %v", execResp.Status) } fcState = engine.ForkchoiceStateV1{ - HeadBlockHash: payload.BlockHash, - SafeBlockHash: payload.ParentHash, - FinalizedBlockHash: payload.ParentHash, + HeadBlockHash: payload.ExecutionPayload.BlockHash, + SafeBlockHash: payload.ExecutionPayload.ParentHash, + FinalizedBlockHash: payload.ExecutionPayload.ParentHash, } if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.ExecutionPayload.Number { t.Fatalf("Chain head should be updated") } parent = ethservice.BlockChain().CurrentBlock() @@ -1736,9 +1733,6 @@ func TestWitnessCreationAndConsumption(t *testing.T) { if err != nil { t.Fatalf("error preparing payload, err=%v", err) } - // Give the payload some time to be built - time.Sleep(100 * time.Millisecond) - payloadID := (&miner.BuildPayloadArgs{ Parent: fcState.HeadBlockHash, Timestamp: blockParams.Timestamp, @@ -1748,7 +1742,7 @@ func TestWitnessCreationAndConsumption(t *testing.T) { BeaconRoot: blockParams.BeaconRoot, Version: engine.PayloadV3, }).Id() - envelope, err := api.GetPayloadV3(payloadID) + envelope, err := api.getPayload(payloadID, true) if err != nil { t.Fatalf("error getting payload, err=%v", err) } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index c325e5010c..f1a815e6d3 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -138,9 +138,6 @@ type Config struct { VMTrace string VMTraceJsonConfig string - // Miscellaneous options - DocRoot string `toml:"-"` - // RPCGasCap is the global gas cap for eth-call variants. RPCGasCap uint64 diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index d96ba0ccb7..0ec0eaddeb 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -46,7 +46,6 @@ func (c Config) MarshalTOML() (interface{}, error) { EnablePreimageRecording bool VMTrace string VMTraceJsonConfig string - DocRoot string `toml:"-"` RPCGasCap uint64 RPCEVMTimeout time.Duration RPCTxFeeCap float64 @@ -83,7 +82,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.EnablePreimageRecording = c.EnablePreimageRecording enc.VMTrace = c.VMTrace enc.VMTraceJsonConfig = c.VMTraceJsonConfig - enc.DocRoot = c.DocRoot enc.RPCGasCap = c.RPCGasCap enc.RPCEVMTimeout = c.RPCEVMTimeout enc.RPCTxFeeCap = c.RPCTxFeeCap @@ -124,7 +122,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { EnablePreimageRecording *bool VMTrace *string VMTraceJsonConfig *string - DocRoot *string `toml:"-"` RPCGasCap *uint64 RPCEVMTimeout *time.Duration RPCTxFeeCap *float64 @@ -222,9 +219,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.VMTraceJsonConfig != nil { c.VMTraceJsonConfig = *dec.VMTraceJsonConfig } - if dec.DocRoot != nil { - c.DocRoot = *dec.DocRoot - } if dec.RPCGasCap != nil { c.RPCGasCap = *dec.RPCGasCap } diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json index 0dbffe9cc0..a098b57029 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json @@ -67,8 +67,7 @@ "transactionPosition": 74, "transactionHash": "0x5ef60b27ac971c22a7d484e546e50093ca62300c8986d165154e47773764b6a4", "blockNumber": 1555279, - "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46", - "time": "209.346µs" + "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46" }, { "action": { diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json index c42b61aeaa..6baa57689f 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json @@ -67,8 +67,7 @@ "transactionPosition": 141, "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", "blockNumber": 1555278, - "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b", - "time": "300.9µs" + "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b" }, { "type": "call", @@ -81,9 +80,7 @@ "callType": "callcode" }, "error": "out of gas", - "traceAddress": [ - 0 - ], + "traceAddress": [0], "subtraces": 0, "transactionPosition": 141, "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json index c3cc19a920..8949dcfe57 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json @@ -63,8 +63,7 @@ "transactionPosition": 117, "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", - "time": "332.877µs" + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" }, { "type": "call", @@ -77,9 +76,7 @@ "callType": "callcode" }, "error": "invalid input length", - "traceAddress": [ - 0 - ], + "traceAddress": [0], "subtraces": 0, "transactionPosition": 117, "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create_oog_parity.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create_oog_parity.json new file mode 100644 index 0000000000..acaa43cefd --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create_oog_parity.json @@ -0,0 +1,92 @@ +{ + "genesis": { + "difficulty": "4639933", + "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", + "gasLimit": "9280188", + "hash": "0x9a5f3a98eb1c60f6e3f450658a9cea190157e7021d04f927b752ad6482cf9194", + "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", + "mixHash": "0x6b6f8fcaa54b8565c4c1ae7cf0a020e938a53007f4561e758b17bc05c9044d78", + "nonce": "0x773aba50dc51b462", + "number": "1555169", + "stateRoot": "0xc4b9703de3e59ff795baae2c3afa010cf039c37244a7a6af7f3f491a10601348", + "timestamp": "1590794111", + "totalDifficulty": "2242105342155", + "alloc": { + "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x62325b40cbbd0915c4b9", + "nonce": "260875", + "code": "0x", + "storage": {} + } + }, + "config": { + "chainId": 63, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 0, + "eip158Block": 0, + "ethash": {}, + "homesteadBlock": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 301243, + "petersburgBlock": 999983, + "istanbulBlock": 999983 + } + }, + "context": { + "number": "1555170", + "difficulty": "4642198", + "timestamp": "1590794112", + "gasLimit": "9289249", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf8658303fb0b843b9aca0083019ee48080915a600055600060006000f0505a6001550081a2a01a7deb3a16d967b766459ef486b00656c6581e5ad58968184a33701e27e0eb8aa07162ccdfe2018d64360a605310a62c399dd586c7282dd42a88c54f02f51d451f", + "tracerConfig": { + "convertParityErrors": true + }, + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0x19ee4", + "init": "0x5a600055600060006000f0505a60015500" + }, + "error": "Out of gas", + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 63, + "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", + "blockNumber": 1555170, + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" + }, + { + "type": "create", + "action": { + "from": "0x9c5cfe45b15eaff4ad617af4250189e26024a4f8", + "value": "0x0", + "gas": "0x3cb", + "init": "0x" + }, + "result": { + "gasUsed": "0x0", + "code": "0x", + "address": "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d" + }, + "traceAddress": [0], + "subtraces": 0, + "transactionPosition": 63, + "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", + "blockNumber": 1555170, + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json index e08e5cab4a..2fad32afe2 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json @@ -67,8 +67,7 @@ "transactionPosition": 18, "transactionHash": "0xc1c42a325856d513523aec464811923b2e2926f54015c7ba37877064cf889803", "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", - "time": "453.925µs" + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" }, { "type": "call", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json index 2606845a9a..4383af2d8a 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json @@ -67,8 +67,7 @@ "transactionPosition": 23, "transactionHash": "0xe267552ce8437a5bc7081385c99f912de5723ad34b958db215dbc41abd5f6c03", "blockNumber": 555462, - "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1", - "time": "1.147715ms" + "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1" }, { "type": "create", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json index cc70f8f71e..9fe9ba2b9d 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json @@ -67,8 +67,7 @@ "transactionPosition": 31, "transactionHash": "0x1257b698c5833c54ce786734087002b097275abc3877af082b5c2a538e894a41", "blockNumber": 1555161, - "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171", - "time": "889.048µs" + "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171" }, { "type": "create", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json index d906ab8fc5..f8ad3b5b0e 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json @@ -63,8 +63,7 @@ "transactionPosition": 63, "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", "blockNumber": 1555170, - "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e", - "time": "952.736µs" + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" }, { "type": "create", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json index 5631e5c907..41199e90e3 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json @@ -73,8 +73,7 @@ "transactionPosition": 26, "transactionHash": "0xcb1090fa85d2a3da8326b75333e92b3dca89963c895d9c981bfdaa64643135e4", "blockNumber": 839247, - "blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c", - "time": "182.267µs" + "blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c" }, { "action": { diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json index f6215a2b3f..544fff9dd3 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json @@ -80,8 +80,7 @@ "transactionPosition": 5, "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", "blockNumber": 553416, - "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282", - "time": "617.42µs" + "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282" }, { "type": "call", @@ -97,9 +96,7 @@ "gasUsed": "0x0", "output": "0x" }, - "traceAddress": [ - 0 - ], + "traceAddress": [0], "subtraces": 0, "transactionPosition": 5, "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", @@ -107,4 +104,4 @@ "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json index 6ef0cadec4..d7b4a22cf5 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json @@ -67,8 +67,7 @@ "transactionPosition": 14, "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", "blockNumber": 1555146, - "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e", - "time": "187.145µs" + "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e" }, { "action": { @@ -92,9 +91,7 @@ "balance": "0x0" }, "result": null, - "traceAddress": [ - 1 - ], + "traceAddress": [1], "subtraces": 0, "transactionPosition": 14, "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json index 283b42b8f6..6e020fe2b7 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json @@ -63,8 +63,7 @@ "transactionPosition": 16, "transactionHash": "0x384487e5ae8d2997aece8e28403d393cb9752425e6de358891bed981c5af1c05", "blockNumber": 1555285, - "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f", - "time": "665.278µs" + "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f" }, { "action": { diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go index 475f0e3344..e56d011139 100644 --- a/eth/tracers/native/call_flat.go +++ b/eth/tracers/native/call_flat.go @@ -55,6 +55,7 @@ var parityErrorMapping = map[string]string{ } var parityErrorMappingStartingWith = map[string]string{ + "out of gas:": "Out of gas", // convert OOG wrapped errors, eg `out of gas: not enough gas for reentrancy sentry` "invalid opcode:": "Bad instruction", "stack underflow": "Stack underflow", } @@ -371,6 +372,7 @@ func convertErrorToParity(call *flatCallFrame) { for gethError, parityError := range parityErrorMappingStartingWith { if strings.HasPrefix(call.Error, gethError) { call.Error = parityError + break } } } diff --git a/go.mod b/go.mod index fc469f3e93..9c68c95034 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,6 @@ require ( github.com/stretchr/testify v1.9.0 github.com/supranational/blst v0.3.13 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 golang.org/x/crypto v0.22.0 diff --git a/go.sum b/go.sum index 7b88051b5c..720acb1caa 100644 --- a/go.sum +++ b/go.sum @@ -499,8 +499,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 10d79c85ae..bea615bf44 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -29,8 +29,6 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" @@ -51,7 +49,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" - "github.com/tyler-smith/go-bip39" ) // estimateGasErrorRatio is the amount of overestimation eth_estimateGas is @@ -298,344 +295,6 @@ func (api *EthereumAccountAPI) Accounts() []common.Address { return api.am.Accounts() } -// PersonalAccountAPI provides an API to access accounts managed by this node. -// It offers methods to create, (un)lock en list accounts. Some methods accept -// passwords and are therefore considered private by default. -type PersonalAccountAPI struct { - am *accounts.Manager - nonceLock *AddrLocker - b Backend -} - -// NewPersonalAccountAPI creates a new PersonalAccountAPI. -func NewPersonalAccountAPI(b Backend, nonceLock *AddrLocker) *PersonalAccountAPI { - return &PersonalAccountAPI{ - am: b.AccountManager(), - nonceLock: nonceLock, - b: b, - } -} - -// ListAccounts will return a list of addresses for accounts this node manages. -func (api *PersonalAccountAPI) ListAccounts() []common.Address { - return api.am.Accounts() -} - -// rawWallet is a JSON representation of an accounts.Wallet interface, with its -// data contents extracted into plain fields. -type rawWallet struct { - URL string `json:"url"` - Status string `json:"status"` - Failure string `json:"failure,omitempty"` - Accounts []accounts.Account `json:"accounts,omitempty"` -} - -// ListWallets will return a list of wallets this node manages. -func (api *PersonalAccountAPI) ListWallets() []rawWallet { - wallets := make([]rawWallet, 0) // return [] instead of nil if empty - for _, wallet := range api.am.Wallets() { - status, failure := wallet.Status() - - raw := rawWallet{ - URL: wallet.URL().String(), - Status: status, - Accounts: wallet.Accounts(), - } - if failure != nil { - raw.Failure = failure.Error() - } - wallets = append(wallets, raw) - } - return wallets -} - -// OpenWallet initiates a hardware wallet opening procedure, establishing a USB -// connection and attempting to authenticate via the provided passphrase. Note, -// the method may return an extra challenge requiring a second open (e.g. the -// Trezor PIN matrix challenge). -func (api *PersonalAccountAPI) OpenWallet(url string, passphrase *string) error { - wallet, err := api.am.Wallet(url) - if err != nil { - return err - } - pass := "" - if passphrase != nil { - pass = *passphrase - } - return wallet.Open(pass) -} - -// DeriveAccount requests an HD wallet to derive a new account, optionally pinning -// it for later reuse. -func (api *PersonalAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) { - wallet, err := api.am.Wallet(url) - if err != nil { - return accounts.Account{}, err - } - derivPath, err := accounts.ParseDerivationPath(path) - if err != nil { - return accounts.Account{}, err - } - if pin == nil { - pin = new(bool) - } - return wallet.Derive(derivPath, *pin) -} - -// NewAccount will create a new account and returns the address for the new account. -func (api *PersonalAccountAPI) NewAccount(password string) (common.AddressEIP55, error) { - ks, err := fetchKeystore(api.am) - if err != nil { - return common.AddressEIP55{}, err - } - acc, err := ks.NewAccount(password) - if err == nil { - addrEIP55 := common.AddressEIP55(acc.Address) - log.Info("Your new key was generated", "address", addrEIP55.String()) - log.Warn("Please backup your key file!", "path", acc.URL.Path) - log.Warn("Please remember your password!") - return addrEIP55, nil - } - return common.AddressEIP55{}, err -} - -// fetchKeystore retrieves the encrypted keystore from the account manager. -func fetchKeystore(am *accounts.Manager) (*keystore.KeyStore, error) { - if ks := am.Backends(keystore.KeyStoreType); len(ks) > 0 { - return ks[0].(*keystore.KeyStore), nil - } - return nil, errors.New("local keystore not used") -} - -// ImportRawKey stores the given hex encoded ECDSA key into the key directory, -// encrypting it with the passphrase. -func (api *PersonalAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) { - key, err := crypto.HexToECDSA(privkey) - if err != nil { - return common.Address{}, err - } - ks, err := fetchKeystore(api.am) - if err != nil { - return common.Address{}, err - } - acc, err := ks.ImportECDSA(key, password) - return acc.Address, err -} - -// UnlockAccount will unlock the account associated with the given address with -// the given password for duration seconds. If duration is nil it will use a -// default of 300 seconds. It returns an indication if the account was unlocked. -func (api *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) { - // When the API is exposed by external RPC(http, ws etc), unless the user - // explicitly specifies to allow the insecure account unlocking, otherwise - // it is disabled. - if api.b.ExtRPCEnabled() && !api.b.AccountManager().Config().InsecureUnlockAllowed { - return false, errors.New("account unlock with HTTP access is forbidden") - } - - const max = uint64(time.Duration(gomath.MaxInt64) / time.Second) - var d time.Duration - if duration == nil { - d = 300 * time.Second - } else if *duration > max { - return false, errors.New("unlock duration too large") - } else { - d = time.Duration(*duration) * time.Second - } - ks, err := fetchKeystore(api.am) - if err != nil { - return false, err - } - err = ks.TimedUnlock(accounts.Account{Address: addr}, password, d) - if err != nil { - log.Warn("Failed account unlock attempt", "address", addr, "err", err) - } - return err == nil, err -} - -// LockAccount will lock the account associated with the given address when it's unlocked. -func (api *PersonalAccountAPI) LockAccount(addr common.Address) bool { - if ks, err := fetchKeystore(api.am); err == nil { - return ks.Lock(addr) == nil - } - return false -} - -// signTransaction sets defaults and signs the given transaction -// NOTE: the caller needs to ensure that the nonceLock is held, if applicable, -// and release it after the transaction has been submitted to the tx pool -func (api *PersonalAccountAPI) signTransaction(ctx context.Context, args *TransactionArgs, passwd string) (*types.Transaction, error) { - // Look up the wallet containing the requested signer - account := accounts.Account{Address: args.from()} - wallet, err := api.am.Find(account) - if err != nil { - return nil, err - } - // Set some sanity defaults and terminate on failure - if err := args.setDefaults(ctx, api.b, false); err != nil { - return nil, err - } - // Assemble the transaction and sign with the wallet - tx := args.ToTransaction(types.LegacyTxType) - - return wallet.SignTxWithPassphrase(account, passwd, tx, api.b.ChainConfig().ChainID) -} - -// SendTransaction will create a transaction from the given arguments and -// tries to sign it with the key associated with args.From. If the given -// passwd isn't able to decrypt the key it fails. -func (api *PersonalAccountAPI) SendTransaction(ctx context.Context, args TransactionArgs, passwd string) (common.Hash, error) { - if args.Nonce == nil { - // Hold the mutex around signing to prevent concurrent assignment of - // the same nonce to multiple accounts. - api.nonceLock.LockAddr(args.from()) - defer api.nonceLock.UnlockAddr(args.from()) - } - if args.IsEIP4844() { - return common.Hash{}, errBlobTxNotSupported - } - signed, err := api.signTransaction(ctx, &args, passwd) - if err != nil { - log.Warn("Failed transaction send attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err) - return common.Hash{}, err - } - return SubmitTransaction(ctx, api.b, signed) -} - -// SignTransaction will create a transaction from the given arguments and -// tries to sign it with the key associated with args.From. If the given passwd isn't -// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast -// to other nodes -func (api *PersonalAccountAPI) SignTransaction(ctx context.Context, args TransactionArgs, passwd string) (*SignTransactionResult, error) { - // No need to obtain the noncelock mutex, since we won't be sending this - // tx into the transaction pool, but right back to the user - if args.From == nil { - return nil, errors.New("sender not specified") - } - if args.Gas == nil { - return nil, errors.New("gas not specified") - } - if args.GasPrice == nil && (args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil) { - return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas") - } - if args.IsEIP4844() { - return nil, errBlobTxNotSupported - } - if args.Nonce == nil { - return nil, errors.New("nonce not specified") - } - // Before actually signing the transaction, ensure the transaction fee is reasonable. - tx := args.ToTransaction(types.LegacyTxType) - if err := checkTxFee(tx.GasPrice(), tx.Gas(), api.b.RPCTxFeeCap()); err != nil { - return nil, err - } - signed, err := api.signTransaction(ctx, &args, passwd) - if err != nil { - log.Warn("Failed transaction sign attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err) - return nil, err - } - data, err := signed.MarshalBinary() - if err != nil { - return nil, err - } - return &SignTransactionResult{data, signed}, nil -} - -// Sign calculates an Ethereum ECDSA signature for: -// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)) -// -// Note, the produced signature conforms to the secp256k1 curve R, S and V values, -// where the V value will be 27 or 28 for legacy reasons. -// -// The key used to calculate the signature is decrypted with the given password. -// -// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-sign -func (api *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { - // Look up the wallet containing the requested signer - account := accounts.Account{Address: addr} - - wallet, err := api.b.AccountManager().Find(account) - if err != nil { - return nil, err - } - // Assemble sign the data with the wallet - signature, err := wallet.SignTextWithPassphrase(account, passwd, data) - if err != nil { - log.Warn("Failed data sign attempt", "address", addr, "err", err) - return nil, err - } - signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper - return signature, nil -} - -// EcRecover returns the address for the account that was used to create the signature. -// Note, this function is compatible with eth_sign and personal_sign. As such it recovers -// the address of: -// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message}) -// addr = ecrecover(hash, signature) -// -// Note, the signature must conform to the secp256k1 curve R, S and V values, where -// the V value must be 27 or 28 for legacy reasons. -// -// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-ecrecover -func (api *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { - if len(sig) != crypto.SignatureLength { - return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) - } - if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 { - return common.Address{}, errors.New("invalid Ethereum signature (V is not 27 or 28)") - } - sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 - - rpk, err := crypto.SigToPub(accounts.TextHash(data), sig) - if err != nil { - return common.Address{}, err - } - return crypto.PubkeyToAddress(*rpk), nil -} - -// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key. -func (api *PersonalAccountAPI) InitializeWallet(ctx context.Context, url string) (string, error) { - wallet, err := api.am.Wallet(url) - if err != nil { - return "", err - } - - entropy, err := bip39.NewEntropy(256) - if err != nil { - return "", err - } - - mnemonic, err := bip39.NewMnemonic(entropy) - if err != nil { - return "", err - } - - seed := bip39.NewSeed(mnemonic, "") - - switch wallet := wallet.(type) { - case *scwallet.Wallet: - return mnemonic, wallet.Initialize(seed) - default: - return "", errors.New("specified wallet does not support initialization") - } -} - -// Unpair deletes a pairing between wallet and geth. -func (api *PersonalAccountAPI) Unpair(ctx context.Context, url string, pin string) error { - wallet, err := api.am.Wallet(url) - if err != nil { - return err - } - - switch wallet := wallet.(type) { - case *scwallet.Wallet: - return wallet.Unpair([]byte(pin)) - default: - return errors.New("specified wallet does not support pairing") - } -} - // BlockChainAPI provides an API to access Ethereum blockchain data. type BlockChainAPI struct { b Backend diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index ccc11472b7..82465ca7d7 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -118,9 +118,6 @@ func GetAPIs(apiBackend Backend) []rpc.API { }, { Namespace: "eth", Service: NewEthereumAccountAPI(apiBackend.AccountManager()), - }, { - Namespace: "personal", - Service: NewPersonalAccountAPI(apiBackend, nonceLock), }, } } diff --git a/internal/flags/flags.go b/internal/flags/flags.go index bf62c53adf..1f6be3d3d3 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -17,7 +17,6 @@ package flags import ( - "encoding" "errors" "flag" "fmt" @@ -122,119 +121,6 @@ func (f *DirectoryFlag) GetDefaultText() string { return f.GetValue() } -type TextMarshaler interface { - encoding.TextMarshaler - encoding.TextUnmarshaler -} - -// textMarshalerVal turns a TextMarshaler into a flag.Value -type textMarshalerVal struct { - v TextMarshaler -} - -func (v textMarshalerVal) String() string { - if v.v == nil { - return "" - } - text, _ := v.v.MarshalText() - return string(text) -} - -func (v textMarshalerVal) Set(s string) error { - return v.v.UnmarshalText([]byte(s)) -} - -var ( - _ cli.Flag = (*TextMarshalerFlag)(nil) - _ cli.RequiredFlag = (*TextMarshalerFlag)(nil) - _ cli.VisibleFlag = (*TextMarshalerFlag)(nil) - _ cli.DocGenerationFlag = (*TextMarshalerFlag)(nil) - _ cli.CategorizableFlag = (*TextMarshalerFlag)(nil) -) - -// TextMarshalerFlag wraps a TextMarshaler value. -type TextMarshalerFlag struct { - Name string - - Category string - DefaultText string - Usage string - - Required bool - Hidden bool - HasBeenSet bool - - Value TextMarshaler - - Aliases []string - EnvVars []string -} - -// For cli.Flag: - -func (f *TextMarshalerFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } -func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet } -func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) } - -func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error { - for _, envVar := range f.EnvVars { - envVar = strings.TrimSpace(envVar) - if value, found := syscall.Getenv(envVar); found { - if err := f.Value.UnmarshalText([]byte(value)); err != nil { - return fmt.Errorf("could not parse %q from environment variable %q for flag %s: %s", value, envVar, f.Name, err) - } - f.HasBeenSet = true - break - } - } - eachName(f, func(name string) { - set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) - }) - return nil -} - -// For cli.RequiredFlag: - -func (f *TextMarshalerFlag) IsRequired() bool { return f.Required } - -// For cli.VisibleFlag: - -func (f *TextMarshalerFlag) IsVisible() bool { return !f.Hidden } - -// For cli.CategorizableFlag: - -func (f *TextMarshalerFlag) GetCategory() string { return f.Category } - -// For cli.DocGenerationFlag: - -func (f *TextMarshalerFlag) TakesValue() bool { return true } -func (f *TextMarshalerFlag) GetUsage() string { return f.Usage } -func (f *TextMarshalerFlag) GetEnvVars() []string { return f.EnvVars } - -func (f *TextMarshalerFlag) GetValue() string { - t, err := f.Value.MarshalText() - if err != nil { - return "(ERR: " + err.Error() + ")" - } - return string(t) -} - -func (f *TextMarshalerFlag) GetDefaultText() string { - if f.DefaultText != "" { - return f.DefaultText - } - return f.GetValue() -} - -// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set. -func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { - val := ctx.Generic(name) - if val == nil { - return nil - } - return val.(textMarshalerVal).v -} - var ( _ cli.Flag = (*BigFlag)(nil) _ cli.RequiredFlag = (*BigFlag)(nil) diff --git a/internal/flags/helpers.go b/internal/flags/helpers.go index 32be3d11a7..fd706869f1 100644 --- a/internal/flags/helpers.go +++ b/internal/flags/helpers.go @@ -48,15 +48,6 @@ func NewApp(usage string) *cli.App { return app } -// Merge merges the given flag slices. -func Merge(groups ...[]cli.Flag) []cli.Flag { - var ret []cli.Flag - for _, group := range groups { - ret = append(ret, group...) - } - return ret -} - var migrationApplied = map[*cli.Command]struct{}{} // MigrateGlobalFlags makes all global flag values available in the @@ -265,9 +256,6 @@ func AutoEnvVars(flags []cli.Flag, prefix string) { case *BigFlag: flag.EnvVars = append(flag.EnvVars, envvar) - case *TextMarshalerFlag: - flag.EnvVars = append(flag.EnvVars, envvar) - case *DirectoryFlag: flag.EnvVars = append(flag.EnvVars, envvar) } diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 927ebc2ef0..0c346bbf79 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -18,16 +18,15 @@ package web3ext var Modules = map[string]string{ - "admin": AdminJs, - "clique": CliqueJs, - "debug": DebugJs, - "eth": EthJs, - "miner": MinerJs, - "net": NetJs, - "personal": PersonalJs, - "rpc": RpcJs, - "txpool": TxpoolJs, - "dev": DevJs, + "admin": AdminJs, + "clique": CliqueJs, + "debug": DebugJs, + "eth": EthJs, + "miner": MinerJs, + "net": NetJs, + "rpc": RpcJs, + "txpool": TxpoolJs, + "dev": DevJs, } const CliqueJs = ` @@ -658,62 +657,6 @@ web3._extend({ }); ` -const PersonalJs = ` -web3._extend({ - property: 'personal', - methods: [ - new web3._extend.Method({ - name: 'importRawKey', - call: 'personal_importRawKey', - params: 2 - }), - new web3._extend.Method({ - name: 'sign', - call: 'personal_sign', - params: 3, - inputFormatter: [null, web3._extend.formatters.inputAddressFormatter, null] - }), - new web3._extend.Method({ - name: 'ecRecover', - call: 'personal_ecRecover', - params: 2 - }), - new web3._extend.Method({ - name: 'openWallet', - call: 'personal_openWallet', - params: 2 - }), - new web3._extend.Method({ - name: 'deriveAccount', - call: 'personal_deriveAccount', - params: 3 - }), - new web3._extend.Method({ - name: 'signTransaction', - call: 'personal_signTransaction', - params: 2, - inputFormatter: [web3._extend.formatters.inputTransactionFormatter, null] - }), - new web3._extend.Method({ - name: 'unpair', - call: 'personal_unpair', - params: 2 - }), - new web3._extend.Method({ - name: 'initializeWallet', - call: 'personal_initializeWallet', - params: 1 - }) - ], - properties: [ - new web3._extend.Property({ - name: 'listWallets', - getter: 'personal_listWallets' - }), - ] -}) -` - const RpcJs = ` web3._extend({ property: 'rpc', diff --git a/node/node.go b/node/node.go index e23425dfbd..92c0c35607 100644 --- a/node/node.go +++ b/node/node.go @@ -375,25 +375,13 @@ func (n *Node) obtainJWTSecret(cliParam string) ([]byte, error) { // startup. It's not meant to be called at any time afterwards as it makes certain // assumptions about the state of the node. func (n *Node) startRPC() error { - // Filter out personal api - var apis []rpc.API - for _, api := range n.rpcAPIs { - if api.Namespace == "personal" { - if n.config.EnablePersonal { - log.Warn("Deprecated personal namespace activated") - } else { - continue - } - } - apis = append(apis, api) - } - if err := n.startInProc(apis); err != nil { + if err := n.startInProc(n.rpcAPIs); err != nil { return err } // Configure IPC. if n.ipc.endpoint != "" { - if err := n.ipc.start(apis); err != nil { + if err := n.ipc.start(n.rpcAPIs); err != nil { return err } } diff --git a/signer/core/signed_data.go b/signer/core/signed_data.go index f8b3c9d86d..c62b513145 100644 --- a/signer/core/signed_data.go +++ b/signer/core/signed_data.go @@ -294,7 +294,7 @@ func typedDataRequest(data any) (*SignDataRequest, error) { func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) { // Returns the address for the Account that was used to create the signature. // - // Note, this function is compatible with eth_sign and personal_sign. As such it recovers + // Note, this function is compatible with eth_sign. As such it recovers // the address of: // hash = keccak256("\x19Ethereum Signed Message:\n${message length}${message}") // addr = ecrecover(hash, signature) diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go index 4efc749b6f..74ea6f52a7 100644 --- a/tests/fuzzers/bls12381/bls12381_fuzz.go +++ b/tests/fuzzers/bls12381/bls12381_fuzz.go @@ -257,8 +257,12 @@ func fuzzCrossG1MultiExp(data []byte) int { cp.MultiExp(gnarkPoints, gnarkScalars, ecc.MultiExpConfig{}) // compare result - if !(bytes.Equal(cp.Marshal(), g1.ToBytes(&kp))) { - panic("G1 multi exponentiation mismatch gnark / geth ") + gnarkRes := cp.Marshal() + gethRes := g1.ToBytes(&kp) + if !bytes.Equal(gnarkRes, gethRes) { + msg := fmt.Sprintf("G1 multi exponentiation mismatch gnark/geth.\ngnark: %x\ngeth: %x\ninput: %x\n ", + gnarkRes, gethRes, data) + panic(msg) } return 1 @@ -283,15 +287,18 @@ func getG1Points(input io.Reader) (*bls12381.PointG1, *gnark.G1Affine, *blst.P1A if err != nil { panic(fmt.Sprintf("Could not marshal gnark.G1 -> geth.G1: %v", err)) } - if !bytes.Equal(g1.ToBytes(kp), cpBytes) { - panic("bytes(gnark.G1) != bytes(geth.G1)") + + gnarkRes := g1.ToBytes(kp) + if !bytes.Equal(gnarkRes, cpBytes) { + panic(fmt.Sprintf("bytes(gnark.G1) != bytes(geth.G1)\ngnark.G1: %x\ngeth.G1: %x\n", gnarkRes, cpBytes)) } // marshal gnark point -> blst point scalar := new(blst.Scalar).FromBEndian(common.LeftPadBytes(s.Bytes(), 32)) p1 := new(blst.P1Affine).From(scalar) - if !bytes.Equal(p1.Serialize(), cpBytes) { - panic("bytes(blst.G1) != bytes(geth.G1)") + blstRes := p1.Serialize() + if !bytes.Equal(blstRes, cpBytes) { + panic(fmt.Sprintf("bytes(blst.G1) != bytes(geth.G1)\nblst.G1: %x\ngeth.G1: %x\n", blstRes, cpBytes)) } return kp, cp, p1, nil @@ -316,8 +323,10 @@ func getG2Points(input io.Reader) (*bls12381.PointG2, *gnark.G2Affine, *blst.P2A if err != nil { panic(fmt.Sprintf("Could not marshal gnark.G2 -> geth.G2: %v", err)) } - if !bytes.Equal(g2.ToBytes(kp), cpBytes) { - panic("bytes(gnark.G2) != bytes(geth.G2)") + + gnarkRes := g2.ToBytes(kp) + if !bytes.Equal(gnarkRes, cpBytes) { + panic(fmt.Sprintf("bytes(gnark.G2) != bytes(geth.G2)\ngnark.G2: %x\ngeth.G2: %x\n", gnarkRes, cpBytes)) } // marshal gnark point -> blst point