forked from TrueCloudLab/frostfs-node
[#247] morph: Drop reputation contract
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
This commit is contained in:
parent
960e3c219e
commit
8799138fcb
8 changed files with 0 additions and 560 deletions
|
@ -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.
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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),
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue