[#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 <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-02-21 09:53:18 +03:00 committed by Alex Vanin
parent 1016ba3a5d
commit 72935d0a80
4 changed files with 43 additions and 23 deletions

View file

@ -90,7 +90,7 @@ type (
audit util.Uint160 // in morph audit util.Uint160 // in morph
gas util.Uint160 // native contract in both chains gas util.Uint160 // native contract in both chains
alphabet [alphabetContractsN]util.Uint160 // in morph alphabet alphabetContracts // in morph
} }
chainParams struct { chainParams struct {
@ -105,8 +105,6 @@ type (
const ( const (
morphPrefix = "morph" morphPrefix = "morph"
mainnetPrefix = "mainnet" mainnetPrefix = "mainnet"
alphabetContractsN = 7 // az, buky, vedi, glagoli, dobro, jest, zhivete
) )
// Start runs all event providers. // Start runs all event providers.
@ -629,20 +627,26 @@ func ParsePublicKeysFromStrings(pubKeys []string) ([]keys.PublicKey, error) {
return publicKeys, nil return publicKeys, nil
} }
func parseAlphabetContracts(cfg *viper.Viper) (res [7]util.Uint160, err error) { func parseAlphabetContracts(cfg *viper.Viper) (alphabetContracts, error) {
// list of glagolic script letters that represent alphabet contracts num := glagoliticLetter(cfg.GetUint("contracts.alphabet.amount"))
glagolic := []string{"az", "buky", "vedi", "glagoli", "dobro", "jest", "zhivete"} alpha := newAlphabetContracts()
for i, letter := range glagolic { if num > lastLetterNum {
contractStr := cfg.GetString("contracts.alphabet." + letter) return nil, errors.Errorf("amount of alphabet contracts overflows glagolitsa %d > %d", num, lastLetterNum)
}
res[i], err = util.Uint160DecodeStringLE(contractStr) for letter := az; letter < num; letter++ {
contractStr := cfg.GetString("contracts.alphabet." + letter.configString())
contractHash, err := util.Uint160DecodeStringLE(contractStr)
if err != nil { if err != nil {
return res, errors.Wrapf(err, "ir: can't read alphabet %s contract", letter) return nil, errors.Wrapf(err, "invalid alphabet %s contract: %s", letter.configString(), contractStr)
}
} }
return res, nil alpha.set(letter, contractHash)
}
return alpha, nil
} }
func (s *Server) initConfigFromBlockchain() error { func (s *Server) initConfigFromBlockchain() error {

View file

@ -15,14 +15,17 @@ func (np *Processor) processEmit() {
np.log.Info("passive mode, ignore gas emission event") np.log.Info("passive mode, ignore gas emission event")
return 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", np.log.Debug("node is out of alphabet range, ignore gas emission event",
zap.Int("index", index)) zap.Int("index", index))
return return
} }
err := invoke.AlphabetEmit(np.morphClient, np.alphabetContracts[index]) err := invoke.AlphabetEmit(np.morphClient, contract)
if err != nil { if err != nil {
np.log.Warn("can't invoke alphabet emit method") np.log.Warn("can't invoke alphabet emit method")

View file

@ -15,11 +15,23 @@ type (
Index() int 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 of events produced for alphabet contracts in sidechain.
Processor struct { Processor struct {
log *zap.Logger log *zap.Logger
pool *ants.Pool pool *ants.Pool
alphabetContracts [7]util.Uint160 alphabetContracts Contracts
netmapContract util.Uint160 netmapContract util.Uint160
morphClient *client.Client morphClient *client.Client
irList Indexer irList Indexer
@ -30,7 +42,7 @@ type (
Params struct { Params struct {
Log *zap.Logger Log *zap.Logger
PoolSize int PoolSize int
AlphabetContracts [7]util.Uint160 AlphabetContracts Contracts
NetmapContract util.Uint160 NetmapContract util.Uint160
MorphClient *client.Client MorphClient *client.Client
IRList Indexer IRList Indexer

View file

@ -2,6 +2,7 @@ package innerring
import ( import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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/innerring/invoke"
"github.com/nspcc-dev/neofs-node/pkg/services/audit" "github.com/nspcc-dev/neofs-node/pkg/services/audit"
"go.uber.org/zap" "go.uber.org/zap"
@ -37,7 +38,7 @@ func (s *Server) InnerRingSize() int {
func (s *Server) voteForSidechainValidator(validators []keys.PublicKey) error { func (s *Server) voteForSidechainValidator(validators []keys.PublicKey) error {
index := s.Index() 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") s.log.Info("ignore validator vote: node not in alphabet range")
return nil return nil
@ -51,14 +52,14 @@ func (s *Server) voteForSidechainValidator(validators []keys.PublicKey) error {
epoch := s.EpochCounter() epoch := s.EpochCounter()
for i := range s.contracts.alphabet { s.contracts.alphabet.iterate(func(letter glagoliticLetter, contract util.Uint160) {
err := invoke.AlphabetVote(s.morphClient, s.contracts.alphabet[i], epoch, validators) err := invoke.AlphabetVote(s.morphClient, contract, epoch, validators)
if err != nil { if err != nil {
s.log.Warn("can't invoke vote method in alphabet contract", 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)) zap.Uint64("epoch", epoch))
} }
} })
return nil return nil
} }