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 3 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
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* [3358](https://github.com/zeta-chain/node/pull/3358) - register aborted CCTX for Bitcoin inbound that carries insufficient depositor fee
* [3368](https://github.com/zeta-chain/node/pull/3368) - cli command to fetch inbound ballot from inbound hash added to zetatools.
* [3425](https://github.com/zeta-chain/node/pull/3425) - enable inscription parsing on Bitcoin mainnet
* [3461](https://github.com/zeta-chain/node/pull/3461) - enable multiple confirmation count values in chain params
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved

### Refactor

Expand Down
17 changes: 17 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59799,6 +59799,8 @@ definitions:
type: boolean
gateway_address:
type: string
confirmation:
$ref: '#/definitions/observerConfirmation'
observerChainParamsList:
type: object
properties:
Expand All @@ -59807,6 +59809,21 @@ definitions:
items:
type: object
$ref: '#/definitions/observerChainParams'
observerConfirmation:
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.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 Confirmation {
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
uint64 safe_inbound_count = 1;
uint64 fast_inbound_count = 2;
uint64 safe_outbound_count = 3;
uint64 fast_outbound_count = 4;
}
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion proto/zetachain/zetacore/observer/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ syntax = "proto3";
package zetachain.zetacore.observer;

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

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

Expand Down Expand Up @@ -30,6 +30,7 @@ message ChainParams {
];
bool is_supported = 16;
string gateway_address = 17;
Confirmation confirmation = 18 [ (gogoproto.nullable) = false ];
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
}

// 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(),
Confirmation: Confirmation(),
}
}

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

func Confirmation() types.Confirmation {
randInboundCount := Uint64InRange(1, 200)
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
randOutboundCount := Uint64InRange(1, 200)

return types.Confirmation{
SafeInboundCount: randInboundCount,
FastInboundCount: randInboundCount - 1,
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
SafeOutboundCount: randOutboundCount,
FastOutboundCount: randOutboundCount - 1,
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
}
}
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
47 changes: 47 additions & 0 deletions typescript/zetachain/zetacore/observer/confirmation_pb.d.ts
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.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.Confirmation
*/
export declare class Confirmation extends Message<Confirmation> {
/**
* @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<Confirmation>);

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

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

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

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

static equals(a: Confirmation | PlainMessage<Confirmation> | undefined, b: Confirmation | PlainMessage<Confirmation> | 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_pb";
export * from "./crosschain_flags_pb";
export * from "./events_pb";
export * from "./genesis_pb";
Expand Down
6 changes: 6 additions & 0 deletions 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 { Confirmation } from "./confirmation_pb.js";

/**
* @generated from message zetachain.zetacore.observer.ChainParamsList
Expand Down Expand Up @@ -109,6 +110,11 @@ export declare class ChainParams extends Message<ChainParams> {
*/
gatewayAddress: string;

/**
* @generated from field: zetachain.zetacore.observer.Confirmation confirmation = 18;
*/
confirmation?: Confirmation;

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.Confirmation.SafeInboundCount = chainParams.ConfirmationCount
chainParams.Confirmation.FastInboundCount = chainParams.ConfirmationCount
chainParams.Confirmation.SafeOutboundCount = chainParams.ConfirmationCount
chainParams.Confirmation.FastOutboundCount = chainParams.ConfirmationCount
}
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
}

ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
// 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)
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved

// ensure the chain params are set correctly
oldChainParams, found := k.GetChainParamsList(ctx)
require.True(t, found)
require.EqualValues(t, chainParams, oldChainParams)
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved

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

// ensure we still have 7 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, newParam.Confirmation.SafeInboundCount, oldParam.ConfirmationCount)
require.Equal(t, newParam.Confirmation.FastInboundCount, oldParam.ConfirmationCount)
require.Equal(t, newParam.Confirmation.SafeOutboundCount, oldParam.ConfirmationCount)
require.Equal(t, newParam.Confirmation.FastOutboundCount, oldParam.ConfirmationCount)
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved

// ensure nothing else has changed except the confirmation
oldParam.Confirmation.SafeInboundCount = oldParam.ConfirmationCount
oldParam.Confirmation.FastInboundCount = oldParam.ConfirmationCount
oldParam.Confirmation.SafeOutboundCount = oldParam.ConfirmationCount
oldParam.Confirmation.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.Confirmation = types.Confirmation{}
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