implement itest and handle optional params

This commit is contained in:
ychiao 2023-02-10 13:33:59 -05:00
parent 37044ed3c3
commit 3c580403c1
15 changed files with 193 additions and 43 deletions

View File

@ -643,6 +643,11 @@ workflows:
suite: itest-eth_deploy
target: "./itests/eth_deploy_test.go"
- test:
name: test-itest-eth_fee_history
suite: itest-eth_fee_history
target: "./itests/eth_fee_history_test.go"
- test:
name: test-itest-eth_filter
suite: itest-eth_filter

View File

@ -786,15 +786,15 @@ type FullNode interface {
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) //perm:read
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) //perm:read
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) //perm:read
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) //perm:read
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) //perm:read
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
NetVersion(ctx context.Context) (string, error) //perm:read
NetListening(ctx context.Context) (bool, error) //perm:read
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read
EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) //perm:read
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) //perm:read
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) //perm:read
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) //perm:read
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
NetVersion(ctx context.Context) (string, error) //perm:read
NetListening(ctx context.Context) (bool, error) //perm:read
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) //perm:read
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) //perm:read

View File

@ -93,7 +93,7 @@ type Gateway interface {
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)
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (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)

View File

@ -1014,18 +1014,18 @@ func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1 interface{}) *gomo
}
// EthFeeHistory mocks base method.
func (m *MockFullNode) EthFeeHistory(arg0 context.Context, arg1 ethtypes.EthUint64, arg2 string, arg3 []float64) (ethtypes.EthFeeHistory, error) {
func (m *MockFullNode) EthFeeHistory(arg0 context.Context, arg1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthFeeHistory", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "EthFeeHistory", arg0, arg1)
ret0, _ := ret[0].(ethtypes.EthFeeHistory)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// EthFeeHistory indicates an expected call of EthFeeHistory.
func (mr *MockFullNodeMockRecorder) EthFeeHistory(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
func (mr *MockFullNodeMockRecorder) EthFeeHistory(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthFeeHistory", reflect.TypeOf((*MockFullNode)(nil).EthFeeHistory), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthFeeHistory", reflect.TypeOf((*MockFullNode)(nil).EthFeeHistory), arg0, arg1)
}
// EthGasPrice mocks base method.

View File

@ -252,7 +252,7 @@ type FullNodeMethods struct {
EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"`
EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `perm:"read"`
EthFeeHistory func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) `perm:"read"`
EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"`
@ -658,7 +658,7 @@ type GatewayMethods struct {
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) ``
EthFeeHistory func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) ``
EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) ``
@ -2051,14 +2051,14 @@ func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *FullNodeStruct) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
func (s *FullNodeStruct) EthFeeHistory(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
if s.Internal.EthFeeHistory == nil {
return *new(ethtypes.EthFeeHistory), ErrNotSupported
}
return s.Internal.EthFeeHistory(p0, p1, p2, p3)
return s.Internal.EthFeeHistory(p0, p1)
}
func (s *FullNodeStub) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
func (s *FullNodeStub) EthFeeHistory(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
return *new(ethtypes.EthFeeHistory), ErrNotSupported
}
@ -4218,14 +4218,14 @@ func (s *GatewayStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (e
return *new(ethtypes.EthUint64), ErrNotSupported
}
func (s *GatewayStruct) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
func (s *GatewayStruct) EthFeeHistory(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
if s.Internal.EthFeeHistory == nil {
return *new(ethtypes.EthFeeHistory), ErrNotSupported
}
return s.Internal.EthFeeHistory(p0, p1, p2, p3)
return s.Internal.EthFeeHistory(p0, p1)
}
func (s *GatewayStub) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
func (s *GatewayStub) EthFeeHistory(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
return *new(ethtypes.EthFeeHistory), ErrNotSupported
}

Binary file not shown.

Binary file not shown.

View File

@ -46,7 +46,11 @@ func (e EthUint64) MarshalJSON() ([]byte, error) {
func (e *EthUint64) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err == nil {
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), 16, 64)
base := 10
if strings.HasPrefix(s, "0x") {
base = 16
}
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), base, 64)
if err != nil {
return err
}
@ -732,3 +736,45 @@ func GetContractEthAddressFromCode(sender EthAddress, salt [32]byte, initcode []
return ethAddr, nil
}
// EthFeeHistoryParams handles raw jsonrpc params for eth_subscribe
type EthFeeHistoryParams struct {
BlkCount EthUint64
NewestBlkNum string
RewardPercentiles *[]float64
}
func (e *EthFeeHistoryParams) UnmarshalJSON(b []byte) error {
var params []json.RawMessage
err := json.Unmarshal(b, &params)
if err != nil {
return err
}
switch len(params) {
case 3:
err = json.Unmarshal(params[2], &e.RewardPercentiles)
if err != nil {
return err
}
fallthrough
case 2:
err = json.Unmarshal(params[1], &e.NewestBlkNum)
if err != nil {
return err
}
err = json.Unmarshal(params[0], &e.BlkCount)
if err != nil {
return err
}
default:
return xerrors.Errorf("expected 2 or 3 params, got %d", len(params))
}
return nil
}
func (e EthFeeHistoryParams) MarshalJSON() ([]byte, error) {
if e.RewardPercentiles != nil {
return json.Marshal([]interface{}{e.BlkCount, e.NewestBlkNum, e.RewardPercentiles})
}
return json.Marshal([]interface{}{e.BlkCount, e.NewestBlkNum})
}

