Merge branch 'release/v1.20.0' into asr/merge-release-into-master
This commit is contained in:
commit
8ff55c027e
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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.
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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), 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
|
||||
}
|
||||
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), 16, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eint := EthUint64(parsedInt)
|
||||
*e = 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, ¶ms)
|
||||
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})
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2332,11 +2332,7 @@ Perms: read
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"0x5",
|
||||
"string value",
|
||||
[
|
||||
12.3
|
||||
]
|
||||
"Bw=="
|
||||
]
|
||||
```
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
@ -67,7 +67,8 @@ func TestEthAccountAbstraction(t *testing.T) {
|
||||
msgFromPlaceholder := &types.Message{
|
||||
From: placeholderAddress,
|
||||
// self-send because an "eth tx payload" can't be to a filecoin address?
|
||||
To: placeholderAddress,
|
||||
To: placeholderAddress,
|
||||
Method: builtin2.MethodsEVM.InvokeContract,
|
||||
}
|
||||
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
@ -100,9 +101,10 @@ func TestEthAccountAbstraction(t *testing.T) {
|
||||
// Send another message, it should succeed without any code CID changes
|
||||
|
||||
msgFromPlaceholder = &types.Message{
|
||||
From: placeholderAddress,
|
||||
To: placeholderAddress,
|
||||
Nonce: 1,
|
||||
From: placeholderAddress,
|
||||
To: placeholderAddress,
|
||||
Method: builtin2.MethodsEVM.InvokeContract,
|
||||
Nonce: 1,
|
||||
}
|
||||
|
||||
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
||||
@ -152,9 +154,10 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
|
||||
|
||||
// create a placeholder actor at the target address
|
||||
msgCreatePlaceholder := &types.Message{
|
||||
From: client.DefaultKey.Address,
|
||||
To: placeholderAddress,
|
||||
Value: abi.TokenAmount(types.MustParseFIL("100")),
|
||||
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)
|
||||
@ -172,9 +175,10 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
|
||||
|
||||
// send a message from the placeholder address
|
||||
msgFromPlaceholder := &types.Message{
|
||||
From: placeholderAddress,
|
||||
To: placeholderAddress,
|
||||
Value: abi.TokenAmount(types.MustParseFIL("20")),
|
||||
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)
|
||||
@ -209,10 +213,11 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
|
||||
// Send a valid message now, it should succeed without any code CID changes
|
||||
|
||||
msgFromPlaceholder = &types.Message{
|
||||
From: placeholderAddress,
|
||||
To: placeholderAddress,
|
||||
Nonce: 1,
|
||||
Value: abi.NewTokenAmount(1),
|
||||
From: placeholderAddress,
|
||||
To: placeholderAddress,
|
||||
Nonce: 1,
|
||||
Value: abi.NewTokenAmount(1),
|
||||
Method: builtin2.MethodsEVM.InvokeContract,
|
||||
}
|
||||
|
||||
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
||||
|
@ -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)
|
||||
},
|
||||
},
|
||||
|
||||
|
87
itests/eth_fee_history_test.go
Normal file
87
itests/eth_fee_history_test.go
Normal 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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
Loading…
Reference in New Issue
Block a user