From dcb384d55123af9596ad7700be19e2d118d4bef5 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Mon, 12 Oct 2020 12:13:19 +0300 Subject: [PATCH] [#86] Specify inner ring list index in global state Inner ring index will be used to access alphabet contracts. First seven inner ring nods communicating with one alphabet contract, depending on their index. Signed-off-by: Alex Vanin --- pkg/innerring/innerring.go | 16 ++++++------- pkg/innerring/invoke/neofs.go | 43 +++++++++++++++++++++++++++++++++++ pkg/innerring/state.go | 8 ++++++- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 5da8762ce..cb97edbbd 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -34,10 +34,10 @@ type ( localTimers *timers.Timers // global state - morphClient *client.Client - mainnetClient *client.Client - epochCounter atomic.Uint64 - activeState atomic.Bool + morphClient *client.Client + mainnetClient *client.Client + epochCounter atomic.Uint64 + innerRingIndex atomic.Int32 // todo: export error channel } @@ -307,17 +307,17 @@ func initConfigFromBlockchain(s *Server, c *contracts, key *ecdsa.PublicKey) err return errors.Wrap(err, "can't read epoch") } - // check if node inside inner ring list - state, err := invoke.IsInnerRing(s.mainnetClient, c.neofs, key) + // check if node inside inner ring list and what index it has + index, err := invoke.InnerRingIndex(s.mainnetClient, c.neofs, key) if err != nil { return errors.Wrap(err, "can't read inner ring list") } s.epochCounter.Store(uint64(epoch)) - s.activeState.Store(state) + s.innerRingIndex.Store(index) s.log.Debug("read config from blockchain", - zap.Bool("active", state), + zap.Bool("active", s.IsActive()), zap.Int64("epoch", epoch), ) diff --git a/pkg/innerring/invoke/neofs.go b/pkg/innerring/invoke/neofs.go index f8cb2b339..b6ace9926 100644 --- a/pkg/innerring/invoke/neofs.go +++ b/pkg/innerring/invoke/neofs.go @@ -1,6 +1,7 @@ package invoke import ( + "bytes" "crypto/ecdsa" "github.com/nspcc-dev/neo-go/pkg/util" @@ -29,6 +30,7 @@ const ( extraFee = 1_5000_0000 // 1.5 Fixed8 gas checkIsInnerRingMethod = "isInnerRing" + innerRingListMethod = "innerRingList" chequeMethod = "cheque" ) @@ -66,3 +68,44 @@ func CashOutCheque(cli *client.Client, con util.Uint160, p *ChequeParams) error p.LockAccount.BytesBE(), ) } + +// InnerRingIndex returns index of the `key` in the inner ring list from sidechain. +// If key is not in the inner ring list, then returns `-1`. +func InnerRingIndex(cli *client.Client, con util.Uint160, key *ecdsa.PublicKey) (int32, error) { + if cli == nil { + return 0, client.ErrNilClient + } + + nodePublicKey := crypto.MarshalPublicKey(key) + + data, err := cli.TestInvoke(con, innerRingListMethod) + if err != nil { + return 0, err + } + + irNodes, err := client.ArrayFromStackItem(data[0]) + if err != nil { + return 0, err + } + + var result int32 = -1 + + for i := range irNodes { + key, err := client.ArrayFromStackItem(irNodes[i]) + if err != nil { + return 0, err + } + + keyValue, err := client.BytesFromStackItem(key[0]) + if err != nil { + return 0, err + } + + if bytes.Equal(keyValue, nodePublicKey) { + result = int32(i) + break + } + } + + return result, nil +} diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 378cc2416..ef36566d8 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -13,5 +13,11 @@ func (s *Server) SetEpochCounter(val uint64) { // IsActive is a getter for a global active flag state. func (s *Server) IsActive() bool { - return s.activeState.Load() + return s.innerRingIndex.Load() >= 0 +} + +// Index is a getter for a global index of node in inner ring list. Negative +// index means that node is not in the inner ring list. +func (s *Server) Index() int32 { + return s.innerRingIndex.Load() }