Merge pull request #9863 from filecoin-project/feat/eth-gateway-api

feat: eth gateway api
This commit is contained in:
Jiaying Wang 2023-01-13 22:32:51 -05:00 committed by GitHub
commit 32615ecbd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1528 additions and 508 deletions

View File

@ -13,6 +13,7 @@ import (
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
)
// MODIFYING THE API INTERFACE
@ -69,4 +70,38 @@ type Gateway interface {
WalletBalance(context.Context, address.Address) (types.BigInt, error)
Version(context.Context) (APIVersion, error)
Discover(context.Context) (apitypes.OpenRPCDocument, error)
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error)
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error)
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error)
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error)
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error)
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error)
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*EthTxReceipt, error)
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error)
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error)
EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error)
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error)
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error)
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error)
EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error)
EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error)
EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error)
EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error)
EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error)
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error)
}

44
api/eth_aliases.go Normal file
View File

@ -0,0 +1,44 @@
package api
import apitypes "github.com/filecoin-project/lotus/api/types"
func CreateEthRPCAliases(as apitypes.Aliaser) {
// TODO: maybe use reflect to automatically register all the eth aliases
as.AliasMethod("eth_accounts", "Filecoin.EthAccounts")
as.AliasMethod("eth_blockNumber", "Filecoin.EthBlockNumber")
as.AliasMethod("eth_getBlockTransactionCountByNumber", "Filecoin.EthGetBlockTransactionCountByNumber")
as.AliasMethod("eth_getBlockTransactionCountByHash", "Filecoin.EthGetBlockTransactionCountByHash")
as.AliasMethod("eth_getBlockByHash", "Filecoin.EthGetBlockByHash")
as.AliasMethod("eth_getBlockByNumber", "Filecoin.EthGetBlockByNumber")
as.AliasMethod("eth_getTransactionByHash", "Filecoin.EthGetTransactionByHash")
as.AliasMethod("eth_getTransactionCount", "Filecoin.EthGetTransactionCount")
as.AliasMethod("eth_getTransactionReceipt", "Filecoin.EthGetTransactionReceipt")
as.AliasMethod("eth_getTransactionByBlockHashAndIndex", "Filecoin.EthGetTransactionByBlockHashAndIndex")
as.AliasMethod("eth_getTransactionByBlockNumberAndIndex", "Filecoin.EthGetTransactionByBlockNumberAndIndex")
as.AliasMethod("eth_getCode", "Filecoin.EthGetCode")
as.AliasMethod("eth_getStorageAt", "Filecoin.EthGetStorageAt")
as.AliasMethod("eth_getBalance", "Filecoin.EthGetBalance")
as.AliasMethod("eth_chainId", "Filecoin.EthChainId")
as.AliasMethod("eth_feeHistory", "Filecoin.EthFeeHistory")
as.AliasMethod("eth_protocolVersion", "Filecoin.EthProtocolVersion")
as.AliasMethod("eth_maxPriorityFeePerGas", "Filecoin.EthMaxPriorityFeePerGas")
as.AliasMethod("eth_gasPrice", "Filecoin.EthGasPrice")
as.AliasMethod("eth_sendRawTransaction", "Filecoin.EthSendRawTransaction")
as.AliasMethod("eth_estimateGas", "Filecoin.EthEstimateGas")
as.AliasMethod("eth_call", "Filecoin.EthCall")
as.AliasMethod("eth_getLogs", "Filecoin.EthGetLogs")
as.AliasMethod("eth_getFilterChanges", "Filecoin.EthGetFilterChanges")
as.AliasMethod("eth_getFilterLogs", "Filecoin.EthGetFilterLogs")
as.AliasMethod("eth_newFilter", "Filecoin.EthNewFilter")
as.AliasMethod("eth_newBlockFilter", "Filecoin.EthNewBlockFilter")
as.AliasMethod("eth_newPendingTransactionFilter", "Filecoin.EthNewPendingTransactionFilter")
as.AliasMethod("eth_uninstallFilter", "Filecoin.EthUninstallFilter")
as.AliasMethod("eth_subscribe", "Filecoin.EthSubscribe")
as.AliasMethod("eth_unsubscribe", "Filecoin.EthUnsubscribe")
as.AliasMethod("net_version", "Filecoin.NetVersion")
as.AliasMethod("net_listening", "Filecoin.NetListening")
}

View File

