From 72935d0a80d814f97c7baeb81dc1c0f841a1a303 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Sun, 21 Feb 2021 09:53:18 +0300 Subject: [PATCH] [#392] ir: Upgrade to a dynamic number of alphabetical contracts In previous implementation IR worked with exactly 7 alphabetic contracts only. Actually number of contracts is limited to only the Glagolitic alphabet. Make IR to work with any valid number of alphabetic contracts. Change parser of alphabetic contract addresses to read amount of processing contracts before performance. Make Alphabet processor to use interface of the alphabetic contract group. Use `alphabetContracts` type in IR `Server`. Signed-off-by: Leonard Lyubich --- pkg/innerring/innerring.go | 32 +++++++++++-------- .../processors/alphabet/process_emit.go | 7 ++-- .../processors/alphabet/processor.go | 16 ++++++++-- pkg/innerring/state.go | 11 ++++--- 4 files changed, 43 insertions(+), 23 deletions(-) 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 }