storj/pkg/bwagreement/test/server_test.go
2019-01-10 20:31:47 -07:00

167 lines
6.6 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package test
import (
"context"
"crypto/ecdsa"
"testing"
//"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"storj.io/storj/internal/testcontext"
"storj.io/storj/internal/testidentity"
"storj.io/storj/internal/teststorj"
"storj.io/storj/pkg/bwagreement"
"storj.io/storj/pkg/pb"
"storj.io/storj/satellite"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
)
func TestSameSerialNumberBandwidthAgreements(t *testing.T) {
satellitedbtest.Run(t, func(t *testing.T, db satellite.DB) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
/* More than one storage node can submit bwagreements with the same serial number.
Uplink would like to download a file from 2 storage nodes.
Uplink requests a PayerBandwidthAllocation from the satellite. One serial number for all storage nodes.
Uplink signes 2 RenterBandwidthAllocation for both storage node. */
satellitePubKey, satellitePrivKey, uplinkPrivKey := generateKeys(ctx, t)
server := bwagreement.NewServer(db.BandwidthAgreement(), zap.NewNop(), satellitePubKey)
pbaFile1, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, false)
assert.NoError(t, err)
rbaNode1, err := GenerateRenterBandwidthAllocation(pbaFile1, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
assert.NoError(t, err)
rbaNode2, err := GenerateRenterBandwidthAllocation(pbaFile1, teststorj.NodeIDFromString("Storage node 2"), uplinkPrivKey)
assert.NoError(t, err)
reply, err := server.BandwidthAgreements(ctx, rbaNode1)
assert.NoError(t, err)
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
reply, err = server.BandwidthAgreements(ctx, rbaNode2)
assert.NoError(t, err)
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
/* Storage node can submit a second bwagreement with a different sequence value.
Uplink downloads another file. New PayerBandwidthAllocation with a new sequence. */
pbaFile2, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, false)
assert.NoError(t, err)
rbaNode1, err = GenerateRenterBandwidthAllocation(pbaFile2, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
assert.NoError(t, err)
reply, err = server.BandwidthAgreements(ctx, rbaNode1)
assert.NoError(t, err)
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
/* Storage nodes can't submit a second bwagreement with the same sequence. */
rbaNode1, err = GenerateRenterBandwidthAllocation(pbaFile1, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
assert.NoError(t, err)
reply, err = server.BandwidthAgreements(ctx, rbaNode1)
assert.EqualError(t, err, "bwagreement error: SerialNumber already exists in the PayerBandwidthAllocation")
assert.Equal(t, pb.AgreementsSummary_FAIL, reply.Status)
/* Storage nodes can't submit the same bwagreement twice.
This test is kind of duplicate cause it will most likely trigger the same sequence error.
For safety we will try it anyway to make sure nothing strange will happen */
reply, err = server.BandwidthAgreements(ctx, rbaNode2)
assert.EqualError(t, err, "bwagreement error: SerialNumber already exists in the PayerBandwidthAllocation")
assert.Equal(t, pb.AgreementsSummary_FAIL, reply.Status)
})
}
func TestManipulatedBandwidthAgreements(t *testing.T) {
satellitedbtest.Run(t, func(t *testing.T, db satellite.DB) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
satellitePubKey, satellitePrivKey, uplinkPrivKey := generateKeys(ctx, t)
server := bwagreement.NewServer(db.BandwidthAgreement(), zap.NewNop(), satellitePubKey)
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, false)
assert.NoError(t, err)
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
assert.NoError(t, err)
// Make sure the bwagreement we are using as blueprint is valid and avoid false positives that way.
reply, err := server.BandwidthAgreements(ctx, rba)
assert.NoError(t, err)
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
// storage nodes can't submit an expired bwagreement
expPBA, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, true)
assert.NoError(t, err)
rba, err = GenerateRenterBandwidthAllocation(expPBA, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
assert.NoError(t, err)
reply, err = server.BandwidthAgreements(ctx, rba)
assert.Error(t, err)
assert.Equal(t, pb.AgreementsSummary_FAIL, reply.Status)
/* Todo: Add more tests for bwagreement manipulations
/* copy and unmarshal pba and rba to manipulate it without overwriting it */
/* manipulate PayerBandwidthAllocation -> invalid signature */
/* self signed. Storage node sends a self signed bwagreement to get a higher payout */
})
}
func TestInvalidBandwidthAgreements(t *testing.T) {
satellitedbtest.Run(t, func(t *testing.T, db satellite.DB) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
satellitePubKey, satellitePrivKey, uplinkPrivKey := generateKeys(ctx, t)
server := bwagreement.NewServer(db.BandwidthAgreement(), zap.NewNop(), satellitePubKey)
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, false)
assert.NoError(t, err)
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
assert.NoError(t, err)
/* Make sure the bwagreement we are using as bluleprint is valid and avoid false positives that way. */
reply, err := server.BandwidthAgreements(ctx, rba)
assert.NoError(t, err)
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
/* Storage node sends an corrupted signuature to force a satellite crash */
rba.Signature = []byte("invalid")
reply, err = server.BandwidthAgreements(ctx, rba)
assert.EqualError(t, err, "bwagreement error: Invalid Renter's Signature Length")
assert.Equal(t, pb.AgreementsSummary_FAIL, reply.Status)
})
}
func generateKeys(ctx context.Context, t *testing.T) (satellitePubKey *ecdsa.PublicKey, satellitePrivKey *ecdsa.PrivateKey, uplinkPrivKey *ecdsa.PrivateKey) {
fiS, err := testidentity.NewTestIdentity(ctx)
assert.NoError(t, err)
satellitePubKey, ok := fiS.Leaf.PublicKey.(*ecdsa.PublicKey)
assert.True(t, ok)
satellitePrivKey, ok = fiS.Key.(*ecdsa.PrivateKey)
assert.True(t, ok)
fiU, err := testidentity.NewTestIdentity(ctx)
assert.NoError(t, err)
uplinkPrivKey, ok = fiU.Key.(*ecdsa.PrivateKey)
assert.True(t, ok)
return
}