Skip to content

Commit

Permalink
Merge pull request #5563 from filecoin-project/feat/eth-json-rpc
Browse files Browse the repository at this point in the history
feat: implement a few ethereum JSON-RPC API methods
  • Loading branch information
diwufeiwen authored Dec 14, 2022
2 parents 8b8674b + 4472afc commit 8b108ba
Show file tree
Hide file tree
Showing 23 changed files with 1,706 additions and 133 deletions.
6 changes: 6 additions & 0 deletions app/node/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/filecoin-project/venus-auth/jwtclient"
"github.com/filecoin-project/venus/app/submodule/dagservice"
"github.com/filecoin-project/venus/app/submodule/eth"
"github.com/filecoin-project/venus/app/submodule/network"

logging "github.com/ipfs/go-log"
Expand Down Expand Up @@ -165,6 +166,10 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
blockDelay := b.repo.Config().NetworkParams.BlockDelay
nd.common = common.NewCommonModule(nd.chain, nd.network, blockDelay)

if nd.eth, err = eth.NewEthSubModule(nd.chain); err != nil {
return nil, err
}

apiBuilder := NewBuilder()
apiBuilder.NameSpace("Filecoin")

Expand All @@ -181,6 +186,7 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
nd.paychan,
nd.market,
nd.common,
nd.eth,
)

if err != nil {
Expand Down
1 change: 1 addition & 0 deletions app/node/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Env struct {
MarketAPI v1api.IMarket
PaychAPI v1api.IPaychan
CommonAPI v1api.ICommon
EthAPI v1api.IETH
}

var _ cmds.Environment = (*Env)(nil)
Expand Down
4 changes: 4 additions & 0 deletions app/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/filecoin-project/venus/app/submodule/common"
configModule "github.com/filecoin-project/venus/app/submodule/config"
"github.com/filecoin-project/venus/app/submodule/dagservice"
"github.com/filecoin-project/venus/app/submodule/eth"
"github.com/filecoin-project/venus/app/submodule/market"
"github.com/filecoin-project/venus/app/submodule/mining"
"github.com/filecoin-project/venus/app/submodule/mpool"
Expand Down Expand Up @@ -95,6 +96,8 @@ type Node struct {

common *common.CommonModule

eth *eth.EthSubModule

//
// Jsonrpc
//
Expand Down Expand Up @@ -358,6 +361,7 @@ func (node *Node) createServerEnv(ctx context.Context) *Env {
MarketAPI: node.market.API(),
MultiSigAPI: &apiwrapper.WrapperV1IMultiSig{IMultiSig: node.multiSig.API(), IMessagePool: node.mpool.API()},
CommonAPI: node.common,
EthAPI: node.eth.API(),
}

return &env
Expand Down
29 changes: 29 additions & 0 deletions app/node/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,35 @@ func (builder *RPCBuilder) Build(version string, limiter *ratelimit.RateLimiter)
default:
panic("invalid version: " + version)
}
aliasETHAPI(server)

return server
}

func aliasETHAPI(rpcServer *jsonrpc.RPCServer) {
// TODO: use reflect to automatically register all the eth aliases
rpcServer.AliasMethod("eth_accounts", "Filecoin.EthAccounts")
rpcServer.AliasMethod("eth_blockNumber", "Filecoin.EthBlockNumber")
rpcServer.AliasMethod("eth_getBlockTransactionCountByNumber", "Filecoin.EthGetBlockTransactionCountByNumber")
rpcServer.AliasMethod("eth_getBlockTransactionCountByHash", "Filecoin.EthGetBlockTransactionCountByHash")

rpcServer.AliasMethod("eth_getBlockByHash", "Filecoin.EthGetBlockByHash")
rpcServer.AliasMethod("eth_getBlockByNumber", "Filecoin.EthGetBlockByNumber")
rpcServer.AliasMethod("eth_getTransactionByHash", "Filecoin.EthGetTransactionByHash")
rpcServer.AliasMethod("eth_getTransactionCount", "Filecoin.EthGetTransactionCount")
rpcServer.AliasMethod("eth_getTransactionReceipt", "Filecoin.EthGetTransactionReceipt")
rpcServer.AliasMethod("eth_getTransactionByBlockHashAndIndex", "Filecoin.EthGetTransactionByBlockHashAndIndex")
rpcServer.AliasMethod("eth_getTransactionByBlockNumberAndIndex", "Filecoin.EthGetTransactionByBlockNumberAndIndex")

rpcServer.AliasMethod("eth_getCode", "Filecoin.EthGetCode")
rpcServer.AliasMethod("eth_getStorageAt", "Filecoin.EthGetStorageAt")
rpcServer.AliasMethod("eth_getBalance", "Filecoin.EthGetBalance")
rpcServer.AliasMethod("eth_chainId", "Filecoin.EthChainId")
rpcServer.AliasMethod("eth_protocolVersion", "Filecoin.EthProtocolVersion")
rpcServer.AliasMethod("eth_maxPriorityFeePerGas", "Filecoin.EthMaxPriorityFeePerGas")
rpcServer.AliasMethod("eth_gasPrice", "Filecoin.EthGasPrice")
rpcServer.AliasMethod("eth_sendRawTransaction", "Filecoin.EthSendRawTransaction")

rpcServer.AliasMethod("net_version", "Filecoin.NetVersion")
rpcServer.AliasMethod("net_listening", "Filecoin.NetListening")
}
139 changes: 139 additions & 0 deletions app/submodule/eth/eth_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package eth

import (
"context"
"fmt"
"strconv"

"github.com/filecoin-project/go-state-types/abi"
v1 "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
"github.com/filecoin-project/venus/venus-shared/types"
)

type ethAPI struct {
em *EthSubModule
chain v1.IChain
}

func (a *ethAPI) EthBlockNumber(ctx context.Context) (types.EthInt, error) {
head, err := a.chain.ChainHead(ctx)
if err != nil {
return types.EthInt(0), err
}
return types.EthInt(head.Height()), nil
}

func (a *ethAPI) EthAccounts(context.Context) ([]types.EthAddress, error) {
// The lotus node is not expected to hold manage accounts, so we'll always return an empty array
return []types.EthAddress{}, nil
}

func (a *ethAPI) countTipsetMsgs(ctx context.Context, ts *types.TipSet) (int, error) {
msgs, err := a.em.chainModule.MessageStore.LoadTipSetMessage(ctx, ts)
if err != nil {
return 0, fmt.Errorf("error loading messages for tipset: %v: %w", ts, err)
}

return len(msgs), nil
}

func (a *ethAPI) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum types.EthInt) (types.EthInt, error) {
ts, err := a.em.chainModule.ChainReader.GetTipSetByHeight(ctx, nil, abi.ChainEpoch(blkNum), false)
if err != nil {
return types.EthInt(0), fmt.Errorf("error loading tipset %s: %w", ts, err)
}

count, err := a.countTipsetMsgs(ctx, ts)
return types.EthInt(count), err
}

func (a *ethAPI) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash types.EthHash) (types.EthInt, error) {
ts, err := a.em.chainModule.ChainReader.GetTipSetByCid(ctx, blkHash.ToCid())
if err != nil {
return types.EthInt(0), fmt.Errorf("error loading tipset %s: %w", ts, err)
}
count, err := a.countTipsetMsgs(ctx, ts)
return types.EthInt(count), err
}

func (a *ethAPI) EthGetBlockByHash(ctx context.Context, blkHash types.EthHash, fullTxInfo bool) (types.EthBlock, error) {
return types.EthBlock{}, nil
}

func (a *ethAPI) EthGetBlockByNumber(ctx context.Context, blkNum types.EthInt, fullTxInfo bool) (types.EthBlock, error) {
return types.EthBlock{}, nil
}

func (a *ethAPI) EthGetTransactionByHash(ctx context.Context, txHash types.EthHash) (types.EthTx, error) {
return types.EthTx{}, nil
}

func (a *ethAPI) EthGetTransactionCount(ctx context.Context, sender types.EthAddress, blkParam string) (types.EthInt, error) {
return types.EthInt(0), nil
}

func (a *ethAPI) EthGetTransactionReceipt(ctx context.Context, blkHash types.EthHash) (types.EthTxReceipt, error) {
return types.EthTxReceipt{}, nil
}

func (a *ethAPI) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash types.EthHash, txIndex types.EthInt) (types.EthTx, error) {
return types.EthTx{}, nil
}

func (a *ethAPI) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum types.EthInt, txIndex types.EthInt) (types.EthTx, error) {
return types.EthTx{}, nil
}

