Skip to content

Commit 8c51a81

Browse files
authored
feat(eth)!: add Eth APIs to /v2 + minor improvements & fixes (#13026)
1 parent f7af37d commit 8c51a81

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+11426
-2990
lines changed

CHANGELOG.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,35 @@
1313
- fix(deps): fix Ledger hardware wallet support ([filecoin-project/lotus#13048](https://github.com/filecoin-project/lotus/pull/13048))
1414
- fix(eth): always return nil for eth transactions not found ([filecoin-project/lotus#12999](https://github.com/filecoin-project/lotus/pull/12999))
1515
- feat: add gas to application metric reporting `vm/applyblocks_early_gas`, `vm/applyblocks_messages_gas`, `vm/applyblocks_cron_gas` ([filecoin-project/lotus#13030](https://github.com/filecoin-project/lotus/pull/13030))
16-
- feat: add Lotus v2 experimental APIs with F3 awareness
17-
The Lotus V2 APIs introduce a powerful new TipSet selection mechanism that significantly enhances how applications interact with the Filecoin blockchain. The design reduces API footprint, seamlessly handles both traditional Expected Consensus and the new F3 protocol, and provides graceful fallbacks. See [Filecoin v2 APIs](https://filoznotebook.notion.site/Filecoin-V2-APIs-1d0dc41950c1808b914de5966d501658) for an
18-
in-depth overview.
19-
Pull requests:
20-
- https://github.com/filecoin-project/lotus/pull/13003
21-
- https://github.com/filecoin-project/lotus/pull/13027
22-
- https://github.com/filecoin-project/lotus/pull/13034
16+
17+
### Experimental v2 APIs with F3 awareness
18+
19+
The Lotus V2 APIs introduce a powerful new TipSet selection mechanism that significantly enhances how applications interact with the Filecoin blockchain. The design reduces API footprint, seamlessly handles both traditional Expected Consensus (EC) and the new F3 protocol, and provides graceful fallbacks.
20+
21+
> [!NOTE]
22+
> V2 APIs are highly experimental and subject to change without notice.
23+
24+
> [!IMPORTANT]
25+
> The `/v2` APIs rely on F3 data even if F3 is not yet finalizing the chain (i.e., `EC.Finalize` is `false` in the live F3 manifest used by all participants). To determine if F3 is actively finalizing, call the `F3GetManifest` API and check if `Manifest.EC.Finalize` is `true`. Only when `EC.Finalize` is `true` will the `/v2` `"finalized"` and `"safe"` tags accurately reflect the chain's finality according to F3. This also applies to Ethereum APIs discussed below.
26+
27+
See [Filecoin v2 APIs](https://filoznotebook.notion.site/Filecoin-V2-APIs-1d0dc41950c1808b914de5966d501658) for an in-depth overview. ([filecoin-project/lotus#13003](https://github.com/filecoin-project/lotus/pull/13003)), ([filecoin-project/lotus#13027](https://github.com/filecoin-project/lotus/pull/13027)), ([filecoin-project/lotus#13034](https://github.com/filecoin-project/lotus/pull/13034))
28+
29+
**F3-aware Ethereum APIs via `/v2` endpoint and improvements to existing `/v1` APIs** ([filecoin-project/lotus#13026](https://github.com/filecoin-project/lotus/pull/13026))
30+
31+
Lotus now offers two versions of its Ethereum-compatible APIs (`eth_*`, `trace_*`, `net_*`, `web3_*` and associated `Filecoin.*` APIs including Filecoin-specific functions such as `Filecoin.EthAddressToFilecoinAddress` and `Filecoin.FilecoinAddressToEthAddress`) with different finality handling:
32+
* **`/v2` APIs (New & Experimental):** These APIs consult the F3 subsystem (if enabled) for finality information.
33+
* `"finalized"` tag maps to the F3 finalized epoch.
34+
* `"safe"` tag maps to the F3 finalized epoch or 200 epochs behind head, whichever is more recent.
35+
* **`/v1` APIs (Existing & Recommended):** These maintain behavior closer to pre-F3 Lotus (EC finality) for compatibility.
36+
* `"finalized"` tag continues to use a fixed 900-epoch delay from the head (EC finality).
37+
* `"safe"` tag uses a 30-epoch delay from the head.
38+
* _One or both of these tags may be adjusted in a future upgrade to take advantage of F3 finality._
39+
* **Note:** Previously, `"finalized"` and `"safe"` tags referred to epochs `N-1`. This `-1` offset has been removed in both V1 and V2.
40+
* Additional improvements affecting **both `/v1` and `/v2`** Ethereum APIs:
41+
* `eth_getBlockTransactionCountByNumber` now accepts standard Ethereum block specifiers (hex numbers _or_ tags like `"latest"`, `"safe"`, `"finalized"`).
42+
* Methods accepting `BlockNumberOrHash` now support all standard tags (`"pending"`, `"latest"`, `"safe"`, `"finalized"`). This includes `eth_estimateGas`, `eth_call`, `eth_getCode`, `eth_getStorageAt`, `eth_getBalance`, `eth_getTransactionCount`, and `eth_getBlockReceipts`.
43+
* Removed internal `Eth*Limited` methods (e.g., `EthGetTransactionByHashLimited`) from the supported gateway API surface.
44+
* Improved error handling: block selection endpoints now consistently return `ErrNullRound` (and corresponding JSONRPC errors) for null tipsets.
2345

2446
# Node and Miner v1.32.2 / 2025-04-04
2547

api/api_full.go

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -841,23 +841,23 @@ type FullNode interface {
841841
// EthBlockNumber returns the height of the latest (heaviest) TipSet
842842
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
843843
// EthGetBlockTransactionCountByNumber returns the number of messages in the TipSet
844-
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error) //perm:read
844+
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum string) (ethtypes.EthUint64, error) //perm:read
845845
// EthGetBlockTransactionCountByHash returns the number of messages in the TipSet
846846
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) //perm:read
847847

848-
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read
849-
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read
850-
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) //perm:read
851-
EthGetTransactionByHashLimited(ctx context.Context, txHash *ethtypes.EthHash, limit abi.ChainEpoch) (*ethtypes.EthTx, error) //perm:read
852-
EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) //perm:read
853-
EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) //perm:read
854-
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) //perm:read
855-
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*EthTxReceipt, error) //perm:read
856-
EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*EthTxReceipt, error) //perm:read
857-
EthGetBlockReceiptsLimited(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*EthTxReceipt, error) //perm:read
858-
EthGetTransactionReceiptLimited(ctx context.Context, txHash ethtypes.EthHash, limit abi.ChainEpoch) (*EthTxReceipt, error) //perm:read
859-
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (*ethtypes.EthTx, error) //perm:read
860-
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum string, txIndex ethtypes.EthUint64) (*ethtypes.EthTx, error) //perm:read
848+
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read
849+
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read
850+
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) //perm:read
851+
EthGetTransactionByHashLimited(ctx context.Context, txHash *ethtypes.EthHash, limit abi.ChainEpoch) (*ethtypes.EthTx, error) //perm:read
852+
EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) //perm:read
853+
EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) //perm:read
854+
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error) //perm:read
855+
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*ethtypes.EthTxReceipt, error) //perm:read
856+
EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*ethtypes.EthTxReceipt, error) //perm:read
857+
EthGetBlockReceiptsLimited(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*ethtypes.EthTxReceipt, error) //perm:read
858+
EthGetTransactionReceiptLimited(ctx context.Context, txHash ethtypes.EthHash, limit abi.ChainEpoch) (*ethtypes.EthTxReceipt, error) //perm:read
859+
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (*ethtypes.EthTx, error) //perm:read
860+
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum string, txIndex ethtypes.EthUint64) (*ethtypes.EthTx, error) //perm:read
861861

