forked from TrueCloudLab/frostfs-node
Initial commit
Initial public review release v0.10.0
This commit is contained in:
commit
dadfd90dcd
276 changed files with 46331 additions and 0 deletions
94
lib/core/storage.go
Normal file
94
lib/core/storage.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-node/internal"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
// BucketType is name of bucket
|
||||
BucketType string
|
||||
|
||||
// FilterHandler where you receive key/val in your closure
|
||||
FilterHandler func(key, val []byte) bool
|
||||
|
||||
// BucketItem used in filter
|
||||
BucketItem struct {
|
||||
Key []byte
|
||||
Val []byte
|
||||
}
|
||||
|
||||
// Bucket is sub-store interface
|
||||
Bucket interface {
|
||||
Get(key []byte) ([]byte, error)
|
||||
Set(key, value []byte) error
|
||||
Del(key []byte) error
|
||||
Has(key []byte) bool
|
||||
Size() int64
|
||||
List() ([][]byte, error)
|
||||
Iterate(FilterHandler) error
|
||||
// Steam can be implemented by badger.Stream, but not for now
|
||||
// Stream(ctx context.Context, key []byte, cb func(io.ReadWriter) error) error
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Storage component interface
|
||||
Storage interface {
|
||||
GetBucket(name BucketType) (Bucket, error)
|
||||
Size() int64
|
||||
Close() error
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// BlobStore is a blob bucket name.
|
||||
BlobStore BucketType = "blob"
|
||||
|
||||
// MetaStore is a meta bucket name.
|
||||
MetaStore BucketType = "meta"
|
||||
|
||||
// SpaceMetricsStore is a space metrics bucket name.
|
||||
SpaceMetricsStore BucketType = "space-metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNilFilterHandler when FilterHandler is empty
|
||||
ErrNilFilterHandler = errors.New("handler can't be nil")
|
||||
|
||||
// ErrNotFound is returned by key-value storage methods
|
||||
// that could not find element by key.
|
||||
ErrNotFound = internal.Error("key not found")
|
||||
)
|
||||
|
||||
// ErrIteratingAborted is returned by storage iterator
|
||||
// after iteration has been interrupted.
|
||||
var ErrIteratingAborted = errors.New("iteration aborted")
|
||||
|
||||
var errEmptyBucket = errors.New("empty bucket")
|
||||
|
||||
func (t BucketType) String() string { return string(t) }
|
||||
|
||||
// ListBucketItems performs iteration over Bucket and returns the full list of its items.
|
||||
func ListBucketItems(b Bucket, h FilterHandler) ([]BucketItem, error) {
|
||||
if b == nil {
|
||||
return nil, errEmptyBucket
|
||||
} else if h == nil {
|
||||
return nil, ErrNilFilterHandler
|
||||
}
|
||||
|
||||
items := make([]BucketItem, 0)
|
||||
|
||||
if err := b.Iterate(func(key, val []byte) bool {
|
||||
if h(key, val) {
|
||||
items = append(items, BucketItem{
|
||||
Key: key,
|
||||
Val: val,
|
||||
})
|
||||
}
|
||||
return true
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
65
lib/core/storage_test.go
Normal file
65
lib/core/storage_test.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type testBucket struct {
|
||||
Bucket
|
||||
|
||||
items []BucketItem
|
||||
}
|
||||
|
||||
func (s *testBucket) Iterate(f FilterHandler) error {
|
||||
for i := range s.items {
|
||||
if !f(s.items[i].Key, s.items[i].Val) {
|
||||
return ErrIteratingAborted
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestListBucketItems(t *testing.T) {
|
||||
_, err := ListBucketItems(nil, nil)
|
||||
require.EqualError(t, err, errEmptyBucket.Error())
|
||||
|
||||
b := new(testBucket)
|
||||
|
||||
_, err = ListBucketItems(b, nil)
|
||||
require.EqualError(t, err, ErrNilFilterHandler.Error())
|
||||
|
||||
var (
|
||||
count = 10
|
||||
ln = 10
|
||||
items = make([]BucketItem, 0, count)
|
||||
)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
items = append(items, BucketItem{
|
||||
Key: testData(t, ln),
|
||||
Val: testData(t, ln),
|
||||
})
|
||||
}
|
||||
|
||||
b.items = items
|
||||
|
||||
res, err := ListBucketItems(b, func(key, val []byte) bool { return true })
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, items, res)
|
||||
|
||||
res, err = ListBucketItems(b, func(key, val []byte) bool { return false })
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, res)
|
||||
}
|
||||
|
||||
func testData(t *testing.T, sz int) []byte {
|
||||
d := make([]byte, sz)
|
||||
_, err := rand.Read(d)
|
||||
require.NoError(t, err)
|
||||
|
||||
return d
|
||||
}
|
22
lib/core/validator.go
Normal file
22
lib/core/validator.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/service"
|
||||
"github.com/nspcc-dev/neofs-node/internal"
|
||||
)
|
||||
|
||||
// ErrMissingKeySignPairs is returned by functions that expect
|
||||
// a non-empty SignKeyPair slice, but received empty.
|
||||
const ErrMissingKeySignPairs = internal.Error("missing key-signature pairs")
|
||||
|
||||
// VerifyRequestWithSignatures checks if request has signatures and all of them are valid.
|
||||
//
|
||||
// Returns ErrMissingKeySignPairs if request does not have signatures.
|
||||
// Otherwise, behaves like service.VerifyRequestData.
|
||||
func VerifyRequestWithSignatures(req service.RequestVerifyData) error {
|
||||
if len(req.GetSignKeyPairs()) == 0 {
|
||||
return ErrMissingKeySignPairs
|
||||
}
|
||||
|
||||
return service.VerifyRequestData(req)
|
||||
}
|
69
lib/core/verify.go
Normal file
69
lib/core/verify.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/service"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/nspcc-dev/neofs-node/internal"
|
||||
)
|
||||
|
||||
// OwnerKeyContainer is an interface of the container of owner's ID and key pair with read access.
|
||||
type OwnerKeyContainer interface {
|
||||
GetOwnerID() refs.OwnerID
|
||||
GetOwnerKey() []byte
|
||||
}
|
||||
|
||||
// OwnerKeyVerifier is an interface of OwnerKeyContainer validator.
|
||||
type OwnerKeyVerifier interface {
|
||||
// Must check if OwnerKeyContainer satisfies a certain criterion.
|
||||
// Nil error is equivalent to matching the criterion.
|
||||
VerifyKey(context.Context, OwnerKeyContainer) error
|
||||
}
|
||||
|
||||
type neoKeyVerifier struct{}
|
||||
|
||||
// ErrNilOwnerKeyContainer is returned by functions that expect a non-nil
|
||||
// OwnerKeyContainer, but received nil.
|
||||
const ErrNilOwnerKeyContainer = internal.Error("owner-key container is nil")
|
||||
|
||||
// ErrNilOwnerKeyVerifier is returned by functions that expect a non-nil
|
||||
// OwnerKeyVerifier, but received nil.
|
||||
const ErrNilOwnerKeyVerifier = internal.Error("owner-key verifier is nil")
|
||||
|
||||
// NewNeoKeyVerifier creates a new Neo owner key verifier and return a OwnerKeyVerifier interface.
|
||||
func NewNeoKeyVerifier() OwnerKeyVerifier {
|
||||
return new(neoKeyVerifier)
|
||||
}
|
||||
|
||||
// VerifyKey checks if the public key converts to owner ID.
|
||||
//
|
||||
// If passed OwnerKeyContainer is nil, ErrNilOwnerKeyContainer returns.
|
||||
// If public key cannot be unmarshaled, service.ErrInvalidPublicKeyBytes returns.
|
||||
// If public key is not converted to owner ID, service.ErrWrongOwner returns.
|
||||
// With neo:morph adoption public key can be unrelated to owner ID. In this
|
||||
// case VerifyKey should call NeoFS.ID smart-contract to check whether public
|
||||
// key is bounded with owner ID. If there is no bound, then return
|
||||
// service.ErrWrongOwner.
|
||||
func (s neoKeyVerifier) VerifyKey(_ context.Context, src OwnerKeyContainer) error {
|
||||
if src == nil {
|
||||
return ErrNilOwnerKeyContainer
|
||||
}
|
||||
|
||||
pubKey := crypto.UnmarshalPublicKey(src.GetOwnerKey())
|
||||
if pubKey == nil {
|
||||
return service.ErrInvalidPublicKeyBytes
|
||||
}
|
||||
|
||||
ownerFromKey, err := refs.NewOwnerID(pubKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ownerFromKey.Equal(src.GetOwnerID()) {
|
||||
return service.ErrWrongOwner
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue