Merge branch 'release/v1.20.0' into asr/merge-release-into-master

This commit is contained in:
Raúl Kripalani 2023-02-13 11:45:09 +00:00
commit 8ff55c027e
20 changed files with 316 additions and 117 deletions

View File

@ -704,6 +704,11 @@ workflows:
- build
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
requires:

View File

@ -794,7 +794,7 @@ type FullNode interface {
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
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

@ -117,41 +117,29 @@ func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
default:
return EthTxArgs{}, fmt.Errorf("unsupported EAM method")
}
} else {
} else if msg.Method == builtintypes.MethodsEVM.InvokeContract {
addr, err := EthAddressFromFilecoinAddress(msg.To)
if err != nil {
return EthTxArgs{}, err
}
to = &addr
if len(msg.Params) == 0 {
if msg.Method != builtintypes.MethodSend {
return EthTxArgs{}, xerrors.Errorf("cannot invoke method %d on non-EAM actor without params", msg.Method)
}
} else {
if msg.Method != builtintypes.MethodsEVM.InvokeContract {
return EthTxArgs{},
xerrors.Errorf("invalid methodnum %d: only allowed non-send method is InvokeContract(%d)",
msg.Method,
builtintypes.MethodsEVM.InvokeContract)
}
if len(msg.Params) > 0 {
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
if err != nil {
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
}
}
} else {
return EthTxArgs{},
xerrors.Errorf("invalid methodnum %d: only allowed method is InvokeContract(%d)",
msg.Method, builtintypes.MethodsEVM.InvokeContract)
}
if paramsReader.Len() != 0 {
return EthTxArgs{}, xerrors.Errorf("extra data found in params")
}
if len(params) == 0 && msg.Method != builtintypes.MethodSend {
// Otherwise, we don't get a guaranteed round-trip.
return EthTxArgs{}, xerrors.Errorf("msgs with empty parameters from an eth-account must be Sends (MethodNum: %d)", msg.Method)
}
return EthTxArgs{
ChainID: build.Eip155ChainId,
Nonce: int(msg.Nonce),
@ -170,9 +158,9 @@ func (tx *EthTxArgs) ToUnsignedMessage(from address.Address) (*types.Message, er
}
var err error
method := builtintypes.MethodSend
var params []byte
var to address.Address
method := builtintypes.MethodsEVM.InvokeContract
// nil indicates the EAM, only CreateExternal is allowed
if tx.To == nil {
to = builtintypes.EthereumAddressManagerActorAddr
@ -192,18 +180,11 @@ func (tx *EthTxArgs) ToUnsignedMessage(from address.Address) (*types.Message, er
if err != nil {
return nil, xerrors.Errorf("failed to convert To into filecoin addr: %w", err)
}
if len(tx.Input) == 0 {
// Yes, this is redundant, but let's be sure what we're doing
method = builtintypes.MethodSend
params = make([]byte, 0)
} else {
// must be InvokeContract
method = builtintypes.MethodsEVM.InvokeContract
if len(tx.Input) > 0 {
buf := new(bytes.Buffer)
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
return nil, xerrors.Errorf("failed to write input args: %w", err)
}
params = buf.Bytes()
}
}

View File

@ -33,18 +33,29 @@ func (e EthUint64) MarshalJSON() ([]byte, error) {
return json.Marshal(e.Hex())
}
// UnmarshalJSON should be able to parse these types of input:
// 1. a JSON string containing a hex-encoded uint64 starting with 0x
// 2. a JSON string containing an uint64 in decimal
// 3. a string containing an uint64 in decimal
func (e *EthUint64) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
if err := json.Unmarshal(b, &s); err == nil {
base := 10
if strings.HasPrefix(s, "0x") {
base = 16
}
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), 16, 64)
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), base, 64)
if err != nil {
return err
}
eint := EthUint64(parsedInt)
*e = eint
return nil
} else if eint, err := strconv.ParseUint(string(b), 10, 64); err == nil {
*e = EthUint64(eint)
return nil
}
return fmt.Errorf("cannot interpret %s as a hex-encoded uint64, or a number", string(b))
}
func EthUint64FromHex(s string) (EthUint64, error) {
@ -719,3 +730,45 @@ func GetContractEthAddressFromCode(sender EthAddress, salt [32]byte, initcode []
return ethAddr, nil
}
// EthFeeHistoryParams handles raw jsonrpc params for eth_feeHistory
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,13 +36,19 @@ 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)},
}
for _, tc := range testcases {
var i EthUint64
err := i.UnmarshalJSON(tc.Input.([]byte))
require.Nil(t, err)
require.Equal(t, i, tc.Output)
require.Equal(t, tc.Output, i)
}
}

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

@ -24,7 +24,7 @@ import (
"github.com/filecoin-project/lotus/itests/kit"
)
// TestEthAccountAbstraction goes over the account abstraction workflow:
// TestEthAccountAbstraction goes over the placeholder creation and promotion workflow:
// - an placeholder is created when it receives a message
// - the placeholder turns into an EOA when it sends a message
func TestEthAccountAbstraction(t *testing.T) {
@ -68,6 +68,7 @@ func TestEthAccountAbstraction(t *testing.T) {
From: placeholderAddress,
// self-send because an "eth tx payload" can't be to a filecoin address?
To: placeholderAddress,
Method: builtin2.MethodsEVM.InvokeContract,
}
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
require.NoError(t, err)
@ -102,6 +103,7 @@ func TestEthAccountAbstraction(t *testing.T) {
msgFromPlaceholder = &types.Message{
From: placeholderAddress,
To: placeholderAddress,
Method: builtin2.MethodsEVM.InvokeContract,
Nonce: 1,
}
@ -155,6 +157,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
From: client.DefaultKey.Address,
To: placeholderAddress,
Value: abi.TokenAmount(types.MustParseFIL("100")),
Method: builtin2.MethodsEVM.InvokeContract,
}
smCreatePlaceholder, err := client.MpoolPushMessage(ctx, msgCreatePlaceholder, nil)
require.NoError(t, err)
@ -175,6 +178,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
From: placeholderAddress,
To: placeholderAddress,
Value: abi.TokenAmount(types.MustParseFIL("20")),
Method: builtin2.MethodsEVM.InvokeContract,
}
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
require.NoError(t, err)
@ -213,6 +217,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
To: placeholderAddress,
Nonce: 1,
Value: abi.NewTokenAmount(1),
Method: builtin2.MethodsEVM.InvokeContract,
}
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)

View File

@ -192,7 +192,7 @@ func TestEthOpenRPCConformance(t *testing.T) {
{
method: "eth_feeHistory",
call: func(a *ethAPIRaw) (json.RawMessage, error) {
return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "", nil)
return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "latest", nil)
},
},

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

@ -8,6 +8,7 @@ import (
"encoding/hex"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
@ -17,6 +18,7 @@ import (
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/manifest"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
@ -786,3 +788,58 @@ func TestFEVMDestroyCreate2(t *testing.T) {
require.Equal(t, ethFromAddr, senderSecondCall)
}
func TestFEVMBareTransferTriggersSmartContractLogic(t *testing.T) {
ctx, cancel, client := kit.SetupFEVMTest(t)
defer cancel()
// This contract emits an event on receiving value.
filename := "contracts/ValueSender.hex"
_, contractAddr := client.EVM().DeployContractFromFilename(ctx, filename)
accctKey, accntEth, accntFil := client.EVM().NewAccount()
kit.SendFunds(ctx, t, client, accntFil, types.FromFil(10))
contractEth, err := ethtypes.EthAddressFromFilecoinAddress(contractAddr)
require.NoError(t, err)
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
From: &accntEth,
To: &contractEth,
Value: ethtypes.EthBigInt(big.NewInt(100)),
})
require.NoError(t, err)
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
require.NoError(t, err)
tx := ethtypes.EthTxArgs{
ChainID: build.Eip155ChainId,
Value: big.NewInt(100),
Nonce: 0,
To: &contractEth,
MaxFeePerGas: types.NanoFil,
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
GasLimit: int(gaslimit),
V: big.Zero(),
R: big.Zero(),
S: big.Zero(),
}
client.EVM().SignTransaction(&tx, accctKey.PrivateKey)
hash := client.EVM().SubmitTransaction(ctx, &tx)
var receipt *api.EthTxReceipt
for i := 0; i < 1000; i++ {
receipt, err = client.EthGetTransactionReceipt(ctx, hash)
require.NoError(t, err)
if receipt != nil {
break
}
time.Sleep(500 * time.Millisecond)
}
// The receive() function emits one log, that's how we know we hit it.
require.Len(t, receipt.Logs, 1)
}

