From d71f5a7d12ef56270c43c7837ff6b3f30f50b009 Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Fri, 16 Dec 2022 12:54:50 -0500 Subject: [PATCH 1/8] Add cli to inspect Eth addresses and simulate calls --- chain/types/ethtypes/eth_types.go | 2 + cli/cmd.go | 1 + cli/eth.go | 169 ++++++++++++++++++++++++++++++ node/impl/full/eth.go | 2 +- 4 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 cli/eth.go diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index f9793e0543a..d06e217f0b4 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -253,6 +253,8 @@ func (ea EthAddress) ToFilecoinAddress() (address.Address, error) { return addr, nil } +// This API assumes that if an ID address is passed in, it doesn't have an equivalent +// delegated address func TryEthAddressFromFilecoinAddress(addr address.Address, allowId bool) (EthAddress, bool, error) { switch addr.Protocol() { case address.ID: diff --git a/cli/cmd.go b/cli/cmd.go index 79023917b46..6184d71ca0a 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -81,6 +81,7 @@ var Commands = []*cli.Command{ WithCategory("developer", LogCmd), WithCategory("developer", WaitApiCmd), WithCategory("developer", FetchParamCmd), + WithCategory("developer", EthCmd), WithCategory("network", NetCmd), WithCategory("network", SyncCmd), WithCategory("status", StatusCmd), diff --git a/cli/eth.go b/cli/eth.go new file mode 100644 index 00000000000..b75d9fa738c --- /dev/null +++ b/cli/eth.go @@ -0,0 +1,169 @@ +package cli + +import ( + "context" + "encoding/hex" + "fmt" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api/v0api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" +) + +var EthCmd = &cli.Command{ + Name: "eth", + Usage: "Query eth contract state", + Subcommands: []*cli.Command{ + EthGetAddressCmd, + EthCallSimulateCmd, + }, +} + +func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi v0api.FullNode) (ethtypes.EthAddress, address.Address, error) { + var faddr address.Address + var err error + + switch addr.Protocol() { + case address.BLS, address.SECP256K1: + faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) + case address.Actor, address.ID: + f0addr, err := fnapi.StateLookupID(ctx, addr, types.EmptyTSK) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + faddr, err = fnapi.StateAccountKey(ctx, f0addr, types.EmptyTSK) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + if faddr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 { + faddr = f0addr + } + case address.Delegated: + faddr = addr + default: + return ethtypes.EthAddress{}, addr, xerrors.Errorf("Filecoin address doesn't match known protocols") + } + + ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(faddr) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + + return ethAddr, faddr, nil +} + +var EthGetAddressCmd = &cli.Command{ + Name: "stat", + Usage: "Print eth/filecoin addrs and code cid", + ArgsUsage: "[faddr]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "filaddr", + Value: "", + Usage: "Filecoin address", + }, + &cli.StringFlag{ + Name: "ethaddr", + Value: "", + Usage: "Ethereum address", + }, + }, + Action: func(cctx *cli.Context) error { + + filaddr := cctx.String("filaddr") + ethaddr := cctx.String("ethaddr") + + var faddr address.Address + var eaddr ethtypes.EthAddress + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if filaddr != "" { + addr, err := address.NewFromString(filaddr) + if err != nil { + return err + } + eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api) + } else if ethaddr != "" { + addr, err := hex.DecodeString(ethaddr) + if err != nil { + return err + } + copy(eaddr[:], addr) + faddr, err = eaddr.ToFilecoinAddress() + if err != nil { + return err + } + } else { + return xerrors.Errorf("Neither filaddr or ethaddr specified") + } + + 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()) + + return nil + + }, +} + +var EthCallSimulateCmd = &cli.Command{ + Name: "call", + Usage: "Simulate an eth contract call", + ArgsUsage: "[from] [to] [params]", + Action: func(cctx *cli.Context) error { + + var fromEthAddr ethtypes.EthAddress + fromAddr, err := hex.DecodeString(cctx.Args().Get(0)) + if err != nil { + return err + } + copy(fromEthAddr[:], fromAddr) + + var toEthAddr ethtypes.EthAddress + toAddr, err := hex.DecodeString(cctx.Args().Get(1)) + if err != nil { + return err + } + copy(toEthAddr[:], toAddr) + + params, err := hex.DecodeString(cctx.Args().Get(2)) + if err != nil { + return err + } + + api, closer, err := GetFullNodeAPIV1(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + res, err := api.EthCall(ctx, ethtypes.EthCall{ + From: &fromEthAddr, + To: &toEthAddr, + Data: params, + }, "") + if err != nil { + fmt.Println("Eth call fails, return val: ", res) + return err + } + + fmt.Println("Result: ", res) + + return nil + + }, +} diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 2acea9b17ab..0c1549d820c 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -608,7 +608,7 @@ func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message) (res * return nil, xerrors.Errorf("CallWithGas failed: %w", err) } if res.MsgRct.ExitCode.IsError() { - return nil, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error) + return nil, xerrors.Errorf("message execution failed: exit %s, msg receipt: %s, reason: %s", res.MsgRct.ExitCode, res.MsgRct.Return, res.Error) } return res, nil } From 4b2ff01a55d22e7b77324fd3bb23c9e8be6cd02c Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Fri, 16 Dec 2022 13:03:27 -0500 Subject: [PATCH 2/8] make gen and lint --- cli/eth.go | 13 ++++++++-- documentation/en/cli-lotus.md | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/cli/eth.go b/cli/eth.go index b75d9fa738c..4f42fbbf9fa 100644 --- a/cli/eth.go +++ b/cli/eth.go @@ -4,12 +4,15 @@ import ( "context" "encoding/hex" "fmt" + + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" - "github.com/urfave/cli/v2" - "golang.org/x/xerrors" ) var EthCmd = &cli.Command{ @@ -28,6 +31,9 @@ func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi switch addr.Protocol() { case address.BLS, address.SECP256K1: faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } case address.Actor, address.ID: f0addr, err := fnapi.StateLookupID(ctx, addr, types.EmptyTSK) if err != nil { @@ -91,6 +97,9 @@ var EthGetAddressCmd = &cli.Command{ return err } eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api) + if err != nil { + return err + } } else if ethaddr != "" { addr, err := hex.DecodeString(ethaddr) if err != nil { diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 35bc11760d1..04297433b46 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -31,6 +31,7 @@ COMMANDS: log Manage logging wait-api Wait for lotus api to come online fetch-params Fetch proving parameters + eth Query eth contract state NETWORK: net Manage P2P Network sync Inspect or interact with the chain syncer @@ -2569,6 +2570,51 @@ OPTIONS: ``` +## lotus eth +``` +NAME: + lotus eth - Query eth contract state + +USAGE: + lotus eth command [command options] [arguments...] + +COMMANDS: + stat Print eth/filecoin addrs and code cid + call Simulate an eth contract call + help, h Shows a list of commands or help for one command + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus eth stat +``` +NAME: + lotus eth stat - Print eth/filecoin addrs and code cid + +USAGE: + lotus eth stat [command options] [faddr] + +OPTIONS: + --ethaddr value Ethereum address + --filaddr value Filecoin address + +``` + +### lotus eth call +``` +NAME: + lotus eth call - Simulate an eth contract call + +USAGE: + lotus eth call [command options] [from] [to] [params] + +OPTIONS: + --help, -h show help (default: false) + +``` + ## lotus net ``` NAME: From cbc61a274fa56509d928c538e4b992e0941f5eaf Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Fri, 16 Dec 2022 13:16:29 -0500 Subject: [PATCH 3/8] small correction on cli usage --- cli/eth.go | 2 +- documentation/en/cli-lotus.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/eth.go b/cli/eth.go index 4f42fbbf9fa..7377d723a43 100644 --- a/cli/eth.go +++ b/cli/eth.go @@ -63,7 +63,7 @@ func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi var EthGetAddressCmd = &cli.Command{ Name: "stat", Usage: "Print eth/filecoin addrs and code cid", - ArgsUsage: "[faddr]", + ArgsUsage: "", Flags: []cli.Flag{ &cli.StringFlag{ Name: "filaddr", diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 04297433b46..65f61cb45f3 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -2594,7 +2594,7 @@ NAME: lotus eth stat - Print eth/filecoin addrs and code cid USAGE: - lotus eth stat [command options] [faddr] + lotus eth stat [command options] [arguments...] OPTIONS: --ethaddr value Ethereum address From c2629b0a96f6900017c757a87031222f84032f8c Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Mon, 19 Dec 2022 12:49:45 -0500 Subject: [PATCH 4/8] Use StateGetActor instead of StateAccountKey --- cli/eth.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/eth.go b/cli/eth.go index 7377d723a43..98f9e62c6cc 100644 --- a/cli/eth.go +++ b/cli/eth.go @@ -35,16 +35,16 @@ func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi return ethtypes.EthAddress{}, addr, err } case address.Actor, address.ID: - f0addr, err := fnapi.StateLookupID(ctx, addr, types.EmptyTSK) + faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) if err != nil { return ethtypes.EthAddress{}, addr, err } - faddr, err = fnapi.StateAccountKey(ctx, f0addr, types.EmptyTSK) + fAct, err := fnapi.StateGetActor(ctx, faddr, types.EmptyTSK) if err != nil { return ethtypes.EthAddress{}, addr, err } - if faddr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 { - faddr = f0addr + if fAct.Address != nil && (*fAct.Address).Protocol() == address.Delegated { + faddr = *fAct.Address } case address.Delegated: faddr = addr From f14eda44687a6f2be2499494c4d4ae5dc117852e Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Mon, 19 Dec 2022 13:05:11 -0500 Subject: [PATCH 5/8] address comments --- cli/eth.go | 100 ++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/cli/eth.go b/cli/eth.go index 98f9e62c6cc..699e490960b 100644 --- a/cli/eth.go +++ b/cli/eth.go @@ -24,62 +24,23 @@ var EthCmd = &cli.Command{ }, } -func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi v0api.FullNode) (ethtypes.EthAddress, address.Address, error) { - var faddr address.Address - var err error - - switch addr.Protocol() { - case address.BLS, address.SECP256K1: - faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) - if err != nil { - return ethtypes.EthAddress{}, addr, err - } - case address.Actor, address.ID: - faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) - if err != nil { - return ethtypes.EthAddress{}, addr, err - } - fAct, err := fnapi.StateGetActor(ctx, faddr, types.EmptyTSK) - if err != nil { - return ethtypes.EthAddress{}, addr, err - } - if fAct.Address != nil && (*fAct.Address).Protocol() == address.Delegated { - faddr = *fAct.Address - } - case address.Delegated: - faddr = addr - default: - return ethtypes.EthAddress{}, addr, xerrors.Errorf("Filecoin address doesn't match known protocols") - } - - ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(faddr) - if err != nil { - return ethtypes.EthAddress{}, addr, err - } - - return ethAddr, faddr, nil -} - var EthGetAddressCmd = &cli.Command{ - Name: "stat", - Usage: "Print eth/filecoin addrs and code cid", - ArgsUsage: "", + Name: "stat", + Usage: "Print eth/filecoin addrs and code cid", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "filaddr", - Value: "", + Name: "filAddr", Usage: "Filecoin address", }, &cli.StringFlag{ - Name: "ethaddr", - Value: "", + Name: "ethAddr", Usage: "Ethereum address", }, }, Action: func(cctx *cli.Context) error { - filaddr := cctx.String("filaddr") - ethaddr := cctx.String("ethaddr") + filAddr := cctx.String("filAddr") + ethAddr := cctx.String("ethAddr") var faddr address.Address var eaddr ethtypes.EthAddress @@ -91,8 +52,8 @@ var EthGetAddressCmd = &cli.Command{ defer closer() ctx := ReqContext(cctx) - if filaddr != "" { - addr, err := address.NewFromString(filaddr) + if filAddr != "" { + addr, err := address.NewFromString(filAddr) if err != nil { return err } @@ -100,8 +61,11 @@ var EthGetAddressCmd = &cli.Command{ if err != nil { return err } - } else if ethaddr != "" { - addr, err := hex.DecodeString(ethaddr) + } else if ethAddr != "" { + if ethAddr[:2] == "0x" { + ethAddr = ethAddr[2:] + } + addr, err := hex.DecodeString(ethAddr) if err != nil { return err } @@ -111,7 +75,7 @@ var EthGetAddressCmd = &cli.Command{ return err } } else { - return xerrors.Errorf("Neither filaddr or ethaddr specified") + return xerrors.Errorf("Neither filAddr nor ethAddr specified") } actor, err := api.StateGetActor(ctx, faddr, types.EmptyTSK) @@ -176,3 +140,39 @@ var EthCallSimulateCmd = &cli.Command{ }, } + +func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi v0api.FullNode) (ethtypes.EthAddress, address.Address, error) { + var faddr address.Address + var err error + + switch addr.Protocol() { + case address.BLS, address.SECP256K1: + faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + case address.Actor, address.ID: + faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + fAct, err := fnapi.StateGetActor(ctx, faddr, types.EmptyTSK) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + if fAct.Address != nil && (*fAct.Address).Protocol() == address.Delegated { + faddr = *fAct.Address + } + case address.Delegated: + faddr = addr + default: + return ethtypes.EthAddress{}, addr, xerrors.Errorf("Filecoin address doesn't match known protocols") + } + + ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(faddr) + if err != nil { + return ethtypes.EthAddress{}, addr, err + } + + return ethAddr, faddr, nil +} From 8baa48256a6f3e4b867153bc667a6f1e1c319895 Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Mon, 19 Dec 2022 13:19:52 -0500 Subject: [PATCH 6/8] Address more comments --- cli/eth.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cli/eth.go b/cli/eth.go index 699e490960b..c3948fa2110 100644 --- a/cli/eth.go +++ b/cli/eth.go @@ -19,12 +19,12 @@ var EthCmd = &cli.Command{ Name: "eth", Usage: "Query eth contract state", Subcommands: []*cli.Command{ - EthGetAddressCmd, + EthGetInfoCmd, EthCallSimulateCmd, }, } -var EthGetAddressCmd = &cli.Command{ +var EthGetInfoCmd = &cli.Command{ Name: "stat", Usage: "Print eth/filecoin addrs and code cid", Flags: []cli.Flag{ @@ -98,19 +98,19 @@ var EthCallSimulateCmd = &cli.Command{ ArgsUsage: "[from] [to] [params]", Action: func(cctx *cli.Context) error { - var fromEthAddr ethtypes.EthAddress - fromAddr, err := hex.DecodeString(cctx.Args().Get(0)) + if cctx.NArg() != 3 { + return IncorrectNumArgs(cctx) + } + + fromEthAddr, err := ethtypes.EthAddressFromHex(cctx.Args().Get(0)) if err != nil { return err } - copy(fromEthAddr[:], fromAddr) - var toEthAddr ethtypes.EthAddress - toAddr, err := hex.DecodeString(cctx.Args().Get(1)) + toEthAddr, err := ethtypes.EthAddressFromHex(cctx.Args().Get(1)) if err != nil { return err } - copy(toEthAddr[:], toAddr) params, err := hex.DecodeString(cctx.Args().Get(2)) if err != nil { From c96608cd330e06114e39115128c88872a33a1d52 Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Mon, 19 Dec 2022 13:40:12 -0500 Subject: [PATCH 7/8] make gen and docsgen --- documentation/en/cli-lotus.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 65f61cb45f3..e5c27f9b29d 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -2597,8 +2597,8 @@ USAGE: lotus eth stat [command options] [arguments...] OPTIONS: - --ethaddr value Ethereum address - --filaddr value Filecoin address + --ethAddr value Ethereum address + --filAddr value Filecoin address ``` From d916253cb5dd30cac8c15b99bb4ed4faa3005206 Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Mon, 19 Dec 2022 14:41:46 -0500 Subject: [PATCH 8/8] small nit --- cli/eth.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cli/eth.go b/cli/eth.go index c3948fa2110..e977e29f61a 100644 --- a/cli/eth.go +++ b/cli/eth.go @@ -62,14 +62,10 @@ var EthGetInfoCmd = &cli.Command{ return err } } else if ethAddr != "" { - if ethAddr[:2] == "0x" { - ethAddr = ethAddr[2:] - } - addr, err := hex.DecodeString(ethAddr) + eaddr, err = ethtypes.EthAddressFromHex(ethAddr) if err != nil { return err } - copy(eaddr[:], addr) faddr, err = eaddr.ToFilecoinAddress() if err != nil { return err