diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 8eeac964a..9f44a3c3f 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -90,7 +90,7 @@ type ( audit util.Uint160 // in morph gas util.Uint160 // native contract in both chains - alphabet [alphabetContractsN]util.Uint160 // in morph + alphabet alphabetContracts // in morph } chainParams struct { @@ -105,8 +105,6 @@ type ( const ( morphPrefix = "morph" mainnetPrefix = "mainnet" - - alphabetContractsN = 7 // az, buky, vedi, glagoli, dobro, jest, zhivete ) // Start runs all event providers. @@ -629,20 +627,26 @@ func ParsePublicKeysFromStrings(pubKeys []string) ([]keys.PublicKey, error) { return publicKeys, nil } -func parseAlphabetContracts(cfg *viper.Viper) (res [7]util.Uint160, err error) { - // list of glagolic script letters that represent alphabet contracts - glagolic := []string{"az", "buky", "vedi", "glagoli", "dobro", "jest", "zhivete"} +func parseAlphabetContracts(cfg *viper.Viper) (alphabetContracts, error) { + num := glagoliticLetter(cfg.GetUint("contracts.alphabet.amount")) + alpha := newAlphabetContracts() - for i, letter := range glagolic { - contractStr := cfg.GetString("contracts.alphabet." + letter) - - res[i], err = util.Uint160DecodeStringLE(contractStr) - if err != nil { - return res, errors.Wrapf(err, "ir: can't read alphabet %s contract", letter) - } + if num > lastLetterNum { + return nil, errors.Errorf("amount of alphabet contracts overflows glagolitsa %d > %d", num, lastLetterNum) } - return res, nil + for letter := az; letter < num; letter++ { + contractStr := cfg.GetString("contracts.alphabet." + letter.configString()) + + contractHash, err := util.Uint160DecodeStringLE(contractStr) + if err != nil { + return nil, errors.Wrapf(err, "invalid alphabet %s contract: %s", letter.configString(), contractStr) + } + + alpha.set(letter, contractHash) + } + + return alpha, nil } func (s *Server) initConfigFromBlockchain() error { diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 319769e13..aa792965a 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -15,14 +15,17 @@ func (np *Processor) processEmit() { np.log.Info("passive mode, ignore gas emission event") return - } else if index >= len(np.alphabetContracts) { + } + + contract, ok := np.alphabetContracts.GetByIndex(index) + if !ok { np.log.Debug("node is out of alphabet range, ignore gas emission event", zap.Int("index", index)) return } - err := invoke.AlphabetEmit(np.morphClient, np.alphabetContracts[index]) + err := invoke.AlphabetEmit(np.morphClient, contract) if err != nil { np.log.Warn("can't invoke alphabet emit method") diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index 978d2c460..d667027f2 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -15,11 +15,23 @@ type ( Index() int } + // Contracts is an interface of the storage + // of the alphabet contract addresses. + Contracts interface { + // Get by index must return address of the + // alphabet contract by index of the glagolitic + // letter (e.g 0 for Az, 40 for Izhitsa). + // + // Must return false if index does not + // match to any alphabet contract. + GetByIndex(int) (util.Uint160, bool) + } + // Processor of events produced for alphabet contracts in sidechain. Processor struct { log *zap.Logger pool *ants.Pool - alphabetContracts [7]util.Uint160 + alphabetContracts Contracts netmapContract util.Uint160 morphClient *client.Client irList Indexer @@ -30,7 +42,7 @@ type ( Params struct { Log *zap.Logger PoolSize int - AlphabetContracts [7]util.Uint160 + AlphabetContracts Contracts NetmapContract util.Uint160 MorphClient *client.Client IRList Indexer diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index b3715905a..89cdccbd2 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -2,6 +2,7 @@ package innerring import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-node/pkg/innerring/invoke" "github.com/nspcc-dev/neofs-node/pkg/services/audit" "go.uber.org/zap" @@ -37,7 +38,7 @@ func (s *Server) InnerRingSize() int { func (s *Server) voteForSidechainValidator(validators []keys.PublicKey) error { index := s.Index() - if index < 0 || index >= alphabetContractsN { + if s.contracts.alphabet.indexOutOfRange(index) { s.log.Info("ignore validator vote: node not in alphabet range") return nil @@ -51,14 +52,14 @@ func (s *Server) voteForSidechainValidator(validators []keys.PublicKey) error { epoch := s.EpochCounter() - for i := range s.contracts.alphabet { - err := invoke.AlphabetVote(s.morphClient, s.contracts.alphabet[i], epoch, validators) + s.contracts.alphabet.iterate(func(letter glagoliticLetter, contract util.Uint160) { + err := invoke.AlphabetVote(s.morphClient, contract, epoch, validators) if err != nil { s.log.Warn("can't invoke vote method in alphabet contract", - zap.Int("alphabet_index", i), + zap.Int8("alphabet_index", int8(letter)), zap.Uint64("epoch", epoch)) } - } + }) return nil }