From b9d30d613831de5f06bea5ef9a415c9ba719ce6d Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 11 May 2020 11:59:39 +0300 Subject: [PATCH] accounting: implement SignedDataSource on BalanceRequest message --- accounting/sign.go | 33 ++++++++++++++++++++++++ accounting/sign_test.go | 54 ++++++++++++++++++++++++++++++++++++++++ accounting/types.go | 10 ++++++++ accounting/types_test.go | 9 +++++++ 4 files changed, 106 insertions(+) create mode 100644 accounting/sign.go create mode 100644 accounting/sign_test.go diff --git a/accounting/sign.go b/accounting/sign.go new file mode 100644 index 0000000..a42375f --- /dev/null +++ b/accounting/sign.go @@ -0,0 +1,33 @@ +package accounting + +import "io" + +// SignedData returns payload bytes of the request. +func (m BalanceRequest) SignedData() ([]byte, error) { + data := make([]byte, m.SignedDataSize()) + + if _, err := m.ReadSignedData(data); err != nil { + return nil, err + } + + return data, nil +} + +// SignedDataSize returns payload size of the request. +func (m BalanceRequest) SignedDataSize() int { + return m.GetOwnerID().Size() +} + +// ReadSignedData copies payload bytes to passed buffer. +// +// If the buffer size is insufficient, io.ErrUnexpectedEOF returns. +func (m BalanceRequest) ReadSignedData(p []byte) (int, error) { + sz := m.SignedDataSize() + if len(p) < sz { + return 0, io.ErrUnexpectedEOF + } + + copy(p, m.GetOwnerID().Bytes()) + + return sz, nil +} diff --git a/accounting/sign_test.go b/accounting/sign_test.go new file mode 100644 index 0000000..03eaf6c --- /dev/null +++ b/accounting/sign_test.go @@ -0,0 +1,54 @@ +package accounting + +import ( + "testing" + + "github.com/nspcc-dev/neofs-api-go/service" + "github.com/nspcc-dev/neofs-crypto/test" + "github.com/stretchr/testify/require" +) + +func TestSignBalanceRequest(t *testing.T) { + // create test OwnerID + ownerID := OwnerID{1, 2, 3} + + // create test BalanceRequest + req := new(BalanceRequest) + req.SetOwnerID(ownerID) + + // create test private key + sk := test.DecodeKey(0) + + items := []struct { + corrupt func() + restore func() + }{ + { + corrupt: func() { + ownerID[0]++ + req.SetOwnerID(ownerID) + }, + restore: func() { + ownerID[0]-- + req.SetOwnerID(ownerID) + }, + }, + } + + for _, item := range items { + // sign with private key + require.NoError(t, service.AddSignatureWithKey(sk, req)) + + // ascertain that verification is passed + require.NoError(t, service.VerifyAccumulatedSignatures(req)) + + // corrupt the request + item.corrupt() + + // ascertain that verification is failed + require.Error(t, service.VerifyAccumulatedSignatures(req)) + + // ascertain that request + item.restore() + } +} diff --git a/accounting/types.go b/accounting/types.go index 6a3b2e2..3ac637d 100644 --- a/accounting/types.go +++ b/accounting/types.go @@ -351,3 +351,13 @@ func (m *Settlement) Equal(s *Settlement) bool { } return len(m.Transactions) == 0 || reflect.DeepEqual(m.Transactions, s.Transactions) } + +// GetOwnerID is an OwnerID field getter. +func (m BalanceRequest) GetOwnerID() OwnerID { + return m.OwnerID +} + +// SetOwnerID is an OwnerID field setter. +func (m *BalanceRequest) SetOwnerID(owner OwnerID) { + m.OwnerID = owner +} diff --git a/accounting/types_test.go b/accounting/types_test.go index df81b46..e89c08c 100644 --- a/accounting/types_test.go +++ b/accounting/types_test.go @@ -84,3 +84,12 @@ func TestCheque(t *testing.T) { require.Equal(t, cheque.Amount, decimal.NewGAS(42)) }) } + +func TestBalanceRequest_SetOwnerID(t *testing.T) { + ownerID := OwnerID{1, 2, 3} + m := new(BalanceRequest) + + m.SetOwnerID(ownerID) + + require.Equal(t, ownerID, m.GetOwnerID()) +}