frostfs-node/pkg/innerring/invoke/netmap.go

160 lines
3.7 KiB
Go

package invoke
import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap/grpc"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
)
type (
UpdatePeerArgs struct {
Key *keys.PublicKey
Status uint32
}
SetConfigArgs struct {
Key []byte
Value []byte
}
)
const (
getEpochMethod = "epoch"
setNewEpochMethod = "newEpoch"
approvePeerMethod = "addPeer"
updatePeerStateMethod = "updateState"
setConfigMethod = "setConfigMethod"
updateInnerRingMethod = "updateInnerRingMethod"
getNetmapSnapshotMethod = "netmap"
)
// Epoch return epoch value from contract.
func Epoch(cli *client.Client, con util.Uint160) (int64, error) {
if cli == nil {
return 0, client.ErrNilClient
}
val, err := cli.TestInvoke(con, getEpochMethod)
if err != nil {
return 0, err
}
epoch, err := client.IntFromStackItem(val[0])
if err != nil {
return 0, err
}
return epoch, nil
}
// SetNewEpoch invokes newEpoch method.
func SetNewEpoch(cli *client.Client, con util.Uint160, epoch uint64) error {
if cli == nil {
return client.ErrNilClient
}
return cli.Invoke(con, feeOneGas, setNewEpochMethod, int64(epoch))
}
// ApprovePeer invokes addPeer method.
func ApprovePeer(cli *client.Client, con util.Uint160, peer []byte) error {
if cli == nil {
return client.ErrNilClient
}
return cli.Invoke(con, feeHalfGas, approvePeerMethod, peer)
}
// UpdatePeerState invokes addPeer method.
func UpdatePeerState(cli *client.Client, con util.Uint160, args *UpdatePeerArgs) error {
if cli == nil {
return client.ErrNilClient
}
return cli.Invoke(con, extraFee, updatePeerStateMethod,
int64(args.Status),
args.Key.Bytes(),
)
}
// SetConfig invokes setConfig method.
func SetConfig(cli *client.Client, con util.Uint160, args *SetConfigArgs) error {
if cli == nil {
return client.ErrNilClient
}
return cli.Invoke(con, extraFee, setConfigMethod,
args.Key,
args.Value,
)
}
// UpdateInnerRing invokes updateInnerRing method.
func UpdateInnerRing(cli *client.Client, con util.Uint160, list []*keys.PublicKey) error {
if cli == nil {
return client.ErrNilClient
}
rawKeys := make([][]byte, 0, len(list))
for i := range list {
rawKeys = append(rawKeys, list[i].Bytes())
}
return cli.Invoke(con, extraFee, updateInnerRingMethod, rawKeys)
}
// NetmapSnapshot returns current netmap node infos.
func NetmapSnapshot(cli *client.Client, con util.Uint160) ([]netmap.NodeInfo, error) {
if cli == nil {
return nil, client.ErrNilClient
}
rawNetmapStack, err := cli.TestInvoke(con, getNetmapSnapshotMethod)
if err != nil {
return nil, err
}
if ln := len(rawNetmapStack); ln != 1 {
return nil, errors.New("invalid RPC response")
}
rawNodeInfos, err := client.ArrayFromStackItem(rawNetmapStack[0])
if err != nil {
return nil, err
}
result := make([]netmap.NodeInfo, 0, len(rawNodeInfos))
for i := range rawNodeInfos {
nodeInfo, err := peerInfoFromStackItem(rawNodeInfos[i])
if err != nil {
return nil, errors.Wrap(err, "invalid RPC response")
}
result = append(result, *nodeInfo)
}
return result, nil
}
func peerInfoFromStackItem(prm stackitem.Item) (*netmap.NodeInfo, error) {
node := new(netmap.NodeInfo)
subItems, err := client.ArrayFromStackItem(prm)
if err != nil {
return nil, err
} else if ln := len(subItems); ln != 1 {
return nil, errors.New("invalid RPC response")
} else if rawNodeInfo, err := client.BytesFromStackItem(subItems[0]); err != nil {
return nil, err
} else if err = proto.Unmarshal(rawNodeInfo, node); err != nil {
return nil, err
}
return node, nil
}