// EthGetCode returns string value of the compiled bytecode
func (a *ethAPI) EthGetCode(ctx context.Context, address types.EthAddress) (string, error) {
return "", nil
}

func (a *ethAPI) EthGetStorageAt(ctx context.Context, address types.EthAddress, position types.EthInt, blkParam string) (string, error) {
return "", nil
}

func (a *ethAPI) EthGetBalance(ctx context.Context, address types.EthAddress, blkParam string) (types.EthBigInt, error) {
filAddr, err := address.ToFilecoinAddress()
if err != nil {
return types.EthBigInt{}, err
}

actor, err := a.chain.StateGetActor(ctx, filAddr, types.EmptyTSK)
if err != nil {
return types.EthBigInt{}, err
}

return types.EthBigInt{Int: actor.Balance.Int}, nil
}

func (a *ethAPI) EthChainId(ctx context.Context) (types.EthInt, error) {
return types.EthInt(0), nil
}

func (a *ethAPI) NetVersion(ctx context.Context) (string, error) {
// Note that networkId is not encoded in hex
nv, err := a.chain.StateNetworkVersion(ctx, types.EmptyTSK)
if err != nil {
return "", err
}
return strconv.FormatUint(uint64(nv), 10), nil
}

func (a *ethAPI) NetListening(ctx context.Context) (bool, error) {
return true, nil
}

func (a *ethAPI) EthProtocolVersion(ctx context.Context) (types.EthInt, error) {
return types.EthInt(0), nil
}

func (a *ethAPI) EthMaxPriorityFeePerGas(ctx context.Context) (types.EthInt, error) {
return types.EthInt(0), nil
}

func (a *ethAPI) EthGasPrice(ctx context.Context) (types.EthInt, error) {
return types.EthInt(0), nil
}

var _ v1.IETH = (*ethAPI)(nil)
20 changes: 20 additions & 0 deletions app/submodule/eth/eth_submodule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package eth

import (
"github.com/filecoin-project/venus/app/submodule/chain"
v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
)

func NewEthSubModule(chainModule *chain.ChainSubmodule) (*EthSubModule, error) {
return &EthSubModule{
chainModule: chainModule,
}, nil
}

type EthSubModule struct { // nolint
chainModule *chain.ChainSubmodule
}

