diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index d5ca7ff574..bd6c69dfa6 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -187,7 +187,15 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error { } func (cp *Processor) approveDeleteContainer(e *containerEvent.Delete) { - err := cp.cnrClient.Delete(e.ContainerID(), e.Signature(), e.SessionToken()) + var err error + + if nr := e.NotaryRequest(); nr != nil { + // delete event was received via Notary service + err = cp.cnrClient.Morph().NotarySignAndInvokeTX(nr.MainTransaction) + } else { + // delete event was received via notification service + err = cp.cnrClient.Delete(e.ContainerID(), e.Signature(), e.SessionToken()) + } if err != nil { cp.log.Error("could not approve delete container", zap.String("error", err.Error()), diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index b36bed1f53..2fcd90517b 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -98,6 +98,10 @@ func New(p *Params) (*Processor, error) { // ListenerNotificationParsers for the 'event.Listener' event producer. func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { + if !cp.notaryDisabled { + return nil + } + var ( parsers = make([]event.NotificationParserInfo, 0, 3) @@ -106,12 +110,10 @@ func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInf p.SetScriptHash(cp.containerContract) - if cp.notaryDisabled { - // container put - p.SetType(event.TypeFromString(putNotification)) - p.SetParser(containerEvent.ParsePut) - parsers = append(parsers, p) - } + // container put + p.SetType(event.TypeFromString(putNotification)) + p.SetParser(containerEvent.ParsePut) + parsers = append(parsers, p) // container delete p.SetType(event.TypeFromString(deleteNotification)) @@ -128,6 +130,10 @@ func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInf // ListenerNotificationHandlers for the 'event.Listener' event producer. func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { + if !cp.notaryDisabled { + return nil + } + var ( handlers = make([]event.NotificationHandlerInfo, 0, 3) @@ -136,12 +142,10 @@ func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI h.SetScriptHash(cp.containerContract) - if cp.notaryDisabled { - // container put - h.SetType(event.TypeFromString(putNotification)) - h.SetHandler(cp.handlePut) - handlers = append(handlers, h) - } + // container put + h.SetType(event.TypeFromString(putNotification)) + h.SetHandler(cp.handlePut) + handlers = append(handlers, h) // container delete h.SetType(event.TypeFromString(deleteNotification)) @@ -158,26 +162,50 @@ func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI // ListenerNotaryParsers for the 'event.Listener' notary event producer. func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { - var p event.NotaryParserInfo + var ( + p event.NotaryParserInfo + + pp = make([]event.NotaryParserInfo, 0, 3) + ) p.SetMempoolType(mempoolevent.TransactionAdded) - p.SetRequestType(containerEvent.PutNotaryEvent) p.SetScriptHash(cp.containerContract) - p.SetParser(containerEvent.ParsePutNotary) - return []event.NotaryParserInfo{p} + // container put + p.SetRequestType(containerEvent.PutNotaryEvent) + p.SetParser(containerEvent.ParsePutNotary) + pp = append(pp, p) + + // container delete + p.SetRequestType(containerEvent.DeleteNotaryEvent) + p.SetParser(containerEvent.ParseDeleteNotary) + pp = append(pp, p) + + return pp } // ListenerNotaryHandlers for the 'event.Listener' notary event producer. func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { - var h event.NotaryHandlerInfo + var ( + h event.NotaryHandlerInfo + + hh = make([]event.NotaryHandlerInfo, 0, 3) + ) - h.SetMempoolType(mempoolevent.TransactionAdded) - h.SetRequestType(containerEvent.PutNotaryEvent) h.SetScriptHash(cp.containerContract) - h.SetHandler(cp.handlePut) + h.SetMempoolType(mempoolevent.TransactionAdded) - return []event.NotaryHandlerInfo{h} + // container put + h.SetRequestType(containerEvent.PutNotaryEvent) + h.SetHandler(cp.handlePut) + hh = append(hh, h) + + // container delete + h.SetRequestType(containerEvent.DeleteNotaryEvent) + h.SetHandler(cp.handleDelete) + hh = append(hh, h) + + return hh } // TimersHandlers for the 'Timers' event producer. diff --git a/pkg/morph/event/container/delete.go b/pkg/morph/event/container/delete.go index b847ea476e..a3115cd076 100644 --- a/pkg/morph/event/container/delete.go +++ b/pkg/morph/event/container/delete.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" @@ -13,6 +14,10 @@ type Delete struct { containerID []byte signature []byte token []byte + + // For notary notifications only. + // Contains raw transactions of notary request. + notaryRequest *payload.P2PNotaryRequest } // MorphEvent implements Neo:Morph Event interface. @@ -30,6 +35,14 @@ func (d Delete) SessionToken() []byte { return d.token } +// NotaryRequest returns raw notary request if notification +// was received via notary service. Otherwise, returns nil. +func (d Delete) NotaryRequest() *payload.P2PNotaryRequest { + return d.notaryRequest +} + +const expectedItemNumDelete = 3 + // ParseDelete from notification into container event structure. // // Expects 3 stack items. @@ -39,10 +52,8 @@ func ParseDelete(params []stackitem.Item) (event.Event, error) { err error ) - const expectedItemNumEACL = 3 - - if ln := len(params); ln != expectedItemNumEACL { - return nil, event.WrongNumberOfParameters(expectedItemNumEACL, ln) + if ln := len(params); ln != expectedItemNumDelete { + return nil, event.WrongNumberOfParameters(expectedItemNumDelete, ln) } // parse container diff --git a/pkg/morph/event/container/delete_notary.go b/pkg/morph/event/container/delete_notary.go new file mode 100644 index 0000000000..a79020ad3e --- /dev/null +++ b/pkg/morph/event/container/delete_notary.go @@ -0,0 +1,70 @@ +package container + +import ( + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" +) + +func (d *Delete) setContainerID(v []byte) { + if v != nil { + d.containerID = v + } +} + +func (d *Delete) setSignature(v []byte) { + if v != nil { + d.signature = v + } +} + +func (d *Delete) setToken(v []byte) { + if v != nil { + d.token = v + } +} + +var deleteFieldSetters = []func(*Delete, []byte){ + // order on stack is reversed + (*Delete).setToken, + (*Delete).setSignature, + (*Delete).setContainerID, +} + +const ( + // DeleteNotaryEvent is method name for container delete operations + // in `Container` contract. Is used as identificator for notary + // delete container requests. + DeleteNotaryEvent = "delete" +) + +// ParseDeleteNotary from NotaryEvent into container event structure. +func ParseDeleteNotary(ne event.NotaryEvent) (event.Event, error) { + var ( + ev Delete + currentOp opcode.Opcode + ) + + fieldNum := 0 + + for _, op := range ne.Params() { + currentOp = op.Code() + + switch { + case opcode.PUSHDATA1 <= currentOp && currentOp <= opcode.PUSHDATA4: + if fieldNum == expectedItemNumDelete { + return nil, event.UnexpectedArgNumErr(DeleteNotaryEvent) + } + + deleteFieldSetters[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(DeleteNotaryEvent, op.Code()) + } + } + + ev.notaryRequest = ne.Raw() + + return ev, nil +} diff --git a/pkg/morph/event/container/put_notary.go b/pkg/morph/event/container/put_notary.go index 82eee70e6e..3226192fa2 100644 --- a/pkg/morph/event/container/put_notary.go +++ b/pkg/morph/event/container/put_notary.go @@ -1,8 +1,6 @@ package container import ( - "fmt" - "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neofs-node/pkg/morph/event" ) @@ -31,7 +29,7 @@ func (p *Put) setToken(v []byte) { } } -var fieldSetters = []func(*Put, []byte){ +var putFieldSetters = []func(*Put, []byte){ // order on stack is reversed (*Put).setToken, (*Put).setPublicKey, @@ -46,8 +44,6 @@ const ( PutNotaryEvent = "put" ) -var errUnexpectedArgumentAmount = fmt.Errorf("unexpected arguments amount in %s call", PutNotaryEvent) - // ParsePutNotary from NotaryEvent into container event structure. func ParsePutNotary(ne event.NotaryEvent) (event.Event, error) { var ( @@ -63,10 +59,10 @@ func ParsePutNotary(ne event.NotaryEvent) (event.Event, error) { switch { case opcode.PUSHDATA1 <= currentOp && currentOp <= opcode.PUSHDATA4: if fieldNum == expectedItemNumPut { - return nil, errUnexpectedArgumentAmount + return nil, event.UnexpectedArgNumErr(PutNotaryEvent) } - fieldSetters[fieldNum](&ev, op.Param()) + putFieldSetters[fieldNum](&ev, op.Param()) fieldNum++ case opcode.PUSH0 <= currentOp && currentOp <= opcode.PUSH16 || currentOp == opcode.PACK: // array packing opcodes. do nothing with it diff --git a/pkg/morph/event/notary.go b/pkg/morph/event/notary.go index 0319158c25..bcfd4f53f6 100644 --- a/pkg/morph/event/notary.go +++ b/pkg/morph/event/notary.go @@ -43,6 +43,12 @@ func NotaryTypeFromString(str string) NotaryType { return NotaryType(str) } +// UnexpectedArgNumErr returns error when notary parsers +// get unexpected amount of argument in contract call. +func UnexpectedArgNumErr(method string) error { + return fmt.Errorf("unexpected arguments amount in %s call", method) +} + // UnexpectedOpcode returns error when notary parsers // get unexpected opcode in contract call. func UnexpectedOpcode(method string, op opcode.Opcode) error {