diff --git a/CHANGELOG.md b/CHANGELOG.md index 05caea4f3..38b7d2f38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - feat: metric: export Mpool message count ([filecoin-project/lotus#11361](https://github.com/filecoin-project/lotus/pull/11361)) - feat: sealing: load SectorsSummary from sealing SectorStats instead of calling API each time ([filecoin-project/lotus#11353](https://github.com/filecoin-project/lotus/pull/11353)) - fix: miner info: Show correct sector state counts ([filecoin-project/lotus#11456](https://github.com/filecoin-project/lotus/pull/11456)) +- feat: add support for specifying block number when calling `eth_estimateGas` RPC number which s ## Improvements - fix: Add time slicing to splitstore purging step during compaction to reduce lock congestion [filecoin-project/lotus#11269](https://github.com/filecoin-project/lotus/pull/11269) diff --git a/api/api_full.go b/api/api_full.go index f919bc13b..8a23131af 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -823,9 +823,9 @@ type FullNode interface { 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 - EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) //perm:read + EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read + EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) //perm:read + EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) //perm:read EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) //perm:read diff --git a/api/api_gateway.go b/api/api_gateway.go index 27e725457..63489f31b 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -114,7 +114,7 @@ type Gateway interface { EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, 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) + EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 856d83813..f27aa6f79 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1042,18 +1042,18 @@ func (mr *MockFullNodeMockRecorder) EthChainId(arg0 interface{}) *gomock.Call { } // EthEstimateGas mocks base method. -func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 ethtypes.EthCall, arg2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1) + ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1, arg2) ret0, _ := ret[0].(ethtypes.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } // EthEstimateGas indicates an expected call of EthEstimateGas. -func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthEstimateGas", reflect.TypeOf((*MockFullNode)(nil).EthEstimateGas), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthEstimateGas", reflect.TypeOf((*MockFullNode)(nil).EthEstimateGas), arg0, arg1, arg2) } // EthFeeHistory mocks base method. diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 2d1333495..3c53ba57b 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -255,7 +255,7 @@ type FullNodeMethods struct { EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"` + EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall, p2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) `perm:"read"` EthFeeHistory func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) `perm:"read"` @@ -679,7 +679,7 @@ type GatewayMethods struct { EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `` + EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall, p2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) `` EthFeeHistory func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) `` @@ -2134,14 +2134,14 @@ func (s *FullNodeStub) EthChainId(p0 context.Context) (ethtypes.EthUint64, error return *new(ethtypes.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall, p2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { if s.Internal.EthEstimateGas == nil { return *new(ethtypes.EthUint64), ErrNotSupported } - return s.Internal.EthEstimateGas(p0, p1) + return s.Internal.EthEstimateGas(p0, p1, p2) } -func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall, p2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { return *new(ethtypes.EthUint64), ErrNotSupported } @@ -4400,14 +4400,14 @@ 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) { +func (s *GatewayStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall, p2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { if s.Internal.EthEstimateGas == nil { return *new(ethtypes.EthUint64), ErrNotSupported } - return s.Internal.EthEstimateGas(p0, p1) + return s.Internal.EthEstimateGas(p0, p1, p2) } -func (s *GatewayStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (s *GatewayStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall, p2 ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { return *new(ethtypes.EthUint64), ErrNotSupported } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 29131b824..cbe2471bb 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index cf83f9390..e9c3d096c 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 1dae12101..377f8b4e6 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -2409,7 +2409,8 @@ Inputs: "gasPrice": "0x0", "value": "0x0", "data": "0x07" - } + }, + "string value" ] ``` diff --git a/gateway/node.go b/gateway/node.go index 367e645c1..5c686e774 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -131,7 +131,7 @@ type TargetAPI interface { EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, 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) + EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) diff --git a/gateway/proxy_eth.go b/gateway/proxy_eth.go index e6d433a17..4fc3b2fd6 100644 --- a/gateway/proxy_eth.go +++ b/gateway/proxy_eth.go @@ -353,13 +353,13 @@ func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt return gw.target.EthMaxPriorityFeePerGas(ctx) } -func (gw *Node) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (gw *Node) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (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) + return gw.target.EthEstimateGas(ctx, tx, blkParam) } func (gw *Node) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) { diff --git a/itests/eth_account_abstraction_test.go b/itests/eth_account_abstraction_test.go index 8d92d0a04..62c0083a7 100644 --- a/itests/eth_account_abstraction_test.go +++ b/itests/eth_account_abstraction_test.go @@ -275,7 +275,7 @@ func TestEthAccountAbstractionFailsFromEvmActor(t *testing.T) { gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: ðAddr, Data: contract, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) diff --git a/itests/eth_conformance_test.go b/itests/eth_conformance_test.go index 15b249977..c43dd7dfa 100644 --- a/itests/eth_conformance_test.go +++ b/itests/eth_conformance_test.go @@ -35,7 +35,7 @@ type ethAPIRaw struct { EthBlockNumber func(context.Context) (json.RawMessage, error) EthCall func(context.Context, ethtypes.EthCall, ethtypes.EthBlockNumberOrHash) (json.RawMessage, error) EthChainId func(context.Context) (json.RawMessage, error) - EthEstimateGas func(context.Context, ethtypes.EthCall) (json.RawMessage, error) + EthEstimateGas func(context.Context, ethtypes.EthCall, ethtypes.EthBlockNumberOrHash) (json.RawMessage, error) EthFeeHistory func(context.Context, ethtypes.EthUint64, string, []float64) (json.RawMessage, error) EthGasPrice func(context.Context) (json.RawMessage, error) EthGetBalance func(context.Context, ethtypes.EthAddress, ethtypes.EthBlockNumberOrHash) (json.RawMessage, error) @@ -185,7 +185,7 @@ func TestEthOpenRPCConformance(t *testing.T) { return ethapi.EthEstimateGas(context.Background(), ethtypes.EthCall{ From: &senderEthAddr, Data: contractBin, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) }, }, @@ -451,7 +451,7 @@ func createRawSignedEthTx(ctx context.Context, t *testing.T, client *kit.TestFul gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: &senderEthAddr, Data: contractBin, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) diff --git a/itests/eth_deploy_test.go b/itests/eth_deploy_test.go index ce4c94a28..422bc3449 100644 --- a/itests/eth_deploy_test.go +++ b/itests/eth_deploy_test.go @@ -63,7 +63,7 @@ func TestDeployment(t *testing.T) { gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: ðAddr, Data: contract, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) diff --git a/itests/eth_hash_lookup_test.go b/itests/eth_hash_lookup_test.go index e1474a90d..dd3980867 100644 --- a/itests/eth_hash_lookup_test.go +++ b/itests/eth_hash_lookup_test.go @@ -50,7 +50,7 @@ func TestTransactionHashLookup(t *testing.T) { gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: ðAddr, Data: contract, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) @@ -353,7 +353,7 @@ func TestEthGetMessageCidByTransactionHashEthTx(t *testing.T) { gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: ðAddr, Data: contract, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) diff --git a/itests/eth_transactions_test.go b/itests/eth_transactions_test.go index 026ac2387..0039ebde0 100644 --- a/itests/eth_transactions_test.go +++ b/itests/eth_transactions_test.go @@ -47,7 +47,7 @@ func TestValueTransferValidSignature(t *testing.T) { gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: ðAddr, Data: contract, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) @@ -235,7 +235,7 @@ func TestContractInvocation(t *testing.T) { From: ðAddr, To: &contractAddr, Data: params, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) @@ -353,7 +353,7 @@ func deployContractTx(ctx context.Context, client *kit.TestFullNode, ethAddr eth gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ From: ðAddr, Data: contract, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) if err != nil { return nil, err } diff --git a/itests/fevm_test.go b/itests/fevm_test.go index cb69c036c..7b09ac7f9 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -661,7 +661,7 @@ func TestFEVMRecursiveActorCallEstimate(t *testing.T) { From: ðAddr, To: &contractAddr, Data: params, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) require.LessOrEqual(t, int64(gaslimit), build.BlockGasLimit) @@ -820,7 +820,7 @@ func TestFEVMBareTransferTriggersSmartContractLogic(t *testing.T) { From: &accntEth, To: &contractEth, Value: ethtypes.EthBigInt(big.NewInt(100)), - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.NoError(t, err) maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) @@ -1037,7 +1037,7 @@ func TestFEVMErrorParsing(t *testing.T) { _, err := e.EthEstimateGas(ctx, ethtypes.EthCall{ To: &contractAddrEth, Data: entryPoint, - }) + }, ethtypes.NewEthBlockNumberOrHashFromPredefined("latest")) require.ErrorContains(t, err, expected) }) }) diff --git a/node/impl/full/dummy.go b/node/impl/full/dummy.go index 743eadf34..857b4c57f 100644 --- a/node/impl/full/dummy.go +++ b/node/impl/full/dummy.go @@ -122,7 +122,7 @@ func (e *EthModuleDummy) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, e return ethtypes.EthBigIntZero, ErrModuleDisabled } -func (e *EthModuleDummy) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (e *EthModuleDummy) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { return 0, ErrModuleDisabled } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 22f78e723..12a9d56ea 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -66,7 +66,7 @@ type EthModuleAPI interface { NetListening(ctx context.Context) (bool, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) - EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) + EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) @@ -1007,7 +1007,7 @@ func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message, tsk ty return res, nil } -func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) { +func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) { msg, err := ethCallToFilecoinMessage(ctx, tx) if err != nil { return ethtypes.EthUint64(0), err @@ -1017,7 +1017,11 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et // gas estimation actually run. msg.GasLimit = 0 - ts := a.Chain.GetHeaviestTipSet() + ts, err := getTipsetByEthBlockNumberOrHash(ctx, a.Chain, blkParam) + if err != nil { + return ethtypes.EthUint64(0), xerrors.Errorf("failed to process block param: %v; %w", blkParam, err) + } + gassedMsg, err := a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key()) if err != nil { // On failure, GasEstimateMessageGas doesn't actually return the invocation result,