From 500c091d0ee027481e27893de6bd21478fac114e Mon Sep 17 00:00:00 2001 From: Giuseppe Natale <12249307+giunatale@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:22:31 +0200 Subject: [PATCH 1/2] migrate emas --- app/upgrades/v4/upgrades.go | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/app/upgrades/v4/upgrades.go b/app/upgrades/v4/upgrades.go index 7aa2f2f5..ea4b93aa 100644 --- a/app/upgrades/v4/upgrades.go +++ b/app/upgrades/v4/upgrades.go @@ -100,6 +100,10 @@ func migrateGovState(ctx context.Context, cdc codec.Codec, govKeeper *govkeeper. errs = errors.Join(errs, fmt.Errorf("failed to migrate gov validator shares by governor: %w", err)) } + if err := migrateParticipationEMAs(ctx, govKeeper, sb); err != nil { + errs = errors.Join(errs, fmt.Errorf("failed to migrate gov participation EMAs: %w", err)) + } + return errs } @@ -613,3 +617,37 @@ func migrateValidatorsCommission(ctx context.Context, stakingKeeper *stakingkeep } return nil } + +// migrateParticipationEMAs re-encodes the three participation EMA values from the old +// atomone decimal-string format ("0.58...") to the scaled-integer bytes expected by +// legacyDecValueCodec. Without this, GetQuorum panics on the first post-upgrade query. +func migrateParticipationEMAs(ctx context.Context, govKeeper *govkeeper.Keeper, sb *collections.SchemaBuilder) error { + // big.Int.UnmarshalText rejects decimal points, so the primary codec fails on the old + // "0.581818..." bytes. The fallback handles them via LegacyNewDecFromStr. + altCodec := collcodec.NewAltValueCodec(sdk.LegacyDecValue, func(b []byte) (math.LegacyDec, error) { + return math.LegacyNewDecFromStr(string(b)) + }) + + migrate := func(prefix collections.Prefix, name string, dest collections.Item[math.LegacyDec]) error { + ema, err := collections.NewItem(sb, prefix, name, altCodec).Get(ctx) + switch { + case errors.Is(err, collections.ErrNotFound): + ema = math.LegacyNewDecWithPrec(12, 2) // matches SDK v5.MigrateStore initial value + case err != nil: + return fmt.Errorf("get %s: %w", name, err) + } + return dest.Set(ctx, ema) + } + + if err := migrate(collections.NewPrefix(80), "participation_ema_legacy", govKeeper.ParticipationEMA); err != nil { + return fmt.Errorf("migrate participation EMA: %w", err) + } + if err := migrate(collections.NewPrefix(96), "constitution_amendment_participation_ema_legacy", govKeeper.ConstitutionAmendmentParticipationEMA); err != nil { + return fmt.Errorf("migrate constitution amendment participation EMA: %w", err) + } + if err := migrate(collections.NewPrefix(112), "law_participation_ema_legacy", govKeeper.LawParticipationEMA); err != nil { + return fmt.Errorf("migrate law participation EMA: %w", err) + } + + return nil +} From 062ad1d64616aac339dfdc8a67e72c03ad421be6 Mon Sep 17 00:00:00 2001 From: Giuseppe Natale <12249307+giunatale@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:24:40 +0200 Subject: [PATCH 2/2] remove extra comment --- app/upgrades/v4/upgrades.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/upgrades/v4/upgrades.go b/app/upgrades/v4/upgrades.go index ea4b93aa..1fa94593 100644 --- a/app/upgrades/v4/upgrades.go +++ b/app/upgrades/v4/upgrades.go @@ -620,7 +620,7 @@ func migrateValidatorsCommission(ctx context.Context, stakingKeeper *stakingkeep // migrateParticipationEMAs re-encodes the three participation EMA values from the old // atomone decimal-string format ("0.58...") to the scaled-integer bytes expected by -// legacyDecValueCodec. Without this, GetQuorum panics on the first post-upgrade query. +// legacyDecValueCodec. func migrateParticipationEMAs(ctx context.Context, govKeeper *govkeeper.Keeper, sb *collections.SchemaBuilder) error { // big.Int.UnmarshalText rejects decimal points, so the primary codec fails on the old // "0.581818..." bytes. The fallback handles them via LegacyNewDecFromStr.