[#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

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

View file

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

View file

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