@ -619,6 +619,68 @@ type GatewayStruct struct {
Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) ``
EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) ``
EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) ``
EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) ``
EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) ``
EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) ``
EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) ``
EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) ``
EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) ``
EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) ``
EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) ``
EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) ``
EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) ``
EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) ``
EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) ``
EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) ``
EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) ``
EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) ``
EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) ``
EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) ``
EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) ``
EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) ``
EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) ``
EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) ``
EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) ``
EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) ``
EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) ``
EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) ``
EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) ``
EthSubscribe func(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) ``
EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) ``
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) ``
GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) ``
MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) ``
@ -631,6 +693,10 @@ type GatewayStruct struct {
MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) ``
NetListening func(p0 context.Context) (bool, error) ``
NetVersion func(p0 context.Context) (string, error) ``
StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) ``
StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) ``
@ -4009,6 +4075,347 @@ func (s *GatewayStub) Discover(p0 context.Context) (apitypes.OpenRPCDocument, er
return *new(apitypes.OpenRPCDocument), ErrNotSupported
}
func (s *GatewayStruct) EthAccounts(p0 context.Context) ([]ethtypes.EthAddress, error) {
if s.Internal.EthAccounts == nil {
return *new([]ethtypes.EthAddress), ErrNotSupported
}
return s.Internal.EthAccounts(p0)
}
func (s *GatewayStub) EthAccounts(p0 context.Context) ([]ethtypes.EthAddress, error) {
return *new([]ethtypes.EthAddress), ErrNotSupported
}
func (s *GatewayStruct) EthBlockNumber(p0 context.Context) (ethtypes.EthUint64, error) {
if s.Internal.EthBlockNumber == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthBlockNumber(p0)
}
func (s *GatewayStub) EthBlockNumber(p0 context.Context) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthCall(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) {
if s.Internal.EthCall == nil {
return *new(ethtypes.EthBytes), ErrNotSupported
}
return s.Internal.EthCall(p0, p1, p2)
}
func (s *GatewayStub) EthCall(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) {
return *new(ethtypes.EthBytes), ErrNotSupported
}
func (s *GatewayStruct) EthChainId(p0 context.Context) (ethtypes.EthUint64, error) {
if s.Internal.EthChainId == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthChainId(p0)
}
func (s *GatewayStub) EthChainId(p0 context.Context) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
if s.Internal.EthEstimateGas == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthEstimateGas(p0, p1)
}
func (s *GatewayStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
if s.Internal.EthFeeHistory == nil {
return *new(ethtypes.EthFeeHistory), ErrNotSupported
}
return s.Internal.EthFeeHistory(p0, p1, p2, p3)
}
func (s *GatewayStub) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
return *new(ethtypes.EthFeeHistory), ErrNotSupported
}
func (s *GatewayStruct) EthGasPrice(p0 context.Context) (ethtypes.EthBigInt, error) {
if s.Internal.EthGasPrice == nil {
return *new(ethtypes.EthBigInt), ErrNotSupported
}
return s.Internal.EthGasPrice(p0)
}
func (s *GatewayStub) EthGasPrice(p0 context.Context) (ethtypes.EthBigInt, error) {
return *new(ethtypes.EthBigInt), ErrNotSupported
}
func (s *GatewayStruct) EthGetBalance(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) {
if s.Internal.EthGetBalance == nil {
return *new(ethtypes.EthBigInt), ErrNotSupported
}
return s.Internal.EthGetBalance(p0, p1, p2)
}
func (s *GatewayStub) EthGetBalance(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) {
return *new(ethtypes.EthBigInt), ErrNotSupported
}
func (s *GatewayStruct) EthGetBlockByHash(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) {
if s.Internal.EthGetBlockByHash == nil {
return *new(ethtypes.EthBlock), ErrNotSupported
}
return s.Internal.EthGetBlockByHash(p0, p1, p2)
}
func (s *GatewayStub) EthGetBlockByHash(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) {
return *new(ethtypes.EthBlock), ErrNotSupported
}
func (s *GatewayStruct) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) {
if s.Internal.EthGetBlockByNumber == nil {
return *new(ethtypes.EthBlock), ErrNotSupported
}
return s.Internal.EthGetBlockByNumber(p0, p1, p2)
}
func (s *GatewayStub) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) {
return *new(ethtypes.EthBlock), ErrNotSupported
}
func (s *GatewayStruct) EthGetBlockTransactionCountByHash(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) {
if s.Internal.EthGetBlockTransactionCountByHash == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthGetBlockTransactionCountByHash(p0, p1)
}
func (s *GatewayStub) EthGetBlockTransactionCountByHash(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) {
if s.Internal.EthGetBlockTransactionCountByNumber == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthGetBlockTransactionCountByNumber(p0, p1)
}
func (s *GatewayStub) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthGetCode(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) {
if s.Internal.EthGetCode == nil {
return *new(ethtypes.EthBytes), ErrNotSupported
}
return s.Internal.EthGetCode(p0, p1, p2)
}
func (s *GatewayStub) EthGetCode(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) {
return *new(ethtypes.EthBytes), ErrNotSupported
}
func (s *GatewayStruct) EthGetFilterChanges(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
if s.Internal.EthGetFilterChanges == nil {
return nil, ErrNotSupported
}
return s.Internal.EthGetFilterChanges(p0, p1)
}
func (s *GatewayStub) EthGetFilterChanges(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
return nil, ErrNotSupported
}
func (s *GatewayStruct) EthGetFilterLogs(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
if s.Internal.EthGetFilterLogs == nil {
return nil, ErrNotSupported
}
return s.Internal.EthGetFilterLogs(p0, p1)
}
func (s *GatewayStub) EthGetFilterLogs(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
return nil, ErrNotSupported
}
func (s *GatewayStruct) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
if s.Internal.EthGetLogs == nil {
return nil, ErrNotSupported
}
return s.Internal.EthGetLogs(p0, p1)
}
func (s *GatewayStub) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
return nil, ErrNotSupported
}
func (s *GatewayStruct) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) {
if s.Internal.EthGetStorageAt == nil {
return *new(ethtypes.EthBytes), ErrNotSupported
}
return s.Internal.EthGetStorageAt(p0, p1, p2, p3)
}
func (s *GatewayStub) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) {
return *new(ethtypes.EthBytes), ErrNotSupported
}
func (s *GatewayStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
if s.Internal.EthGetTransactionByBlockHashAndIndex == nil {
return *new(ethtypes.EthTx), ErrNotSupported
}
return s.Internal.EthGetTransactionByBlockHashAndIndex(p0, p1, p2)
}
func (s *GatewayStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
return *new(ethtypes.EthTx), ErrNotSupported
}
func (s *GatewayStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
if s.Internal.EthGetTransactionByBlockNumberAndIndex == nil {
return *new(ethtypes.EthTx), ErrNotSupported
}
return s.Internal.EthGetTransactionByBlockNumberAndIndex(p0, p1, p2)
}
func (s *GatewayStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
return *new(ethtypes.EthTx), ErrNotSupported
}
func (s *GatewayStruct) EthGetTransactionByHash(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) {
if s.Internal.EthGetTransactionByHash == nil {
return nil, ErrNotSupported
}
return s.Internal.EthGetTransactionByHash(p0, p1)
}
func (s *GatewayStub) EthGetTransactionByHash(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) {
return nil, ErrNotSupported
}
func (s *GatewayStruct) EthGetTransactionCount(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) {
if s.Internal.EthGetTransactionCount == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthGetTransactionCount(p0, p1, p2)
}
func (s *GatewayStub) EthGetTransactionCount(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthGetTransactionReceipt(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) {
if s.Internal.EthGetTransactionReceipt == nil {
return nil, ErrNotSupported
}
return s.Internal.EthGetTransactionReceipt(p0, p1)
}
func (s *GatewayStub) EthGetTransactionReceipt(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) {
return nil, ErrNotSupported
}
func (s *GatewayStruct) EthMaxPriorityFeePerGas(p0 context.Context) (ethtypes.EthBigInt, error) {
if s.Internal.EthMaxPriorityFeePerGas == nil {
return *new(ethtypes.EthBigInt), ErrNotSupported
}
return s.Internal.EthMaxPriorityFeePerGas(p0)
}
func (s *GatewayStub) EthMaxPriorityFeePerGas(p0 context.Context) (ethtypes.EthBigInt, error) {
return *new(ethtypes.EthBigInt), ErrNotSupported
}
func (s *GatewayStruct) EthNewBlockFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
if s.Internal.EthNewBlockFilter == nil {
return *new(ethtypes.EthFilterID), ErrNotSupported
}
return s.Internal.EthNewBlockFilter(p0)
}
func (s *GatewayStub) EthNewBlockFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
return *new(ethtypes.EthFilterID), ErrNotSupported
}
func (s *GatewayStruct) EthNewFilter(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
if s.Internal.EthNewFilter == nil {
return *new(ethtypes.EthFilterID), ErrNotSupported
}
return s.Internal.EthNewFilter(p0, p1)
}
func (s *GatewayStub) EthNewFilter(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
return *new(ethtypes.EthFilterID), ErrNotSupported
}
func (s *GatewayStruct) EthNewPendingTransactionFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
if s.Internal.EthNewPendingTransactionFilter == nil {
return *new(ethtypes.EthFilterID), ErrNotSupported
}
return s.Internal.EthNewPendingTransactionFilter(p0)
}
func (s *GatewayStub) EthNewPendingTransactionFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
return *new(ethtypes.EthFilterID), ErrNotSupported
}
func (s *GatewayStruct) EthProtocolVersion(p0 context.Context) (ethtypes.EthUint64, error) {
if s.Internal.EthProtocolVersion == nil {
return *new(ethtypes.EthUint64), ErrNotSupported
}
return s.Internal.EthProtocolVersion(p0)
}
func (s *GatewayStub) EthProtocolVersion(p0 context.Context) (ethtypes.EthUint64, error) {
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthSendRawTransaction(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) {
if s.Internal.EthSendRawTransaction == nil {
return *new(ethtypes.EthHash), ErrNotSupported
}
return s.Internal.EthSendRawTransaction(p0, p1)
}
func (s *GatewayStub) EthSendRawTransaction(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) {
return *new(ethtypes.EthHash), ErrNotSupported
}
func (s *GatewayStruct) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
if s.Internal.EthSubscribe == nil {
return nil, ErrNotSupported
}
return s.Internal.EthSubscribe(p0, p1, p2)
}
func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
return nil, ErrNotSupported
}
func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
if s.Internal.EthUninstallFilter == nil {
return false, ErrNotSupported
}
return s.Internal.EthUninstallFilter(p0, p1)
}
func (s *GatewayStub) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
return false, ErrNotSupported
}
func (s *GatewayStruct) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) {
if s.Internal.EthUnsubscribe == nil {
return false, ErrNotSupported
}
return s.Internal.EthUnsubscribe(p0, p1)
}
func (s *GatewayStub) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) {
return false, ErrNotSupported
}
func (s *GatewayStruct) GasEstimateMessageGas(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) {
if s.Internal.GasEstimateMessageGas == nil {
return nil, ErrNotSupported
@ -4075,6 +4482,28 @@ func (s *GatewayStub) MsigGetVestingSchedule(p0 context.Context, p1 address.Addr
return *new(MsigVesting), ErrNotSupported
}
func (s *GatewayStruct) NetListening(p0 context.Context) (bool, error) {
if s.Internal.NetListening == nil {
return false, ErrNotSupported
}
return s.Internal.NetListening(p0)
}
func (s *GatewayStub) NetListening(p0 context.Context) (bool, error) {
return false, ErrNotSupported
}
func (s *GatewayStruct) NetVersion(p0 context.Context) (string, error) {
if s.Internal.NetVersion == nil {
return "", ErrNotSupported
}
return s.Internal.NetVersion(p0)
}
func (s *GatewayStub) NetVersion(p0 context.Context) (string, error) {
return "", ErrNotSupported
}
func (s *GatewayStruct) StateAccountKey(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) {
if s.Internal.StateAccountKey == nil {
return *new(address.Address), ErrNotSupported

5
api/types/rpc.go Normal file
View File

@ -0,0 +1,5 @@
package apitypes
type Aliaser interface {
AliasMethod(alias, original string)
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -25,6 +25,10 @@ type perConnLimiterKeyType string
const perConnLimiterKey perConnLimiterKeyType = "limiter"
type filterTrackerKeyType string
const filterTrackerKey filterTrackerKeyType = "filterTracker"
// Handler returns a gateway http.Handler, to be mounted as-is on the server.
func Handler(gwapi lapi.Gateway, api lapi.FullNode, rateLimit int64, connPerMinute int64, opts ...jsonrpc.ServerOption) (http.Handler, error) {
m := mux.NewRouter()
@ -34,6 +38,8 @@ func Handler(gwapi lapi.Gateway, api lapi.FullNode, rateLimit int64, connPerMinu
rpcServer.Register("Filecoin", hnd)
rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover")
lapi.CreateEthRPCAliases(rpcServer)
m.Handle(path, rpcServer)
}
@ -81,8 +87,12 @@ type RateLimiterHandler struct {
}
func (h RateLimiterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r2 := r.WithContext(context.WithValue(r.Context(), perConnLimiterKey, h.limiter))
h.handler.ServeHTTP(w, r2)
r = r.WithContext(context.WithValue(r.Context(), perConnLimiterKey, h.limiter))
// also add a filter tracker to the context
r = r.WithContext(context.WithValue(r.Context(), filterTrackerKey, newFilterTracker()))
h.handler.ServeHTTP(w, r)
}
// this blocks new connections if there have already been too many.

View File

@ -9,21 +9,18 @@ import (
"github.com/ipfs/go-cid"
"go.opencensus.io/stats"
"golang.org/x/time/rate"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
@ -88,7 +85,40 @@ type TargetAPI interface {
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read
WalletBalance(context.Context, address.Address) (types.BigInt, error)
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error)
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error)
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error)
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error)
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error)
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error)
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error)
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error)
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error)
EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error)
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error)
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error)
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error)
EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error)
EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error)
EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error)
EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error)
EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error)
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error)
}
var _ TargetAPI = *new(api.FullNode) // gateway depends on latest
@ -184,462 +214,3 @@ func (gw *Node) limit(ctx context.Context, tokens int) error {
}
return nil
}
func (gw *Node) Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) {
return build.OpenRPCDiscoverJSON_Gateway(), nil
}
func (gw *Node) Version(ctx context.Context) (api.APIVersion, error) {
if err := gw.limit(ctx, basicRateLimitTokens); err != nil {
return api.APIVersion{}, err
}
return gw.target.Version(ctx)
}
func (gw *Node) ChainGetParentMessages(ctx context.Context, c cid.Cid) ([]api.Message, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetParentMessages(ctx, c)
}
func (gw *Node) ChainGetParentReceipts(ctx context.Context, c cid.Cid) ([]*types.MessageReceipt, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetParentReceipts(ctx, c)
}
func (gw *Node) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetBlockMessages(ctx, c)
}
func (gw *Node) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return false, err
}
return gw.target.ChainHasObj(ctx, c)
}
func (gw *Node) ChainHead(ctx context.Context) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainHead(ctx)
}
func (gw *Node) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetMessage(ctx, mc)
}
func (gw *Node) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetTipSet(ctx, tsk)
}
func (gw *Node) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipSetHeight(ctx, h, tsk); err != nil {
return nil, err
}
return gw.target.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (gw *Node) ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipSetHeight(ctx, h, tsk); err != nil {
return nil, err
}
return gw.target.ChainGetTipSetAfterHeight(ctx, h, tsk)
}
func (gw *Node) checkTipSetHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) error {
var ts *types.TipSet
if tsk.IsEmpty() {
head, err := gw.target.ChainHead(ctx)
if err != nil {
return err
}
ts = head
} else {
gts, err := gw.target.ChainGetTipSet(ctx, tsk)
if err != nil {
return err
}
ts = gts
}
// Check if the tipset key refers to gw tipset that's too far in the past
if err := gw.checkTipset(ts); err != nil {
return err
}
// Check if the height is too far in the past
if err := gw.checkTipsetHeight(ts, h); err != nil {
return err
}
return nil
}
func (gw *Node) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetNode(ctx, p)
}
func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainNotify(ctx)
}
func (gw *Node) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, from); err != nil {
return nil, xerrors.Errorf("gateway: checking 'from' tipset: %w", err)
}
if err := gw.checkTipsetKey(ctx, to); err != nil {
return nil, xerrors.Errorf("gateway: checking 'to' tipset: %w", err)
}
return gw.target.ChainGetPath(ctx, from, to)
}
func (gw *Node) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetGenesis(ctx)
}
func (gw *Node) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainReadObj(ctx, c)
}
func (gw *Node) ChainPutObj(context.Context, blocks.Block) error {
return xerrors.New("not supported")
}
func (gw *Node) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.GasEstimateMessageGas(ctx, msg, spec, tsk)
}
func (gw *Node) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return cid.Cid{}, err
}
// TODO: additional anti-spam checks
return gw.target.MpoolPushUntrusted(ctx, sm)
}
func (gw *Node) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return types.BigInt{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return types.NewInt(0), err
}
return gw.target.MsigGetAvailableBalance(ctx, addr, tsk)
}
func (gw *Node) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return types.BigInt{}, err
}
if err := gw.checkTipsetKey(ctx, start); err != nil {
return types.NewInt(0), err
}
if err := gw.checkTipsetKey(ctx, end); err != nil {
return types.NewInt(0), err
}
return gw.target.MsigGetVested(ctx, addr, start, end)
}
func (gw *Node) MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MsigVesting, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return api.MsigVesting{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.MsigVesting{}, err
}
return gw.target.MsigGetVestingSchedule(ctx, addr, tsk)
}
func (gw *Node) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.MsigGetPending(ctx, addr, tsk)
}
func (gw *Node) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return address.Address{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return address.Undef, err
}
return gw.target.StateAccountKey(ctx, addr, tsk)
}
func (gw *Node) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.DealCollateralBounds{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.DealCollateralBounds{}, err
}
return gw.target.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
}
func (gw *Node) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateGetActor(ctx, actor, tsk)
}
func (gw *Node) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateListMiners(ctx, tsk)
}
func (gw *Node) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return address.Address{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return address.Undef, err
}
return gw.target.StateLookupID(ctx, addr, tsk)
}
func (gw *Node) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.MarketBalance{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.MarketBalance{}, err
}
return gw.target.StateMarketBalance(ctx, addr, tsk)
}
func (gw *Node) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMarketStorageDeal(ctx, dealId, tsk)
}
func (gw *Node) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return network.VersionMax, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return network.VersionMax, err
}
return gw.target.StateNetworkVersion(ctx, tsk)
}
func (gw *Node) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if limit == api.LookbackNoLimit {
limit = gw.stateWaitLookbackLimit
}
if gw.stateWaitLookbackLimit != api.LookbackNoLimit && limit > gw.stateWaitLookbackLimit {
limit = gw.stateWaitLookbackLimit
}
if err := gw.checkTipsetKey(ctx, from); err != nil {
return nil, err
}
return gw.target.StateSearchMsg(ctx, from, msg, limit, allowReplaced)
}
func (gw *Node) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if limit == api.LookbackNoLimit {
limit = gw.stateWaitLookbackLimit
}
if gw.stateWaitLookbackLimit != api.LookbackNoLimit && limit > gw.stateWaitLookbackLimit {
limit = gw.stateWaitLookbackLimit
}
return gw.target.StateWaitMsg(ctx, msg, confidence, limit, allowReplaced)
}
func (gw *Node) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateReadState(ctx, actor, tsk)
}
func (gw *Node) StateMinerPower(ctx context.Context, m address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMinerPower(ctx, m, tsk)
}
func (gw *Node) StateMinerFaults(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return bitfield.BitField{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return bitfield.BitField{}, err
}
return gw.target.StateMinerFaults(ctx, m, tsk)
}
func (gw *Node) StateMinerRecoveries(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return bitfield.BitField{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return bitfield.BitField{}, err
}
return gw.target.StateMinerRecoveries(ctx, m, tsk)
}
func (gw *Node) StateMinerInfo(ctx context.Context, m address.Address, tsk types.TipSetKey) (api.MinerInfo, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.MinerInfo{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.MinerInfo{}, err
}
return gw.target.StateMinerInfo(ctx, m, tsk)
}
func (gw *Node) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]api.Deadline, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMinerDeadlines(ctx, m, tsk)
}
func (gw *Node) StateMinerAvailableBalance(ctx context.Context, m address.Address, tsk types.TipSetKey) (types.BigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return types.BigInt{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return types.BigInt{}, err
}
return gw.target.StateMinerAvailableBalance(ctx, m, tsk)
}
func (gw *Node) StateMinerProvingDeadline(ctx context.Context, m address.Address, tsk types.TipSetKey) (*dline.Info, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMinerProvingDeadline(ctx, m, tsk)
}
func (gw *Node) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return abi.TokenAmount{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return abi.TokenAmount{}, err
}
return gw.target.StateCirculatingSupply(ctx, tsk)
}
func (gw *Node) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateSectorGetInfo(ctx, maddr, n, tsk)
}
func (gw *Node) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateVerifiedClientStatus(ctx, addr, tsk)
}
func (gw *Node) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.CirculatingSupply{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.CirculatingSupply{}, err
}
return gw.target.StateVMCirculatingSupplyInternal(ctx, tsk)
}
func (gw *Node) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return false, err
}
return sigs.Verify(sig, k, msg) == nil, nil
}
func (gw *Node) WalletBalance(ctx context.Context, k address.Address) (types.BigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return types.BigInt{}, err
}
return gw.target.WalletBalance(ctx, k)
}

