forked from TrueCloudLab/frostfs-node
[#452] Use API structures for reputation PeerID and GlobalTrust
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
7cf48d4d91
commit
27cf6f5112
6 changed files with 116 additions and 36 deletions
|
@ -10,16 +10,18 @@ import (
|
||||||
|
|
||||||
func (rp *Processor) handlePutReputation(ev event.Event) {
|
func (rp *Processor) handlePutReputation(ev event.Event) {
|
||||||
put := ev.(reputationEvent.Put)
|
put := ev.(reputationEvent.Put)
|
||||||
|
peerID := put.PeerID()
|
||||||
|
|
||||||
rp.log.Info("notification",
|
rp.log.Info("notification",
|
||||||
zap.String("type", "reputation put"),
|
zap.String("type", "reputation put"),
|
||||||
zap.String("peer_id", hex.EncodeToString(put.PeerID().Bytes())))
|
zap.String("peer_id", hex.EncodeToString(peerID.ToV2().GetValue())))
|
||||||
|
|
||||||
// send event to the worker pool
|
// send event to the worker pool
|
||||||
|
|
||||||
err := rp.pool.Submit(func() {
|
err := rp.pool.Submit(func() {
|
||||||
rp.processPut(
|
rp.processPut(
|
||||||
put.Epoch(),
|
put.Epoch(),
|
||||||
put.PeerID(),
|
peerID,
|
||||||
put.Value(),
|
put.Value(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,18 +3,38 @@ package reputation
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/reputation"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client/reputation/wrapper"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/client/reputation/wrapper"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rp *Processor) processPut(epoch uint64, id reputation.PeerID, value []byte) {
|
func (rp *Processor) processPut(epoch uint64, id reputation.PeerID, value reputation.GlobalTrust) {
|
||||||
if !rp.alphabetState.IsAlphabet() {
|
if !rp.alphabetState.IsAlphabet() {
|
||||||
rp.log.Info("non alphabet mode, ignore reputation put notification")
|
rp.log.Info("non alphabet mode, ignore reputation put notification")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: do sanity checks of value and epoch
|
// check if epoch is valid
|
||||||
|
currentEpoch := rp.epochState.EpochCounter()
|
||||||
|
if epoch >= currentEpoch {
|
||||||
|
rp.log.Info("ignore reputation value",
|
||||||
|
zap.String("reason", "invalid epoch number"),
|
||||||
|
zap.Uint64("trust_epoch", epoch),
|
||||||
|
zap.Uint64("local_epoch", currentEpoch))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check signature
|
||||||
|
if err := value.VerifySignature(); err != nil {
|
||||||
|
rp.log.Info("ignore reputation value",
|
||||||
|
zap.String("reason", "invalid signature"),
|
||||||
|
zap.String("error", err.Error()))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: do sanity checks of value
|
||||||
|
|
||||||
args := wrapper.PutArgs{}
|
args := wrapper.PutArgs{}
|
||||||
args.SetEpoch(epoch)
|
args.SetEpoch(epoch)
|
||||||
|
@ -24,7 +44,7 @@ func (rp *Processor) processPut(epoch uint64, id reputation.PeerID, value []byte
|
||||||
err := rp.reputationWrp.PutViaNotary(args)
|
err := rp.reputationWrp.PutViaNotary(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rp.log.Warn("can't send approval tx for reputation value",
|
rp.log.Warn("can't send approval tx for reputation value",
|
||||||
zap.String("peer_id", hex.EncodeToString(id.Bytes())),
|
zap.String("peer_id", hex.EncodeToString(id.ToV2().GetValue())),
|
||||||
zap.String("error", err.Error()))
|
zap.String("error", err.Error()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package wrapper
|
package wrapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/reputation"
|
||||||
reputationClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/reputation"
|
reputationClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/reputation"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -21,7 +22,7 @@ type (
|
||||||
// GetResults groups the result of "get reputation value" and
|
// GetResults groups the result of "get reputation value" and
|
||||||
// "get reputation value by reputation id" test invocations.
|
// "get reputation value by reputation id" test invocations.
|
||||||
GetResult struct {
|
GetResult struct {
|
||||||
reputations [][]byte // todo: replace with the slice of structures
|
reputations []reputation.GlobalTrust
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ func (g *GetByIDArgs) SetID(v ReputationID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reputations returns slice of reputation values.
|
// Reputations returns slice of reputation values.
|
||||||
func (g GetResult) Reputations() [][]byte {
|
func (g GetResult) Reputations() []reputation.GlobalTrust {
|
||||||
return g.reputations
|
return g.reputations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ func (g GetResult) Reputations() [][]byte {
|
||||||
func (w *ClientWrapper) Get(v GetArgs) (*GetResult, error) {
|
func (w *ClientWrapper) Get(v GetArgs) (*GetResult, error) {
|
||||||
args := reputationClient.GetArgs{}
|
args := reputationClient.GetArgs{}
|
||||||
args.SetEpoch(v.epoch)
|
args.SetEpoch(v.epoch)
|
||||||
args.SetPeerID(v.peerID.Bytes())
|
args.SetPeerID(v.peerID.ToV2().GetValue())
|
||||||
|
|
||||||
data, err := (*reputationClient.Client)(w).Get(args)
|
data, err := (*reputationClient.Client)(w).Get(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -75,10 +76,20 @@ func (w *ClientWrapper) GetByID(v GetByIDArgs) (*GetResult, error) {
|
||||||
|
|
||||||
func parseGetResult(data *reputationClient.GetResult) (*GetResult, error) {
|
func parseGetResult(data *reputationClient.GetResult) (*GetResult, error) {
|
||||||
rawReputations := data.Reputations()
|
rawReputations := data.Reputations()
|
||||||
|
reputations := make([]reputation.GlobalTrust, 0, len(rawReputations))
|
||||||
|
|
||||||
// todo: unmarshal all reputation values into structure
|
for i := range rawReputations {
|
||||||
|
r := reputation.GlobalTrust{}
|
||||||
|
|
||||||
|
err := r.Unmarshal(rawReputations[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't unmarshal global trust value")
|
||||||
|
}
|
||||||
|
|
||||||
|
reputations = append(reputations, r)
|
||||||
|
}
|
||||||
|
|
||||||
return &GetResult{
|
return &GetResult{
|
||||||
reputations: rawReputations,
|
reputations: reputations,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package wrapper
|
package wrapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/reputation"
|
||||||
reputationClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/reputation"
|
reputationClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/reputation"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -10,7 +11,7 @@ type (
|
||||||
PutArgs struct {
|
PutArgs struct {
|
||||||
epoch uint64
|
epoch uint64
|
||||||
peerID reputation.PeerID
|
peerID reputation.PeerID
|
||||||
value []byte // todo: replace with struct
|
value reputation.GlobalTrust
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,16 +26,16 @@ func (p *PutArgs) SetPeerID(v reputation.PeerID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetValue sets reputation value.
|
// SetValue sets reputation value.
|
||||||
func (p *PutArgs) SetValue(v []byte) {
|
func (p *PutArgs) SetValue(v reputation.GlobalTrust) {
|
||||||
p.value = v
|
p.value = v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put invokes direct call of "put reputation value" method of reputation contract.
|
// Put invokes direct call of "put reputation value" method of reputation contract.
|
||||||
func (w *ClientWrapper) Put(v PutArgs) error {
|
func (w *ClientWrapper) Put(v PutArgs) error {
|
||||||
args := reputationClient.PutArgs{}
|
args, err := preparePutArgs(v)
|
||||||
args.SetEpoch(v.epoch)
|
if err != nil {
|
||||||
args.SetPeerID(v.peerID.Bytes())
|
return err
|
||||||
args.SetValue(v.value) // todo: marshal reputation value to `value` bytes there
|
}
|
||||||
|
|
||||||
return (*reputationClient.Client)(w).Put(args)
|
return (*reputationClient.Client)(w).Put(args)
|
||||||
}
|
}
|
||||||
|
@ -42,10 +43,25 @@ func (w *ClientWrapper) Put(v PutArgs) error {
|
||||||
// PutViaNotary invokes notary call of "put reputation value" method of
|
// PutViaNotary invokes notary call of "put reputation value" method of
|
||||||
// reputation contract.
|
// reputation contract.
|
||||||
func (w *ClientWrapper) PutViaNotary(v PutArgs) error {
|
func (w *ClientWrapper) PutViaNotary(v PutArgs) error {
|
||||||
args := reputationClient.PutArgs{}
|
args, err := preparePutArgs(v)
|
||||||
args.SetEpoch(v.epoch)
|
if err != nil {
|
||||||
args.SetPeerID(v.peerID.Bytes())
|
return err
|
||||||
args.SetValue(v.value) // todo: marshal reputation value to `value` bytes there
|
}
|
||||||
|
|
||||||
return (*reputationClient.Client)(w).PutViaNotary(args)
|
return (*reputationClient.Client)(w).PutViaNotary(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func preparePutArgs(v PutArgs) (reputationClient.PutArgs, error) {
|
||||||
|
args := reputationClient.PutArgs{}
|
||||||
|
|
||||||
|
data, err := v.value.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return args, errors.Wrap(err, "can't marshal global trust value")
|
||||||
|
}
|
||||||
|
|
||||||
|
args.SetEpoch(v.epoch)
|
||||||
|
args.SetPeerID(v.peerID.ToV2().GetValue())
|
||||||
|
args.SetValue(data)
|
||||||
|
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package reputation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/reputation"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,9 +13,11 @@ import (
|
||||||
type Put struct {
|
type Put struct {
|
||||||
epoch uint64
|
epoch uint64
|
||||||
peerID reputation.PeerID
|
peerID reputation.PeerID
|
||||||
value []byte
|
value reputation.GlobalTrust
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const peerIDLength = 33 // compressed public key
|
||||||
|
|
||||||
// MorphEvent implements Neo:Morph Event interface.
|
// MorphEvent implements Neo:Morph Event interface.
|
||||||
func (Put) MorphEvent() {}
|
func (Put) MorphEvent() {}
|
||||||
|
|
||||||
|
@ -30,8 +32,8 @@ func (p Put) PeerID() reputation.PeerID {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns reputation structure.
|
// Value returns reputation structure.
|
||||||
func (p Put) Value() []byte {
|
func (p Put) Value() reputation.GlobalTrust {
|
||||||
return p.value // consider returning parsed structure
|
return p.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParsePut from notification into reputation event structure.
|
// ParsePut from notification into reputation event structure.
|
||||||
|
@ -45,6 +47,7 @@ func ParsePut(prms []stackitem.Item) (event.Event, error) {
|
||||||
return nil, event.WrongNumberOfParameters(3, ln)
|
return nil, event.WrongNumberOfParameters(3, ln)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse epoch number
|
||||||
epoch, err := client.IntFromStackItem(prms[0])
|
epoch, err := client.IntFromStackItem(prms[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get integer epoch number")
|
return nil, errors.Wrap(err, "could not get integer epoch number")
|
||||||
|
@ -52,16 +55,29 @@ func ParsePut(prms []stackitem.Item) (event.Event, error) {
|
||||||
|
|
||||||
ev.epoch = uint64(epoch)
|
ev.epoch = uint64(epoch)
|
||||||
|
|
||||||
|
// parse peer ID value
|
||||||
peerID, err := client.BytesFromStackItem(prms[1])
|
peerID, err := client.BytesFromStackItem(prms[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get peer ID value")
|
return nil, errors.Wrap(err, "could not get peer ID value")
|
||||||
}
|
}
|
||||||
|
|
||||||
ev.peerID = reputation.PeerIDFromBytes(peerID)
|
if ln := len(peerID); ln != peerIDLength {
|
||||||
|
return nil, errors.Errorf("peer ID is %d byte long, expected %d", ln, peerIDLength)
|
||||||
|
}
|
||||||
|
|
||||||
ev.value, err = client.BytesFromStackItem(prms[2])
|
var publicKey [33]byte
|
||||||
|
copy(publicKey[:], peerID)
|
||||||
|
ev.peerID.SetPublicKey(publicKey)
|
||||||
|
|
||||||
|
// parse global trust value
|
||||||
|
rawValue, err := client.BytesFromStackItem(prms[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get reputation value")
|
return nil, errors.Wrap(err, "could not get global trust value")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ev.value.Unmarshal(rawValue)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not parse global trust value")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ev, nil
|
return ev, nil
|
||||||
|
|
|
@ -5,19 +5,34 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/reputation"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParsePut(t *testing.T) {
|
func TestParsePut(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
|
peerID reputation.PeerID
|
||||||
|
|
||||||
|
value reputation.GlobalTrust
|
||||||
|
trust reputation.Trust
|
||||||
|
trustValue float64 = 64
|
||||||
|
|
||||||
epoch uint64 = 42
|
epoch uint64 = 42
|
||||||
|
|
||||||
peerID = reputation.PeerIDFromBytes([]byte("peerID"))
|
rawPeerID = [33]byte{1, 2, 3, 4, 5, 6}
|
||||||
value = []byte("There should be marshalled structure")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
peerID.SetPublicKey(rawPeerID)
|
||||||
|
|
||||||
|
trust.SetValue(trustValue)
|
||||||
|
trust.SetPeer(&peerID)
|
||||||
|
|
||||||
|
value.SetTrust(&trust)
|
||||||
|
|
||||||
|
rawValue, err := value.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("wrong number of parameters", func(t *testing.T) {
|
t.Run("wrong number of parameters", func(t *testing.T) {
|
||||||
prms := []stackitem.Item{
|
prms := []stackitem.Item{
|
||||||
stackitem.NewMap(),
|
stackitem.NewMap(),
|
||||||
|
@ -48,7 +63,7 @@ func TestParsePut(t *testing.T) {
|
||||||
t.Run("wrong value parameter", func(t *testing.T) {
|
t.Run("wrong value parameter", func(t *testing.T) {
|
||||||
_, err := ParsePut([]stackitem.Item{
|
_, err := ParsePut([]stackitem.Item{
|
||||||
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
|
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
|
||||||
stackitem.NewByteArray(peerID.Bytes()),
|
stackitem.NewByteArray(rawPeerID[:]),
|
||||||
stackitem.NewMap(),
|
stackitem.NewMap(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -58,8 +73,8 @@ func TestParsePut(t *testing.T) {
|
||||||
t.Run("correct behavior", func(t *testing.T) {
|
t.Run("correct behavior", func(t *testing.T) {
|
||||||
ev, err := ParsePut([]stackitem.Item{
|
ev, err := ParsePut([]stackitem.Item{
|
||||||
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
|
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
|
||||||
stackitem.NewByteArray(peerID.Bytes()),
|
stackitem.NewByteArray(rawPeerID[:]),
|
||||||
stackitem.NewByteArray(value),
|
stackitem.NewByteArray(rawValue),
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue