diff --git a/pkg/innerring/processors/container/process_eacl.go b/pkg/innerring/processors/container/process_eacl.go index 920ffbd4..15901889 100644 --- a/pkg/innerring/processors/container/process_eacl.go +++ b/pkg/innerring/processors/container/process_eacl.go @@ -83,7 +83,15 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error { } func (cp *Processor) approveSetEACL(e container.SetEACL) { - err := cp.cnrClient.PutEACL(e.Table(), e.PublicKey(), e.Signature(), e.SessionToken()) + var err error + + if nr := e.NotaryRequest(); nr != nil { + // setEACL event was received via Notary service + err = cp.cnrClient.Morph().NotarySignAndInvokeTX(nr.MainTransaction) + } else { + // setEACL event was received via notification service + err = cp.cnrClient.PutEACL(e.Table(), e.PublicKey(), e.Signature(), e.SessionToken()) + } if err != nil { cp.log.Error("could not approve set EACL", zap.String("error", err.Error()), diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index 2fcd9051..f778a99b 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -181,6 +181,11 @@ func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { p.SetParser(containerEvent.ParseDeleteNotary) pp = append(pp, p) + // set EACL + p.SetRequestType(containerEvent.SetEACLNotaryEvent) + p.SetParser(containerEvent.ParseSetEACLNotary) + pp = append(pp, p) + return pp } @@ -205,6 +210,11 @@ func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { h.SetHandler(cp.handleDelete) hh = append(hh, h) + // set eACL + h.SetRequestType(containerEvent.SetEACLNotaryEvent) + h.SetHandler(cp.handleSetEACL) + hh = append(hh, h) + return hh } diff --git a/pkg/morph/event/container/eacl.go b/pkg/morph/event/container/eacl.go index 595d672e..f1814598 100644 --- a/pkg/morph/event/container/eacl.go +++ b/pkg/morph/event/container/eacl.go @@ -3,6 +3,7 @@ package container import ( "fmt" + "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/client" "github.com/nspcc-dev/neofs-node/pkg/morph/event" @@ -11,13 +12,14 @@ import ( // SetEACL represents structure of notification about // modified eACL table coming from NeoFS Container contract. type SetEACL struct { - table []byte - + table []byte signature []byte - publicKey []byte + token []byte - token []byte + // For notary notifications only. + // Contains raw transactions of notary request. + notaryRequest *payload.P2PNotaryRequest } // MorphEvent implements Neo:Morph Event interface. @@ -45,6 +47,14 @@ func (x SetEACL) SessionToken() []byte { return x.token } +// NotaryRequest returns raw notary request if notification +// was received via notary service. Otherwise, returns nil. +func (x SetEACL) NotaryRequest() *payload.P2PNotaryRequest { + return x.notaryRequest +} + +const expectedItemNumEACL = 4 + // ParseSetEACL parses SetEACL notification event from list of stack items. // // Expects 4 stack items. @@ -54,8 +64,6 @@ func ParseSetEACL(items []stackitem.Item) (event.Event, error) { err error ) - const expectedItemNumEACL = 4 - if ln := len(items); ln != expectedItemNumEACL { return nil, event.WrongNumberOfParameters(expectedItemNumEACL, ln) } diff --git a/pkg/morph/event/container/eacl_notary.go b/pkg/morph/event/container/eacl_notary.go new file mode 100644 index 00000000..5492605b --- /dev/null +++ b/pkg/morph/event/container/eacl_notary.go @@ -0,0 +1,77 @@ +package container + +import ( + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" +) + +func (x *SetEACL) setTable(v []byte) { + if v != nil { + x.table = v + } +} + +func (x *SetEACL) setSignature(v []byte) { + if v != nil { + x.signature = v + } +} + +func (x *SetEACL) setPublicKey(v []byte) { + if v != nil { + x.publicKey = v + } +} + +func (x *SetEACL) setToken(v []byte) { + if v != nil { + x.token = v + } +} + +var setEACLFieldSetters = []func(*SetEACL, []byte){ + // order on stack is reversed + (*SetEACL).setToken, + (*SetEACL).setPublicKey, + (*SetEACL).setSignature, + (*SetEACL).setTable, +} + +const ( + // SetEACLNotaryEvent is method name for container EACL operations + // in `Container` contract. Is used as identificator for notary + // EACL changing requests. + SetEACLNotaryEvent = "setEACL" +) + +// ParseSetEACLNotary from NotaryEvent into container event structure. +func ParseSetEACLNotary(ne event.NotaryEvent) (event.Event, error) { + var ( + ev SetEACL + currentOp opcode.Opcode + ) + + fieldNum := 0 + + for _, op := range ne.Params() { + currentOp = op.Code() + + switch { + case opcode.PUSHDATA1 <= currentOp && currentOp <= opcode.PUSHDATA4: + if fieldNum == expectedItemNumEACL { + return nil, event.UnexpectedArgNumErr(SetEACLNotaryEvent) + } + + setEACLFieldSetters[fieldNum](&ev, op.Param()) + fieldNum++ + case opcode.PUSH0 <= currentOp && currentOp <= opcode.PUSH16 || currentOp == opcode.PACK: + // array packing opcodes. do nothing with it + default: + return nil, event.UnexpectedOpcode(SetEACLNotaryEvent, op.Code()) + } + } + + ev.notaryRequest = ne.Raw() + + return ev, nil +}