481
gateway/proxy_eth.go Normal file
View File

@ -0,0 +1,481 @@
package gateway
import (
"bytes"
"context"
"fmt"
"sync"
"time"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
)
func (gw *Node) EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) {
// gateway provides public API, so it can't hold user accounts
return []ethtypes.EthAddress{}, nil
}
func (gw *Node) EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
return gw.target.EthBlockNumber(ctx)
}
func (gw *Node) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
head, err := gw.target.ChainHead(ctx)
if err != nil {
return 0, err
}
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(blkNum)); err != nil {
return 0, err
}
return gw.target.EthGetBlockTransactionCountByNumber(ctx, blkNum)
}
func (gw *Node) tskByEthHash(ctx context.Context, blkHash ethtypes.EthHash) (types.TipSetKey, error) {
tskCid := blkHash.ToCid()
tskBlk, err := gw.target.ChainReadObj(ctx, tskCid)
if err != nil {
return types.EmptyTSK, err
}
tsk := new(types.TipSetKey)
if err := tsk.UnmarshalCBOR(bytes.NewReader(tskBlk)); err != nil {
return types.EmptyTSK, xerrors.Errorf("cannot unmarshal block into tipset key: %w", err)
}
return *tsk, nil
}
func (gw *Node) checkBlkHash(ctx context.Context, blkHash ethtypes.EthHash) error {
tsk, err := gw.tskByEthHash(ctx, blkHash)
if err != nil {
return err
}
return gw.checkTipsetKey(ctx, tsk)
}
func (gw *Node) checkBlkParam(ctx context.Context, blkParam string) error {
if blkParam == "earliest" {
// also not supported in node impl
return fmt.Errorf("block param \"earliest\" is not supported")
}
switch blkParam {
case "pending", "latest":
// those will be recent enough, so we don't need to check
return nil
default:
var num ethtypes.EthUint64
err := num.UnmarshalJSON([]byte(`"` + blkParam + `"`))
if err != nil {
return fmt.Errorf("cannot parse block number: %v", err)
}
head, err := gw.target.ChainHead(ctx)
if err != nil {
return err
}
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(num)); err != nil {
return err
}
}
return nil
}
func (gw *Node) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
if err := gw.checkBlkHash(ctx, blkHash); err != nil {
return 0, err
}
return gw.target.EthGetBlockTransactionCountByHash(ctx, blkHash)
}
func (gw *Node) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthBlock{}, err
}
if err := gw.checkBlkHash(ctx, blkHash); err != nil {
return ethtypes.EthBlock{}, err
}
return gw.target.EthGetBlockByHash(ctx, blkHash, fullTxInfo)
}
func (gw *Node) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthBlock{}, err
}
if err := gw.checkBlkParam(ctx, blkNum); err != nil {
return ethtypes.EthBlock{}, err
}
return gw.target.EthGetBlockByNumber(ctx, blkNum, fullTxInfo)
}
func (gw *Node) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
return gw.target.EthGetTransactionByHash(ctx, txHash)
}
func (gw *Node) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
if err := gw.checkBlkParam(ctx, blkOpt); err != nil {
return 0, err
}
return gw.target.EthGetTransactionCount(ctx, sender, blkOpt)
}
func (gw *Node) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
return gw.target.EthGetTransactionReceipt(ctx, txHash)
}
func (gw *Node) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthTx{}, err
}
if err := gw.checkBlkHash(ctx, blkHash); err != nil {
return ethtypes.EthTx{}, err
}
return gw.target.EthGetTransactionByBlockHashAndIndex(ctx, blkHash, txIndex)
}
func (gw *Node) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthTx{}, err
}
head, err := gw.target.ChainHead(ctx)
if err != nil {
return ethtypes.EthTx{}, err
}
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(blkNum)); err != nil {
return ethtypes.EthTx{}, err
}
return gw.target.EthGetTransactionByBlockNumberAndIndex(ctx, blkNum, txIndex)
}
func (gw *Node) EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkBlkParam(ctx, blkOpt); err != nil {
return nil, err
}
return gw.target.EthGetCode(ctx, address, blkOpt)
}
func (gw *Node) EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkBlkParam(ctx, blkParam); err != nil {
return nil, err
}
return gw.target.EthGetStorageAt(ctx, address, position, blkParam)
}
func (gw *Node) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthBigInt(big.Zero()), err
}
if err := gw.checkBlkParam(ctx, blkParam); err != nil {
return ethtypes.EthBigInt(big.Zero()), err
}
return gw.target.EthGetBalance(ctx, address, blkParam)
}
func (gw *Node) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
return gw.target.EthChainId(ctx)
}
func (gw *Node) NetVersion(ctx context.Context) (string, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return "", err
}
return gw.target.NetVersion(ctx)
}
func (gw *Node) NetListening(ctx context.Context) (bool, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return false, err
}
return gw.target.NetListening(ctx)
}
func (gw *Node) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
return gw.target.EthProtocolVersion(ctx)
}
func (gw *Node) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthBigInt(big.Zero()), err
}
return gw.target.EthGasPrice(ctx)
}
var EthFeeHistoryMaxBlockCount = 128 // this seems to be expensive; todo: figure out what is a good number that works with everything
func (gw *Node) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFeeHistory{}, err
}
if err := gw.checkBlkParam(ctx, newestBlk); err != nil {
return ethtypes.EthFeeHistory{}, err
}
if blkCount > ethtypes.EthUint64(EthFeeHistoryMaxBlockCount) {
return ethtypes.EthFeeHistory{}, fmt.Errorf("block count too high")
}
return gw.target.EthFeeHistory(ctx, blkCount, newestBlk, rewardPercentiles)
}
func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthBigInt(big.Zero()), err
}
return gw.target.EthMaxPriorityFeePerGas(ctx)
}
func (gw *Node) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err
}
// todo limit gas? to what?
return gw.target.EthEstimateGas(ctx, tx)
}
func (gw *Node) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkBlkParam(ctx, blkParam); err != nil {
return nil, err
}
// todo limit gas? to what?
return gw.target.EthCall(ctx, tx, blkParam)
}
func (gw *Node) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthHash{}, err
}
return gw.target.EthSendRawTransaction(ctx, rawTx)
}
func (gw *Node) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if filter.FromBlock != nil {
if err := gw.checkBlkParam(ctx, *filter.FromBlock); err != nil {
return nil, err
}
}
if filter.ToBlock != nil {
if err := gw.checkBlkParam(ctx, *filter.ToBlock); err != nil {
return nil, err
}
}
if filter.BlockHash != nil {
if err := gw.checkBlkHash(ctx, *filter.BlockHash); err != nil {
return nil, err
}
}
return gw.target.EthGetLogs(ctx, filter)
}
/* FILTERS: Those are stateful.. figure out how to properly either bind them to users, or time out? */
func (gw *Node) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
_, ok := ft.userFilters[id]
ft.lk.Unlock()
if !ok {
return nil, nil
}
return gw.target.EthGetFilterChanges(ctx, id)
}
func (gw *Node) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
_, ok := ft.userFilters[id]
ft.lk.Unlock()
if !ok {
return nil, nil
}
return gw.target.EthGetFilterLogs(ctx, id)
}
func (gw *Node) EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFilterID{}, err
}
return addUserFilterLimited(ctx, func() (ethtypes.EthFilterID, error) {
return gw.target.EthNewFilter(ctx, filter)
})
}
func (gw *Node) EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFilterID{}, err
}
return addUserFilterLimited(ctx, func() (ethtypes.EthFilterID, error) {
return gw.target.EthNewBlockFilter(ctx)
})
}
func (gw *Node) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFilterID{}, err
}
return addUserFilterLimited(ctx, func() (ethtypes.EthFilterID, error) {
return gw.target.EthNewPendingTransactionFilter(ctx)
})
}
func (gw *Node) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return false, err
}
// check if the filter belongs to this connection
ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
defer ft.lk.Unlock()
if _, ok := ft.userFilters[id]; !ok {
return false, nil
}
ok, err := gw.target.EthUninstallFilter(ctx, id)
if err != nil {
return false, err
}
delete(ft.userFilters, id)
return ok, nil
}
func (gw *Node) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
return nil, xerrors.Errorf("not implemented")
}
func (gw *Node) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) {
return false, xerrors.Errorf("not implemented")
}
var EthMaxFiltersPerConn = 16 // todo make this configurable
func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, error)) (ethtypes.EthFilterID, error) {
ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
defer ft.lk.Unlock()
if len(ft.userFilters) >= EthMaxFiltersPerConn {
return ethtypes.EthFilterID{}, fmt.Errorf("too many filters")
}
id, err := cb()
if err != nil {
return id, err
}
ft.userFilters[id] = time.Now()
return id, nil
}
func filterTrackerFromContext(ctx context.Context) *filterTracker {
return ctx.Value(filterTrackerKey).(*filterTracker)
}
type filterTracker struct {
lk sync.Mutex
userFilters map[ethtypes.EthFilterID]time.Time
}
// called per request (ws connection)
func newFilterTracker() *filterTracker {
return &filterTracker{
userFilters: make(map[ethtypes.EthFilterID]time.Time),
}
}

