From eef8b6f720ad2ad1f39f81175c9db07d1794249b Mon Sep 17 00:00:00 2001 From: Evgenii Baidakov Date: Wed, 10 Dec 2025 11:17:09 +0400 Subject: [PATCH] ir/container: Support setAttribute container contract method Signed-off-by: Evgenii Baidakov --- CHANGELOG.md | 1 + .../processors/container/handlers.go | 27 +++++++++ .../processors/container/processor.go | 9 +++ pkg/morph/event/container/attributes.go | 59 +++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 pkg/morph/event/container/attributes.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3562925907..e2b2177000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Changelog for NeoFS Node - Support for GET of LINK objects in EC containers (#3722) - Containers can now be locked for deletion via `__NEOFS__LOCK_UNTIL` attribute (#3708) - SN can respond with `CONTAINER_LOCKED` status now (#3708) +- IR now supports `setAttrbibute` method to Container contract (#3728) ### Fixed - IR panics at graceful shutdown (#3706) diff --git a/pkg/innerring/processors/container/handlers.go b/pkg/innerring/processors/container/handlers.go index 5bca0ecab1..a96aa1c30b 100644 --- a/pkg/innerring/processors/container/handlers.go +++ b/pkg/innerring/processors/container/handlers.go @@ -158,3 +158,30 @@ func (cp *Processor) handleObjectPut(ev event.Event) { cp.log.Warn("object pool submission failed", zap.Error(err)) } } + +func (cp *Processor) handleSetAttribute(ev event.Event) { + e := ev.(containerEvent.SetAttribute) + + cp.log.Debug("notification", + zap.String("type", "set attribute"), + zap.String("cID", base58.Encode(e.CID)), + ) + + if !cp.alphabetState.IsAlphabet() { + cp.log.Debug("non alphabet mode, ignore set attribute") + return + } + + err := cp.objectPool.Submit(func() { + err := cp.cnrClient.Morph().NotarySignAndInvokeTX(e.NotaryRequest.MainTransaction, false) + if err != nil { + cp.log.Error("could not approve set attribute", + zap.String("cID", base58.Encode(e.CID)), + zap.Error(err), + ) + } + }) + if err != nil { + cp.log.Warn("object pool submission failed", zap.Error(err)) + } +} diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index 3bc46d3553..a527d7068b 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -179,6 +179,10 @@ func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { p.SetRequestType(fschaincontracts.AddContainerStructsMethod) p.SetParser(containerEvent.RestoreAddStructsRequest) + // set attribute + p.SetRequestType(containerEvent.SetAttributeNotaryEvent) + p.SetParser(containerEvent.ParseSetAttribute) + return pp } @@ -240,6 +244,11 @@ func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { h.SetHandler(cp.handleObjectPut) hh = append(hh, h) + // container setAttribute + h.SetRequestType(containerEvent.SetAttributeNotaryEvent) + h.SetHandler(cp.handleSetAttribute) + hh = append(hh, h) + // migrate protobuf->struct h.SetRequestType(fschaincontracts.AddContainerStructsMethod) h.SetHandler(func(ev event.Event) { diff --git a/pkg/morph/event/container/attributes.go b/pkg/morph/event/container/attributes.go new file mode 100644 index 0000000000..96555f8812 --- /dev/null +++ b/pkg/morph/event/container/attributes.go @@ -0,0 +1,59 @@ +package container + +import ( + "github.com/nspcc-dev/neo-go/pkg/network/payload" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" +) + +const ( + // SetAttributeNotaryEvent is method name for setAttribute operations in `Container` contract. + SetAttributeNotaryEvent = "setAttribute" +) + +// SetAttribute represents structure of notification about modified container attributes +// coming from NeoFS Container contract. +type SetAttribute struct { + CID []byte + Name []byte + Value []byte + Token []byte + + // For notary notifications only. + // Contains raw transactions of notary request. + NotaryRequest *payload.P2PNotaryRequest +} + +// MorphEvent implements [event.Event]. +func (r SetAttribute) MorphEvent() {} + +// ParseSetAttribute from NotaryEvent into container event structure. +func ParseSetAttribute(ne event.NotaryEvent) (event.Event, error) { + const expectedItemNumAnnounceLoad = 4 + args, err := getArgsFromEvent(ne, expectedItemNumAnnounceLoad) + if err != nil { + return nil, err + } + var ev SetAttribute + + ev.Token, err = getValueFromArg(args, 0, "session token", stackitem.ByteArrayT, event.BytesFromOpcode) + if err != nil { + return nil, err + } + ev.Value, err = getValueFromArg(args, 1, "attribute value", stackitem.ByteArrayT, event.BytesFromOpcode) + if err != nil { + return nil, err + } + ev.Name, err = getValueFromArg(args, 2, "attribute name", stackitem.ByteArrayT, event.BytesFromOpcode) + if err != nil { + return nil, err + } + ev.CID, err = getValueFromArg(args, 3, "container ID", stackitem.ByteArrayT, event.BytesFromOpcode) + if err != nil { + return nil, err + } + + ev.NotaryRequest = ne.Raw() + + return ev, nil +}