View File

@ -354,7 +354,7 @@ func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFull
return ctx, cancel, client
}
func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address, toAddr address.Address, sendAmount big.Int) {
func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address, toAddr address.Address, sendAmount big.Int) *api.MsgLookup {
sendMsg := &types.Message{
From: fromAddr,
To: toAddr,
@ -365,6 +365,7 @@ func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address,
mLookup, err := e.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true)
require.NoError(e.t, err)
require.Equal(e.t, exitcode.Ok, mLookup.Receipt.ExitCode)
return mLookup
}
func NewEthFilterBuilder() *EthFilterBuilder {

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,35 +581,30 @@ 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")
}
newestBlkHeight := uint64(a.Chain.GetHeaviestTipSet().Height())
// TODO https://github.com/filecoin-project/ref-fvm/issues/1016
var blkNum ethtypes.EthUint64
err := blkNum.UnmarshalJSON([]byte(`"` + newestBlkNum + `"`))
if err == nil && uint64(blkNum) < newestBlkHeight {
newestBlkHeight = uint64(blkNum)
}
// 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
}
ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(newestBlkHeight), nil, false)
ts, err := a.parseBlkParam(ctx, params.NewestBlkNum)
if err != nil {
return ethtypes.EthFeeHistory{}, fmt.Errorf("cannot load find block height: %v", newestBlkHeight)
return ethtypes.EthFeeHistory{}, fmt.Errorf("bad block parameter %s: %s", params.NewestBlkNum, err)
}
// FIXME: baseFeePerGas should include the next block after the newest of the returned range, because this
// can be inferred from the newest block. we use the newest block's baseFeePerGas for now but need to fix it
// In other words, due to deferred execution, we might not be returning the most useful value here for the client.
// Deal with the case that the chain is shorter than the number of requested blocks.
oldestBlkHeight := uint64(1)
if abi.ChainEpoch(params.BlkCount) <= ts.Height() {
oldestBlkHeight = uint64(ts.Height()) - uint64(params.BlkCount) + 1
}
// NOTE: baseFeePerGas should include the next block after the newest of the returned range,
// because the next base fee can be inferred from the messages in the newest block.
// However, this is NOT the case in Filecoin due to deferred execution, so the best
// we can do is duplicate the last value.
baseFeeArray := []ethtypes.EthBigInt{ethtypes.EthBigInt(ts.Blocks()[0].ParentBaseFee)}
gasUsedRatioArray := []float64{}
@ -633,7 +628,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 +635,21 @@ 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 {
// TODO: Populate reward percentiles
// https://github.com/filecoin-project/lotus/issues/10236
// We need to calculate the requested percentiles of effective gas premium
// based on the newest block (I presume it's the newest, we need to dig in
// as it's underspecified). Effective means we're clamped at the gas_fee_cap - base_fee.
reward := make([][]ethtypes.EthBigInt, 0)
ret.Reward = &reward
}
return ret, nil
}
func (a *EthModule) NetVersion(ctx context.Context) (string, error) {
@ -761,10 +765,9 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.Et
return nil, fmt.Errorf("failed to encode tx input into a cbor byte-string")
}
params = buf.Bytes()
method = builtintypes.MethodsEVM.InvokeContract
} else {
method = builtintypes.MethodSend
}
method = builtintypes.MethodsEVM.InvokeContract
}
return &types.Message{