Skip to content

Commit aee5a5b

Browse files
aarshkshah1992rjan90
authored andcommitted
fix: allow users to optionally configure node startup even if index reconciliation fails (#12930)
* optional index start on reconciliation failure * warning * fix ChangeLog * fix make gen * fix compilation
1 parent 5103a2e commit aee5a5b

File tree

6 files changed

+106
-48
lines changed

6 files changed

+106
-48
lines changed

CHANGELOG.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
# Lotus changelog
22

3-
> **Historical Note**
3+
> **Historical Note**
44
> Previous changelog entries are archived in:
55
> * [CHANGELOG_0.x.md](./documentation/changelog/CHANGELOG_0.x.md) - v0.1.0 to v0.9.1
66
> * [CHANGELOG_1.0x.md](./documentation/changelog/CHANGELOG_1.0x.md) - v1.0.0 to v1.9.0
77
> * [CHANGELOG_1.1x.md](./documentation/changelog/CHANGELOG_1.1x.md) - v1.10.0 to v1.19.0
88
> * [CHANGELOG_1.2x.md](./documentation/changelog/CHANGELOG_1.2x.md) - v1.20.0 to v1.29.2
99
10-
# UNRELEASED
11-
1210
# UNRELEASED v.1.32.0
1311

1412
See https://github.com/filecoin-project/lotus/blob/release/v1.32.0/CHANGELOG.md
1513

14+
# Special Zondax v1.31.2 tag:
15+
- Allow users to start node even if Index Reconciliation fails (https://github.com/filecoin-project/lotus/pull/12930)
16+
1617
# Node v1.31.1 / 2025-01-27
1718

1819
This Lotus release introduces several new features and improvements, including JSON output for tipsets in `lotus chain list` cmd, enhanced logging during network upgrade migrations, and additional Bootstrap nodes. It also includes a refactored Ethereum API implementation into smaller, more manageable modules in a new `github.com/filecoin-project/lotus/node/impl/eth` package, as well as adding network name as a tag in most metrics - making it easier to create Graphana Dashboards for multiple networks. Please review the upgrade warnings and documentation for any important changes affecting RPC providers, node operators, and storage providers.
@@ -156,7 +157,7 @@ Network Version: 24
156157
Actor Version: 15
157158
Manifest CID: bafy2bzaceakwje2hyinucrhgtsfo44p54iw4g6otbv5ghov65vajhxgntr53u
158159
159-
Actor CID
160+
Actor CID
160161
account bafk2bzacecia5zacqt4gvd4z7275lnkhgraq75shy63cphakphhw6crf4joii
161162
cron bafk2bzacecbyx7utt3tkvhqnfk64kgtlt5jlvv56o2liwczikgzfowk2cvqvk
162163
datacap bafk2bzacecrypcpyzidphfl3sf3vhrjbiwzu7w3hoole45wsk2bqpverw4tni

documentation/en/default-lotus-config.toml

+18
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,24 @@
348348
# env var: LOTUS_CHAININDEXER_MAXRECONCILETIPSETS
349349
#MaxReconcileTipsets = 8640
350350

351+
# AllowIndexReconciliationFailure determines whether node startup should continue
352+
# if the index reconciliation with the chain state fails.
353+
#
354+
# When set to true:
355+
# - If index reconciliation fails during startup, the node will log a warning but continue to start.
356+
#
357+
# When set to false (default):
358+
# - If index reconciliation fails during startup, the node will fail to start.
359+
# - This ensures that the index is always in a consistent state with the chain before the node starts.
360+
#
361+
# Default: false
362+
# // WARNING: Only set to true if you are okay with an index that may be out of sync with the chain.
363+
# This can lead to inaccurate or missing data in RPC responses that depend on the indexer.
364+
#
365+
# type: bool
366+
# env var: LOTUS_CHAININDEXER_ALLOWINDEXRECONCILIATIONFAILURE
367+
#AllowIndexReconciliationFailure = false
368+
351369

352370
[FaultReporter]
353371
# EnableConsensusFaultReporter controls whether the node will monitor and

node/builder_chain.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ func ConfigFullNode(c interface{}) Option {
330330
Override(new(index.Indexer), modules.ChainIndexer(cfg.ChainIndexer)),
331331
Override(new(full.ChainIndexerAPI), modules.ChainIndexHandler(cfg.ChainIndexer)),
332332
If(cfg.ChainIndexer.EnableIndexer,
333-
Override(InitChainIndexerKey, modules.InitChainIndexer),
333+
Override(InitChainIndexerKey, modules.InitChainIndexer(cfg.ChainIndexer)),
334334
),
335335
),
336336
)

node/config/doc_gen.go

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/config/types.go

+15
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,21 @@ type ChainIndexerConfig struct {
628628
// Note: Setting this value too low may result in incomplete indexing, while setting it too high
629629
// may increase startup time.
630630
MaxReconcileTipsets uint64
631+
632+
// AllowIndexReconciliationFailure determines whether node startup should continue
633+
// if the index reconciliation with the chain state fails.
634+
//
635+
// When set to true:
636+
// - If index reconciliation fails during startup, the node will log a warning but continue to start.
637+
//
638+
// When set to false (default):
639+
// - If index reconciliation fails during startup, the node will fail to start.
640+
// - This ensures that the index is always in a consistent state with the chain before the node starts.
641+
//
642+
// Default: false
643+
// // WARNING: Only set to true if you are okay with an index that may be out of sync with the chain.
644+
// This can lead to inaccurate or missing data in RPC responses that depend on the indexer.
645+
AllowIndexReconciliationFailure bool
631646
}
632647

633648
type HarmonyDB struct {

node/modules/chainindex.go

+49-43
Original file line numberDiff line numberDiff line change
@@ -51,60 +51,66 @@ func ChainIndexer(cfg config.ChainIndexerConfig) func(lc fx.Lifecycle, mctx help
5151
}
5252
}
5353

54-
func InitChainIndexer(lc fx.Lifecycle, mctx helpers.MetricsCtx, indexer index.Indexer,
54+
func InitChainIndexer(cfg config.ChainIndexerConfig) func(lc fx.Lifecycle, mctx helpers.MetricsCtx, indexer index.Indexer,
5555
evapi EventHelperAPI, mp *messagepool.MessagePool, sm *stmgr.StateManager) {
56-
ctx := helpers.LifecycleCtx(mctx, lc)
56+
return func(lc fx.Lifecycle, mctx helpers.MetricsCtx, indexer index.Indexer,
57+
evapi EventHelperAPI, mp *messagepool.MessagePool, sm *stmgr.StateManager) {
58+
ctx := helpers.LifecycleCtx(mctx, lc)
5759

58-
lc.Append(fx.Hook{
59-
OnStart: func(_ context.Context) error {
60-
indexer.SetActorToDelegatedAddresFunc(func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) {
61-
idAddr, err := address.NewIDAddress(uint64(emitter))
60+
lc.Append(fx.Hook{
61+
OnStart: func(_ context.Context) error {
62+
indexer.SetActorToDelegatedAddresFunc(func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) {
63+
idAddr, err := address.NewIDAddress(uint64(emitter))
64+
if err != nil {
65+
return address.Undef, false
66+
}
67+
68+
actor, err := sm.LoadActor(ctx, idAddr, ts)
69+
if err != nil || actor.DelegatedAddress == nil {
70+
return idAddr, true
71+
}
72+
73+
return *actor.DelegatedAddress, true
74+
})
75+
76+
indexer.SetRecomputeTipSetStateFunc(func(ctx context.Context, ts *types.TipSet) error {
77+
_, _, err := sm.RecomputeTipSetState(ctx, ts)
78+
return err
79+
})
80+
81+
ch, err := mp.Updates(ctx)
6282
if err != nil {
63-
return address.Undef, false
83+
return err
6484
}
85+
go WaitForMpoolUpdates(ctx, ch, indexer)
6586

66-
actor, err := sm.LoadActor(ctx, idAddr, ts)
67-
if err != nil || actor.DelegatedAddress == nil {
68-
return idAddr, true
87+
ev, err := events.NewEvents(ctx, &evapi)
88+
if err != nil {
89+
return err
6990
}
7091

71-
return *actor.DelegatedAddress, true
72-
})
73-
74-
indexer.SetRecomputeTipSetStateFunc(func(ctx context.Context, ts *types.TipSet) error {
75-
_, _, err := sm.RecomputeTipSetState(ctx, ts)
76-
return err
77-
})
78-
79-
ch, err := mp.Updates(ctx)
80-
if err != nil {
81-
return err
82-
}
83-
go WaitForMpoolUpdates(ctx, ch, indexer)
84-
85-
ev, err := events.NewEvents(ctx, &evapi)
86-
if err != nil {
87-
return err
88-
}
89-
90-
// Tipset listener
92+
// Tipset listener
9193

92-
// `ObserveAndBlock` returns the current head and guarantees that it will call the observer with all future tipsets
93-
head, unlockObserver, err := ev.ObserveAndBlock(indexer)
94-
if err != nil {
95-
return xerrors.Errorf("error while observing tipsets: %w", err)
96-
}
97-
if err := indexer.ReconcileWithChain(ctx, head); err != nil {
94+
// `ObserveAndBlock` returns the current head and guarantees that it will call the observer with all future tipsets
95+
head, unlockObserver, err := ev.ObserveAndBlock(indexer)
96+
if err != nil {
97+
return xerrors.Errorf("error while observing tipsets: %w", err)
98+
}
99+
if err := indexer.ReconcileWithChain(ctx, head); err != nil {
100+
unlockObserver()
101+
if !cfg.AllowIndexReconciliationFailure {
102+
return xerrors.Errorf("error while reconciling chain index with chain state: %w", err)
103+
}
104+
log.Warnf("error while reconciling chain index with chain state: %s", err)
105+
}
98106
unlockObserver()
99-
return xerrors.Errorf("error while reconciling chain index with chain state: %w", err)
100-
}
101-
unlockObserver()
102107

103-
indexer.Start()
108+
indexer.Start()
104109

105-
return nil
106-
},
107-
})
110+
return nil
111+
},
112+
})
113+
}
108114
}
109115

110116
func ChainIndexHandler(cfg config.ChainIndexerConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, index.Indexer) (*full.ChainIndexHandler, error) {

0 commit comments

Comments
 (0)