This commit is contained in:
Evgeniy Kulikov 2019-11-18 16:34:06 +03:00
commit 1cf33e5ffd
No known key found for this signature in database
GPG key ID: BF6AEE0A2A699BF2
87 changed files with 29835 additions and 0 deletions

7
service/epoch.go Normal file
View file

@ -0,0 +1,7 @@
package service
// EpochRequest interface gives possibility to get or set epoch in RPC Requests.
type EpochRequest interface {
GetEpoch() uint64
SetEpoch(v uint64)
}

24
service/role.go Normal file
View file

@ -0,0 +1,24 @@
package service
// NodeRole to identify in Bootstrap service.
type NodeRole int32
const (
_ NodeRole = iota
// InnerRingNode that work like IR node.
InnerRingNode
// StorageNode that work like a storage node.
StorageNode
)
// String is method, that represent NodeRole as string.
func (nt NodeRole) String() string {
switch nt {
case InnerRingNode:
return "InnerRingNode"
case StorageNode:
return "StorageNode"
default:
return "Unknown"
}
}

22
service/role_test.go Normal file
View file

@ -0,0 +1,22 @@
package service
import (
"github.com/stretchr/testify/require"
"testing"
)
func TestNodeRole_String(t *testing.T) {
tests := []struct {
nt NodeRole
want string
}{
{want: "Unknown"},
{nt: StorageNode, want: "StorageNode"},
{nt: InnerRingNode, want: "InnerRingNode"},
}
for _, tt := range tests {
t.Run(tt.want, func(t *testing.T) {
require.Equal(t, tt.want, tt.nt.String())
})
}
}

47
service/sign.go Normal file
View file

@ -0,0 +1,47 @@
package service
import (
"crypto/ecdsa"
crypto "github.com/nspcc-dev/neofs-crypto"
"github.com/nspcc-dev/neofs-proto/internal"
"github.com/pkg/errors"
)
// ErrWrongSignature should be raised when wrong signature is passed into VerifyRequest.
const ErrWrongSignature = internal.Error("wrong signature")
// SignedRequest interface allows sign and verify requests.
type SignedRequest interface {
PrepareData() ([]byte, error)
GetSignature() []byte
SetSignature([]byte)
}
// SignRequest with passed private key.
func SignRequest(r SignedRequest, key *ecdsa.PrivateKey) error {
var signature []byte
if data, err := r.PrepareData(); err != nil {
return err
} else if signature, err = crypto.Sign(key, data); err != nil {
return errors.Wrap(err, "could not sign data")
}
r.SetSignature(signature)
return nil
}
// VerifyRequest by passed public keys.
func VerifyRequest(r SignedRequest, keys ...*ecdsa.PublicKey) bool {
data, err := r.PrepareData()
if err != nil {
return false
}
for i := range keys {
if err := crypto.Verify(keys[i], data, r.GetSignature()); err == nil {
return true
}
}
return false
}

45
service/ttl.go Normal file
View file

@ -0,0 +1,45 @@
package service
import (
"github.com/nspcc-dev/neofs-proto/internal"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// TTLRequest to verify and update ttl requests.
type TTLRequest interface {
GetTTL() uint32
SetTTL(uint32)
}
const (
// ZeroTTL is empty ttl, should produce ErrZeroTTL.
ZeroTTL = iota
// NonForwardingTTL is a ttl that allows direct connections only.
NonForwardingTTL
// SingleForwardingTTL is a ttl that allows connections through another node.
SingleForwardingTTL
// ErrZeroTTL is raised when zero ttl is passed.
ErrZeroTTL = internal.Error("zero ttl")
// ErrIncorrectTTL is raised when NonForwardingTTL is passed and NodeRole != InnerRingNode.
ErrIncorrectTTL = internal.Error("incorrect ttl")
)
// CheckTTLRequest validates and update ttl requests.
func CheckTTLRequest(req TTLRequest, role NodeRole) error {
var ttl = req.GetTTL()
if ttl == ZeroTTL {
return status.New(codes.InvalidArgument, ErrZeroTTL.Error()).Err()
} else if ttl == NonForwardingTTL && role != InnerRingNode {
return status.New(codes.InvalidArgument, ErrIncorrectTTL.Error()).Err()
}
req.SetTTL(ttl - 1)
return nil
}

72
service/ttl_test.go Normal file
View file

@ -0,0 +1,72 @@
package service
import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"testing"
)
type mockedRequest struct {
msg string
ttl uint32
name string
role NodeRole
code codes.Code
}
func (m *mockedRequest) SetTTL(v uint32) { m.ttl = v }
func (m mockedRequest) GetTTL() uint32 { return m.ttl }
func TestCheckTTLRequest(t *testing.T) {
tests := []mockedRequest{
{
ttl: NonForwardingTTL,
role: InnerRingNode,
name: "direct to ir node",
},
{
ttl: NonForwardingTTL,
role: StorageNode,
code: codes.InvalidArgument,
msg: ErrIncorrectTTL.Error(),
name: "direct to storage node",
},
{
ttl: ZeroTTL,
role: StorageNode,
msg: ErrZeroTTL.Error(),
code: codes.InvalidArgument,
name: "zero ttl",
},
{
ttl: SingleForwardingTTL,
role: InnerRingNode,
name: "default to ir node",
},
{
ttl: SingleForwardingTTL,
role: StorageNode,
name: "default to storage node",
},
}
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
before := tt.ttl
err := CheckTTLRequest(&tt, tt.role)
if tt.msg != "" {
require.Errorf(t, err, tt.msg)
state, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, state.Code(), tt.code)
require.Equal(t, state.Message(), tt.msg)
} else {
require.NoError(t, err)
require.NotEqualf(t, before, tt.ttl, "ttl should be changed: %d vs %d", before, tt.ttl)
}
})
}
}