[#247] morph: Drop reputation contract

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
This commit is contained in:
Pavel Karpy 2023-04-14 14:05:31 +03:00
parent 960e3c219e
commit 8799138fcb
8 changed files with 0 additions and 560 deletions

View file

@ -32,8 +32,6 @@ const (
NNSNetmapContractName = "netmap.frostfs"
// NNSProxyContractName is a name of the proxy contract in NNS.
NNSProxyContractName = "proxy.frostfs"
// NNSReputationContractName is a name of the reputation contract in NNS.
NNSReputationContractName = "reputation.frostfs"
// NNSSubnetworkContractName is a name of the subnet contract in NNS.
NNSSubnetworkContractName = "subnet.frostfs"
// NNSGroupKeyName is a name for the FrostFS group key record in NNS.

View file

@ -1,83 +0,0 @@
package reputation
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Client is a wrapper over StaticClient
// which makes calls with the names and arguments
// of the FrostFS reputation contract.
//
// Working client must be created via constructor New.
// Using the Client that has been created with new(Client)
// expression (or just declaring a Client variable) is unsafe
// and can lead to panic.
type Client struct {
client *client.StaticClient // static reputation contract client
}
const (
putMethod = "put"
getMethod = "get"
getByIDMethod = "getByID"
listByEpochMethod = "listByEpoch"
)
// NewFromMorph returns the wrapper instance from the raw morph client.
func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts ...Option) (*Client, error) {
o := defaultOpts()
for i := range opts {
opts[i](o)
}
sc, err := client.NewStatic(cli, contract, fee, ([]client.StaticClientOption)(*o)...)
if err != nil {
return nil, fmt.Errorf("could not create static client of reputation contract: %w", err)
}
return &Client{client: sc}, nil
}
// Morph returns raw morph client.
func (c Client) Morph() *client.Client {
return c.client.Morph()
}
// ContractAddress returns the address of the associated contract.
func (c Client) ContractAddress() util.Uint160 {
return c.client.ContractAddress()
}
// Option allows to set an optional
// parameter of ClientWrapper.
type Option func(*opts)
type opts []client.StaticClientOption
func defaultOpts() *opts {
return new(opts)
}
// TryNotary returns option to enable
// notary invocation tries.
func TryNotary() Option {
return func(o *opts) {
*o = append(*o, client.TryNotary())
}
}
// AsAlphabet returns option to sign main TX
// of notary requests with client's private
// key.
//
// Considered to be used by IR nodes only.
func AsAlphabet() Option {
return func(o *opts) {
*o = append(*o, client.AsAlphabet())
}
}

View file

@ -1,108 +0,0 @@
package reputation
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/reputation"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
type (
// GetPrm groups the arguments of "get reputation value" test invocation.
GetPrm struct {
epoch uint64
peerID reputation.PeerID
}
// GetByIDPrm groups the arguments of "get reputation value by
// reputation id" test invocation.
GetByIDPrm struct {
id ID
}
)
// SetEpoch sets epoch of expected reputation value.
func (g *GetPrm) SetEpoch(v uint64) {
g.epoch = v
}
// SetPeerID sets peer id of expected reputation value.
func (g *GetPrm) SetPeerID(v reputation.PeerID) {
g.peerID = v
}
// SetID sets id of expected reputation value in reputation contract.
func (g *GetByIDPrm) SetID(v ID) {
g.id = v
}
// Get invokes the call of "get reputation value" method of reputation contract.
func (c *Client) Get(p GetPrm) ([]reputation.GlobalTrust, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(getMethod)
invokePrm.SetArgs(p.epoch, p.peerID.PublicKey())
res, err := c.client.TestInvoke(invokePrm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getMethod, err)
}
return parseReputations(res, getMethod)
}
// GetByID invokes the call of "get reputation value by reputation id" method
// of reputation contract.
func (c *Client) GetByID(p GetByIDPrm) ([]reputation.GlobalTrust, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(getByIDMethod)
invokePrm.SetArgs([]byte(p.id))
prms, err := c.client.TestInvoke(invokePrm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getByIDMethod, err)
}
return parseReputations(prms, getByIDMethod)
}
func parseGetResult(rawReputations [][]byte, method string) ([]reputation.GlobalTrust, error) {
reputations := make([]reputation.GlobalTrust, 0, len(rawReputations))
for i := range rawReputations {
r := reputation.GlobalTrust{}
err := r.Unmarshal(rawReputations[i])
if err != nil {
return nil, fmt.Errorf("can't unmarshal global trust value (%s): %w", method, err)
}
reputations = append(reputations, r)
}
return reputations, nil
}
func parseReputations(items []stackitem.Item, method string) ([]reputation.GlobalTrust, error) {
if ln := len(items); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", method, ln)
}
items, err := client.ArrayFromStackItem(items[0])
if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", method, err)
}
res := make([][]byte, 0, len(items))
for i := range items {
rawReputation, err := client.BytesFromStackItem(items[i])
if err != nil {
return nil, fmt.Errorf("could not get byte array from stack item (%s): %w", method, err)
}
res = append(res, rawReputation)
}
return parseGetResult(res, method)
}

