2019-06-07 22:02:36 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package audit
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-09-11 23:37:01 +01:00
|
|
|
"math/rand"
|
2019-06-07 22:02:36 +01:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/vivint/infectious"
|
2019-06-13 13:46:08 +01:00
|
|
|
|
2019-12-27 11:48:47 +00:00
|
|
|
"storj.io/common/pkcrypto"
|
|
|
|
"storj.io/common/storj"
|
|
|
|
"storj.io/common/testrand"
|
2021-04-21 13:42:57 +01:00
|
|
|
"storj.io/storj/satellite/metabase"
|
2019-06-07 22:02:36 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestFailingAudit(t *testing.T) {
|
|
|
|
const (
|
|
|
|
required = 8
|
|
|
|
total = 14
|
|
|
|
)
|
|
|
|
|
|
|
|
f, err := infectious.NewFEC(required, total)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
shares := make([]infectious.Share, total)
|
|
|
|
output := func(s infectious.Share) {
|
|
|
|
shares[s.Number] = s.DeepCopy()
|
|
|
|
}
|
|
|
|
|
|
|
|
// the data to encode must be padded to a multiple of required, hence the
|
|
|
|
// underscores.
|
|
|
|
err = f.Encode([]byte("hello, world! __"), output)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
modifiedShares := make([]infectious.Share, len(shares))
|
|
|
|
for i := range shares {
|
|
|
|
modifiedShares[i] = shares[i].DeepCopy()
|
|
|
|
}
|
|
|
|
|
|
|
|
modifiedShares[0].Data[1] = '!'
|
|
|
|
modifiedShares[2].Data[0] = '#'
|
|
|
|
modifiedShares[3].Data[1] = '!'
|
|
|
|
modifiedShares[4].Data[0] = 'b'
|
|
|
|
|
|
|
|
badPieceNums := []int{0, 2, 3, 4}
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
auditPkgShares := make(map[int]Share, len(modifiedShares))
|
|
|
|
for i := range modifiedShares {
|
|
|
|
auditPkgShares[modifiedShares[i].Number] = Share{
|
|
|
|
PieceNum: modifiedShares[i].Number,
|
|
|
|
Data: append([]byte(nil), modifiedShares[i].Data...),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pieceNums, correctedShares, err := auditShares(ctx, 8, 14, auditPkgShares)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, num := range pieceNums {
|
|
|
|
if num != badPieceNums[i] {
|
|
|
|
t.Fatal("expected nums in pieceNums to be same as in badPieceNums")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.Equal(t, shares, correctedShares)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNotEnoughShares(t *testing.T) {
|
|
|
|
const (
|
|
|
|
required = 8
|
|
|
|
total = 14
|
|
|
|
)
|
|
|
|
|
|
|
|
f, err := infectious.NewFEC(required, total)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
shares := make([]infectious.Share, total)
|
|
|
|
output := func(s infectious.Share) {
|
|
|
|
shares[s.Number] = s.DeepCopy()
|
|
|
|
}
|
|
|
|
|
|
|
|
// the data to encode must be padded to a multiple of required, hence the
|
|
|
|
// underscores.
|
|
|
|
err = f.Encode([]byte("hello, world! __"), output)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
auditPkgShares := make(map[int]Share, len(shares))
|
|
|
|
for i := range shares {
|
|
|
|
auditPkgShares[shares[i].Number] = Share{
|
|
|
|
PieceNum: shares[i].Number,
|
|
|
|
Data: append([]byte(nil), shares[i].Data...),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_, _, err = auditShares(ctx, 20, 40, auditPkgShares)
|
2019-07-25 16:01:44 +01:00
|
|
|
require.NotNil(t, err)
|
2020-06-05 17:39:01 +01:00
|
|
|
require.Contains(t, err.Error(), "must specify at least the number of required shares")
|
2019-06-07 22:02:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreatePendingAudits(t *testing.T) {
|
|
|
|
const (
|
|
|
|
required = 8
|
|
|
|
total = 14
|
|
|
|
)
|
|
|
|
|
|
|
|
f, err := infectious.NewFEC(required, total)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
shares := make([]infectious.Share, total)
|
|
|
|
output := func(s infectious.Share) {
|
|
|
|
shares[s.Number] = s.DeepCopy()
|
|
|
|
}
|
|
|
|
|
2019-09-11 23:37:01 +01:00
|
|
|
// The data to encode must be padded to a multiple of required, hence the
|
2019-06-07 22:02:36 +01:00
|
|
|
// underscores.
|
|
|
|
err = f.Encode([]byte("hello, world! __"), output)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
testNodeID := testrand.NodeID()
|
2019-06-07 22:02:36 +01:00
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
contained := make(map[int]storj.NodeID)
|
|
|
|
contained[1] = testNodeID
|
2019-09-11 23:37:01 +01:00
|
|
|
|
2020-12-14 12:54:22 +00:00
|
|
|
segment := testSegment("test")
|
|
|
|
segmentInfo := metabase.Segment{
|
|
|
|
StreamID: segment.StreamID,
|
|
|
|
RootPieceID: testrand.PieceID(),
|
|
|
|
Redundancy: storj.RedundancyScheme{
|
|
|
|
Algorithm: storj.ReedSolomon,
|
|
|
|
RequiredShares: required,
|
|
|
|
TotalShares: total,
|
|
|
|
ShareSize: int32(len(shares[0].Data)),
|
2019-06-07 22:02:36 +01:00
|
|
|
},
|
|
|
|
}
|
2020-12-14 12:54:22 +00:00
|
|
|
randomIndex := rand.Int31n(10)
|
2019-06-07 22:02:36 +01:00
|
|
|
|
2020-12-14 12:54:22 +00:00
|
|
|
pending, err := createPendingAudits(ctx, contained, shares, segment, segmentInfo, randomIndex)
|
2019-06-07 22:02:36 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(pending))
|
|
|
|
assert.Equal(t, testNodeID, pending[0].NodeID)
|
2020-12-14 12:54:22 +00:00
|
|
|
assert.Equal(t, segmentInfo.RootPieceID, pending[0].PieceID)
|
2019-09-11 23:37:01 +01:00
|
|
|
assert.Equal(t, randomIndex, pending[0].StripeIndex)
|
2020-12-14 12:54:22 +00:00
|
|
|
assert.Equal(t, segmentInfo.Redundancy.ShareSize, pending[0].ShareSize)
|
2019-06-07 22:02:36 +01:00
|
|
|
assert.Equal(t, pkcrypto.SHA256Hash(shares[1].Data), pending[0].ExpectedShareHash)
|
|
|
|
assert.EqualValues(t, 0, pending[0].ReverifyCount)
|
|
|
|
}
|