[#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
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)
if num > lastLetterNum {
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 {
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 {

View file

@ -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")

View file

@ -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

View file

@ -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
}