2021-03-23 12:44:09 +00:00
|
|
|
package innerring
|
|
|
|
|
|
|
|
import (
|
2021-05-21 07:45:15 +00:00
|
|
|
"bytes"
|
2021-05-18 08:12:51 +00:00
|
|
|
"fmt"
|
2021-03-23 12:44:09 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2021-05-21 07:45:15 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
2021-03-23 12:44:09 +00:00
|
|
|
)
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
type (
|
2021-07-22 09:45:25 +00:00
|
|
|
irFetcher interface {
|
|
|
|
InnerRingKeys() (keys.PublicKeys, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
committeeFetcher interface {
|
|
|
|
Committee() (keys.PublicKeys, error)
|
|
|
|
}
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
innerRingIndexer struct {
|
|
|
|
sync.RWMutex
|
2021-03-23 12:44:09 +00:00
|
|
|
|
2021-07-22 09:45:25 +00:00
|
|
|
irFetcher irFetcher
|
|
|
|
commFetcher committeeFetcher
|
|
|
|
key *keys.PublicKey
|
|
|
|
timeout time.Duration
|
2021-03-23 12:44:09 +00:00
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
ind indexes
|
2021-03-23 12:44:09 +00:00
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
lastAccess time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
indexes struct {
|
|
|
|
innerRingIndex, innerRingSize int32
|
|
|
|
alphabetIndex int32
|
|
|
|
}
|
|
|
|
)
|
2021-03-23 12:44:09 +00:00
|
|
|
|
2021-07-22 09:45:25 +00:00
|
|
|
func newInnerRingIndexer(comf committeeFetcher, irf irFetcher, key *keys.PublicKey, to time.Duration) *innerRingIndexer {
|
2021-03-23 12:44:09 +00:00
|
|
|
return &innerRingIndexer{
|
2021-07-22 09:45:25 +00:00
|
|
|
irFetcher: irf,
|
|
|
|
commFetcher: comf,
|
|
|
|
key: key,
|
|
|
|
timeout: to,
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
func (s *innerRingIndexer) update() (ind indexes, err error) {
|
2021-03-23 12:44:09 +00:00
|
|
|
s.RLock()
|
|
|
|
|
|
|
|
if time.Since(s.lastAccess) < s.timeout {
|
|
|
|
s.RUnlock()
|
2021-03-26 08:36:07 +00:00
|
|
|
return s.ind, nil
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
s.RUnlock()
|
|
|
|
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
|
|
|
|
if time.Since(s.lastAccess) < s.timeout {
|
2021-03-26 08:36:07 +00:00
|
|
|
return s.ind, nil
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 09:45:25 +00:00
|
|
|
innerRing, err := s.irFetcher.InnerRingKeys()
|
2021-03-23 12:44:09 +00:00
|
|
|
if err != nil {
|
2021-03-26 08:36:07 +00:00
|
|
|
return indexes{}, err
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
2021-05-21 07:45:15 +00:00
|
|
|
s.ind.innerRingIndex = keyPosition(s.key, innerRing)
|
|
|
|
s.ind.innerRingSize = int32(len(innerRing))
|
|
|
|
|
2021-07-22 09:45:25 +00:00
|
|
|
alphabet, err := s.commFetcher.Committee()
|
2021-03-23 14:58:25 +00:00
|
|
|
if err != nil {
|
2021-03-26 08:36:07 +00:00
|
|
|
return indexes{}, err
|
2021-03-23 14:58:25 +00:00
|
|
|
}
|
|
|
|
|
2021-05-21 07:45:15 +00:00
|
|
|
s.ind.alphabetIndex = keyPosition(s.key, alphabet)
|
2021-03-23 12:44:09 +00:00
|
|
|
s.lastAccess = time.Now()
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
return s.ind, nil
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *innerRingIndexer) InnerRingIndex() (int32, error) {
|
2021-03-26 08:36:07 +00:00
|
|
|
ind, err := s.update()
|
|
|
|
if err != nil {
|
2021-05-18 08:12:51 +00:00
|
|
|
return 0, fmt.Errorf("can't update index state: %w", err)
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
return ind.innerRingIndex, nil
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *innerRingIndexer) InnerRingSize() (int32, error) {
|
2021-03-26 08:36:07 +00:00
|
|
|
ind, err := s.update()
|
|
|
|
if err != nil {
|
2021-05-18 08:12:51 +00:00
|
|
|
return 0, fmt.Errorf("can't update index state: %w", err)
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
return ind.innerRingSize, nil
|
2021-03-23 12:44:09 +00:00
|
|
|
}
|
2021-03-23 14:58:25 +00:00
|
|
|
|
|
|
|
func (s *innerRingIndexer) AlphabetIndex() (int32, error) {
|
2021-03-26 08:36:07 +00:00
|
|
|
ind, err := s.update()
|
|
|
|
if err != nil {
|
2021-05-18 08:12:51 +00:00
|
|
|
return 0, fmt.Errorf("can't update index state: %w", err)
|
2021-03-23 14:58:25 +00:00
|
|
|
}
|
|
|
|
|
2021-03-26 08:36:07 +00:00
|
|
|
return ind.alphabetIndex, nil
|
2021-03-23 14:58:25 +00:00
|
|
|
}
|
2021-05-21 07:45:15 +00:00
|
|
|
|
|
|
|
// keyPosition returns "-1" if key is not found in the list, otherwise returns
|
|
|
|
// index of the key.
|
2021-05-31 08:55:38 +00:00
|
|
|
func keyPosition(key *keys.PublicKey, list keys.PublicKeys) (result int32) {
|
2021-05-21 07:45:15 +00:00
|
|
|
result = -1
|
2021-05-31 08:55:38 +00:00
|
|
|
rawBytes := key.Bytes()
|
2021-05-21 07:45:15 +00:00
|
|
|
|
|
|
|
for i := range list {
|
|
|
|
if bytes.Equal(list[i].Bytes(), rawBytes) {
|
|
|
|
result = int32(i)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|