From 05a351d344ec33f8ad91ab88736d035a08223a0d Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 2 Apr 2021 12:20:09 +0300 Subject: [PATCH] [#265] pkg/reputation: Change PeerID implementation Make `PeerID` type to be the wrapper over v2 `PeerID` message structure. Signed-off-by: Leonard Lyubich --- pkg/reputation/peer.go | 92 ++++++++++++++++++++++++++++----- pkg/reputation/peer_test.go | 46 ++++++++++++++--- pkg/reputation/test/generate.go | 6 ++- 3 files changed, 123 insertions(+), 21 deletions(-) diff --git a/pkg/reputation/peer.go b/pkg/reputation/peer.go index ef1a314f..60d4ea32 100644 --- a/pkg/reputation/peer.go +++ b/pkg/reputation/peer.go @@ -1,29 +1,93 @@ package reputation +import ( + "bytes" + + "github.com/mr-tron/base58" + "github.com/nspcc-dev/neofs-api-go/v2/reputation" + crypto "github.com/nspcc-dev/neofs-crypto" +) + // PeerID represents peer ID compatible with NeoFS API v2. -type PeerID []byte +type PeerID reputation.PeerID // NewPeerID creates and returns blank PeerID. func NewPeerID() *PeerID { - return PeerIDFromV2(nil) + return PeerIDFromV2(new(reputation.PeerID)) } -// PeerIDFromV2 converts bytes slice to PeerID. -func PeerIDFromV2(data []byte) *PeerID { - return (*PeerID)(&data) +// PeerIDFromV2 converts NeoFS API v2 reputation.PeerID message to PeerID. +func PeerIDFromV2(id *reputation.PeerID) *PeerID { + return (*PeerID)(id) } -// SetBytes sets bytes of peer ID. -func (x *PeerID) SetBytes(v []byte) { - *x = v +// SetPublicKey sets peer ID as a compressed public key. +func (x *PeerID) SetPublicKey(v [crypto.PublicKeyCompressedSize]byte) { + (*reputation.PeerID)(x). + SetValue(v[:]) } -// Bytes returns bytes of peer ID. -func (x PeerID) Bytes() []byte { - return x +// ToV2 converts PeerID to NeoFS API v2 reputation.PeerID message. +func (x *PeerID) ToV2() *reputation.PeerID { + return (*reputation.PeerID)(x) } -// ToV2 converts PeerID to byte slice. -func (x PeerID) ToV2() []byte { - return x +// Equal returns true if identifiers are identical. +func (x *PeerID) Equal(x2 *PeerID) bool { + return bytes.Equal( + (*reputation.PeerID)(x).GetValue(), + (*reputation.PeerID)(x2).GetValue(), + ) +} + +// Parse parses PeerID from base58 string. +func (x *PeerID) Parse(s string) error { + data, err := base58.Decode(s) + if err != nil { + return err + } + + (*reputation.PeerID)(x).SetValue(data) + + return nil +} + +// String returns base58 string representation of PeerID. +func (x *PeerID) String() string { + return base58.Encode( + (*reputation.PeerID)(x). + GetValue(), + ) +} + +// Marshal marshals PeerID into a protobuf binary form. +// +// Buffer is allocated when the argument is empty. +// Otherwise, the first buffer is used. +func (x *PeerID) Marshal(b ...[]byte) ([]byte, error) { + var buf []byte + if len(b) > 0 { + buf = b[0] + } + + return (*reputation.PeerID)(x). + StableMarshal(buf) +} + +// Unmarshal unmarshals protobuf binary representation of PeerID. +func (x *PeerID) Unmarshal(data []byte) error { + return (*reputation.PeerID)(x). + Unmarshal(data) +} + +// MarshalJSON encodes PeerID to protobuf JSON format. +func (x *PeerID) MarshalJSON() ([]byte, error) { + return (*reputation.PeerID)(x). + MarshalJSON() +} + +// UnmarshalJSON decodes PeerID from protobuf JSON format. +func (x *PeerID) UnmarshalJSON(data []byte) error { + return (*reputation.PeerID)(x). + UnmarshalJSON(data) } diff --git a/pkg/reputation/peer_test.go b/pkg/reputation/peer_test.go index 79c0da74..4a63546c 100644 --- a/pkg/reputation/peer_test.go +++ b/pkg/reputation/peer_test.go @@ -4,15 +4,49 @@ import ( "testing" "github.com/nspcc-dev/neofs-api-go/pkg/reputation" + reputationtest "github.com/nspcc-dev/neofs-api-go/pkg/reputation/test" "github.com/stretchr/testify/require" ) -func TestPeerID(t *testing.T) { - peerID := reputation.NewPeerID() - - data := []byte{1, 2, 3} - peerID.SetBytes(data) - require.Equal(t, data, peerID.Bytes()) +func TestPeerID_ToV2(t *testing.T) { + peerID := reputationtest.GeneratePeerID() require.Equal(t, peerID, reputation.PeerIDFromV2(peerID.ToV2())) } + +func TestPeerID_String(t *testing.T) { + id := reputationtest.GeneratePeerID() + + strID := id.String() + + id2 := reputation.NewPeerID() + + err := id2.Parse(strID) + require.NoError(t, err) + + require.Equal(t, id, id2) +} + +func TestPeerIDEncoding(t *testing.T) { + id := reputationtest.GeneratePeerID() + + t.Run("binary", func(t *testing.T) { + data, err := id.Marshal() + require.NoError(t, err) + + id2 := reputation.NewPeerID() + require.NoError(t, id2.Unmarshal(data)) + + require.Equal(t, id, id2) + }) + + t.Run("json", func(t *testing.T) { + data, err := id.MarshalJSON() + require.NoError(t, err) + + id2 := reputation.NewPeerID() + require.NoError(t, id2.UnmarshalJSON(data)) + + require.Equal(t, id, id2) + }) +} diff --git a/pkg/reputation/test/generate.go b/pkg/reputation/test/generate.go index 7d02c8b9..06676e9e 100644 --- a/pkg/reputation/test/generate.go +++ b/pkg/reputation/test/generate.go @@ -8,7 +8,11 @@ import ( func GeneratePeerID() *reputation.PeerID { v := reputation.NewPeerID() - v.SetBytes(crypto.MarshalPublicKey(&test.DecodeKey(-1).PublicKey)) + + key := [crypto.PublicKeyCompressedSize]byte{} + copy(key[:], crypto.MarshalPublicKey(&test.DecodeKey(-1).PublicKey)) + + v.SetPublicKey(key) return v }