Skip to content

Commit

Permalink
feat: add zetaclient minimum version check (#3320)
Browse files Browse the repository at this point in the history
* feat: add minimum version check

* review feedback

* changelog
  • Loading branch information
gartnera authored Jan 8, 2025
1 parent 148935c commit 47c9444
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 37 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

* [3235](https://github.com/zeta-chain/node/pull/3235) - add /systemtime telemetry endpoint (zetaclient)
* [3317](https://github.com/zeta-chain/node/pull/3317) - add configurable signer latency correction (zetaclient)
* [3320](https://github.com/zeta-chain/node/pull/3320) - add zetaclient minimum version check

### Tests

Expand Down
27 changes: 17 additions & 10 deletions cmd/zetaclientd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ func Start(_ *cobra.Command, _ []string) error {
return errors.Wrap(err, "unable to resolve observer pub key bech32")
}

isObserver, err := isObserverNode(ctx, zetacoreClient)
switch {
case err != nil:
return errors.Wrap(err, "unable to check if observer node")
case !isObserver:
logger.Std.Warn().Msg("This node is not an observer node. Exit 0")
return nil
}

shutdownListener := maintenance.NewShutdownListener(zetacoreClient, logger.Std)
if err := shutdownListener.RunPreStartCheck(ctx); err != nil {
return errors.Wrap(err, "pre start check failed")
}

tssSetupProps := zetatss.SetupProps{
Config: cfg,
Zetacore: zetacoreClient,
Expand All @@ -94,28 +108,21 @@ func Start(_ *cobra.Command, _ []string) error {
Telemetry: telemetry,
}

// This will start p2p communication so it should only happen after
// preflight checks have completed
tss, err := zetatss.Setup(ctx, tssSetupProps, logger.Std)
if err != nil {
return errors.Wrap(err, "unable to setup TSS service")
}

isObserver, err := isObserverNode(ctx, zetacoreClient)
switch {
case err != nil:
return errors.Wrap(err, "unable to check if observer node")
case !isObserver:
logger.Std.Warn().Msg("This node is not an observer node. Exit 0")
return nil
}

// Starts various background TSS listeners.
// Shuts down zetaclientd if any is triggered.
maintenance.NewTSSListener(zetacoreClient, logger.Std).Listen(ctx, func() {
logger.Std.Info().Msg("TSS listener received an action to shutdown zetaclientd.")
graceful.ShutdownNow()
})

maintenance.NewShutdownListener(zetacoreClient, logger.Std).Listen(ctx, func() {
shutdownListener.Listen(ctx, func() {
logger.Std.Info().Msg("Shutdown listener received an action to shutdown zetaclientd.")
graceful.ShutdownNow()
})
Expand Down
6 changes: 6 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58115,6 +58115,12 @@ definitions:
description: |-
Offset from the zetacore block time to initiate signing.
Should be calculated and set based on max(zetaclient_core_block_latency).
minimum_version:
type: string
description: |-
Minimum version of zetaclient that is allowed to run. This must be either
a valid semver string (v23.0.1) or empty. If empty, all versions are
allowed.
description: Flags for the top-level operation of zetaclient.
observerPendingNonces:
type: object
Expand Down
5 changes: 5 additions & 0 deletions proto/zetachain/zetacore/observer/operational.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ message OperationalFlags {
// Should be calculated and set based on max(zetaclient_core_block_latency).
google.protobuf.Duration signer_block_time_offset = 2
[ (gogoproto.stdduration) = true ];

// Minimum version of zetaclient that is allowed to run. This must be either
// a valid semver string (v23.0.1) or empty. If empty, all versions are
// allowed.
string minimum_version = 3;
}
9 changes: 9 additions & 0 deletions typescript/zetachain/zetacore/observer/operational_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ export declare class OperationalFlags extends Message<OperationalFlags> {
*/
signerBlockTimeOffset?: Duration;

/**
* Minimum version of zetaclient that is allowed to run. This must be either
* a valid semver string (v23.0.1) or empty. If empty, all versions are
* allowed.
*
* @generated from field: string minimum_version = 3;
*/
minimumVersion: string;

constructor(data?: PartialMessage<OperationalFlags>);

static readonly runtime: typeof proto3;
Expand Down
5 changes: 5 additions & 0 deletions x/observer/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ var (
1140,
"signer block time offset exceeds limit",
)
ErrOperationalFlagsInvalidMinimumVersion = errorsmod.Register(
ModuleName,
1141,
"minimum version is not a valid semver string",
)
)
4 changes: 4 additions & 0 deletions x/observer/types/operational.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

cosmoserrors "cosmossdk.io/errors"
"golang.org/x/mod/semver"
)

const (
Expand All @@ -23,5 +24,8 @@ func (f *OperationalFlags) Validate() error {
return cosmoserrors.Wrapf(ErrOperationalFlagsSignerBlockTimeOffsetLimit, "(%s)", signerBlockTimeOffset)
}
}
if f.MinimumVersion != "" && !semver.IsValid(f.MinimumVersion) {
return ErrOperationalFlagsInvalidMinimumVersion
}
return nil
}
94 changes: 75 additions & 19 deletions x/observer/types/operational.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions x/observer/types/operational_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ func TestOperationalFlags_Validate(t *testing.T) {
of types.OperationalFlags
errContains string
}{
{
name: "empty is valid",
of: types.OperationalFlags{},
},
{
name: "invalid restart height",
of: types.OperationalFlags{
Expand Down Expand Up @@ -48,11 +52,25 @@ func TestOperationalFlags_Validate(t *testing.T) {
},
errContains: types.ErrOperationalFlagsSignerBlockTimeOffsetLimit.Error(),
},
{
name: "minimum version valid",
of: types.OperationalFlags{
MinimumVersion: "v1.1.1",
},
},
{
name: "minimum version invalid",
of: types.OperationalFlags{
MinimumVersion: "asdf",
},
errContains: types.ErrOperationalFlagsInvalidMinimumVersion.Error(),
},
{
name: "all flags valid",
of: types.OperationalFlags{
RestartHeight: 1,
SignerBlockTimeOffset: ptr.Ptr(time.Second),
MinimumVersion: "v1.1.1",
},
},
}
Expand Down
Loading

0 comments on commit 47c9444

Please sign in to comment.