Skip to content

Commit d9a9318

Browse files
authored
feat: expose /v2 APIs through Lotus Gateway (#13075)
Integrate the existing v2 APIs into Lotus Gateway such that they are accessible via `/rpc/v2` endpoint similar to full node APIs except through the gateway reverse proxy along with rate limiting and handling of stateful connections over web socket. The prior gateway implementation did not have a concept of per-uri reverse proxy handling. The changes here separate reverse proxy implementation in gateway from the gateway node to introduce separate handling of v1 and v2 APIs. The work introduces a top-level `v2api.Gateway` interface to capture the APIs exposed by the v2 gateway and generate any relevant documentation based on the interface. Specifically, the work here separates the handling of stateful connections between v1 and v2 to avoid any cross-contamination between Eth calls to either API. However, the total rate limiting has stayed shared across both URIs. The underused mock interface in v1 is now removed in favor of the generated gomock interfaces to reduce the LOC in `gateway` package. The interface was barely used by the tests and would have resulted in unnecessary LOC to implement v2. I have held back on unrelated refactoring of `gateway` package. The code can use further restructuring, but for now the focus is to expose existing /v2 APIs over the gateway. The implementation of `Version` in /v2 APIs is also left as a TODO since it requires implementation at the top level API and bubbles up into `Common` APIs.
1 parent 0829903 commit d9a9318

File tree

24 files changed

+8924
-1881
lines changed

24 files changed

+8924
-1881
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- feat: add gas to application metric reporting `vm/applyblocks_early_gas`, `vm/applyblocks_messages_gas`, `vm/applyblocks_cron_gas` ([filecoin-project/lotus#13030](https://github.com/filecoin-project/lotus/pull/13030))
1616
- feat: fall back to EC if F3 finalized tipeset is older than 900 epochs ([filecoin-project/lotus#13066](https://github.com/filecoin-project/lotus/pull/13066))
1717
- feat: fall back to EC finalized tipset if F3 is too far behind in eth APIs ([filecoin-project/lotus#13070](https://github.com/filecoin-project/lotus/pull/13070))
18+
- feat: expose `/v2` APIs through Lotus Gateway ([filecoin-project/lotus#13075](https://github.com/filecoin-project/lotus/pull/13075))
1819

1920
### Experimental v2 APIs with F3 awareness
2021

api/client/client.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ func NewGatewayRPCV1(ctx context.Context, addr string, requestHeader http.Header
119119
return &res, closer, err
120120
}
121121

122+
// NewGatewayRPCV2 creates a new http jsonrpc client for a gateway node.
123+
func NewGatewayRPCV2(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v2api.Gateway, jsonrpc.ClientCloser, error) {
124+
var res v2api.GatewayStruct
125+
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
126+
api.GetInternalStructs(&res),
127+
requestHeader,
128+
append(opts, jsonrpc.WithErrors(api.RPCErrors))...,
129+
)
130+
131+
return &res, closer, err
132+
}
133+
122134
// NewGatewayRPCV0 creates a new http jsonrpc client for a gateway node.
123135
func NewGatewayRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.Gateway, jsonrpc.ClientCloser, error) {
124136
var res v0api.GatewayStruct

api/docgen/docgen.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []r
524524
i = &v2api.FullNodeStruct{}
525525
t = reflect.TypeOf(new(struct{ v2api.FullNode })).Elem()
526526
permStruct = append(permStruct, reflect.TypeOf(v2api.FullNodeStruct{}.Internal))
527+
case "Gateway":
528+
i = &v2api.GatewayStruct{}
529+
t = reflect.TypeOf(new(struct{ v2api.Gateway })).Elem()
530+
permStruct = append(permStruct, reflect.TypeOf(v2api.GatewayStruct{}.Internal))
527531
default:
528532
panic("unknown type")
529533
}

api/v2api/gateway.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package v2api
2+
3+
import (
4+
"context"
5+
6+
"github.com/ipfs/go-cid"
7+
8+
"github.com/filecoin-project/go-address"
9+
"github.com/filecoin-project/go-jsonrpc"
10+
"github.com/filecoin-project/go-state-types/abi"
11+
12+
apitypes "github.com/filecoin-project/lotus/api/types"
13+
"github.com/filecoin-project/lotus/chain/types"
14+
"github.com/filecoin-project/lotus/chain/types/ethtypes"
15+
)
16+
17+
var _ FullNode = (Gateway)(nil)
18+
19+
type Gateway interface {
20+
ChainGetTipSet(context.Context, types.TipSetSelector) (*types.TipSet, error)
21+
StateGetActor(context.Context, address.Address, types.TipSetSelector) (*types.Actor, error)
22+
StateGetID(context.Context, address.Address, types.TipSetSelector) (*address.Address, error)
23+
EthAddressToFilecoinAddress(ctx context.Context, ethAddress ethtypes.EthAddress) (address.Address, error)
24+
FilecoinAddressToEthAddress(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthAddress, error)
25+
Web3ClientVersion(ctx context.Context) (string, error)
26+
EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
27+
NetVersion(ctx context.Context) (string, error)
28+
NetListening(ctx context.Context) (bool, error)
29+
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)
30+
EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error)
31+
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
32+
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
33+
EthSendRawTransactionUntrusted(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
34+
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
35+
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum string) (ethtypes.EthUint64, error)
36+
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error)
37+
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error)
38+
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error)
39+
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error)
40+
EthGetTransactionByHashLimited(ctx context.Context, txHash *ethtypes.EthHash, limit abi.ChainEpoch) (*ethtypes.EthTx, error)
41+
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (*ethtypes.EthTx, error)
42+
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum string, txIndex ethtypes.EthUint64) (*ethtypes.EthTx, error)
43+
EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error)
44+
EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error)
45+
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error)
46+
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*ethtypes.EthTxReceipt, error)
47+
EthGetTransactionReceiptLimited(ctx context.Context, txHash ethtypes.EthHash, limit abi.ChainEpoch) (*ethtypes.EthTxReceipt, error)
48+
EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*ethtypes.EthTxReceipt, error)
49+
EthGetBlockReceiptsLimited(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*ethtypes.EthTxReceipt, error)
50+
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
51+
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
52+
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBigInt, error)
53+
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
54+
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
55+
EthTraceTransaction(ctx context.Context, txHash string) ([]*ethtypes.EthTraceTransaction, error)
56+
EthTraceFilter(ctx context.Context, filter ethtypes.EthTraceFilterCriteria) ([]*ethtypes.EthTraceFilterResult, error)
57+
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error)
58+
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error)
59+
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
60+
EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthUint64, error)
61+
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
62+
EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error)
63+
EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error)
64+
EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error)
65+
EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error)
66+
EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error)
67+
EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
68+
EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
69+
EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error)
70+
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error)
71+
72+
Discover(context.Context) (apitypes.OpenRPCDocument, error)
73+
}

0 commit comments

Comments
 (0)