862862
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) //perm:read
863863
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) //perm:read
@@ -1456,20 +1456,4 @@ type HotGCOpts struct {
14561456
Moving bool
14571457
}
14581458

1459-
type EthTxReceipt struct {
1460-
TransactionHash ethtypes.EthHash `json:"transactionHash"`
1461-
TransactionIndex ethtypes.EthUint64 `json:"transactionIndex"`
1462-
BlockHash ethtypes.EthHash `json:"blockHash"`
1463-
BlockNumber ethtypes.EthUint64 `json:"blockNumber"`
1464-
From ethtypes.EthAddress `json:"from"`
1465-
To *ethtypes.EthAddress `json:"to"`
1466-
StateRoot ethtypes.EthHash `json:"root"`
1467-
Status ethtypes.EthUint64 `json:"status"`
1468-
ContractAddress *ethtypes.EthAddress `json:"contractAddress"`
1469-
CumulativeGasUsed ethtypes.EthUint64 `json:"cumulativeGasUsed"`
1470-
GasUsed ethtypes.EthUint64 `json:"gasUsed"`
1471-
EffectiveGasPrice ethtypes.EthBigInt `json:"effectiveGasPrice"`
1472-
LogsBloom ethtypes.EthBytes `json:"logsBloom"`
1473-
Logs []ethtypes.EthLog `json:"logs"`
1474-
Type ethtypes.EthUint64 `json:"type"`
1475-
}
1459+
type EthTxReceipt = ethtypes.EthTxReceipt // Deprecated: use ethtypes.EthTxReceipt instead

