Merge pull request #9897 from filecoin-project/sbansal/eth-state-cli
feat: cli: Add cli to inspect Eth addresses and simulate calls
This commit is contained in:
commit
3d3bce6702
@ -266,6 +266,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:
|
||||
|
@ -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),
|
||||
|
174
cli/eth.go
Normal file
174
cli/eth.go
Normal file
@ -0,0 +1,174 @@
|
||||
package cli
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
var EthCmd = &cli.Command{
|
||||
Name: "eth",
|
||||
Usage: "Query eth contract state",
|
||||
Subcommands: []*cli.Command{
|
||||
EthGetInfoCmd,
|
||||
EthCallSimulateCmd,
|
||||
},
|
||||
}
|
||||
|
||||
var EthGetInfoCmd = &cli.Command{
|
||||
Name: "stat",
|
||||
Usage: "Print eth/filecoin addrs and code cid",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "filAddr",
|
||||
Usage: "Filecoin address",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ethAddr",
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if ethAddr != "" {
|
||||
eaddr, err = ethtypes.EthAddressFromHex(ethAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
faddr, err = eaddr.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return xerrors.Errorf("Neither filAddr nor 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 {
|
||||
|
||||
if cctx.NArg() != 3 {
|
||||
return IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
fromEthAddr, err := ethtypes.EthAddressFromHex(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toEthAddr, err := ethtypes.EthAddressFromHex(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@ -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] [arguments...]
|
||||
|
||||
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:
|
||||
|
@ -706,7 +706,7 @@ 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, 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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user