[#625] client/container: remove intermediate wrapper

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2022-01-31 16:34:01 +03:00 committed by Alex Vanin
parent 819d80a7a9
commit c34cfa1f35
28 changed files with 556 additions and 1168 deletions

View file

@ -7,7 +7,7 @@ import (
lru "github.com/hashicorp/golang-lru"
"github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/core/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
containerSDK "github.com/nspcc-dev/neofs-sdk-go/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
@ -262,7 +262,7 @@ func (s *lruNetmapSource) Epoch() (uint64, error) {
// that implements container lister.
type ttlContainerLister ttlNetCache
func newCachedContainerLister(w *wrapper.Wrapper) *ttlContainerLister {
func newCachedContainerLister(c *cntClient.Client) *ttlContainerLister {
const (
containerListerCacheSize = 100
containerListerCacheTTL = 30 * time.Second
@ -283,7 +283,7 @@ func newCachedContainerLister(w *wrapper.Wrapper) *ttlContainerLister {
}
}
return w.List(id)
return c.List(id)
})
return (*ttlContainerLister)(lruCnrListerCache)

View file

@ -14,7 +14,7 @@ import (
containerCore "github.com/nspcc-dev/neofs-node/pkg/core/container"
netmapCore "github.com/nspcc-dev/neofs-node/pkg/core/netmap"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
containerEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
containerTransportGRPC "github.com/nspcc-dev/neofs-node/pkg/network/transport/container/grpc"
@ -43,15 +43,15 @@ const (
func initContainerService(c *cfg) {
// container wrapper that tries to invoke notary
// requests if chain is configured so
wrap, err := wrapper.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, wrapper.TryNotary())
wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, cntClient.TryNotary())
fatalOnErr(err)
// container wrapper that always sends non-notary
// requests
wrapperNoNotary, err := wrapper.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0)
wrapperNoNotary, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0)
fatalOnErr(err)
cnrSrc := wrapper.AsContainerSource(wrap)
cnrSrc := cntClient.AsContainerSource(wrap)
eACLFetcher := &morphEACLFetcher{
w: wrap,
@ -209,7 +209,7 @@ func setContainerNotificationParser(c *cfg, sTyp string, p event.NotificationPar
type morphLoadWriter struct {
log *logger.Logger
cnrMorphClient *wrapper.Wrapper
cnrMorphClient *cntClient.Client
key []byte
}
@ -221,7 +221,7 @@ func (w *morphLoadWriter) Put(a containerSDK.UsedSpaceAnnouncement) error {
zap.Uint64("size", a.UsedSpace()),
)
prm := wrapper.AnnounceLoadPrm{}
prm := cntClient.AnnounceLoadPrm{}
prm.SetAnnouncement(a)
prm.SetReporter(w.key)
@ -561,7 +561,7 @@ func (x *morphContainerReader) List(id *owner.ID) ([]*cid.ID, error) {
}
type morphContainerWriter struct {
neoClient *wrapper.Wrapper
neoClient *cntClient.Client
cacheEnabled bool
containers *ttlContainerStorage
@ -570,7 +570,7 @@ type morphContainerWriter struct {
}
func (m morphContainerWriter) Put(cnr *containerSDK.Container) (*cid.ID, error) {
containerID, err := wrapper.Put(m.neoClient, cnr)
containerID, err := cntClient.Put(m.neoClient, cnr)
if err != nil {
return nil, err
}
@ -583,7 +583,7 @@ func (m morphContainerWriter) Put(cnr *containerSDK.Container) (*cid.ID, error)
}
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
err := wrapper.Delete(m.neoClient, witness)
err := cntClient.Delete(m.neoClient, witness)
if err != nil {
return err
}
@ -602,7 +602,7 @@ func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error
}
func (m morphContainerWriter) PutEACL(table *eaclSDK.Table) error {
err := wrapper.PutEACL(m.neoClient, table)
err := cntClient.PutEACL(m.neoClient, table)
if err != nil {
return err
}

View file

@ -14,7 +14,7 @@ import (
objectCore "github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
cntrwrp "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
nmClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap"
objectTransportGRPC "github.com/nspcc-dev/neofs-node/pkg/network/transport/object/grpc"
objectService "github.com/nspcc-dev/neofs-node/pkg/services/object"
@ -384,7 +384,7 @@ func initObjectService(c *cfg) {
}
type morphEACLFetcher struct {
w *cntrwrp.Wrapper
w *cntClient.Client
}
type signedEACLTable eaclSDK.Table

View file

@ -7,7 +7,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/alphabet"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement"
timerEvent "github.com/nspcc-dev/neofs-node/pkg/innerring/timers"
container "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/nspcc-dev/neofs-node/pkg/morph/timer"
"go.uber.org/zap"
@ -32,8 +32,8 @@ type (
newEpochHandlers []newEpochHandler
cnrWrapper *container.Wrapper // to invoke stop container estimation
epoch epochState // to specify which epoch to stop, and epoch duration
cnrWrapper *container.Client // to invoke stop container estimation
epoch epochState // to specify which epoch to stop, and epoch duration
stopEstimationDMul uint32 // X: X/Y of epoch in blocks
stopEstimationDDiv uint32 // Y: X/Y of epoch in blocks

View file

@ -31,7 +31,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
auditClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/audit"
balanceClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/balance"
cntWrapper "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
neofsClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/neofs"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/neofsid"
nmClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap"
@ -469,21 +469,21 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
}
// form morph container client's options
morphCnrOpts := make([]cntWrapper.Option, 0, 3)
morphCnrOpts := make([]cntClient.Option, 0, 3)
morphCnrOpts = append(morphCnrOpts,
cntWrapper.TryNotary(),
cntWrapper.AsAlphabet(),
cntClient.TryNotary(),
cntClient.AsAlphabet(),
)
if server.sideNotaryConfig.disabled {
// in non-notary environments we customize fee for named container registration
// because it takes much more additional GAS than other operations.
morphCnrOpts = append(morphCnrOpts,
cntWrapper.WithCustomFeeForNamedPut(server.feeConfig.NamedContainerRegistrationFee()),
cntClient.WithCustomFeeForNamedPut(server.feeConfig.NamedContainerRegistrationFee()),
)
}
cnrClient, err := cntWrapper.NewFromMorph(server.morphClient, server.contracts.container, fee, morphCnrOpts...)
cnrClient, err := cntClient.NewFromMorph(server.morphClient, server.contracts.container, fee, morphCnrOpts...)
if err != nil {
return nil, err
}
@ -602,7 +602,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
settlementDeps := &settlementDeps{
globalConfig: globalConfig,
log: server.log,
cnrSrc: cntWrapper.AsContainerSource(cnrClient),
cnrSrc: cntClient.AsContainerSource(cnrClient),
auditClient: server.auditClient,
nmSrc: server.netmapClient,
clientCache: clientCache,

View file

@ -5,7 +5,7 @@ import (
"encoding/hex"
clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/services/audit"
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
@ -47,7 +47,7 @@ func (ap *Processor) processStartAudit(epoch uint64) {
auditCtx, ap.prevAuditCanceler = context.WithCancel(context.Background())
for i := range containers {
cnr, err := wrapper.Get(ap.containerClient, containers[i]) // get container structure
cnr, err := cntClient.Get(ap.containerClient, containers[i]) // get container structure
if err != nil {
log.Error("can't get container info, ignore",
zap.Stringer("cid", containers[i]),

View file

@ -8,7 +8,7 @@ import (
"time"
"github.com/nspcc-dev/neofs-node/pkg/core/client"
wrapContainer "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
nmClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/nspcc-dev/neofs-node/pkg/services/audit"
@ -41,7 +41,7 @@ type (
sgSrc SGSource
searchTimeout time.Duration
containerClient *wrapContainer.Wrapper
containerClient *cntClient.Client
netmapClient *nmClient.Client
taskManager TaskManager
@ -53,7 +53,7 @@ type (
Params struct {
Log *zap.Logger
NetmapClient *nmClient.Client
ContainerClient *wrapContainer.Wrapper
ContainerClient *cntClient.Client
IRList Indexer
SGSource SGSource
RPCSearchTimeout time.Duration

View file

@ -10,7 +10,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/neofsid"
morphsubnet "github.com/nspcc-dev/neofs-node/pkg/morph/client/subnet"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
@ -130,7 +130,7 @@ func (cp *Processor) approvePutContainer(ctx *putContainerContext) {
var err error
prm := wrapper.PutPrm{}
prm := cntClient.PutPrm{}
prm.SetContainer(e.Container())
prm.SetKey(e.PublicKey())
@ -243,7 +243,7 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
func (cp *Processor) approveDeleteContainer(e *containerEvent.Delete) {
var err error
prm := wrapper.DeletePrm{}
prm := cntClient.DeletePrm{}
prm.SetCID(e.ContainerID())
prm.SetSignature(e.Signature())

View file

@ -7,7 +7,7 @@ import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/session"
@ -57,7 +57,7 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error {
}
// receive owner of the related container
cnr, err := wrapper.Get(cp.cnrClient, table.CID())
cnr, err := cntClient.Get(cp.cnrClient, table.CID())
if err != nil {
return fmt.Errorf("could not receive the container: %w", err)
}
@ -91,7 +91,7 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error {
func (cp *Processor) approveSetEACL(e container.SetEACL) {
var err error
prm := wrapper.PutEACLPrm{}
prm := cntClient.PutEACLPrm{}
prm.SetTable(e.Table())
prm.SetKey(e.PublicKey())

View file

@ -5,7 +5,7 @@ import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/neofsid"
morphsubnet "github.com/nspcc-dev/neofs-node/pkg/morph/client/subnet"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
@ -25,7 +25,7 @@ type (
log *zap.Logger
pool *ants.Pool
alphabetState AlphabetState
cnrClient *wrapper.Wrapper // notary must be enabled
cnrClient *container.Client // notary must be enabled
idClient *neofsid.Client
subnetClient *morphsubnet.Client
netState NetworkState
@ -37,7 +37,7 @@ type (
Log *zap.Logger
PoolSize int
AlphabetState AlphabetState
ContainerClient *wrapper.Wrapper
ContainerClient *container.Client
NeoFSIDClient *neofsid.Client
SubnetClient *morphsubnet.Client
NetworkState NetworkState

View file

@ -4,7 +4,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/audit"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/governance"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap"
"go.uber.org/zap"
)
@ -37,7 +37,7 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) {
return
}
prm := wrapper.StartEstimationPrm{}
prm := cntClient.StartEstimationPrm{}
prm.SetEpoch(epoch - 1)
prm.SetHash(ev.TxHash())

View file

@ -6,7 +6,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
"github.com/nspcc-dev/neo-go/pkg/util"
container "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
nmClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap"
@ -60,7 +60,7 @@ type (
alphabetState AlphabetState
netmapClient *nmClient.Client
containerWrp *container.Wrapper
containerWrp *container.Client
subnetContract util.Uint160
@ -86,7 +86,7 @@ type (
AlphabetState AlphabetState
CleanupEnabled bool
CleanupThreshold uint64 // in epochs
ContainerWrapper *container.Wrapper
ContainerWrapper *container.Client
SubnetContract *util.Uint160
HandleAudit event.Handler

View file

@ -4,7 +4,7 @@ import (
"math/big"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement/common"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
cntClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"go.uber.org/zap"
)
@ -76,7 +76,7 @@ func (inc *IncomeSettlementContext) Collect() {
// avgEstimation returns estimation value for single container. Right now it
// simply calculates average of all announcements, however it can be smarter and
// base result on reputation of announcers and clever math.
func (inc *IncomeSettlementContext) avgEstimation(e *wrapper.Estimations) (avg uint64) {
func (inc *IncomeSettlementContext) avgEstimation(e *cntClient.Estimations) (avg uint64) {
if len(e.Values) == 0 {
return 0
}

View file

@ -7,14 +7,14 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement/common"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"go.uber.org/zap"
)
type (
EstimationFetcher interface {
Estimations(uint64) ([]*wrapper.Estimations, error)
Estimations(uint64) ([]*container.Estimations, error)
}
RateFetcher interface {

View file

@ -16,7 +16,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement/common"
auditClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/audit"
balanceClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/balance"
containerClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
containerClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
auditAPI "github.com/nspcc-dev/neofs-sdk-go/audit"
containerAPI "github.com/nspcc-dev/neofs-sdk-go/container"
@ -55,7 +55,7 @@ type auditSettlementDeps struct {
type basicIncomeSettlementDeps struct {
*settlementDeps
cnrClient *containerClient.Wrapper
cnrClient *containerClient.Client
}
type basicSettlementConstructor struct {

View file

@ -1,6 +1,11 @@
package container
import (
"errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
)
@ -31,16 +36,86 @@ const (
listSizesMethod = "listContainerSizes"
getSizeMethod = "getContainerSize"
// PutNamedMethod is method name for container put with an alias. It is exported to provide custom fee.
PutNamedMethod = "putNamed"
// putNamedMethod is method name for container put with an alias. It is exported to provide custom fee.
putNamedMethod = "putNamed"
)
// New creates, initializes and returns the Client instance.
func New(c *client.StaticClient) *Client {
return &Client{client: c}
var (
errNilArgument = errors.New("empty argument")
errUnsupported = errors.New("unsupported structure version")
)
// NewFromMorph returns the wrapper instance from the raw morph client.
//
// Specified fee is used for all operations by default. If WithCustomFeeForNamedPut is provided,
// the customized fee is used for Put operations with named containers.
func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts ...Option) (*Client, error) {
o := defaultOpts()
for i := range opts {
opts[i](o)
}
if o.feePutNamedSet {
o.staticOpts = append(o.staticOpts, client.WithCustomFee(putNamedMethod, o.feePutNamed))
}
sc, err := client.NewStatic(cli, contract, fee, o.staticOpts...)
if err != nil {
return nil, fmt.Errorf("can't create container static client: %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 Wrapper.
type Option func(*opts)
type opts struct {
feePutNamedSet bool
feePutNamed fixedn.Fixed8
staticOpts []client.StaticClientOption
}
func defaultOpts() *opts {
return new(opts)
}
// TryNotary returns option to enable
// notary invocation tries.
func TryNotary() Option {
return func(o *opts) {
o.staticOpts = append(o.staticOpts, 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.staticOpts = append(o.staticOpts, client.AsAlphabet())
}
}
// WithCustomFeeForNamedPut returns option to specify custom fee for each Put operation with named container.
func WithCustomFeeForNamedPut(fee fixedn.Fixed8) Option {
return func(o *opts) {
o.feePutNamed = fee
o.feePutNamedSet = true
}
}

View file

@ -3,51 +3,75 @@ package container
import (
"fmt"
core "github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
)
// DeleteArgs groups the arguments
// of delete container invocation call.
type DeleteArgs struct {
cid []byte // container identifier
// Delete marshals container ID, and passes it to Wrapper's Delete method
// along with signature and session token.
//
// Returns error if container ID is nil.
func Delete(c *Client, witness core.RemovalWitness) error {
id := witness.ContainerID()
if id == nil {
return errNilArgument
}
sig []byte // container identifier signature
binToken, err := witness.SessionToken().Marshal()
if err != nil {
return fmt.Errorf("could not marshal session token: %w", err)
}
token []byte // binary session token
return c.Delete(
DeletePrm{
cid: id.ToV2().GetValue(),
signature: witness.Signature(),
token: binToken,
})
}
// DeletePrm groups parameters of Delete client operation.
type DeletePrm struct {
cid []byte
signature []byte
token []byte
client.InvokePrmOptional
}
// SetCID sets the container identifier
// in a binary format.
func (p *DeleteArgs) SetCID(v []byte) {
p.cid = v
// SetCID sets container ID.
func (d *DeletePrm) SetCID(cid []byte) {
d.cid = cid
}
// SetSignature sets the container identifier
// owner's signature.
func (p *DeleteArgs) SetSignature(v []byte) {
p.sig = v
// SetSignature sets signature.
func (d *DeletePrm) SetSignature(signature []byte) {
d.signature = signature
}
// SetSessionToken sets token of the session
// within which the container was removed
// in a NeoFS API binary format.
func (p *DeleteArgs) SetSessionToken(v []byte) {
p.token = v
// SetToken sets session token.
func (d *DeletePrm) SetToken(token []byte) {
d.token = token
}
// Delete invokes the call of delete container
// method of NeoFS Container contract.
func (c *Client) Delete(args DeleteArgs) error {
// Delete removes the container from NeoFS system
// through Container contract call.
//
// Returns any error encountered that caused
// the removal to interrupt.
//
// If TryNotary is provided, calls notary contract.
func (c *Client) Delete(p DeletePrm) error {
if len(p.signature) == 0 {
return errNilArgument
}
prm := client.InvokePrm{}
prm.SetMethod(deleteMethod)
prm.SetArgs(args.cid, args.sig, args.token)
prm.InvokePrmOptional = args.InvokePrmOptional
prm.SetArgs(p.cid, p.signature, p.token)
prm.InvokePrmOptional = p.InvokePrmOptional
err := c.client.Invoke(prm)
if err != nil {
return fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err)
}

View file

@ -3,64 +3,31 @@ package container
import (
"fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/signature"
)
// EACLArgs groups the arguments
// of get eACL test invoke call.
type EACLArgs struct {
cid []byte // container identifier
}
// GetEACL reads the extended ACL table from NeoFS system
// through Container contract call.
func (c *Client) GetEACL(cid *cid.ID) (*eacl.Table, error) {
if cid == nil {
return nil, errNilArgument
}
// EACLValues groups the stack parameters
// returned by get eACL test invoke.
type EACLValues struct {
eacl []byte // extended ACL table
v2 := cid.ToV2()
if v2 == nil {
return nil, errUnsupported // use other major version if there any
}
signature []byte // RFC-6979 signature of extended ACL table
prm := client.TestInvokePrm{}
prm.SetMethod(eaclMethod)
prm.SetArgs(v2.GetValue())
publicKey []byte // public key of the extended ACL table signer
token []byte // token of the session within which the eACL table was set
}
// SetCID sets the container identifier
// in a binary format.
func (g *EACLArgs) SetCID(v []byte) {
g.cid = v
}
// EACL returns the eACL table
// in a binary format.
func (g *EACLValues) EACL() []byte {
return g.eacl
}
// Signature returns RFC-6979 signature of extended ACL table.
func (g *EACLValues) Signature() []byte {
return g.signature
}
// PublicKey of the signature.
func (g *EACLValues) PublicKey() []byte {
return g.publicKey
}
// SessionToken returns token of the session within which
// the eACl table was set in a NeoFS API binary format.
func (g *EACLValues) SessionToken() []byte {
return g.token
}
// EACL performs the test invoke of get eACL
// method of NeoFS Container contract.
func (c *Client) EACL(args EACLArgs) (*EACLValues, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(eaclMethod)
invokePrm.SetArgs(args.cid)
prms, err := c.client.TestInvoke(invokePrm)
prms, err := c.client.TestInvoke(prm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", eaclMethod, err)
} else if ln := len(prms); ln != 1 {
@ -76,7 +43,7 @@ func (c *Client) EACL(args EACLArgs) (*EACLValues, error) {
return nil, fmt.Errorf("unexpected eacl stack item count (%s): %d", eaclMethod, len(arr))
}
eacl, err := client.BytesFromStackItem(arr[0])
rawEACL, err := client.BytesFromStackItem(arr[0])
if err != nil {
return nil, fmt.Errorf("could not get byte array of eACL (%s): %w", eaclMethod, err)
}
@ -86,20 +53,45 @@ func (c *Client) EACL(args EACLArgs) (*EACLValues, error) {
return nil, fmt.Errorf("could not get byte array of eACL signature (%s): %w", eaclMethod, err)
}
// Client may not return errors if the table is missing, so check this case additionally.
// The absence of a signature in the response can be taken as an eACL absence criterion,
// since unsigned table cannot be approved in the storage by design.
if len(sig) == 0 {
return nil, container.ErrEACLNotFound
}
pub, err := client.BytesFromStackItem(arr[2])
if err != nil {
return nil, fmt.Errorf("could not get byte array of eACL public key (%s): %w", eaclMethod, err)
}
tok, err := client.BytesFromStackItem(arr[3])
binToken, err := client.BytesFromStackItem(arr[3])
if err != nil {
return nil, fmt.Errorf("could not get byte array of eACL session token (%s): %w", eaclMethod, err)
}
return &EACLValues{
eacl: eacl,
signature: sig,
publicKey: pub,
token: tok,
}, nil
table := eacl.NewTable()
if err = table.Unmarshal(rawEACL); err != nil {
// use other major version if there any
return nil, err
}
if len(binToken) > 0 {
tok := session.NewToken()
err = tok.Unmarshal(binToken)
if err != nil {
return nil, fmt.Errorf("could not unmarshal session token: %w", err)
}
table.SetSessionToken(tok)
}
tableSignature := signature.New()
tableSignature.SetKey(pub)
tableSignature.SetSign(sig)
table.SetSignature(tableSignature)
return table, nil
}

View file

@ -4,58 +4,86 @@ import (
"fmt"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
)
// SetEACLArgs groups the arguments
// of set eACL invocation call.
type SetEACLArgs struct {
eacl []byte // extended ACL table
// PutEACL marshals table, and passes it to Wrapper's PutEACLBinary method
// along with sig.Key() and sig.Sign().
//
// Returns error if table is nil.
//
// If TryNotary is provided, calls notary contract.
func PutEACL(c *Client, table *eacl.Table) error {
if table == nil {
return errNilArgument
}
sig []byte // eACL table signature
data, err := table.Marshal()
if err != nil {
return fmt.Errorf("can't marshal eacl table: %w", err)
}
pubkey []byte // binary public key
binToken, err := table.SessionToken().Marshal()
if err != nil {
return fmt.Errorf("could not marshal session token: %w", err)
}
token []byte // binary session token
sig := table.Signature()
return c.PutEACL(
PutEACLPrm{
table: data,
key: sig.Key(),
sig: sig.Sign(),
token: binToken,
})
}
// PutEACLPrm groups parameters of PutEACL operation.
type PutEACLPrm struct {
table []byte
key []byte
sig []byte
token []byte
client.InvokePrmOptional
}
// SetEACL sets the extended ACL table
// in a binary format.
func (p *SetEACLArgs) SetEACL(v []byte) {
p.eacl = v
// SetTable sets table.
func (p *PutEACLPrm) SetTable(table []byte) {
p.table = table
}
// SetSignature sets the eACL table structure
// owner's signature.
func (p *SetEACLArgs) SetSignature(v []byte) {
p.sig = v
// SetKey sets key.
func (p *PutEACLPrm) SetKey(key []byte) {
p.key = key
}
// SetPublicKey sets public key related to
// table signature.
func (p *SetEACLArgs) SetPublicKey(v []byte) {
p.pubkey = v
// SetSignature sets signature.
func (p *PutEACLPrm) SetSignature(sig []byte) {
p.sig = sig
}
// SetSessionToken sets token of the session
// within which the eACL table was set
// in a binary format.
func (p *SetEACLArgs) SetSessionToken(v []byte) {
p.token = v
// SetToken sets session token.
func (p *PutEACLPrm) SetToken(token []byte) {
p.token = token
}
// SetEACL invokes the call of set eACL method
// of NeoFS Container contract.
func (c *Client) SetEACL(args SetEACLArgs) error {
// PutEACL saves binary eACL table with its session token, key and signature
// in NeoFS system through Container contract call.
//
// Returns any error encountered that caused the saving to interrupt.
func (c *Client) PutEACL(p PutEACLPrm) error {
if len(p.sig) == 0 || len(p.key) == 0 {
return errNilArgument
}
prm := client.InvokePrm{}
prm.SetMethod(setEACLMethod)
prm.SetArgs(args.eacl, args.sig, args.pubkey, args.token)
prm.InvokePrmOptional = args.InvokePrmOptional
prm.SetArgs(p.table, p.sig, p.key, p.token)
prm.InvokePrmOptional = p.InvokePrmOptional
err := c.client.Invoke(prm)
if err != nil {
return fmt.Errorf("could not invoke method (%s): %w", setEACLMethod, err)
}

View file

@ -6,33 +6,33 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
)
// StartEstimation groups parameters of StartEstimation operation.
type StartEstimation struct {
epoch int64
// StartEstimationPrm groups parameters of StartEstimation operation.
type StartEstimationPrm struct {
commonEstimationPrm
}
// StopEstimationPrm groups parameters of StopEstimation operation.
type StopEstimationPrm struct {
commonEstimationPrm
}
type commonEstimationPrm struct {
epoch uint64
client.InvokePrmOptional
}
func (e *StartEstimation) SetEpoch(v int64) {
e.epoch = v
// SetEpoch sets epoch.
func (p *commonEstimationPrm) SetEpoch(epoch uint64) {
p.epoch = epoch
}
type StopEstimation struct {
epoch int64
client.InvokePrmOptional
}
func (e *StopEstimation) SetEpoch(v int64) {
e.epoch = v
}
func (c *Client) StartEstimation(args StartEstimation) error {
// StartEstimation votes to produce start estimation notification.
func (c *Client) StartEstimation(p StartEstimationPrm) error {
prm := client.InvokePrm{}
prm.SetMethod(startEstimationMethod)
prm.SetArgs(args.epoch)
prm.InvokePrmOptional = args.InvokePrmOptional
prm.SetArgs(int64(p.epoch))
prm.InvokePrmOptional = p.InvokePrmOptional
if err := c.client.Invoke(prm); err != nil {
return fmt.Errorf("could not invoke method (%s): %w", startEstimationMethod, err)
@ -40,12 +40,12 @@ func (c *Client) StartEstimation(args StartEstimation) error {
return nil
}
func (c *Client) StopEstimation(args StopEstimation) error {
// StopEstimation votes to produce stop estimation notification.
func (c *Client) StopEstimation(p StopEstimationPrm) error {
prm := client.InvokePrm{}
prm.SetMethod(stopEstimationMethod)
prm.SetArgs(args.epoch)
prm.InvokePrmOptional = args.InvokePrmOptional
prm.SetArgs(int64(p.epoch))
prm.InvokePrmOptional = p.InvokePrmOptional
if err := c.client.Invoke(prm); err != nil {
return fmt.Errorf("could not invoke method (%s): %w", stopEstimationMethod, err)

View file

@ -2,72 +2,63 @@ package container
import (
"fmt"
"strings"
core "github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-sdk-go/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/signature"
)
// GetArgs groups the arguments
// of get container test invoke call.
type GetArgs struct {
cid []byte // container identifier
type containerSource Client
func (x *containerSource) Get(cid *cid.ID) (*container.Container, error) {
return Get((*Client)(x), cid)
}
// GetValues groups the stack parameters
// returned by get container test invoke.
type GetValues struct {
cnr []byte // container in a binary form
signature []byte // RFC-6979 signature of container
publicKey []byte // public key of the container signer
token []byte // token of the session within which the container was created
// AsContainerSource provides container Source interface
// from Wrapper instance.
func AsContainerSource(w *Client) core.Source {
return (*containerSource)(w)
}
// SetCID sets the container identifier
// in a binary format.
func (g *GetArgs) SetCID(v []byte) {
g.cid = v
// Get marshals container ID, and passes it to Wrapper's Get method.
//
// Returns error if cid is nil.
func Get(c *Client, cid *cid.ID) (*container.Container, error) {
return c.Get(cid.ToV2().GetValue())
}
// Container returns the container
// in a binary format.
func (g *GetValues) Container() []byte {
return g.cnr
}
// Get reads the container from NeoFS system by binary identifier
// through Container contract call.
//
// If an empty slice is returned for the requested identifier,
// storage.ErrNotFound error is returned.
func (c *Client) Get(cid []byte) (*container.Container, error) {
prm := client.TestInvokePrm{}
prm.SetMethod(getMethod)
prm.SetArgs(cid)
// Signature returns RFC-6979 signature of the container.
func (g *GetValues) Signature() []byte {
return g.signature
}
// PublicKey returns public key related to signature.
func (g *GetValues) PublicKey() []byte {
return g.publicKey
}
// SessionToken returns token of the session within which
// the container was created in a NeoFS API binary format.
func (g *GetValues) SessionToken() []byte {
return g.token
}
// Get performs the test invoke of get container
// method of NeoFS Container contract.
func (c *Client) Get(args GetArgs) (*GetValues, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(getMethod)
invokePrm.SetArgs(args.cid)
prms, err := c.client.TestInvoke(invokePrm)
res, err := c.client.TestInvoke(prm)
if err != nil {
// TODO(fyrchik): reuse messages from container contract.
// Currently there are some dependency problems:
// github.com/nspcc-dev/neofs-node/pkg/innerring imports
// github.com/nspcc-dev/neofs-sdk-go/audit imports
// github.com/nspcc-dev/neofs-api-go/v2/audit: ambiguous import: found package github.com/nspcc-dev/neofs-api-go/v2/audit in multiple modules:
// github.com/nspcc-dev/neofs-api-go v1.27.1 (/home/dzeta/go/pkg/mod/github.com/nspcc-dev/neofs-api-go@v1.27.1/v2/audit)
// github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1 (/home/dzeta/go/pkg/mod/github.com/nspcc-dev/neofs-api-go/v2@v2.11.0-pre.0.20211201134523-3604d96f3fe1/audit)
if strings.Contains(err.Error(), "container does not exist") {
return nil, core.ErrNotFound
}
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getMethod, err)
} else if ln := len(prms); ln != 1 {
} else if ln := len(res); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", getMethod, ln)
}
arr, err := client.ArrayFromStackItem(prms[0])
arr, err := client.ArrayFromStackItem(res[0])
if err != nil {
return nil, fmt.Errorf("could not get item array of container (%s): %w", getMethod, err)
}
@ -81,7 +72,7 @@ func (c *Client) Get(args GetArgs) (*GetValues, error) {
return nil, fmt.Errorf("could not get byte array of container (%s): %w", getMethod, err)
}
sig, err := client.BytesFromStackItem(arr[1])
sigBytes, err := client.BytesFromStackItem(arr[1])
if err != nil {
return nil, fmt.Errorf("could not get byte array of container signature (%s): %w", getMethod, err)
}
@ -91,15 +82,32 @@ func (c *Client) Get(args GetArgs) (*GetValues, error) {
return nil, fmt.Errorf("could not get byte array of public key (%s): %w", getMethod, err)
}
tok, err := client.BytesFromStackItem(arr[3])
tokBytes, err := client.BytesFromStackItem(arr[3])
if err != nil {
return nil, fmt.Errorf("could not get byte array of session token (%s): %w", getMethod, err)
}
return &GetValues{
cnr: cnrBytes,
signature: sig,
publicKey: pub,
token: tok,
}, nil
cnr := container.New()
if err := cnr.Unmarshal(cnrBytes); err != nil {
// use other major version if there any
return nil, fmt.Errorf("can't unmarshal container: %w", err)
}
if len(tokBytes) > 0 {
tok := session.NewToken()
err = tok.Unmarshal(tokBytes)
if err != nil {
return nil, fmt.Errorf("could not unmarshal session token: %w", err)
}
cnr.SetSessionToken(tok)
}
sig := signature.New()
sig.SetKey(pub)
sig.SetSign(sigBytes)
cnr.SetSignature(sig)
return cnr, nil
}

View file

@ -3,65 +3,56 @@ package container
import (
"fmt"
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/owner"
)
// ListArgs groups the arguments
// of list containers test invoke call.
type ListArgs struct {
ownerID []byte // container owner identifier
}
// List returns a list of container identifiers belonging
// to the specified owner of NeoFS system. The list is composed
// through Container contract call.
//
// Returns the identifiers of all NeoFS containers if pointer
// to owner identifier is nil.
func (c *Client) List(ownerID *owner.ID) ([]*cid.ID, error) {
var rawID []byte
if ownerID == nil {
rawID = []byte{}
} else if v2 := ownerID.ToV2(); v2 == nil {
return nil, errUnsupported // use other major version if there any
} else {
rawID = v2.GetValue()
}
// ListValues groups the stack parameters
// returned by list containers test invoke.
type ListValues struct {
cidList [][]byte // list of container identifiers
}
prm := client.TestInvokePrm{}
prm.SetMethod(listMethod)
prm.SetArgs(rawID)
// SetOwnerID sets the container owner identifier
// in a binary format.
func (l *ListArgs) SetOwnerID(v []byte) {
l.ownerID = v
}
// CIDList returns the list of container
// identifiers in a binary format.
func (l *ListValues) CIDList() [][]byte {
return l.cidList
}
// List performs the test invoke of list container
// method of NeoFS Container contract.
func (c *Client) List(args ListArgs) (*ListValues, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(listMethod)
invokePrm.SetArgs(args.ownerID)
prms, err := c.client.TestInvoke(invokePrm)
res, err := c.client.TestInvoke(prm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", listMethod, err)
} else if ln := len(prms); ln != 1 {
} else if ln := len(res); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", listMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
res, err = client.ArrayFromStackItem(res[0])
if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listMethod, err)
}
res := &ListValues{
cidList: make([][]byte, 0, len(prms)),
}
for i := range prms {
cid, err := client.BytesFromStackItem(prms[i])
cidList := make([]*cid.ID, 0, len(res))
for i := range res {
rawCid, err := client.BytesFromStackItem(res[i])
if err != nil {
return nil, fmt.Errorf("could not get byte array from stack item (%s): %w", listMethod, err)
}
res.cidList = append(res.cidList, cid)
v2 := new(v2refs.ContainerID)
v2.SetValue(rawCid)
cidList = append(cidList, cid.NewFromV2(v2))
}
return res, nil
return cidList, nil
}

View file

@ -3,94 +3,61 @@ package container
import (
"fmt"
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-sdk-go/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
)
// PutSizeArgs groups the arguments
// of "put container size" invocation call.
type PutSizeArgs struct {
epoch int64
size int64
cid []byte
reporterKey []byte
// AnnounceLoadPrm groups parameters of AnnounceLoad operation.
type AnnounceLoadPrm struct {
a container.UsedSpaceAnnouncement
key []byte
client.InvokePrmOptional
}
// SetEpoch sets the number of the epoch when
// size was estimated.
func (p *PutSizeArgs) SetEpoch(v uint64) {
p.epoch = int64(v)
// SetAnnouncement sets announcement.
func (a2 *AnnounceLoadPrm) SetAnnouncement(a container.UsedSpaceAnnouncement) {
a2.a = a
}
// SetSize sets estimation of the container size.
func (p *PutSizeArgs) SetSize(v uint64) {
p.size = int64(v)
// SetReporter sets public key of the reporter.
func (a2 *AnnounceLoadPrm) SetReporter(key []byte) {
a2.key = key
}
// SetContainerID sets identifier of the container
// being evaluated.
func (p *PutSizeArgs) SetContainerID(v []byte) {
p.cid = v
}
// AnnounceLoad saves container size estimation calculated by storage node
// with key in NeoFS system through Container contract call.
//
// Returns any error encountered that caused the saving to interrupt.
func (c *Client) AnnounceLoad(p AnnounceLoadPrm) error {
v2 := p.a.ContainerID().ToV2()
if v2 == nil {
return errUnsupported // use other major version if there any
}
// SetReporterKey ыуеы public key of the storage node
// that collected size estimation.
func (p *PutSizeArgs) SetReporterKey(v []byte) {
p.reporterKey = v
}
// PutSize invokes the call of put container size method
// of NeoFS Container contract.
func (c *Client) PutSize(args PutSizeArgs) error {
prm := client.InvokePrm{}
prm.SetMethod(putSizeMethod)
prm.SetArgs(args.epoch, args.cid, args.size, args.reporterKey)
prm.InvokePrmOptional = args.InvokePrmOptional
prm.SetArgs(int64(p.a.Epoch()), v2.GetValue(), int64(p.a.UsedSpace()), p.key)
prm.InvokePrmOptional = p.InvokePrmOptional
err := c.client.Invoke(prm)
if err != nil {
return fmt.Errorf("could not invoke method (%s): %w", putSizeMethod, err)
}
return nil
}
// ListSizesArgs groups the arguments
// of "list container sizes" test invoke call..
type ListSizesArgs struct {
epoch int64
}
// EstimationID is an identity of container load estimation inside Container contract.
type EstimationID []byte
// SetEpoch sets the number of the epoch to select
// the estimations.
func (p *ListSizesArgs) SetEpoch(v uint64) {
p.epoch = int64(v)
}
// ListSizesValues groups the stack items
// returned by "list container sizes" test invoke.
type ListSizesValues struct {
ids [][]byte
}
// IDList returns list of identifiers of the
// container load estimations.
func (v *ListSizesValues) IDList() [][]byte {
return v.ids
}
// ListSizes performs the test invoke of "list container sizes"
// method of NeoFS Container contract.
func (c *Client) ListSizes(args ListSizesArgs) (*ListSizesValues, error) {
// ListLoadEstimationsByEpoch returns a list of container load estimations for to the specified epoch.
// The list is composed through Container contract call.
func (c *Client) ListLoadEstimationsByEpoch(epoch uint64) ([]EstimationID, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(listSizesMethod)
invokePrm.SetArgs(args.epoch)
invokePrm.SetArgs(int64(epoch))
prms, err := c.client.TestInvoke(invokePrm)
if err != nil {
@ -104,65 +71,42 @@ func (c *Client) ListSizes(args ListSizesArgs) (*ListSizesValues, error) {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listSizesMethod, err)
}
res := &ListSizesValues{
ids: make([][]byte, 0, len(prms)),
}
res := make([]EstimationID, 0, len(prms))
for i := range prms {
id, err := client.BytesFromStackItem(prms[i])
if err != nil {
return nil, fmt.Errorf("could not get ID byte array from stack item (%s): %w", listSizesMethod, err)
}
res.ids = append(res.ids, id)
res = append(res, id)
}
return res, nil
}
// GetSizeArgs groups the arguments
// of "get container size" test invoke call..
type GetSizeArgs struct {
id []byte
}
// SetID sets identifier of the container estimation.
func (p *GetSizeArgs) SetID(v []byte) {
p.id = v
}
// Estimation is a structure of single container load estimation
// reported by storage node.
type Estimation struct {
Size int64
Size uint64
Reporter []byte
}
// Estimations is a structure of grouped container load estimation inside Container contract.
type Estimations struct {
ContainerID []byte
ContainerID *cid.ID
Estimations []Estimation
Values []Estimation
}
// GetSizeValues groups the stack items
// returned by "get container size" test invoke.
type GetSizeValues struct {
est Estimations
}
// GetUsedSpaceEstimations returns a list of container load estimations by ID.
// The list is composed through Container contract call.
func (c *Client) GetUsedSpaceEstimations(id EstimationID) (*Estimations, error) {
prm := client.TestInvokePrm{}
prm.SetMethod(getSizeMethod)
prm.SetArgs([]byte(id))
// Estimations returns list of the container load estimations.
func (v *GetSizeValues) Estimations() Estimations {
return v.est
}
// GetContainerSize performs the test invoke of "get container size"
// method of NeoFS Container contract.
func (c *Client) GetContainerSize(args GetSizeArgs) (*GetSizeValues, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(getSizeMethod)
invokePrm.SetArgs(args.id)
prms, err := c.client.TestInvoke(invokePrm)
prms, err := c.client.TestInvoke(prm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getSizeMethod, err)
} else if ln := len(prms); ln != 1 {
@ -176,9 +120,7 @@ func (c *Client) GetContainerSize(args GetSizeArgs) (*GetSizeValues, error) {
return nil, fmt.Errorf("unexpected stack item count of estimations fields (%s)", getSizeMethod)
}
es := Estimations{}
es.ContainerID, err = client.BytesFromStackItem(prms[0])
rawCID, err := client.BytesFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get container ID byte array from stack item (%s): %w", getSizeMethod, err)
}
@ -188,7 +130,12 @@ func (c *Client) GetContainerSize(args GetSizeArgs) (*GetSizeValues, error) {
return nil, fmt.Errorf("could not get estimation list array from stack item (%s): %w", getSizeMethod, err)
}
es.Estimations = make([]Estimation, 0, len(prms))
v2 := new(v2refs.ContainerID)
v2.SetValue(rawCID)
res := &Estimations{
ContainerID: cid.NewFromV2(v2),
Values: make([]Estimation, 0, len(prms)),
}
for i := range prms {
arr, err := client.ArrayFromStackItem(prms[i])
@ -198,22 +145,21 @@ func (c *Client) GetContainerSize(args GetSizeArgs) (*GetSizeValues, error) {
return nil, fmt.Errorf("unexpected stack item count of estimation fields (%s)", getSizeMethod)
}
e := Estimation{}
e.Reporter, err = client.BytesFromStackItem(arr[0])
reporter, err := client.BytesFromStackItem(arr[0])
if err != nil {
return nil, fmt.Errorf("could not get reporter byte array from stack item (%s): %w", getSizeMethod, err)
}
e.Size, err = client.IntFromStackItem(arr[1])
sz, err := client.IntFromStackItem(arr[1])
if err != nil {
return nil, fmt.Errorf("could not get estimation size from stack item (%s): %w", getSizeMethod, err)
}
es.Estimations = append(es.Estimations, e)
res.Values = append(res.Values, Estimation{
Reporter: reporter,
Size: uint64(sz),
})
}
return &GetSizeValues{
est: es,
}, nil
return res, nil
}

View file

@ -1,82 +1,128 @@
package container
import (
"crypto/sha256"
"fmt"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-sdk-go/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
)
// PutArgs groups the arguments
// of put container invocation call.
type PutArgs struct {
cnr []byte // container in a binary format
// Put marshals container, and passes it to Wrapper's Put method
// along with sig.Key() and sig.Sign().
//
// Returns error if container is nil.
func Put(c *Client, cnr *container.Container) (*cid.ID, error) {
if cnr == nil {
return nil, errNilArgument
}
sig []byte // binary container signature
data, err := cnr.Marshal()
if err != nil {
return nil, fmt.Errorf("can't marshal container: %w", err)
}
publicKey []byte // public key of container owner
binToken, err := cnr.SessionToken().Marshal()
if err != nil {
return nil, fmt.Errorf("could not marshal session token: %w", err)
}
token []byte // binary session token
sig := cnr.Signature()
name, zone string // native name and zone
name, zone := container.GetNativeNameWithZone(cnr)
err = c.Put(PutPrm{
cnr: data,
key: sig.Key(),
sig: sig.Sign(),
token: binToken,
name: name,
zone: zone,
})
if err != nil {
return nil, err
}
id := cid.New()
id.SetSHA256(sha256.Sum256(data))
return id, nil
}
// PutPrm groups parameters of Put operation.
type PutPrm struct {
cnr []byte
key []byte
sig []byte
token []byte
name string
zone string
client.InvokePrmOptional
}
// SetPublicKey sets the public key of container owner
// in a binary format.
func (p *PutArgs) SetPublicKey(v []byte) {
p.publicKey = v
// SetContainer sets container data.
func (p *PutPrm) SetContainer(cnr []byte) {
p.cnr = cnr
}
// SetContainer sets the container structure
// in a binary format.
func (p *PutArgs) SetContainer(v []byte) {
p.cnr = v
// SetKey sets public key.
func (p *PutPrm) SetKey(key []byte) {
p.key = key
}
// SetSignature sets the container structure
// owner's signature.
func (p *PutArgs) SetSignature(v []byte) {
p.sig = v
// SetSignature sets signature.
func (p *PutPrm) SetSignature(sig []byte) {
p.sig = sig
}
// SetSessionToken sets token of the session
// within which the container was created
// in a binary format.
func (p *PutArgs) SetSessionToken(v []byte) {
p.token = v
// SetToken sets session token.
func (p *PutPrm) SetToken(token []byte) {
p.token = token
}
// SetNativeNameWithZone sets container native name and its zone.
func (p *PutArgs) SetNativeNameWithZone(name, zone string) {
p.name, p.zone = name, zone
// SetName sets native name.
func (p *PutPrm) SetName(name string) {
p.name = name
}
// Put invokes the call of put (named if name is set) container method
// of NeoFS Container contract.
func (c *Client) Put(args PutArgs) error {
// SetZone sets zone.
func (p *PutPrm) SetZone(zone string) {
p.zone = zone
}
// Put saves binary container with its session token, key and signature
// in NeoFS system through Container contract call.
//
// Returns calculated container identifier and any error
// encountered that caused the saving to interrupt.
//
// If TryNotary is provided, calls notary contract.
func (c *Client) Put(p PutPrm) error {
if len(p.sig) == 0 || len(p.key) == 0 {
return errNilArgument
}
var (
method string
prm client.InvokePrm
)
if args.name != "" {
method = PutNamedMethod
prm.SetArgs(args.cnr, args.sig, args.publicKey, args.token, args.name, args.zone)
if p.name != "" {
method = putNamedMethod
prm.SetArgs(p.cnr, p.sig, p.key, p.token, p.name, p.zone)
} else {
method = putMethod
prm.SetArgs(args.cnr, args.sig, args.publicKey, args.token)
prm.SetArgs(p.cnr, p.sig, p.key, p.token)
}
prm.SetMethod(method)
prm.InvokePrmOptional = args.InvokePrmOptional
prm.InvokePrmOptional = p.InvokePrmOptional
err := c.client.Invoke(prm)
if err != nil {
return fmt.Errorf("could not invoke method (%s): %w", method, err)
}
return nil
}

View file

@ -1,424 +0,0 @@
package wrapper
import (
"crypto/sha256"
"errors"
"fmt"
"strings"
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
core "github.com/nspcc-dev/neofs-node/pkg/core/container"
staticli "github.com/nspcc-dev/neofs-node/pkg/morph/client"
client "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-sdk-go/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/signature"
)
var (
errNilArgument = errors.New("empty argument")
errUnsupported = errors.New("unsupported structure version")
)
// Put marshals container, and passes it to Wrapper's Put method
// along with sig.Key() and sig.Sign().
//
// Returns error if container is nil.
func Put(w *Wrapper, cnr *container.Container) (*cid.ID, error) {
if cnr == nil {
return nil, errNilArgument
}
data, err := cnr.Marshal()
if err != nil {
return nil, fmt.Errorf("can't marshal container: %w", err)
}
binToken, err := cnr.SessionToken().Marshal()
if err != nil {
return nil, fmt.Errorf("could not marshal session token: %w", err)
}
sig := cnr.Signature()
name, zone := container.GetNativeNameWithZone(cnr)
err = w.Put(PutPrm{
cnr: data,
key: sig.Key(),
sig: sig.Sign(),
token: binToken,
name: name,
zone: zone,
})
if err != nil {
return nil, err
}
id := cid.New()
id.SetSHA256(sha256.Sum256(data))
return id, nil
}
// PutPrm groups parameters of Put operation.
type PutPrm struct {
cnr []byte
key []byte
sig []byte
token []byte
name string
zone string
staticli.InvokePrmOptional
}
// SetContainer sets container data.
func (p *PutPrm) SetContainer(cnr []byte) {
p.cnr = cnr
}
// SetKey sets public key.
func (p *PutPrm) SetKey(key []byte) {
p.key = key
}
// SetSignature sets signature.
func (p *PutPrm) SetSignature(sig []byte) {
p.sig = sig
}
// SetToken sets session token.
func (p *PutPrm) SetToken(token []byte) {
p.token = token
}
// SetName sets native name.
func (p *PutPrm) SetName(name string) {
p.name = name
}
// SetZone sets zone.
func (p *PutPrm) SetZone(zone string) {
p.zone = zone
}
// Put saves binary container with its session token, key and signature
// in NeoFS system through Container contract call.
//
// Returns calculated container identifier and any error
// encountered that caused the saving to interrupt.
//
// If TryNotary is provided, calls notary contract.
func (w *Wrapper) Put(prm PutPrm) error {
if len(prm.sig) == 0 || len(prm.key) == 0 {
return errNilArgument
}
var args client.PutArgs
args.SetContainer(prm.cnr)
args.SetSignature(prm.sig)
args.SetPublicKey(prm.key)
args.SetSessionToken(prm.token)
args.SetNativeNameWithZone(prm.name, prm.zone)
args.InvokePrmOptional = prm.InvokePrmOptional
err := w.client.Put(args)
if err != nil {
return err
}
return nil
}
type containerSource Wrapper
func (x *containerSource) Get(cid *cid.ID) (*container.Container, error) {
return Get((*Wrapper)(x), cid)
}
// AsContainerSource provides container Source interface
// from Wrapper instance.
func AsContainerSource(w *Wrapper) core.Source {
return (*containerSource)(w)
}
// Get marshals container ID, and passes it to Wrapper's Get method.
//
// Returns error if cid is nil.
func Get(w *Wrapper, cid *cid.ID) (*container.Container, error) {
return w.Get(cid.ToV2().GetValue())
}
// Get reads the container from NeoFS system by binary identifier
// through Container contract call.
//
// If an empty slice is returned for the requested identifier,
// storage.ErrNotFound error is returned.
func (w *Wrapper) Get(cid []byte) (*container.Container, error) {
var args client.GetArgs
args.SetCID(cid)
// ask RPC neo node to get serialized container
rpcAnswer, err := w.client.Get(args)
if err != nil {
// TODO(fyrchik): reuse messages from container contract.
// Currently there are some dependency problems:
// github.com/nspcc-dev/neofs-node/pkg/innerring imports
// github.com/nspcc-dev/neofs-sdk-go/audit imports
// github.com/nspcc-dev/neofs-api-go/v2/audit: ambiguous import: found package github.com/nspcc-dev/neofs-api-go/v2/audit in multiple modules:
// github.com/nspcc-dev/neofs-api-go v1.27.1 (/home/dzeta/go/pkg/mod/github.com/nspcc-dev/neofs-api-go@v1.27.1/v2/audit)
// github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1 (/home/dzeta/go/pkg/mod/github.com/nspcc-dev/neofs-api-go/v2@v2.11.0-pre.0.20211201134523-3604d96f3fe1/audit)
if strings.Contains(err.Error(), "container does not exist") {
return nil, core.ErrNotFound
}
return nil, err
}
// unmarshal container
cnr := container.New()
if err := cnr.Unmarshal(rpcAnswer.Container()); err != nil {
// use other major version if there any
return nil, fmt.Errorf("can't unmarshal container: %w", err)
}
binToken := rpcAnswer.SessionToken()
if len(binToken) > 0 {
tok := session.NewToken()
err = tok.Unmarshal(binToken)
if err != nil {
return nil, fmt.Errorf("could not unmarshal session token: %w", err)
}
cnr.SetSessionToken(tok)
}
sig := signature.New()
sig.SetKey(rpcAnswer.PublicKey())
sig.SetSign(rpcAnswer.Signature())
cnr.SetSignature(sig)
return cnr, nil
}
// Delete marshals container ID, and passes it to Wrapper's Delete method
// along with signature and session token.
//
// Returns error if container ID is nil.
func Delete(w *Wrapper, witness core.RemovalWitness) error {
id := witness.ContainerID()
if id == nil {
return errNilArgument
}
binToken, err := witness.SessionToken().Marshal()
if err != nil {
return fmt.Errorf("could not marshal session token: %w", err)
}
return w.Delete(
DeletePrm{
cid: id.ToV2().GetValue(),
signature: witness.Signature(),
token: binToken,
})
}
// DeletePrm groups parameters of Delete client operation.
type DeletePrm struct {
cid []byte
signature []byte
token []byte
staticli.InvokePrmOptional
}
// SetCID sets container ID.
func (d *DeletePrm) SetCID(cid []byte) {
d.cid = cid
}
// SetSignature sets signature.
func (d *DeletePrm) SetSignature(signature []byte) {
d.signature = signature
}
// SetToken sets session token.
func (d *DeletePrm) SetToken(token []byte) {
d.token = token
}
// Delete removes the container from NeoFS system
// through Container contract call.
//
// Returns any error encountered that caused
// the removal to interrupt.
//
// If TryNotary is provided, calls notary contract.
func (w *Wrapper) Delete(prm DeletePrm) error {
if len(prm.signature) == 0 {
return errNilArgument
}
var args client.DeleteArgs
args.SetSignature(prm.signature)
args.SetCID(prm.cid)
args.SetSessionToken(prm.token)
args.InvokePrmOptional = prm.InvokePrmOptional
return w.client.Delete(args)
}
// List returns a list of container identifiers belonging
// to the specified owner of NeoFS system. The list is composed
// through Container contract call.
//
// Returns the identifiers of all NeoFS containers if pointer
// to owner identifier is nil.
func (w *Wrapper) List(ownerID *owner.ID) ([]*cid.ID, error) {
args := client.ListArgs{}
if ownerID == nil {
args.SetOwnerID([]byte{})
} else if v2 := ownerID.ToV2(); v2 == nil {
return nil, errUnsupported // use other major version if there any
} else {
args.SetOwnerID(v2.GetValue())
}
// ask RPC neo node to get serialized container
rpcAnswer, err := w.client.List(args)
if err != nil {
return nil, err
}
rawIDs := rpcAnswer.CIDList()
result := make([]*cid.ID, 0, len(rawIDs))
for i := range rawIDs {
v2 := new(v2refs.ContainerID)
v2.SetValue(rawIDs[i])
id := cid.NewFromV2(v2)
result = append(result, id)
}
return result, nil
}
// AnnounceLoadPrm groups parameters of AnnounceLoad operation.
type AnnounceLoadPrm struct {
a container.UsedSpaceAnnouncement
key []byte
staticli.InvokePrmOptional
}
// SetAnnouncement sets announcement.
func (a2 *AnnounceLoadPrm) SetAnnouncement(a container.UsedSpaceAnnouncement) {
a2.a = a
}
// SetReporter sets public key of the reporter.
func (a2 *AnnounceLoadPrm) SetReporter(key []byte) {
a2.key = key
}
// AnnounceLoad saves container size estimation calculated by storage node
// with key in NeoFS system through Container contract call.
//
// Returns any error encountered that caused the saving to interrupt.
func (w *Wrapper) AnnounceLoad(prm AnnounceLoadPrm) error {
v2 := prm.a.ContainerID().ToV2()
if v2 == nil {
return errUnsupported // use other major version if there any
}
args := client.PutSizeArgs{}
args.SetContainerID(v2.GetValue())
args.SetEpoch(prm.a.Epoch())
args.SetSize(prm.a.UsedSpace())
args.SetReporterKey(prm.key)
args.InvokePrmOptional = prm.InvokePrmOptional
return w.client.PutSize(args)
}
// EstimationID is an identity of container load estimation inside Container contract.
type EstimationID []byte
// ListLoadEstimationsByEpoch returns a list of container load estimations for to the specified epoch.
// The list is composed through Container contract call.
func (w *Wrapper) ListLoadEstimationsByEpoch(epoch uint64) ([]EstimationID, error) {
args := client.ListSizesArgs{}
args.SetEpoch(epoch)
// ask RPC neo node to get serialized container
rpcAnswer, err := w.client.ListSizes(args)
if err != nil {
return nil, err
}
rawIDs := rpcAnswer.IDList()
result := make([]EstimationID, 0, len(rawIDs))
for i := range rawIDs {
result = append(result, rawIDs[i])
}
return result, nil
}
// Estimation is a structure of single container load estimation
// reported by storage node.
type Estimation struct {
Size uint64
Reporter []byte
}
// Estimations is a structure of grouped container load estimation inside Container contract.
type Estimations struct {
ContainerID *cid.ID
Values []Estimation
}
// GetUsedSpaceEstimations returns a list of container load estimations by ID.
// The list is composed through Container contract call.
func (w *Wrapper) GetUsedSpaceEstimations(id EstimationID) (*Estimations, error) {
args := client.GetSizeArgs{}
args.SetID(id)
rpcAnswer, err := w.client.GetContainerSize(args)
if err != nil {
return nil, err
}
es := rpcAnswer.Estimations()
v2 := new(v2refs.ContainerID)
v2.SetValue(es.ContainerID)
res := &Estimations{
ContainerID: cid.NewFromV2(v2),
Values: make([]Estimation, 0, len(es.Estimations)),
}
for i := range es.Estimations {
res.Values = append(res.Values, Estimation{
Size: uint64(es.Estimations[i].Size),
Reporter: es.Estimations[i].Reporter,
})
}
return res, nil
}

View file

@ -1,150 +0,0 @@
package wrapper
import (
"fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/container"
staticli "github.com/nspcc-dev/neofs-node/pkg/morph/client"
client "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/signature"
)
// GetEACL reads the extended ACL table from NeoFS system
// through Container contract call.
func (w *Wrapper) GetEACL(cid *cid.ID) (*eacl.Table, error) {
if cid == nil {
return nil, errNilArgument
}
args := client.EACLArgs{}
v2 := cid.ToV2()
if v2 == nil {
return nil, errUnsupported // use other major version if there any
}
args.SetCID(v2.GetValue())
rpcAnswer, err := w.client.EACL(args)
if err != nil {
return nil, err
}
// Client may not return errors if the table is missing, so check this case additionally.
// The absence of a signature in the response can be taken as an eACL absence criterion,
// since unsigned table cannot be approved in the storage by design.
sig := rpcAnswer.Signature()
if len(sig) == 0 {
return nil, container.ErrEACLNotFound
}
table := eacl.NewTable()
if err = table.Unmarshal(rpcAnswer.EACL()); err != nil {
// use other major version if there any
return nil, err
}
binToken := rpcAnswer.SessionToken()
if len(binToken) > 0 {
tok := session.NewToken()
err = tok.Unmarshal(binToken)
if err != nil {
return nil, fmt.Errorf("could not unmarshal session token: %w", err)
}
table.SetSessionToken(tok)
}
tableSignature := signature.New()
tableSignature.SetKey(rpcAnswer.PublicKey())
tableSignature.SetSign(sig)
table.SetSignature(tableSignature)
return table, nil
}
// PutEACL marshals table, and passes it to Wrapper's PutEACLBinary method
// along with sig.Key() and sig.Sign().
//
// Returns error if table is nil.
//
// If TryNotary is provided, calls notary contract.
func PutEACL(w *Wrapper, table *eacl.Table) error {
if table == nil {
return errNilArgument
}
data, err := table.Marshal()
if err != nil {
return fmt.Errorf("can't marshal eacl table: %w", err)
}
binToken, err := table.SessionToken().Marshal()
if err != nil {
return fmt.Errorf("could not marshal session token: %w", err)
}
sig := table.Signature()
return w.PutEACL(
PutEACLPrm{
table: data,
key: sig.Key(),
sig: sig.Sign(),
token: binToken,
})
}
// PutEACLPrm groups parameters of PutEACL operation.
type PutEACLPrm struct {
table []byte
key []byte
sig []byte
token []byte
staticli.InvokePrmOptional
}
// SetTable sets table.
func (p *PutEACLPrm) SetTable(table []byte) {
p.table = table
}
// SetKey sets key.
func (p *PutEACLPrm) SetKey(key []byte) {
p.key = key
}
// SetSignature sets signature.
func (p *PutEACLPrm) SetSignature(sig []byte) {
p.sig = sig
}
// SetToken sets session token.
func (p *PutEACLPrm) SetToken(token []byte) {
p.token = token
}
// PutEACL saves binary eACL table with its session token, key and signature
// in NeoFS system through Container contract call.
//
// Returns any error encountered that caused the saving to interrupt.
func (w *Wrapper) PutEACL(prm PutEACLPrm) error {
if len(prm.sig) == 0 || len(prm.key) == 0 {
return errNilArgument
}
args := client.SetEACLArgs{}
args.SetSignature(prm.sig)
args.SetPublicKey(prm.key)
args.SetEACL(prm.table)
args.SetSessionToken(prm.token)
args.InvokePrmOptional = prm.InvokePrmOptional
return w.client.SetEACL(args)
}

View file

@ -1,48 +0,0 @@
package wrapper
import (
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
)
// StartEstimationPrm groups parameters of StartEstimation operation.
type StartEstimationPrm struct {
epoch uint64
client.InvokePrmOptional
}
// SetEpoch sets epoch.
func (s *StartEstimationPrm) SetEpoch(epoch uint64) {
s.epoch = epoch
}
// StartEstimation votes to produce start estimation notification.
func (w *Wrapper) StartEstimation(prm StartEstimationPrm) error {
args := container.StartEstimation{}
args.SetEpoch(int64(prm.epoch))
args.InvokePrmOptional = prm.InvokePrmOptional
return w.client.StartEstimation(args)
}
// StopEstimationPrm groups parameters of StopEstimation operation.
type StopEstimationPrm struct {
epoch uint64
client.InvokePrmOptional
}
// SetEpoch sets epoch.
func (s *StopEstimationPrm) SetEpoch(epoch uint64) {
s.epoch = epoch
}
// StopEstimation votes to produce stop estimation notification.
func (w *Wrapper) StopEstimation(prm StopEstimationPrm) error {
args := container.StopEstimation{}
args.SetEpoch(int64(prm.epoch))
args.InvokePrmOptional = prm.InvokePrmOptional
return w.client.StopEstimation(args)
}

View file

@ -1,100 +0,0 @@
package wrapper
import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/internal"
)
// Wrapper is a wrapper over container contract
// client which implements container storage and
// eACL storage methods.
//
// Working wrapper must be created via constructor New.
// Using the Wrapper that has been created with new(Wrapper)
// expression (or just declaring a Wrapper variable) is unsafe
// and can lead to panic.
type Wrapper struct {
internal.StaticClient
client *container.Client
}
// Option allows to set an optional
// parameter of Wrapper.
type Option func(*opts)
type opts struct {
feePutNamedSet bool
feePutNamed fixedn.Fixed8
staticOpts []client.StaticClientOption
}
func defaultOpts() *opts {
return new(opts)
}
// Morph returns raw morph client.
func (w Wrapper) Morph() *client.Client {
return w.client.Morph()
}
// TryNotary returns option to enable
// notary invocation tries.
func TryNotary() Option {
return func(o *opts) {
o.staticOpts = append(o.staticOpts, 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.staticOpts = append(o.staticOpts, client.AsAlphabet())
}
}
// WithCustomFeeForNamedPut returns option to specify custom fee for each Put operation with named container.
func WithCustomFeeForNamedPut(fee fixedn.Fixed8) Option {
return func(o *opts) {
o.feePutNamed = fee
o.feePutNamedSet = true
}
}
// NewFromMorph returns the wrapper instance from the raw morph client.
//
// Specified fee is used for all operations by default. If WithCustomFeeForNamedPut is provided,
// the customized fee is used for Put operations with named containers.
func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts ...Option) (*Wrapper, error) {
o := defaultOpts()
for i := range opts {
opts[i](o)
}
staticOpts := o.staticOpts
if o.feePutNamedSet {
staticOpts = append(staticOpts, client.WithCustomFee(container.PutNamedMethod, o.feePutNamed))
}
staticClient, err := client.NewStatic(cli, contract, fee, staticOpts...)
if err != nil {
return nil, fmt.Errorf("can't create container static client: %w", err)
}
return &Wrapper{
StaticClient: staticClient,
client: container.New(staticClient),
}, nil
}