482
gateway/proxy_fil.go Normal file
View File

@ -0,0 +1,482 @@
package gateway
import (
"context"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
)
func (gw *Node) Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) {
return build.OpenRPCDiscoverJSON_Gateway(), nil
}
func (gw *Node) Version(ctx context.Context) (api.APIVersion, error) {
if err := gw.limit(ctx, basicRateLimitTokens); err != nil {
return api.APIVersion{}, err
}
return gw.target.Version(ctx)
}
func (gw *Node) ChainGetParentMessages(ctx context.Context, c cid.Cid) ([]api.Message, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetParentMessages(ctx, c)
}
func (gw *Node) ChainGetParentReceipts(ctx context.Context, c cid.Cid) ([]*types.MessageReceipt, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetParentReceipts(ctx, c)
}
func (gw *Node) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetBlockMessages(ctx, c)
}
func (gw *Node) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return false, err
}
return gw.target.ChainHasObj(ctx, c)
}
func (gw *Node) ChainHead(ctx context.Context) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainHead(ctx)
}
func (gw *Node) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetMessage(ctx, mc)
}
func (gw *Node) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetTipSet(ctx, tsk)
}
func (gw *Node) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipSetHeight(ctx, h, tsk); err != nil {
return nil, err
}
return gw.target.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (gw *Node) ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipSetHeight(ctx, h, tsk); err != nil {
return nil, err
}
return gw.target.ChainGetTipSetAfterHeight(ctx, h, tsk)
}
func (gw *Node) checkTipSetHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) error {
var ts *types.TipSet
if tsk.IsEmpty() {
head, err := gw.target.ChainHead(ctx)
if err != nil {
return err
}
ts = head
} else {
gts, err := gw.target.ChainGetTipSet(ctx, tsk)
if err != nil {
return err
}
ts = gts
}
// Check if the tipset key refers to gw tipset that's too far in the past
if err := gw.checkTipset(ts); err != nil {
return err
}
// Check if the height is too far in the past
if err := gw.checkTipsetHeight(ts, h); err != nil {
return err
}
return nil
}
func (gw *Node) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetNode(ctx, p)
}
func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainNotify(ctx)
}
func (gw *Node) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, from); err != nil {
return nil, xerrors.Errorf("gateway: checking 'from' tipset: %w", err)
}
if err := gw.checkTipsetKey(ctx, to); err != nil {
return nil, xerrors.Errorf("gateway: checking 'to' tipset: %w", err)
}
return gw.target.ChainGetPath(ctx, from, to)
}
func (gw *Node) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainGetGenesis(ctx)
}
func (gw *Node) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
return nil, err
}
return gw.target.ChainReadObj(ctx, c)
}
func (gw *Node) ChainPutObj(context.Context, blocks.Block) error {
return xerrors.New("not supported")
}
func (gw *Node) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.GasEstimateMessageGas(ctx, msg, spec, tsk)
}
func (gw *Node) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return cid.Cid{}, err
}
// TODO: additional anti-spam checks
return gw.target.MpoolPushUntrusted(ctx, sm)
}
func (gw *Node) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return types.BigInt{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return types.NewInt(0), err
}
return gw.target.MsigGetAvailableBalance(ctx, addr, tsk)
}
func (gw *Node) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return types.BigInt{}, err
}
if err := gw.checkTipsetKey(ctx, start); err != nil {
return types.NewInt(0), err
}
if err := gw.checkTipsetKey(ctx, end); err != nil {
return types.NewInt(0), err
}
return gw.target.MsigGetVested(ctx, addr, start, end)
}
func (gw *Node) MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MsigVesting, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return api.MsigVesting{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.MsigVesting{}, err
}
return gw.target.MsigGetVestingSchedule(ctx, addr, tsk)
}
func (gw *Node) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) {
if err := gw.limit(ctx, walletRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.MsigGetPending(ctx, addr, tsk)
}
func (gw *Node) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return address.Address{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return address.Undef, err
}
return gw.target.StateAccountKey(ctx, addr, tsk)
}
func (gw *Node) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.DealCollateralBounds{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.DealCollateralBounds{}, err
}
return gw.target.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
}
func (gw *Node) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateGetActor(ctx, actor, tsk)
}
func (gw *Node) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateListMiners(ctx, tsk)
}
func (gw *Node) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return address.Address{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return address.Undef, err
}
return gw.target.StateLookupID(ctx, addr, tsk)
}
func (gw *Node) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.MarketBalance{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.MarketBalance{}, err
}
return gw.target.StateMarketBalance(ctx, addr, tsk)
}
func (gw *Node) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMarketStorageDeal(ctx, dealId, tsk)
}
func (gw *Node) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return network.VersionMax, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return network.VersionMax, err
}
return gw.target.StateNetworkVersion(ctx, tsk)
}
func (gw *Node) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if limit == api.LookbackNoLimit {
limit = gw.stateWaitLookbackLimit
}
if gw.stateWaitLookbackLimit != api.LookbackNoLimit && limit > gw.stateWaitLookbackLimit {
limit = gw.stateWaitLookbackLimit
}
if err := gw.checkTipsetKey(ctx, from); err != nil {
return nil, err
}
return gw.target.StateSearchMsg(ctx, from, msg, limit, allowReplaced)
}
func (gw *Node) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if limit == api.LookbackNoLimit {
limit = gw.stateWaitLookbackLimit
}
if gw.stateWaitLookbackLimit != api.LookbackNoLimit && limit > gw.stateWaitLookbackLimit {
limit = gw.stateWaitLookbackLimit
}
return gw.target.StateWaitMsg(ctx, msg, confidence, limit, allowReplaced)
}
func (gw *Node) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateReadState(ctx, actor, tsk)
}
func (gw *Node) StateMinerPower(ctx context.Context, m address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMinerPower(ctx, m, tsk)
}
func (gw *Node) StateMinerFaults(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return bitfield.BitField{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return bitfield.BitField{}, err
}
return gw.target.StateMinerFaults(ctx, m, tsk)
}
func (gw *Node) StateMinerRecoveries(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return bitfield.BitField{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return bitfield.BitField{}, err
}
return gw.target.StateMinerRecoveries(ctx, m, tsk)
}
func (gw *Node) StateMinerInfo(ctx context.Context, m address.Address, tsk types.TipSetKey) (api.MinerInfo, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.MinerInfo{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.MinerInfo{}, err
}
return gw.target.StateMinerInfo(ctx, m, tsk)
}
func (gw *Node) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]api.Deadline, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMinerDeadlines(ctx, m, tsk)
}
func (gw *Node) StateMinerAvailableBalance(ctx context.Context, m address.Address, tsk types.TipSetKey) (types.BigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return types.BigInt{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return types.BigInt{}, err
}
return gw.target.StateMinerAvailableBalance(ctx, m, tsk)
}
func (gw *Node) StateMinerProvingDeadline(ctx context.Context, m address.Address, tsk types.TipSetKey) (*dline.Info, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateMinerProvingDeadline(ctx, m, tsk)
}
func (gw *Node) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return abi.TokenAmount{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return abi.TokenAmount{}, err
}
return gw.target.StateCirculatingSupply(ctx, tsk)
}
func (gw *Node) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateSectorGetInfo(ctx, maddr, n, tsk)
}
func (gw *Node) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return gw.target.StateVerifiedClientStatus(ctx, addr, tsk)
}
func (gw *Node) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.CirculatingSupply{}, err
}
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
return api.CirculatingSupply{}, err
}
return gw.target.StateVMCirculatingSupplyInternal(ctx, tsk)
}
func (gw *Node) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return false, err
}
return sigs.Verify(sig, k, msg) == nil, nil
}
func (gw *Node) WalletBalance(ctx context.Context, k address.Address) (types.BigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return types.BigInt{}, err
}
return gw.target.WalletBalance(ctx, k)
}

