diff --git a/CHANGELOG.md b/CHANGELOG.md index f8f271a91d1..7fea0805e47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - fix(eth): always return nil for eth transactions not found ([filecoin-project/lotus#12999](https://github.com/filecoin-project/lotus/pull/12999)) - 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)) - feat: fall back to EC if F3 finalized tipeset is older than 900 epochs ([filecoin-project/lotus#13066](https://github.com/filecoin-project/lotus/pull/13066)) - +- feat: fall back to EC finalized tipset if F3 is too far behind in eth APIs ([filecoin-project/lotus#13070](https://github.com/filecoin-project/lotus/pull/13070)) ### Experimental v2 APIs with F3 awareness diff --git a/itests/eth_api_f3_test.go b/itests/eth_api_f3_test.go index 5c7da300b1b..978f124cd25 100644 --- a/itests/eth_api_f3_test.go +++ b/itests/eth_api_f3_test.go @@ -330,6 +330,18 @@ func TestEthAPIWithF3(t *testing.T) { wantTipSetV1: ecSafeV1, wantErrV2: internalF3Error.Error(), }, + { + name: "finalize tag when f3 is too far behind falls back to ec", + blkParam: "finalized", + setup: func(t *testing.T) { + mockF3.Running = true + mockF3.Finalizing = true + mockF3.LatestCert = plausibleCertAt(t, targetHeight-policy.ChainFinality-5) + mockF3.LatestCertErr = nil + }, + wantTipSetV1: ecFinalized, + wantTipSetV2: ecFinalized, + }, { name: "latest tag when f3 fails is ok", blkParam: "latest", diff --git a/node/impl/eth/tipsetresolver.go b/node/impl/eth/tipsetresolver.go index 5dade0aaf2e..67edfb50b4f 100644 --- a/node/impl/eth/tipsetresolver.go +++ b/node/impl/eth/tipsetresolver.go @@ -91,6 +91,18 @@ func (tsr *tipSetResolver) getFinalizedF3TipSet(ctx context.Context) (*types.Tip // F3 is disabled or not ready; fall back to EC finality. return tsr.getFinalizedECTipSet(ctx) } + // Check F3 finalized tipset against the heaviest tipset, and if it is too far + // behind fall back to EC. + head := tsr.cs.GetHeaviestTipSet() + if head == nil { + return nil, xerrors.Errorf("no known heaviest tipset") + } + f3FinalizedHeight := abi.ChainEpoch(cert.ECChain.Head().Epoch) + if head.Height()-f3FinalizedHeight > policy.ChainFinality { + log.Debugw("Falling back to EC finalized tipset as the latest F3 finalized tipset is too far behind", "headHeight", head.Height(), "f3FinalizedHeight", f3FinalizedHeight) + return tsr.getFinalizedECTipSet(ctx) + } + // F3 is finalizing a higher height than EC safe; return F3 tipset return tsr.getFinalizedF3TipSetFromCert(ctx, cert) }