api/api_gateway.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,11 @@ import (
3535
// * Generate openrpc blobs
3636

3737
type Gateway interface {
38-
MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error)
3938
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
40-
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error)
41-
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
42-
GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
43-
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
4439
ChainHasObj(context.Context, cid.Cid) (bool, error)
4540
ChainPutObj(context.Context, blocks.Block) error
4641
ChainHead(ctx context.Context) (*types.TipSet, error)
42+
ChainGetEvents(context.Context, cid.Cid) ([]types.Event, error)
4743
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
4844
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
4945
ChainGetMessagesInTipset(context.Context, types.TipSetKey) ([]Message, error)
@@ -56,15 +52,22 @@ type Gateway interface {
5652
ChainNotify(context.Context) (<-chan []*HeadChange, error)
5753
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
5854
ChainGetGenesis(context.Context) (*types.TipSet, error)
55+
56+
GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
5957
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
58+
6059
MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error)
60+
MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error)
6161
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
62+
6263
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
6364
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error)
6465
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
6566
MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MsigVesting, error)
67+
6668
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
6769
StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*InvocResult, error)
70+
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
6871
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
6972
StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error)
7073
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
@@ -83,34 +86,33 @@ type Gateway interface {
8386
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]Deadline, error)
8487
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
8588
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
89+
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
8690
StateNetworkName(context.Context) (dtypes.NetworkName, error)
8791
StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error)
8892
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error)
8993
StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
9094
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
9195
StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error)
9296
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error)
97+
98+
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error)
99+
93100
WalletBalance(context.Context, address.Address) (types.BigInt, error)
94-
Version(context.Context) (APIVersion, error)
95-
Discover(context.Context) (apitypes.OpenRPCDocument, error)
96101

97102
EthAddressToFilecoinAddress(ctx context.Context, ethAddress ethtypes.EthAddress) (address.Address, error)
98103
FilecoinAddressToEthAddress(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthAddress, error)
99104
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
100105
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
101-
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error)
106+
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum string) (ethtypes.EthUint64, error)
102107
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error)
103108
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error)
104109
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error)
105110
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error)
106-
EthGetTransactionByHashLimited(ctx context.Context, txHash *ethtypes.EthHash, limit abi.ChainEpoch) (*ethtypes.EthTx, error)
107111
EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error)
108112
EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error)
109113
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthUint64, error)
110-
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*EthTxReceipt, error)
111-
EthGetTransactionReceiptLimited(ctx context.Context, txHash ethtypes.EthHash, limit abi.ChainEpoch) (*EthTxReceipt, error)
112-
EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*EthTxReceipt, error)
113-
EthGetBlockReceiptsLimited(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*EthTxReceipt, error)
114+
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*ethtypes.EthTxReceipt, error)
115+
EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*ethtypes.EthTxReceipt, error)
114116
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
115117
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
116118
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBigInt, error)
@@ -143,8 +145,10 @@ type Gateway interface {
143145
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, index ethtypes.EthUint64) (*ethtypes.EthTx, error)
144146
GetActorEventsRaw(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error)
145147
SubscribeActorEventsRaw(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error)
146-
ChainGetEvents(context.Context, cid.Cid) ([]types.Event, error)
147148

148149
F3GetCertificate(ctx context.Context, instance uint64) (*certs.FinalityCertificate, error)
149150
F3GetLatestCertificate(ctx context.Context) (*certs.FinalityCertificate, error)
151+
152+
Version(context.Context) (APIVersion, error)
153+
Discover(context.Context) (apitypes.OpenRPCDocument, error)
150154
}

0 commit comments

Comments
 (0)