[#452] Use API structures for reputation PeerID and GlobalTrust

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2021-04-05 12:29:33 +03:00 committed by Alex Vanin
parent 7cf48d4d91
commit 27cf6f5112
6 changed files with 116 additions and 36 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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