diff --git a/.changelog/5400.bugfix.md b/.changelog/5400.bugfix.md new file mode 100644 index 00000000000..9c9240295c4 --- /dev/null +++ b/.changelog/5400.bugfix.md @@ -0,0 +1 @@ +go/worker/common: Refresh current epoch for suspended runtimes diff --git a/go/oasis-node/cmd/config/migrate/migrate.go b/go/oasis-node/cmd/config/migrate/migrate.go index 028fb23a0c8..8c7a2aaeef4 100644 --- a/go/oasis-node/cmd/config/migrate/migrate.go +++ b/go/oasis-node/cmd/config/migrate/migrate.go @@ -68,6 +68,8 @@ func translateKnownP2P(in []string) ([]string, uint) { "E27F6B7A350B4CC2B48A6CBE94B0A02B0DCB0BF3@35.199.49.168:26656": "H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:26656", // Testnet seed node. "53572F689E5BACDD3C6527E6594EC49C8F3093F6@34.86.165.6:26656": "HcDFrTp/MqRHtju5bCx6TIhIMd6X/0ZQ3lUG73q5898=@34.86.165.6:26656", + // Old Testnet seed node. + "05EAC99BB37F6DAAD4B13386FF5E087ACBDDC450@34.86.165.6:26656": "HcDFrTp/MqRHtju5bCx6TIhIMd6X/0ZQ3lUG73q5898=@34.86.165.6:26656", } var numUnknown uint @@ -720,6 +722,16 @@ func doMigrateConfig(cmd *cobra.Command, args []string) { // Also prune new config. pruneEmptyMaps(newCfg) + // If a node has `consensus.validator` set to true and it does not have any runtimes configured, + // the new `mode` should be set to `validator`. + if newValidator, ok := m(newCfg["consensus"])["validator"]; ok { + isValidator, _ := newValidator.(bool) + if _, hasRuntimes := m(newCfg["runtime"])["paths"]; !hasRuntimes && isValidator { + nodeMode = "validator" + delete(m(newCfg["consensus"]), "validator") + } + } + // Check for options that are only available on the command-line. if _, ok = oldCfg["debug"]; ok { logger.Warn("note that some debug.* options are from now on only available on the command-line") diff --git a/go/oasis-node/cmd/config/migrate/migrate_test.go b/go/oasis-node/cmd/config/migrate/migrate_test.go index 05d2ae9ecd1..a55bdcc581e 100644 --- a/go/oasis-node/cmd/config/migrate/migrate_test.go +++ b/go/oasis-node/cmd/config/migrate/migrate_test.go @@ -230,7 +230,38 @@ runtime: - /km/runtimes/keymanager.orc ` -// Non-valiator node from docs test configuration file. +// Validator node. +const testValidatorConfigRaw = ` +datadir: /node/data + +log: + level: + default: info + tendermint: info + tendermint/context: error + format: JSON + +genesis: + file: /node/etc/genesis.json + +consensus: + validator: true + + tendermint: + p2p: + # List of seed nodes to connect to. + # NOTE: You can add additional seed nodes to this list if you want. + seed: + - "E27F6B7A350B4CC2B48A6CBE94B0A02B0DCB0BF3@35.199.49.168:26656" + +worker: + registration: + # In order for the node to register itself, the entity.json of the entity + # used to provision the node must be available on the node. + entity: /node/entity/entity.json +` + +// Non-validator node from docs test configuration file. const testDocsNonValidatorConfigRaw = ` datadir: /node/data @@ -564,6 +595,23 @@ func TestConfigMigrationKM(t *testing.T) { require.Equal(newConfig.Consensus.Validator, false) } +func TestConfigMigrationValidator(t *testing.T) { + require := require.New(t) + newConfig := prepareTest(require, testValidatorConfigRaw) + + // Now check if the config struct fields actually match the original state. + require.Equal(newConfig.Mode, config.ModeValidator) + require.Equal(newConfig.Common.DataDir, "/node/data") + require.Equal(newConfig.Common.Log.Format, "JSON") + require.Equal(newConfig.Common.Log.Level["default"], "info") + require.Equal(newConfig.Common.Log.Level["cometbft"], "info") + require.Equal(newConfig.Common.Log.Level["cometbft/context"], "error") + require.Equal(newConfig.Genesis.File, "/node/etc/genesis.json") + require.Equal(newConfig.P2P.Seeds[0], "H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:26656") + require.Equal(newConfig.P2P.Seeds[1], "H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:9200") + require.Equal(newConfig.Consensus.Validator, false) +} + func TestConfigMigrationDocsNonValidator(t *testing.T) { require := require.New(t) newConfig := prepareTest(require, testDocsNonValidatorConfigRaw) diff --git a/go/p2p/peermgmt/connector.go b/go/p2p/peermgmt/connector.go index e17545c26b4..8baa2656260 100644 --- a/go/p2p/peermgmt/connector.go +++ b/go/p2p/peermgmt/connector.go @@ -173,9 +173,6 @@ func (c *peerConnector) connect(ctx context.Context, info peer.AddrInfo) bool { // Skip if the peer is connected. if c.host.Network().Connectedness(info.ID) == network.Connected { - c.logger.Debug("peer already connected", - "peer_id", info.ID, - ) return true } diff --git a/go/runtime/registry/config.go b/go/runtime/registry/config.go index b0d67007a31..42dee2182bf 100644 --- a/go/runtime/registry/config.go +++ b/go/runtime/registry/config.go @@ -82,13 +82,13 @@ func newConfig(dataDir string, commonStore *persistent.CommonStore, consensus co if haveSetRuntimes && !cmdFlags.DebugDontBlameOasis() { return nil, fmt.Errorf("no runtimes should be configured when in validator or seed modes") } - case config.ModeArchive: - // Runtimes can be optionally configured. - default: - // In any other mode, at least one runtime should be configured. + case config.ModeCompute, config.ModeKeyManager, config.ModeStatelessClient: + // At least one runtime should be configured. if !haveSetRuntimes && !cmdFlags.DebugDontBlameOasis() { - return nil, fmt.Errorf("at least one runtime must be configured when in compute, keymanager, client, or client-stateless modes") + return nil, fmt.Errorf("at least one runtime must be configured when in compute, keymanager, or client-stateless modes") } + default: + // In any other mode, runtimes can be optionally configured. } // Check if any runtimes are configured to be hosted. diff --git a/go/worker/common/committee/node.go b/go/worker/common/committee/node.go index 21c6518b5f1..b065ab09695 100644 --- a/go/worker/common/committee/node.go +++ b/go/worker/common/committee/node.go @@ -414,7 +414,19 @@ func (n *Node) handleSuspendLocked(int64) { return } + // Refresh current epoch as otherwise it could be stale which will result in the + // new runtime version not being activated. + currentEpoch, err := n.Consensus.Beacon().GetEpoch(n.ctx, consensus.HeightLatest) + switch err { + case nil: + n.CurrentEpoch = currentEpoch + default: + n.logger.Error("failed to fetch current epoch", + "err", err, + ) + } n.CurrentDescriptor = rt + n.updateHostedRuntimeVersionLocked() n.CrossNode.Unlock() case <-resumeCh: