[#58] core/object: Add content validation to FormatValidator

Add content validation step to FormatValidator. Check tombstone payload
correctness.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
remotes/KirillovDenis/release/v0.21.1
Leonard Lyubich 2020-09-30 14:07:28 +03:00 committed by Alex Vanin
parent 017afbf0e3
commit 107f3097e4
2 changed files with 73 additions and 11 deletions

View File

@ -35,6 +35,10 @@ func (v *FormatValidator) Validate(obj *Object) error {
return errNilCID
}
if err := v.validateContent(obj.GetType(), obj.GetPayload()); err != nil {
return errors.Wrapf(err, "(%T) incorrect content", v)
}
if err := v.validateSignatureKey(obj); err != nil {
return errors.Wrapf(err, "(%T) could not validate signature key", v)
}
@ -83,3 +87,23 @@ func (v *FormatValidator) checkOwnerKey(id *owner.ID, key []byte) error {
return nil
}
func (v *FormatValidator) validateContent(t object.Type, payload []byte) error {
switch t {
case object.TypeTombstone:
if len(payload) == 0 {
return errors.Errorf("(%T) empty payload in tombstone", v)
}
addr, err := object.AddressFromBytes(payload)
if err != nil {
return errors.Wrapf(err, "(%T) could not parse object address from tombstone", v)
}
if addr.GetContainerID() == nil || addr.GetObjectID() == nil {
return errors.Errorf("(%T) empty address reference in tombstone", v)
}
}
return nil
}

View File

@ -1,6 +1,7 @@
package object
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/sha256"
"testing"
@ -38,9 +39,25 @@ func testObjectID(t *testing.T) *object.ID {
return id
}
func blankValidObject(t *testing.T, key *ecdsa.PrivateKey) *RawObject {
wallet, err := owner.NEO3WalletFromPublicKey(&key.PublicKey)
require.NoError(t, err)
ownerID := owner.NewID()
ownerID.SetNeo3Wallet(wallet)
obj := NewRaw()
obj.SetContainerID(testContainerID(t))
obj.SetOwnerID(ownerID)
return obj
}
func TestFormatValidator_Validate(t *testing.T) {
v := NewFormatValidator()
ownerKey := test.DecodeKey(-1)
t.Run("nil input", func(t *testing.T) {
require.Error(t, v.Validate(nil))
})
@ -67,32 +84,53 @@ func TestFormatValidator_Validate(t *testing.T) {
})
t.Run("correct w/ session token", func(t *testing.T) {
sessionKey := test.DecodeKey(-1)
tok := token.NewSessionToken()
tok.SetSessionKey(crypto.MarshalPublicKey(&sessionKey.PublicKey))
tok.SetSessionKey(crypto.MarshalPublicKey(&ownerKey.PublicKey))
obj := NewRaw()
obj.SetContainerID(testContainerID(t))
obj.SetSessionToken(tok)
require.NoError(t, object.SetIDWithSignature(sessionKey, obj.SDK()))
require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
require.NoError(t, v.Validate(obj.Object()))
})
t.Run("correct w/o session token", func(t *testing.T) {
ownerKey := test.DecodeKey(-1)
obj := blankValidObject(t, ownerKey)
wallet, err := owner.NEO3WalletFromPublicKey(&ownerKey.PublicKey)
require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
require.NoError(t, v.Validate(obj.Object()))
})
t.Run("tombstone content", func(t *testing.T) {
obj := blankValidObject(t, ownerKey)
obj.SetType(object.TypeTombstone)
require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
require.Error(t, v.Validate(obj.Object()))
addr := object.NewAddress()
data, err := addr.ToV2().StableMarshal(nil)
require.NoError(t, err)
ownerID := owner.NewID()
ownerID.SetNeo3Wallet(wallet)
obj.SetPayload(data)
obj := NewRaw()
obj.SetContainerID(testContainerID(t))
obj.SetOwnerID(ownerID)
require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
require.Error(t, v.Validate(obj.Object()))
addr.SetContainerID(testContainerID(t))
addr.SetObjectID(testObjectID(t))
data, err = addr.ToV2().StableMarshal(nil)
require.NoError(t, err)
obj.SetPayload(data)
require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))