[#473] Implement EigenTrust calculations

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-04-10 15:02:51 +03:00 committed by Alex Vanin
parent 0ec8bcf6b4
commit a97e08cfd7
14 changed files with 1112 additions and 3 deletions

View file

@ -0,0 +1,189 @@
package consumerstorage
import (
"sync"
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
"github.com/nspcc-dev/neofs-node/pkg/services/reputation/eigentrust"
)
// Put saves intermediate trust of the consumer to daughter peer.
func (x *Storage) Put(trust eigentrust.IterationTrust) {
var s *iterationConsumersStorage
x.mtx.Lock()
{
epoch := trust.Epoch()
s = x.mItems[epoch]
if s == nil {
s = &iterationConsumersStorage{
mItems: make(map[uint32]*ConsumersStorage, 1),
}
x.mItems[epoch] = s
}
}
x.mtx.Unlock()
s.put(trust)
}
// Consumers returns the storage of trusts of the consumers of the daugher peers
// for particular iteration of EigenTrust calculation for particular epoch.
//
// Returns false if there is no data for the epoch and iter.
func (x *Storage) Consumers(epoch uint64, iter uint32) (*ConsumersStorage, bool) {
var (
s *iterationConsumersStorage
ok bool
)
x.mtx.Lock()
{
s, ok = x.mItems[epoch]
}
x.mtx.Unlock()
if !ok {
return nil, false
}
return s.consumers(iter)
}
// maps iteration numbers of EigenTrust algorithm to repositories
// of the trusts of the consumers of the daughter peers.
type iterationConsumersStorage struct {
mtx sync.RWMutex
mItems map[uint32]*ConsumersStorage
}
func (x *iterationConsumersStorage) put(trust eigentrust.IterationTrust) {
var s *ConsumersStorage
x.mtx.Lock()
{
iter := trust.I()
s = x.mItems[iter]
if s == nil {
s = &ConsumersStorage{
mItems: make(map[reputation.PeerID]*ConsumersTrusts, 1),
}
x.mItems[iter] = s
}
}
x.mtx.Unlock()
s.put(trust)
}
func (x *iterationConsumersStorage) consumers(iter uint32) (s *ConsumersStorage, ok bool) {
x.mtx.Lock()
{
s, ok = x.mItems[iter]
}
x.mtx.Unlock()
return
}
// ConsumersStorage represents in-memory storage of intermediate trusts
// of the peer consumers.
//
// Maps daughter peers to repositories of the trusts of their consumers.
type ConsumersStorage struct {
mtx sync.RWMutex
mItems map[reputation.PeerID]*ConsumersTrusts
}
func (x *ConsumersStorage) put(trust eigentrust.IterationTrust) {
var s *ConsumersTrusts
x.mtx.Lock()
{
daughter := trust.Peer()
s = x.mItems[daughter]
if s == nil {
s = &ConsumersTrusts{
mItems: make(map[reputation.PeerID]reputation.Trust, 1),
}
x.mItems[daughter] = s
}
}
x.mtx.Unlock()
s.put(trust)
}
// Iterate passes IDs of the daughter peers with the trusts of their consumers to h.
//
// Returns errors from h directly.
func (x *ConsumersStorage) Iterate(h func(trusted reputation.PeerID, consumerTrusts *ConsumersTrusts) error) (err error) {
x.mtx.RLock()
{
for trusted, trusts := range x.mItems {
if err = h(trusted, trusts); err != nil {
break
}
}
}
x.mtx.RUnlock()
return
}
// ConsumersTrusts represents in-memory storage of the trusts
// of the consumer peers to some other peer.
type ConsumersTrusts struct {
mtx sync.RWMutex
mItems map[reputation.PeerID]reputation.Trust
}
func (x *ConsumersTrusts) put(trust eigentrust.IterationTrust) {
x.mtx.Lock()
{
x.mItems[trust.TrustingPeer()] = trust.Trust
}
x.mtx.Unlock()
}
// Iterate passes all stored trusts to h.
//
// Returns errors from h directly.
func (x *ConsumersTrusts) Iterate(h reputation.TrustHandler) (err error) {
x.mtx.RLock()
{
for _, trust := range x.mItems {
if err = h(trust); err != nil {
break
}
}
}
x.mtx.RUnlock()
return
}

View file

@ -0,0 +1,40 @@
package consumerstorage
import (
"sync"
)
// Prm groups the required parameters of the Storage's constructor.
//
// All values must comply with the requirements imposed on them.
// Passing incorrect parameter values will result in constructor
// failure (error or panic depending on the implementation).
//
// The component is not parameterizable at the moment.
type Prm struct{}
// Storage represents in-memory storage that of the trusts
// of the consumer peers.
//
// It maps epoch numbers to the repositories of intermediate
// trusts of the consumers of the daughter peers.
//
// For correct operation, Storage must be created
// using the constructor (New) based on the required parameters
// and optional components. After successful creation,
// Storage is immediately ready to work through API.
type Storage struct {
mtx sync.RWMutex
mItems map[uint64]*iterationConsumersStorage
}
// New creates a new instance of the Storage.
//
// The created Storage does not require additional
// initialization and is completely ready for work.
func New(_ Prm) *Storage {
return &Storage{
mItems: make(map[uint64]*iterationConsumersStorage),
}
}

View file

@ -0,0 +1,134 @@
package daughters
import (
"sync"
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
)
// Put saves daughter peer's trust to its provider for the epoch.
func (x *Storage) Put(epoch uint64, trust reputation.Trust) {
var s *daughterStorage
x.mtx.Lock()
{
s = x.mItems[epoch]
if s == nil {
s = &daughterStorage{
mItems: make(map[reputation.PeerID]*DaughterTrusts, 1),
}
x.mItems[epoch] = s
}
}
x.mtx.Unlock()
s.put(trust)
}
// DaughterTrusts returns daughter trusts for the epoch.
//
// Returns false if there is no data for the epoch and daughter.
func (x *Storage) DaughterTrusts(epoch uint64, daughter reputation.PeerID) (*DaughterTrusts, bool) {
var (
s *daughterStorage
ok bool
)
x.mtx.RLock()
{
s, ok = x.mItems[epoch]
}
x.mtx.RUnlock()
if !ok {
return nil, false
}
return s.daughterTrusts(daughter)
}
// maps IDs of daughter peers to repositories of the local trusts to their providers.
type daughterStorage struct {
mtx sync.RWMutex
mItems map[reputation.PeerID]*DaughterTrusts
}
func (x *daughterStorage) put(trust reputation.Trust) {
var dt *DaughterTrusts
x.mtx.Lock()
{
trusting := trust.TrustingPeer()
dt = x.mItems[trusting]
if dt == nil {
dt = &DaughterTrusts{
mItems: make(map[reputation.PeerID]reputation.Trust, 1),
}
x.mItems[trusting] = dt
}
}
x.mtx.Unlock()
dt.put(trust)
}
func (x *daughterStorage) daughterTrusts(id reputation.PeerID) (dt *DaughterTrusts, ok bool) {
x.mtx.RLock()
{
dt, ok = x.mItems[id]
}
x.mtx.RUnlock()
return
}
// DaughterTrusts represents in-memory storage of local trusts
// of the daughter peer to its providers.
//
// Maps IDs of daughter's providers to the local trusts to them.
type DaughterTrusts struct {
mtx sync.RWMutex
mItems map[reputation.PeerID]reputation.Trust
}
func (x *DaughterTrusts) put(trust reputation.Trust) {
x.mtx.Lock()
{
x.mItems[trust.Peer()] = trust
}
x.mtx.Unlock()
}
// Iterate passes all stored trusts to h.
//
// Returns errors from h directly.
func (x *DaughterTrusts) Iterate(h reputation.TrustHandler) (err error) {
x.mtx.RLock()
{
for _, trust := range x.mItems {
if err = h(trust); err != nil {
break
}
}
}
x.mtx.RUnlock()
return
}

View file

@ -0,0 +1,38 @@
package daughters
import "sync"
// Prm groups the required parameters of the Storage's constructor.
//
// All values must comply with the requirements imposed on them.
// Passing incorrect parameter values will result in constructor
// failure (error or panic depending on the implementation).
//
// The component is not parameterizable at the moment.
type Prm struct{}
// Storage represents in-memory storage of local trust
// values of the daughter peers.
//
// It maps epoch numbers to the repositories of local trusts
// of the daughter peers.
//
// For correct operation, Storage must be created
// using the constructor (New) based on the required parameters
// and optional components. After successful creation,
// Storage is immediately ready to work through API.
type Storage struct {
mtx sync.RWMutex
mItems map[uint64]*daughterStorage
}
// New creates a new instance of the Storage.
//
// The created Storage does not require additional
// initialization and is completely ready for work.
func New(_ Prm) *Storage {
return &Storage{
mItems: make(map[uint64]*daughterStorage),
}
}