From 3fca3352d817cf5ebc482892400d43d4aa9f4252 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 26 Jul 2022 15:18:30 +0300 Subject: [PATCH] cli: read new config on signal and check ProtocolConfiguration ProtocolConfiguration must remain the same, any errors mean that the signal will be ignored. --- cli/server/server.go | 11 ++++- pkg/config/protocol_config.go | 75 ++++++++++++++++++++++++++++++ pkg/config/protocol_config_test.go | 74 +++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 1 deletion(-) diff --git a/cli/server/server.go b/cli/server/server.go index c772e1927..5f80bf42b 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -528,9 +528,18 @@ Main: shutdownErr = fmt.Errorf("server error: %w", err) cancel() case sig := <-sighupCh: + log.Info("signal received", zap.Stringer("name", sig)) + cfgnew, err := getConfigFromContext(ctx) + if err != nil { + log.Warn("can't reread the config file, signal ignored", zap.Error(err)) + break // Continue working. + } + if !cfg.ProtocolConfiguration.Equals(&cfgnew.ProtocolConfiguration) { + log.Warn("ProtocolConfiguration changed, signal ignored") + break // Continue working. + } switch sig { case syscall.SIGHUP: - log.Info("SIGHUP received, restarting rpc-server") rpcServer.Shutdown() rpcServer = rpcsrv.New(chain, cfg.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan) serv.AddService(&rpcServer) // Replaces old one by service name. diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index ab4c60cfd..5cfc743df 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -196,3 +196,78 @@ func (p *ProtocolConfiguration) GetNumOfCNs(height uint32) int { func (p *ProtocolConfiguration) ShouldUpdateCommitteeAt(height uint32) bool { return height%uint32(p.GetCommitteeSize(height)) == 0 } + +// Equals allows to compare two ProtocolConfiguration instances, returns true if +// they're equal. +func (p *ProtocolConfiguration) Equals(o *ProtocolConfiguration) bool { + if p.GarbageCollectionPeriod != o.GarbageCollectionPeriod || + p.InitialGASSupply != o.InitialGASSupply || + p.KeepOnlyLatestState != o.KeepOnlyLatestState || + p.Magic != o.Magic || + p.MaxBlockSize != o.MaxBlockSize || + p.MaxBlockSystemFee != o.MaxBlockSystemFee || + p.MaxTraceableBlocks != o.MaxTraceableBlocks || + p.MaxTransactionsPerBlock != o.MaxTransactionsPerBlock || + p.MaxValidUntilBlockIncrement != o.MaxValidUntilBlockIncrement || + p.MemPoolSize != o.MemPoolSize || + p.P2PNotaryRequestPayloadPoolSize != o.P2PNotaryRequestPayloadPoolSize || + p.P2PSigExtensions != o.P2PSigExtensions || + p.P2PStateExchangeExtensions != o.P2PStateExchangeExtensions || + p.RemoveUntraceableBlocks != o.RemoveUntraceableBlocks || + p.ReservedAttributes != o.ReservedAttributes || + p.SaveStorageBatch != o.SaveStorageBatch || + p.SecondsPerBlock != o.SecondsPerBlock || + p.StateRootInHeader != o.StateRootInHeader || + p.StateSyncInterval != o.StateSyncInterval || + p.ValidatorsCount != o.ValidatorsCount || + p.VerifyBlocks != o.VerifyBlocks || + p.VerifyTransactions != o.VerifyTransactions || + len(p.CommitteeHistory) != len(o.CommitteeHistory) || + len(p.Hardforks) != len(o.Hardforks) || + len(p.NativeUpdateHistories) != len(o.NativeUpdateHistories) || + len(p.SeedList) != len(o.SeedList) || + len(p.StandbyCommittee) != len(o.StandbyCommittee) || + len(p.ValidatorsHistory) != len(o.ValidatorsHistory) { + return false + } + for k, v := range p.CommitteeHistory { + vo, ok := o.CommitteeHistory[k] + if !ok || v != vo { + return false + } + } + for k, v := range p.Hardforks { + vo, ok := o.Hardforks[k] + if !ok || v != vo { + return false + } + } + for k, v := range p.NativeUpdateHistories { + vo := o.NativeUpdateHistories[k] + if len(v) != len(vo) { + return false + } + for i := range v { + if v[i] != vo[i] { + return false + } + } + } + for i := range p.SeedList { + if p.SeedList[i] != o.SeedList[i] { + return false + } + } + for i := range p.StandbyCommittee { + if p.StandbyCommittee[i] != o.StandbyCommittee[i] { + return false + } + } + for k, v := range p.ValidatorsHistory { + vo, ok := o.ValidatorsHistory[k] + if !ok || v != vo { + return false + } + } + return true +} diff --git a/pkg/config/protocol_config_test.go b/pkg/config/protocol_config_test.go index f95898f45..a2e976099 100644 --- a/pkg/config/protocol_config_test.go +++ b/pkg/config/protocol_config_test.go @@ -1,6 +1,7 @@ package config import ( + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -143,3 +144,76 @@ func TestGetCommitteeAndCNs(t *testing.T) { require.Equal(t, 4, p.GetNumOfCNs(200)) require.Equal(t, 4, p.GetNumOfCNs(201)) } + +func TestProtocolConfigurationEquals(t *testing.T) { + p := &ProtocolConfiguration{} + o := &ProtocolConfiguration{} + require.True(t, p.Equals(o)) + require.True(t, o.Equals(p)) + require.True(t, p.Equals(p)) + + cfg1, err := LoadFile(filepath.Join("..", "..", "config", "protocol.mainnet.yml")) + require.NoError(t, err) + cfg2, err := LoadFile(filepath.Join("..", "..", "config", "protocol.testnet.yml")) + require.NoError(t, err) + require.False(t, cfg1.ProtocolConfiguration.Equals(&cfg2.ProtocolConfiguration)) + + cfg2, err = LoadFile(filepath.Join("..", "..", "config", "protocol.mainnet.yml")) + require.NoError(t, err) + p = &cfg1.ProtocolConfiguration + o = &cfg2.ProtocolConfiguration + require.True(t, p.Equals(o)) + + o.CommitteeHistory = map[uint32]int{111: 7} + p.CommitteeHistory = map[uint32]int{111: 7} + require.True(t, p.Equals(o)) + p.CommitteeHistory[111] = 8 + require.False(t, p.Equals(o)) + + o.CommitteeHistory = nil + p.CommitteeHistory = nil + + p.Hardforks = map[string]uint32{"Fork": 42} + o.Hardforks = map[string]uint32{"Fork": 42} + require.True(t, p.Equals(o)) + p.Hardforks = map[string]uint32{"Fork2": 42} + require.False(t, p.Equals(o)) + + p.Hardforks = nil + o.Hardforks = nil + + p.NativeUpdateHistories = map[string][]uint32{"Contract": {1, 2, 3}} + o.NativeUpdateHistories = map[string][]uint32{"Contract": {1, 2, 3}} + require.True(t, p.Equals(o)) + p.NativeUpdateHistories["Contract"] = []uint32{1, 2, 3, 4} + require.False(t, p.Equals(o)) + p.NativeUpdateHistories["Contract"] = []uint32{1, 2, 4} + require.False(t, p.Equals(o)) + + p.NativeUpdateHistories = nil + o.NativeUpdateHistories = nil + + p.SeedList = []string{"url1", "url2"} + o.SeedList = []string{"url1", "url2"} + require.True(t, p.Equals(o)) + p.SeedList = []string{"url11", "url22"} + require.False(t, p.Equals(o)) + + p.SeedList = nil + o.SeedList = nil + + p.StandbyCommittee = []string{"key1", "key2"} + o.StandbyCommittee = []string{"key1", "key2"} + require.True(t, p.Equals(o)) + p.StandbyCommittee = []string{"key2", "key1"} + require.False(t, p.Equals(o)) + + p.StandbyCommittee = nil + o.StandbyCommittee = nil + + o.ValidatorsHistory = map[uint32]int{111: 0} + p.ValidatorsHistory = map[uint32]int{111: 0} + require.True(t, p.Equals(o)) + p.ValidatorsHistory = map[uint32]int{112: 0} + require.False(t, p.Equals(o)) +}