[#807] morph/event/container: Add delete notary support

Includes:
- `delete` container notary notification;
- refactor in processor bindings;
- fixed conflicts in `put` notifications.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2021-09-08 11:17:19 +03:00 committed by Pavel Karpy
parent 19e97e4d7c
commit e03b44ffc1
6 changed files with 152 additions and 33 deletions

View file

@ -187,7 +187,15 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
} }
func (cp *Processor) approveDeleteContainer(e *containerEvent.Delete) { 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 { if err != nil {
cp.log.Error("could not approve delete container", cp.log.Error("could not approve delete container",
zap.String("error", err.Error()), zap.String("error", err.Error()),

View file

@ -98,6 +98,10 @@ func New(p *Params) (*Processor, error) {
// ListenerNotificationParsers for the 'event.Listener' event producer. // ListenerNotificationParsers for the 'event.Listener' event producer.
func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
if !cp.notaryDisabled {
return nil
}
var ( var (
parsers = make([]event.NotificationParserInfo, 0, 3) parsers = make([]event.NotificationParserInfo, 0, 3)
@ -106,12 +110,10 @@ func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInf
p.SetScriptHash(cp.containerContract) p.SetScriptHash(cp.containerContract)
if cp.notaryDisabled { // container put
// container put p.SetType(event.TypeFromString(putNotification))
p.SetType(event.TypeFromString(putNotification)) p.SetParser(containerEvent.ParsePut)
p.SetParser(containerEvent.ParsePut) parsers = append(parsers, p)
parsers = append(parsers, p)
}
// container delete // container delete
p.SetType(event.TypeFromString(deleteNotification)) p.SetType(event.TypeFromString(deleteNotification))
@ -128,6 +130,10 @@ func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInf
// ListenerNotificationHandlers for the 'event.Listener' event producer. // ListenerNotificationHandlers for the 'event.Listener' event producer.
func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
if !cp.notaryDisabled {
return nil
}
var ( var (
handlers = make([]event.NotificationHandlerInfo, 0, 3) handlers = make([]event.NotificationHandlerInfo, 0, 3)
@ -136,12 +142,10 @@ func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
h.SetScriptHash(cp.containerContract) h.SetScriptHash(cp.containerContract)
if cp.notaryDisabled { // container put
// container put h.SetType(event.TypeFromString(putNotification))
h.SetType(event.TypeFromString(putNotification)) h.SetHandler(cp.handlePut)
h.SetHandler(cp.handlePut) handlers = append(handlers, h)
handlers = append(handlers, h)
}
// container delete // container delete
h.SetType(event.TypeFromString(deleteNotification)) h.SetType(event.TypeFromString(deleteNotification))
@ -158,26 +162,50 @@ func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
// ListenerNotaryParsers for the 'event.Listener' notary event producer. // ListenerNotaryParsers for the 'event.Listener' notary event producer.
func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { 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.SetMempoolType(mempoolevent.TransactionAdded)
p.SetRequestType(containerEvent.PutNotaryEvent)
p.SetScriptHash(cp.containerContract) 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. // ListenerNotaryHandlers for the 'event.Listener' notary event producer.
func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { 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.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. // TimersHandlers for the 'Timers' event producer.

View file

@ -3,6 +3,7 @@ package container
import ( import (
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "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/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
@ -13,6 +14,10 @@ type Delete struct {
containerID []byte containerID []byte
signature []byte signature []byte
token []byte token []byte
// For notary notifications only.
// Contains raw transactions of notary request.
notaryRequest *payload.P2PNotaryRequest
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
@ -30,6 +35,14 @@ func (d Delete) SessionToken() []byte {
return d.token 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. // ParseDelete from notification into container event structure.
// //
// Expects 3 stack items. // Expects 3 stack items.
@ -39,10 +52,8 @@ func ParseDelete(params []stackitem.Item) (event.Event, error) {
err error err error
) )
const expectedItemNumEACL = 3 if ln := len(params); ln != expectedItemNumDelete {
return nil, event.WrongNumberOfParameters(expectedItemNumDelete, ln)
if ln := len(params); ln != expectedItemNumEACL {
return nil, event.WrongNumberOfParameters(expectedItemNumEACL, ln)
} }
// parse container // parse container

View file

@ -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
}

View file

@ -1,8 +1,6 @@
package container package container
import ( import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "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 // order on stack is reversed
(*Put).setToken, (*Put).setToken,
(*Put).setPublicKey, (*Put).setPublicKey,
@ -46,8 +44,6 @@ const (
PutNotaryEvent = "put" PutNotaryEvent = "put"
) )
var errUnexpectedArgumentAmount = fmt.Errorf("unexpected arguments amount in %s call", PutNotaryEvent)
// ParsePutNotary from NotaryEvent into container event structure. // ParsePutNotary from NotaryEvent into container event structure.
func ParsePutNotary(ne event.NotaryEvent) (event.Event, error) { func ParsePutNotary(ne event.NotaryEvent) (event.Event, error) {
var ( var (
@ -63,10 +59,10 @@ func ParsePutNotary(ne event.NotaryEvent) (event.Event, error) {
switch { switch {
case opcode.PUSHDATA1 <= currentOp && currentOp <= opcode.PUSHDATA4: case opcode.PUSHDATA1 <= currentOp && currentOp <= opcode.PUSHDATA4:
if fieldNum == expectedItemNumPut { if fieldNum == expectedItemNumPut {
return nil, errUnexpectedArgumentAmount return nil, event.UnexpectedArgNumErr(PutNotaryEvent)
} }
fieldSetters[fieldNum](&ev, op.Param()) putFieldSetters[fieldNum](&ev, op.Param())
fieldNum++ fieldNum++
case opcode.PUSH0 <= currentOp && currentOp <= opcode.PUSH16 || currentOp == opcode.PACK: case opcode.PUSH0 <= currentOp && currentOp <= opcode.PUSH16 || currentOp == opcode.PACK:
// array packing opcodes. do nothing with it // array packing opcodes. do nothing with it

View file

@ -43,6 +43,12 @@ func NotaryTypeFromString(str string) NotaryType {
return NotaryType(str) 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 // UnexpectedOpcode returns error when notary parsers
// get unexpected opcode in contract call. // get unexpected opcode in contract call.
func UnexpectedOpcode(method string, op opcode.Opcode) error { func UnexpectedOpcode(method string, op opcode.Opcode) error {