From 9dc741d43e24bd0415beb70d177a0a6e87ba2d5e Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 31 May 2021 20:22:43 +0300 Subject: [PATCH] [#556] morph/neofs: Implement contract client Implement NeoFS contact's client which is responsible for collecting call arguments and parsing stack items. Initially key binding and unbinding are supported. Signed-off-by: Leonard Lyubich --- pkg/morph/client/neofs/bind.go | 63 ++++++++++++++++++++++ pkg/morph/client/neofs/client.go | 92 ++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 pkg/morph/client/neofs/bind.go create mode 100644 pkg/morph/client/neofs/client.go diff --git a/pkg/morph/client/neofs/bind.go b/pkg/morph/client/neofs/bind.go new file mode 100644 index 000000000..646e4ce6b --- /dev/null +++ b/pkg/morph/client/neofs/bind.go @@ -0,0 +1,63 @@ +package neofscontract + +import ( + "fmt" +) + +// BindKeysArgs groups the arguments +// of key binding call. +type BindKeysArgs struct { + commonBindArgs +} + +// UnbindKeysArgs groups the arguments +// of key unbinding call. +type UnbindKeysArgs struct { + commonBindArgs +} + +type commonBindArgs struct { + scriptHash []byte // script hash of account identifier + + keys [][]byte // list of serialized public keys +} + +// SetScriptHash sets script hash of the NeoFS account identifier. +func (x *commonBindArgs) SetScriptHash(v []byte) { + x.scriptHash = v +} + +// SetKeys sets list of public keys in a binary format. +func (x *commonBindArgs) SetKeys(v [][]byte) { + x.keys = v +} + +// BindKeys invokes the call of key binding method +// of NeoFS contract. +func (x *Client) BindKeys(args BindKeysArgs) error { + err := x.client.Invoke( + x.bindKeysMethod, + args.scriptHash, + args.keys, + ) + if err != nil { + return fmt.Errorf("could not invoke method (%s): %w", x.bindKeysMethod, err) + } + + return nil +} + +// UnbindKeys invokes the call of key unbinding method +// of NeoFS contract. +func (x *Client) UnbindKeys(args UnbindKeysArgs) error { + err := x.client.Invoke( + x.unbindKeysMethod, + args.scriptHash, + args.keys, + ) + if err != nil { + return fmt.Errorf("could not invoke method (%s): %w", x.unbindKeysMethod, err) + } + + return nil +} diff --git a/pkg/morph/client/neofs/client.go b/pkg/morph/client/neofs/client.go new file mode 100644 index 000000000..60b7aea8f --- /dev/null +++ b/pkg/morph/client/neofs/client.go @@ -0,0 +1,92 @@ +package neofscontract + +import ( + "github.com/nspcc-dev/neofs-node/pkg/morph/client" +) + +// Client is a wrapper over StaticClient +// which makes calls with the names and arguments +// of the NeoFS 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 NeoFS contract client + + *cfg // contract method names +} + +// Option is a client configuration change function. +type Option func(*cfg) + +type cfg struct { + bindKeysMethod, + unbindKeysMethod string +} + +func defaultConfig() *cfg { + const ( + defaultBindKeysMethod = "bind" + defaultUnbindKeysMethod = "unbind" + ) + + return &cfg{ + bindKeysMethod: defaultBindKeysMethod, + unbindKeysMethod: defaultUnbindKeysMethod, + } +} + +// New creates, initializes and returns the Client instance. +// +// If StaticClient is nil, panic occurs. +// +// Other values are set according to provided options, or by default: +// * key binding method name: bind; +// * key unbinding method name: unbind; +// +// If desired option satisfies the default value, it can be omitted. +// If multiple options of the same config value are supplied, +// the option with the highest index in the arguments will be used. +func New(c *client.StaticClient, opts ...Option) *Client { + if c == nil { + panic("static client is nil") + } + + res := &Client{ + client: c, + cfg: defaultConfig(), // build default configuration + } + + // apply options + for _, opt := range opts { + opt(res.cfg) + } + + return res +} + +// WithBindKeysMethod returns a client constructor option that +// specifies the method name of key binding operation. +// +// Ignores empty value. +func WithBindKeysMethod(n string) Option { + return func(c *cfg) { + if n != "" { + c.bindKeysMethod = n + } + } +} + +// WithUnbindKeysMethod returns a client constructor option that +// specifies the method name of key unbinding operation. +// +// Ignores empty value. +func WithUnbindKeysMethod(n string) Option { + return func(c *cfg) { + if n != "" { + c.unbindKeysMethod = n + } + } +}