[#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 <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2020-10-12 12:13:19 +03:00 committed by Alex Vanin
parent dee1d81b04
commit dcb384d551
3 changed files with 58 additions and 9 deletions

View file

@ -37,7 +37,7 @@ type (
morphClient *client.Client morphClient *client.Client
mainnetClient *client.Client mainnetClient *client.Client
epochCounter atomic.Uint64 epochCounter atomic.Uint64
activeState atomic.Bool innerRingIndex atomic.Int32
// todo: export error channel // 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") return errors.Wrap(err, "can't read epoch")
} }
// check if node inside inner ring list // check if node inside inner ring list and what index it has
state, err := invoke.IsInnerRing(s.mainnetClient, c.neofs, key) index, err := invoke.InnerRingIndex(s.mainnetClient, c.neofs, key)
if err != nil { if err != nil {
return errors.Wrap(err, "can't read inner ring list") return errors.Wrap(err, "can't read inner ring list")
} }
s.epochCounter.Store(uint64(epoch)) s.epochCounter.Store(uint64(epoch))
s.activeState.Store(state) s.innerRingIndex.Store(index)
s.log.Debug("read config from blockchain", s.log.Debug("read config from blockchain",
zap.Bool("active", state), zap.Bool("active", s.IsActive()),
zap.Int64("epoch", epoch), zap.Int64("epoch", epoch),
) )

View file

@ -1,6 +1,7 @@
package invoke package invoke
import ( import (
"bytes"
"crypto/ecdsa" "crypto/ecdsa"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
@ -29,6 +30,7 @@ const (
extraFee = 1_5000_0000 // 1.5 Fixed8 gas extraFee = 1_5000_0000 // 1.5 Fixed8 gas
checkIsInnerRingMethod = "isInnerRing" checkIsInnerRingMethod = "isInnerRing"
innerRingListMethod = "innerRingList"
chequeMethod = "cheque" chequeMethod = "cheque"
) )
@ -66,3 +68,44 @@ func CashOutCheque(cli *client.Client, con util.Uint160, p *ChequeParams) error
p.LockAccount.BytesBE(), 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
}

View file

@ -13,5 +13,11 @@ func (s *Server) SetEpochCounter(val uint64) {
// IsActive is a getter for a global active flag state. // IsActive is a getter for a global active flag state.
func (s *Server) IsActive() bool { 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()
} }