From 620ef5b69d9b5606028afb91be6ad0e89d96a2a9 Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Tue, 4 Mar 2025 09:32:59 +0400 Subject: [PATCH 1/5] optional index start on reconciliation failure --- node/config/types.go | 13 ++++++ node/modules/chainindex.go | 92 ++++++++++++++++++++------------------ 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/node/config/types.go b/node/config/types.go index 3824427b2af..e05ae7f4d94 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -628,6 +628,19 @@ type ChainIndexerConfig struct { // Note: Setting this value too low may result in incomplete indexing, while setting it too high // may increase startup time. MaxReconcileTipsets uint64 + + // AllowIndexReconciliationFailure determines whether node startup should continue + // if the index reconciliation with the chain state fails. + // + // When set to true: + // - If index reconciliation fails during startup, the node will log a warning but continue to start. + // + // When set to false (default): + // - If index reconciliation fails during startup, the node will fail to start. + // - This ensures that the index is always in a consistent state with the chain before the node starts. + // + // Default: false + AllowIndexReconciliationFailure bool } type HarmonyDB struct { diff --git a/node/modules/chainindex.go b/node/modules/chainindex.go index d2307a77600..8c25b8d0c38 100644 --- a/node/modules/chainindex.go +++ b/node/modules/chainindex.go @@ -51,60 +51,66 @@ func ChainIndexer(cfg config.ChainIndexerConfig) func(lc fx.Lifecycle, mctx help } } -func InitChainIndexer(lc fx.Lifecycle, mctx helpers.MetricsCtx, indexer index.Indexer, +func InitChainIndexer(cfg config.ChainIndexerConfig) func(lc fx.Lifecycle, mctx helpers.MetricsCtx, indexer index.Indexer, evapi EventHelperAPI, mp *messagepool.MessagePool, sm *stmgr.StateManager) { - ctx := helpers.LifecycleCtx(mctx, lc) + return func(lc fx.Lifecycle, mctx helpers.MetricsCtx, indexer index.Indexer, + evapi EventHelperAPI, mp *messagepool.MessagePool, sm *stmgr.StateManager) { + ctx := helpers.LifecycleCtx(mctx, lc) - lc.Append(fx.Hook{ - OnStart: func(_ context.Context) error { - indexer.SetActorToDelegatedAddresFunc(func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) { - idAddr, err := address.NewIDAddress(uint64(emitter)) + lc.Append(fx.Hook{ + OnStart: func(_ context.Context) error { + indexer.SetActorToDelegatedAddresFunc(func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) { + idAddr, err := address.NewIDAddress(uint64(emitter)) + if err != nil { + return address.Undef, false + } + + actor, err := sm.LoadActor(ctx, idAddr, ts) + if err != nil || actor.DelegatedAddress == nil { + return idAddr, true + } + + return *actor.DelegatedAddress, true + }) + + indexer.SetRecomputeTipSetStateFunc(func(ctx context.Context, ts *types.TipSet) error { + _, _, err := sm.RecomputeTipSetState(ctx, ts) + return err + }) + + ch, err := mp.Updates(ctx) if err != nil { - return address.Undef, false + return err } + go WaitForMpoolUpdates(ctx, ch, indexer) - actor, err := sm.LoadActor(ctx, idAddr, ts) - if err != nil || actor.DelegatedAddress == nil { - return idAddr, true + ev, err := events.NewEvents(ctx, &evapi) + if err != nil { + return err } - return *actor.DelegatedAddress, true - }) - - indexer.SetRecomputeTipSetStateFunc(func(ctx context.Context, ts *types.TipSet) error { - _, _, err := sm.RecomputeTipSetState(ctx, ts) - return err - }) - - ch, err := mp.Updates(ctx) - if err != nil { - return err - } - go WaitForMpoolUpdates(ctx, ch, indexer) - - ev, err := events.NewEvents(ctx, &evapi) - if err != nil { - return err - } - - // Tipset listener + // Tipset listener - // `ObserveAndBlock` returns the current head and guarantees that it will call the observer with all future tipsets - head, unlockObserver, err := ev.ObserveAndBlock(indexer) - if err != nil { - return xerrors.Errorf("error while observing tipsets: %w", err) - } - if err := indexer.ReconcileWithChain(ctx, head); err != nil { + // `ObserveAndBlock` returns the current head and guarantees that it will call the observer with all future tipsets + head, unlockObserver, err := ev.ObserveAndBlock(indexer) + if err != nil { + return xerrors.Errorf("error while observing tipsets: %w", err) + } + if err := indexer.ReconcileWithChain(ctx, head); err != nil { + unlockObserver() + if !cfg.AllowIndexReconciliationFailure { + return xerrors.Errorf("error while reconciling chain index with chain state: %w", err) + } + log.Warnf("error while reconciling chain index with chain state: %s", err) + } unlockObserver() - return xerrors.Errorf("error while reconciling chain index with chain state: %w", err) - } - unlockObserver() - indexer.Start() + indexer.Start() - return nil - }, - }) + return nil + }, + }) + } } func ChainIndexHandler(cfg config.ChainIndexerConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, index.Indexer) (*full.ChainIndexHandler, error) { From 8aafaa5201b1fff8ed16d53643f2baca23ed700e Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Tue, 4 Mar 2025 09:34:02 +0400 Subject: [PATCH 2/5] warning --- node/config/types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/config/types.go b/node/config/types.go index e05ae7f4d94..ce15554fb05 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -640,6 +640,8 @@ type ChainIndexerConfig struct { // - This ensures that the index is always in a consistent state with the chain before the node starts. // // Default: false + // // WARNING: Only set to true if you are okay with an index that may be out of sync with the chain. + // This can lead to inaccurate or missing data in RPC responses that depend on the indexer. AllowIndexReconciliationFailure bool } From de99773632ac84a0f6ad5f73ffe84e4ace104dee Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Tue, 4 Mar 2025 09:37:13 +0400 Subject: [PATCH 3/5] fix ChangeLog --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13f75670c84..c4f233112f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Lotus changelog -> **Historical Note** +> **Historical Note** > Previous changelog entries are archived in: > * [CHANGELOG_0.x.md](./documentation/changelog/CHANGELOG_0.x.md) - v0.1.0 to v0.9.1 > * [CHANGELOG_1.0x.md](./documentation/changelog/CHANGELOG_1.0x.md) - v1.0.0 to v1.9.0 @@ -8,7 +8,7 @@ > * [CHANGELOG_1.2x.md](./documentation/changelog/CHANGELOG_1.2x.md) - v1.20.0 to v1.29.2 # UNRELEASED - +- Allow users to start node even if Index Reconciliation fails (https://github.com/filecoin-project/lotus/pull/12930) - Exposed `StateGetNetworkParams` in the Lotus Gateway API ([filecoin-project/lotus#12881](https://github.com/filecoin-project/lotus/pull/12881)) - **BREAKING**: Removed `SupportedProofTypes` from `StateGetNetworkParams` response as it was unreliable and didn't match FVM's actual supported proofs ([filecoin-project/lotus#12881](https://github.com/filecoin-project/lotus/pull/12881)) - refactor(eth): attach ToFilecoinMessage converter to EthCall method for improved package/module import structure. This change also exports the converter as a public method, enhancing usability for developers utilizing Lotus as a library. ([filecoin-project/lotus#12844](https://github.com/filecoin-project/lotus/pull/12844)) @@ -170,7 +170,7 @@ Network Version: 24 Actor Version: 15 Manifest CID: bafy2bzaceakwje2hyinucrhgtsfo44p54iw4g6otbv5ghov65vajhxgntr53u -Actor CID +Actor CID account bafk2bzacecia5zacqt4gvd4z7275lnkhgraq75shy63cphakphhw6crf4joii cron bafk2bzacecbyx7utt3tkvhqnfk64kgtlt5jlvv56o2liwczikgzfowk2cvqvk datacap bafk2bzacecrypcpyzidphfl3sf3vhrjbiwzu7w3hoole45wsk2bqpverw4tni From fe0a99850cb732f5ae43fc7b55eafea50f47404f Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Thu, 6 Mar 2025 10:40:27 +0400 Subject: [PATCH 4/5] fix make gen --- node/config/doc_gen.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index feab3d5b6e0..4d13a93ad26 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -132,6 +132,24 @@ Default: 3 * epochsPerDay (approximately 3 days of chain history) Note: Setting this value too low may result in incomplete indexing, while setting it too high may increase startup time.`, }, + { + Name: "AllowIndexReconciliationFailure", + Type: "bool", + + Comment: `AllowIndexReconciliationFailure determines whether node startup should continue +if the index reconciliation with the chain state fails. + +When set to true: +- If index reconciliation fails during startup, the node will log a warning but continue to start. + +When set to false (default): +- If index reconciliation fails during startup, the node will fail to start. +- This ensures that the index is always in a consistent state with the chain before the node starts. + +Default: false +// WARNING: Only set to true if you are okay with an index that may be out of sync with the chain. +This can lead to inaccurate or missing data in RPC responses that depend on the indexer.`, + }, }, "Chainstore": { { From e3c17f34b30ed5d300e8df0717c219767be94b4f Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Thu, 6 Mar 2025 11:11:40 +0400 Subject: [PATCH 5/5] fix compilation --- documentation/en/default-lotus-config.toml | 18 ++++++++++++++++++ node/builder_chain.go | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/documentation/en/default-lotus-config.toml b/documentation/en/default-lotus-config.toml index 1a915593edb..7d7d4caf6de 100644 --- a/documentation/en/default-lotus-config.toml +++ b/documentation/en/default-lotus-config.toml @@ -348,6 +348,24 @@ # env var: LOTUS_CHAININDEXER_MAXRECONCILETIPSETS #MaxReconcileTipsets = 8640 + # AllowIndexReconciliationFailure determines whether node startup should continue + # if the index reconciliation with the chain state fails. + # + # When set to true: + # - If index reconciliation fails during startup, the node will log a warning but continue to start. + # + # When set to false (default): + # - If index reconciliation fails during startup, the node will fail to start. + # - This ensures that the index is always in a consistent state with the chain before the node starts. + # + # Default: false + # // WARNING: Only set to true if you are okay with an index that may be out of sync with the chain. + # This can lead to inaccurate or missing data in RPC responses that depend on the indexer. + # + # type: bool + # env var: LOTUS_CHAININDEXER_ALLOWINDEXRECONCILIATIONFAILURE + #AllowIndexReconciliationFailure = false + [FaultReporter] # EnableConsensusFaultReporter controls whether the node will monitor and diff --git a/node/builder_chain.go b/node/builder_chain.go index c2b6a5c1a38..3748698dc2f 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -332,7 +332,7 @@ func ConfigFullNode(c interface{}) Option { Override(new(index.Indexer), modules.ChainIndexer(cfg.ChainIndexer)), Override(new(full.ChainIndexerAPI), modules.ChainIndexHandler(cfg.ChainIndexer)), If(cfg.ChainIndexer.EnableIndexer, - Override(InitChainIndexerKey, modules.InitChainIndexer), + Override(InitChainIndexerKey, modules.InitChainIndexer(cfg.ChainIndexer)), ), ), )