[#284] *: Return error from all ReadFromV2 methods

Return `error` from all `ReadFromV2` methods in order to support
backward compatibility if message will be extended with some formatted
field.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-07-07 13:51:05 +03:00 committed by LeL
parent 0d862d8568
commit 7d10b432d1
17 changed files with 133 additions and 60 deletions

View file

@ -13,11 +13,13 @@ import "github.com/nspcc-dev/neofs-api-go/v2/accounting"
// _ = Decimal(accounting.Decimal{}) // not recommended
type Decimal accounting.Decimal
// ReadFromV2 reads Decimal from the accounting.Decimal message.
// ReadFromV2 reads Decimal from the accounting.Decimal message. Checks if the
// message conforms to NeoFS API V2 protocol.
//
// See also WriteToV2.
func (d *Decimal) ReadFromV2(m accounting.Decimal) {
func (d *Decimal) ReadFromV2(m accounting.Decimal) error {
*d = Decimal(m)
return nil
}
// WriteToV2 writes Decimal to the accounting.Decimal message.

View file

@ -32,7 +32,7 @@ func TestDecimalMessageV2(t *testing.T) {
m.SetValue(7)
m.SetPrecision(8)
d.ReadFromV2(m)
require.NoError(t, d.ReadFromV2(m))
require.EqualValues(t, m.GetValue(), d.Value())
require.EqualValues(t, m.GetPrecision(), d.Precision())

View file

@ -279,10 +279,9 @@ func (b Token) VerifySignature() bool {
}
var sig neofscrypto.Signature
sig.ReadFromV2(b.sig)
// TODO: (#233) check owner<->key relation
return sig.Verify(b.signedData())
return sig.ReadFromV2(b.sig) == nil && sig.Verify(b.signedData())
}
// Marshal encodes Token into a binary format of the NeoFS API protocol

View file

@ -3,6 +3,7 @@ package checksum
import (
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
@ -35,11 +36,24 @@ const (
TZ
)
// ReadFromV2 reads Checksum from the refs.Checksum message.
// ReadFromV2 reads Checksum from the refs.Checksum message. Checks if the
// message conforms to NeoFS API V2 protocol.
//
// See also WriteToV2.
func (c *Checksum) ReadFromV2(m refs.Checksum) {
func (c *Checksum) ReadFromV2(m refs.Checksum) error {
if len(m.GetSum()) == 0 {
return errors.New("missing value")
}
switch m.GetType() {
default:
return fmt.Errorf("unsupported type %v", m.GetType())
case refs.SHA256, refs.TillichZemor:
}
*c = Checksum(m)
return nil
}
// WriteToV2 writes Checksum to the refs.Checksum message.

View file

@ -2,6 +2,8 @@ package client
import (
"context"
"errors"
"fmt"
v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
@ -94,12 +96,21 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
cc.result = func(r responseV2) {
resp := r.(*v2accounting.BalanceResponse)
if bal := resp.GetBody().GetBalance(); bal != nil {
var d accounting.Decimal
d.ReadFromV2(*bal)
res.setAmount(&d)
bal := resp.GetBody().GetBalance()
if bal == nil {
cc.err = errors.New("missing balance field")
return
}
var d accounting.Decimal
cc.err = d.ReadFromV2(*bal)
if cc.err != nil {
cc.err = fmt.Errorf("invalid balance: %w", cc.err)
return
}
res.setAmount(&d)
}
// process call

View file

@ -95,7 +95,11 @@ func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEnd
var ver version.Version
if v2ver := body.GetVersion(); v2ver != nil {
ver.ReadFromV2(*v2ver)
cc.err = ver.ReadFromV2(*v2ver)
if cc.err != nil {
cc.err = fmt.Errorf("invalid version: %w", cc.err)
return
}
}
res.setLatestVersion(&ver)

View file

@ -63,7 +63,7 @@ func TestContainer_Init(t *testing.T) {
require.NotNil(t, verV2)
var ver version.Version
ver.ReadFromV2(*verV2)
require.NoError(t, ver.ReadFromV2(*verV2))
require.Equal(t, version.Current(), ver)
@ -345,7 +345,7 @@ func TestCalculateSignature(t *testing.T) {
sig.WriteToV2(&msg)
var sig2 neofscrypto.Signature
sig2.ReadFromV2(msg)
require.NoError(t, sig2.ReadFromV2(msg))
require.True(t, container.VerifySignature(sig2, val))
}

View file

@ -39,7 +39,7 @@ func TestSignature(t *testing.T) {
s.WriteToV2(&m)
s.ReadFromV2(m)
require.NoError(t, s.ReadFromV2(m))
valid := s.Verify(data)
require.True(t, valid, "type %T", signer)

View file

@ -1,6 +1,7 @@
package neofscrypto
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
@ -16,11 +17,29 @@ import (
// _ = Signature(refs.Signature{}) // not recommended
type Signature refs.Signature
// ReadFromV2 reads Signature from the refs.Signature message.
// ReadFromV2 reads Signature from the refs.Signature message. Checks if the
// message conforms to NeoFS API V2 protocol.
//
// See also WriteToV2.
func (x *Signature) ReadFromV2(m refs.Signature) {
func (x *Signature) ReadFromV2(m refs.Signature) error {
if len(m.GetKey()) == 0 {
return errors.New("missing public key")
} else if len(m.GetSign()) == 0 {
return errors.New("missing signature")
}
switch m.GetScheme() {
default:
return fmt.Errorf("unsupported scheme %v", m.GetSign())
case
refs.ECDSA_SHA512,
refs.ECDSA_RFC6979_SHA256,
refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
}
*x = Signature(m)
return nil
}
// WriteToV2 writes Signature to the refs.Signature message.

View file

@ -127,9 +127,8 @@ func (o *Object) VerifyIDSignature() bool {
}
var sig neofscrypto.Signature
sig.ReadFromV2(*sigV2)
return sig.Verify(idV2.StableMarshal(nil))
return sig.ReadFromV2(*sigV2) == nil && sig.Verify(idV2.StableMarshal(nil))
}
// SetIDWithSignature sets object identifier and signature.

View file

@ -117,7 +117,7 @@ func (o *Object) Signature() *neofscrypto.Signature {
}
var sig neofscrypto.Signature
sig.ReadFromV2(*sigv2)
sig.ReadFromV2(*sigv2) // FIXME(@cthulhu-rider): #226 handle error
return &sig
}
@ -149,7 +149,7 @@ func (o *Object) SetPayload(v []byte) {
func (o *Object) Version() *version.Version {
var ver version.Version
if verV2 := (*object.Object)(o).GetHeader().GetVersion(); verV2 != nil {
ver.ReadFromV2(*verV2)
ver.ReadFromV2(*verV2) // FIXME(@cthulhu-rider): #226 handle error
}
return &ver
}
@ -248,7 +248,7 @@ func (o *Object) PayloadChecksum() (checksum.Checksum, bool) {
v2 := (*object.Object)(o)
if hash := v2.GetHeader().GetPayloadHash(); hash != nil {
v.ReadFromV2(*hash)
v.ReadFromV2(*hash) // FIXME(@cthulhu-rider): #226 handle error
return v, true
}
@ -278,7 +278,7 @@ func (o *Object) PayloadHomomorphicHash() (checksum.Checksum, bool) {
v2 := (*object.Object)(o)
if hash := v2.GetHeader().GetHomomorphicHash(); hash != nil {
v.ReadFromV2(*hash)
v.ReadFromV2(*hash) // FIXME(@cthulhu-rider): #226 handle error
return v, true
}

View file

@ -394,9 +394,8 @@ func (x GlobalTrust) VerifySignature() bool {
}
var sig neofscrypto.Signature
sig.ReadFromV2(*sigV2)
return sig.Verify(x.m.GetBody().StableMarshal(nil))
return sig.ReadFromV2(*sigV2) == nil && sig.Verify(x.m.GetBody().StableMarshal(nil))
}
// Marshal encodes GlobalTrust into a binary format of the NeoFS API protocol

View file

@ -178,10 +178,9 @@ func (x commonData) verifySignature(w contextWriter) bool {
}
var sig neofscrypto.Signature
sig.ReadFromV2(x.sig)
// TODO: (#233) check owner<->key relation
return sig.Verify(x.signedData(w))
return sig.ReadFromV2(x.sig) == nil && sig.Verify(x.signedData(w))
}
func (x commonData) marshal(w contextWriter) []byte {

View file

@ -210,7 +210,6 @@ func (x Container) VerifySessionDataSignature(data, signature []byte) bool {
sigV2.SetSign(signature)
var sig neofscrypto.Signature
sig.ReadFromV2(sigV2)
return sig.Verify(data)
return sig.ReadFromV2(sigV2) == nil && sig.Verify(data)
}

View file

@ -1,6 +1,7 @@
package storagegroup
import (
"errors"
"fmt"
"strconv"
@ -23,11 +24,55 @@ import (
// _ = StorageGroup(storagegroup.StorageGroup) // not recommended
type StorageGroup storagegroup.StorageGroup
// reads StorageGroup from the storagegroup.StorageGroup message. If checkFieldPresence is set,
// returns an error on absence of any protocol-required field.
func (sg *StorageGroup) readFromV2(m storagegroup.StorageGroup, checkFieldPresence bool) error {
var err error
h := m.GetValidationHash()
if h != nil {
err = new(checksum.Checksum).ReadFromV2(*h)
if err != nil {
return fmt.Errorf("invalid hash: %w", err)
}
} else if checkFieldPresence {
return errors.New("missing hash")
}
members := m.GetMembers()
if len(members) > 0 {
var member oid.ID
mMembers := make(map[oid.ID]struct{}, len(members))
var exits bool
for i := range members {
err = member.ReadFromV2(members[i])
if err != nil {
return fmt.Errorf("invalid member: %w", err)
}
_, exits = mMembers[member]
if exits {
return fmt.Errorf("duplicated member %s", member)
}
mMembers[member] = struct{}{}
}
} else if checkFieldPresence {
return errors.New("missing members")
}
*sg = StorageGroup(m)
return nil
}
// ReadFromV2 reads StorageGroup from the storagegroup.StorageGroup message.
// Checks if the message conforms to NeoFS API V2 protocol.
//
// See also WriteToV2.
func (sg *StorageGroup) ReadFromV2(m storagegroup.StorageGroup) {
*sg = StorageGroup(m)
func (sg *StorageGroup) ReadFromV2(m storagegroup.StorageGroup) error {
return sg.readFromV2(m, true)
}
// WriteToV2 writes StorageGroup to the storagegroup.StorageGroup message.
@ -68,7 +113,7 @@ func (sg *StorageGroup) SetValidationDataSize(epoch uint64) {
func (sg StorageGroup) ValidationDataHash() (v checksum.Checksum, isSet bool) {
v2 := (storagegroup.StorageGroup)(sg)
if checksumV2 := v2.GetValidationHash(); checksumV2 != nil {
v.ReadFromV2(*checksumV2)
v.ReadFromV2(*checksumV2) // FIXME(@cthulhu-rider): #226 handle error
isSet = true
}
@ -174,7 +219,7 @@ func (sg *StorageGroup) Unmarshal(data []byte) error {
return err
}
return formatCheck(v2)
return sg.readFromV2(*v2, false)
}
// MarshalJSON encodes StorageGroup to protobuf JSON format.
@ -195,20 +240,7 @@ func (sg *StorageGroup) UnmarshalJSON(data []byte) error {
return err
}
return formatCheck(v2)
}
func formatCheck(v2 *storagegroup.StorageGroup) error {
var oID oid.ID
for _, m := range v2.GetMembers() {
err := oID.ReadFromV2(m)
if err != nil {
return err
}
}
return nil
return sg.readFromV2(*v2, false)
}
// ReadFromObject assemble StorageGroup from a regular

View file

@ -49,13 +49,7 @@ func TestStorageGroup_ReadFromV2(t *testing.T) {
v2 storagegroupV2.StorageGroup
)
x.ReadFromV2(v2)
require.Zero(t, x.ExpirationEpoch())
require.Zero(t, x.ValidationDataSize())
_, set := x.ValidationDataHash()
require.False(t, set)
require.Zero(t, x.Members())
require.Error(t, x.ReadFromV2(v2))
})
t.Run("from non-zero", func(t *testing.T) {
@ -72,13 +66,13 @@ func TestStorageGroup_ReadFromV2(t *testing.T) {
mm := v2.GetMembers()
hashV2 := v2.GetValidationHash()
x.ReadFromV2(*v2)
require.NoError(t, x.ReadFromV2(*v2))
require.Equal(t, epoch, x.ExpirationEpoch())
require.Equal(t, size, x.ValidationDataSize())
var hash checksum.Checksum
hash.ReadFromV2(*hashV2)
require.NoError(t, hash.ReadFromV2(*hashV2))
h, set := x.ValidationDataHash()
require.True(t, set)
require.Equal(t, hash, h)
@ -143,7 +137,7 @@ func TestStorageGroup_WriteToV2(t *testing.T) {
require.Equal(t, x.ValidationDataSize(), v2.GetValidationDataSize())
var hash checksum.Checksum
hash.ReadFromV2(*v2.GetValidationHash())
require.NoError(t, hash.ReadFromV2(*v2.GetValidationHash()))
h, set := x.ValidationDataHash()
require.True(t, set)

View file

@ -55,11 +55,13 @@ func (v Version) WriteToV2(m *refs.Version) {
*m = (refs.Version)(v)
}
// ReadFromV2 reads Version from the refs.Version message.
// ReadFromV2 reads Version from the refs.Version message. Checks if the message
// conforms to NeoFS API V2 protocol.
//
// See also WriteToV2.
func (v *Version) ReadFromV2(m refs.Version) {
func (v *Version) ReadFromV2(m refs.Version) error {
*v = Version(m)
return nil
}
// String implements fmt.Stringer.