diff --git a/pkg/morph/event/container/put.go b/pkg/morph/event/container/put.go new file mode 100644 index 00000000..03fe3b69 --- /dev/null +++ b/pkg/morph/event/container/put.go @@ -0,0 +1,67 @@ +package container + +import ( + "crypto/elliptic" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neofs-node/pkg/morph/client" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" + "github.com/pkg/errors" +) + +// Put structure of container.Put notification from morph chain. +type Put struct { + rawContainer []byte + signature []byte + publicKey *keys.PublicKey +} + +// MorphEvent implements Neo:Morph Event interface. +func (Put) MorphEvent() {} + +// Container is a marshalled container structure, defined in API. +func (p Put) Container() []byte { return p.rawContainer } + +// Signature of marshalled container by container owner. +func (p Put) Signature() []byte { return p.signature } + +// PublicKey of container owner. +func (p Put) PublicKey() *keys.PublicKey { return p.publicKey } + +// ParsePut from notification into container event structure. +func ParsePut(params []smartcontract.Parameter) (event.Event, error) { + var ( + ev Put + err error + ) + + if ln := len(params); ln != 3 { + return nil, event.WrongNumberOfParameters(3, ln) + } + + // parse container + ev.rawContainer, err = client.BytesFromStackParameter(params[0]) + if err != nil { + return nil, errors.Wrap(err, "could not get container") + } + + // parse signature + ev.signature, err = client.BytesFromStackParameter(params[1]) + if err != nil { + return nil, errors.Wrap(err, "could not get signature") + } + + // parse public key + key, err := client.BytesFromStackParameter(params[2]) + if err != nil { + return nil, errors.Wrap(err, "could not get public key") + } + + ev.publicKey, err = keys.NewPublicKeyFromBytes(key, elliptic.P256()) + if err != nil { + return nil, errors.Wrap(err, "could not parse public key") + } + + return ev, nil +} diff --git a/pkg/morph/event/container/put_test.go b/pkg/morph/event/container/put_test.go new file mode 100644 index 00000000..f5d618b8 --- /dev/null +++ b/pkg/morph/event/container/put_test.go @@ -0,0 +1,100 @@ +package container + +import ( + "crypto/elliptic" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + crypto "github.com/nspcc-dev/neofs-crypto" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" + "github.com/nspcc-dev/neofs-node/pkg/util/test" + "github.com/stretchr/testify/require" +) + +func TestParsePut(t *testing.T) { + var ( + containerData = []byte("containerData") + signature = []byte("signature") + publicKey = &test.DecodeKey(-1).PublicKey + ) + + t.Run("wrong number of parameters", func(t *testing.T) { + prms := []smartcontract.Parameter{ + {}, + {}, + } + + _, err := ParsePut(prms) + require.EqualError(t, err, event.WrongNumberOfParameters(3, len(prms)).Error()) + }) + + t.Run("wrong container parameter", func(t *testing.T) { + _, err := ParsePut([]smartcontract.Parameter{ + { + Type: smartcontract.ArrayType, + }, + }) + + require.Error(t, err) + }) + + t.Run("wrong signature parameter", func(t *testing.T) { + _, err := ParsePut([]smartcontract.Parameter{ + { + Type: smartcontract.ByteArrayType, + Value: containerData, + }, + { + Type: smartcontract.ArrayType, + }, + }) + + require.Error(t, err) + }) + + t.Run("wrong key parameter", func(t *testing.T) { + _, err := ParsePut([]smartcontract.Parameter{ + { + Type: smartcontract.ByteArrayType, + Value: containerData, + }, + { + Type: smartcontract.ByteArrayType, + Value: signature, + }, + { + Type: smartcontract.ArrayType, + }, + }) + + require.Error(t, err) + }) + + t.Run("correct behavior", func(t *testing.T) { + ev, err := ParsePut([]smartcontract.Parameter{ + { + Type: smartcontract.ByteArrayType, + Value: containerData, + }, + { + Type: smartcontract.ByteArrayType, + Value: signature, + }, + { + Type: smartcontract.ByteArrayType, + Value: crypto.MarshalPublicKey(publicKey), + }, + }) + require.NoError(t, err) + + expectedKey, err := keys.NewPublicKeyFromBytes(crypto.MarshalPublicKey(publicKey), elliptic.P256()) + require.NoError(t, err) + + require.Equal(t, Put{ + rawContainer: containerData, + signature: signature, + publicKey: expectedKey, + }, ev) + }) +}