View File

@ -152,8 +152,8 @@ var ChainNode = Options(
Override(new(full.MpoolModuleAPI), From(new(api.Gateway))),
Override(new(full.StateModuleAPI), From(new(api.Gateway))),
Override(new(stmgr.StateManagerAPI), rpcstmgr.NewRPCStateManager),
// this to make tests pass, but we should consider actually implementing it in the gateway
Override(new(full.EthModuleAPI), new(full.EthModuleDummy)),
Override(new(full.EthModuleAPI), From(new(api.Gateway))),
Override(new(full.EthEventAPI), From(new(api.Gateway))),
),
// Full node API / service startup
@ -259,7 +259,8 @@ func ConfigFullNode(c interface{}) Option {
// Actor event filtering support
Override(new(events.EventAPI), From(new(modules.EventAPI))),
Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.ActorEvent)),
// in lite-mode Eth event api is provided by gateway
ApplyIf(isFullNode, Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.ActorEvent))),
)
}

View File

@ -79,44 +79,7 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server
rpcServer.Register("Filecoin", hnd)
rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover")
// 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_feeHistory", "Filecoin.EthFeeHistory")
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("eth_estimateGas", "Filecoin.EthEstimateGas")
rpcServer.AliasMethod("eth_call", "Filecoin.EthCall")
rpcServer.AliasMethod("eth_getLogs", "Filecoin.EthGetLogs")
rpcServer.AliasMethod("eth_getFilterChanges", "Filecoin.EthGetFilterChanges")
rpcServer.AliasMethod("eth_getFilterLogs", "Filecoin.EthGetFilterLogs")
rpcServer.AliasMethod("eth_newFilter", "Filecoin.EthNewFilter")
rpcServer.AliasMethod("eth_newBlockFilter", "Filecoin.EthNewBlockFilter")
rpcServer.AliasMethod("eth_newPendingTransactionFilter", "Filecoin.EthNewPendingTransactionFilter")
rpcServer.AliasMethod("eth_uninstallFilter", "Filecoin.EthUninstallFilter")
rpcServer.AliasMethod("eth_subscribe", "Filecoin.EthSubscribe")
rpcServer.AliasMethod("eth_unsubscribe", "Filecoin.EthUnsubscribe")
rpcServer.AliasMethod("net_version", "Filecoin.NetVersion")
rpcServer.AliasMethod("net_listening", "Filecoin.NetListening")
api.CreateEthRPCAliases(rpcServer)
var handler http.Handler = rpcServer
if permissioned {
@ -144,7 +107,6 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server
Next: handleImportFunc,
}
m.Handle("/rest/v0/import", importAH)
exportAH := &auth.Handler{
Verify: a.AuthVerify,
Next: handleExportFunc,