View file

@ -1,55 +0,0 @@
package reputation
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)
type (
// ID is an ID of the reputation record in reputation contract.
ID []byte
// ListByEpochArgs groups the arguments of
// "list reputation ids by epoch" test invoke call.
ListByEpochArgs struct {
epoch uint64
}
)
// SetEpoch sets epoch of expected reputation ids.
func (l *ListByEpochArgs) SetEpoch(v uint64) {
l.epoch = v
}
// ListByEpoch invokes the call of "list reputation ids by epoch" method of
// reputation contract.
func (c *Client) ListByEpoch(p ListByEpochArgs) ([]ID, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(listByEpochMethod)
invokePrm.SetArgs(p.epoch)
prms, err := c.client.TestInvoke(invokePrm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", listByEpochMethod, err)
} else if ln := len(prms); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", listByEpochMethod, ln)
}
items, err := client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listByEpochMethod, err)
}
result := make([]ID, 0, len(items))
for i := range items {
rawReputation, err := client.BytesFromStackItem(items[i])
if err != nil {
return nil, fmt.Errorf("could not get byte array from stack item (%s): %w", listByEpochMethod, err)
}
result = append(result, rawReputation)
}
return result, nil
}

View file

@ -1,47 +0,0 @@
package reputation
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/reputation"
)
type (
// PutPrm groups the arguments of "put reputation value" invocation call.
PutPrm struct {
epoch uint64
peerID reputation.PeerID
value reputation.GlobalTrust
}
)
// SetEpoch sets epoch of reputation value.
func (p *PutPrm) SetEpoch(v uint64) {
p.epoch = v
}
// SetPeerID sets peer id of reputation value.
func (p *PutPrm) SetPeerID(v reputation.PeerID) {
p.peerID = v
}
// SetValue sets reputation value.
func (p *PutPrm) SetValue(v reputation.GlobalTrust) {
p.value = v
}
// Put invokes direct call of "put reputation value" method of reputation contract.
//
// If TryNotary is provided, calls notary contract.
func (c *Client) Put(p PutPrm) error {
prm := client.InvokePrm{}
prm.SetMethod(putMethod)
prm.SetArgs(p.epoch, p.peerID.PublicKey(), p.value.Marshal())
err := c.client.Invoke(prm)
if err != nil {
return fmt.Errorf("could not invoke method (%s): %w", putMethod, err)
}
return nil
}

View file

@ -1,99 +0,0 @@
package reputation
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/reputation"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
)
// Put structure of reputation.reputationPut notification from
// morph chain.
type Put struct {
epoch uint64
peerID reputation.PeerID
value reputation.GlobalTrust
// For notary notifications only.
// Contains raw transactions of notary request.
notaryRequest *payload.P2PNotaryRequest
}
const peerIDLength = 33 // compressed public key
// MorphEvent implements Neo:Morph Event interface.
func (Put) MorphEvent() {}
// Epoch returns epoch value of reputation data.
func (p Put) Epoch() uint64 {
return p.epoch
}
// PeerID returns peer id of reputation data.
func (p Put) PeerID() reputation.PeerID {
return p.peerID
}
// Value returns reputation structure.
func (p Put) Value() reputation.GlobalTrust {
return p.value
}
// NotaryRequest returns raw notary request if notification
// was received via notary service. Otherwise, returns nil.
func (p Put) NotaryRequest() *payload.P2PNotaryRequest {
return p.notaryRequest
}
// ParsePut from notification into reputation event structure.
func ParsePut(e *state.ContainedNotificationEvent) (event.Event, error) {
var (
ev Put
err error
)
params, err := event.ParseStackArray(e)
if err != nil {
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
}
if ln := len(params); ln != 3 {
return nil, event.WrongNumberOfParameters(3, ln)
}
// parse epoch number
epoch, err := client.IntFromStackItem(params[0])
if err != nil {
return nil, fmt.Errorf("could not get integer epoch number: %w", err)
}
ev.epoch = uint64(epoch)
// parse peer ID value
peerID, err := client.BytesFromStackItem(params[1])
if err != nil {
return nil, fmt.Errorf("could not get peer ID value: %w", err)
}
if ln := len(peerID); ln != peerIDLength {
return nil, fmt.Errorf("peer ID is %d byte long, expected %d", ln, peerIDLength)
}
ev.peerID.SetPublicKey(peerID)
// parse global trust value
rawValue, err := client.BytesFromStackItem(params[2])
if err != nil {
return nil, fmt.Errorf("could not get global trust value: %w", err)
}
err = ev.value.Unmarshal(rawValue)
if err != nil {
return nil, fmt.Errorf("could not parse global trust value: %w", err)
}
return ev, nil
}

View file

@ -1,74 +0,0 @@
package reputation
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
)
func (p *Put) setEpoch(v uint64) {
p.epoch = v
}
func (p *Put) setPeerID(v []byte) error {
if ln := len(v); ln != peerIDLength {
return fmt.Errorf("peer ID is %d byte long, expected %d", ln, peerIDLength)
}
p.peerID.SetPublicKey(v)
return nil
}
func (p *Put) setValue(v []byte) error {
return p.value.Unmarshal(v)
}
var fieldSetters = []func(*Put, []byte) error{
// order on stack is reversed
(*Put).setValue,
(*Put).setPeerID,
}
const (
// PutNotaryEvent is method name for reputation put operations
// in `Reputation` contract. Is used as identifier for notary
// put reputation requests.
PutNotaryEvent = "put"
)
// ParsePutNotary from NotaryEvent into reputation event structure.
func ParsePutNotary(ne event.NotaryEvent) (event.Event, error) {
var ev Put
fieldNum := 0
for _, op := range ne.Params() {
switch fieldNum {
case 0, 1:
data, err := event.BytesFromOpcode(op)
if err != nil {
return nil, err
}
err = fieldSetters[fieldNum](&ev, data)
if err != nil {
return nil, fmt.Errorf("can't parse field num %d: %w", fieldNum, err)
}
case 2:
n, err := event.IntFromOpcode(op)
if err != nil {
return nil, err
}
ev.setEpoch(uint64(n))
default:
return nil, event.UnexpectedArgNumErr(PutNotaryEvent)
}
fieldNum++
}
ev.notaryRequest = ne.Raw()
return ev, nil
}

View file

@ -1,92 +0,0 @@
package reputation
import (
"math/big"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/reputation"
reputationtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/reputation/test"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
func TestParsePut(t *testing.T) {
var (
peerID = reputationtest.PeerID()
value reputation.GlobalTrust
trust reputation.Trust
trustValue float64 = 0.64
epoch uint64 = 42
)
trust.SetValue(trustValue)
trust.SetPeer(peerID)
value.SetTrust(trust)
rawValue := value.Marshal()
t.Run("wrong number of parameters", func(t *testing.T) {
prms := []stackitem.Item{
stackitem.NewMap(),
stackitem.NewMap(),
}
_, err := ParsePut(createNotifyEventFromItems(prms))
require.EqualError(t, err, event.WrongNumberOfParameters(3, len(prms)).Error())
})
t.Run("wrong epoch parameter", func(t *testing.T) {
_, err := ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("wrong peerID parameter", func(t *testing.T) {
_, err := ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("wrong value parameter", func(t *testing.T) {
_, err := ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
stackitem.NewByteArray(peerID.PublicKey()),
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("correct behavior", func(t *testing.T) {
ev, err := ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewBigInteger(new(big.Int).SetUint64(epoch)),
stackitem.NewByteArray(peerID.PublicKey()),
stackitem.NewByteArray(rawValue),
}))
require.NoError(t, err)
require.Equal(t, Put{
epoch: epoch,
peerID: peerID,
value: value,
}, ev)
})
}
func createNotifyEventFromItems(items []stackitem.Item) *state.ContainedNotificationEvent {
return &state.ContainedNotificationEvent{
NotificationEvent: state.NotificationEvent{
Item: stackitem.NewArray(items),
},
}
}