diff --git a/pkg/morph/client/netmap/client.go b/pkg/morph/client/netmap/client.go index dd89985f6..0c54f4bb4 100644 --- a/pkg/morph/client/netmap/client.go +++ b/pkg/morph/client/netmap/client.go @@ -35,6 +35,7 @@ type cfg struct { newEpochMethod, // new epoch method name for invocation netMapMethod, // get network map method name snapshotMethod, // get network map snapshot method name + epochSnapshotMethod, // get network map snapshot by epoch method name updateStateMethod, // update state method name for invocation innerRingListMethod, // IR list method name for invocation epochMethod, // get epoch number method name @@ -50,6 +51,8 @@ const ( defaultInnerRIngListMethod = "innerRingList" // default IR list method name defaultEpochMethod = "epoch" // default get epoch number method name defaultConfigMethod = "config" // default get config value method name + + defaultEpochSnapshotMethod = "snapshotByEpoch" // default get network map snapshot by epoch method name ) func defaultConfig() *cfg { @@ -58,6 +61,7 @@ func defaultConfig() *cfg { newEpochMethod: defaultNewEpochMethod, netMapMethod: defaultNetMapMethod, snapshotMethod: defaultSnapshotMethod, + epochSnapshotMethod: defaultEpochSnapshotMethod, updateStateMethod: defaultUpdateStateMethod, innerRingListMethod: defaultInnerRIngListMethod, epochMethod: defaultEpochMethod, @@ -194,3 +198,17 @@ func WithConfigMethod(n string) Option { } } } + +// WithEpochSnapshotMethod returns a client constructor option that +// specifies the method name of snapshot by value receiving operation. +// +// Ignores empty value. +// +// If option not provided, "snapshotByValue" is used. +func WithEpochSnapshotMethod(n string) Option { + return func(c *cfg) { + if n != "" { + c.epochSnapshotMethod = n + } + } +} diff --git a/pkg/morph/client/netmap/netmap.go b/pkg/morph/client/netmap/netmap.go index 86f86c2ad..043e33dd1 100644 --- a/pkg/morph/client/netmap/netmap.go +++ b/pkg/morph/client/netmap/netmap.go @@ -23,6 +23,18 @@ type GetNetMapValues struct { peers [][]byte } +// EpochSnapshotArgs groups the arguments +// of snapshot by epoch test invoke call. +type EpochSnapshotArgs struct { + epoch uint64 +} + +// EpochSnapshotValues groups the stack parameters +// returned by snapshot by epoch test invoke. +type EpochSnapshotValues struct { + *GetNetMapValues +} + const nodeInfoFixedPrmNumber = 1 // SetDiff sets argument for snapshot method of @@ -31,6 +43,11 @@ func (g *GetSnapshotArgs) SetDiff(d uint64) { g.diff = d } +// SetEpoch sets epoch number to get snapshot. +func (a *EpochSnapshotArgs) SetEpoch(d uint64) { + a.epoch = d +} + // Peers return the list of peers from // network map in a binary format. func (g GetNetMapValues) Peers() [][]byte { @@ -69,6 +86,29 @@ func (c *Client) Snapshot(a GetSnapshotArgs) (*GetNetMapValues, error) { return peersFromStackItems(prms, c.snapshotMethod) } +// EpochSnapshot performs the test invoke of get snapshot of network map by epoch +// from NeoFS Netmap contract. +func (c *Client) EpochSnapshot(args EpochSnapshotArgs) (*EpochSnapshotValues, error) { + prms, err := c.client.TestInvoke( + c.epochSnapshotMethod, + int64(args.epoch), + ) + if err != nil { + return nil, errors.Wrapf(err, + "could not perform test invocation (%s)", + c.epochSnapshotMethod) + } + + nmVals, err := peersFromStackItems(prms, c.epochSnapshotMethod) + if err != nil { + return nil, err + } + + return &EpochSnapshotValues{ + GetNetMapValues: nmVals, + }, nil +} + func peersFromStackItems(stack []stackitem.Item, method string) (*GetNetMapValues, error) { if ln := len(stack); ln != 1 { return nil, errors.Errorf("unexpected stack item count (%s): %d", diff --git a/pkg/morph/client/netmap/wrapper/netmap.go b/pkg/morph/client/netmap/wrapper/netmap.go index 9d3a06a6a..fb96a64ae 100644 --- a/pkg/morph/client/netmap/wrapper/netmap.go +++ b/pkg/morph/client/netmap/wrapper/netmap.go @@ -14,12 +14,30 @@ func (w Wrapper) GetNetMap(diff uint64) (*netmap.Netmap, error) { args := client.GetSnapshotArgs{} args.SetDiff(diff) - peers, err := w.client.Snapshot(args) + vals, err := w.client.Snapshot(args) if err != nil { return nil, err } - rawPeers := peers.Peers() // slice of serialized node infos + return unmarshalNetmap(vals.Peers()) +} + +// 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 (w Wrapper) GetNetMapByEpoch(epoch uint64) (*netmap.Netmap, error) { + args := client.EpochSnapshotArgs{} + args.SetEpoch(epoch) + + vals, err := w.client.EpochSnapshot(args) + if err != nil { + return nil, err + } + + return unmarshalNetmap(vals.Peers()) +} + +func unmarshalNetmap(rawPeers [][]byte) (*netmap.Netmap, error) { infos := make([]netmap.NodeInfo, 0, len(rawPeers)) for _, peer := range rawPeers {