View File

@ -36,6 +36,9 @@ func TestEthIntUnmarshalJSON(t *testing.T) {
{[]byte("\"0x0\""), EthUint64(0)},
{[]byte("\"0x41\""), EthUint64(65)},
{[]byte("\"0x400\""), EthUint64(1024)},
{[]byte("\"0\""), EthUint64(0)},
{[]byte("\"41\""), EthUint64(41)},
{[]byte("\"400\""), EthUint64(400)},
{[]byte("0"), EthUint64(0)},
{[]byte("100"), EthUint64(100)},
{[]byte("1024"), EthUint64(1024)},

View File

@ -2332,11 +2332,7 @@ Perms: read
Inputs:
```json
[
"0x5",
"string value",
[
12.3
]
"Bw=="
]
```

View File

@ -108,7 +108,7 @@ type TargetAPI interface {
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)
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (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)

View File

@ -294,20 +294,25 @@ func (gw *Node) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) {
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) {
func (gw *Node) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
params, err := jsonrpc.DecodeParams[ethtypes.EthFeeHistoryParams](p)
if err != nil {
return ethtypes.EthFeeHistory{}, xerrors.Errorf("decoding params: %w", err)
}
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFeeHistory{}, err
}
if err := gw.checkBlkParam(ctx, newestBlk); err != nil {
if err := gw.checkBlkParam(ctx, params.NewestBlkNum); err != nil {
return ethtypes.EthFeeHistory{}, err
}
if blkCount > ethtypes.EthUint64(EthFeeHistoryMaxBlockCount) {
if params.BlkCount > ethtypes.EthUint64(EthFeeHistoryMaxBlockCount) {
return ethtypes.EthFeeHistory{}, fmt.Errorf("block count too high")
}
return gw.target.EthFeeHistory(ctx, blkCount, newestBlk, rewardPercentiles)
return gw.target.EthFeeHistory(ctx, p)
}
func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) {

View File

@ -0,0 +1,87 @@
package itests
import (
"context"
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
"github.com/filecoin-project/lotus/itests/kit"
"github.com/filecoin-project/lotus/lib/result"
)
func TestEthFeeHistory(t *testing.T) {
require := require.New(t)
kit.QuietAllLogsExcept()
blockTime := 100 * time.Millisecond
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
ens.InterconnectAll().BeginMining(blockTime)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
// Wait for the network to create 20 blocks
<-time.After(20 * blockTime)
history, err := client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{5, "0x10"}),
).Assert(require.NoError))
require.NoError(err)
require.Equal(6, len(history.BaseFeePerGas))
require.Equal(5, len(history.GasUsedRatio))
require.Equal(ethtypes.EthUint64(16-5+1), history.OldestBlock)
history, err = client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{"5", "0x10"}),
).Assert(require.NoError))
require.NoError(err)
require.Equal(6, len(history.BaseFeePerGas))
require.Equal(5, len(history.GasUsedRatio))
require.Equal(ethtypes.EthUint64(16-5+1), history.OldestBlock)
history, err = client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{"0x10", "0x12"}),
).Assert(require.NoError))
require.NoError(err)
require.Equal(17, len(history.BaseFeePerGas))
require.Equal(16, len(history.GasUsedRatio))
require.Equal(ethtypes.EthUint64(18-16+1), history.OldestBlock)
history, err = client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{5, "0x10"}),
).Assert(require.NoError))
require.NoError(err)
require.Equal(6, len(history.BaseFeePerGas))
require.Equal(5, len(history.GasUsedRatio))
require.Equal(ethtypes.EthUint64(16-5+1), history.OldestBlock)
history, err = client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{5, "10"}),
).Assert(require.NoError))
require.NoError(err)
require.Equal(6, len(history.BaseFeePerGas))
require.Equal(5, len(history.GasUsedRatio))
require.Equal(ethtypes.EthUint64(10-5+1), history.OldestBlock)
history, err = client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{5, "10", &[]float64{0.25, 0.50, 0.75}}),
).Assert(require.NoError))
require.NoError(err)
require.Equal(6, len(history.BaseFeePerGas))
require.Equal(5, len(history.GasUsedRatio))
require.Equal(ethtypes.EthUint64(10-5+1), history.OldestBlock)
require.NotNil(history.Reward)
require.Equal(0, len(*history.Reward))
history, err = client.EthFeeHistory(ctx, result.Wrap[jsonrpc.RawParams](
json.Marshal([]interface{}{1025, "10", &[]float64{0.25, 0.50, 0.75}}),
).Assert(require.NoError))
require.Error(err)
}

View File

@ -80,7 +80,7 @@ func (e *EthModuleDummy) EthGetBalance(ctx context.Context, address ethtypes.Eth
return ethtypes.EthBigIntZero, ErrModuleDisabled
}
func (e *EthModuleDummy) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) {
func (e *EthModuleDummy) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
return ethtypes.EthFeeHistory{}, ErrModuleDisabled
}

View File

@ -57,7 +57,7 @@ type EthModuleAPI interface {
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)
EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error)
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error)
EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error)
@ -581,8 +581,12 @@ func (a *EthModule) EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
return ethtypes.EthUint64(build.Eip155ChainId), nil
}
func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlkNum string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) {
if blkCount > 1024 {
func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
params, err := jsonrpc.DecodeParams[ethtypes.EthFeeHistoryParams](p)
if err != nil {
return ethtypes.EthFeeHistory{}, xerrors.Errorf("decoding params: %w", err)
}
if params.BlkCount > 1024 {
return ethtypes.EthFeeHistory{}, fmt.Errorf("block count should be smaller than 1024")
}
@ -590,7 +594,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
// TODO https://github.com/filecoin-project/ref-fvm/issues/1016
var blkNum ethtypes.EthUint64
err := blkNum.UnmarshalJSON([]byte(`"` + newestBlkNum + `"`))
err = blkNum.UnmarshalJSON([]byte(`"` + params.NewestBlkNum + `"`))
if err == nil && uint64(blkNum) < newestBlkHeight {
newestBlkHeight = uint64(blkNum)
}
@ -598,8 +602,8 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
// Deal with the case that the chain is shorter than the number of
// requested blocks.
oldestBlkHeight := uint64(1)
if uint64(blkCount) <= newestBlkHeight {
oldestBlkHeight = newestBlkHeight - uint64(blkCount) + 1
if uint64(params.BlkCount) <= newestBlkHeight {
oldestBlkHeight = newestBlkHeight - uint64(params.BlkCount) + 1
}
ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(newestBlkHeight), nil, false)
@ -633,7 +637,6 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
}
// Reverse the arrays; we collected them newest to oldest; the client expects oldest to newest.
for i, j := 0, len(baseFeeArray)-1; i < j; i, j = i+1, j-1 {
baseFeeArray[i], baseFeeArray[j] = baseFeeArray[j], baseFeeArray[i]
}
@ -641,11 +644,16 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
gasUsedRatioArray[i], gasUsedRatioArray[j] = gasUsedRatioArray[j], gasUsedRatioArray[i]
}
return ethtypes.EthFeeHistory{
ret := ethtypes.EthFeeHistory{
OldestBlock: ethtypes.EthUint64(oldestBlkHeight),
BaseFeePerGas: baseFeeArray,
GasUsedRatio: gasUsedRatioArray,
}, nil
}
if params.RewardPercentiles != nil {
reward := make([][]ethtypes.EthBigInt, 0)
ret.Reward = &reward
}
return ret, nil
}
func (a *EthModule) NetVersion(ctx context.Context) (string, error) {