func (em *EthSubModule) API() v1api.IETH {
return &ethAPI{em: em}
}
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/dustin/go-humanize v1.0.0
github.com/fatih/color v1.13.0
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f
github.com/filecoin-project/go-address v1.0.0
github.com/filecoin-project/go-address v1.1.0
github.com/filecoin-project/go-bitfield v0.2.4
github.com/filecoin-project/go-cbor-util v0.0.1
github.com/filecoin-project/go-commp-utils v0.1.3
Expand All @@ -30,7 +30,7 @@ require (
github.com/filecoin-project/go-fil-markets v1.24.0-v17
github.com/filecoin-project/go-jsonrpc v0.1.5
github.com/filecoin-project/go-paramfetch v0.0.4
github.com/filecoin-project/go-state-types v0.9.8
github.com/filecoin-project/go-state-types v0.10.0-alpha-2
github.com/filecoin-project/pubsub v1.0.0
github.com/filecoin-project/specs-actors v0.9.15
github.com/filecoin-project/specs-actors/v2 v2.3.6
Expand All @@ -49,6 +49,7 @@ require (
github.com/golang/mock v1.6.0
github.com/google/go-github v17.0.0+incompatible
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e
github.com/hashicorp/go-multierror v1.1.1
Expand Down Expand Up @@ -83,6 +84,7 @@ require (
github.com/libp2p/go-libp2p v0.22.0
github.com/libp2p/go-libp2p-kad-dht v0.18.0
github.com/libp2p/go-libp2p-pubsub v0.8.0
github.com/libp2p/go-msgio v0.2.0
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.6.0
Expand Down Expand Up @@ -178,7 +180,6 @@ require (
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand Down Expand Up @@ -220,7 +221,6 @@ require (
github.com/libp2p/go-libp2p-core v0.20.0 // indirect
github.com/libp2p/go-libp2p-kbucket v0.4.7 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
github.com/libp2p/go-msgio v0.2.0 // indirect
github.com/libp2p/go-nat v0.1.0 // indirect
github.com/libp2p/go-netroute v0.2.0 // indirect
github.com/libp2p/go-openssl v0.1.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ github.com/filecoin-project/dagstore v0.5.2 h1:Nd6oXdnolbbVhpMpkYT5PJHOjQp4OBSnt
github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8=
github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8=
github.com/filecoin-project/go-address v0.0.6/go.mod h1:7B0/5DA13n6nHkB8bbGx1gWzG/dbTsZ0fgOJVGsM3TE=
github.com/filecoin-project/go-address v1.0.0 h1:IrexI0kpADLaPP+CdmU3CVAUqnW/FQC0KTmz4lVKiFU=
github.com/filecoin-project/go-address v1.0.0/go.mod h1:5t3z6qPmIADZBtuE9EIzi0EwzcRy2nVhpo0I/c1r0OA=
github.com/filecoin-project/go-address v1.1.0 h1:ofdtUtEsNxkIxkDw67ecSmvtzaVSdcea4boAmLbnHfE=
github.com/filecoin-project/go-address v1.1.0/go.mod h1:5t3z6qPmIADZBtuE9EIzi0EwzcRy2nVhpo0I/c1r0OA=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 h1:pIuR0dnMD0i+as8wNnjjHyQrnhP5O5bmba/lmgQeRgU=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349/go.mod h1:vgmwKBkx+ca5OIeEvstiQgzAZnb7R6QaqE1oEDSqa6g=
Expand Down Expand Up @@ -342,8 +342,8 @@ github.com/filecoin-project/go-state-types v0.1.4/go.mod h1:xCA/WfKlC2zcn3fUmDv4
github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.9.8 h1:xkdITiR7h691z1tWOhNCJxHI+cq+Mq7ATkpHQ7f1gu8=
github.com/filecoin-project/go-state-types v0.9.8/go.mod h1:+HCZifUV+e8TlQkgll22Ucuiq8OrVJkK+4Kh4u75iiw=
github.com/filecoin-project/go-state-types v0.10.0-alpha-2 h1:xz8+sXAuCMane7SkEYCtQjD/zYJ4n1d5bxwYNL8Thf0=
github.com/filecoin-project/go-state-types v0.10.0-alpha-2/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=
Expand Down
25 changes: 25 additions & 0 deletions pkg/chain/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,24 @@ func (store *Store) GetTipSetByHeight(ctx context.Context, ts *types.TipSet, h a
return store.GetTipSet(ctx, lbts.Parents())
}

func (store *Store) GetTipSetByCid(ctx context.Context, c cid.Cid) (*types.TipSet, error) {
blk, err := store.bsstore.Get(ctx, c)
if err != nil {
return nil, fmt.Errorf("cannot find tipset with cid %s: %w", c, err)
}

tsk := new(types.TipSetKey)
if err := tsk.UnmarshalCBOR(bytes.NewReader(blk.RawData())); err != nil {
return nil, fmt.Errorf("cannot unmarshal block into tipset key: %w", err)
}

ts, err := store.GetTipSet(ctx, *tsk)
if err != nil {
return nil, fmt.Errorf("cannot get tipset from key: %w", err)
}
return ts, nil
}

// GetTipSetState returns the aggregate state of the tipset identified by `key`.
func (store *Store) GetTipSetState(ctx context.Context, ts *types.TipSet) (tree.Tree, error) {
if ts == nil {
Expand Down Expand Up @@ -548,6 +566,13 @@ func (store *Store) SetHead(ctx context.Context, newTS *types.TipSet) error {
old: dropped,
new: added,
}

tskBlk, err := newTS.Key().ToStorageBlock()
if err != nil {
log.Errorf("failed to create a block from tsk: %s", newTS.Key())
}
_ = store.bsstore.Put(ctx, tskBlk)

return nil
}

Expand Down
7 changes: 7 additions & 0 deletions venus-devtool/api-gen/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ func init() {

uuidTmp := auuid.MustParse("102334ec-35a3-4b36-be9f-02883844503a")
addExample(&uuidTmp)

// eth types
ethint := types.EthInt(5)
addExample(ethint)
addExample(&ethint)
ethaddr, _ := types.EthAddressFromHex("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031")
addExample(&ethaddr)
}

func ExampleValue(method string, t, parent reflect.Type) interface{} {
Expand Down
Loading

0 comments on commit 8b108ba

Please sign in to comment.