From 6a90d328856a8f81340cf7c545a3c72b9f8695a7 Mon Sep 17 00:00:00 2001 From: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Date: Tue, 14 Feb 2023 20:52:32 -0500 Subject: [PATCH 01/25] chore: add v1.20.0-rc1 changelog (#10273) * add v1.20.0-rc1 changelog Co-authored-by: Aayush Rajasekaran --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd450afd2..b77b86ee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,55 @@ # Lotus changelog +# 1.20.0-rc1 / 2023-02-14 + +This is the first release candidate for the upcoming MANDATORY 1.20.0 release of Lotus. This release will deliver the Hygge network upgrade, introducing Filecoin network version 18. The centerpiece of the upgrade is the introduction of the [Filecoin Virtual Machine (FVM)’s Milestone 2.1](https://fvm.filecoin.io/), which will allow for EVM-compatible contracts to be deployed on the Filecoin network. This upgrade delivers user-programmablity to the Filecoin network for the first time! + +Note that this release candidate does NOT set the epoch at which mainnet will upgrade; that detail will be finalized in the 1.20.0 release. + +The Hygge upgrade introduces the following Filecoin Improvement Proposals (FIPs), delivered in FVM3 (see FVM [v3.0.0-rc.1](https://github.com/filecoin-project/ref-fvm/pull/1664)) and builtin-actors v10 (see actors [v1.10.0-rc.1](https://github.com/filecoin-project/builtin-actors/releases/tag/v10.0.0-rc.1)): + +- [FIP-0048](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0048.md): f4 Address Class +- [FIP-0049](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0049.md): Actor events +- [FIP-0050](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0050.md): API between user-programmed actors and built-in actors +- [FIP-0054](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0054.md): Filecoin EVM runtime (FEVM) +- [FIP-0055](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0055.md): Supporting Ethereum Accounts, Addresses, and Transactions +- [FIP-0057](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0057.md): Update gas charging schedule and system limits for FEVM + +## Filecoin Ethereum Virtual Machine (FEVM) + +The Filecoin Ethereum Virtual Machine (FEVM) is built on top of the WASM-based execution environment introduced in the Skyr v16 upgrade. The chief feature introduced is the ability for anyone participating in the Filecoin network to deploy their own EVM-compatible contracts onto the blockchain, and invoke them as appropriate. + +## New Built-in Actors + +The FEVM is principally delivered through the introduction of **the new [EVM actor](https://github.com/filecoin-project/builtin-actors/tree/master/actors/evm)**. This actor “represents” smart contracts on the Filecoin network, and includes an interpreter that implements all EVM opcodes as their Filecoin equivalents, and translates state I/O operations to be compatible with Filecoin’s IPLD-based data model. For more on the EVM actors, please see [FIP-0054](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0054.md). + +The creation of EVM actors is managed by **the new** [Ethereum Address Manager actor (EAM)](https://github.com/filecoin-project/builtin-actors/tree/master/actors/eam), a singleton that is invoked in order to deploy EVM actors. In order to make usage of the FEVM as seamless as possible for users familiar with the Ethereum ecosystem, this upgrades also introduces **a dedicated actor to serve as “[Ethereum Accounts](https://github.com/filecoin-project/builtin-actors/tree/master/actors/ethaccount)”**. This actor exists to allow for secp keys to be used in the Ethereum addressing scheme. **The last new built-in actor introduced is [the Placeholder actor](https://github.com/filecoin-project/builtin-actors/tree/master/actors/placeholder)**, a thin “shell” of an actor that can transform into either EVM or EthAccount actors. For more on the EAM, EthAccount, and Placeholder actors, please see [FIP-0055](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0055.md). + +## Calibration nv18 Hygge Upgrade + +This release candidate sets the calibration-net nv18 Hygge upgrade at epoch 322354, 22023-02-21T16:30:00Z. The bundle the network will be using is [v10.0.0 actors](https://github.com/filecoin-project/builtin-actors/releases/tag/v10.0.0-rc.1) +(located at `build/actors/v10.tar.zst`) upon/post migration, manifest CID `bafy2bzaced25ta3j6ygs34roprilbtb3f6mxifyfnm7z7ndquaruxzdq3y7lo`. + +## Node Operators + +FVM has been running in lotus since v1.16.0 and up, and the new FEVM does not increase any node hardware spec requirement. + +With FEVM on Filecoin, we aim to provide full compatibility with the existing EVM ecosystem and its tooling out of box and thus, lotus now provides a full set of [Ethereum-styled APIs](https://github.com/filecoin-project/lotus/blob/release/v1.20.0/node/impl/full/eth.go) for developers and token holders to interact with the Filecoin network as well. + +**Enable Ethereum JSON RPC API** + +Note that Ethereum APIs are only supported in the lotus v1 API, meaning that any node operator who wants to enable Eth API services must be using the v1 API, instead of the v0 API. To enable Eth RPC, simply set `EnableEthRPC` to `true` in your node config.toml file; or set env var `LOTUS_FEVM_ENABLEETHRPC` to `1` before starting your lotus node. + +**Eth tx hash and Filecoin message CID** + +Most of the Eth APIs take Eth accounts and tx has as an input, and they start with `0x` , and that is what Ethereum tooling support. However, in Filecoin, we have Filecoin account formats where things start with `f` (`f410` specifically for eth accounts on Filecoin) and the messages are in the format of CIDs. To enable a smooth developer experience, Lotus internally converts between Ethereum address and Filecoin account address as needed. In addition, lotus also keeps a Eth tx hash <> Filecoin message CID map and stores them in a SQLite database as node sees a FEVM messages. The database is initiated and the maps are populated automatically in `~//sqlite/txhash.db` for any node that as Eth RPC enabled. Node operators can configure how many historical mappings they wanna store by configuring `EthTxHashMappingLifetimeDays` . + +**Events*** + +[FIP-0049 introduces actor events](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0049.md) that can be emitted and externally observable during message execution. An `events.db` is created automatically under `~//sqlite` to store these events if the node has Eth RPC enabled. Node operators can configure the events support base on their needs by configuration `Events` configurations. + +Note: All three features are new and we welcome user feedbacks, create an issue if you have any enhancements that you’d like to see! + # 1.19.0 / 2022-12-07 This is an optional feature release of Lotus. This feature release includes the SplitStore beta, the experimental Lotus node cluster feature, as well as numerous enhancments and bugfixes. From 4f259d8644b458793fda8c9dee8d3fa695d43b0a Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 15 Feb 2023 11:09:24 -0500 Subject: [PATCH 02/25] Revert "Standardize path variable" This reverts commit a9c1caa1886fbb7c576c46d4ade90f5c1561f6a2. --- cmd/lotus-shed/balances.go | 10 ++++------ cmd/lotus-shed/datastore.go | 12 +----------- cmd/lotus-shed/deal-label.go | 5 ++--- cmd/lotus-shed/diff.go | 5 ++--- cmd/lotus-shed/export-car.go | 5 ++--- cmd/lotus-shed/export.go | 10 ++++------ cmd/lotus-shed/fip-0036.go | 11 ++++++++--- cmd/lotus-shed/gas-estimation.go | 10 ++++------ cmd/lotus-shed/import-car.go | 14 -------------- cmd/lotus-shed/invariants.go | 5 ++--- cmd/lotus-shed/keyinfo.go | 11 +++-------- cmd/lotus-shed/main.go | 14 ++++++++++++++ cmd/lotus-shed/market.go | 10 ++++------ cmd/lotus-shed/migrations.go | 5 ++--- cmd/lotus-shed/miner-peerid.go | 8 +++----- cmd/lotus-shed/miner-types.go | 8 +++----- cmd/lotus-shed/msig.go | 5 ++--- cmd/lotus-shed/nonce-fix.go | 6 ++++++ cmd/lotus-shed/pruning.go | 5 ++--- cmd/lotus-shed/splitstore.go | 10 ++++------ cmd/lotus-shed/terminations.go | 5 ++--- 21 files changed, 74 insertions(+), 100 deletions(-) diff --git a/cmd/lotus-shed/balances.go b/cmd/lotus-shed/balances.go index c647f3b8e..9ce4faf72 100644 --- a/cmd/lotus-shed/balances.go +++ b/cmd/lotus-shed/balances.go @@ -454,9 +454,8 @@ var chainBalanceStateCmd = &cli.Command{ Description: "Produces a csv file of all account balances from a given stateroot", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.BoolFlag{ Name: "miner-info", @@ -678,9 +677,8 @@ var chainPledgeCmd = &cli.Command{ Description: "Calculate sector pledge numbers", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, ArgsUsage: "[stateroot epoch]", diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index d6b932954..5614e34f6 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -41,11 +41,6 @@ var datastoreListCmd = &cli.Command{ Name: "list", Description: "list datastore keys", Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, - }, &cli.StringFlag{ Name: "repo-type", Usage: "node type (FullNode, StorageMiner, Worker, Wallet)", @@ -115,11 +110,6 @@ var datastoreGetCmd = &cli.Command{ Name: "get", Description: "list datastore keys", Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, - }, &cli.StringFlag{ Name: "repo-type", Usage: "node type (FullNode, StorageMiner, Worker, Wallet)", @@ -133,7 +123,7 @@ var datastoreGetCmd = &cli.Command{ }, ArgsUsage: "[namespace key]", Action: func(cctx *cli.Context) error { - _ = logging.SetLogLevel("badger", "ERROR") + logging.SetLogLevel("badger", "ERROR") // nolint:errcheck r, err := repo.NewFS(cctx.String("repo")) if err != nil { diff --git a/cmd/lotus-shed/deal-label.go b/cmd/lotus-shed/deal-label.go index 2baa751a9..417d13701 100644 --- a/cmd/lotus-shed/deal-label.go +++ b/cmd/lotus-shed/deal-label.go @@ -24,9 +24,8 @@ var dealLabelCmd = &cli.Command{ Usage: "Scrape state to report on how many deals have non UTF-8 labels", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/diff.go b/cmd/lotus-shed/diff.go index e29d9ca6d..981dc850c 100644 --- a/cmd/lotus-shed/diff.go +++ b/cmd/lotus-shed/diff.go @@ -33,9 +33,8 @@ var diffMinerStates = &cli.Command{ ArgsUsage: " ", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/export-car.go b/cmd/lotus-shed/export-car.go index e32dbb2cf..5cb4737ea 100644 --- a/cmd/lotus-shed/export-car.go +++ b/cmd/lotus-shed/export-car.go @@ -35,9 +35,8 @@ var exportCarCmd = &cli.Command{ Description: "Export a car from repo", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, ArgsUsage: "[outfile] [root cid]", diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index ab6d88698..459de3383 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -42,9 +42,8 @@ var exportChainCmd = &cli.Command{ Description: "Export chain from repo (requires node to be offline)", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.StringFlag{ Name: "tipset", @@ -147,9 +146,8 @@ var exportRawCmd = &cli.Command{ Description: "Export raw blocks from repo (requires node to be offline)", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.StringFlag{ Name: "car-size", diff --git a/cmd/lotus-shed/fip-0036.go b/cmd/lotus-shed/fip-0036.go index 1929eb4dd..485302b9b 100644 --- a/cmd/lotus-shed/fip-0036.go +++ b/cmd/lotus-shed/fip-0036.go @@ -58,6 +58,12 @@ var fip36PollCmd = &cli.Command{ Name: "fip36poll", Usage: "Process the FIP0036 FilPoll result", ArgsUsage: "[state root, votes]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, Subcommands: []*cli.Command{ finalResultCmd, }, @@ -69,9 +75,8 @@ var finalResultCmd = &cli.Command{ ArgsUsage: "[state root] [height] [votes json]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, diff --git a/cmd/lotus-shed/gas-estimation.go b/cmd/lotus-shed/gas-estimation.go index 669c1c345..cf56ea03d 100644 --- a/cmd/lotus-shed/gas-estimation.go +++ b/cmd/lotus-shed/gas-estimation.go @@ -42,9 +42,8 @@ var gasTraceCmd = &cli.Command{ ArgsUsage: "[migratedStateRootCid networkVersion messageCid]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { @@ -147,9 +146,8 @@ var replayOfflineCmd = &cli.Command{ ArgsUsage: "[messageCid]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.Int64Flag{ Name: "lookback-limit", diff --git a/cmd/lotus-shed/import-car.go b/cmd/lotus-shed/import-car.go index 6bba1d980..973e7b31b 100644 --- a/cmd/lotus-shed/import-car.go +++ b/cmd/lotus-shed/import-car.go @@ -19,13 +19,6 @@ import ( var importCarCmd = &cli.Command{ Name: "import-car", Description: "Import a car file into node chain blockstore", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, - }, - }, Action: func(cctx *cli.Context) error { r, err := repo.NewFS(cctx.String("repo")) if err != nil { @@ -103,13 +96,6 @@ var importCarCmd = &cli.Command{ var importObjectCmd = &cli.Command{ Name: "import-obj", Usage: "import a raw ipld object into your datastore", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, - }, - }, Action: func(cctx *cli.Context) error { r, err := repo.NewFS(cctx.String("repo")) if err != nil { diff --git a/cmd/lotus-shed/invariants.go b/cmd/lotus-shed/invariants.go index 953674ed0..e48f301c4 100644 --- a/cmd/lotus-shed/invariants.go +++ b/cmd/lotus-shed/invariants.go @@ -35,9 +35,8 @@ var invariantsCmd = &cli.Command{ ArgsUsage: "[StateRootCid, height]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/keyinfo.go b/cmd/lotus-shed/keyinfo.go index 1c322f7d6..38f5ee6fe 100644 --- a/cmd/lotus-shed/keyinfo.go +++ b/cmd/lotus-shed/keyinfo.go @@ -146,14 +146,9 @@ var keyinfoImportCmd = &cli.Command{ Examples env LOTUS_PATH=/var/lib/lotus lotus-shed keyinfo import libp2p-host.keyinfo`, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, - }, - }, Action: func(cctx *cli.Context) error { + flagRepo := cctx.String("repo") + var input io.Reader if cctx.NArg() == 0 { input = os.Stdin @@ -182,7 +177,7 @@ var keyinfoImportCmd = &cli.Command{ return err } - fsrepo, err := repo.NewFS(cctx.String("repo")) + fsrepo, err := repo.NewFS(flagRepo) if err != nil { return err } diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index c0d0043f1..28a59f14d 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "os" logging "github.com/ipfs/go-log/v2" @@ -88,6 +89,19 @@ func main() { Version: build.UserVersion(), Commands: local, Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + EnvVars: []string{"LOTUS_PATH"}, + Hidden: true, + Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME + }, + &cli.StringFlag{ + Name: "miner-repo", + Aliases: []string{"storagerepo"}, + EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"}, + Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME + Usage: fmt.Sprintf("Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON"), + }, &cli.StringFlag{ Name: "log-level", Value: "info", diff --git a/cmd/lotus-shed/market.go b/cmd/lotus-shed/market.go index 6d86c90b9..0c5e7c81d 100644 --- a/cmd/lotus-shed/market.go +++ b/cmd/lotus-shed/market.go @@ -124,9 +124,8 @@ var marketExportDatastoreCmd = &cli.Command{ Description: "export markets datastore key/values to a file", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Usage: "path to the repo", }, &cli.StringFlag{ Name: "backup-dir", @@ -242,9 +241,8 @@ var marketImportDatastoreCmd = &cli.Command{ Description: "import markets datastore key/values from a backup file", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Usage: "path to the repo", }, &cli.StringFlag{ Name: "backup-path", diff --git a/cmd/lotus-shed/migrations.go b/cmd/lotus-shed/migrations.go index e0336283a..a7e0ee34f 100644 --- a/cmd/lotus-shed/migrations.go +++ b/cmd/lotus-shed/migrations.go @@ -54,9 +54,8 @@ var migrationsCmd = &cli.Command{ ArgsUsage: "[new network version, block to look back from]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.BoolFlag{ Name: "skip-pre-migration", diff --git a/cmd/lotus-shed/miner-peerid.go b/cmd/lotus-shed/miner-peerid.go index fdf8dae8d..e43063797 100644 --- a/cmd/lotus-shed/miner-peerid.go +++ b/cmd/lotus-shed/miner-peerid.go @@ -26,12 +26,10 @@ import ( var minerPeeridCmd = &cli.Command{ Name: "miner-peerid", - Usage: "Scrape state to find a miner based on peerid", - Flags: []cli.Flag{ + Usage: "Scrape state to find a miner based on peerid", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/miner-types.go b/cmd/lotus-shed/miner-types.go index 15e5db265..822d037aa 100644 --- a/cmd/lotus-shed/miner-types.go +++ b/cmd/lotus-shed/miner-types.go @@ -28,12 +28,10 @@ import ( var minerTypesCmd = &cli.Command{ Name: "miner-types", - Usage: "Scrape state to report on how many miners of each WindowPoStProofType exist", - Flags: []cli.Flag{ + Usage: "Scrape state to report on how many miners of each WindowPoStProofType exist", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/msig.go b/cmd/lotus-shed/msig.go index 96ba91219..ccc932c93 100644 --- a/cmd/lotus-shed/msig.go +++ b/cmd/lotus-shed/msig.go @@ -43,9 +43,8 @@ var multisigGetAllCmd = &cli.Command{ ArgsUsage: "[state root]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/nonce-fix.go b/cmd/lotus-shed/nonce-fix.go index d68f22e0b..d69c8a48d 100644 --- a/cmd/lotus-shed/nonce-fix.go +++ b/cmd/lotus-shed/nonce-fix.go @@ -17,6 +17,12 @@ import ( var noncefix = &cli.Command{ Name: "noncefix", Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + EnvVars: []string{"LOTUS_PATH"}, + Hidden: true, + Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME + }, &cli.Uint64Flag{ Name: "start", }, diff --git a/cmd/lotus-shed/pruning.go b/cmd/lotus-shed/pruning.go index 1b6553057..275f3bc0a 100644 --- a/cmd/lotus-shed/pruning.go +++ b/cmd/lotus-shed/pruning.go @@ -86,9 +86,8 @@ var stateTreePruneCmd = &cli.Command{ Description: "Deletes old state root data from local chainstore", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.Int64Flag{ Name: "keep-from-lookback", diff --git a/cmd/lotus-shed/splitstore.go b/cmd/lotus-shed/splitstore.go index 348f2e36d..e8c45a0c5 100644 --- a/cmd/lotus-shed/splitstore.go +++ b/cmd/lotus-shed/splitstore.go @@ -39,9 +39,8 @@ var splitstoreRollbackCmd = &cli.Command{ Description: "rollbacks a splitstore installation", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.BoolFlag{ Name: "gc-coldstore", @@ -130,9 +129,8 @@ var splitstoreClearCmd = &cli.Command{ Description: "clears a splitstore installation for restart from snapshot", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, &cli.BoolFlag{ Name: "keys-only", diff --git a/cmd/lotus-shed/terminations.go b/cmd/lotus-shed/terminations.go index c9e3d26bb..c5f35995a 100644 --- a/cmd/lotus-shed/terminations.go +++ b/cmd/lotus-shed/terminations.go @@ -33,9 +33,8 @@ var terminationsCmd = &cli.Command{ ArgsUsage: "[block to look back from] [lookback period (epochs)]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - EnvVars: []string{"LOTUS_PATH"}, + Name: "repo", + Value: "~/.lotus", }, }, Action: func(cctx *cli.Context) error { From 1d0a524b885c285c7c243e2963d890feeeeeecef Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 15 Feb 2023 14:17:00 -0500 Subject: [PATCH 03/25] feat: EthAPI: Add EthAddressToFilecoinAddress --- .circleci/config.yml | 5 +++ api/api_full.go | 2 + api/mocks/mock_full.go | 15 +++++++ api/proxy_gen.go | 13 ++++++ build/openrpc/full.json.gz | Bin 33131 -> 33201 bytes build/openrpc/gateway.json.gz | Bin 8485 -> 8483 bytes build/openrpc/miner.json.gz | Bin 16043 -> 16046 bytes build/openrpc/worker.json.gz | Bin 5224 -> 5223 bytes documentation/en/api-v1-unstable-methods.md | 16 +++++++ gateway/node.go | 1 + itests/eth_api_test.go | 47 ++++++++++++++++++++ node/impl/full/dummy.go | 5 +++ node/impl/full/eth.go | 4 ++ 13 files changed, 108 insertions(+) create mode 100644 itests/eth_api_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 2230bfb00..2391a4e92 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -618,6 +618,11 @@ workflows: suite: itest-eth_account_abstraction target: "./itests/eth_account_abstraction_test.go" + - test: + name: test-itest-eth_api + suite: itest-eth_api + target: "./itests/eth_api_test.go" + - test: name: test-itest-eth_balance suite: itest-eth_balance diff --git a/api/api_full.go b/api/api_full.go index 3bd875dc7..c81bb2d6b 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -769,6 +769,8 @@ type FullNode interface { // // EthAccounts will always return [] since we don't expect Lotus to manage private keys EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) //perm:read + // EthAddressToFilecoinAddress converts an EthAddress into an f410 Filecoin Address + EthAddressToFilecoinAddress(ctx context.Context, ethAddress ethtypes.EthAddress) (address.Address, error) //perm:read // EthBlockNumber returns the height of the latest (heaviest) TipSet EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) //perm:read // EthGetBlockTransactionCountByNumber returns the number of messages in the TipSet diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 6e4873715..a5c65f07a 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -953,6 +953,21 @@ func (mr *MockFullNodeMockRecorder) EthAccounts(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthAccounts", reflect.TypeOf((*MockFullNode)(nil).EthAccounts), arg0) } +// EthAddressToFilecoinAddress mocks base method. +func (m *MockFullNode) EthAddressToFilecoinAddress(arg0 context.Context, arg1 ethtypes.EthAddress) (address.Address, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EthAddressToFilecoinAddress", arg0, arg1) + ret0, _ := ret[0].(address.Address) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EthAddressToFilecoinAddress indicates an expected call of EthAddressToFilecoinAddress. +func (mr *MockFullNodeMockRecorder) EthAddressToFilecoinAddress(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthAddressToFilecoinAddress", reflect.TypeOf((*MockFullNode)(nil).EthAddressToFilecoinAddress), arg0, arg1) +} + // EthBlockNumber mocks base method. func (m *MockFullNode) EthBlockNumber(arg0 context.Context) (ethtypes.EthUint64, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 2cfaa099a..f04bea2a9 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -244,6 +244,8 @@ type FullNodeMethods struct { EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"` + EthAddressToFilecoinAddress func(p0 context.Context, p1 ethtypes.EthAddress) (address.Address, error) `perm:"read"` + EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `perm:"read"` @@ -2007,6 +2009,17 @@ func (s *FullNodeStub) EthAccounts(p0 context.Context) ([]ethtypes.EthAddress, e return *new([]ethtypes.EthAddress), ErrNotSupported } +func (s *FullNodeStruct) EthAddressToFilecoinAddress(p0 context.Context, p1 ethtypes.EthAddress) (address.Address, error) { + if s.Internal.EthAddressToFilecoinAddress == nil { + return *new(address.Address), ErrNotSupported + } + return s.Internal.EthAddressToFilecoinAddress(p0, p1) +} + +func (s *FullNodeStub) EthAddressToFilecoinAddress(p0 context.Context, p1 ethtypes.EthAddress) (address.Address, error) { + return *new(address.Address), ErrNotSupported +} + func (s *FullNodeStruct) EthBlockNumber(p0 context.Context) (ethtypes.EthUint64, error) { if s.Internal.EthBlockNumber == nil { return *new(ethtypes.EthUint64), ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index dabb581c2497e0d343d2e6e60a77f16f33a092da..06e43869da8a7952e093c3dccc9c1bdc726af3e1 100644 GIT binary patch literal 33201 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 literal 33131 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

tF#jj(7HkY`vS*RWis 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

h-{i7Th)aBuxC+j*` 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 C&Dd7} diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 545fe83cbc154490e171f37c40506cb431851e83..906c69d7a9d619d4dc889a9f7a8d7a70ca4349a5 100644 GIT binary patch delta 13501 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 delta 13519 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 JH=Fev0|3FwRu=#O diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index e5db590da6187c9a79b127d23aea535a8fc93df9..1b44c69bdec0a76c795eda80e5c2e3cb41e7d992 100644 GIT binary patch delta 4083 zcmVL|$7QdJrbvQ_CHh#GTFMe_6TvgbU+_8Il=Ajsb|1Z-O)e1D4! zQuu!1`-ShX;`@inINSGsK?J#wh7Rvve`xg&*IrcEmCr4QcX`pkX7>!6oam5SeN#YD z)ZXGiEP)%Z6*meO4@14)zgFlQ38CQJM1}|(^#yv8(wXn{545inZlxuv{WtebA+~SmhIlE)YFHbX6%v^uI7M z?Z*rIidKa3T>(WA)0b$5nT*I}e<^)G>*F|k_mOD>18zqHH<5^*3)`cCs+`TCWg#*P zwh1v|<@Wu&th7r=OnX6)=f&v2POwYgsLK$8U7k{mAX!BvZV>Ch&CC7Wn=;e^6GIb|RkM z=<1y;g?j}-NPGNqG7e84DYkBuN+Z#>&&mKxtPcyBSSrjeJ|1N%+jM3+x-JW&4*$|F zz1xZjZO)ohtp;Q2XL^D-D3seC{`C0agVdT2Ad8u35_SqWX-3jA>~xC*zUl2yfq54H zuTLw=l1l$WEaiW%KFtmCf8TTT?++h*RlmoM!`gC_OK$Ht8EaggDjCb!T(oUZ(gK;- z@0$rG&|UpX4BKSp%zUSZ271J!6h+N$`=eUm?z7E)1LL3ah+6?8X?f9}3s>X>rd8Ah2- zQOXRtxM5`*IU0?tLFHP?hjcZY51o^#%}Ib*mh8_=lE(?KltpZWy)U=&wk?i}frOGa z@)b&!a78n-XreN6vVYnh-B!ia6g>E!?#a^mjMy%^M4r8Ljm?n)vJ`pnBz;4Ri}}jK z{s()yDzgXI9#hHif5+7$bYeetZ_h5Sz2L7e{$Dq70qzo2Ikrbn9+Z6kGUb@EzxA&rfp!U51ht_7)kBzFb^Or;03nf*#7M z;mjt+(sdD`(y6kRrCvgmkv19)l(;n8XEh2GttTmynvkide+;#u-W#cUOsw9Zrwn@P zP#e@L*{(JvQ#vgnou;ZiRqg9TRf&tIXv%P`_WC_VFC}0nTf#v~LQU8DjsY6XJht9#Pmk10+k-w$J

R2BShU$0_6E6Dr`GiaQ{!xE4 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 delta 4085 zcmV4A z9|<#OlaQdtI5@{nl!M7dmfeRSbrj@ksVWV$Y*qRPqQ;z4k^DTo>^TpyeMY@|c>(D> zd>q||`DpkZ|IIcLCz1ArZHhZ@dP3~O2+CYybtta+&8>6Qu*j9B-Dw*wrFBxslBI}H ze<1o@kWfNg7p?{ASo z3g0h$zwrH)eE)cm?fbtVf?P;LhxaeEfBJ`OFDmTH=a$2}yl7yvdxlL;bjYo~DWE87 zZ*d@&z>U|68-*q8%MOw5|df9hB) zEs72Hw&OtK9+}%(SZBQlkeC31Z!Faudh>34Df3A>VR{ayD|PY{8VG8So;e?^G^h>e zMDy;^!ui|&@gHZovKP+Zlf@LRrkXy*+Hy5mE|IQ2=+auO@(Dy2i0&i0uN_5*{ud^u z{di$t(TY&ME1)Q1`V!4BlM$ILf2HqdeH>@+J~C}!!0l+@CKAzeVS6-Cm9sgtEJS9( zHX$ag+`gZem39ez4PqUb+*xD|ZImG73{GR4 zRij2CvLkBLU^uy=G_upSN9W6Zz{L>7_oDVxIvs6%>=sUB|1~nt0^eT;f6B_zPQ=q2 zUA>c~aIYW;X^($S#^LEB#nz2dX(ZbASs7r7^STo6bx}*JWYU;a}RN zcUv)`%~_MG)nH8hOivI8g>u`&pB_JakXrKrWHA#>!cGAv%}82?oo;c!H@zJyFwf%u z^=U;}Qt5w)rTp*Jr@2A?e|wJp{o#YJ>i5`jSX*v#$?Y8{V~xvGC1W|8i?;1aS|Ahq zeKWxXx~pG_VVlgHneX(_K#zEoqNv$ze^d+HeYV+e+&R8BBHSD8CBg)g*8NK7rW15m&|N`y1>Mb}f4i@jI;PxqhEb+d zlrlpuZdlnyjz;5ZP`Q@!A$6S1htA2=<|IHYOZI0b$>RiA$|5$x-j`c>+ZM;gKtf3y z`3faVxT2X^G*Ov3**|TMZmVKy3LgAV_hjjOMr;>dBF|pB#^y)?S&BS(lD?tE#eC&q z|AReUmDz)9kEvw%f8**AIS|m=cl=VE<;HRdy9-mUoNhtQ$?0OK@Vls zaAp%@>AHwe=~P+EQZFIONE?j?N?e-lvl<18){~S;O~}+!e}>vn?~PPFCRT6IQwBYC zs10hBY*(9-DV>&(PE*yMs`mAvs>H=pG-Wted;OlGmlCj(E#V*~p{8s7@lYFSgY5p( z6A}(|UDf-_Sl1I0s-uxUR(hk+NU2xC!D!eU>%)ORHW?E3+hYKO78<~?)dnzXy#b6{ zZUAdJiVOskf0=-WYS7Sp_wd3&o~=e69}^3nSv&y*wF1HM)jjF_Tc++w&)+I_U(5a{ zq0H?=({%i^fUCQFrEM<%0DDiAfO?obH zOli^!LC2IPz4CKBX(Ha)aZxkN{cmEwcck<+e`Tyr!_jC^zW_G`INhF zlg?-Q|3g;$GsMhUemWuml$NOB_5MRd3{JnqJe4z2N4Yi9i4k!K+rraL&of0&8Yq@snX8rN|{0v7YPxvgZ}YC?s^NnfFvr+W(S$E)__m0TvGE7^xyhH=O5MleyMf_g+8d8X zlMb3{N=G+`s58-!(HX;mI-Keg*oPxYmi|I`HmAYO4qt5pT7E^T>m|-0x$@WD0&QkL zsqG$q@6o2%tZCS;lB~DkjYP?LQ=|r~7jTcm4_1n_;>^v!Fw!sG(8M3+ljZlD91nenz^ji(QAioS|;k|Zd zn9y2*$2lTlx?AD|^#PAUmwLD4Ku@x5bZU5_Z%SNTRf;V%a&>>;YW{ zo7%y}XX%;CURz6+z&md=f3Vp-!=``P#kBHeO)Ep4 z-am`XyxuTg))_W|%c}Pfq0H5J$eMP7G!sUgjIa!7nlAD@WCFY`tqaa6bC6TpT_6)o zRse!OksAOB1ZTF14Djx8j*U6M#Kf$Ltd7OfqS#<>I}SANk-4pffBH*3keC31Z!Fau zdh>34l3ULem=O*X(yAJ+0~I6Fj*&^1Ek)8o+tkuv#-4 zmVwic`Ye<`VJyu@Fyf5HA=GW#F*v)TV8vJmvpwIAG%Oit#X$j!_8qr0t_ zkj!|4rV`aRMc~t|6v0z1GuJi{_LMf4jT-oUI`t4`Bc*f^irHfsT#`kv)0e_L8sM)-&SFf!NOhJIMq3pcLb zFweLmtE${K7Rk%cT$yrSU}T_kGPSvRYozMtSZlm}g0r^6{#(XbV|rYcv2Hl3rpl6^ z`7G$YCm?tSjSf1{*h-0sWNG#rc%)ma{=H{Mmw zH=@yQ;K^C%qKhEsf}Fo(a;}Z{k#pX-&q&Vdr)GqF_4g&M%%>ZR+>AF+ETFZ_LfgQh zvlRIy@=Aet0`XoO;`MXRiDGX3!bR0rq;{EWT9i6$J1H(wlVBKYcyxV9U}8&bxDA;2 z2G*6te@ctkHxoof5S4m}${^?9uNdT3nVs)4SD&EoFu&RyeJ8`SFcUFTZ=u1qftBQF z^h=~B0s{pGzBUXT=A4OF?J&Hl`yU{4;gu5$5e240@xiXb z1$6H{K<8*<70?4Hcz3d~jxPAkrhv{N`v-f#LzH4NyCn;_0uF}$kkEZFLe9Wsh@!a{-a~G3Yks`&*Iar@kV&!|@+UC*zYGNry z5jz{Z&cof_oL2X8K35DC;4`Aon19UZlu~NF&Ccl+6S-^B=BPA{oG$<7v`5YP9xvA6 z2e`#Z0f&0VNKv(_lkktPTEn%xPgw#TI6$}af3*5Nc(;Jg&2E|Q{PSHfZiUMfkwOdB zDsoEZTe*nK--sv8ku%lP`RU56X_mU7<5W5^A%!Onq;r4avfz@un!=9TY7BZ_=xCr3 zm&inh1>HleB3?$G)Bhzp=Kem_zU7Fl(rdzjl*rGr?G)>Ra;VVL#$yN-y`v7)en;0Q zf4$BGntEqqD#J;CJW*9cuZ$LjdoE&G_< zznb9M!(3a8ly|5F#zkwMf~A^Sl8%K}ryKrmT|H>P#^wB9oXDU48f-LV7Xag%5h zcz-6sIaHLK7^2XYImu?2D|@20br1PeFHBNE^THHd>~1GjBRf5LUA24O5RPiSk*-um z(v~V@FDFRpFNo>Cml#n_mE7jz3*gvhJ9GssT7S0s?W&qswsG%)C85{?bdFpEpo;(r nf;BzhE(!5NJVlfTpHis Date: Thu, 16 Feb 2023 10:33:47 -0700 Subject: [PATCH 04/25] support network name overrides in pack to build releases --- Makefile | 2 +- build/actors/pack.sh | 2 +- gen/bundle/bundle.go | 32 +++++++++++++++++++++++++------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 023ca61f5..385ea3482 100644 --- a/Makefile +++ b/Makefile @@ -298,7 +298,7 @@ actors-gen: actors-code-gen fiximports .PHONY: actors-gen bundle-gen: - $(GOCC) run ./gen/bundle $(RELEASE) + $(GOCC) run ./gen/bundle $(RELEASE) $(RELEASE_OVERRIDES) $(GOCC) fmt ./build/... .PHONY: bundle-gen diff --git a/build/actors/pack.sh b/build/actors/pack.sh index 863a3c5c7..b8d2bdb3d 100755 --- a/build/actors/pack.sh +++ b/build/actors/pack.sh @@ -52,4 +52,4 @@ popd echo "Generating metadata..." -make -C ../../ RELEASE="$RELEASE" bundle-gen +make -C ../../ RELEASE="$RELEASE" RELEASE_OVERRIDES="${RELEASE_OVERRIDES[*]}" bundle-gen diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index d953b99c9..da38f192f 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -2,6 +2,7 @@ package main import ( "os" + "strings" "text/template" "github.com/filecoin-project/lotus/build" @@ -32,19 +33,36 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet } `)) +func splitOverride(override string) (string, string) { + x := strings.Split(override, "=") + return x[0], x[1] +} + func main() { metadata, err := build.ReadEmbeddedBuiltinActorsMetadata() if err != nil { panic(err) } - // TODO: Re-enable this when we can set the tag for ONLY the appropriate version - // https://github.com/filecoin-project/lotus/issues/10185#issuecomment-1422864836 - //if len(os.Args) > 1 { - // for _, m := range metadata { - // m.BundleGitTag = os.Args[1] - // } - //} + // see ./build/actors/pack.sh + // expected args are git bundle tag then number of per network overrides + // overrides are in the format network_name=override + overrides := map[string]string{} + for _, override := range os.Args[2:] { + network, version := splitOverride(override) + overrides[network] = version + } + + if len(os.Args) > 1 { + for _, m := range metadata { + override, ok := overrides[m.Network] + if ok { + m.BundleGitTag = override + } else { + m.BundleGitTag = os.Args[1] + } + } + } fi, err := os.Create("./build/builtin_actors_gen.go") if err != nil { From 16b7d4525fe7cd7ba938658bb70746b365c89f0d Mon Sep 17 00:00:00 2001 From: mike seiler Date: Thu, 16 Feb 2023 10:40:16 -0700 Subject: [PATCH 05/25] lintfix --- gen/bundle/bundle.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index da38f192f..e369fd3dc 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -44,9 +44,9 @@ func main() { panic(err) } - // see ./build/actors/pack.sh - // expected args are git bundle tag then number of per network overrides - // overrides are in the format network_name=override + // see ./build/actors/pack.sh + // expected args are git bundle tag then number of per network overrides + // overrides are in the format network_name=override overrides := map[string]string{} for _, override := range os.Args[2:] { network, version := splitOverride(override) From ea03e1b6e70969e3c4bc7194bdf12b4b2aac7a45 Mon Sep 17 00:00:00 2001 From: mike seiler Date: Thu, 16 Feb 2023 13:10:25 -0700 Subject: [PATCH 06/25] only override the correct version for bundle gen --- gen/bundle/bundle.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index e369fd3dc..908ef57e8 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "os" "strings" "text/template" @@ -56,7 +57,7 @@ func main() { if len(os.Args) > 1 { for _, m := range metadata { override, ok := overrides[m.Network] - if ok { + if ok && strings.HasPrefix(override, fmt.Sprintf("v%d", m.Version)) { m.BundleGitTag = override } else { m.BundleGitTag = os.Args[1] From 0f6cbf1be25aa2d255051fcdc0b2e1d280910174 Mon Sep 17 00:00:00 2001 From: mike seiler Date: Thu, 16 Feb 2023 14:01:45 -0700 Subject: [PATCH 07/25] include the version that pack is running on for filtering the build gen metadata --- Makefile | 2 +- build/actors/pack.sh | 2 +- gen/bundle/bundle.go | 30 ++++++++++++++++++++---------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 385ea3482..d1e7d159a 100644 --- a/Makefile +++ b/Makefile @@ -298,7 +298,7 @@ actors-gen: actors-code-gen fiximports .PHONY: actors-gen bundle-gen: - $(GOCC) run ./gen/bundle $(RELEASE) $(RELEASE_OVERRIDES) + $(GOCC) run ./gen/bundle $(VERSION) $(RELEASE) $(RELEASE_OVERRIDES) $(GOCC) fmt ./build/... .PHONY: bundle-gen diff --git a/build/actors/pack.sh b/build/actors/pack.sh index b8d2bdb3d..e594bb2da 100755 --- a/build/actors/pack.sh +++ b/build/actors/pack.sh @@ -52,4 +52,4 @@ popd echo "Generating metadata..." -make -C ../../ RELEASE="$RELEASE" RELEASE_OVERRIDES="${RELEASE_OVERRIDES[*]}" bundle-gen +make -C ../../ VERSION="$VERSION" RELEASE="$RELEASE" RELEASE_OVERRIDES="${RELEASE_OVERRIDES[*]}" bundle-gen diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index 908ef57e8..a1eab4e04 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -45,24 +45,34 @@ func main() { panic(err) } + var metadataSpecificVersion []*build.BuiltinActorsMetadata + // see ./build/actors/pack.sh // expected args are git bundle tag then number of per network overrides // overrides are in the format network_name=override - overrides := map[string]string{} - for _, override := range os.Args[2:] { - network, version := splitOverride(override) - overrides[network] = version - } if len(os.Args) > 1 { + version := os.Args[1] + overrides := map[string]string{} + for _, override := range os.Args[3:] { + k, v := splitOverride(override) + overrides[k] = v + } for _, m := range metadata { - override, ok := overrides[m.Network] - if ok && strings.HasPrefix(override, fmt.Sprintf("v%d", m.Version)) { - m.BundleGitTag = override - } else { - m.BundleGitTag = os.Args[1] + if strings.HasPrefix(version, fmt.Sprintf("v%d", m.Version)) { + // correct version + override, ok := overrides[m.Network] + if ok { + m.BundleGitTag = override + } else { + m.BundleGitTag = os.Args[2] + } + fmt.Println("hi") + metadataSpecificVersion = append(metadataSpecificVersion, m) } } + metadata = metadataSpecificVersion + } fi, err := os.Create("./build/builtin_actors_gen.go") From 5854d72784eeb4eba464d7d650e00236228d12da Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 16 Feb 2023 16:36:52 -0800 Subject: [PATCH 08/25] fix: eth: correctly decode EthGetStorageAt output (#10284) * fix: eth: correctly decode EthGetStorageAt output We cbor-encode it. Also: 1. Actually use the passed block param. 2. Check if the target actor is an EVM actor to avoid nonsense outputs. fixes https://github.com/filecoin-project/ref-fvm/issues/1621 --- itests/fevm_test.go | 14 ++++++++++++++ node/impl/full/eth.go | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/itests/fevm_test.go b/itests/fevm_test.go index 3018bf63d..cf70faba2 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -265,6 +265,20 @@ func TestFEVMDelegateCall(t *testing.T) { expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) require.Equal(t, result, expectedResultActor) + + // The implementation's storage should not have been updated. + actorAddrEth, err := ethtypes.EthAddressFromFilecoinAddress(actorAddr) + require.NoError(t, err) + value, err := client.EVM().EthGetStorageAt(ctx, actorAddrEth, nil, "latest") + require.NoError(t, err) + require.Equal(t, ethtypes.EthBytes(make([]byte, 32)), value) + + // The storage actor's storage _should_ have been updated + storageAddrEth, err := ethtypes.EthAddressFromFilecoinAddress(storageAddr) + require.NoError(t, err) + value, err = client.EVM().EthGetStorageAt(ctx, storageAddrEth, nil, "latest") + require.NoError(t, err) + require.Equal(t, ethtypes.EthBytes(expectedResult), value) } // TestFEVMDelegateCallRevert makes a delegatecall action and then calls revert. diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index e30fe4da1..3fc6c6940 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -510,13 +510,18 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, } func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) { + ts, err := a.parseBlkParam(ctx, blkParam) + if err != nil { + return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) + } + l := len(position) if l > 32 { return nil, fmt.Errorf("supplied storage key is too long") } // pad with zero bytes if smaller than 32 bytes - position = append(make([]byte, 32-l, 32-l), position...) + position = append(make([]byte, 32-l, 32), position...) to, err := ethAddr.ToFilecoinAddress() if err != nil { @@ -529,6 +534,18 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAdd return nil, fmt.Errorf("failed to construct system sender address: %w", err) } + actor, err := a.StateManager.LoadActor(ctx, to, ts) + if err != nil { + if xerrors.Is(err, types.ErrActorNotFound) { + return ethtypes.EthBytes(make([]byte, 32)), nil + } + return nil, xerrors.Errorf("failed to lookup contract %s: %w", ethAddr, err) + } + + if !builtinactors.IsEvmActor(actor.Code) { + return ethtypes.EthBytes(make([]byte, 32)), nil + } + params, err := actors.SerializeParams(&evm.GetStorageAtParams{ StorageKey: *(*[32]byte)(position), }) @@ -547,8 +564,6 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAdd GasPremium: big.Zero(), } - ts := a.Chain.GetHeaviestTipSet() - // Try calling until we find a height with no migration. var res *api.InvocResult for { @@ -567,10 +582,22 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAdd } if res.MsgRct == nil { - return nil, fmt.Errorf("no message receipt") + return nil, xerrors.Errorf("no message receipt") } - return res.MsgRct.Return, nil + if res.MsgRct.ExitCode.IsError() { + return nil, xerrors.Errorf("failed to lookup storage slot: %s", res.Error) + } + + var ret abi.CborBytes + if err := ret.UnmarshalCBOR(bytes.NewReader(res.MsgRct.Return)); err != nil { + return nil, xerrors.Errorf("failed to unmarshal storage slot: %w", err) + } + + // pad with zero bytes if smaller than 32 bytes + ret = append(make([]byte, 32-len(ret), 32), ret...) + + return ethtypes.EthBytes(ret), nil } func (a *EthModule) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) { From b2610bed52ce8e1b809cc34daaf112ddbd673fac Mon Sep 17 00:00:00 2001 From: mike seiler Date: Thu, 16 Feb 2023 17:55:04 -0700 Subject: [PATCH 09/25] change rpc types from uint to hash to match fevm implementation --- itests/specs/eth_openrpc.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/itests/specs/eth_openrpc.json b/itests/specs/eth_openrpc.json index 1947bbd32..0f354b5c7 100644 --- a/itests/specs/eth_openrpc.json +++ b/itests/specs/eth_openrpc.json @@ -1794,9 +1794,9 @@ "result": { "name": "Filter Identifier", "schema": { - "title": "hex encoded unsigned integer", + "title": "32 byte hex value", "type": "string", - "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + "pattern": "^0x[0-9a-f]{64}$" } } }, @@ -1807,9 +1807,9 @@ "result": { "name": "Filter Identifier", "schema": { - "title": "hex encoded unsigned integer", + "title": "32 byte hex value", "type": "string", - "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + "pattern": "^0x[0-9a-f]{64}$" } } }, @@ -1820,9 +1820,9 @@ "result": { "name": "Filter Identifier", "schema": { - "title": "hex encoded unsigned integer", + "title": "32 byte hex value", "type": "string", - "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + "pattern": "^0x[0-9a-f]{64}$" } } }, @@ -1833,9 +1833,9 @@ { "name": "Filter Identifier", "schema": { - "title": "hex encoded unsigned integer", + "title": "32 byte hex value", "type": "string", - "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + "pattern": "^0x[0-9a-f]{64}$" } } ], @@ -1853,9 +1853,9 @@ { "name": "Filter Identifier", "schema": { - "title": "hex encoded unsigned integer", + "title": "32 byte hex value", "type": "string", - "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + "pattern": "^0x[0-9a-f]{64}$" } } ], @@ -1954,9 +1954,9 @@ { "name": "Filter Identifier", "schema": { - "title": "hex encoded unsigned integer", + "title": "32 byte hex value", "type": "string", - "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + "pattern": "^0x[0-9a-f]{64}$" } } ], From 00b6d060411c9230265206cfac1a6e557dce7f95 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 16 Feb 2023 17:18:03 -0800 Subject: [PATCH 10/25] feat: eth: parse revert data (#10295) We don't really want to do this in the FVM because it's Ethereum specific, but this makes sense to do in the Ethereum API. See: See https://docs.soliditylang.org/en/latest/control-structures.html#panic-via-assert-and-error-via-require --- chain/types/ethtypes/eth_types.go | 33 +++++++++--- itests/contracts/Errors.hex | 1 + itests/contracts/Errors.sol | 24 +++++++++ itests/fevm_test.go | 30 +++++++++++ node/impl/full/eth.go | 84 ++++++++++++++++++++++++++++++- 5 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 itests/contracts/Errors.hex create mode 100644 itests/contracts/Errors.sol diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index 1539a638b..006ffffdc 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -66,6 +66,18 @@ func EthUint64FromHex(s string) (EthUint64, error) { return EthUint64(parsedInt), nil } +// Parse a uint64 from big-endian encoded bytes. +func EthUint64FromBytes(b []byte) (EthUint64, error) { + if len(b) != 32 { + return 0, xerrors.Errorf("eth int must be 32 bytes long") + } + var zeros [32 - 8]byte + if !bytes.Equal(b[:len(zeros)], zeros[:]) { + return 0, xerrors.Errorf("eth int overflows 64 bits") + } + return EthUint64(binary.BigEndian.Uint64(b[len(zeros):])), nil +} + func (e EthUint64) Hex() string { if e == 0 { return "0x0" @@ -78,11 +90,15 @@ type EthBigInt big.Int var EthBigIntZero = EthBigInt{Int: big.Zero().Int} -func (e EthBigInt) MarshalJSON() ([]byte, error) { +func (e EthBigInt) String() string { if e.Int == nil || e.Int.BitLen() == 0 { - return json.Marshal("0x0") + return "0x0" } - return json.Marshal(fmt.Sprintf("0x%x", e.Int)) + return fmt.Sprintf("0x%x", e.Int) +} + +func (e EthBigInt) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) } func (e *EthBigInt) UnmarshalJSON(b []byte) error { @@ -106,12 +122,15 @@ func (e *EthBigInt) UnmarshalJSON(b []byte) error { // EthBytes represent arbitrary bytes. A nil or empty slice serializes to "0x". type EthBytes []byte -func (e EthBytes) MarshalJSON() ([]byte, error) { +func (e EthBytes) String() string { if len(e) == 0 { - return json.Marshal("0x") + return "0x" } - s := hex.EncodeToString(e) - return json.Marshal("0x" + s) + return "0x" + hex.EncodeToString(e) +} + +func (e EthBytes) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) } func (e *EthBytes) UnmarshalJSON(b []byte) error { diff --git a/itests/contracts/Errors.hex b/itests/contracts/Errors.hex new file mode 100644 index 000000000..64e4ea6df --- /dev/null +++ b/itests/contracts/Errors.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506102de806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80630abe88b61461005c57806358d4cbce1461006657806359be8c55146100705780638791bd331461007a578063c6dbcf2e14610084575b600080fd5b61006461008e565b005b61006e61009f565b005b6100786100a4565b005b6100826100df565b005b61008c610111565b005b600061009d5761009c61012a565b5b565b600080fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100d6906101b6565b60405180910390fd5b6040517f09caebf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001905060008082610125919061023e565b505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082825260208201905092915050565b7f6d7920726561736f6e0000000000000000000000000000000000000000000000600082015250565b60006101a0600983610159565b91506101ab8261016a565b602082019050919050565b600060208201905081810360008301526101cf81610193565b9050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610249826101d6565b9150610254836101d6565b925082610264576102636101e0565b5b600160000383147f80000000000000000000000000000000000000000000000000000000000000008314161561029d5761029c61020f565b5b82820590509291505056fea26469706673582212207815355e9e7ced2b8168a953c364e82871c0fe326602bbb9106e6551aea673ed64736f6c63430008120033 \ No newline at end of file diff --git a/itests/contracts/Errors.sol b/itests/contracts/Errors.sol new file mode 100644 index 000000000..f9bcfbce2 --- /dev/null +++ b/itests/contracts/Errors.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract Errors { + error CustomError(); + + function failRevertEmpty() public { + revert(); + } + function failRevertReason() public { + revert("my reason"); + } + function failAssert() public { + assert(false); + } + function failDivZero() public { + int a = 1; + int b = 0; + a / b; + } + function failCustom() public { + revert CustomError(); + } +} diff --git a/itests/fevm_test.go b/itests/fevm_test.go index cf70faba2..d9c0019de 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -882,3 +882,33 @@ func TestFEVMGetBlockDifficulty(t *testing.T) { require.NoError(t, err) require.Equal(t, len(ret), 32) } + +func TestFEVMErrorParsing(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + e := client.EVM() + + _, contractAddr := e.DeployContractFromFilename(ctx, "contracts/Errors.hex") + contractAddrEth, err := ethtypes.EthAddressFromFilecoinAddress(contractAddr) + require.NoError(t, err) + customError := ethtypes.EthBytes(kit.CalcFuncSignature("CustomError()")).String() + for sig, expected := range map[string]string{ + "failRevertEmpty()": "none", + "failRevertReason()": "Error(my reason)", + "failAssert()": "Assert()", + "failDivZero()": "DivideByZero()", + "failCustom()": customError, + } { + sig := sig + expected := expected + t.Run(sig, func(t *testing.T) { + entryPoint := kit.CalcFuncSignature(sig) + _, err := e.EthCall(ctx, ethtypes.EthCall{ + To: &contractAddrEth, + Data: entryPoint, + }, "latest") + require.ErrorContains(t, err, fmt.Sprintf("exit 33, revert reason: %s, vm error", expected)) + }) + } +} diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 3fc6c6940..454b3eca5 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -871,7 +871,8 @@ func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message, tsk ty return nil, xerrors.Errorf("CallWithGas failed: %w", err) } if res.MsgRct.ExitCode.IsError() { - return nil, xerrors.Errorf("message execution failed: exit %s, msg receipt: %s, reason: %s", res.MsgRct.ExitCode, res.MsgRct.Return, res.Error) + reason := parseEthRevert(res.MsgRct.Return) + return nil, xerrors.Errorf("message execution failed: exit %s, revert reason: %s, vm error: %s", res.MsgRct.ExitCode, reason, res.Error) } return res, nil } @@ -1032,7 +1033,7 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s invokeResult, err := a.applyMessage(ctx, msg, ts.Key()) if err != nil { - return nil, xerrors.Errorf("failed to apply message: %w", err) + return nil, err } if msg.To == builtintypes.EthereumAddressManagerActorAddr { @@ -2211,6 +2212,85 @@ func parseEthTopics(topics ethtypes.EthTopicSpec) (map[string][][]byte, error) { return keys, nil } +const errorFunctionSelector = "\x08\xc3\x79\xa0" // Error(string) +const panicFunctionSelector = "\x4e\x48\x7b\x71" // Panic(uint256) +// Eth ABI (solidity) panic codes. +var panicErrorCodes map[uint64]string = map[uint64]string{ + 0x00: "Panic()", + 0x01: "Assert()", + 0x11: "ArithmeticOverflow()", + 0x12: "DivideByZero()", + 0x21: "InvalidEnumVariant()", + 0x22: "InvalidStorageArray()", + 0x31: "PopEmptyArray()", + 0x32: "ArrayIndexOutOfBounds()", + 0x41: "OutOfMemory()", + 0x51: "CalledUninitializedFunction()", +} + +// Parse an ABI encoded revert reason. This reason should be encoded as if it were the parameters to +// an `Error(string)` function call. +// +// See https://docs.soliditylang.org/en/latest/control-structures.html#panic-via-assert-and-error-via-require +func parseEthRevert(ret []byte) string { + if len(ret) == 0 { + return "none" + } + var cbytes abi.CborBytes + if err := cbytes.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { + return "ERROR: revert reason is not cbor encoded bytes" + } + if len(cbytes) == 0 { + return "none" + } + // If it's not long enough to contain an ABI encoded response, return immediately. + if len(cbytes) < 4+32 { + return ethtypes.EthBytes(cbytes).String() + } + switch string(cbytes[:4]) { + case panicFunctionSelector: + cbytes := cbytes[4 : 4+32] + // Read the and check the code. + code, err := ethtypes.EthUint64FromBytes(cbytes) + if err != nil { + // If it's too big, just return the raw value. + codeInt := big.PositiveFromUnsignedBytes(cbytes) + return fmt.Sprintf("Panic(%s)", ethtypes.EthBigInt(codeInt).String()) + } + if s, ok := panicErrorCodes[uint64(code)]; ok { + return s + } + return fmt.Sprintf("Panic(0x%x)", code) + case errorFunctionSelector: + cbytes := cbytes[4:] + cbytesLen := ethtypes.EthUint64(len(cbytes)) + // Read the and check the offset. + offset, err := ethtypes.EthUint64FromBytes(cbytes[:32]) + if err != nil { + break + } + if cbytesLen < offset { + break + } + + // Read and check the length. + if cbytesLen-offset < 32 { + break + } + start := offset + 32 + length, err := ethtypes.EthUint64FromBytes(cbytes[offset : offset+32]) + if err != nil { + break + } + if cbytesLen-start < length { + break + } + // Slice the error message. + return fmt.Sprintf("Error(%s)", cbytes[start:start+length]) + } + return ethtypes.EthBytes(cbytes).String() +} + func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRewardSorter) ([]ethtypes.EthBigInt, uint64) { var totalGasUsed uint64 for _, tx := range txGasRewards { From ccdb4470853a99f57cbaacff2675168ba2c0f3a8 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 16 Feb 2023 23:58:16 -0500 Subject: [PATCH 11/25] avoid actor not found --- cli/evm.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cli/evm.go b/cli/evm.go index 2169a3486..7aee5d838 100644 --- a/cli/evm.go +++ b/cli/evm.go @@ -8,6 +8,8 @@ import ( "fmt" "os" + "github.com/filecoin-project/specs-actors/v8/actors/builtin" + "github.com/urfave/cli/v2" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" @@ -75,13 +77,18 @@ var EvmGetInfoCmd = &cli.Command{ } actor, err := api.StateGetActor(ctx, faddr, types.EmptyTSK) - if err != nil { - return err - } - fmt.Println("Filecoin address: ", faddr) fmt.Println("Eth address: ", eaddr) - fmt.Println("Code cid: ", actor.Code.String()) + if err != nil { + fmt.Printf("Actor lookup failed for faddr %s with error: %s\n", faddr, err) + } else { + idAddr, err := api.StateLookupID(ctx, faddr, types.EmptyTSK) + if err == nil { + fmt.Println("ID address: ", idAddr) + fmt.Println("Code cid: ", actor.Code.String()) + fmt.Println("Actor Type: ", builtin.ActorNameByCode(actor.Code)) + } + } return nil }, From f2648adee8bd3a5de63bb04ad8a610cffdbf51a9 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Fri, 17 Feb 2023 00:11:07 -0500 Subject: [PATCH 12/25] fix import --- cli/evm.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/evm.go b/cli/evm.go index 7aee5d838..e1c4d7b93 100644 --- a/cli/evm.go +++ b/cli/evm.go @@ -8,8 +8,7 @@ import ( "fmt" "os" - "github.com/filecoin-project/specs-actors/v8/actors/builtin" - + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/urfave/cli/v2" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" From 59db4eeacd9931a8956c00308a87112ffb4b0cc6 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Fri, 17 Feb 2023 00:21:29 -0500 Subject: [PATCH 13/25] fix gen --- cli/evm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/evm.go b/cli/evm.go index e1c4d7b93..d153e7212 100644 --- a/cli/evm.go +++ b/cli/evm.go @@ -8,7 +8,6 @@ import ( "fmt" "os" - "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/urfave/cli/v2" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" @@ -22,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" ) From d589443a5e0ab3bfc40a569146329369f2631e14 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Fri, 17 Feb 2023 12:16:09 -0500 Subject: [PATCH 14/25] feat: EthApiTest: Confirm EthAddressToFilecoinAddress works without EthRPC (#10302) --- itests/eth_api_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/itests/eth_api_test.go b/itests/eth_api_test.go index 39026637f..63c6aa5a2 100644 --- a/itests/eth_api_test.go +++ b/itests/eth_api_test.go @@ -16,7 +16,8 @@ import ( ) func TestEthAddressToFilecoinAddress(t *testing.T) { - client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + // Disable EthRPC to confirm that this method does NOT need the EthEnableRPC config set to true + client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.DisableEthRPC()) ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() From 2d3065ae8eb904ad89c7df5b5b96f757735a870f Mon Sep 17 00:00:00 2001 From: Jorropo Date: Thu, 26 Jan 2023 16:41:28 +0100 Subject: [PATCH 15/25] chore: all: bump go-libipfs to replace go-block-format Includes changes from: - https://github.com/ipfs/go-block-format/pull/37 - https://github.com/ipfs/go-libipfs/pull/58 (cherry picked from commit f572852d06aa73e54193d053601ab879642638f7) --- api/api_full.go | 2 +- api/api_gateway.go | 2 +- api/docgen/docgen.go | 2 +- api/mocks/mock_full.go | 2 +- api/proxy_gen.go | 2 +- api/v0api/full.go | 2 +- api/v0api/gateway.go | 2 +- api/v0api/proxy_gen.go | 2 +- api/v0api/v0mocks/mock_full.go | 2 +- blockstore/api.go | 2 +- blockstore/autobatch.go | 2 +- blockstore/badger/blockstore.go | 2 +- blockstore/badger/blockstore_test.go | 2 +- blockstore/badger/blockstore_test_suite.go | 2 +- blockstore/buffered.go | 2 +- blockstore/discard.go | 2 +- blockstore/fallback.go | 2 +- blockstore/idstore.go | 2 +- blockstore/ipfs.go | 2 +- blockstore/mem.go | 2 +- blockstore/mem_test.go | 2 +- blockstore/net.go | 2 +- blockstore/net_serve.go | 2 +- blockstore/net_test.go | 2 +- blockstore/splitstore/debug.go | 2 +- blockstore/splitstore/splitstore.go | 2 +- blockstore/splitstore/splitstore_compact.go | 2 +- blockstore/splitstore/splitstore_expose.go | 2 +- blockstore/splitstore/splitstore_reify.go | 2 +- blockstore/splitstore/splitstore_test.go | 2 +- blockstore/splitstore/splitstore_warmup.go | 2 +- blockstore/sync.go | 2 +- blockstore/timed.go | 2 +- blockstore/timed_test.go | 2 +- blockstore/union.go | 2 +- blockstore/union_test.go | 2 +- chain/events/state/mock/api.go | 2 +- chain/gen/genesis/genblock.go | 2 +- chain/store/messages.go | 2 +- chain/store/snapshot.go | 2 +- chain/store/store.go | 2 +- chain/sub/incoming.go | 2 +- chain/sub/incoming_test.go | 2 +- chain/sync.go | 2 +- chain/types/blockheader.go | 2 +- chain/types/message.go | 2 +- chain/types/signedmessage.go | 2 +- chain/types/tipset_key.go | 2 +- chain/vm/vm.go | 2 +- cmd/lotus-shed/datastore-vlog.go | 2 +- cmd/lotus-shed/export.go | 2 +- cmd/lotus-shed/import-car.go | 2 +- cmd/tvx/stores.go | 2 +- conformance/runner.go | 2 +- gateway/node.go | 2 +- gateway/proxy_fil.go | 2 +- go.mod | 9 +++++---- go.sum | 19 ++++++++++++------- .../deals_partial_retrieval_dm-level_test.go | 2 +- itests/deals_partial_retrieval_test.go | 2 +- markets/dagstore/blockstore.go | 2 +- markets/storageadapter/api.go | 2 +- .../ondealsectorcommitted_test.go | 2 +- node/impl/full/chain.go | 2 +- 64 files changed, 79 insertions(+), 73 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index c81bb2d6b..e7a2d289e 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -7,8 +7,8 @@ import ( "time" "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-libp2p/core/peer" "github.com/filecoin-project/go-address" diff --git a/api/api_gateway.go b/api/api_gateway.go index aea6fc3d1..2e877fb1a 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -3,8 +3,8 @@ package api import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-jsonrpc" diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 606ae9d8e..65d71d208 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -14,9 +14,9 @@ import ( "unicode" "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" "github.com/ipfs/go-graphsync" + blocks "github.com/ipfs/go-libipfs/blocks" textselector "github.com/ipld/go-ipld-selector-text-lite" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/metrics" diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index a5c65f07a..f49e912a2 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -12,8 +12,8 @@ import ( gomock "github.com/golang/mock/gomock" uuid "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" metrics "github.com/libp2p/go-libp2p/core/metrics" network0 "github.com/libp2p/go-libp2p/core/network" peer "github.com/libp2p/go-libp2p/core/peer" diff --git a/api/proxy_gen.go b/api/proxy_gen.go index f04bea2a9..baf433735 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -8,8 +8,8 @@ import ( "time" "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-libp2p/core/metrics" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" diff --git a/api/v0api/full.go b/api/v0api/full.go index 87d5cba4e..490cd73c8 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -3,8 +3,8 @@ package v0api import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" textselector "github.com/ipld/go-ipld-selector-text-lite" "github.com/libp2p/go-libp2p/core/peer" diff --git a/api/v0api/gateway.go b/api/v0api/gateway.go index bd55917c7..674371c14 100644 --- a/api/v0api/gateway.go +++ b/api/v0api/gateway.go @@ -3,8 +3,8 @@ package v0api import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index 4acf2e111..5fa0d949c 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -5,8 +5,8 @@ package v0api import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-libp2p/core/peer" "golang.org/x/xerrors" diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 3aff979ff..619f19d35 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -11,8 +11,8 @@ import ( gomock "github.com/golang/mock/gomock" uuid "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" metrics "github.com/libp2p/go-libp2p/core/metrics" network0 "github.com/libp2p/go-libp2p/core/network" peer "github.com/libp2p/go-libp2p/core/peer" diff --git a/blockstore/api.go b/blockstore/api.go index 090f53e5a..251deb13a 100644 --- a/blockstore/api.go +++ b/blockstore/api.go @@ -3,8 +3,8 @@ package blockstore import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/autobatch.go b/blockstore/autobatch.go index d41d521ef..3cb8eafa6 100644 --- a/blockstore/autobatch.go +++ b/blockstore/autobatch.go @@ -5,9 +5,9 @@ import ( "sync" "time" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + block "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 050ed6d3b..da4f9f67d 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -13,9 +13,9 @@ import ( "github.com/dgraph-io/badger/v2" "github.com/dgraph-io/badger/v2/options" "github.com/dgraph-io/badger/v2/pb" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" logger "github.com/ipfs/go-log/v2" pool "github.com/libp2p/go-buffer-pool" "github.com/multiformats/go-base32" diff --git a/blockstore/badger/blockstore_test.go b/blockstore/badger/blockstore_test.go index a14515796..fc81be43e 100644 --- a/blockstore/badger/blockstore_test.go +++ b/blockstore/badger/blockstore_test.go @@ -10,8 +10,8 @@ import ( "strings" "testing" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" diff --git a/blockstore/badger/blockstore_test_suite.go b/blockstore/badger/blockstore_test_suite.go index 7db155901..877eb6e6b 100644 --- a/blockstore/badger/blockstore_test_suite.go +++ b/blockstore/badger/blockstore_test_suite.go @@ -9,10 +9,10 @@ import ( "strings" "testing" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" u "github.com/ipfs/go-ipfs-util" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" "github.com/filecoin-project/lotus/blockstore" diff --git a/blockstore/buffered.go b/blockstore/buffered.go index dbee095a2..e089ed561 100644 --- a/blockstore/buffered.go +++ b/blockstore/buffered.go @@ -4,9 +4,9 @@ import ( "context" "os" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + block "github.com/ipfs/go-libipfs/blocks" ) // buflog is a logger for the buffered blockstore. It is subscoped from the diff --git a/blockstore/discard.go b/blockstore/discard.go index a8e6cfec7..7f1a76a22 100644 --- a/blockstore/discard.go +++ b/blockstore/discard.go @@ -4,8 +4,8 @@ import ( "context" "io" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" ) var _ Blockstore = (*discardstore)(nil) diff --git a/blockstore/fallback.go b/blockstore/fallback.go index de948b346..9fab960f5 100644 --- a/blockstore/fallback.go +++ b/blockstore/fallback.go @@ -5,9 +5,9 @@ import ( "sync" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/idstore.go b/blockstore/idstore.go index 23b85146a..a0ecec5f0 100644 --- a/blockstore/idstore.go +++ b/blockstore/idstore.go @@ -4,8 +4,8 @@ import ( "context" "io" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" mh "github.com/multiformats/go-multihash" "golang.org/x/xerrors" ) diff --git a/blockstore/ipfs.go b/blockstore/ipfs.go index 41c2b8710..756314f2d 100644 --- a/blockstore/ipfs.go +++ b/blockstore/ipfs.go @@ -5,9 +5,9 @@ import ( "context" "io/ioutil" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" httpapi "github.com/ipfs/go-ipfs-http-client" + blocks "github.com/ipfs/go-libipfs/blocks" iface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" "github.com/ipfs/interface-go-ipfs-core/path" diff --git a/blockstore/mem.go b/blockstore/mem.go index 7cfefafd7..05da287c5 100644 --- a/blockstore/mem.go +++ b/blockstore/mem.go @@ -3,9 +3,9 @@ package blockstore import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" ) // NewMemory returns a temporary memory-backed blockstore. diff --git a/blockstore/mem_test.go b/blockstore/mem_test.go index 4d4a77624..6a5e0d2d1 100644 --- a/blockstore/mem_test.go +++ b/blockstore/mem_test.go @@ -4,8 +4,8 @@ import ( "context" "testing" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" mh "github.com/multiformats/go-multihash" "github.com/stretchr/testify/require" ) diff --git a/blockstore/net.go b/blockstore/net.go index 77da764a5..a6b008af2 100644 --- a/blockstore/net.go +++ b/blockstore/net.go @@ -8,9 +8,9 @@ import ( "sync" "sync/atomic" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-msgio" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" diff --git a/blockstore/net_serve.go b/blockstore/net_serve.go index 2540c845e..b58d2a5fd 100644 --- a/blockstore/net_serve.go +++ b/blockstore/net_serve.go @@ -5,9 +5,9 @@ import ( "context" "encoding/binary" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + block "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-msgio" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" diff --git a/blockstore/net_test.go b/blockstore/net_test.go index d8c33818e..6c3060a98 100644 --- a/blockstore/net_test.go +++ b/blockstore/net_test.go @@ -6,8 +6,8 @@ import ( "io" "testing" - block "github.com/ipfs/go-block-format" ipld "github.com/ipfs/go-ipld-format" + block "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-msgio" "github.com/stretchr/testify/require" ) diff --git a/blockstore/splitstore/debug.go b/blockstore/splitstore/debug.go index f059ae4ce..c870a44e1 100644 --- a/blockstore/splitstore/debug.go +++ b/blockstore/splitstore/debug.go @@ -12,8 +12,8 @@ import ( "sync" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "go.uber.org/multierr" "golang.org/x/xerrors" ) diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index dee6e784c..0afb15c11 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -8,10 +8,10 @@ import ( "sync/atomic" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "go.opencensus.io/stats" "go.uber.org/multierr" diff --git a/blockstore/splitstore/splitstore_compact.go b/blockstore/splitstore/splitstore_compact.go index 6ffb35726..0422736f0 100644 --- a/blockstore/splitstore/splitstore_compact.go +++ b/blockstore/splitstore/splitstore_compact.go @@ -10,9 +10,9 @@ import ( "sync/atomic" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" cbg "github.com/whyrusleeping/cbor-gen" "go.opencensus.io/stats" "golang.org/x/sync/errgroup" diff --git a/blockstore/splitstore/splitstore_expose.go b/blockstore/splitstore/splitstore_expose.go index ff9bf1f71..d092fbb9b 100644 --- a/blockstore/splitstore/splitstore_expose.go +++ b/blockstore/splitstore/splitstore_expose.go @@ -4,9 +4,9 @@ import ( "context" "errors" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" bstore "github.com/filecoin-project/lotus/blockstore" ) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index 9db480b8c..aa14f090a 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -5,8 +5,8 @@ import ( "runtime" "sync/atomic" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/splitstore/splitstore_test.go b/blockstore/splitstore/splitstore_test.go index 750a2efed..c97a9d01c 100644 --- a/blockstore/splitstore/splitstore_test.go +++ b/blockstore/splitstore/splitstore_test.go @@ -11,11 +11,11 @@ import ( "testing" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" dssync "github.com/ipfs/go-datastore/sync" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" mh "github.com/multiformats/go-multihash" diff --git a/blockstore/splitstore/splitstore_warmup.go b/blockstore/splitstore/splitstore_warmup.go index e387263da..23bbad7ca 100644 --- a/blockstore/splitstore/splitstore_warmup.go +++ b/blockstore/splitstore/splitstore_warmup.go @@ -5,9 +5,9 @@ import ( "sync/atomic" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" diff --git a/blockstore/sync.go b/blockstore/sync.go index 1b4ad8297..4f97027ae 100644 --- a/blockstore/sync.go +++ b/blockstore/sync.go @@ -4,8 +4,8 @@ import ( "context" "sync" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" ) // NewMemorySync returns a thread-safe in-memory blockstore. diff --git a/blockstore/timed.go b/blockstore/timed.go index 38f4e51f3..dda2e1958 100644 --- a/blockstore/timed.go +++ b/blockstore/timed.go @@ -6,9 +6,9 @@ import ( "sync" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/raulk/clock" "go.uber.org/multierr" ) diff --git a/blockstore/timed_test.go b/blockstore/timed_test.go index 931f14507..fb3aa00c9 100644 --- a/blockstore/timed_test.go +++ b/blockstore/timed_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/raulk/clock" "github.com/stretchr/testify/require" ) diff --git a/blockstore/union.go b/blockstore/union.go index 71e785f1a..3372cd20c 100644 --- a/blockstore/union.go +++ b/blockstore/union.go @@ -3,9 +3,9 @@ package blockstore import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" ) type unionBlockstore []Blockstore diff --git a/blockstore/union_test.go b/blockstore/union_test.go index 579489947..47aab852a 100644 --- a/blockstore/union_test.go +++ b/blockstore/union_test.go @@ -5,7 +5,7 @@ import ( "context" "testing" - blocks "github.com/ipfs/go-block-format" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" ) diff --git a/chain/events/state/mock/api.go b/chain/events/state/mock/api.go index cdec42659..680e304f5 100644 --- a/chain/events/state/mock/api.go +++ b/chain/events/state/mock/api.go @@ -4,8 +4,8 @@ import ( "context" "sync" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" diff --git a/chain/gen/genesis/genblock.go b/chain/gen/genesis/genblock.go index f26659cdf..930b3ccff 100644 --- a/chain/gen/genesis/genblock.go +++ b/chain/gen/genesis/genblock.go @@ -3,8 +3,8 @@ package genesis import ( "encoding/hex" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/multiformats/go-multihash" ) diff --git a/chain/store/messages.go b/chain/store/messages.go index 1ee1f8ad4..5ac62d394 100644 --- a/chain/store/messages.go +++ b/chain/store/messages.go @@ -3,10 +3,10 @@ package store import ( "context" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" + block "github.com/ipfs/go-libipfs/blocks" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" diff --git a/chain/store/snapshot.go b/chain/store/snapshot.go index e90a60611..36435152e 100644 --- a/chain/store/snapshot.go +++ b/chain/store/snapshot.go @@ -5,8 +5,8 @@ import ( "context" "io" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" carutil "github.com/ipld/go-car/util" carv2 "github.com/ipld/go-car/v2" diff --git a/chain/store/store.go b/chain/store/store.go index 2773f1ad3..754e3a123 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -12,11 +12,11 @@ import ( "time" lru "github.com/hashicorp/golang-lru" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/query" cbor "github.com/ipfs/go-ipld-cbor" + block "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "go.opencensus.io/stats" "go.opencensus.io/trace" diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index b8427e036..4c7d16a9a 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -8,9 +8,9 @@ import ( "time" lru "github.com/hashicorp/golang-lru" - blocks "github.com/ipfs/go-block-format" bserv "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/connmgr" diff --git a/chain/sub/incoming_test.go b/chain/sub/incoming_test.go index 8566391b9..d17b08825 100644 --- a/chain/sub/incoming_test.go +++ b/chain/sub/incoming_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/golang/mock/gomock" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" pubsub "github.com/libp2p/go-libp2p-pubsub" pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" diff --git a/chain/sync.go b/chain/sync.go index b0c8b50ff..db7b7fc04 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -11,10 +11,10 @@ import ( "github.com/Gurpartap/async" "github.com/hashicorp/go-multierror" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "github.com/libp2p/go-libp2p/core/connmgr" "github.com/libp2p/go-libp2p/core/peer" diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index e0b9e6b30..559569ba0 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -4,8 +4,8 @@ import ( "bytes" "math/big" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + block "github.com/ipfs/go-libipfs/blocks" "github.com/minio/blake2b-simd" "golang.org/x/xerrors" diff --git a/chain/types/message.go b/chain/types/message.go index 352548d0c..a25cd05b6 100644 --- a/chain/types/message.go +++ b/chain/types/message.go @@ -5,8 +5,8 @@ import ( "encoding/json" "fmt" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + block "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" diff --git a/chain/types/signedmessage.go b/chain/types/signedmessage.go index 168531714..dc867c5e5 100644 --- a/chain/types/signedmessage.go +++ b/chain/types/signedmessage.go @@ -4,8 +4,8 @@ import ( "bytes" "encoding/json" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + block "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" diff --git a/chain/types/tipset_key.go b/chain/types/tipset_key.go index 15e655da7..50753ffd2 100644 --- a/chain/types/tipset_key.go +++ b/chain/types/tipset_key.go @@ -7,8 +7,8 @@ import ( "io" "strings" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + block "github.com/ipfs/go-libipfs/blocks" typegen "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-state-types/abi" diff --git a/chain/vm/vm.go b/chain/vm/vm.go index dcebe2b17..f09864c2d 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -7,9 +7,9 @@ import ( "sync/atomic" "time" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" + block "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" mh "github.com/multiformats/go-multihash" cbg "github.com/whyrusleeping/cbor-gen" diff --git a/cmd/lotus-shed/datastore-vlog.go b/cmd/lotus-shed/datastore-vlog.go index 936d33849..af412df19 100644 --- a/cmd/lotus-shed/datastore-vlog.go +++ b/cmd/lotus-shed/datastore-vlog.go @@ -12,8 +12,8 @@ import ( "strings" "github.com/dgraph-io/badger/v2/y" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + block "github.com/ipfs/go-libipfs/blocks" "github.com/mitchellh/go-homedir" "github.com/multiformats/go-base32" "github.com/urfave/cli/v2" diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index 459de3383..d67fa4493 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -15,11 +15,11 @@ import ( "github.com/dgraph-io/badger/v2" "github.com/dgraph-io/badger/v2/pb" "github.com/dustin/go-humanize" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" ipld "github.com/ipfs/go-ipld-format" + block "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-merkledag" "github.com/ipld/go-car" "github.com/multiformats/go-base32" diff --git a/cmd/lotus-shed/import-car.go b/cmd/lotus-shed/import-car.go index 973e7b31b..4c636a3af 100644 --- a/cmd/lotus-shed/import-car.go +++ b/cmd/lotus-shed/import-car.go @@ -7,8 +7,8 @@ import ( "io" "os" - block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + block "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" "github.com/urfave/cli/v2" "golang.org/x/xerrors" diff --git a/cmd/tvx/stores.go b/cmd/tvx/stores.go index 9035c482a..b863ffa74 100644 --- a/cmd/tvx/stores.go +++ b/cmd/tvx/stores.go @@ -6,7 +6,6 @@ import ( "sync" "github.com/fatih/color" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" @@ -15,6 +14,7 @@ import ( offline "github.com/ipfs/go-ipfs-exchange-offline" cbor "github.com/ipfs/go-ipld-cbor" format "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-merkledag" "golang.org/x/xerrors" diff --git a/conformance/runner.go b/conformance/runner.go index b6bb5a164..ff738a4a5 100644 --- a/conformance/runner.go +++ b/conformance/runner.go @@ -14,12 +14,12 @@ import ( "github.com/fatih/color" "github.com/hashicorp/go-multierror" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" offline "github.com/ipfs/go-ipfs-exchange-offline" format "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-merkledag" "github.com/ipld/go-car" diff --git a/gateway/node.go b/gateway/node.go index 4f57d1d6a..00a83df96 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "go.opencensus.io/stats" "golang.org/x/time/rate" diff --git a/gateway/proxy_fil.go b/gateway/proxy_fil.go index 0e53130fb..1f6ee2ccc 100644 --- a/gateway/proxy_fil.go +++ b/gateway/proxy_fil.go @@ -3,8 +3,8 @@ package gateway import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" diff --git a/go.mod b/go.mod index f74149438..777eabd86 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,6 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/ipfs/bbloom v0.0.4 github.com/ipfs/go-bitswap v0.10.2 - github.com/ipfs/go-block-format v0.0.3 github.com/ipfs/go-blockservice v0.4.0 github.com/ipfs/go-cid v0.3.2 github.com/ipfs/go-cidutil v0.1.0 @@ -100,6 +99,7 @@ require ( github.com/ipfs/go-ipfs-util v0.0.2 github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-format v0.4.0 + github.com/ipfs/go-libipfs v0.3.0 github.com/ipfs/go-log/v2 v2.5.1 github.com/ipfs/go-merkledag v0.8.1 github.com/ipfs/go-metrics-interface v0.0.1 @@ -115,7 +115,7 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/koalacxr/quantile v0.0.1 github.com/libp2p/go-buffer-pool v0.1.0 - github.com/libp2p/go-libp2p v0.23.2 + github.com/libp2p/go-libp2p v0.23.4 github.com/libp2p/go-libp2p-consensus v0.0.1 github.com/libp2p/go-libp2p-gorpc v0.4.0 github.com/libp2p/go-libp2p-kad-dht v0.18.0 @@ -130,7 +130,7 @@ require ( github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.7.0 + github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/multiformats/go-multibase v0.1.1 github.com/multiformats/go-multihash v0.2.1 @@ -140,7 +140,7 @@ require ( github.com/prometheus/client_golang v1.13.0 github.com/raulk/clock v1.1.0 github.com/raulk/go-watchdog v1.3.0 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/urfave/cli/v2 v2.16.3 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba @@ -234,6 +234,7 @@ require ( github.com/huin/goupnp v1.0.3 // indirect github.com/iancoleman/orderedmap v0.1.0 // indirect github.com/ipfs/go-bitfield v1.0.0 // indirect + github.com/ipfs/go-block-format v0.1.1 // indirect github.com/ipfs/go-filestore v1.2.0 // indirect github.com/ipfs/go-ipfs-cmds v0.7.0 // indirect github.com/ipfs/go-ipfs-config v0.18.0 // indirect diff --git a/go.sum b/go.sum index 4d8dc0630..f7cf3a6b2 100644 --- a/go.sum +++ b/go.sum @@ -691,8 +691,9 @@ github.com/ipfs/go-bitswap v0.10.2 h1:B81RIwkTnIvSYT1ZCzxjYTeF0Ek88xa9r1AMpTfk+9 github.com/ipfs/go-bitswap v0.10.2/go.mod h1:+fZEvycxviZ7c+5KlKwTzLm0M28g2ukCPqiuLfJk4KA= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= -github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/dDTpMc= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= +github.com/ipfs/go-block-format v0.1.1 h1:129vSO3zwbsYADcyQWcOYiuCpAqt462SFfqFHdFJhhI= +github.com/ipfs/go-block-format v0.1.1/go.mod h1:+McEIT+g52p+zz5xGAABGSOKrzmrdX97bc0USBdWPUs= github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-blockservice v0.2.1/go.mod h1:k6SiwmgyYgs4M/qt+ww6amPeUH9EISLRBnvUurKJhi8= @@ -820,6 +821,8 @@ github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2 github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A= github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= +github.com/ipfs/go-libipfs v0.3.0 h1:YvzFWGcl88eiz2tjOheNqaeQseH+dW3fUKrSaHOG/dU= +github.com/ipfs/go-libipfs v0.3.0/go.mod h1:pSUHZ5qPJTAidsxe9bAeHp3KIiw2ODEW2a2kM3v+iXI= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= @@ -1039,8 +1042,8 @@ github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2 github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m2kJVru3rM= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.19.4/go.mod h1:MIt8y481VDhUe4ErWi1a4bvt/CjjFfOq6kZTothWIXY= -github.com/libp2p/go-libp2p v0.23.2 h1:yqyTeKQJyofWXxEv/eEVUvOrGdt/9x+0PIQ4N1kaxmE= -github.com/libp2p/go-libp2p v0.23.2/go.mod h1:s9DEa5NLR4g+LZS+md5uGU4emjMWFiqkZr6hBTY8UxI= +github.com/libp2p/go-libp2p v0.23.4 h1:hWi9XHSOVFR1oDWRk7rigfyA4XNMuYL20INNybP9LP8= +github.com/libp2p/go-libp2p v0.23.4/go.mod h1:s9DEa5NLR4g+LZS+md5uGU4emjMWFiqkZr6hBTY8UxI= github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= @@ -1496,8 +1499,8 @@ github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9x github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= -github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc= -github.com/multiformats/go-multiaddr v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= +github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1793,8 +1796,9 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1803,8 +1807,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= diff --git a/itests/deals_partial_retrieval_dm-level_test.go b/itests/deals_partial_retrieval_dm-level_test.go index f56d64026..246541229 100644 --- a/itests/deals_partial_retrieval_dm-level_test.go +++ b/itests/deals_partial_retrieval_dm-level_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" textselector "github.com/ipld/go-ipld-selector-text-lite" "github.com/stretchr/testify/require" diff --git a/itests/deals_partial_retrieval_test.go b/itests/deals_partial_retrieval_test.go index 0bbf23da0..e2dae9aff 100644 --- a/itests/deals_partial_retrieval_test.go +++ b/itests/deals_partial_retrieval_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" "github.com/stretchr/testify/require" "golang.org/x/xerrors" diff --git a/markets/dagstore/blockstore.go b/markets/dagstore/blockstore.go index 317cb08b9..593204ec8 100644 --- a/markets/dagstore/blockstore.go +++ b/markets/dagstore/blockstore.go @@ -4,9 +4,9 @@ import ( "context" "io" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/dagstore" diff --git a/markets/storageadapter/api.go b/markets/storageadapter/api.go index b93ffdfbb..3105f2261 100644 --- a/markets/storageadapter/api.go +++ b/markets/storageadapter/api.go @@ -3,9 +3,9 @@ package storageadapter import ( "context" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" + blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" diff --git a/markets/storageadapter/ondealsectorcommitted_test.go b/markets/storageadapter/ondealsectorcommitted_test.go index 1d7519ff9..592c22db7 100644 --- a/markets/storageadapter/ondealsectorcommitted_test.go +++ b/markets/storageadapter/ondealsectorcommitted_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" "golang.org/x/xerrors" diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index 8448a542e..17444ca58 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -11,12 +11,12 @@ import ( "strings" "sync" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "github.com/ipfs/go-merkledag" mh "github.com/multiformats/go-multihash" From 7a4205ac36d4a4c963377f059f25b0dd8fa92402 Mon Sep 17 00:00:00 2001 From: Jorropo Date: Fri, 27 Jan 2023 23:01:51 +0100 Subject: [PATCH 16/25] chore: node: migrate go-bitswap to go-libipfs/bitswap This was migrated in https://github.com/ipfs/go-libipfs/pull/63. (cherry picked from commit d060df2fb901faee701f711e02ea3a3ad6b8ef7f) --- go.mod | 5 ++--- go.sum | 8 ++++---- node/modules/chain.go | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 777eabd86..953f862df 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,6 @@ require ( github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/ipfs/bbloom v0.0.4 - github.com/ipfs/go-bitswap v0.10.2 github.com/ipfs/go-blockservice v0.4.0 github.com/ipfs/go-cid v0.3.2 github.com/ipfs/go-cidutil v0.1.0 @@ -95,11 +94,11 @@ require ( github.com/ipfs/go-ipfs-exchange-offline v0.3.0 github.com/ipfs/go-ipfs-files v0.1.1 github.com/ipfs/go-ipfs-http-client v0.4.0 - github.com/ipfs/go-ipfs-routing v0.2.1 + github.com/ipfs/go-ipfs-routing v0.3.0 github.com/ipfs/go-ipfs-util v0.0.2 github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-format v0.4.0 - github.com/ipfs/go-libipfs v0.3.0 + github.com/ipfs/go-libipfs v0.4.0 github.com/ipfs/go-log/v2 v2.5.1 github.com/ipfs/go-merkledag v0.8.1 github.com/ipfs/go-metrics-interface v0.0.1 diff --git a/go.sum b/go.sum index f7cf3a6b2..04250657b 100644 --- a/go.sum +++ b/go.sum @@ -688,7 +688,6 @@ github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiL github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= github.com/ipfs/go-bitswap v0.6.0/go.mod h1:Hj3ZXdOC5wBJvENtdqsixmzzRukqd8EHLxZLZc3mzRA= github.com/ipfs/go-bitswap v0.10.2 h1:B81RIwkTnIvSYT1ZCzxjYTeF0Ek88xa9r1AMpTfk+9Q= -github.com/ipfs/go-bitswap v0.10.2/go.mod h1:+fZEvycxviZ7c+5KlKwTzLm0M28g2ukCPqiuLfJk4KA= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= @@ -798,8 +797,9 @@ github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= -github.com/ipfs/go-ipfs-routing v0.2.1 h1:E+whHWhJkdN9YeoHZNj5itzc+OR292AJ2uE9FFiW0BY= github.com/ipfs/go-ipfs-routing v0.2.1/go.mod h1:xiNNiwgjmLqPS1cimvAw6EyB9rkVDbiocA4yY+wRNLM= +github.com/ipfs/go-ipfs-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc= +github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= @@ -821,8 +821,8 @@ github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2 github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A= github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= -github.com/ipfs/go-libipfs v0.3.0 h1:YvzFWGcl88eiz2tjOheNqaeQseH+dW3fUKrSaHOG/dU= -github.com/ipfs/go-libipfs v0.3.0/go.mod h1:pSUHZ5qPJTAidsxe9bAeHp3KIiw2ODEW2a2kM3v+iXI= +github.com/ipfs/go-libipfs v0.4.0 h1:TkUxJGjtPnSzAgkw7VjS0/DBay3MPjmTBa4dGdUQCDE= +github.com/ipfs/go-libipfs v0.4.0/go.mod h1:XsU2cP9jBhDrXoJDe0WxikB8XcVmD3k2MEZvB3dbYu8= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= diff --git a/node/modules/chain.go b/node/modules/chain.go index 6129f0345..f304ab135 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -4,9 +4,9 @@ import ( "context" "time" - "github.com/ipfs/go-bitswap" - "github.com/ipfs/go-bitswap/network" "github.com/ipfs/go-blockservice" + "github.com/ipfs/go-libipfs/bitswap" + "github.com/ipfs/go-libipfs/bitswap/network" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/routing" "go.uber.org/fx" From 198217d6bc96544e661440a9a5218e7f3ed2ab88 Mon Sep 17 00:00:00 2001 From: Jorropo Date: Fri, 17 Feb 2023 18:46:58 +0100 Subject: [PATCH 17/25] chore: all: bump go-libipfs to v0.4.1 --- go.mod | 6 +++--- go.sum | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 953f862df..1d74e1a23 100644 --- a/go.mod +++ b/go.mod @@ -98,7 +98,7 @@ require ( github.com/ipfs/go-ipfs-util v0.0.2 github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-format v0.4.0 - github.com/ipfs/go-libipfs v0.4.0 + github.com/ipfs/go-libipfs v0.4.1 github.com/ipfs/go-log/v2 v2.5.1 github.com/ipfs/go-merkledag v0.8.1 github.com/ipfs/go-metrics-interface v0.0.1 @@ -239,12 +239,12 @@ require ( github.com/ipfs/go-ipfs-config v0.18.0 // indirect github.com/ipfs/go-ipfs-delay v0.0.1 // indirect github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect - github.com/ipfs/go-ipfs-pq v0.0.2 // indirect + github.com/ipfs/go-ipfs-pq v0.0.3 // indirect github.com/ipfs/go-ipld-legacy v0.1.1 // indirect github.com/ipfs/go-ipns v0.3.0 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-path v0.3.0 // indirect - github.com/ipfs/go-peertaskqueue v0.8.0 // indirect + github.com/ipfs/go-peertaskqueue v0.8.1 // indirect github.com/ipfs/go-verifcid v0.0.2 // indirect github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0 // indirect github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 // indirect diff --git a/go.sum b/go.sum index 04250657b..948e87ebb 100644 --- a/go.sum +++ b/go.sum @@ -793,8 +793,9 @@ github.com/ipfs/go-ipfs-http-client v0.4.0/go.mod h1:NXzPUKt/QVCuR74a8angJCGOSLP github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= +github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE= +github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= github.com/ipfs/go-ipfs-routing v0.2.1/go.mod h1:xiNNiwgjmLqPS1cimvAw6EyB9rkVDbiocA4yY+wRNLM= @@ -821,8 +822,8 @@ github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2 github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A= github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= -github.com/ipfs/go-libipfs v0.4.0 h1:TkUxJGjtPnSzAgkw7VjS0/DBay3MPjmTBa4dGdUQCDE= -github.com/ipfs/go-libipfs v0.4.0/go.mod h1:XsU2cP9jBhDrXoJDe0WxikB8XcVmD3k2MEZvB3dbYu8= +github.com/ipfs/go-libipfs v0.4.1 h1:tyu3RRMKFQUyUQt5jyt5SmDnls93H4Tr3HifL50zihg= +github.com/ipfs/go-libipfs v0.4.1/go.mod h1:Ad8ybPqwCkl2cNiNUMvM/iaVc/5bwNpHu8RPZ5te1hw= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= @@ -863,8 +864,8 @@ github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= -github.com/ipfs/go-peertaskqueue v0.8.0 h1:JyNO144tfu9bx6Hpo119zvbEL9iQ760FHOiJYsUjqaU= -github.com/ipfs/go-peertaskqueue v0.8.0/go.mod h1:cz8hEnnARq4Du5TGqiWKgMr/BOSQ5XOgMOh1K5YYKKM= +github.com/ipfs/go-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg= +github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= From dbcf30470f8ddb1e916ab230dee4bd7a97a9f39e Mon Sep 17 00:00:00 2001 From: mike seiler Date: Fri, 17 Feb 2023 11:16:40 -0700 Subject: [PATCH 18/25] clean up comment remove print --- gen/bundle/bundle.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index a1eab4e04..bc038569d 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -46,9 +46,9 @@ func main() { } var metadataSpecificVersion []*build.BuiltinActorsMetadata - // see ./build/actors/pack.sh - // expected args are git bundle tag then number of per network overrides + // expected args are: + // $(GOCC) run ./gen/bundle $(VERSION) $(RELEASE) $(RELEASE_OVERRIDES) // overrides are in the format network_name=override if len(os.Args) > 1 { @@ -67,7 +67,6 @@ func main() { } else { m.BundleGitTag = os.Args[2] } - fmt.Println("hi") metadataSpecificVersion = append(metadataSpecificVersion, m) } } From 30615a4ed6963bc83f6d3f1ad2180b707120ab94 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Feb 2023 10:36:30 -0800 Subject: [PATCH 19/25] feat: eth: return revert data on failed gas estimation (#10298) Unfortunately, we need to execute the message twice to get this (unless we want to change some APIs). But it's unlikely to be a performance issue and will definitely help people debug failures. --- itests/fevm_test.go | 21 +++++++++++++++------ node/impl/full/eth.go | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/itests/fevm_test.go b/itests/fevm_test.go index d9c0019de..940d56ef1 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -901,14 +901,23 @@ func TestFEVMErrorParsing(t *testing.T) { "failCustom()": customError, } { sig := sig - expected := expected + expected := fmt.Sprintf("exit 33, revert reason: %s, vm error", expected) t.Run(sig, func(t *testing.T) { entryPoint := kit.CalcFuncSignature(sig) - _, err := e.EthCall(ctx, ethtypes.EthCall{ - To: &contractAddrEth, - Data: entryPoint, - }, "latest") - require.ErrorContains(t, err, fmt.Sprintf("exit 33, revert reason: %s, vm error", expected)) + t.Run("EthCall", func(t *testing.T) { + _, err := e.EthCall(ctx, ethtypes.EthCall{ + To: &contractAddrEth, + Data: entryPoint, + }, "latest") + require.ErrorContains(t, err, expected) + }) + t.Run("EthEstimateGas", func(t *testing.T) { + _, err := e.EthEstimateGas(ctx, ethtypes.EthCall{ + To: &contractAddrEth, + Data: entryPoint, + }) + require.ErrorContains(t, err, expected) + }) }) } } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 454b3eca5..2f50d873e 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -888,12 +888,22 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et msg.GasLimit = 0 ts := a.Chain.GetHeaviestTipSet() - msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key()) + gassedMsg, err := a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key()) if err != nil { + // On failure, GasEstimateMessageGas doesn't actually return the invocation result, + // it just returns an error. That means we can't get the revert reason. + // + // So we re-execute the message with EthCall (well, applyMessage which contains the + // guts of EthCall). This will give us an ethereum specific error with revert + // information. + msg.GasLimit = build.BlockGasLimit + if _, err2 := a.applyMessage(ctx, msg, ts.Key()); err2 != nil { + err = err2 + } return ethtypes.EthUint64(0), xerrors.Errorf("failed to estimate gas: %w", err) } - expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, msg, ts) + expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, gassedMsg, ts) if err != nil { log.Errorw("expected gas", "err", err) } From a3bc65ba052ab37a1f34653c3053894d147a4f31 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 16 Feb 2023 20:07:20 -0800 Subject: [PATCH 20/25] fix: eth: return the correct nonce from EthGetTransactionCount EVM contracts track this number internally. fixes https://github.com/filecoin-project/lotus/issues/10255 --- chain/actors/builtin/evm/actor.go.template | 1 + chain/actors/builtin/evm/evm.go | 1 + chain/actors/builtin/evm/state.go.template | 6 +++++ chain/actors/builtin/evm/v10.go | 4 ++++ itests/eth_bytecode_test.go | 27 +++++++++++++++++++--- node/impl/full/eth.go | 24 +++++++++++++++++++ 6 files changed, 60 insertions(+), 3 deletions(-) diff --git a/chain/actors/builtin/evm/actor.go.template b/chain/actors/builtin/evm/actor.go.template index aa23b5f11..62da06867 100644 --- a/chain/actors/builtin/evm/actor.go.template +++ b/chain/actors/builtin/evm/actor.go.template @@ -48,6 +48,7 @@ type State interface { cbor.Marshaler Nonce() (uint64, error) + IsAlive() (bool, error) GetState() interface{} GetBytecode() ([]byte, error) diff --git a/chain/actors/builtin/evm/evm.go b/chain/actors/builtin/evm/evm.go index f55a2177d..f214cdc13 100644 --- a/chain/actors/builtin/evm/evm.go +++ b/chain/actors/builtin/evm/evm.go @@ -48,6 +48,7 @@ type State interface { cbor.Marshaler Nonce() (uint64, error) + IsAlive() (bool, error) GetState() interface{} GetBytecode() ([]byte, error) diff --git a/chain/actors/builtin/evm/state.go.template b/chain/actors/builtin/evm/state.go.template index eb55a8463..f193733d1 100644 --- a/chain/actors/builtin/evm/state.go.template +++ b/chain/actors/builtin/evm/state.go.template @@ -4,6 +4,8 @@ import ( "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/go-state-types/abi" evm{{.v}} "github.com/filecoin-project/go-state-types/builtin{{.import}}evm" ) @@ -40,6 +42,10 @@ func (s *state{{.v}}) Nonce() (uint64, error) { return s.State.Nonce, nil } +func (s *state{{.v}}) IsAlive() (bool, error) { + return s.State.Tombstone == nil, nil +} + func (s *state{{.v}}) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/evm/v10.go b/chain/actors/builtin/evm/v10.go index 77a09037b..d467aa187 100644 --- a/chain/actors/builtin/evm/v10.go +++ b/chain/actors/builtin/evm/v10.go @@ -41,6 +41,10 @@ func (s *state10) Nonce() (uint64, error) { return s.State.Nonce, nil } +func (s *state10) IsAlive() (bool, error) { + return s.State.Tombstone == nil, nil +} + func (s *state10) GetState() interface{} { return &s.State } diff --git a/itests/eth_bytecode_test.go b/itests/eth_bytecode_test.go index 4d03a0f6d..a8a75e83f 100644 --- a/itests/eth_bytecode_test.go +++ b/itests/eth_bytecode_test.go @@ -10,15 +10,16 @@ import ( "github.com/stretchr/testify/require" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/itests/kit" ) -// TestGetCode ensures that GetCode returns the correct results for: +// TestGetCodeAndNonce ensures that GetCode and GetTransactionCount return the correct results for: // 1. Placeholders. // 2. Non-existent actors. // 3. Normal EVM actors. // 4. Self-destructed EVM actors. -func TestGetCode(t *testing.T) { +func TestGetCodeAndNonce(t *testing.T) { kit.QuietMiningLogs() blockTime := 100 * time.Millisecond @@ -28,7 +29,7 @@ func TestGetCode(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - // Accounts should have empty code. + // Accounts should have empty code, empty nonce. { // A random eth address should have no code. _, ethAddr, filAddr := client.EVM().NewAccount() @@ -36,6 +37,11 @@ func TestGetCode(t *testing.T) { require.NoError(t, err) require.Empty(t, bytecode) + // Nonce should also be zero + nonce, err := client.EVM().EthGetTransactionCount(ctx, ethAddr, "latest") + require.NoError(t, err) + require.Zero(t, nonce) + // send some funds to the account. kit.SendFunds(ctx, t, client, filAddr, types.FromFil(10)) @@ -43,6 +49,11 @@ func TestGetCode(t *testing.T) { bytecode, err = client.EVM().EthGetCode(ctx, ethAddr, "latest") require.NoError(t, err) require.Empty(t, bytecode) + + // Nonce should still be zero. + nonce, err = client.EVM().EthGetTransactionCount(ctx, ethAddr, "latest") + require.NoError(t, err) + require.Zero(t, nonce) } // Check contract code. @@ -61,6 +72,11 @@ func TestGetCode(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, bytecode) + // Nonce should be one. + nonce, err := client.EVM().EthGetTransactionCount(ctx, contractAddr, "latest") + require.NoError(t, err) + require.Equal(t, ethtypes.EthUint64(1), nonce) + // Destroy it. _, _, err = client.EVM().InvokeContractByFuncName(ctx, client.DefaultKey.Address, contractFilAddr, "destroy()", nil) require.NoError(t, err) @@ -69,6 +85,11 @@ func TestGetCode(t *testing.T) { bytecode, err = client.EVM().EthGetCode(ctx, contractAddr, "latest") require.NoError(t, err) require.Empty(t, bytecode) + + // Nonce should go back to zero + nonce, err = client.EVM().EthGetTransactionCount(ctx, contractAddr, "latest") + require.NoError(t, err) + require.Zero(t, nonce) } } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 454b3eca5..552223343 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -31,6 +31,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin" + builtinevm "github.com/filecoin-project/lotus/chain/actors/builtin/evm" "github.com/filecoin-project/lotus/chain/ethhashlookup" "github.com/filecoin-project/lotus/chain/events/filter" "github.com/filecoin-project/lotus/chain/messagepool" @@ -367,6 +368,29 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender ethtypes. return ethtypes.EthUint64(0), xerrors.Errorf("cannot parse block param: %s", blkParam) } + // First, handle the case where the "sender" is an EVM actor. + actor, err := a.StateManager.LoadActor(ctx, addr, ts) + if err != nil { + if xerrors.Is(err, types.ErrActorNotFound) { + return 0, nil + } + return 0, xerrors.Errorf("failed to lookup contract %s: %w", sender, err) + } + + if builtinactors.IsEvmActor(actor.Code) { + evmState, err := builtinevm.Load(a.Chain.ActorStore(ctx), actor) + if err != nil { + return 0, xerrors.Errorf("failed to load evm state: %w", err) + } + if alive, err := evmState.IsAlive(); err != nil { + return 0, err + } else if !alive { + return 0, nil + } + nonce, err := evmState.Nonce() + return ethtypes.EthUint64(nonce), err + } + nonce, err := a.Mpool.GetNonce(ctx, addr, ts.Key()) if err != nil { return ethtypes.EthUint64(0), nil From 4dedced1752e7fefebb3196b98ed6619bb447c99 Mon Sep 17 00:00:00 2001 From: mike seiler Date: Fri, 17 Feb 2023 11:52:40 -0700 Subject: [PATCH 21/25] lintfix --- gen/bundle/bundle.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index bc038569d..d3e5ebf6b 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -47,7 +47,7 @@ func main() { var metadataSpecificVersion []*build.BuiltinActorsMetadata // see ./build/actors/pack.sh - // expected args are: + // expected args are: // $(GOCC) run ./gen/bundle $(VERSION) $(RELEASE) $(RELEASE_OVERRIDES) // overrides are in the format network_name=override From f41435d2858a00bf465252aa7f003c74b731bd0e Mon Sep 17 00:00:00 2001 From: Aayush Date: Fri, 17 Feb 2023 14:17:30 -0500 Subject: [PATCH 22/25] feat: bundle: only write git tags for newly packed bundles --- gen/bundle/bundle.go | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index d3e5ebf6b..f57ced15b 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -1,8 +1,8 @@ package main import ( - "fmt" "os" + "strconv" "strings" "text/template" @@ -40,38 +40,42 @@ func splitOverride(override string) (string, string) { } func main() { + // read metadata from the embedded bundle, includes all info except git tags metadata, err := build.ReadEmbeddedBuiltinActorsMetadata() if err != nil { panic(err) } - var metadataSpecificVersion []*build.BuiltinActorsMetadata - // see ./build/actors/pack.sh - // expected args are: - // $(GOCC) run ./gen/bundle $(VERSION) $(RELEASE) $(RELEASE_OVERRIDES) - // overrides are in the format network_name=override - + // IF args have been provided, extract git tag info from them, otherwise + // rely on previously embedded metadata for git tags. if len(os.Args) > 1 { - version := os.Args[1] + // see ./build/actors/pack.sh + // (optional) expected args are: + // $(GOCC) run ./gen/bundle $(VERSION) $(RELEASE) $(RELEASE_OVERRIDES) + // overrides are in the format network_name=override + gitTag := os.Args[2] + packedActorsVersion, err := strconv.Atoi(os.Args[1][1:]) + if err != nil { + panic(err) + } + overrides := map[string]string{} for _, override := range os.Args[3:] { k, v := splitOverride(override) overrides[k] = v } for _, m := range metadata { - if strings.HasPrefix(version, fmt.Sprintf("v%d", m.Version)) { - // correct version + if int(m.Version) == packedActorsVersion { override, ok := overrides[m.Network] if ok { m.BundleGitTag = override } else { - m.BundleGitTag = os.Args[2] + m.BundleGitTag = gitTag } - metadataSpecificVersion = append(metadataSpecificVersion, m) + } else { + m.BundleGitTag = getOldGitTagFromEmbeddedMetadata(m) } } - metadata = metadataSpecificVersion - } fi, err := os.Create("./build/builtin_actors_gen.go") @@ -85,3 +89,14 @@ func main() { panic(err) } } + +func getOldGitTagFromEmbeddedMetadata(m *build.BuiltinActorsMetadata) string { + for _, v := range build.EmbeddedBuiltinActorsMetadata { + // if we agree on the manifestCid for the previously embedded metadata, use the previously set tag + if m.Version == v.Version && m.Network == v.Network && m.ManifestCid == v.ManifestCid { + return m.BundleGitTag + } + } + + return "" +} From 49cd428c437e753bed411a8d90e1a7a3c514ac0c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Feb 2023 11:17:35 -0800 Subject: [PATCH 23/25] nit: put evm case in a block --- node/impl/full/eth.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 552223343..f0df89bff 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -369,26 +369,28 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender ethtypes. } // First, handle the case where the "sender" is an EVM actor. - actor, err := a.StateManager.LoadActor(ctx, addr, ts) - if err != nil { - if xerrors.Is(err, types.ErrActorNotFound) { - return 0, nil - } - return 0, xerrors.Errorf("failed to lookup contract %s: %w", sender, err) - } - - if builtinactors.IsEvmActor(actor.Code) { - evmState, err := builtinevm.Load(a.Chain.ActorStore(ctx), actor) + { + actor, err := a.StateManager.LoadActor(ctx, addr, ts) if err != nil { - return 0, xerrors.Errorf("failed to load evm state: %w", err) + if xerrors.Is(err, types.ErrActorNotFound) { + return 0, nil + } + return 0, xerrors.Errorf("failed to lookup contract %s: %w", sender, err) } - if alive, err := evmState.IsAlive(); err != nil { - return 0, err - } else if !alive { - return 0, nil + + if builtinactors.IsEvmActor(actor.Code) { + evmState, err := builtinevm.Load(a.Chain.ActorStore(ctx), actor) + if err != nil { + return 0, xerrors.Errorf("failed to load evm state: %w", err) + } + if alive, err := evmState.IsAlive(); err != nil { + return 0, err + } else if !alive { + return 0, nil + } + nonce, err := evmState.Nonce() + return ethtypes.EthUint64(nonce), err } - nonce, err := evmState.Nonce() - return ethtypes.EthUint64(nonce), err } nonce, err := a.Mpool.GetNonce(ctx, addr, ts.Key()) From 6c0f4cbd744205b7931f4ebd7ae706f061a92ca6 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Feb 2023 11:18:51 -0800 Subject: [PATCH 24/25] nit: actually, don't use blocks --- node/impl/full/eth.go | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index f0df89bff..0141f6a56 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -369,28 +369,23 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender ethtypes. } // First, handle the case where the "sender" is an EVM actor. - { - actor, err := a.StateManager.LoadActor(ctx, addr, ts) + if actor, err := a.StateManager.LoadActor(ctx, addr, ts); err != nil { + if xerrors.Is(err, types.ErrActorNotFound) { + return 0, nil + } + return 0, xerrors.Errorf("failed to lookup contract %s: %w", sender, err) + } else if builtinactors.IsEvmActor(actor.Code) { + evmState, err := builtinevm.Load(a.Chain.ActorStore(ctx), actor) if err != nil { - if xerrors.Is(err, types.ErrActorNotFound) { - return 0, nil - } - return 0, xerrors.Errorf("failed to lookup contract %s: %w", sender, err) + return 0, xerrors.Errorf("failed to load evm state: %w", err) } - - if builtinactors.IsEvmActor(actor.Code) { - evmState, err := builtinevm.Load(a.Chain.ActorStore(ctx), actor) - if err != nil { - return 0, xerrors.Errorf("failed to load evm state: %w", err) - } - if alive, err := evmState.IsAlive(); err != nil { - return 0, err - } else if !alive { - return 0, nil - } - nonce, err := evmState.Nonce() - return ethtypes.EthUint64(nonce), err + if alive, err := evmState.IsAlive(); err != nil { + return 0, err + } else if !alive { + return 0, nil } + nonce, err := evmState.Nonce() + return ethtypes.EthUint64(nonce), err } nonce, err := a.Mpool.GetNonce(ctx, addr, ts.Key()) From bad41c247a51916b096b93ade2bffe21e8a5255c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Feb 2023 12:02:00 -0800 Subject: [PATCH 25/25] fix: eth: cleanup error cases 1. Return an error on gas estimation failure instead of logging. 2. Return early when processing signed messages on failure instead of continuing. --- node/impl/full/eth.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 454b3eca5..5e18e7e77 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -895,7 +895,7 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, msg, ts) if err != nil { - log.Errorw("expected gas", "err", err) + return 0, xerrors.Errorf("gas search failed: %w", err) } return ethtypes.EthUint64(expectedGas), nil @@ -2157,11 +2157,13 @@ func (m *EthTxHashManager) ProcessSignedMessage(ctx context.Context, msg *types. ethTx, err := newEthTxFromSignedMessage(ctx, msg, m.StateAPI) if err != nil { log.Errorf("error converting filecoin message to eth tx: %s", err) + return } err = m.TransactionHashLookup.UpsertHash(ethTx.Hash, msg.Cid()) if err != nil { log.Errorf("error inserting tx mapping to db: %s", err) + return } }