forked from TrueCloudLab/frostfs-node
[#1513] Upgrade NeoFS SDK Go with changed netmap
package
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
24b4c1ecf4
commit
21d2f8f861
70 changed files with 878 additions and 992 deletions
|
@ -9,13 +9,13 @@ import (
|
|||
|
||||
// AddPeerPrm groups parameters of AddPeer operation.
|
||||
type AddPeerPrm struct {
|
||||
nodeInfo *netmap.NodeInfo
|
||||
nodeInfo netmap.NodeInfo
|
||||
|
||||
client.InvokePrmOptional
|
||||
}
|
||||
|
||||
// SetNodeInfo sets new peer NodeInfo.
|
||||
func (a *AddPeerPrm) SetNodeInfo(nodeInfo *netmap.NodeInfo) {
|
||||
func (a *AddPeerPrm) SetNodeInfo(nodeInfo netmap.NodeInfo) {
|
||||
a.nodeInfo = nodeInfo
|
||||
}
|
||||
|
||||
|
@ -31,18 +31,9 @@ func (c *Client) AddPeer(p AddPeerPrm) error {
|
|||
method += "IR"
|
||||
}
|
||||
|
||||
if p.nodeInfo == nil {
|
||||
return fmt.Errorf("nil node info (%s)", method)
|
||||
}
|
||||
|
||||
rawNodeInfo, err := p.nodeInfo.Marshal()
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't marshal node info (%s): %w", method, err)
|
||||
}
|
||||
|
||||
prm := client.InvokePrm{}
|
||||
prm.SetMethod(method)
|
||||
prm.SetArgs(rawNodeInfo)
|
||||
prm.SetArgs(p.nodeInfo.Marshal())
|
||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
||||
|
||||
if err := c.client.Invoke(prm); err != nil {
|
||||
|
|
|
@ -185,85 +185,112 @@ func (c *Client) SetConfig(p SetConfigPrm) error {
|
|||
return c.client.Invoke(prm)
|
||||
}
|
||||
|
||||
// IterateConfigParameters iterates over configuration parameters stored in Netmap contract and passes them to f.
|
||||
//
|
||||
// Returns f's errors directly.
|
||||
func (c *Client) IterateConfigParameters(f func(key, value []byte) error) error {
|
||||
// RawNetworkParameter is a NeoFS network parameter which is transmitted but
|
||||
// not interpreted by the NeoFS API protocol.
|
||||
type RawNetworkParameter struct {
|
||||
// Name of the parameter.
|
||||
Name string
|
||||
|
||||
// Raw parameter value.
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// NetworkConfiguration represents NeoFS network configuration stored
|
||||
// in the NeoFS Sidechain.
|
||||
type NetworkConfiguration struct {
|
||||
MaxObjectSize uint64
|
||||
|
||||
StoragePrice uint64
|
||||
|
||||
AuditFee uint64
|
||||
|
||||
EpochDuration uint64
|
||||
|
||||
ContainerFee uint64
|
||||
|
||||
ContainerAliasFee uint64
|
||||
|
||||
EigenTrustIterations uint64
|
||||
|
||||
EigenTrustAlpha float64
|
||||
|
||||
IRCandidateFee uint64
|
||||
|
||||
WithdrawalFee uint64
|
||||
|
||||
Raw []RawNetworkParameter
|
||||
}
|
||||
|
||||
// ReadNetworkConfiguration reads NetworkConfiguration from the NeoFS Sidechain.
|
||||
func (c *Client) ReadNetworkConfiguration() (*NetworkConfiguration, error) {
|
||||
prm := client.TestInvokePrm{}
|
||||
prm.SetMethod(configListMethod)
|
||||
|
||||
items, err := c.client.TestInvoke(prm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not perform test invocation (%s): %w",
|
||||
return nil, fmt.Errorf("could not perform test invocation (%s): %w",
|
||||
configListMethod, err)
|
||||
}
|
||||
|
||||
if ln := len(items); ln != 1 {
|
||||
return fmt.Errorf("unexpected stack item count (%s): %d", configListMethod, ln)
|
||||
return nil, fmt.Errorf("unexpected stack item count (%s): %d", configListMethod, ln)
|
||||
}
|
||||
|
||||
arr, err := client.ArrayFromStackItem(items[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("record list (%s): %w", configListMethod, err)
|
||||
return nil, fmt.Errorf("record list (%s): %w", configListMethod, err)
|
||||
}
|
||||
|
||||
return iterateRecords(arr, func(key, value []byte) error {
|
||||
return f(key, value)
|
||||
})
|
||||
}
|
||||
m := make(map[string]struct{}, len(arr))
|
||||
var res NetworkConfiguration
|
||||
res.Raw = make([]RawNetworkParameter, 0, len(arr))
|
||||
|
||||
// ConfigWriter is an interface of NeoFS network config writer.
|
||||
type ConfigWriter interface {
|
||||
UnknownParameter(string, []byte)
|
||||
MaxObjectSize(uint64)
|
||||
BasicIncomeRate(uint64)
|
||||
AuditFee(uint64)
|
||||
EpochDuration(uint64)
|
||||
ContainerFee(uint64)
|
||||
ContainerAliasFee(uint64)
|
||||
EigenTrustIterations(uint64)
|
||||
EigenTrustAlpha(float64)
|
||||
InnerRingCandidateFee(uint64)
|
||||
WithdrawFee(uint64)
|
||||
}
|
||||
err = iterateRecords(arr, func(name string, value []byte) error {
|
||||
_, ok := m[name]
|
||||
if ok {
|
||||
return fmt.Errorf("duplicated config name %s", name)
|
||||
}
|
||||
|
||||
// WriteConfig writes NeoFS network configuration received via iterator.
|
||||
//
|
||||
// Returns iterator's errors directly.
|
||||
func WriteConfig(dst ConfigWriter, iterator func(func(key, val []byte) error) error) error {
|
||||
return iterator(func(key, val []byte) error {
|
||||
switch k := string(key); k {
|
||||
m[name] = struct{}{}
|
||||
|
||||
switch name {
|
||||
default:
|
||||
dst.UnknownParameter(k, val)
|
||||
res.Raw = append(res.Raw, RawNetworkParameter{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
case maxObjectSizeConfig:
|
||||
dst.MaxObjectSize(bytesToUint64(val))
|
||||
res.MaxObjectSize = bytesToUint64(value)
|
||||
case basicIncomeRateConfig:
|
||||
dst.BasicIncomeRate(bytesToUint64(val))
|
||||
res.StoragePrice = bytesToUint64(value)
|
||||
case auditFeeConfig:
|
||||
dst.AuditFee(bytesToUint64(val))
|
||||
res.AuditFee = bytesToUint64(value)
|
||||
case epochDurationConfig:
|
||||
dst.EpochDuration(bytesToUint64(val))
|
||||
res.EpochDuration = bytesToUint64(value)
|
||||
case containerFeeConfig:
|
||||
dst.ContainerFee(bytesToUint64(val))
|
||||
res.ContainerFee = bytesToUint64(value)
|
||||
case containerAliasFeeConfig:
|
||||
dst.ContainerAliasFee(bytesToUint64(val))
|
||||
res.ContainerAliasFee = bytesToUint64(value)
|
||||
case etIterationsConfig:
|
||||
dst.EigenTrustIterations(bytesToUint64(val))
|
||||
res.EigenTrustIterations = bytesToUint64(value)
|
||||
case etAlphaConfig:
|
||||
v, err := strconv.ParseFloat(string(val), 64)
|
||||
res.EigenTrustAlpha, err = strconv.ParseFloat(string(value), 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("prm %s: %v", etAlphaConfig, err)
|
||||
return fmt.Errorf("invalid prm %s: %v", etAlphaConfig, err)
|
||||
}
|
||||
|
||||
dst.EigenTrustAlpha(v)
|
||||
case irCandidateFeeConfig:
|
||||
dst.InnerRingCandidateFee(bytesToUint64(val))
|
||||
res.IRCandidateFee = bytesToUint64(value)
|
||||
case withdrawFeeConfig:
|
||||
dst.WithdrawFee(bytesToUint64(val))
|
||||
res.WithdrawalFee = bytesToUint64(value)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func bytesToUint64(val []byte) uint64 {
|
||||
|
@ -307,7 +334,7 @@ func StringAssert(item stackitem.Item) (interface{}, error) {
|
|||
// iterateRecords iterates over all config records and passes them to f.
|
||||
//
|
||||
// Returns f's errors directly.
|
||||
func iterateRecords(arr []stackitem.Item, f func(key, value []byte) error) error {
|
||||
func iterateRecords(arr []stackitem.Item, f func(key string, value []byte) error) error {
|
||||
for i := range arr {
|
||||
fields, err := client.ArrayFromStackItem(arr[i])
|
||||
if err != nil {
|
||||
|
@ -328,7 +355,7 @@ func iterateRecords(arr []stackitem.Item, f func(key, value []byte) error) error
|
|||
return fmt.Errorf("record value: %w", err)
|
||||
}
|
||||
|
||||
if err := f(k, v); err != nil {
|
||||
if err := f(string(k), v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,20 +8,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
)
|
||||
|
||||
// State is an enumeration of various states of the NeoFS node.
|
||||
type State int64
|
||||
|
||||
const (
|
||||
// Undefined is unknown state.
|
||||
Undefined State = iota
|
||||
|
||||
// Online is network unavailable state.
|
||||
Online
|
||||
|
||||
// Offline is an active state in the network.
|
||||
Offline
|
||||
)
|
||||
|
||||
const (
|
||||
nodeInfoFixedPrmNumber = 1
|
||||
|
||||
|
@ -31,7 +17,7 @@ const (
|
|||
// GetNetMapByEpoch receives information list about storage nodes
|
||||
// through the Netmap contract call, composes network map
|
||||
// from them and returns it. Returns snapshot of the specified epoch number.
|
||||
func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.Netmap, error) {
|
||||
func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) {
|
||||
invokePrm := client.TestInvokePrm{}
|
||||
invokePrm.SetMethod(epochSnapshotMethod)
|
||||
invokePrm.SetArgs(epoch)
|
||||
|
@ -48,7 +34,7 @@ func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.Netmap, error) {
|
|||
// GetCandidates receives information list about candidates
|
||||
// for the next epoch network map through the Netmap contract
|
||||
// call, composes network map from them and returns it.
|
||||
func (c *Client) GetCandidates() (*netmap.Netmap, error) {
|
||||
func (c *Client) GetCandidates() (*netmap.NetMap, error) {
|
||||
invokePrm := client.TestInvokePrm{}
|
||||
invokePrm.SetMethod(netMapCandidatesMethod)
|
||||
|
||||
|
@ -62,7 +48,10 @@ func (c *Client) GetCandidates() (*netmap.Netmap, error) {
|
|||
return nil, fmt.Errorf("could not parse contract response: %w", err)
|
||||
}
|
||||
|
||||
return netmap.NewNetmap(netmap.NodesFromInfo(candVals))
|
||||
var nm netmap.NetMap
|
||||
nm.SetNodes(candVals)
|
||||
|
||||
return &nm, nil
|
||||
}
|
||||
|
||||
// NetMap performs the test invoke of get network map
|
||||
|
@ -128,11 +117,9 @@ func stackItemToNodeInfo(prm stackitem.Item, res *netmap.NodeInfo) error {
|
|||
|
||||
switch state {
|
||||
case 1:
|
||||
res.SetState(netmap.NodeStateOnline)
|
||||
res.SetOnline()
|
||||
case 2:
|
||||
res.SetState(netmap.NodeStateOffline)
|
||||
default:
|
||||
res.SetState(0)
|
||||
res.SetOffline()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -17,23 +17,29 @@ func Test_stackItemsToNodeInfos(t *testing.T) {
|
|||
pub := make([]byte, 33)
|
||||
rand.Read(pub)
|
||||
|
||||
expected[i].SetState(netmap.NodeState(i % 3))
|
||||
switch i % 3 {
|
||||
case 1:
|
||||
expected[i].SetOffline()
|
||||
case 2:
|
||||
expected[i].SetOnline()
|
||||
}
|
||||
|
||||
expected[i].SetPublicKey(pub)
|
||||
|
||||
var attr netmap.NodeAttribute
|
||||
attr.SetKey("key")
|
||||
attr.SetValue(strconv.Itoa(i))
|
||||
expected[i].SetAttributes(attr)
|
||||
expected[i].SetAttribute("key", strconv.Itoa(i))
|
||||
}
|
||||
|
||||
items := make([]stackitem.Item, 4)
|
||||
for i := range items {
|
||||
data, err := expected[i].Marshal()
|
||||
require.NoError(t, err)
|
||||
data := expected[i].Marshal()
|
||||
|
||||
state := int64(expected[i].State())
|
||||
if state != 0 { // In contract online=1, offline=2, in API it is the other way.
|
||||
state = 3 - state
|
||||
var state int64
|
||||
|
||||
switch {
|
||||
case expected[i].IsOnline():
|
||||
state = 1
|
||||
case expected[i].IsOffline():
|
||||
state = 2
|
||||
}
|
||||
|
||||
items[i] = stackitem.NewStruct([]stackitem.Item{
|
||||
|
|
|
@ -12,17 +12,17 @@ import (
|
|||
// through the Netmap contract call, composes network map
|
||||
// from them and returns it. With diff == 0 returns current
|
||||
// network map, else return snapshot of previous network map.
|
||||
func (c *Client) GetNetMap(diff uint64) (*netmap.Netmap, error) {
|
||||
func (c *Client) GetNetMap(diff uint64) (*netmap.NetMap, error) {
|
||||
return c.getNetMap(diff)
|
||||
}
|
||||
|
||||
// Snapshot returns current netmap node infos.
|
||||
// Consider using pkg/morph/client/netmap for this.
|
||||
func (c *Client) Snapshot() (*netmap.Netmap, error) {
|
||||
func (c *Client) Snapshot() (*netmap.NetMap, error) {
|
||||
return c.getNetMap(0)
|
||||
}
|
||||
|
||||
func (c *Client) getNetMap(diff uint64) (*netmap.Netmap, error) {
|
||||
func (c *Client) getNetMap(diff uint64) (*netmap.NetMap, error) {
|
||||
prm := client.TestInvokePrm{}
|
||||
prm.SetMethod(snapshotMethod)
|
||||
prm.SetArgs(diff)
|
||||
|
@ -35,7 +35,7 @@ func (c *Client) getNetMap(diff uint64) (*netmap.Netmap, error) {
|
|||
return unmarshalNetmap(res, snapshotMethod)
|
||||
}
|
||||
|
||||
func unmarshalNetmap(items []stackitem.Item, method string) (*netmap.Netmap, error) {
|
||||
func unmarshalNetmap(items []stackitem.Item, method string) (*netmap.NetMap, error) {
|
||||
rawPeers, err := peersFromStackItems(items, method)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -48,5 +48,8 @@ func unmarshalNetmap(items []stackitem.Item, method string) (*netmap.Netmap, err
|
|||
}
|
||||
}
|
||||
|
||||
return netmap.NewNetmap(netmap.NodesFromInfo(result))
|
||||
var nm netmap.NetMap
|
||||
nm.SetNodes(result)
|
||||
|
||||
return &nm, nil
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
)
|
||||
|
||||
// UpdatePeerPrm groups parameters of UpdatePeerState operation.
|
||||
type UpdatePeerPrm struct {
|
||||
key []byte
|
||||
state netmap.NodeState
|
||||
key []byte
|
||||
|
||||
online bool
|
||||
|
||||
client.InvokePrmOptional
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ func (u *UpdatePeerPrm) SetKey(key []byte) {
|
|||
}
|
||||
|
||||
// SetState sets node state.
|
||||
func (u *UpdatePeerPrm) SetState(state netmap.NodeState) {
|
||||
u.state = state
|
||||
func (u *UpdatePeerPrm) SetOnline() {
|
||||
u.online = true
|
||||
}
|
||||
|
||||
// UpdatePeerState changes peer status through Netmap contract call.
|
||||
|
@ -36,9 +36,14 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) error {
|
|||
method += "IR"
|
||||
}
|
||||
|
||||
state := 2
|
||||
if p.online {
|
||||
state = 1
|
||||
}
|
||||
|
||||
prm := client.InvokePrm{}
|
||||
prm.SetMethod(method)
|
||||
prm.SetArgs(int64(p.state.ToV2()), p.key)
|
||||
prm.SetArgs(int64(state), p.key)
|
||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
||||
|
||||
if err := c.client.Invoke(prm); err != nil {
|
||||
|
|
|
@ -10,12 +10,12 @@ import (
|
|||
v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
)
|
||||
|
||||
type UpdatePeer struct {
|
||||
publicKey *keys.PublicKey
|
||||
status netmap.NodeState
|
||||
|
||||
online bool
|
||||
|
||||
// For notary notifications only.
|
||||
// Contains raw transactions of notary request.
|
||||
|
@ -25,8 +25,8 @@ type UpdatePeer struct {
|
|||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (UpdatePeer) MorphEvent() {}
|
||||
|
||||
func (s UpdatePeer) Status() netmap.NodeState {
|
||||
return s.status
|
||||
func (s UpdatePeer) Online() bool {
|
||||
return s.online
|
||||
}
|
||||
|
||||
func (s UpdatePeer) PublicKey() *keys.PublicKey {
|
||||
|
@ -73,7 +73,13 @@ func ParseUpdatePeer(e *subscriptions.NotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get node status: %w", err)
|
||||
}
|
||||
|
||||
ev.status = netmap.NodeStateFromV2(v2netmap.NodeState(st))
|
||||
switch v2netmap.NodeState(st) {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported node state %d", st)
|
||||
case v2netmap.Offline:
|
||||
case v2netmap.Online:
|
||||
ev.online = true
|
||||
}
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -7,9 +7,8 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
netmapv2 "github.com/nspcc-dev/neofs-api-go/v2/netmap"
|
||||
v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
)
|
||||
|
||||
var errNilPubKey = errors.New("could not parse public key: public key is nil")
|
||||
|
@ -27,10 +26,6 @@ func (s *UpdatePeer) setPublicKey(v []byte) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *UpdatePeer) setStatus(v uint32) {
|
||||
s.status = netmap.NodeStateFromV2(netmapv2.NodeState(v))
|
||||
}
|
||||
|
||||
const (
|
||||
// UpdateStateNotaryEvent is method name for netmap state updating
|
||||
// operations in `Netmap` contract. Is used as identificator for
|
||||
|
@ -66,7 +61,13 @@ func ParseUpdatePeerNotary(ne event.NotaryEvent) (event.Event, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ev.setStatus(uint32(state))
|
||||
switch v2netmap.NodeState(state) {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported node state %d", err)
|
||||
case v2netmap.Offline:
|
||||
case v2netmap.Online:
|
||||
ev.online = true
|
||||
}
|
||||
|
||||
fieldNum++
|
||||
case fieldNum == expectedItemNumUpdatePeer:
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -15,10 +14,7 @@ func TestParseUpdatePeer(t *testing.T) {
|
|||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
var (
|
||||
publicKey = priv.PublicKey()
|
||||
state = netmap.NodeStateOffline
|
||||
)
|
||||
publicKey := priv.PublicKey()
|
||||
|
||||
t.Run("wrong number of parameters", func(t *testing.T) {
|
||||
prms := []stackitem.Item{
|
||||
|
@ -48,14 +44,14 @@ func TestParseUpdatePeer(t *testing.T) {
|
|||
|
||||
t.Run("correct behavior", func(t *testing.T) {
|
||||
ev, err := ParseUpdatePeer(createNotifyEventFromItems([]stackitem.Item{
|
||||
stackitem.NewBigInteger(new(big.Int).SetInt64(int64(state.ToV2()))),
|
||||
stackitem.NewBigInteger(new(big.Int).SetInt64(1)),
|
||||
stackitem.NewByteArray(publicKey.Bytes()),
|
||||
}))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, UpdatePeer{
|
||||
publicKey: publicKey,
|
||||
status: state,
|
||||
online: true,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue