Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Changelog for NeoFS Node
- Compressed object format support from FSTree (#4223)
- Deprecated homomorphic hashing setting from CLI netinfo output (#4225)
- Support for multiaddr addresses in CLI and node (#4238)
- Support for `create` method of Container contract in IR (#4242)
- Support for `Created` and `Removed` events of Container contract in SN (#4242)

### Updated
- `github.com/nspcc-dev/neofs-sdk-go` module to `v1.0.0-rc.23.0.20261021092246-abe302e8498b` (#4194, #4219, #4228, #4224, #4222, #4240)
Expand Down
12 changes: 0 additions & 12 deletions cmd/neofs-node/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,6 @@ func registerEventParserOnceContainer(c *cfg, name string, p event.NotificationP
// NOT be called concurrently with itself and other similar functions. Owner may
// be zero.
func subscribeToContainerCreation(c *cfg, h func(id cid.ID, owner user.ID)) {
const eventNameContainerCreatedV2 = "Created"
registerEventParserOnceContainer(c, eventNameContainerCreatedV2, containerEvent.RestoreCreated)
addContainerAsyncNotificationHandler(c, eventNameContainerCreatedV2, func(e event.Event) {
created := e.(containerEvent.Created)
h(created.ID, created.Owner)
})
subscribeToContainerTransfer(c, func(id cid.ID, from, to user.ID) {
if from.IsZero() {
h(id, to)
Expand All @@ -346,12 +340,6 @@ func subscribeToContainerCreation(c *cfg, h func(id cid.ID, owner user.ID)) {

// like subscribeToContainerCreation but for removal. Owner may be zero.
func subscribeToContainerRemoval(c *cfg, h func(id cid.ID, owner user.ID)) {
const eventNameContainerRemovedV2 = "Removed"
registerEventParserOnceContainer(c, eventNameContainerRemovedV2, containerEvent.RestoreRemoved)
addContainerAsyncNotificationHandler(c, eventNameContainerRemovedV2, func(e event.Event) {
removed := e.(containerEvent.Removed)
h(removed.ID, removed.Owner)
})
subscribeToContainerTransfer(c, func(id cid.ID, from, to user.ID) {
if to.IsZero() {
h(id, from)
Expand Down
19 changes: 0 additions & 19 deletions pkg/innerring/processors/container/handlers.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package container

import (
"crypto/sha256"
"encoding/hex"

"github.com/mr-tron/base58"
Expand All @@ -20,24 +19,6 @@ func (cp *Processor) handleCreationRequest(ev event.Event) {
}
}

func (cp *Processor) handlePut(ev event.Event) {
req := ev.(containerEvent.CreateContainerRequest)

id := sha256.Sum256(req.Container)
cp.log.Info("notification",
zap.String("type", "container put"),
zap.String("id", base58.Encode(id[:])))

// send an event to the worker pool

err := cp.pool.Submit(func() { cp.processContainerPut(req, id) })
if err != nil {
// there system can be moved into controlled degradation stage
cp.log.Warn("container processor worker pool drained",
zap.Int("capacity", cp.pool.Cap()))
}
}

func (cp *Processor) handleDelete(ev event.Event) {
req := ev.(containerEvent.RemoveContainerRequest)
if req.VerificationScript == nil {
Expand Down
54 changes: 2 additions & 52 deletions pkg/innerring/processors/container/process_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (cp *Processor) processCreateContainerRequest(req containerEvent.CreateCont
cnrBytes := cnr.Marshal()
id := cid.NewFromMarshalledContainer(cnrBytes)

err = cp.checkPutContainer(cnr, cnrBytes, req.SessionToken, req.InvocationScript, req.VerificationScript, "", "")
err = cp.checkPutContainer(cnr, cnrBytes, req.SessionToken, req.InvocationScript, req.VerificationScript)
if err != nil {
cp.log.Error("container creation request failed check",
zap.Stringer("container", id), zap.Error(err))
Expand Down Expand Up @@ -72,34 +72,6 @@ func (cp *Processor) processCreateContainerRequest(req containerEvent.CreateCont
cp.approvePutContainer(req.MainTransaction, cnr, id)
}

// Process a new container from the user by checking the container sanity
// and sending approve tx back to the FS chain.
func (cp *Processor) processContainerPut(req containerEvent.CreateContainerRequest, id cid.ID) {
if !cp.alphabetState.IsAlphabet() {
cp.log.Info("non alphabet mode, ignore container put")
return
}

var cnr container.Container
if err := cnr.Unmarshal(req.Container); err != nil {
cp.log.Error("put container check failed",
zap.Error(fmt.Errorf("invalid binary container: %w", err)),
)
return
}

err := cp.checkPutContainer(cnr, req.Container, req.SessionToken, req.InvocationScript, req.VerificationScript, req.DomainName, req.DomainZone)
if err != nil {
cp.log.Error("put container check failed",
zap.Error(err),
)

return
}

cp.approvePutContainer(req.MainTransaction, cnr, id)
}

const (
sysAttrPrefix = "__NEOFS__"
sysAttrChainMeta = sysAttrPrefix + "METAINFO_CONSISTENCY"
Expand All @@ -112,7 +84,7 @@ var allowedSystemAttributes = map[string]struct{}{
sysAttrChainMeta: {},
}

func (cp *Processor) checkPutContainer(cnr container.Container, cnrBytes, sessionToken, invocScript, verifScript []byte, domainName, domainZone string) error {
func (cp *Processor) checkPutContainer(cnr container.Container, cnrBytes, sessionToken, invocScript, verifScript []byte) error {
if ver := cnr.Version(); ver.Compare(minContainerAPIVersion) < 0 {
return fmt.Errorf("API version is %s while %s is minimum supported", ver, minContainerAPIVersion)
}
Expand Down Expand Up @@ -161,13 +133,6 @@ func (cp *Processor) checkPutContainer(cnr container.Container, cnrBytes, sessio
return fmt.Errorf("invalid storage policy: %w", err)
}

if domainZone != "" { // if PutNamed event => check if values in-container domain name and zone correspond to args
err = checkNNS(cnr, domainName, domainZone)
if err != nil {
return fmt.Errorf("NNS: %w", err)
}
}

return nil
}

Expand Down Expand Up @@ -452,18 +417,3 @@ func (cp *Processor) approveRemoveAttributeRequest(req containerEvent.RemoveAttr
zap.Stringer("container", id), zap.Error(err))
}
}

func checkNNS(cnr container.Container, name, zone string) error {
// fetch domain info
d := cnr.ReadDomain()

if name != d.Name() {
return fmt.Errorf("names differ %s/%s", name, d.Name())
}

if zone != d.Zone() {
return fmt.Errorf("zones differ %s/%s", zone, d.Zone())
}

return nil
}
8 changes: 0 additions & 8 deletions pkg/innerring/processors/container/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,6 @@ func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo {
p.SetScriptHash(cp.cnrClient.ContractAddress())

// create container
p.SetRequestType(fschaincontracts.CreateContainerMethod)
p.SetUnaryParser(containerEvent.RestoreCreateContainerRequest)
pp = append(pp, p)

p.SetRequestType(fschaincontracts.CreateContainerV2Method)
p.SetParser(containerEvent.RestoreCreateContainerV2Request)
pp = append(pp, p)
Expand Down Expand Up @@ -177,10 +173,6 @@ func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo {
h.SetScriptHash(cp.cnrClient.ContractAddress())

// create container
h.SetRequestType(fschaincontracts.CreateContainerMethod)
h.SetHandler(cp.handlePut)
hh = append(hh, h)

h.SetRequestType(fschaincontracts.CreateContainerV2Method)
h.SetHandler(cp.handleCreationRequest)
hh = append(hh, h)
Expand Down
17 changes: 0 additions & 17 deletions pkg/morph/client/container/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package container
import (
"errors"
"fmt"
"strings"

"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
)
Expand All @@ -23,11 +21,7 @@ type Client struct {
}

const (
putMethod = "put"
getDataMethod = "getContainerData"
getInfoMethod = "getInfo"
Comment thread
roman-khimov marked this conversation as resolved.
getInfoRevisionedMethod = "getRevisionedInfo"
listMethod = "containersOf"
eaclDataMethod = "getEACLData"
tokensOfMethod = "tokensOf"
tokensMethod = "tokens"
Expand Down Expand Up @@ -97,14 +91,3 @@ func AsAlphabet() Option {
o.staticOpts = append(o.staticOpts, client.AsAlphabet())
}
}

func isMethodNotFoundError(err error, mtd string) bool {
if exc, ok := errors.AsType[unwrap.Exception](err); ok {
return isMethodNotFoundException(string(exc), mtd)
}
return isMethodNotFoundException(err.Error(), mtd)
}

func isMethodNotFoundException(msg, mtd string) bool {
return strings.Contains(msg, "method not found: "+mtd)
}
45 changes: 5 additions & 40 deletions pkg/morph/client/container/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"strings"

"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
containerrpc "github.com/nspcc-dev/neofs-contract/rpc/container"
containercore "github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
Expand Down Expand Up @@ -38,58 +37,24 @@ func Get(c *Client, cnr cid.ID) (container.Container, error) {
func (c *Client) Get(cid []byte) (container.Container, error) {
var cnr container.Container
prm := client.TestInvokePrm{}
method := getInfoRevisionedMethod
prm.SetMethod(method)
prm.SetMethod(getInfoRevisionedMethod)
prm.SetArgs(cid)

arr, err := c.client.TestInvoke(prm)
if err != nil && isMethodNotFoundError(err, method) {
method = getInfoMethod
prm.SetMethod(method)
arr, err = c.client.TestInvoke(prm)
if err != nil && isMethodNotFoundError(err, method) {
method = getDataMethod
prm.SetMethod(method)
arr, err = c.client.TestInvoke(prm)
}
}
if err != nil {
if strings.Contains(err.Error(), containerrpc.NotFoundError) {
var errNotFound apistatus.ContainerNotFound

return cnr, errNotFound
}
return cnr, fmt.Errorf("could not perform test invocation (%s): %w", method, err)
return cnr, fmt.Errorf("could not perform test invocation (%s): %w", getInfoRevisionedMethod, err)
} else if ln := len(arr); ln != 1 {
return cnr, fmt.Errorf("unexpected stack item count (%s): %d", method, ln)
return cnr, fmt.Errorf("unexpected stack item count (%s): %d", getInfoRevisionedMethod, ln)
}

switch method {
case getInfoRevisionedMethod:
cnr, err = revisionedContainerFromStackItem(arr[0])
case getInfoMethod:
cnr, err = containerFromStackItem(arr[0])
default:
cnr, err = decodeOldGetResponse(arr, method)
}
cnr, err = revisionedContainerFromStackItem(arr[0])
if err != nil {
return cnr, fmt.Errorf("invalid %q method result: invalid stack item: %w", method, err)
}

return cnr, nil
}

func decodeOldGetResponse(arr []stackitem.Item, method string) (container.Container, error) {
var cnr container.Container

cnrBytes, err := client.BytesFromStackItem(arr[0])
if err != nil {
return cnr, fmt.Errorf("could not get byte array of container (%s): %w", method, err)
}

if err := cnr.Unmarshal(cnrBytes); err != nil {
// use other major version if there any
return cnr, fmt.Errorf("can't unmarshal container: %w", err)
return cnr, fmt.Errorf("invalid %q method result: invalid stack item: %w", getInfoRevisionedMethod, err)
}

return cnr, nil
Expand Down
9 changes: 0 additions & 9 deletions pkg/morph/client/container/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ func (c *Client) List(idUser *user.ID) ([]cid.ID, error) {
}

res, err := c.client.TestInvokeIterator(mtd, iteratorPrefetchNumber, args...)
if err != nil && isMethodNotFoundError(err, mtd) {
var rawIdUser []byte
if idUser != nil {
rawIdUser = idUser[:]
}

res, err = c.client.TestInvokeIterator(listMethod, iteratorPrefetchNumber, rawIdUser)
mtd = listMethod
}
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", mtd, err)
}
Expand Down
9 changes: 0 additions & 9 deletions pkg/morph/client/container/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ func revisionedContainerFromStackItem(item stackitem.Item) (container.Container,
return cnr, nil
}

func containerFromStackItem(item stackitem.Item) (container.Container, error) {
var contractStruct containerrpc.ContainerInfo
if err := contractStruct.FromStackItem(item); err != nil {
return container.Container{}, err
}

return ContainerFromStruct(contractStruct)
}

// ContainerFromStruct decodes container from contract structure.
func ContainerFromStruct(contractStruct containerrpc.ContainerInfo) (container.Container, error) {
mjr, mnr, err := containerVersionFromStruct(contractStruct.Version)
Expand Down
27 changes: 2 additions & 25 deletions pkg/morph/client/container/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,34 +70,11 @@ func (c *Client) Put(ctx context.Context, p PutPrm) (cid.ID, error) {
err := c.client.CallWithAlphabetWitness(ctx, fschaincontracts.CreateContainerV2Method, []any{
containerToStackItem(p.cnr), p.sig, p.key, p.token,
})
if err == nil {
return cid.NewFromMarshalledContainer(p.cnr.Marshal()), nil
}
if !isMethodNotFoundError(err, fschaincontracts.CreateContainerV2Method) {
if err != nil {
return cid.ID{}, fmt.Errorf("could not invoke method (%s): %w", fschaincontracts.CreateContainerV2Method, err)
}

domain := p.cnr.ReadDomain()
metaAttr := p.cnr.Attribute("__NEOFS__METAINFO_CONSISTENCY")
metaEnabled := metaAttr == "optimistic" || metaAttr == "strict"
cnrBytes := p.cnr.Marshal()

err = c.client.CallWithAlphabetWitness(ctx, fschaincontracts.CreateContainerMethod, []any{
cnrBytes, p.sig, p.key, p.token, domain.Name(), domain.Zone(), metaEnabled,
})
if err != nil {
if isMethodNotFoundError(err, fschaincontracts.CreateContainerMethod) {
err = c.client.CallWithAlphabetWitness(ctx, putMethod, []any{
cnrBytes, p.sig, p.key, p.token, domain.Name(), domain.Zone(), metaEnabled,
})
if err != nil {
return cid.ID{}, fmt.Errorf("could not invoke method (%s): %w", putMethod, err)
}
return cid.NewFromMarshalledContainer(cnrBytes), nil
}
return cid.ID{}, fmt.Errorf("could not invoke method (%s): %w", fschaincontracts.CreateContainerMethod, err)
}
return cid.NewFromMarshalledContainer(cnrBytes), nil
return cid.NewFromMarshalledContainer(p.cnr.Marshal()), nil
}

func (c *Client) putContainerWithEacl(ctx context.Context, p PutPrm) (cid.ID, error) {
Expand Down
1 change: 0 additions & 1 deletion pkg/morph/contracts/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package fschaincontracts
const (
PayBalanceMethod = "settleContainerPayment"
UnpaidBalanceMethod = "getUnpaidContainerEpoch"
CreateContainerMethod = "create"
CreateContainerV2Method = "createV2"
RemoveContainerMethod = "remove"
PutContainerEACLMethod = "putEACL"
Expand Down
Loading
Loading