From 27cf6f5112ec8259add2daaf306b7223fd86afa7 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Mon, 5 Apr 2021 12:29:33 +0300 Subject: [PATCH] [#452] Use API structures for reputation PeerID and GlobalTrust Signed-off-by: Alex Vanin --- .../processors/reputation/handlers.go | 6 ++- .../processors/reputation/process_put.go | 28 ++++++++++++-- pkg/morph/client/reputation/wrapper/get.go | 23 ++++++++--- pkg/morph/client/reputation/wrapper/put.go | 38 +++++++++++++------ pkg/morph/event/reputation/put.go | 30 +++++++++++---- pkg/morph/event/reputation/put_test.go | 27 ++++++++++--- 6 files changed, 116 insertions(+), 36 deletions(-) diff --git a/pkg/innerring/processors/reputation/handlers.go b/pkg/innerring/processors/reputation/handlers.go index 28b54125..d5383a48 100644 --- a/pkg/innerring/processors/reputation/handlers.go +++ b/pkg/innerring/processors/reputation/handlers.go @@ -10,16 +10,18 @@ import ( func (rp *Processor) handlePutReputation(ev event.Event) { put := ev.(reputationEvent.Put) + peerID := put.PeerID() + rp.log.Info("notification", 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 err := rp.pool.Submit(func() { rp.processPut( put.Epoch(), - put.PeerID(), + peerID, put.Value(), ) }) diff --git a/pkg/innerring/processors/reputation/process_put.go b/pkg/innerring/processors/reputation/process_put.go index 64426d0e..c1f97cfd 100644 --- a/pkg/innerring/processors/reputation/process_put.go +++ b/pkg/innerring/processors/reputation/process_put.go @@ -3,18 +3,38 @@ package reputation import ( "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/services/reputation" "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() { rp.log.Info("non alphabet mode, ignore reputation put notification") 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.SetEpoch(epoch) @@ -24,7 +44,7 @@ func (rp *Processor) processPut(epoch uint64, id reputation.PeerID, value []byte err := rp.reputationWrp.PutViaNotary(args) if err != nil { 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())) } } diff --git a/pkg/morph/client/reputation/wrapper/get.go b/pkg/morph/client/reputation/wrapper/get.go index 4924b47a..2d3d1b3a 100644 --- a/pkg/morph/client/reputation/wrapper/get.go +++ b/pkg/morph/client/reputation/wrapper/get.go @@ -1,8 +1,9 @@ package wrapper import ( + "github.com/nspcc-dev/neofs-api-go/pkg/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 ( @@ -21,7 +22,7 @@ type ( // GetResults groups the result of "get reputation value" and // "get reputation value by reputation id" test invocations. 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. -func (g GetResult) Reputations() [][]byte { +func (g GetResult) Reputations() []reputation.GlobalTrust { return g.reputations } @@ -49,7 +50,7 @@ func (g GetResult) Reputations() [][]byte { func (w *ClientWrapper) Get(v GetArgs) (*GetResult, error) { args := reputationClient.GetArgs{} args.SetEpoch(v.epoch) - args.SetPeerID(v.peerID.Bytes()) + args.SetPeerID(v.peerID.ToV2().GetValue()) data, err := (*reputationClient.Client)(w).Get(args) if err != nil { @@ -75,10 +76,20 @@ func (w *ClientWrapper) GetByID(v GetByIDArgs) (*GetResult, error) { func parseGetResult(data *reputationClient.GetResult) (*GetResult, error) { 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{ - reputations: rawReputations, + reputations: reputations, }, nil } diff --git a/pkg/morph/client/reputation/wrapper/put.go b/pkg/morph/client/reputation/wrapper/put.go index b181d97a..91a693cd 100644 --- a/pkg/morph/client/reputation/wrapper/put.go +++ b/pkg/morph/client/reputation/wrapper/put.go @@ -1,8 +1,9 @@ package wrapper import ( + "github.com/nspcc-dev/neofs-api-go/pkg/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 ( @@ -10,7 +11,7 @@ type ( PutArgs struct { epoch uint64 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. -func (p *PutArgs) SetValue(v []byte) { +func (p *PutArgs) SetValue(v reputation.GlobalTrust) { p.value = v } // Put invokes direct call of "put reputation value" method of reputation contract. func (w *ClientWrapper) Put(v PutArgs) error { - args := reputationClient.PutArgs{} - args.SetEpoch(v.epoch) - args.SetPeerID(v.peerID.Bytes()) - args.SetValue(v.value) // todo: marshal reputation value to `value` bytes there + args, err := preparePutArgs(v) + if err != nil { + return err + } 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 // reputation contract. func (w *ClientWrapper) PutViaNotary(v PutArgs) error { - args := reputationClient.PutArgs{} - args.SetEpoch(v.epoch) - args.SetPeerID(v.peerID.Bytes()) - args.SetValue(v.value) // todo: marshal reputation value to `value` bytes there + args, err := preparePutArgs(v) + if err != nil { + return err + } 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 +} diff --git a/pkg/morph/event/reputation/put.go b/pkg/morph/event/reputation/put.go index 89b76109..1acc9873 100644 --- a/pkg/morph/event/reputation/put.go +++ b/pkg/morph/event/reputation/put.go @@ -2,9 +2,9 @@ package reputation import ( "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/event" - "github.com/nspcc-dev/neofs-node/pkg/services/reputation" "github.com/pkg/errors" ) @@ -13,9 +13,11 @@ import ( type Put struct { epoch uint64 peerID reputation.PeerID - value []byte + value reputation.GlobalTrust } +const peerIDLength = 33 // compressed public key + // MorphEvent implements Neo:Morph Event interface. func (Put) MorphEvent() {} @@ -30,8 +32,8 @@ func (p Put) PeerID() reputation.PeerID { } // Value returns reputation structure. -func (p Put) Value() []byte { - return p.value // consider returning parsed structure +func (p Put) Value() reputation.GlobalTrust { + return p.value } // 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) } + // parse epoch number epoch, err := client.IntFromStackItem(prms[0]) if err != nil { 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) + // parse peer ID value peerID, err := client.BytesFromStackItem(prms[1]) if err != nil { 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 { - 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 diff --git a/pkg/morph/event/reputation/put_test.go b/pkg/morph/event/reputation/put_test.go index 9856f0bd..c67a9606 100644 --- a/pkg/morph/event/reputation/put_test.go +++ b/pkg/morph/event/reputation/put_test.go @@ -5,19 +5,34 @@ import ( "testing" "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/services/reputation" "github.com/stretchr/testify/require" ) func TestParsePut(t *testing.T) { var ( + peerID reputation.PeerID + + value reputation.GlobalTrust + trust reputation.Trust + trustValue float64 = 64 + epoch uint64 = 42 - peerID = reputation.PeerIDFromBytes([]byte("peerID")) - value = []byte("There should be marshalled structure") + rawPeerID = [33]byte{1, 2, 3, 4, 5, 6} ) + 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) { prms := []stackitem.Item{ stackitem.NewMap(), @@ -48,7 +63,7 @@ func TestParsePut(t *testing.T) { t.Run("wrong value parameter", func(t *testing.T) { _, err := ParsePut([]stackitem.Item{ stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)), - stackitem.NewByteArray(peerID.Bytes()), + stackitem.NewByteArray(rawPeerID[:]), stackitem.NewMap(), }) @@ -58,8 +73,8 @@ func TestParsePut(t *testing.T) { t.Run("correct behavior", func(t *testing.T) { ev, err := ParsePut([]stackitem.Item{ stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)), - stackitem.NewByteArray(peerID.Bytes()), - stackitem.NewByteArray(value), + stackitem.NewByteArray(rawPeerID[:]), + stackitem.NewByteArray(rawValue), }) require.NoError(t, err)