99640225fd
The old paths.Path type is now replaced with the new storj.Path. storj.Path is simply an alias to the built-in string type. As such it can be used just as any string, which simplifies a lot working with paths. No more conversions paths.New and path.String(). As an alias storj.Path does not define any methods. However, any functions applying to strings (like those from the strings package) gracefully apply to storj.Path too. In addition we have a few more functions defined: storj.SplitPath storj.JoinPaths encryption.EncryptPath encryption.DecryptPath encryption.DerivePathKey encryption.DeriveContentKey All code in master is migrated to the new storj.Path type. The Path example is also updated and is good for reference: /pkg/encryption/examples_test.go This PR also resolve a nonce misuse issue in path encryption: https://storjlabs.atlassian.net/browse/V3-545
123 lines
2.9 KiB
Go
123 lines
2.9 KiB
Go
// Copyright (C) 2018 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package audit
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"math/big"
|
|
"sync"
|
|
|
|
"github.com/vivint/infectious"
|
|
|
|
"storj.io/storj/pkg/eestream"
|
|
"storj.io/storj/pkg/pb"
|
|
"storj.io/storj/pkg/pointerdb/pdbclient"
|
|
"storj.io/storj/pkg/storage/meta"
|
|
"storj.io/storj/pkg/storj"
|
|
)
|
|
|
|
// Stripe keeps track of a stripe's index and its parent segment
|
|
type Stripe struct {
|
|
Index int
|
|
Segment *pb.Pointer
|
|
}
|
|
|
|
// Cursor keeps track of audit location in pointer db
|
|
type Cursor struct {
|
|
pointers pdbclient.Client
|
|
lastPath storj.Path
|
|
mutex sync.Mutex
|
|
}
|
|
|
|
// NewCursor creates a Cursor which iterates over pointer db
|
|
func NewCursor(pointers pdbclient.Client) *Cursor {
|
|
return &Cursor{pointers: pointers}
|
|
}
|
|
|
|
// NextStripe returns a random stripe to be audited
|
|
func (cursor *Cursor) NextStripe(ctx context.Context) (stripe *Stripe, err error) {
|
|
cursor.mutex.Lock()
|
|
defer cursor.mutex.Unlock()
|
|
|
|
var pointerItems []pdbclient.ListItem
|
|
var path storj.Path
|
|
var more bool
|
|
|
|
if cursor.lastPath == "" {
|
|
pointerItems, more, err = cursor.pointers.List(ctx, "", "", "", true, 0, meta.None)
|
|
} else {
|
|
pointerItems, more, err = cursor.pointers.List(ctx, "", cursor.lastPath, "", true, 0, meta.None)
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// get random pointer
|
|
pointerItem, err := getRandomPointer(pointerItems)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// get path
|
|
path = pointerItem.Path
|
|
|
|
// keep track of last path listed
|
|
if !more {
|
|
cursor.lastPath = ""
|
|
} else {
|
|
cursor.lastPath = pointerItems[len(pointerItems)-1].Path
|
|
}
|
|
|
|
// get pointer info
|
|
pointer, err := cursor.pointers.Get(ctx, path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// create the erasure scheme so we can get the stripe size
|
|
es, err := makeErasureScheme(pointer.GetRemote().GetRedundancy())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
//get random stripe
|
|
index, err := getRandomStripe(es, pointer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Stripe{Index: index, Segment: pointer}, nil
|
|
}
|
|
|
|
// create the erasure scheme
|
|
func makeErasureScheme(rs *pb.RedundancyScheme) (eestream.ErasureScheme, error) {
|
|
fc, err := infectious.NewFEC(int(rs.GetMinReq()), int(rs.GetTotal()))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
es := eestream.NewRSScheme(fc, int(rs.GetErasureShareSize()))
|
|
return es, nil
|
|
}
|
|
|
|
func getRandomStripe(es eestream.ErasureScheme, pointer *pb.Pointer) (index int, err error) {
|
|
stripeSize := es.StripeSize()
|
|
randomStripeIndex, err := rand.Int(rand.Reader, big.NewInt(pointer.GetSize()/int64(stripeSize)))
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
return int(randomStripeIndex.Int64()), nil
|
|
}
|
|
|
|
func getRandomPointer(pointerItems []pdbclient.ListItem) (pointer pdbclient.ListItem, err error) {
|
|
randomNum, err := rand.Int(rand.Reader, big.NewInt(int64(len(pointerItems))))
|
|
if err != nil {
|
|
return pdbclient.ListItem{}, err
|
|
}
|
|
randomNumInt64 := randomNum.Int64()
|
|
pointerItem := pointerItems[randomNumInt64]
|
|
return pointerItem, nil
|
|
}
|