Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable multiple confirmation count values in chain params #3461

Merged
merged 13 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

* [3461](https://github.com/zeta-chain/node/pull/3461) - enable multiple confirmation count values in chain params

### Tests

* [3430](https://github.com/zeta-chain/node/pull/3430) - add simulation test for MsgWithDrawEmission
Expand Down
19 changes: 19 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59767,6 +59767,7 @@ definitions:
confirmation_count:
type: string
format: uint64
title: 'Deprecated(v28): use confirmation_params instead'
gas_price_ticker:
type: string
format: uint64
Expand Down Expand Up @@ -59799,6 +59800,9 @@ definitions:
type: boolean
gateway_address:
type: string
confirmation_params:
$ref: '#/definitions/observerConfirmationParams'
title: Advanced confirmation parameters for chain to support fast observation
observerChainParamsList:
type: object
properties:
Expand All @@ -59807,6 +59811,21 @@ definitions:
items:
type: object
$ref: '#/definitions/observerChainParams'
observerConfirmationParams:
type: object
properties:
safe_inbound_count:
type: string
format: uint64
fast_inbound_count:
type: string
format: uint64
safe_outbound_count:
type: string
format: uint64
fast_outbound_count:
type: string
format: uint64
observerCrosschainFlags:
type: object
properties:
Expand Down
11 changes: 11 additions & 0 deletions proto/zetachain/zetacore/observer/confirmation_params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";
package zetachain.zetacore.observer;

option go_package = "github.com/zeta-chain/node/x/observer/types";

message ConfirmationParams {
uint64 safe_inbound_count = 1;
uint64 fast_inbound_count = 2;
uint64 safe_outbound_count = 3;
uint64 fast_outbound_count = 4;
}
8 changes: 6 additions & 2 deletions proto/zetachain/zetacore/observer/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ syntax = "proto3";
package zetachain.zetacore.observer;

import "gogoproto/gogo.proto";
import "zetachain/zetacore/observer/observer.proto";
import "zetachain/zetacore/observer/confirmation_params.proto";

option go_package = "github.com/zeta-chain/node/x/observer/types";

message ChainParamsList { repeated ChainParams chain_params = 1; }

message ChainParams {
int64 chain_id = 11;
uint64 confirmation_count = 1;
// Deprecated(v28): use confirmation_params instead
uint64 confirmation_count = 1 [ deprecated = true ];
uint64 gas_price_ticker = 2;
uint64 inbound_ticker = 3;
uint64 outbound_ticker = 4;
Expand All @@ -30,6 +31,9 @@ message ChainParams {
];
bool is_supported = 16;
string gateway_address = 17;

// Advanced confirmation parameters for chain to support fast observation
ConfirmationParams confirmation_params = 18 [ (gogoproto.nullable) = false ];
}

// Deprecated(v17)
Expand Down
14 changes: 14 additions & 0 deletions testutil/sample/observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ func ChainParams(chainID int64) *types.ChainParams {
BallotThreshold: fiftyPercent,
MinObserverDelegation: sdkmath.LegacyNewDec(r.Int63()),
IsSupported: false,
GatewayAddress: EthAddress().String(),
ConfirmationParams: ConfirmationParams(),
}
}

Expand Down Expand Up @@ -337,3 +339,15 @@ func OperationalFlags() types.OperationalFlags {
SignerBlockTimeOffset: ptr.Ptr(time.Second),
}
}

func ConfirmationParams() types.ConfirmationParams {
randInboundCount := Uint64InRange(1, 200)
randOutboundCount := Uint64InRange(1, 200)

return types.ConfirmationParams{
SafeInboundCount: randInboundCount,
FastInboundCount: Uint64InRange(1, randInboundCount),
SafeOutboundCount: randOutboundCount,
FastOutboundCount: Uint64InRange(1, randOutboundCount),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// @generated by protoc-gen-es v1.3.0 with parameter "target=dts"
// @generated from file zetachain/zetacore/observer/confirmation_params.proto (package zetachain.zetacore.observer, syntax proto3)
/* eslint-disable */
// @ts-nocheck

import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";

/**
* @generated from message zetachain.zetacore.observer.ConfirmationParams
*/
export declare class ConfirmationParams extends Message<ConfirmationParams> {
/**
* @generated from field: uint64 safe_inbound_count = 1;
*/
safeInboundCount: bigint;

/**
* @generated from field: uint64 fast_inbound_count = 2;
*/
fastInboundCount: bigint;

/**
* @generated from field: uint64 safe_outbound_count = 3;
*/
safeOutboundCount: bigint;

/**
* @generated from field: uint64 fast_outbound_count = 4;
*/
fastOutboundCount: bigint;

constructor(data?: PartialMessage<ConfirmationParams>);

static readonly runtime: typeof proto3;
static readonly typeName = "zetachain.zetacore.observer.ConfirmationParams";
static readonly fields: FieldList;

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConfirmationParams;

static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConfirmationParams;

static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConfirmationParams;

static equals(a: ConfirmationParams | PlainMessage<ConfirmationParams> | undefined, b: ConfirmationParams | PlainMessage<ConfirmationParams> | undefined): boolean;
}

1 change: 1 addition & 0 deletions typescript/zetachain/zetacore/observer/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from "./ballot_pb";
export * from "./blame_pb";
export * from "./chain_nonces_pb";
export * from "./confirmation_params_pb";
export * from "./crosschain_flags_pb";
export * from "./events_pb";
export * from "./genesis_pb";
Expand Down
13 changes: 12 additions & 1 deletion typescript/zetachain/zetacore/observer/params_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";
import type { ConfirmationParams } from "./confirmation_params_pb.js";

/**
* @generated from message zetachain.zetacore.observer.ChainParamsList
Expand Down Expand Up @@ -40,7 +41,10 @@ export declare class ChainParams extends Message<ChainParams> {
chainId: bigint;

/**
* @generated from field: uint64 confirmation_count = 1;
* Deprecated(v28): use confirmation_params instead
*
* @generated from field: uint64 confirmation_count = 1 [deprecated = true];
* @deprecated
*/
confirmationCount: bigint;

Expand Down Expand Up @@ -109,6 +113,13 @@ export declare class ChainParams extends Message<ChainParams> {
*/
gatewayAddress: string;

/**
* Advanced confirmation parameters for chain to support fast observation
*
* @generated from field: zetachain.zetacore.observer.ConfirmationParams confirmation_params = 18;
*/
confirmationParams?: ConfirmationParams;

constructor(data?: PartialMessage<ChainParams>);

static readonly runtime: typeof proto3;
Expand Down
6 changes: 6 additions & 0 deletions x/observer/keeper/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"

v10 "github.com/zeta-chain/node/x/observer/migrations/v10"
v8 "github.com/zeta-chain/node/x/observer/migrations/v8"
v9 "github.com/zeta-chain/node/x/observer/migrations/v9"
)
Expand Down Expand Up @@ -55,3 +56,8 @@ func (m Migrator) Migrate7to8(ctx sdk.Context) error {
func (m Migrator) Migrate8to9(ctx sdk.Context) error {
return v9.MigrateStore(ctx, m.observerKeeper)
}

// Migrate9to10 migrates the store from consensus version 9 to 10
func (m Migrator) Migrate9to10(ctx sdk.Context) error {
return v10.MigrateStore(ctx, m.observerKeeper)
}
41 changes: 41 additions & 0 deletions x/observer/migrations/v10/migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package v10

import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/zeta-chain/node/x/observer/types"
)

type observerKeeper interface {
GetChainParamsList(ctx sdk.Context) (val types.ChainParamsList, found bool)
SetChainParamsList(ctx sdk.Context, chainParams types.ChainParamsList)
}

// MigrateStore migrates the x/observer module state from the consensus version 9 to version 10.
// The migration sets existing 'confirmation_count' as default value for newly added fields:
// - 'safe_inbound_count'
// - 'fast_inbound_count'
// - 'safe_outbound_count'
// - 'fast_outbound_count'
func MigrateStore(ctx sdk.Context, observerKeeper observerKeeper) error {
allChainParams, found := observerKeeper.GetChainParamsList(ctx)
if !found {
return errorsmod.Wrap(types.ErrChainParamsNotFound, "failed to get chain params")
}

// set new fields to the same value as 'confirmation_count'
for _, chainParams := range allChainParams.ChainParams {
if chainParams != nil {
chainParams.ConfirmationParams.SafeInboundCount = chainParams.ConfirmationCount
chainParams.ConfirmationParams.FastInboundCount = chainParams.ConfirmationCount
chainParams.ConfirmationParams.SafeOutboundCount = chainParams.ConfirmationCount
chainParams.ConfirmationParams.FastOutboundCount = chainParams.ConfirmationCount
}
}

// set the updated chain params list
observerKeeper.SetChainParamsList(ctx, allChainParams)

return nil
}
100 changes: 100 additions & 0 deletions x/observer/migrations/v10/migrate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package v10_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
keepertest "github.com/zeta-chain/node/testutil/keeper"
"github.com/zeta-chain/node/testutil/sample"
"github.com/zeta-chain/node/x/observer/keeper"
v10 "github.com/zeta-chain/node/x/observer/migrations/v10"
"github.com/zeta-chain/node/x/observer/types"
)

var chainParams = types.ChainParamsList{
ChainParams: []*types.ChainParams{
makeChainParamsEmptyConfirmation(1, 14),
makeChainParamsEmptyConfirmation(56, 20),
makeChainParamsEmptyConfirmation(8332, 3),
makeChainParamsEmptyConfirmation(7000, 0),
makeChainParamsEmptyConfirmation(137, 200),
makeChainParamsEmptyConfirmation(8453, 90),
makeChainParamsEmptyConfirmation(900, 32),
},
}

func TestMigrateStore(t *testing.T) {
t.Run("can migrate confirmation count", func(t *testing.T) {
k, ctx, _, _ := keepertest.ObserverKeeper(t)

// set chain params
setChainParamsList(ctx, *k, chainParams)

// ensure the chain params are set correctly
oldChainParams, found := k.GetChainParamsList(ctx)
require.True(t, found)
require.Equal(t, chainParams, oldChainParams)

// migrate the store
err := v10.MigrateStore(ctx, *k)
require.NoError(t, err)

// ensure we still have same number of chain params after migration
newChainParams, found := k.GetChainParamsList(ctx)
require.True(t, found)
require.Len(t, newChainParams.ChainParams, len(oldChainParams.ChainParams))

// compare the old and new chain params
for i, newParam := range newChainParams.ChainParams {
oldParam := oldChainParams.ChainParams[i]

// ensure the confirmation fields are set correctly
require.Equal(t, oldParam.ConfirmationCount, newParam.ConfirmationParams.SafeInboundCount)
require.Equal(t, oldParam.ConfirmationCount, newParam.ConfirmationParams.FastInboundCount)
require.Equal(t, oldParam.ConfirmationCount, newParam.ConfirmationParams.SafeOutboundCount)
require.Equal(t, oldParam.ConfirmationCount, newParam.ConfirmationParams.FastOutboundCount)

// ensure nothing else has changed except the confirmation
oldParam.ConfirmationParams.SafeInboundCount = oldParam.ConfirmationCount
oldParam.ConfirmationParams.FastInboundCount = oldParam.ConfirmationCount
oldParam.ConfirmationParams.SafeOutboundCount = oldParam.ConfirmationCount
oldParam.ConfirmationParams.FastOutboundCount = oldParam.ConfirmationCount
require.Equal(t, newParam, oldParam)
}
})

t.Run("migrate nothing if chain params not found", func(t *testing.T) {
k, ctx, _, _ := keepertest.ObserverKeeper(t)

// ensure no chain params are set
allChainParams, found := k.GetChainParamsList(ctx)
require.False(t, found)
require.Empty(t, allChainParams.ChainParams)

// migrate the store
err := v10.MigrateStore(ctx, *k)
require.ErrorIs(t, err, types.ErrChainParamsNotFound)

// ensure nothing has changed
allChainParams, found = k.GetChainParamsList(ctx)
require.False(t, found)
require.Empty(t, allChainParams.ChainParams)
})
}

// makeChainParamsEmptyConfirmation creates a sample chain params with empty confirmation
func makeChainParamsEmptyConfirmation(chainID int64, confirmationCount uint64) *types.ChainParams {
chainParams := sample.ChainParams(chainID)
chainParams.ConfirmationCount = confirmationCount
chainParams.ConfirmationParams = types.ConfirmationParams{}
return chainParams
}

// setChainParamsList set chain params list in the store
func setChainParamsList(ctx sdk.Context, observerKeeper keeper.Keeper, chainParams types.ChainParamsList) {
store := ctx.KVStore(observerKeeper.StoreKey())
b := observerKeeper.Codec().MustMarshal(&chainParams)
key := types.KeyPrefix(types.AllChainParamsKey)
store.Set(key, b)
}
5 changes: 4 additions & 1 deletion x/observer/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
if err := cfg.RegisterMigration(types.ModuleName, 8, m.Migrate8to9); err != nil {
panic(err)
}
if err := cfg.RegisterMigration(types.ModuleName, 9, m.Migrate9to10); err != nil {
panic(err)
}
}

// RegisterInvariants registers the observer module's invariants.
Expand All @@ -176,7 +179,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
}

// ConsensusVersion implements ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 9 }
func (AppModule) ConsensusVersion() uint64 { return 10 }

// BeginBlock executes all ABCI BeginBlock logic respective to the observer module.
func (am AppModule) BeginBlock(c context.Context) error {
Expand Down
Loading