Make Bandwidth Agreements Secure / Trustable (#1117)
* Added cert chains and nodeid verification to bandwidth agreement
This commit is contained in:
parent
1385a2d6bd
commit
8ba4b61e59
@ -5,7 +5,6 @@ package tally_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -18,6 +17,7 @@ import (
|
||||
"storj.io/storj/pkg/accounting/tally"
|
||||
"storj.io/storj/pkg/bwagreement"
|
||||
"storj.io/storj/pkg/bwagreement/test"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/overlay/mocks"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/pointerdb"
|
||||
@ -65,25 +65,23 @@ func TestQueryWithBw(t *testing.T) {
|
||||
//get a private key
|
||||
fiC, err := testidentity.NewTestIdentity(ctx)
|
||||
assert.NoError(t, err)
|
||||
k, ok := fiC.Key.(*ecdsa.PrivateKey)
|
||||
assert.True(t, ok)
|
||||
|
||||
makeBWA(ctx, t, bwDb, "1", k, pb.PayerBandwidthAllocation_PUT)
|
||||
makeBWA(ctx, t, bwDb, "2", k, pb.PayerBandwidthAllocation_GET)
|
||||
makeBWA(ctx, t, bwDb, "3", k, pb.PayerBandwidthAllocation_GET_AUDIT)
|
||||
makeBWA(ctx, t, bwDb, "4", k, pb.PayerBandwidthAllocation_GET_REPAIR)
|
||||
makeBWA(ctx, t, bwDb, "5", k, pb.PayerBandwidthAllocation_PUT_REPAIR)
|
||||
makeBWA(ctx, t, bwDb, "1", fiC, pb.PayerBandwidthAllocation_PUT)
|
||||
makeBWA(ctx, t, bwDb, "2", fiC, pb.PayerBandwidthAllocation_GET)
|
||||
makeBWA(ctx, t, bwDb, "3", fiC, pb.PayerBandwidthAllocation_GET_AUDIT)
|
||||
makeBWA(ctx, t, bwDb, "4", fiC, pb.PayerBandwidthAllocation_GET_REPAIR)
|
||||
makeBWA(ctx, t, bwDb, "5", fiC, pb.PayerBandwidthAllocation_PUT_REPAIR)
|
||||
|
||||
//check the db
|
||||
err = tally.QueryBW(ctx)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func makeBWA(ctx context.Context, t *testing.T, bwDb bwagreement.DB, serialNum string, k *ecdsa.PrivateKey, action pb.PayerBandwidthAllocation_Action) {
|
||||
func makeBWA(ctx context.Context, t *testing.T, bwDb bwagreement.DB, serialNum string, fiC *identity.FullIdentity, action pb.PayerBandwidthAllocation_Action) {
|
||||
//generate an agreement with the key
|
||||
pba, err := test.GeneratePayerBandwidthAllocation(action, k, k, time.Hour)
|
||||
pba, err := test.GeneratePayerBandwidthAllocation(action, fiC, fiC, time.Hour)
|
||||
assert.NoError(t, err)
|
||||
rba, err := test.GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("StorageNodeID"), k)
|
||||
rba, err := test.GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("StorageNodeID"), fiC, 666)
|
||||
assert.NoError(t, err)
|
||||
//save to db
|
||||
err = bwDb.CreateAgreement(ctx, serialNum, bwagreement.Agreement{Signature: rba.GetSignature(), Agreement: rba.GetData()})
|
||||
|
85
pkg/auth/signedMessage.go
Normal file
85
pkg/auth/signedMessage.go
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/gtank/cryptopasta"
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/peertls"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
var (
|
||||
//ECDSA indicates a key was not an ECDSA key
|
||||
ECDSA = errs.New("Key is not ecdsa key")
|
||||
//Sign indicates a failure during signing
|
||||
Sign = errs.Class("Failed to sign message")
|
||||
//Verify indicates a failure during signature validation
|
||||
Verify = errs.Class("Failed to validate message signature")
|
||||
//SigLen indicates an invalid signature length
|
||||
SigLen = errs.Class("Invalid signature length")
|
||||
//Serial indicates an invalid serial number length
|
||||
Serial = errs.Class("Invalid SerialNumber")
|
||||
//Expired indicates the agreement is expired
|
||||
Expired = errs.Class("Agreement is expired")
|
||||
//Signer indicates a public key / node id mismatch
|
||||
Signer = errs.Class("Message public key did not match expected signer")
|
||||
//BadID indicates a public key / node id mismatch
|
||||
BadID = errs.Class("Node ID did not match expected id")
|
||||
)
|
||||
|
||||
//VerifyMsg checks the crypto-related aspects of signed message
|
||||
func VerifyMsg(sm pb.SignedMsg, signer storj.NodeID) error {
|
||||
//no null fields
|
||||
if ok, err := pb.MsgComplete(sm); !ok {
|
||||
return err
|
||||
}
|
||||
certs := sm.GetCerts()
|
||||
if len(certs) < 2 {
|
||||
return Verify.New("Expected at least leaf and CA public keys")
|
||||
}
|
||||
//correct signature length
|
||||
err := peertls.VerifyPeerFunc(peertls.VerifyPeerCertChains)(certs, nil)
|
||||
if err != nil {
|
||||
return Verify.Wrap(err)
|
||||
}
|
||||
leafPubKey, err := parseECDSA(certs[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
caPubKey, err := parseECDSA(certs[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signatureLength := leafPubKey.Curve.Params().P.BitLen() / 8
|
||||
if len(sm.GetSignature()) < signatureLength {
|
||||
return SigLen.New("%s", sm.GetSignature())
|
||||
}
|
||||
// verify signature
|
||||
if id, err := identity.NodeIDFromECDSAKey(caPubKey); err != nil || id != signer {
|
||||
return Signer.New("%+v vs %+v", id, signer)
|
||||
}
|
||||
if ok := cryptopasta.Verify(sm.GetData(), sm.GetSignature(), leafPubKey); !ok {
|
||||
return Verify.New("%+v", ok)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseECDSA(rawCert []byte) (*ecdsa.PublicKey, error) {
|
||||
cert, err := x509.ParseCertificate(rawCert)
|
||||
if err != nil {
|
||||
return nil, Verify.Wrap(err)
|
||||
}
|
||||
ecdsa, ok := cert.PublicKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, ECDSA
|
||||
}
|
||||
return ecdsa, nil
|
||||
}
|
@ -5,19 +5,16 @@ package bwagreement
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/x509"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gtank/cryptopasta"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
monkit "gopkg.in/spacemonkeygo/monkit.v2"
|
||||
|
||||
"storj.io/storj/pkg/auth"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/peertls"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -44,7 +41,7 @@ type DB interface {
|
||||
// Server is an implementation of the pb.BandwidthServer interface
|
||||
type Server struct {
|
||||
db DB
|
||||
pkey crypto.PublicKey
|
||||
NodeID storj.NodeID
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
@ -57,129 +54,60 @@ type Agreement struct {
|
||||
}
|
||||
|
||||
// NewServer creates instance of Server
|
||||
func NewServer(db DB, logger *zap.Logger, pkey crypto.PublicKey) *Server {
|
||||
func NewServer(db DB, logger *zap.Logger, nodeID storj.NodeID) *Server {
|
||||
// TODO: reorder arguments, rename logger -> log
|
||||
return &Server{
|
||||
db: db,
|
||||
logger: logger,
|
||||
pkey: pkey,
|
||||
}
|
||||
return &Server{db: db, logger: logger, NodeID: nodeID}
|
||||
}
|
||||
|
||||
// Close closes resources
|
||||
func (s *Server) Close() error { return nil }
|
||||
|
||||
// BandwidthAgreements receives and stores bandwidth agreements from storage nodes
|
||||
func (s *Server) BandwidthAgreements(ctx context.Context, ba *pb.RenterBandwidthAllocation) (reply *pb.AgreementsSummary, err error) {
|
||||
func (s *Server) BandwidthAgreements(ctx context.Context, rba *pb.RenterBandwidthAllocation) (reply *pb.AgreementsSummary, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
s.logger.Debug("Received Agreement...")
|
||||
|
||||
reply = &pb.AgreementsSummary{
|
||||
Status: pb.AgreementsSummary_REJECTED,
|
||||
}
|
||||
|
||||
// storagenode signature is empty
|
||||
if len(ba.GetSignature()) == 0 {
|
||||
return reply, Error.New("Invalid Storage Node Signature length in the RenterBandwidthAllocation")
|
||||
}
|
||||
|
||||
rbad := &pb.RenterBandwidthAllocation_Data{}
|
||||
if err = proto.Unmarshal(ba.GetData(), rbad); err != nil {
|
||||
return reply, Error.New("Failed to unmarshal RenterBandwidthAllocation: %+v", err)
|
||||
}
|
||||
|
||||
pba := rbad.GetPayerAllocation()
|
||||
pbad := &pb.PayerBandwidthAllocation_Data{}
|
||||
if err := proto.Unmarshal(pba.GetData(), pbad); err != nil {
|
||||
return reply, Error.New("Failed to unmarshal PayerBandwidthAllocation: %+v", err)
|
||||
}
|
||||
|
||||
// satellite signature is empty
|
||||
if len(pba.GetSignature()) == 0 {
|
||||
return reply, Error.New("Invalid Satellite Signature length in the PayerBandwidthAllocation")
|
||||
}
|
||||
|
||||
if len(pbad.SerialNumber) == 0 {
|
||||
return reply, Error.New("Invalid SerialNumber in the PayerBandwidthAllocation")
|
||||
}
|
||||
|
||||
if err = s.verifySignature(ctx, ba); err != nil {
|
||||
rbad, pba, pbad, err := rba.Unpack()
|
||||
if err != nil {
|
||||
return reply, err
|
||||
}
|
||||
|
||||
//verify message content
|
||||
pi, err := identity.PeerIdentityFromContext(ctx)
|
||||
if err != nil || rbad.StorageNodeId != pi.ID {
|
||||
return reply, auth.BadID.New("Storage Node ID: %s vs %s", rbad.StorageNodeId, pi.ID)
|
||||
}
|
||||
//todo: use whitelist for uplinks?
|
||||
if pbad.SatelliteId != s.NodeID {
|
||||
return reply, pb.Payer.New("Satellite ID: %s vs %s", pbad.SatelliteId, s.NodeID)
|
||||
}
|
||||
serialNum := pbad.GetSerialNumber() + rbad.StorageNodeId.String()
|
||||
|
||||
// get and check expiration
|
||||
if len(pbad.SerialNumber) == 0 {
|
||||
return reply, pb.Payer.Wrap(pb.Missing.New("Serial"))
|
||||
}
|
||||
exp := time.Unix(pbad.GetExpirationUnixSec(), 0).UTC()
|
||||
if exp.Before(time.Now().UTC()) {
|
||||
return reply, Error.New("Bandwidth agreement is expired (%v)", exp)
|
||||
return reply, pb.Payer.Wrap(auth.Expired.New("%v vs %v", exp, time.Now().UTC()))
|
||||
}
|
||||
|
||||
//verify message crypto
|
||||
if err := auth.VerifyMsg(rba, pbad.UplinkId); err != nil {
|
||||
return reply, pb.Renter.Wrap(err)
|
||||
}
|
||||
if err := auth.VerifyMsg(pba, pbad.SatelliteId); err != nil {
|
||||
return reply, pb.Payer.Wrap(err)
|
||||
}
|
||||
//save and return rersults
|
||||
err = s.db.CreateAgreement(ctx, serialNum, Agreement{
|
||||
Signature: ba.GetSignature(),
|
||||
Agreement: ba.GetData(),
|
||||
Signature: rba.GetSignature(),
|
||||
Agreement: rba.GetData(),
|
||||
ExpiresAt: exp,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
//todo: better classify transport errors (AgreementsSummary_FAIL) vs logical (AgreementsSummary_REJECTED)
|
||||
return reply, Error.New("SerialNumber already exists in the PayerBandwidthAllocation")
|
||||
return reply, pb.Payer.Wrap(auth.Serial.Wrap(err))
|
||||
}
|
||||
|
||||
reply.Status = pb.AgreementsSummary_OK
|
||||
s.logger.Debug("Stored Agreement...")
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func (s *Server) verifySignature(ctx context.Context, ba *pb.RenterBandwidthAllocation) error {
|
||||
// TODO(security): detect replay attacks
|
||||
|
||||
//Deserealize RenterBandwidthAllocation.GetData() so we can get public key
|
||||
rbad := &pb.RenterBandwidthAllocation_Data{}
|
||||
if err := proto.Unmarshal(ba.GetData(), rbad); err != nil {
|
||||
return Error.New("Failed to unmarshal RenterBandwidthAllocation: %+v", err)
|
||||
}
|
||||
|
||||
pba := rbad.GetPayerAllocation()
|
||||
pbad := &pb.PayerBandwidthAllocation_Data{}
|
||||
if err := proto.Unmarshal(pba.GetData(), pbad); err != nil {
|
||||
return Error.New("Failed to unmarshal PayerBandwidthAllocation: %+v", err)
|
||||
}
|
||||
// Extract renter's public key from PayerBandwidthAllocation_Data
|
||||
pubkey, err := x509.ParsePKIXPublicKey(pbad.GetPubKey())
|
||||
if err != nil {
|
||||
return Error.New("Failed to extract Public Key from RenterBandwidthAllocation: %+v", err)
|
||||
}
|
||||
|
||||
// Typecast public key
|
||||
k, ok := pubkey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return peertls.ErrUnsupportedKey.New("%T", pubkey)
|
||||
}
|
||||
|
||||
signatureLength := k.Curve.Params().P.BitLen() / 8
|
||||
if len(ba.GetSignature()) < signatureLength {
|
||||
return Error.New("Invalid Renter's Signature Length")
|
||||
}
|
||||
// verify Renter's (uplink) signature
|
||||
if ok := cryptopasta.Verify(ba.GetData(), ba.GetSignature(), k); !ok {
|
||||
return Error.New("Failed to verify Renter's Signature")
|
||||
}
|
||||
|
||||
// satellite public key
|
||||
k, ok = s.pkey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return peertls.ErrUnsupportedKey.New("%T", s.pkey)
|
||||
}
|
||||
|
||||
signatureLength = k.Curve.Params().P.BitLen() / 8
|
||||
if len(rbad.GetPayerAllocation().GetSignature()) < signatureLength {
|
||||
return Error.New("Inavalid Payer's Signature Length")
|
||||
}
|
||||
// verify Payer's (satellite) signature
|
||||
if ok := cryptopasta.Verify(rbad.GetPayerAllocation().GetData(), rbad.GetPayerAllocation().GetSignature(), k); !ok {
|
||||
return Error.New("Failed to verify Payer's Signature")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -4,107 +4,76 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/x509"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gtank/cryptopasta"
|
||||
"github.com/skyrings/skyring-common/tools/uuid"
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/internal/teststorj"
|
||||
"storj.io/storj/pkg/auth"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
//GeneratePayerBandwidthAllocation creates a signed PayerBandwidthAllocation from a PayerBandwidthAllocation_Action
|
||||
func GeneratePayerBandwidthAllocation(action pb.PayerBandwidthAllocation_Action, satelliteKey crypto.PrivateKey, uplinkKey crypto.PrivateKey, expiration time.Duration) (*pb.PayerBandwidthAllocation, error) {
|
||||
satelliteKeyEcdsa, ok := satelliteKey.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errs.New("Satellite Private Key is not a valid *ecdsa.PrivateKey")
|
||||
}
|
||||
|
||||
pubbytes, err := getUplinkPubKey(uplinkKey)
|
||||
if err != nil {
|
||||
return nil, errs.New("Uplink Private Key is not a valid *ecdsa.PrivateKey")
|
||||
}
|
||||
|
||||
func GeneratePayerBandwidthAllocation(action pb.PayerBandwidthAllocation_Action, satID *identity.FullIdentity, upID *identity.FullIdentity, expiration time.Duration) (*pb.PayerBandwidthAllocation, error) {
|
||||
serialNum, err := uuid.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate PayerBandwidthAllocation_Data
|
||||
data, _ := proto.Marshal(
|
||||
&pb.PayerBandwidthAllocation_Data{
|
||||
SatelliteId: teststorj.NodeIDFromString("SatelliteID"),
|
||||
UplinkId: teststorj.NodeIDFromString("UplinkID"),
|
||||
SatelliteId: satID.ID,
|
||||
UplinkId: upID.ID,
|
||||
ExpirationUnixSec: time.Now().Add(expiration).Unix(),
|
||||
SerialNumber: serialNum.String(),
|
||||
Action: action,
|
||||
CreatedUnixSec: time.Now().Unix(),
|
||||
PubKey: pubbytes,
|
||||
},
|
||||
)
|
||||
|
||||
// Sign the PayerBandwidthAllocation_Data with the "Satellite" Private Key
|
||||
s, err := cryptopasta.Sign(data, satelliteKeyEcdsa)
|
||||
if err != nil {
|
||||
return nil, errs.New("Failed to sign PayerBandwidthAllocation_Data with satellite Private Key: %+v", err)
|
||||
satPrivECDSA, ok := satID.Key.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, pb.Payer.Wrap(auth.ECDSA)
|
||||
}
|
||||
s, err := cryptopasta.Sign(data, satPrivECDSA)
|
||||
if err != nil {
|
||||
return nil, pb.Payer.Wrap(auth.Sign.Wrap(err))
|
||||
}
|
||||
|
||||
// Combine Signature and Data for PayerBandwidthAllocation
|
||||
return &pb.PayerBandwidthAllocation{
|
||||
Data: data,
|
||||
Signature: s,
|
||||
Certs: satID.ChainRaw(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
//GenerateRenterBandwidthAllocation creates a signed RenterBandwidthAllocation from a PayerBandwidthAllocation
|
||||
func GenerateRenterBandwidthAllocation(pba *pb.PayerBandwidthAllocation, storageNodeID storj.NodeID, uplinkKey crypto.PrivateKey) (*pb.RenterBandwidthAllocation, error) {
|
||||
// get "Uplink" Public Key
|
||||
uplinkKeyEcdsa, ok := uplinkKey.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errs.New("Uplink Private Key is not a valid *ecdsa.PrivateKey")
|
||||
}
|
||||
|
||||
func GenerateRenterBandwidthAllocation(pba *pb.PayerBandwidthAllocation, storageNodeID storj.NodeID, upID *identity.FullIdentity, total int64) (*pb.RenterBandwidthAllocation, error) {
|
||||
// Generate RenterBandwidthAllocation_Data
|
||||
data, _ := proto.Marshal(
|
||||
&pb.RenterBandwidthAllocation_Data{
|
||||
PayerAllocation: pba,
|
||||
StorageNodeId: storageNodeID,
|
||||
Total: int64(666),
|
||||
Total: total,
|
||||
},
|
||||
)
|
||||
|
||||
// Sign the PayerBandwidthAllocation_Data with the "Uplink" Private Key
|
||||
s, err := cryptopasta.Sign(data, uplinkKeyEcdsa)
|
||||
if err != nil {
|
||||
return nil, errs.New("Failed to sign RenterBandwidthAllocation_Data with uplink Private Key: %+v", err)
|
||||
upPrivECDSA, ok := upID.Key.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, pb.Payer.Wrap(auth.ECDSA)
|
||||
}
|
||||
s, err := cryptopasta.Sign(data, upPrivECDSA)
|
||||
if err != nil {
|
||||
return nil, pb.Payer.Wrap(auth.Sign.Wrap(err))
|
||||
}
|
||||
|
||||
// Combine Signature and Data for RenterBandwidthAllocation
|
||||
return &pb.RenterBandwidthAllocation{
|
||||
Signature: s,
|
||||
Data: data,
|
||||
Certs: upID.ChainRaw(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// get uplink's public key
|
||||
func getUplinkPubKey(uplinkKey crypto.PrivateKey) ([]byte, error) {
|
||||
|
||||
// get "Uplink" Public Key
|
||||
uplinkKeyEcdsa, ok := uplinkKey.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errs.New("Uplink Private Key is not a valid *ecdsa.PrivateKey")
|
||||
}
|
||||
|
||||
pubbytes, err := x509.MarshalPKIXPublicKey(&uplinkKeyEcdsa.PublicKey)
|
||||
if err != nil {
|
||||
return nil, errs.New("Could not generate byte array from Uplink Public key: %+v", err)
|
||||
}
|
||||
|
||||
return pubbytes, nil
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -13,12 +16,16 @@ import (
|
||||
"github.com/gtank/cryptopasta"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/internal/testidentity"
|
||||
"storj.io/storj/internal/teststorj"
|
||||
"storj.io/storj/pkg/auth"
|
||||
"storj.io/storj/pkg/bwagreement"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/storj"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/satellitedb/satellitedbtest"
|
||||
)
|
||||
@ -32,18 +39,41 @@ func TestBandwidthAgreement(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func getPeerContext(ctx context.Context, t *testing.T) (context.Context, storj.NodeID) {
|
||||
ident, err := testidentity.NewTestIdentity(ctx)
|
||||
if !assert.NoError(t, err) || !assert.NotNil(t, ident) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
grpcPeer := &peer.Peer{
|
||||
Addr: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5},
|
||||
AuthInfo: credentials.TLSInfo{
|
||||
State: tls.ConnectionState{
|
||||
PeerCertificates: []*x509.Certificate{ident.Leaf, ident.CA},
|
||||
},
|
||||
},
|
||||
}
|
||||
nodeID, err := identity.NodeIDFromKey(ident.CA.PublicKey)
|
||||
assert.NoError(t, err)
|
||||
return peer.NewContext(ctx, grpcPeer), nodeID
|
||||
}
|
||||
|
||||
func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
satellitePubKey, satellitePrivKey, uplinkPrivKey := generateKeys(ctx, t)
|
||||
satellite := bwagreement.NewServer(bwdb, zap.NewNop(), satellitePubKey)
|
||||
upID, err := testidentity.NewTestIdentity(ctx)
|
||||
assert.NoError(t, err)
|
||||
satID, err := testidentity.NewTestIdentity(ctx)
|
||||
assert.NoError(t, err)
|
||||
satellite := bwagreement.NewServer(bwdb, zap.NewNop(), satID.ID)
|
||||
|
||||
{ // TestSameSerialNumberBandwidthAgreements
|
||||
pbaFile1, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, time.Hour)
|
||||
pbaFile1, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, time.Hour)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rbaNode1, err := GenerateRenterBandwidthAllocation(pbaFile1, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
ctxSN1, storageNode1 := getPeerContext(ctx, t)
|
||||
rbaNode1, err := GenerateRenterBandwidthAllocation(pbaFile1, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rbaNode2, err := GenerateRenterBandwidthAllocation(pbaFile1, teststorj.NodeIDFromString("Storage node 2"), uplinkPrivKey)
|
||||
ctxSN2, storageNode2 := getPeerContext(ctx, t)
|
||||
rbaNode2, err := GenerateRenterBandwidthAllocation(pbaFile1, storageNode2, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
/* More than one storage node can submit bwagreements with the same serial number.
|
||||
@ -51,11 +81,11 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
Uplink requests a PayerBandwidthAllocation from the satellite. One serial number for all storage nodes.
|
||||
Uplink signes 2 RenterBandwidthAllocation for both storage node. */
|
||||
{
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rbaNode1)
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, rbaNode1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
|
||||
|
||||
reply, err = satellite.BandwidthAgreements(ctx, rbaNode2)
|
||||
reply, err = satellite.BandwidthAgreements(ctxSN2, rbaNode2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
|
||||
}
|
||||
@ -63,24 +93,24 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
/* 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, time.Hour)
|
||||
pbaFile2, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, time.Hour)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rbaNode1, err := GenerateRenterBandwidthAllocation(pbaFile2, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
rbaNode1, err := GenerateRenterBandwidthAllocation(pbaFile2, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rbaNode1)
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, 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)
|
||||
rbaNode1, err := GenerateRenterBandwidthAllocation(pbaFile1, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rbaNode1)
|
||||
assert.EqualError(t, err, "bwagreement error: SerialNumber already exists in the PayerBandwidthAllocation")
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, rbaNode1)
|
||||
assert.True(t, auth.Serial.Has(err))
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
@ -88,55 +118,61 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
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 := satellite.BandwidthAgreements(ctx, rbaNode2)
|
||||
assert.EqualError(t, err, "bwagreement error: SerialNumber already exists in the PayerBandwidthAllocation")
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN2, rbaNode2)
|
||||
assert.True(t, auth.Serial.Has(err))
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
}
|
||||
|
||||
{ // TestExpiredBandwidthAgreements
|
||||
{ // storage nodes can submit a bwagreement that will expire in one second
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, time.Second)
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, time.Second)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
ctxSN1, storageNode1 := getPeerContext(ctx, t)
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rba)
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, rba)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pb.AgreementsSummary_OK, reply.Status)
|
||||
}
|
||||
|
||||
{ // storage nodes can't submit a bwagreement that expires right now
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, 0*time.Second)
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, 0*time.Second)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
ctxSN1, storageNode1 := getPeerContext(ctx, t)
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rba)
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, rba)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
{ // storage nodes can't submit a bwagreement that expires yesterday
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, -23*time.Hour-55*time.Second)
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, -23*time.Hour-55*time.Second)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
ctxSN1, storageNode1 := getPeerContext(ctx, t)
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rba)
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, rba)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
}
|
||||
|
||||
{ // TestManipulatedBandwidthAgreements
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, time.Hour)
|
||||
assert.NoError(t, err)
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, time.Hour)
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
ctxSN1, storageNode1 := getPeerContext(ctx, t)
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Unmarschal Renter and Payer bwagreements
|
||||
@ -156,51 +192,59 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Generate a new keypair for self signing bwagreements
|
||||
_, manipPrivKey, _ := generateKeys(ctx, t)
|
||||
manipPubKey, err := getUplinkPubKey(manipPrivKey)
|
||||
manipID, err := testidentity.NewTestIdentity(ctx)
|
||||
assert.NoError(t, err)
|
||||
manipCerts := manipID.ChainRaw() //todo: do we need RestChain?
|
||||
manipPrivKey, ok := manipID.Key.(*ecdsa.PrivateKey)
|
||||
assert.True(t, ok)
|
||||
|
||||
/* Storage node can't manipulate the bwagreement size (or any other field)
|
||||
Satellite will verify Renter's Signature */
|
||||
Satellite will verify Renter's Signature. */
|
||||
{
|
||||
// Using uplink signature
|
||||
reply, err := satellite.BandwidthAgreements(ctx, &pb.RenterBandwidthAllocation{
|
||||
Signature: rba.GetSignature(),
|
||||
Data: maniprba,
|
||||
})
|
||||
|
||||
assert.EqualError(t, err, "bwagreement error: Failed to verify Renter's Signature")
|
||||
reply, err := callBWA(ctxSN1, satellite, rba.GetSignature(), maniprba, rba.GetCerts())
|
||||
assert.True(t, auth.Verify.Has(err) && pb.Renter.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
/* Storage node can't sign the manipulated bwagreement
|
||||
Satellite will verify Renter's Signature */
|
||||
Satellite will verify Renter's Signature. */
|
||||
{
|
||||
manipSignature, err := cryptopasta.Sign(maniprba, manipPrivKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Using self created signature
|
||||
reply, err := satellite.BandwidthAgreements(ctx, &pb.RenterBandwidthAllocation{
|
||||
Signature: manipSignature,
|
||||
Data: maniprba,
|
||||
})
|
||||
|
||||
assert.EqualError(t, err, "bwagreement error: Failed to verify Renter's Signature")
|
||||
reply, err := callBWA(ctxSN1, satellite, manipSignature, maniprba, rba.GetCerts())
|
||||
assert.True(t, auth.Verify.Has(err) && pb.Renter.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
/* Storage node can't replace uplink PubKey
|
||||
Satellite will verify Payer's Signature */
|
||||
/* Storage node can't replace uplink Certs
|
||||
Satellite will check uplink Certs against uplinkeId. */
|
||||
{
|
||||
// Overwrite the uplink public key with our own keypair
|
||||
pbaData.PubKey = manipPubKey
|
||||
manipSignature, err := cryptopasta.Sign(maniprba, manipPrivKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Using self created signature + public key
|
||||
reply, err := callBWA(ctxSN1, satellite, manipSignature, maniprba, manipCerts)
|
||||
assert.True(t, auth.Signer.Has(err) && pb.Renter.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
/* Storage node can't replace uplink NodeId
|
||||
Satellite will verify the Payer's Signature. */
|
||||
{
|
||||
// Overwrite the uplinkId with our own keypair
|
||||
pbaData.UplinkId = manipID.ID
|
||||
|
||||
manippba, err := proto.Marshal(pbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Overwrite the uplink public key with our own keypair
|
||||
rbaData.PayerAllocation = &pb.PayerBandwidthAllocation{
|
||||
Signature: pba.GetSignature(),
|
||||
Data: manippba,
|
||||
Certs: pba.GetCerts(),
|
||||
}
|
||||
|
||||
maniprba, err := proto.Marshal(rbaData)
|
||||
@ -210,20 +254,16 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Using self created signature + public key
|
||||
reply, err := satellite.BandwidthAgreements(ctx, &pb.RenterBandwidthAllocation{
|
||||
Signature: manipSignature,
|
||||
Data: maniprba,
|
||||
})
|
||||
|
||||
assert.EqualError(t, err, "bwagreement error: Failed to verify Payer's Signature")
|
||||
reply, err := callBWA(ctxSN1, satellite, manipSignature, maniprba, manipCerts)
|
||||
assert.True(t, auth.Verify.Has(err) && pb.Payer.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
/* Storage node can't self sign the PayerBandwidthAllocation.
|
||||
Satellite will verify the Payer's Signature with his own public key. */
|
||||
Satellite will verify the Payer's Signature. */
|
||||
{
|
||||
// Overwrite the uplink public key with our own keypair
|
||||
pbaData.PubKey = manipPubKey
|
||||
// Overwrite the uplinkId with our own keypair
|
||||
pbaData.UplinkId = manipID.ID
|
||||
|
||||
manippba, err := proto.Marshal(pbaData)
|
||||
assert.NoError(t, err)
|
||||
@ -234,6 +274,7 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
rbaData.PayerAllocation = &pb.PayerBandwidthAllocation{
|
||||
Signature: manipSignature,
|
||||
Data: manippba,
|
||||
Certs: pba.GetCerts(),
|
||||
}
|
||||
|
||||
maniprba, err := proto.Marshal(rbaData)
|
||||
@ -243,33 +284,92 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Using self created Payer and Renter bwagreement signatures
|
||||
reply, err := satellite.BandwidthAgreements(ctx, &pb.RenterBandwidthAllocation{
|
||||
Signature: manipSignature,
|
||||
Data: maniprba,
|
||||
})
|
||||
reply, err := callBWA(ctxSN1, satellite, manipSignature, maniprba, manipCerts)
|
||||
assert.True(t, auth.Verify.Has(err) && pb.Payer.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
assert.EqualError(t, err, "bwagreement error: Failed to verify Payer's Signature")
|
||||
/* Storage node can't replace the satellite Certs.
|
||||
Satellite will check satellite certs against satelliteId. */
|
||||
{
|
||||
// Overwrite the uplinkId with our own keypair
|
||||
pbaData.UplinkId = manipID.ID
|
||||
|
||||
manippba, err := proto.Marshal(pbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manipSignature, err := cryptopasta.Sign(manippba, manipPrivKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rbaData.PayerAllocation = &pb.PayerBandwidthAllocation{
|
||||
Signature: manipSignature,
|
||||
Data: manippba,
|
||||
Certs: manipCerts,
|
||||
}
|
||||
|
||||
maniprba, err := proto.Marshal(rbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manipSignature, err = cryptopasta.Sign(maniprba, manipPrivKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Using self created Payer and Renter bwagreement signatures
|
||||
reply, err := callBWA(ctxSN1, satellite, manipSignature, maniprba, manipCerts)
|
||||
assert.True(t, auth.Signer.Has(err) && pb.Payer.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
/* Storage node can't replace the satellite.
|
||||
Satellite will verify the Satellite Id. */
|
||||
{
|
||||
// Overwrite the uplinkId and satelliteID with our own keypair
|
||||
pbaData.UplinkId = manipID.ID
|
||||
pbaData.SatelliteId = manipID.ID
|
||||
|
||||
manippba, err := proto.Marshal(pbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manipSignature, err := cryptopasta.Sign(manippba, manipPrivKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rbaData.PayerAllocation = &pb.PayerBandwidthAllocation{
|
||||
Signature: manipSignature,
|
||||
Data: manippba,
|
||||
Certs: manipCerts,
|
||||
}
|
||||
|
||||
maniprba, err := proto.Marshal(rbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manipSignature, err = cryptopasta.Sign(maniprba, manipPrivKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Using self created Payer and Renter bwagreement signatures
|
||||
reply, err := callBWA(ctxSN1, satellite, manipSignature, maniprba, manipCerts)
|
||||
assert.True(t, pb.Payer.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
}
|
||||
|
||||
{ //TestInvalidBandwidthAgreements
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satellitePrivKey, uplinkPrivKey, time.Hour)
|
||||
ctxSN1, storageNode1 := getPeerContext(ctx, t)
|
||||
ctxSN2, storageNode2 := getPeerContext(ctx, t)
|
||||
pba, err := GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, satID, upID, time.Hour)
|
||||
assert.NoError(t, err)
|
||||
|
||||
{ // Storage node sends an corrupted signuature to force a satellite crash
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 1"), uplinkPrivKey)
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, storageNode1, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rba.Signature = []byte("invalid")
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, rba)
|
||||
assert.EqualError(t, err, "bwagreement error: Invalid Renter's Signature Length")
|
||||
reply, err := satellite.BandwidthAgreements(ctxSN1, rba)
|
||||
assert.True(t, auth.SigLen.Has(err) && pb.Renter.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, reply.Status)
|
||||
}
|
||||
|
||||
{ // Storage node sends an corrupted uplink pubkey to force a crash
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, teststorj.NodeIDFromString("Storage node 2"), uplinkPrivKey)
|
||||
{ // Storage node sends an corrupted uplink Certs to force a crash
|
||||
rba, err := GenerateRenterBandwidthAllocation(pba, storageNode2, upID, 666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rbaData := &pb.RenterBandwidthAllocation_Data{}
|
||||
@ -280,7 +380,7 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
err = proto.Unmarshal(pba.GetData(), pbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
pbaData.PubKey = nil
|
||||
pba.Certs = nil
|
||||
|
||||
invalidpba, err := proto.Marshal(pbaData)
|
||||
assert.NoError(t, err)
|
||||
@ -288,35 +388,20 @@ func testDatabase(ctx context.Context, t *testing.T, bwdb bwagreement.DB) {
|
||||
rbaData.PayerAllocation = &pb.PayerBandwidthAllocation{
|
||||
Signature: pba.GetSignature(),
|
||||
Data: invalidpba,
|
||||
Certs: pba.GetCerts(),
|
||||
}
|
||||
|
||||
invalidrba, err := proto.Marshal(rbaData)
|
||||
assert.NoError(t, err)
|
||||
|
||||
reply, err := satellite.BandwidthAgreements(ctx, &pb.RenterBandwidthAllocation{
|
||||
Signature: rba.GetSignature(),
|
||||
Data: invalidrba,
|
||||
})
|
||||
assert.EqualError(t, err, "bwagreement error: Failed to extract Public Key from RenterBandwidthAllocation: asn1: syntax error: sequence truncated")
|
||||
reply, err := callBWA(ctxSN2, satellite, rba.GetSignature(), invalidrba, rba.GetCerts())
|
||||
assert.True(t, auth.Verify.Has(err) && pb.Renter.Has(err), err.Error())
|
||||
assert.Equal(t, pb.AgreementsSummary_REJECTED, 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
|
||||
func callBWA(ctx context.Context, sat *bwagreement.Server, signature, data []byte, certs [][]byte) (*pb.AgreementsSummary, error) {
|
||||
rba := &pb.RenterBandwidthAllocation{Signature: signature, Data: data, Certs: certs}
|
||||
return sat.BandwidthAgreements(ctx, rba)
|
||||
}
|
||||
|
@ -214,13 +214,8 @@ func (c CertificateSigner) Sign(ctx context.Context, req *pb.SigningRequest) (*p
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signedChainBytes := append(
|
||||
[][]byte{
|
||||
signedPeerCA.Raw,
|
||||
c.signer.Cert.Raw,
|
||||
},
|
||||
c.signer.RestChainRaw()...,
|
||||
)
|
||||
signedChainBytes := [][]byte{signedPeerCA.Raw, c.signer.Cert.Raw}
|
||||
signedChainBytes = append(signedChainBytes, c.signer.RestChainRaw()...)
|
||||
err = c.authDB.Claim(&ClaimOpts{
|
||||
Req: req,
|
||||
Peer: grpcPeer,
|
||||
|
@ -196,7 +196,7 @@ func NodeIDFromECDSAKey(k *ecdsa.PublicKey) (storj.NodeID, error) {
|
||||
}
|
||||
mid := sha256.Sum256(kb)
|
||||
end := sha256.Sum256(mid[:])
|
||||
return storj.NodeIDFromBytes(end[:])
|
||||
return storj.NodeID(end), nil
|
||||
}
|
||||
|
||||
// NewFullIdentity creates a new ID for nodes with difficulty and concurrency params
|
||||
@ -298,6 +298,15 @@ func (ic Config) SaveBackup(fi *FullIdentity) error {
|
||||
}.Save(fi)
|
||||
}
|
||||
|
||||
// ChainRaw returns all of the certificate chain as a 2d byte slice
|
||||
func (fi *FullIdentity) ChainRaw() [][]byte {
|
||||
chain := [][]byte{fi.Leaf.Raw, fi.CA.Raw}
|
||||
for _, cert := range fi.RestChain {
|
||||
chain = append(chain, cert.Raw)
|
||||
}
|
||||
return chain
|
||||
}
|
||||
|
||||
// RestChainRaw returns the rest (excluding leaf and CA) of the certificate chain as a 2d byte slice
|
||||
func (fi *FullIdentity) RestChainRaw() [][]byte {
|
||||
var chain [][]byte
|
||||
@ -310,9 +319,7 @@ func (fi *FullIdentity) RestChainRaw() [][]byte {
|
||||
// ServerOption returns a grpc `ServerOption` for incoming connections
|
||||
// to the node with this full identity
|
||||
func (fi *FullIdentity) ServerOption(pcvFuncs ...peertls.PeerCertVerificationFunc) (grpc.ServerOption, error) {
|
||||
ch := [][]byte{fi.Leaf.Raw, fi.CA.Raw}
|
||||
ch = append(ch, fi.RestChainRaw()...)
|
||||
c, err := peertls.TLSCert(ch, fi.Leaf, fi.Key)
|
||||
c, err := peertls.TLSCert(fi.ChainRaw(), fi.Leaf, fi.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -337,9 +344,7 @@ func (fi *FullIdentity) ServerOption(pcvFuncs ...peertls.PeerCertVerificationFun
|
||||
// to the node with this peer identity
|
||||
// id is an optional id of the node we are dialing
|
||||
func (fi *FullIdentity) DialOption(id storj.NodeID) (grpc.DialOption, error) {
|
||||
ch := [][]byte{fi.Leaf.Raw, fi.CA.Raw}
|
||||
ch = append(ch, fi.RestChainRaw()...)
|
||||
c, err := peertls.TLSCert(ch, fi.Leaf, fi.Key)
|
||||
c, err := peertls.TLSCert(fi.ChainRaw(), fi.Leaf, fi.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
63
pkg/pb/BandwidthUtils.go
Normal file
63
pkg/pb/BandwidthUtils.go
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
"github.com/zeebo/errs"
|
||||
)
|
||||
|
||||
var (
|
||||
//Renter wraps errors related to renter bandwidth allocations
|
||||
Renter = errs.Class("Renter agreement")
|
||||
//Payer wraps errors related to payer bandwidth allocations
|
||||
Payer = errs.Class("Payer agreement")
|
||||
//Marshal indicates a failure during serialization
|
||||
Marshal = errs.Class("Could not generate byte array from key")
|
||||
//Unmarshal indicates a failure during deserialization
|
||||
Unmarshal = errs.Class("Could not generate key from byte array")
|
||||
//Missing indicates missing or empty information
|
||||
Missing = errs.Class("Required field is empty")
|
||||
)
|
||||
|
||||
//SignedMsg interface has a key, data, and signature
|
||||
type SignedMsg interface {
|
||||
GetCerts() [][]byte
|
||||
GetData() []byte
|
||||
GetSignature() []byte
|
||||
}
|
||||
|
||||
// MsgComplete ensures a SignedMsg has no nulls
|
||||
func MsgComplete(sm SignedMsg) (bool, error) {
|
||||
if sm == nil {
|
||||
return false, Missing.New("message")
|
||||
} else if sm.GetData() == nil {
|
||||
return false, Missing.New("message data")
|
||||
} else if sm.GetSignature() == nil {
|
||||
return false, Missing.New("message signature")
|
||||
} else if sm.GetCerts() == nil {
|
||||
return false, Missing.New("message certificates")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
//Unpack helps get things out of a RenterBandwidthAllocation
|
||||
func (rba *RenterBandwidthAllocation) Unpack() (*RenterBandwidthAllocation_Data, *PayerBandwidthAllocation, *PayerBandwidthAllocation_Data, error) {
|
||||
if ok, err := MsgComplete(rba); !ok {
|
||||
return nil, nil, nil, Renter.Wrap(err)
|
||||
}
|
||||
rbad := &RenterBandwidthAllocation_Data{}
|
||||
if err := proto.Unmarshal(rba.GetData(), rbad); err != nil {
|
||||
return nil, nil, nil, Renter.Wrap(Unmarshal.Wrap(err))
|
||||
}
|
||||
if ok, err := MsgComplete(rba); !ok {
|
||||
return nil, nil, nil, Payer.Wrap(err)
|
||||
}
|
||||
pba := rbad.GetPayerAllocation()
|
||||
pbad := &PayerBandwidthAllocation_Data{}
|
||||
if err := proto.Unmarshal(pba.GetData(), pbad); err != nil {
|
||||
return nil, nil, nil, Payer.Wrap(Unmarshal.Wrap(err))
|
||||
}
|
||||
return rbad, pba, pbad, nil
|
||||
}
|
@ -54,12 +54,13 @@ func (x PayerBandwidthAllocation_Action) String() string {
|
||||
return proto.EnumName(PayerBandwidthAllocation_Action_name, int32(x))
|
||||
}
|
||||
func (PayerBandwidthAllocation_Action) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{0, 0}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{0, 0}
|
||||
}
|
||||
|
||||
type PayerBandwidthAllocation struct {
|
||||
Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Certs [][]byte `protobuf:"bytes,1,rep,name=certs,proto3" json:"certs,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -69,7 +70,7 @@ func (m *PayerBandwidthAllocation) Reset() { *m = PayerBandwidthAllocati
|
||||
func (m *PayerBandwidthAllocation) String() string { return proto.CompactTextString(m) }
|
||||
func (*PayerBandwidthAllocation) ProtoMessage() {}
|
||||
func (*PayerBandwidthAllocation) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{0}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{0}
|
||||
}
|
||||
func (m *PayerBandwidthAllocation) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PayerBandwidthAllocation.Unmarshal(m, b)
|
||||
@ -89,6 +90,13 @@ func (m *PayerBandwidthAllocation) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_PayerBandwidthAllocation proto.InternalMessageInfo
|
||||
|
||||
func (m *PayerBandwidthAllocation) GetCerts() [][]byte {
|
||||
if m != nil {
|
||||
return m.Certs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PayerBandwidthAllocation) GetSignature() []byte {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
@ -111,7 +119,6 @@ type PayerBandwidthAllocation_Data struct {
|
||||
SerialNumber string `protobuf:"bytes,5,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"`
|
||||
Action PayerBandwidthAllocation_Action `protobuf:"varint,6,opt,name=action,proto3,enum=piecestoreroutes.PayerBandwidthAllocation_Action" json:"action,omitempty"`
|
||||
CreatedUnixSec int64 `protobuf:"varint,7,opt,name=created_unix_sec,json=createdUnixSec,proto3" json:"created_unix_sec,omitempty"`
|
||||
PubKey []byte `protobuf:"bytes,8,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -121,7 +128,7 @@ func (m *PayerBandwidthAllocation_Data) Reset() { *m = PayerBandwidthAll
|
||||
func (m *PayerBandwidthAllocation_Data) String() string { return proto.CompactTextString(m) }
|
||||
func (*PayerBandwidthAllocation_Data) ProtoMessage() {}
|
||||
func (*PayerBandwidthAllocation_Data) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{0, 0}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{0, 0}
|
||||
}
|
||||
func (m *PayerBandwidthAllocation_Data) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PayerBandwidthAllocation_Data.Unmarshal(m, b)
|
||||
@ -176,16 +183,10 @@ func (m *PayerBandwidthAllocation_Data) GetCreatedUnixSec() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *PayerBandwidthAllocation_Data) GetPubKey() []byte {
|
||||
if m != nil {
|
||||
return m.PubKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RenterBandwidthAllocation struct {
|
||||
Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Certs [][]byte `protobuf:"bytes,1,rep,name=certs,proto3" json:"certs,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -195,7 +196,7 @@ func (m *RenterBandwidthAllocation) Reset() { *m = RenterBandwidthAlloca
|
||||
func (m *RenterBandwidthAllocation) String() string { return proto.CompactTextString(m) }
|
||||
func (*RenterBandwidthAllocation) ProtoMessage() {}
|
||||
func (*RenterBandwidthAllocation) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{1}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{1}
|
||||
}
|
||||
func (m *RenterBandwidthAllocation) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RenterBandwidthAllocation.Unmarshal(m, b)
|
||||
@ -215,6 +216,13 @@ func (m *RenterBandwidthAllocation) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_RenterBandwidthAllocation proto.InternalMessageInfo
|
||||
|
||||
func (m *RenterBandwidthAllocation) GetCerts() [][]byte {
|
||||
if m != nil {
|
||||
return m.Certs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RenterBandwidthAllocation) GetSignature() []byte {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
@ -230,7 +238,7 @@ func (m *RenterBandwidthAllocation) GetData() []byte {
|
||||
}
|
||||
|
||||
type RenterBandwidthAllocation_Data struct {
|
||||
PayerAllocation *PayerBandwidthAllocation `protobuf:"bytes,1,opt,name=payer_allocation,json=payerAllocation" json:"payer_allocation,omitempty"`
|
||||
PayerAllocation *PayerBandwidthAllocation `protobuf:"bytes,1,opt,name=payer_allocation,json=payerAllocation,proto3" json:"payer_allocation,omitempty"`
|
||||
Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"`
|
||||
StorageNodeId NodeID `protobuf:"bytes,3,opt,name=storage_node_id,json=storageNodeId,proto3,customtype=NodeID" json:"storage_node_id"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
@ -242,7 +250,7 @@ func (m *RenterBandwidthAllocation_Data) Reset() { *m = RenterBandwidthA
|
||||
func (m *RenterBandwidthAllocation_Data) String() string { return proto.CompactTextString(m) }
|
||||
func (*RenterBandwidthAllocation_Data) ProtoMessage() {}
|
||||
func (*RenterBandwidthAllocation_Data) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{1, 0}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{1, 0}
|
||||
}
|
||||
func (m *RenterBandwidthAllocation_Data) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RenterBandwidthAllocation_Data.Unmarshal(m, b)
|
||||
@ -277,9 +285,9 @@ func (m *RenterBandwidthAllocation_Data) GetTotal() int64 {
|
||||
}
|
||||
|
||||
type PieceStore struct {
|
||||
BandwidthAllocation *RenterBandwidthAllocation `protobuf:"bytes,1,opt,name=bandwidth_allocation,json=bandwidthAllocation" json:"bandwidth_allocation,omitempty"`
|
||||
PieceData *PieceStore_PieceData `protobuf:"bytes,2,opt,name=piece_data,json=pieceData" json:"piece_data,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,3,opt,name=authorization" json:"authorization,omitempty"`
|
||||
BandwidthAllocation *RenterBandwidthAllocation `protobuf:"bytes,1,opt,name=bandwidth_allocation,json=bandwidthAllocation,proto3" json:"bandwidth_allocation,omitempty"`
|
||||
PieceData *PieceStore_PieceData `protobuf:"bytes,2,opt,name=piece_data,json=pieceData,proto3" json:"piece_data,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -289,7 +297,7 @@ func (m *PieceStore) Reset() { *m = PieceStore{} }
|
||||
func (m *PieceStore) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceStore) ProtoMessage() {}
|
||||
func (*PieceStore) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{2}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{2}
|
||||
}
|
||||
func (m *PieceStore) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceStore.Unmarshal(m, b)
|
||||
@ -344,7 +352,7 @@ func (m *PieceStore_PieceData) Reset() { *m = PieceStore_PieceData{} }
|
||||
func (m *PieceStore_PieceData) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceStore_PieceData) ProtoMessage() {}
|
||||
func (*PieceStore_PieceData) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{2, 0}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{2, 0}
|
||||
}
|
||||
func (m *PieceStore_PieceData) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceStore_PieceData.Unmarshal(m, b)
|
||||
@ -388,7 +396,7 @@ func (m *PieceStore_PieceData) GetContent() []byte {
|
||||
type PieceId struct {
|
||||
// TODO: may want to use customtype and fixed-length byte slice
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,2,opt,name=authorization" json:"authorization,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,2,opt,name=authorization,proto3" json:"authorization,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -398,7 +406,7 @@ func (m *PieceId) Reset() { *m = PieceId{} }
|
||||
func (m *PieceId) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceId) ProtoMessage() {}
|
||||
func (*PieceId) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{3}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{3}
|
||||
}
|
||||
func (m *PieceId) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceId.Unmarshal(m, b)
|
||||
@ -445,7 +453,7 @@ func (m *PieceSummary) Reset() { *m = PieceSummary{} }
|
||||
func (m *PieceSummary) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceSummary) ProtoMessage() {}
|
||||
func (*PieceSummary) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{4}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{4}
|
||||
}
|
||||
func (m *PieceSummary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceSummary.Unmarshal(m, b)
|
||||
@ -487,9 +495,9 @@ func (m *PieceSummary) GetExpirationUnixSec() int64 {
|
||||
}
|
||||
|
||||
type PieceRetrieval struct {
|
||||
BandwidthAllocation *RenterBandwidthAllocation `protobuf:"bytes,1,opt,name=bandwidth_allocation,json=bandwidthAllocation" json:"bandwidth_allocation,omitempty"`
|
||||
PieceData *PieceRetrieval_PieceData `protobuf:"bytes,2,opt,name=piece_data,json=pieceData" json:"piece_data,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,3,opt,name=authorization" json:"authorization,omitempty"`
|
||||
BandwidthAllocation *RenterBandwidthAllocation `protobuf:"bytes,1,opt,name=bandwidth_allocation,json=bandwidthAllocation,proto3" json:"bandwidth_allocation,omitempty"`
|
||||
PieceData *PieceRetrieval_PieceData `protobuf:"bytes,2,opt,name=piece_data,json=pieceData,proto3" json:"piece_data,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -499,7 +507,7 @@ func (m *PieceRetrieval) Reset() { *m = PieceRetrieval{} }
|
||||
func (m *PieceRetrieval) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceRetrieval) ProtoMessage() {}
|
||||
func (*PieceRetrieval) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{5}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{5}
|
||||
}
|
||||
func (m *PieceRetrieval) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceRetrieval.Unmarshal(m, b)
|
||||
@ -554,7 +562,7 @@ func (m *PieceRetrieval_PieceData) Reset() { *m = PieceRetrieval_PieceDa
|
||||
func (m *PieceRetrieval_PieceData) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceRetrieval_PieceData) ProtoMessage() {}
|
||||
func (*PieceRetrieval_PieceData) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{5, 0}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{5, 0}
|
||||
}
|
||||
func (m *PieceRetrieval_PieceData) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceRetrieval_PieceData.Unmarshal(m, b)
|
||||
@ -607,7 +615,7 @@ func (m *PieceRetrievalStream) Reset() { *m = PieceRetrievalStream{} }
|
||||
func (m *PieceRetrievalStream) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceRetrievalStream) ProtoMessage() {}
|
||||
func (*PieceRetrievalStream) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{6}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{6}
|
||||
}
|
||||
func (m *PieceRetrievalStream) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceRetrievalStream.Unmarshal(m, b)
|
||||
@ -644,7 +652,7 @@ func (m *PieceRetrievalStream) GetContent() []byte {
|
||||
type PieceDelete struct {
|
||||
// TODO: may want to use customtype and fixed-length byte slice
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,3,opt,name=authorization" json:"authorization,omitempty"`
|
||||
Authorization *SignedMessage `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -654,7 +662,7 @@ func (m *PieceDelete) Reset() { *m = PieceDelete{} }
|
||||
func (m *PieceDelete) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceDelete) ProtoMessage() {}
|
||||
func (*PieceDelete) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{7}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{7}
|
||||
}
|
||||
func (m *PieceDelete) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceDelete.Unmarshal(m, b)
|
||||
@ -699,7 +707,7 @@ func (m *PieceDeleteSummary) Reset() { *m = PieceDeleteSummary{} }
|
||||
func (m *PieceDeleteSummary) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceDeleteSummary) ProtoMessage() {}
|
||||
func (*PieceDeleteSummary) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{8}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{8}
|
||||
}
|
||||
func (m *PieceDeleteSummary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceDeleteSummary.Unmarshal(m, b)
|
||||
@ -738,7 +746,7 @@ func (m *PieceStoreSummary) Reset() { *m = PieceStoreSummary{} }
|
||||
func (m *PieceStoreSummary) String() string { return proto.CompactTextString(m) }
|
||||
func (*PieceStoreSummary) ProtoMessage() {}
|
||||
func (*PieceStoreSummary) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{9}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{9}
|
||||
}
|
||||
func (m *PieceStoreSummary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PieceStoreSummary.Unmarshal(m, b)
|
||||
@ -782,7 +790,7 @@ func (m *StatsReq) Reset() { *m = StatsReq{} }
|
||||
func (m *StatsReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*StatsReq) ProtoMessage() {}
|
||||
func (*StatsReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{10}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{10}
|
||||
}
|
||||
func (m *StatsReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StatsReq.Unmarshal(m, b)
|
||||
@ -816,7 +824,7 @@ func (m *StatSummary) Reset() { *m = StatSummary{} }
|
||||
func (m *StatSummary) String() string { return proto.CompactTextString(m) }
|
||||
func (*StatSummary) ProtoMessage() {}
|
||||
func (*StatSummary) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{11}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{11}
|
||||
}
|
||||
func (m *StatSummary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StatSummary.Unmarshal(m, b)
|
||||
@ -877,7 +885,7 @@ func (m *SignedMessage) Reset() { *m = SignedMessage{} }
|
||||
func (m *SignedMessage) String() string { return proto.CompactTextString(m) }
|
||||
func (*SignedMessage) ProtoMessage() {}
|
||||
func (*SignedMessage) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{12}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{12}
|
||||
}
|
||||
func (m *SignedMessage) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignedMessage.Unmarshal(m, b)
|
||||
@ -928,7 +936,7 @@ func (m *DashboardReq) Reset() { *m = DashboardReq{} }
|
||||
func (m *DashboardReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*DashboardReq) ProtoMessage() {}
|
||||
func (*DashboardReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{13}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{13}
|
||||
}
|
||||
func (m *DashboardReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DashboardReq.Unmarshal(m, b)
|
||||
@ -952,9 +960,9 @@ type DashboardStats struct {
|
||||
NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
|
||||
NodeConnections int64 `protobuf:"varint,2,opt,name=node_connections,json=nodeConnections,proto3" json:"node_connections,omitempty"`
|
||||
Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
|
||||
Stats *StatSummary `protobuf:"bytes,4,opt,name=stats" json:"stats,omitempty"`
|
||||
Stats *StatSummary `protobuf:"bytes,4,opt,name=stats,proto3" json:"stats,omitempty"`
|
||||
Connection bool `protobuf:"varint,5,opt,name=connection,proto3" json:"connection,omitempty"`
|
||||
Uptime *duration.Duration `protobuf:"bytes,6,opt,name=uptime" json:"uptime,omitempty"`
|
||||
Uptime *duration.Duration `protobuf:"bytes,6,opt,name=uptime,proto3" json:"uptime,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -964,7 +972,7 @@ func (m *DashboardStats) Reset() { *m = DashboardStats{} }
|
||||
func (m *DashboardStats) String() string { return proto.CompactTextString(m) }
|
||||
func (*DashboardStats) ProtoMessage() {}
|
||||
func (*DashboardStats) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_piecestore_4b57efffb1b6b03f, []int{14}
|
||||
return fileDescriptor_piecestore_ad8894e1f36b2897, []int{14}
|
||||
}
|
||||
func (m *DashboardStats) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DashboardStats.Unmarshal(m, b)
|
||||
@ -1380,79 +1388,79 @@ var _PieceStoreRoutes_serviceDesc = grpc.ServiceDesc{
|
||||
Metadata: "piecestore.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("piecestore.proto", fileDescriptor_piecestore_4b57efffb1b6b03f) }
|
||||
func init() { proto.RegisterFile("piecestore.proto", fileDescriptor_piecestore_ad8894e1f36b2897) }
|
||||
|
||||
var fileDescriptor_piecestore_4b57efffb1b6b03f = []byte{
|
||||
// 1130 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4b, 0x6f, 0xdb, 0xc6,
|
||||
0x13, 0x17, 0x29, 0x5b, 0x8f, 0x91, 0x25, 0x2b, 0x9b, 0xe0, 0xff, 0x97, 0x85, 0xd8, 0x16, 0x98,
|
||||
0x26, 0x55, 0x13, 0x40, 0x8e, 0x15, 0xa0, 0x77, 0xbb, 0x32, 0x02, 0xa1, 0xa8, 0xe3, 0xae, 0xec,
|
||||
0x4b, 0x0e, 0x65, 0x56, 0xe4, 0x58, 0x26, 0x42, 0x91, 0x2c, 0xb9, 0x74, 0x6d, 0x7f, 0xa5, 0xa2,
|
||||
0xdf, 0xa3, 0x9f, 0xa0, 0x87, 0x1e, 0x02, 0x14, 0xe8, 0xb9, 0xc7, 0x5e, 0x0a, 0x14, 0xc5, 0xee,
|
||||
0xf2, 0x21, 0x5b, 0x0f, 0x17, 0x41, 0x73, 0xdb, 0x79, 0xec, 0xcc, 0xec, 0x6f, 0x7f, 0xb3, 0xb3,
|
||||
0xd0, 0x0c, 0x1c, 0xb4, 0x30, 0xe2, 0x7e, 0x88, 0xbd, 0x20, 0xf4, 0xb9, 0x4f, 0x66, 0x34, 0xa1,
|
||||
0x1f, 0x73, 0x8c, 0xda, 0xe0, 0xf9, 0x76, 0x62, 0x6d, 0xc3, 0xc4, 0x9f, 0xf8, 0xc9, 0x7a, 0x67,
|
||||
0xe2, 0xfb, 0x13, 0x17, 0xf7, 0xa4, 0x34, 0x8e, 0xcf, 0xf7, 0xec, 0x38, 0x64, 0xdc, 0xf1, 0x3d,
|
||||
0x65, 0x37, 0xfe, 0x2e, 0x42, 0xeb, 0x84, 0x5d, 0x63, 0x78, 0xc8, 0x3c, 0xfb, 0x07, 0xc7, 0xe6,
|
||||
0x17, 0x07, 0xae, 0xeb, 0x5b, 0xd2, 0x85, 0x3c, 0x86, 0x6a, 0xe4, 0x4c, 0x3c, 0xc6, 0xe3, 0x10,
|
||||
0x5b, 0x5a, 0x47, 0xeb, 0x6e, 0xd0, 0x5c, 0x41, 0x08, 0xac, 0xd9, 0x8c, 0xb3, 0x96, 0x2e, 0x0d,
|
||||
0x72, 0xdd, 0xfe, 0x5d, 0x87, 0xb5, 0x01, 0xe3, 0x8c, 0xec, 0xc3, 0x46, 0xc4, 0x38, 0xba, 0xae,
|
||||
0xc3, 0xd1, 0x74, 0x6c, 0xb5, 0xfb, 0xb0, 0xf1, 0xf3, 0x87, 0xdd, 0xc2, 0xaf, 0x1f, 0x76, 0x4b,
|
||||
0xc7, 0xbe, 0x8d, 0xc3, 0x01, 0xad, 0x65, 0x3e, 0x43, 0x9b, 0xbc, 0x80, 0x6a, 0x1c, 0xb8, 0x8e,
|
||||
0xf7, 0x5e, 0xf8, 0xeb, 0x0b, 0xfd, 0x2b, 0xca, 0x61, 0x68, 0x93, 0x2d, 0xa8, 0x4c, 0xd9, 0x95,
|
||||
0x19, 0x39, 0x37, 0xd8, 0x2a, 0x76, 0xb4, 0x6e, 0x91, 0x96, 0xa7, 0xec, 0x6a, 0xe4, 0xdc, 0x20,
|
||||
0xe9, 0xc1, 0x43, 0xbc, 0x0a, 0x1c, 0x75, 0x4c, 0x33, 0xf6, 0x9c, 0x2b, 0x33, 0x42, 0xab, 0xb5,
|
||||
0x26, 0xbd, 0x1e, 0xe4, 0xa6, 0x33, 0xcf, 0xb9, 0x1a, 0xa1, 0x45, 0x9e, 0x40, 0x3d, 0xc2, 0xd0,
|
||||
0x61, 0xae, 0xe9, 0xc5, 0xd3, 0x31, 0x86, 0xad, 0xf5, 0x8e, 0xd6, 0xad, 0xd2, 0x0d, 0xa5, 0x3c,
|
||||
0x96, 0x3a, 0x32, 0x84, 0x12, 0xb3, 0xc4, 0xae, 0x56, 0xa9, 0xa3, 0x75, 0x1b, 0xfd, 0xfd, 0xde,
|
||||
0xdd, 0x2b, 0xe8, 0x2d, 0x83, 0xb1, 0x77, 0x20, 0x37, 0xd2, 0x24, 0x00, 0xe9, 0x42, 0xd3, 0x0a,
|
||||
0x91, 0x71, 0xb4, 0xf3, 0xe2, 0xca, 0xb2, 0xb8, 0x46, 0xa2, 0x4f, 0x2b, 0xfb, 0x3f, 0x94, 0x83,
|
||||
0x78, 0x6c, 0xbe, 0xc7, 0xeb, 0x56, 0x45, 0x82, 0x5c, 0x0a, 0xe2, 0xf1, 0xd7, 0x78, 0x6d, 0x0c,
|
||||
0xa1, 0xa4, 0x82, 0x92, 0x32, 0x14, 0x4f, 0xce, 0x4e, 0x9b, 0x05, 0xb1, 0x78, 0x7d, 0x74, 0xda,
|
||||
0xd4, 0x48, 0x1d, 0xaa, 0xaf, 0x8f, 0x4e, 0xcd, 0x83, 0xb3, 0xc1, 0xf0, 0xb4, 0xa9, 0x93, 0x06,
|
||||
0x80, 0x10, 0xe9, 0xd1, 0xc9, 0xc1, 0x90, 0x36, 0x8b, 0x42, 0x3e, 0x39, 0xcb, 0xe4, 0x35, 0xe3,
|
||||
0x2f, 0x0d, 0xb6, 0x28, 0x7a, 0xfc, 0xbf, 0x62, 0xc0, 0x8f, 0x5a, 0xc2, 0x80, 0x33, 0x68, 0x06,
|
||||
0x02, 0x11, 0x93, 0x65, 0xe1, 0x64, 0x84, 0x5a, 0xff, 0xf9, 0xbf, 0xc7, 0x8e, 0x6e, 0xca, 0x18,
|
||||
0x33, 0x15, 0x3d, 0x82, 0x75, 0xee, 0x73, 0xe6, 0xca, 0xa4, 0x45, 0xaa, 0x04, 0xf2, 0x25, 0x6c,
|
||||
0x8a, 0x70, 0x6c, 0x82, 0xa6, 0x68, 0x04, 0xc1, 0xa0, 0xe2, 0x42, 0x06, 0xd5, 0x13, 0x37, 0x29,
|
||||
0xda, 0xc6, 0x6f, 0x3a, 0xc0, 0x89, 0x28, 0x66, 0x24, 0x8a, 0x21, 0xdf, 0xc1, 0xa3, 0x71, 0x5a,
|
||||
0xc4, 0x7c, 0xdd, 0x2f, 0xe6, 0xeb, 0x5e, 0x8a, 0x1c, 0x7d, 0x38, 0x5e, 0x00, 0xe7, 0x11, 0x80,
|
||||
0x0c, 0x61, 0x66, 0xb0, 0xd5, 0xfa, 0xcf, 0x16, 0xa0, 0x91, 0x55, 0xa4, 0x96, 0x02, 0x4f, 0x5a,
|
||||
0x0d, 0xd2, 0x25, 0x39, 0x82, 0x3a, 0x8b, 0xf9, 0x85, 0x1f, 0x3a, 0x37, 0xaa, 0xbe, 0xa2, 0x8c,
|
||||
0xb4, 0x3b, 0x1f, 0x69, 0xe4, 0x4c, 0x3c, 0xb4, 0xbf, 0xc1, 0x28, 0x62, 0x13, 0xa4, 0xb7, 0x77,
|
||||
0xb5, 0x11, 0xaa, 0x59, 0x78, 0xd2, 0x00, 0x3d, 0x69, 0xd3, 0x2a, 0xd5, 0x1d, 0x7b, 0x59, 0x17,
|
||||
0xe9, 0xcb, 0xba, 0xa8, 0x05, 0x65, 0xcb, 0xf7, 0x38, 0x7a, 0x5c, 0x21, 0x4f, 0x53, 0xd1, 0x78,
|
||||
0x07, 0x65, 0x99, 0x66, 0x68, 0xcf, 0x25, 0x99, 0x3b, 0x88, 0xfe, 0x31, 0x07, 0x31, 0xa6, 0xb0,
|
||||
0xa1, 0x20, 0x8b, 0xa7, 0x53, 0x16, 0x5e, 0xcf, 0xa5, 0xd9, 0x4e, 0x61, 0x97, 0xcf, 0x85, 0x3a,
|
||||
0x82, 0x82, 0x73, 0xd5, 0x83, 0x51, 0x5c, 0x72, 0x54, 0xe3, 0x17, 0x1d, 0x1a, 0x32, 0x1f, 0x45,
|
||||
0x1e, 0x3a, 0x78, 0xc9, 0xdc, 0x4f, 0x4e, 0x9c, 0xe1, 0x02, 0xe2, 0x3c, 0x5f, 0x42, 0x9c, 0xac,
|
||||
0xaa, 0x4f, 0x4a, 0x1e, 0xba, 0x8a, 0x3c, 0xf7, 0x00, 0xfe, 0x3f, 0x28, 0xf9, 0xe7, 0xe7, 0x11,
|
||||
0xf2, 0x04, 0xe3, 0x44, 0x32, 0xde, 0xc0, 0xa3, 0xdb, 0x27, 0x18, 0xf1, 0x10, 0xd9, 0xf4, 0x4e,
|
||||
0x38, 0xed, 0x6e, 0xb8, 0x19, 0xea, 0xe9, 0xb7, 0xa9, 0x67, 0x43, 0x4d, 0x15, 0x89, 0x2e, 0x72,
|
||||
0xbc, 0x9f, 0x7e, 0x1f, 0x05, 0x85, 0xd1, 0x03, 0x32, 0x93, 0x25, 0x25, 0x61, 0x0b, 0xca, 0x53,
|
||||
0xe5, 0x9f, 0x64, 0x4c, 0x45, 0xe3, 0x14, 0x1e, 0xe4, 0x1d, 0x7e, 0xaf, 0x3b, 0x79, 0x0a, 0x0d,
|
||||
0xf9, 0xc8, 0x99, 0x21, 0x5a, 0xe8, 0x5c, 0xa2, 0x9d, 0x00, 0x5a, 0x97, 0x5a, 0x9a, 0x28, 0x0d,
|
||||
0x80, 0xca, 0x88, 0x33, 0x1e, 0x51, 0xfc, 0xde, 0xf8, 0x49, 0x83, 0x9a, 0x10, 0xd2, 0xe0, 0xdb,
|
||||
0x00, 0x71, 0x84, 0xb6, 0x19, 0x05, 0xcc, 0xca, 0x00, 0x14, 0x9a, 0x91, 0x50, 0x90, 0xcf, 0x61,
|
||||
0x93, 0x5d, 0x32, 0xc7, 0x65, 0x63, 0x17, 0x13, 0x1f, 0x95, 0xa2, 0x91, 0xa9, 0x95, 0xe3, 0x53,
|
||||
0x68, 0xc8, 0x38, 0x19, 0x45, 0x93, 0x0b, 0xac, 0x0b, 0x6d, 0x46, 0x66, 0xb2, 0x07, 0x0f, 0xf3,
|
||||
0x78, 0xb9, 0xaf, 0x9a, 0xc0, 0x24, 0x33, 0x65, 0x1b, 0x8c, 0x77, 0x50, 0xbf, 0x85, 0x70, 0x36,
|
||||
0x59, 0xb4, 0x7c, 0xb2, 0xdc, 0x9e, 0x45, 0xfa, 0xdd, 0x59, 0x24, 0x38, 0x12, 0x8f, 0x5d, 0xc7,
|
||||
0x92, 0xe3, 0x52, 0x3d, 0x41, 0x55, 0xa5, 0x11, 0x13, 0xb3, 0x01, 0x1b, 0x03, 0x16, 0x5d, 0x8c,
|
||||
0x7d, 0x16, 0xda, 0x02, 0xa1, 0x3f, 0x35, 0x68, 0x64, 0x0a, 0x89, 0x9b, 0x98, 0xb6, 0xe9, 0xec,
|
||||
0x50, 0x37, 0x50, 0xf2, 0xe4, 0x90, 0x20, 0x5f, 0x40, 0x53, 0x1a, 0x2c, 0xdf, 0xf3, 0x50, 0x8e,
|
||||
0xdd, 0x28, 0xc1, 0x67, 0x53, 0xe8, 0xbf, 0xca, 0xd5, 0xe2, 0x16, 0x99, 0x6d, 0x87, 0x18, 0x45,
|
||||
0xb2, 0x84, 0x2a, 0x4d, 0x45, 0xf2, 0x0a, 0xd6, 0x23, 0x91, 0x46, 0xa2, 0x50, 0xeb, 0x6f, 0x2f,
|
||||
0xe0, 0x58, 0x7e, 0x61, 0x54, 0xf9, 0x92, 0x1d, 0x80, 0x3c, 0xa9, 0xfc, 0x97, 0x54, 0xe8, 0x8c,
|
||||
0x86, 0xec, 0x43, 0x29, 0x0e, 0xb8, 0x33, 0x45, 0xf9, 0x2b, 0xa9, 0xf5, 0xb7, 0x7a, 0xea, 0xbb,
|
||||
0xd7, 0x4b, 0xbf, 0x7b, 0xbd, 0x41, 0xf2, 0xdd, 0xa3, 0x89, 0x63, 0xff, 0x8f, 0x22, 0x34, 0x73,
|
||||
0xf6, 0x51, 0x99, 0x9a, 0x0c, 0x60, 0x5d, 0xea, 0xc8, 0xd6, 0x92, 0x37, 0x65, 0x68, 0xb7, 0x77,
|
||||
0x96, 0xcd, 0x29, 0x55, 0xb2, 0x51, 0x20, 0x6f, 0xa1, 0x92, 0x74, 0x2e, 0x92, 0xce, 0x7d, 0x8f,
|
||||
0x53, 0xfb, 0xd9, 0x7d, 0x1e, 0xaa, 0xf9, 0x8d, 0x42, 0x57, 0x7b, 0xa9, 0x91, 0x63, 0x58, 0x57,
|
||||
0x23, 0xfa, 0xf1, 0xaa, 0x71, 0xd9, 0x7e, 0xb2, 0xca, 0x9a, 0x55, 0xda, 0xd5, 0xc8, 0x1b, 0x28,
|
||||
0x25, 0x8f, 0xc2, 0xf6, 0x92, 0x2d, 0xca, 0xdc, 0xfe, 0x6c, 0xa5, 0x39, 0x3f, 0xfc, 0x40, 0x14,
|
||||
0x28, 0xee, 0xac, 0xbd, 0xf8, 0x66, 0x45, 0x5f, 0xb6, 0x57, 0xdf, 0xba, 0x51, 0x20, 0xdf, 0x42,
|
||||
0x35, 0x63, 0x25, 0x59, 0x80, 0xf8, 0x2c, 0x87, 0xdb, 0x9d, 0x15, 0x76, 0x99, 0xd2, 0x28, 0xbc,
|
||||
0xd4, 0x0e, 0xd7, 0xde, 0xea, 0xc1, 0x78, 0x5c, 0x92, 0x8c, 0x78, 0xf5, 0x4f, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x14, 0xe3, 0x9c, 0x65, 0x4c, 0x0c, 0x00, 0x00,
|
||||
var fileDescriptor_piecestore_ad8894e1f36b2897 = []byte{
|
||||
// 1121 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x6e, 0xdb, 0x46,
|
||||
0x10, 0x16, 0x29, 0x5b, 0xb2, 0x46, 0x3f, 0x56, 0x36, 0x46, 0x2b, 0x0b, 0xb1, 0x2d, 0x30, 0x4d,
|
||||
0xaa, 0x26, 0x80, 0x1c, 0x3b, 0x40, 0xef, 0x76, 0x65, 0x04, 0x42, 0x51, 0xc7, 0x5d, 0xd9, 0x97,
|
||||
0x1c, 0xca, 0xac, 0xc8, 0xb1, 0x4c, 0x84, 0x22, 0x55, 0x72, 0xe9, 0xda, 0x7e, 0x8b, 0x3e, 0x47,
|
||||
0xd1, 0xf7, 0x28, 0xd0, 0x7b, 0x0f, 0x3d, 0x04, 0xe8, 0x0b, 0xf4, 0xd8, 0x4b, 0x2f, 0xc5, 0xfe,
|
||||
0x88, 0xb4, 0xad, 0xbf, 0x22, 0x80, 0x6f, 0x3b, 0x3f, 0x3b, 0x33, 0xfb, 0xcd, 0xb7, 0x3b, 0x0b,
|
||||
0xf5, 0xb1, 0x87, 0x0e, 0xc6, 0x3c, 0x8c, 0xb0, 0x33, 0x8e, 0x42, 0x1e, 0x92, 0x5b, 0x9a, 0x28,
|
||||
0x4c, 0x38, 0xc6, 0x4d, 0x08, 0x42, 0x57, 0x5b, 0x9b, 0x30, 0x0c, 0x87, 0xa1, 0x5e, 0x6f, 0x0f,
|
||||
0xc3, 0x70, 0xe8, 0xe3, 0xae, 0x94, 0x06, 0xc9, 0xf9, 0xae, 0x9b, 0x44, 0x8c, 0x7b, 0x61, 0xa0,
|
||||
0xec, 0xd6, 0xbf, 0x79, 0x68, 0x9c, 0xb0, 0x6b, 0x8c, 0x0e, 0x59, 0xe0, 0xfe, 0xe4, 0xb9, 0xfc,
|
||||
0xe2, 0xc0, 0xf7, 0x43, 0x47, 0xba, 0x90, 0x0d, 0x58, 0x75, 0x30, 0xe2, 0x71, 0xc3, 0x68, 0xe5,
|
||||
0xdb, 0x15, 0xaa, 0x04, 0xf2, 0x04, 0x4a, 0xb1, 0x37, 0x0c, 0x18, 0x4f, 0x22, 0x6c, 0x98, 0x2d,
|
||||
0xa3, 0x5d, 0xa1, 0x99, 0x82, 0x10, 0x58, 0x71, 0x19, 0x67, 0x8d, 0xbc, 0x34, 0xc8, 0x75, 0xf3,
|
||||
0x77, 0x13, 0x56, 0xba, 0x8c, 0x33, 0xb2, 0x07, 0x95, 0x98, 0x71, 0xf4, 0x7d, 0x8f, 0xa3, 0xed,
|
||||
0xb9, 0x0d, 0x43, 0x38, 0x1d, 0xd6, 0x7e, 0xfb, 0xb8, 0x93, 0xfb, 0xf3, 0xe3, 0x4e, 0xe1, 0x38,
|
||||
0x74, 0xb1, 0xd7, 0xa5, 0xe5, 0xd4, 0xa7, 0xe7, 0x92, 0x97, 0x50, 0x4a, 0xc6, 0xbe, 0x17, 0x7c,
|
||||
0x10, 0xfe, 0xe6, 0x4c, 0xff, 0x35, 0xe5, 0xd0, 0x73, 0xc9, 0x26, 0xac, 0x8d, 0xd8, 0x95, 0x1d,
|
||||
0x7b, 0x37, 0x28, 0x0b, 0xc8, 0xd3, 0xe2, 0x88, 0x5d, 0xf5, 0xbd, 0x1b, 0x24, 0x1d, 0x78, 0x8c,
|
||||
0x57, 0x63, 0x4f, 0x1d, 0xde, 0x4e, 0x02, 0xef, 0xca, 0x8e, 0xd1, 0x69, 0xac, 0x48, 0xaf, 0x47,
|
||||
0x99, 0xe9, 0x2c, 0xf0, 0xae, 0xfa, 0xe8, 0x90, 0xa7, 0x50, 0x8d, 0x31, 0xf2, 0x98, 0x6f, 0x07,
|
||||
0xc9, 0x68, 0x80, 0x51, 0x63, 0xb5, 0x65, 0xb4, 0x4b, 0xb4, 0xa2, 0x94, 0xc7, 0x52, 0x47, 0x7a,
|
||||
0x50, 0x60, 0x8e, 0xd8, 0xd5, 0x28, 0xb4, 0x8c, 0x76, 0x6d, 0x7f, 0xaf, 0x73, 0xbf, 0x31, 0x9d,
|
||||
0x79, 0xe0, 0x76, 0x0e, 0xe4, 0x46, 0xaa, 0x03, 0x90, 0x36, 0xd4, 0x9d, 0x08, 0x19, 0x47, 0x37,
|
||||
0x2b, 0xae, 0x28, 0x8b, 0xab, 0x69, 0xbd, 0xae, 0xcc, 0xea, 0x41, 0x41, 0xed, 0x25, 0x45, 0xc8,
|
||||
0x9f, 0x9c, 0x9d, 0xd6, 0x73, 0x62, 0xf1, 0xe6, 0xe8, 0xb4, 0x6e, 0x90, 0x2a, 0x94, 0xde, 0x1c,
|
||||
0x9d, 0xda, 0x07, 0x67, 0xdd, 0xde, 0x69, 0xdd, 0x24, 0x35, 0x00, 0x21, 0xd2, 0xa3, 0x93, 0x83,
|
||||
0x1e, 0xad, 0xe7, 0x85, 0x7c, 0x72, 0x96, 0xca, 0x2b, 0xd6, 0xcf, 0x26, 0x6c, 0x52, 0x0c, 0xf8,
|
||||
0xc3, 0xb6, 0xff, 0x17, 0x43, 0xb7, 0xff, 0x0c, 0xea, 0x63, 0x01, 0x87, 0xcd, 0xd2, 0x24, 0x92,
|
||||
0x02, 0xe5, 0xfd, 0x17, 0xff, 0x1f, 0x38, 0xba, 0x2e, 0x63, 0xdc, 0xad, 0x93, 0x87, 0x9c, 0xf9,
|
||||
0xb2, 0x9a, 0x3c, 0x55, 0x02, 0xf9, 0x1a, 0xd6, 0x45, 0x38, 0x36, 0x44, 0x5b, 0xdc, 0x0d, 0x41,
|
||||
0x9f, 0xfc, 0x4c, 0xfa, 0x54, 0xb5, 0x9b, 0x14, 0x5d, 0xeb, 0x2f, 0x13, 0xe0, 0x44, 0x14, 0xd3,
|
||||
0x17, 0xc5, 0x90, 0x1f, 0x60, 0x63, 0x30, 0x29, 0x62, 0xba, 0xee, 0x97, 0xd3, 0x75, 0xcf, 0xc5,
|
||||
0x93, 0x3e, 0x1e, 0xcc, 0x00, 0xf9, 0x08, 0x40, 0x86, 0xb0, 0x25, 0x6c, 0xa6, 0x8c, 0xfa, 0x7c,
|
||||
0x06, 0x1a, 0x69, 0x45, 0x6a, 0x29, 0xf0, 0xa4, 0xa5, 0xf1, 0x64, 0x49, 0x8e, 0xa0, 0xca, 0x12,
|
||||
0x7e, 0x11, 0x46, 0xde, 0x8d, 0xaa, 0x2f, 0x2f, 0x23, 0xed, 0x4c, 0x47, 0xea, 0x7b, 0xc3, 0x00,
|
||||
0xdd, 0xef, 0x30, 0x8e, 0xd9, 0x10, 0xe9, 0xdd, 0x5d, 0x4d, 0x84, 0x52, 0x1a, 0x9e, 0xd4, 0xc0,
|
||||
0xd4, 0x77, 0xb4, 0x44, 0x4d, 0xcf, 0x9d, 0x77, 0x85, 0xcc, 0x79, 0x57, 0xa8, 0x01, 0x45, 0x27,
|
||||
0x0c, 0x38, 0x06, 0x5c, 0xd3, 0x61, 0x22, 0x5a, 0xef, 0xa1, 0x28, 0xd3, 0xf4, 0xdc, 0xa9, 0x24,
|
||||
0x53, 0x07, 0x31, 0x3f, 0xe5, 0x20, 0xd6, 0x08, 0x2a, 0x0a, 0xb2, 0x64, 0x34, 0x62, 0xd1, 0xf5,
|
||||
0x54, 0x9a, 0xad, 0x09, 0xec, 0xf2, 0xad, 0x50, 0x47, 0x50, 0x70, 0x2e, 0x7a, 0x2d, 0xf2, 0x73,
|
||||
0x8e, 0x6a, 0xfd, 0x61, 0x42, 0x4d, 0xe6, 0xa3, 0xc8, 0x23, 0x0f, 0x2f, 0x99, 0xff, 0xe0, 0xc4,
|
||||
0xe9, 0xcd, 0x20, 0xce, 0x8b, 0x39, 0xc4, 0x49, 0xab, 0x7a, 0x50, 0xf2, 0xd0, 0x45, 0xe4, 0x59,
|
||||
0x02, 0xf8, 0x67, 0x50, 0x08, 0xcf, 0xcf, 0x63, 0xe4, 0x1a, 0x63, 0x2d, 0x59, 0x6f, 0x61, 0xe3,
|
||||
0xee, 0x09, 0xfa, 0x3c, 0x42, 0x36, 0xba, 0x17, 0xce, 0xb8, 0x1f, 0xee, 0x16, 0xf5, 0xcc, 0xbb,
|
||||
0xd4, 0x73, 0xa1, 0xac, 0x8a, 0x44, 0x1f, 0x39, 0x2e, 0xa7, 0xdf, 0x27, 0x41, 0x61, 0x75, 0x80,
|
||||
0xdc, 0xca, 0x32, 0x21, 0x61, 0x03, 0x8a, 0x23, 0xe5, 0xaf, 0x33, 0x4e, 0x44, 0xeb, 0x14, 0x1e,
|
||||
0x65, 0x37, 0x7c, 0xa9, 0x3b, 0x79, 0x06, 0x35, 0xf9, 0xc8, 0xd9, 0x11, 0x3a, 0xe8, 0x5d, 0xa2,
|
||||
0xab, 0x01, 0xad, 0x4a, 0x2d, 0xd5, 0x4a, 0x0b, 0x60, 0xad, 0xcf, 0x19, 0x8f, 0x29, 0xfe, 0x68,
|
||||
0xfd, 0x6a, 0x40, 0x59, 0x08, 0x93, 0xe0, 0x5b, 0x00, 0x49, 0x8c, 0xae, 0x1d, 0x8f, 0x99, 0x93,
|
||||
0x02, 0x28, 0x34, 0x7d, 0xa1, 0x20, 0x5f, 0xc2, 0x3a, 0xbb, 0x64, 0x9e, 0xcf, 0x06, 0x3e, 0x6a,
|
||||
0x1f, 0x95, 0xa2, 0x96, 0xaa, 0x95, 0xe3, 0x33, 0xa8, 0xc9, 0x38, 0x29, 0x45, 0x75, 0x03, 0xab,
|
||||
0x42, 0x9b, 0x92, 0x99, 0xec, 0xc2, 0xe3, 0x2c, 0x5e, 0xe6, 0xab, 0xc6, 0x2f, 0x49, 0x4d, 0xe9,
|
||||
0x06, 0xeb, 0x3d, 0x54, 0xef, 0x20, 0x9c, 0x4e, 0x16, 0x23, 0x9b, 0x2c, 0x4b, 0x66, 0x91, 0xe0,
|
||||
0x48, 0x32, 0xf0, 0x3d, 0xc7, 0xfe, 0x80, 0xd7, 0xfa, 0x09, 0x2a, 0x29, 0xcd, 0xb7, 0x78, 0x6d,
|
||||
0xd5, 0xa0, 0xd2, 0x65, 0xf1, 0xc5, 0x20, 0x64, 0x91, 0x2b, 0x10, 0xfa, 0xc7, 0x80, 0x5a, 0xaa,
|
||||
0x90, 0xb8, 0x91, 0xcf, 0xa1, 0x38, 0x99, 0x1d, 0xaa, 0x03, 0x85, 0x40, 0x0e, 0x09, 0xf2, 0x15,
|
||||
0xd4, 0xa5, 0xc1, 0x09, 0x83, 0x00, 0xe5, 0x30, 0x8e, 0x35, 0x3e, 0xeb, 0x42, 0xff, 0x4d, 0xa6,
|
||||
0x16, 0x5d, 0x64, 0xae, 0x1b, 0x61, 0x1c, 0xcb, 0x12, 0x4a, 0x74, 0x22, 0x92, 0xd7, 0xb0, 0x1a,
|
||||
0x8b, 0x34, 0x12, 0x85, 0xf2, 0xfe, 0xd6, 0x0c, 0x8e, 0x65, 0x0d, 0xa3, 0xca, 0x97, 0x6c, 0x03,
|
||||
0x64, 0x49, 0xe5, 0xa7, 0x64, 0x8d, 0xde, 0xd2, 0x90, 0x3d, 0x28, 0x24, 0x63, 0xee, 0x8d, 0x50,
|
||||
0x7e, 0x49, 0xca, 0xfb, 0x9b, 0x1d, 0xf5, 0x03, 0xec, 0x4c, 0x7e, 0x80, 0x9d, 0xae, 0xfe, 0x01,
|
||||
0x52, 0xed, 0xb8, 0xff, 0x77, 0x1e, 0xea, 0x19, 0xfb, 0xa8, 0x4c, 0x4d, 0xba, 0xb0, 0x2a, 0x75,
|
||||
0x64, 0x73, 0xce, 0x9b, 0xd2, 0x73, 0x9b, 0xdb, 0xf3, 0xe6, 0x94, 0x2a, 0xd9, 0xca, 0x91, 0x77,
|
||||
0xb0, 0xa6, 0x6f, 0x2e, 0x92, 0xd6, 0xb2, 0xc7, 0xa9, 0xf9, 0x7c, 0x99, 0x87, 0xba, 0xfc, 0x56,
|
||||
0xae, 0x6d, 0xbc, 0x32, 0xc8, 0x31, 0xac, 0xaa, 0x11, 0xfd, 0x64, 0xd1, 0xb8, 0x6c, 0x3e, 0x5d,
|
||||
0x64, 0x4d, 0x2b, 0x6d, 0x1b, 0xe4, 0x2d, 0x14, 0xf4, 0xa3, 0xb0, 0x35, 0x67, 0x8b, 0x32, 0x37,
|
||||
0xbf, 0x58, 0x68, 0xce, 0x0e, 0xdf, 0x15, 0x05, 0x8a, 0x9e, 0x35, 0x67, 0x77, 0x56, 0xdc, 0xcb,
|
||||
0xe6, 0xe2, 0xae, 0x5b, 0x39, 0xf2, 0x3d, 0x94, 0x52, 0x56, 0x92, 0x19, 0x88, 0xdf, 0xe6, 0x70,
|
||||
0xb3, 0xb5, 0xc0, 0x2e, 0x53, 0x5a, 0xb9, 0x57, 0xc6, 0xe1, 0xca, 0x3b, 0x73, 0x3c, 0x18, 0x14,
|
||||
0x24, 0x23, 0x5e, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xc4, 0x7c, 0xff, 0x5a, 0x5f, 0x0c, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ message PayerBandwidthAllocation { // Payer refers to satellite
|
||||
string serial_number = 5; // Unique serial number
|
||||
Action action = 6; // GET or PUT
|
||||
int64 created_unix_sec = 7; // Unix timestamp for when PayerbandwidthAllocation was created
|
||||
bytes pub_key = 8; // Renter Public Key
|
||||
}
|
||||
|
||||
bytes signature = 1; // Seralized Data signed by Satellite
|
||||
bytes data = 2; // Serialization of above Data Struct
|
||||
repeated bytes certs = 1; // Satellite certificate chain
|
||||
bytes signature = 2; // Proof that the data was signed by the Satellite
|
||||
bytes data = 3; // Serialization of above Data Struct
|
||||
}
|
||||
|
||||
message RenterBandwidthAllocation { // Renter refers to uplink
|
||||
@ -56,8 +56,9 @@ message RenterBandwidthAllocation { // Renter refers to uplink
|
||||
bytes storage_node_id = 3 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false]; // Storage Node Identity
|
||||
}
|
||||
|
||||
bytes signature = 1; // Seralized Data signed by Uplink
|
||||
bytes data = 2; // Serialization of above Data Struct
|
||||
repeated bytes certs = 1; // Uplink certificate chain
|
||||
bytes signature = 2; // Proof that the data was signed by the Uplink
|
||||
bytes data = 3; // Serialization of above Data Struct
|
||||
}
|
||||
|
||||
message PieceStore {
|
||||
|
@ -5,7 +5,6 @@ package psclient
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"flag"
|
||||
"fmt"
|
||||
@ -19,6 +18,7 @@ import (
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"storj.io/storj/internal/memory"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/ranger"
|
||||
"storj.io/storj/pkg/storj"
|
||||
@ -55,9 +55,9 @@ type Client interface {
|
||||
type PieceStore struct {
|
||||
closeFunc func() error // function that closes the transport connection
|
||||
client pb.PieceStoreRoutesClient // PieceStore for interacting with Storage Node
|
||||
prikey crypto.PrivateKey // Uplink private key
|
||||
selfID *identity.FullIdentity // This client's (an uplink) identity
|
||||
bandwidthMsgSize int // max bandwidth message size in bytes
|
||||
nodeID storj.NodeID // Storage node being connected to
|
||||
remoteID storj.NodeID // Storage node being connected to
|
||||
}
|
||||
|
||||
// NewPSClient initilizes a piecestore client
|
||||
@ -80,13 +80,13 @@ func NewPSClient(ctx context.Context, tc transport.Client, n *pb.Node, bandwidth
|
||||
closeFunc: conn.Close,
|
||||
client: pb.NewPieceStoreRoutesClient(conn),
|
||||
bandwidthMsgSize: bandwidthMsgSize,
|
||||
prikey: tc.Identity().Key,
|
||||
nodeID: n.Id,
|
||||
selfID: tc.Identity(),
|
||||
remoteID: n.Id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewCustomRoute creates new PieceStore with custom client interface
|
||||
func NewCustomRoute(client pb.PieceStoreRoutesClient, target *pb.Node, bandwidthMsgSize int, prikey crypto.PrivateKey) (*PieceStore, error) {
|
||||
func NewCustomRoute(client pb.PieceStoreRoutesClient, target *pb.Node, bandwidthMsgSize int, selfID *identity.FullIdentity) (*PieceStore, error) {
|
||||
target.Type.DPanicOnInvalid("new custom route")
|
||||
if bandwidthMsgSize < 0 || bandwidthMsgSize > maxBandwidthMsgSize.Int() {
|
||||
return nil, ClientError.New("invalid Bandwidth Message Size: %v", bandwidthMsgSize)
|
||||
@ -99,8 +99,8 @@ func NewCustomRoute(client pb.PieceStoreRoutesClient, target *pb.Node, bandwidth
|
||||
return &PieceStore{
|
||||
client: client,
|
||||
bandwidthMsgSize: bandwidthMsgSize,
|
||||
prikey: prikey,
|
||||
nodeID: target.Id,
|
||||
selfID: selfID,
|
||||
remoteID: target.Id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -185,10 +185,13 @@ func (ps *PieceStore) Delete(ctx context.Context, id PieceID, authorization *pb.
|
||||
|
||||
// sign a message using the clients private key
|
||||
func (ps *PieceStore) sign(msg []byte) (signature []byte, err error) {
|
||||
if ps.prikey == nil {
|
||||
if ps.selfID == nil || ps.selfID.Key == nil {
|
||||
return nil, ClientError.New("failed to sign msg: Private Key not Set")
|
||||
}
|
||||
|
||||
// use c.pkey to sign msg
|
||||
return cryptopasta.Sign(msg, ps.prikey.(*ecdsa.PrivateKey))
|
||||
return cryptopasta.Sign(msg, ps.selfID.Key.(*ecdsa.PrivateKey))
|
||||
}
|
||||
|
||||
//certs returns this uplink's certificates
|
||||
func (ps *PieceStore) certs() [][]byte {
|
||||
return ps.selfID.ChainRaw()
|
||||
}
|
||||
|
@ -5,9 +5,6 @@ package psclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -16,6 +13,8 @@ import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/internal/testidentity"
|
||||
"storj.io/storj/internal/teststorj"
|
||||
"storj.io/storj/pkg/pb"
|
||||
)
|
||||
@ -45,8 +44,10 @@ func TestPieceRanger(t *testing.T) {
|
||||
} {
|
||||
errTag := fmt.Sprintf("Test case #%d", i)
|
||||
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.Nil(t, err)
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
id, err := testidentity.NewTestIdentity(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
route := pb.NewMockPieceStoreRoutesClient(ctrl)
|
||||
|
||||
@ -74,8 +75,6 @@ func TestPieceRanger(t *testing.T) {
|
||||
stream.EXPECT().Recv().Return(&pb.PieceRetrievalStream{}, io.EOF)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
target := &pb.Node{
|
||||
Address: &pb.NodeAddress{
|
||||
Address: "",
|
||||
@ -85,7 +84,7 @@ func TestPieceRanger(t *testing.T) {
|
||||
Type: pb.NodeType_STORAGE,
|
||||
}
|
||||
target.Type.DPanicOnInvalid("pr test")
|
||||
c, err := NewCustomRoute(route, target, 32*1024, priv)
|
||||
c, err := NewCustomRoute(route, target, 32*1024, id)
|
||||
assert.NoError(t, err)
|
||||
rr, err := PieceRanger(ctx, c, stream, pid, &pb.PayerBandwidthAllocation{}, nil)
|
||||
if assert.NoError(t, err, errTag) {
|
||||
@ -108,6 +107,11 @@ func TestPieceRangerSize(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
id, err := testidentity.NewTestIdentity(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
for i, tt := range []struct {
|
||||
data string
|
||||
size, offset, length int64
|
||||
@ -134,9 +138,6 @@ func TestPieceRangerSize(t *testing.T) {
|
||||
|
||||
stream := pb.NewMockPieceStoreRoutes_RetrieveClient(ctrl)
|
||||
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
if tt.offset >= 0 && tt.length > 0 && tt.offset+tt.length <= tt.size {
|
||||
msg1 := &pb.PieceRetrieval{
|
||||
PieceData: &pb.PieceRetrieval_PieceData{
|
||||
@ -165,7 +166,7 @@ func TestPieceRangerSize(t *testing.T) {
|
||||
Type: pb.NodeType_STORAGE,
|
||||
}
|
||||
target.Type.DPanicOnInvalid("pr test 2")
|
||||
c, err := NewCustomRoute(route, target, 32*1024, priv)
|
||||
c, err := NewCustomRoute(route, target, 32*1024, id)
|
||||
assert.NoError(t, err)
|
||||
rr := PieceRangerSize(c, stream, pid, tt.size, &pb.PayerBandwidthAllocation{}, nil)
|
||||
assert.Equal(t, tt.size, rr.Size(), errTag)
|
||||
|
@ -25,13 +25,13 @@ type StreamWriter struct {
|
||||
// Write Piece data to a piece store server upload stream
|
||||
func (s *StreamWriter) Write(b []byte) (int, error) {
|
||||
updatedAllocation := s.totalWritten + int64(len(b))
|
||||
allocationData := &pb.RenterBandwidthAllocation_Data{
|
||||
renterBWA := &pb.RenterBandwidthAllocation_Data{
|
||||
PayerAllocation: s.pba,
|
||||
Total: updatedAllocation,
|
||||
StorageNodeId: s.signer.nodeID,
|
||||
StorageNodeId: s.signer.remoteID,
|
||||
}
|
||||
|
||||
serializedAllocation, err := proto.Marshal(allocationData)
|
||||
serializedAllocation, err := proto.Marshal(renterBWA)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -44,7 +44,9 @@ func (s *StreamWriter) Write(b []byte) (int, error) {
|
||||
msg := &pb.PieceStore{
|
||||
PieceData: &pb.PieceStore_PieceData{Content: b},
|
||||
BandwidthAllocation: &pb.RenterBandwidthAllocation{
|
||||
Data: serializedAllocation, Signature: sig,
|
||||
Data: serializedAllocation,
|
||||
Signature: sig,
|
||||
Certs: s.signer.certs(),
|
||||
},
|
||||
}
|
||||
|
||||
@ -93,6 +95,7 @@ func NewStreamReader(client *PieceStore, stream pb.PieceStoreRoutes_RetrieveClie
|
||||
// TODO: make these flag/config-file configurable
|
||||
trustLimit := int64(client.bandwidthMsgSize * 64)
|
||||
sendThreshold := int64(client.bandwidthMsgSize * 8)
|
||||
certs := client.certs()
|
||||
|
||||
// Send signed allocations to the piece store server
|
||||
go func() {
|
||||
@ -109,7 +112,7 @@ func NewStreamReader(client *PieceStore, stream pb.PieceStoreRoutes_RetrieveClie
|
||||
allocationData := &pb.RenterBandwidthAllocation_Data{
|
||||
PayerAllocation: pba,
|
||||
Total: sr.allocated + allocate,
|
||||
StorageNodeId: sr.client.nodeID,
|
||||
StorageNodeId: sr.client.remoteID,
|
||||
}
|
||||
|
||||
serializedAllocation, err := proto.Marshal(allocationData)
|
||||
@ -128,6 +131,7 @@ func NewStreamReader(client *PieceStore, stream pb.PieceStoreRoutes_RetrieveClie
|
||||
BandwidthAllocation: &pb.RenterBandwidthAllocation{
|
||||
Signature: sig,
|
||||
Data: serializedAllocation,
|
||||
Certs: certs,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ func (s *Server) retrieveData(ctx context.Context, stream pb.PieceStoreRoutes_Re
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.verifySignature(ctx, alloc); err != nil {
|
||||
if err = s.verifySignature(stream.Context(), alloc); err != nil {
|
||||
allocationTracking.Fail(err)
|
||||
return
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ package psserver
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/hmac"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
@ -17,19 +16,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/gtank/cryptopasta"
|
||||
"github.com/mr-tron/base58/base58"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"storj.io/storj/pkg/auth"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/kademlia"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/peertls"
|
||||
pstore "storj.io/storj/pkg/piecestore"
|
||||
"storj.io/storj/pkg/piecestore/psserver/psdb"
|
||||
"storj.io/storj/pkg/provider"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
@ -262,12 +259,10 @@ func (s *Server) Dashboard(in *pb.DashboardReq, stream pb.PieceStoreRoutes_Dashb
|
||||
// Delete -- Delete data by Id from piecestore
|
||||
func (s *Server) Delete(ctx context.Context, in *pb.PieceDelete) (*pb.PieceDeleteSummary, error) {
|
||||
s.log.Debug("Deleting", zap.String("Piece ID", fmt.Sprint(in.GetId())))
|
||||
|
||||
authorization := in.GetAuthorization()
|
||||
if err := s.verifier(authorization); err != nil {
|
||||
return nil, ServerError.Wrap(err)
|
||||
}
|
||||
|
||||
id, err := getNamespacedPieceID([]byte(in.GetId()), getNamespace(authorization))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -285,28 +280,43 @@ func (s *Server) deleteByID(id string) error {
|
||||
if err := s.storage.Delete(id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.DB.DeleteTTLByID(id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) verifySignature(ctx context.Context, ba *pb.RenterBandwidthAllocation) error {
|
||||
func (s *Server) verifySignature(ctx context.Context, rba *pb.RenterBandwidthAllocation) error {
|
||||
// TODO(security): detect replay attacks
|
||||
pi, err := provider.PeerIdentityFromContext(ctx)
|
||||
_, pba, pbad, err := rba.Unpack()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k, ok := pi.Leaf.PublicKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return peertls.ErrUnsupportedKey.New("%T", pi.Leaf.PublicKey)
|
||||
//verify message content
|
||||
pi, err := identity.PeerIdentityFromContext(ctx)
|
||||
if err != nil || pbad.UplinkId != pi.ID {
|
||||
return auth.BadID.New("Uplink Node ID: %s vs %s", pbad.UplinkId, pi.ID)
|
||||
}
|
||||
|
||||
if ok := cryptopasta.Verify(ba.GetData(), ba.GetSignature(), k); !ok {
|
||||
return ServerError.New("failed to verify Signature")
|
||||
//todo: use whitelist for uplinks?
|
||||
//todo: use whitelist for satellites?
|
||||
switch {
|
||||
case len(pbad.SerialNumber) == 0:
|
||||
return pb.Payer.Wrap(pb.Missing.New("serial"))
|
||||
case pbad.SatelliteId.IsZero():
|
||||
return pb.Payer.Wrap(pb.Missing.New("satellite id"))
|
||||
case pbad.UplinkId.IsZero():
|
||||
return pb.Payer.Wrap(pb.Missing.New("uplink id"))
|
||||
}
|
||||
exp := time.Unix(pbad.GetExpirationUnixSec(), 0).UTC()
|
||||
if exp.Before(time.Now().UTC()) {
|
||||
return pb.Payer.Wrap(auth.Expired.New("%v vs %v", exp, time.Now().UTC()))
|
||||
}
|
||||
//verify message crypto
|
||||
if err := auth.VerifyMsg(rba, pbad.UplinkId); err != nil {
|
||||
return pb.Renter.Wrap(err)
|
||||
}
|
||||
if err := auth.VerifyMsg(pba, pbad.SatelliteId); err != nil {
|
||||
return pb.Payer.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -4,12 +4,9 @@
|
||||
package psserver
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"os"
|
||||
@ -17,9 +14,9 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gtank/cryptopasta"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zeebo/errs"
|
||||
@ -29,37 +26,29 @@ import (
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/internal/testidentity"
|
||||
"storj.io/storj/internal/teststorj"
|
||||
"storj.io/storj/pkg/bwagreement/test"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
pstore "storj.io/storj/pkg/piecestore"
|
||||
"storj.io/storj/pkg/piecestore/psserver/psdb"
|
||||
"storj.io/storj/pkg/server"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
func (TS *TestServer) writeFile(pieceID string) error {
|
||||
file, err := TS.s.storage.Writer(pieceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = file.Write([]byte("xyzwq"))
|
||||
return errs.Combine(err, file.Close())
|
||||
|
||||
}
|
||||
|
||||
func TestPiece(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
TS := NewTestServer(t, []storj.NodeID{})
|
||||
defer TS.Stop()
|
||||
snID, upID := newTestID(ctx, t), newTestID(ctx, t)
|
||||
s, c, cleanup := NewTest(ctx, t, snID, upID, []storj.NodeID{})
|
||||
defer cleanup()
|
||||
|
||||
if err := TS.writeFile("11111111111111111111"); err != nil {
|
||||
if err := writeFile(s, "11111111111111111111"); err != nil {
|
||||
t.Errorf("Error: %v\nCould not create test piece", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() { _ = TS.s.storage.Delete("11111111111111111111") }()
|
||||
defer func() { _ = s.storage.Delete("11111111111111111111") }()
|
||||
|
||||
// set up test cases
|
||||
tests := []struct {
|
||||
@ -85,7 +74,7 @@ func TestPiece(t *testing.T) {
|
||||
size: 5,
|
||||
expiration: 9999999999,
|
||||
err: fmt.Sprintf("rpc error: code = Unknown desc = stat %s: no such file or directory", func() string {
|
||||
path, _ := TS.s.storage.PiecePath("22222222222222222222")
|
||||
path, _ := s.storage.PiecePath("22222222222222222222")
|
||||
return path
|
||||
}()),
|
||||
},
|
||||
@ -102,16 +91,16 @@ func TestPiece(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// simulate piece TTL entry
|
||||
_, err := TS.s.DB.DB.Exec(fmt.Sprintf(`INSERT INTO ttl (id, created, expires) VALUES ("%s", "%d", "%d")`, tt.id, 1234567890, tt.expiration))
|
||||
_, err := s.DB.DB.Exec(fmt.Sprintf(`INSERT INTO ttl (id, created, expires) VALUES ("%s", "%d", "%d")`, tt.id, 1234567890, tt.expiration))
|
||||
assert.NoError(err)
|
||||
|
||||
defer func() {
|
||||
_, err := TS.s.DB.DB.Exec(fmt.Sprintf(`DELETE FROM ttl WHERE id="%s"`, tt.id))
|
||||
_, err := s.DB.DB.Exec(fmt.Sprintf(`DELETE FROM ttl WHERE id="%s"`, tt.id))
|
||||
assert.NoError(err)
|
||||
}()
|
||||
|
||||
req := &pb.PieceId{Id: tt.id}
|
||||
resp, err := TS.c.Piece(ctx, req)
|
||||
resp, err := c.Piece(ctx, req)
|
||||
|
||||
if tt.err != "" {
|
||||
assert.NotNil(err)
|
||||
@ -133,20 +122,19 @@ func TestPiece(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetrieve(t *testing.T) {
|
||||
t.Skip("broken test")
|
||||
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
TS := NewTestServer(t, []storj.NodeID{})
|
||||
defer TS.Stop()
|
||||
snID, upID := newTestID(ctx, t), newTestID(ctx, t)
|
||||
s, c, cleanup := NewTest(ctx, t, snID, upID, []storj.NodeID{})
|
||||
defer cleanup()
|
||||
|
||||
if err := TS.writeFile("11111111111111111111"); err != nil {
|
||||
if err := writeFile(s, "11111111111111111111"); err != nil {
|
||||
t.Errorf("Error: %v\nCould not create test piece", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() { _ = TS.s.storage.Delete("11111111111111111111") }()
|
||||
defer func() { _ = s.storage.Delete("11111111111111111111") }()
|
||||
|
||||
// set up test cases
|
||||
tests := []struct {
|
||||
@ -182,7 +170,7 @@ func TestRetrieve(t *testing.T) {
|
||||
respSize: 3,
|
||||
allocSize: 3,
|
||||
offset: 0,
|
||||
content: []byte("but"),
|
||||
content: []byte("xyz"),
|
||||
err: "",
|
||||
},
|
||||
{ // should successfully retrieve data
|
||||
@ -211,7 +199,7 @@ func TestRetrieve(t *testing.T) {
|
||||
offset: 0,
|
||||
content: []byte("xyzwq"),
|
||||
err: fmt.Sprintf("rpc error: code = Unknown desc = retrieve error: stat %s: no such file or directory", func() string {
|
||||
path, _ := TS.s.storage.PiecePath("22222222222222222222")
|
||||
path, _ := s.storage.PiecePath("22222222222222222222")
|
||||
return path
|
||||
}()),
|
||||
},
|
||||
@ -221,7 +209,7 @@ func TestRetrieve(t *testing.T) {
|
||||
respSize: 4,
|
||||
allocSize: 5,
|
||||
offset: 1,
|
||||
content: []byte("utts"),
|
||||
content: []byte("yzwq"),
|
||||
err: "",
|
||||
},
|
||||
{ // server should return expected content with reduced reqSize
|
||||
@ -230,7 +218,7 @@ func TestRetrieve(t *testing.T) {
|
||||
respSize: 4,
|
||||
allocSize: 5,
|
||||
offset: 0,
|
||||
content: []byte("butt"),
|
||||
content: []byte("xyzw"),
|
||||
err: "",
|
||||
},
|
||||
}
|
||||
@ -238,13 +226,16 @@ func TestRetrieve(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run("should return expected PieceRetrievalStream values", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
stream, err := TS.c.Retrieve(ctx)
|
||||
stream, err := c.Retrieve(ctx)
|
||||
assert.NoError(err)
|
||||
|
||||
// send piece database
|
||||
err = stream.Send(&pb.PieceRetrieval{PieceData: &pb.PieceRetrieval_PieceData{Id: tt.id, PieceSize: tt.reqSize, Offset: tt.offset}})
|
||||
assert.NoError(err)
|
||||
|
||||
pba, err := test.GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_GET, snID, upID, time.Hour)
|
||||
assert.NoError(err)
|
||||
|
||||
totalAllocated := int64(0)
|
||||
var data string
|
||||
var totalRetrieved = int64(0)
|
||||
@ -253,20 +244,12 @@ func TestRetrieve(t *testing.T) {
|
||||
// Send bandwidth bandwidthAllocation
|
||||
totalAllocated += tt.allocSize
|
||||
|
||||
ba := pb.RenterBandwidthAllocation{
|
||||
Data: serializeData(&pb.RenterBandwidthAllocation_Data{
|
||||
PayerAllocation: &pb.PayerBandwidthAllocation{},
|
||||
Total: totalAllocated,
|
||||
}),
|
||||
}
|
||||
|
||||
s, err := cryptopasta.Sign(ba.Data, TS.k.(*ecdsa.PrivateKey))
|
||||
rba, err := test.GenerateRenterBandwidthAllocation(pba, snID.ID, upID, totalAllocated)
|
||||
assert.NoError(err)
|
||||
ba.Signature = s
|
||||
|
||||
err = stream.Send(
|
||||
&pb.PieceRetrieval{
|
||||
BandwidthAllocation: &ba,
|
||||
BandwidthAllocation: rba,
|
||||
},
|
||||
)
|
||||
assert.NoError(err)
|
||||
@ -300,7 +283,7 @@ func TestStore(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
satID := teststorj.NodeIDFromString("satelliteid")
|
||||
satID := newTestID(ctx, t)
|
||||
|
||||
tests := []struct {
|
||||
id string
|
||||
@ -314,7 +297,7 @@ func TestStore(t *testing.T) {
|
||||
}{
|
||||
{ // should successfully store data with no approved satellites
|
||||
id: "99999999999999999999",
|
||||
satelliteID: satID,
|
||||
satelliteID: satID.ID,
|
||||
whitelist: []storj.NodeID{},
|
||||
ttl: 9999999999,
|
||||
content: []byte("xyzwq"),
|
||||
@ -324,8 +307,8 @@ func TestStore(t *testing.T) {
|
||||
},
|
||||
{ // should err with invalid id length
|
||||
id: "butts",
|
||||
satelliteID: satID,
|
||||
whitelist: []storj.NodeID{satID},
|
||||
satelliteID: satID.ID,
|
||||
whitelist: []storj.NodeID{satID.ID},
|
||||
ttl: 9999999999,
|
||||
content: []byte("xyzwq"),
|
||||
message: "",
|
||||
@ -334,8 +317,8 @@ func TestStore(t *testing.T) {
|
||||
},
|
||||
{ // should err with piece ID not specified
|
||||
id: "",
|
||||
satelliteID: satID,
|
||||
whitelist: []storj.NodeID{satID},
|
||||
satelliteID: satID.ID,
|
||||
whitelist: []storj.NodeID{satID.ID},
|
||||
ttl: 9999999999,
|
||||
content: []byte("xyzwq"),
|
||||
message: "",
|
||||
@ -346,41 +329,27 @@ func TestStore(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run("should return expected PieceStoreSummary values", func(t *testing.T) {
|
||||
TS := NewTestServer(t, tt.whitelist)
|
||||
db := TS.s.DB.DB
|
||||
defer TS.Stop()
|
||||
snID, upID := newTestID(ctx, t), newTestID(ctx, t)
|
||||
s, c, cleanup := NewTest(ctx, t, snID, upID, []storj.NodeID{})
|
||||
defer cleanup()
|
||||
db := s.DB.DB
|
||||
|
||||
assert := assert.New(t)
|
||||
stream, err := TS.c.Store(ctx)
|
||||
stream, err := c.Store(ctx)
|
||||
assert.NoError(err)
|
||||
|
||||
// Write the buffer to the stream we opened earlier
|
||||
err = stream.Send(&pb.PieceStore{PieceData: &pb.PieceStore_PieceData{Id: tt.id, ExpirationUnixSec: tt.ttl}})
|
||||
assert.NoError(err)
|
||||
|
||||
pbad := &pb.PayerBandwidthAllocation_Data{
|
||||
SatelliteId: tt.satelliteID,
|
||||
UplinkId: teststorj.NodeIDFromString("uplinkid"),
|
||||
Action: pb.PayerBandwidthAllocation_PUT,
|
||||
}
|
||||
pbaData, err := proto.Marshal(pbad)
|
||||
assert.NoError(err)
|
||||
pba := &pb.PayerBandwidthAllocation{Data: pbaData}
|
||||
// Send Bandwidth Allocation Data
|
||||
msg := &pb.PieceStore{
|
||||
PieceData: &pb.PieceStore_PieceData{Content: tt.content},
|
||||
BandwidthAllocation: &pb.RenterBandwidthAllocation{
|
||||
Data: serializeData(&pb.RenterBandwidthAllocation_Data{
|
||||
PayerAllocation: pba,
|
||||
Total: int64(len(tt.content)),
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
s, err := cryptopasta.Sign(msg.BandwidthAllocation.Data, TS.k.(*ecdsa.PrivateKey))
|
||||
pba, err := test.GeneratePayerBandwidthAllocation(pb.PayerBandwidthAllocation_PUT, snID, upID, time.Hour)
|
||||
assert.NoError(err)
|
||||
msg.BandwidthAllocation.Signature = s
|
||||
|
||||
rba, err := test.GenerateRenterBandwidthAllocation(pba, snID.ID, upID, tt.totalReceived)
|
||||
assert.NoError(err)
|
||||
msg := &pb.PieceStore{
|
||||
PieceData: &pb.PieceStore_PieceData{Content: tt.content},
|
||||
BandwidthAllocation: rba,
|
||||
}
|
||||
// Write the buffer to the stream we opened earlier
|
||||
err = stream.Send(msg)
|
||||
if err != io.EOF && err != nil {
|
||||
@ -390,11 +359,12 @@ func TestStore(t *testing.T) {
|
||||
resp, err := stream.CloseAndRecv()
|
||||
if tt.err != "" {
|
||||
assert.NotNil(err)
|
||||
assert.Equal(tt.err, err.Error())
|
||||
assert.True(strings.HasPrefix(err.Error(), tt.err), "expected")
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(err)
|
||||
if !assert.NoError(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_, err := db.Exec(fmt.Sprintf(`DELETE FROM ttl WHERE id="%s"`, tt.id))
|
||||
@ -426,7 +396,9 @@ func TestStore(t *testing.T) {
|
||||
}
|
||||
err = rows.Err()
|
||||
assert.NoError(err)
|
||||
|
||||
if !assert.NotNil(resp) {
|
||||
t.Fatalf("resp is null")
|
||||
}
|
||||
assert.Equal(tt.message, resp.Message)
|
||||
assert.Equal(tt.totalReceived, resp.TotalReceived)
|
||||
})
|
||||
@ -435,6 +407,8 @@ func TestStore(t *testing.T) {
|
||||
|
||||
func TestPbaValidation(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
snID, upID := newTestID(ctx, t), newTestID(ctx, t)
|
||||
satID1, satID2, satID3 := newTestID(ctx, t), newTestID(ctx, t), newTestID(ctx, t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
tests := []struct {
|
||||
@ -445,87 +419,59 @@ func TestPbaValidation(t *testing.T) {
|
||||
err string
|
||||
}{
|
||||
{ // unapproved satellite id
|
||||
satelliteID: teststorj.NodeIDFromString("bad-satellite"),
|
||||
uplinkID: teststorj.NodeIDFromString("uplinkid"),
|
||||
whitelist: []storj.NodeID{
|
||||
teststorj.NodeIDFromString("satelliteid1"),
|
||||
teststorj.NodeIDFromString("satelliteid2"),
|
||||
teststorj.NodeIDFromString("satelliteid3"),
|
||||
},
|
||||
action: pb.PayerBandwidthAllocation_PUT,
|
||||
err: "rpc error: code = Unknown desc = store error: Satellite ID not approved",
|
||||
satelliteID: satID1.ID,
|
||||
uplinkID: upID.ID,
|
||||
whitelist: []storj.NodeID{satID1.ID, satID2.ID, satID3.ID},
|
||||
action: pb.PayerBandwidthAllocation_PUT,
|
||||
err: "rpc error: code = Unknown desc = store error: Satellite ID not approved",
|
||||
},
|
||||
{ // missing satellite id
|
||||
satelliteID: storj.NodeID{},
|
||||
uplinkID: teststorj.NodeIDFromString("uplinkid"),
|
||||
whitelist: []storj.NodeID{
|
||||
teststorj.NodeIDFromString("satelliteid1"),
|
||||
teststorj.NodeIDFromString("satelliteid2"),
|
||||
teststorj.NodeIDFromString("satelliteid3"),
|
||||
},
|
||||
action: pb.PayerBandwidthAllocation_PUT,
|
||||
err: "rpc error: code = Unknown desc = store error: payer bandwidth allocation: missing satellite id",
|
||||
uplinkID: upID.ID,
|
||||
whitelist: []storj.NodeID{satID1.ID, satID2.ID, satID3.ID},
|
||||
action: pb.PayerBandwidthAllocation_PUT,
|
||||
err: "rpc error: code = Unknown desc = store error: payer bandwidth allocation: missing satellite id",
|
||||
},
|
||||
{ // missing uplink id
|
||||
satelliteID: teststorj.NodeIDFromString("satelliteid1"),
|
||||
satelliteID: satID1.ID,
|
||||
uplinkID: storj.NodeID{},
|
||||
whitelist: []storj.NodeID{
|
||||
teststorj.NodeIDFromString("satelliteid1"),
|
||||
teststorj.NodeIDFromString("satelliteid2"),
|
||||
teststorj.NodeIDFromString("satelliteid3"),
|
||||
},
|
||||
action: pb.PayerBandwidthAllocation_PUT,
|
||||
err: "rpc error: code = Unknown desc = store error: payer bandwidth allocation: missing uplink id",
|
||||
whitelist: []storj.NodeID{satID1.ID, satID2.ID, satID3.ID},
|
||||
action: pb.PayerBandwidthAllocation_PUT,
|
||||
err: "rpc error: code = Unknown desc = store error: payer bandwidth allocation: missing uplink id",
|
||||
},
|
||||
{ // wrong action type
|
||||
satelliteID: teststorj.NodeIDFromString("satelliteid1"),
|
||||
uplinkID: teststorj.NodeIDFromString("uplinkid"),
|
||||
whitelist: []storj.NodeID{
|
||||
teststorj.NodeIDFromString("satelliteid1"),
|
||||
teststorj.NodeIDFromString("satelliteid2"),
|
||||
teststorj.NodeIDFromString("satelliteid3"),
|
||||
},
|
||||
action: pb.PayerBandwidthAllocation_GET,
|
||||
err: "rpc error: code = Unknown desc = store error: payer bandwidth allocation: invalid action GET",
|
||||
satelliteID: satID1.ID,
|
||||
uplinkID: upID.ID,
|
||||
whitelist: []storj.NodeID{satID1.ID, satID2.ID, satID3.ID},
|
||||
action: pb.PayerBandwidthAllocation_GET,
|
||||
err: "rpc error: code = Unknown desc = store error: payer bandwidth allocation: invalid action GET",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run("should validate payer bandwidth allocation struct", func(t *testing.T) {
|
||||
TS := NewTestServer(t, tt.whitelist)
|
||||
defer TS.Stop()
|
||||
s, c, cleanup := NewTest(ctx, t, snID, upID, tt.whitelist)
|
||||
defer cleanup()
|
||||
|
||||
assert := assert.New(t)
|
||||
stream, err := TS.c.Store(ctx)
|
||||
stream, err := c.Store(ctx)
|
||||
assert.NoError(err)
|
||||
|
||||
//cleanup incase tests previously paniced
|
||||
_ = s.storage.Delete("99999999999999999999")
|
||||
// Write the buffer to the stream we opened earlier
|
||||
err = stream.Send(&pb.PieceStore{PieceData: &pb.PieceStore_PieceData{Id: "99999999999999999999", ExpirationUnixSec: 9999999999}})
|
||||
assert.NoError(err)
|
||||
|
||||
pbad := &pb.PayerBandwidthAllocation_Data{
|
||||
SatelliteId: tt.satelliteID,
|
||||
UplinkId: tt.uplinkID,
|
||||
Action: tt.action,
|
||||
}
|
||||
pbaData, err := proto.Marshal(pbad)
|
||||
assert.NoError(err)
|
||||
pba := &pb.PayerBandwidthAllocation{Data: pbaData}
|
||||
// Send Bandwidth Allocation Data
|
||||
content := []byte("content")
|
||||
msg := &pb.PieceStore{
|
||||
PieceData: &pb.PieceStore_PieceData{Content: content},
|
||||
BandwidthAllocation: &pb.RenterBandwidthAllocation{
|
||||
Data: serializeData(&pb.RenterBandwidthAllocation_Data{
|
||||
PayerAllocation: pba,
|
||||
Total: int64(len(content)),
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
s, err := cryptopasta.Sign(msg.BandwidthAllocation.Data, TS.k.(*ecdsa.PrivateKey))
|
||||
pba, err := test.GeneratePayerBandwidthAllocation(tt.action, satID1, upID, time.Hour)
|
||||
assert.NoError(err)
|
||||
msg.BandwidthAllocation.Signature = s
|
||||
rba, err := test.GenerateRenterBandwidthAllocation(pba, snID.ID, upID, int64(len(content)))
|
||||
assert.NoError(err)
|
||||
msg := &pb.PieceStore{
|
||||
PieceData: &pb.PieceStore_PieceData{Content: content},
|
||||
BandwidthAllocation: rba,
|
||||
}
|
||||
|
||||
// Write the buffer to the stream we opened earlier
|
||||
err = stream.Send(msg)
|
||||
@ -549,10 +495,11 @@ func TestDelete(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
TS := NewTestServer(t, []storj.NodeID{})
|
||||
defer TS.Stop()
|
||||
snID, upID := newTestID(ctx, t), newTestID(ctx, t)
|
||||
s, c, cleanup := NewTest(ctx, t, snID, upID, []storj.NodeID{})
|
||||
defer cleanup()
|
||||
|
||||
db := TS.s.DB.DB
|
||||
db := s.DB.DB
|
||||
|
||||
// set up test cases
|
||||
tests := []struct {
|
||||
@ -582,7 +529,7 @@ func TestDelete(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// simulate piece stored with storagenode
|
||||
if err := TS.writeFile("11111111111111111111"); err != nil {
|
||||
if err := writeFile(s, "11111111111111111111"); err != nil {
|
||||
t.Errorf("Error: %v\nCould not create test piece", err)
|
||||
return
|
||||
}
|
||||
@ -597,11 +544,11 @@ func TestDelete(t *testing.T) {
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
assert.NoError(TS.s.storage.Delete("11111111111111111111"))
|
||||
assert.NoError(s.storage.Delete("11111111111111111111"))
|
||||
}()
|
||||
|
||||
req := &pb.PieceDelete{Id: tt.id}
|
||||
resp, err := TS.c.Delete(ctx, req)
|
||||
resp, err := c.Delete(ctx, req)
|
||||
|
||||
if tt.err != "" {
|
||||
assert.Equal(tt.err, err.Error())
|
||||
@ -612,7 +559,7 @@ func TestDelete(t *testing.T) {
|
||||
assert.Equal(tt.message, resp.GetMessage())
|
||||
|
||||
// if test passes, check if file was indeed deleted
|
||||
filePath, err := TS.s.storage.PiecePath(tt.id)
|
||||
filePath, err := s.storage.PiecePath(tt.id)
|
||||
assert.NoError(err)
|
||||
if _, err = os.Stat(filePath); os.IsExist(err) {
|
||||
t.Errorf("File not deleted")
|
||||
@ -622,25 +569,20 @@ func TestDelete(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestServerStruct(t *testing.T, ids []storj.NodeID) (*Server, func()) {
|
||||
func NewTest(ctx context.Context, t *testing.T, snID, upID *identity.FullIdentity,
|
||||
ids []storj.NodeID) (*Server, pb.PieceStoreRoutesClient, func()) {
|
||||
//init ps server backend
|
||||
tmp, err := ioutil.TempDir("", "storj-piecestore")
|
||||
if err != nil {
|
||||
log.Fatalf("failed temp-dir: %v", err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
tempDBPath := filepath.Join(tmp, "test.db")
|
||||
tempDir := filepath.Join(tmp, "test-data", "3000")
|
||||
storage := pstore.NewStorage(tempDir)
|
||||
|
||||
psDB, err := psdb.Open(context.TODO(), storage, tempDBPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed open psdb: %v", err)
|
||||
}
|
||||
|
||||
psDB, err := psdb.Open(ctx, storage, tempDBPath)
|
||||
assert.NoError(t, err)
|
||||
verifier := func(authorization *pb.SignedMessage) error {
|
||||
return nil
|
||||
}
|
||||
server := &Server{
|
||||
psServer := &Server{
|
||||
log: zaptest.NewLogger(t),
|
||||
storage: storage,
|
||||
DB: psDB,
|
||||
@ -649,95 +591,45 @@ func newTestServerStruct(t *testing.T, ids []storj.NodeID) (*Server, func()) {
|
||||
totalBwAllocated: math.MaxInt64,
|
||||
whitelist: ids,
|
||||
}
|
||||
return server, func() {
|
||||
if serr := server.Stop(context.TODO()); serr != nil {
|
||||
t.Fatal(serr)
|
||||
}
|
||||
// TODO:fix this error check
|
||||
_ = os.RemoveAll(tmp)
|
||||
// if err := os.RemoveAll(tmp); err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
//init ps server grpc
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
publicConfig := server.Config{Address: "127.0.0.1:0"}
|
||||
publicOptions, err := server.NewOptions(snID, publicConfig)
|
||||
assert.NoError(t, err)
|
||||
grpcServer, err := server.NewServer(publicOptions, listener, nil)
|
||||
assert.NoError(t, err)
|
||||
pb.RegisterPieceStoreRoutesServer(grpcServer.GRPC(), psServer)
|
||||
go func() { assert.NoError(t, grpcServer.Run(ctx)) }()
|
||||
//init client
|
||||
co, err := upID.DialOption(storj.NodeID{})
|
||||
assert.NoError(t, err)
|
||||
conn, err := grpc.Dial(listener.Addr().String(), co)
|
||||
assert.NoError(t, err)
|
||||
psClient := pb.NewPieceStoreRoutesClient(conn)
|
||||
//cleanup callback
|
||||
cleanup := func() {
|
||||
assert.NoError(t, conn.Close())
|
||||
assert.NoError(t, psServer.Close())
|
||||
assert.NoError(t, psServer.Stop(ctx))
|
||||
assert.NoError(t, os.RemoveAll(tmp))
|
||||
}
|
||||
return psServer, psClient, cleanup
|
||||
}
|
||||
|
||||
func connect(addr string, o ...grpc.DialOption) (pb.PieceStoreRoutesClient, *grpc.ClientConn) {
|
||||
conn, err := grpc.Dial(addr, o...)
|
||||
func newTestID(ctx context.Context, t *testing.T) *identity.FullIdentity {
|
||||
id, err := testidentity.NewTestIdentity(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
c := pb.NewPieceStoreRoutesClient(conn)
|
||||
|
||||
return c, conn
|
||||
return id
|
||||
}
|
||||
|
||||
type TestServer struct {
|
||||
s *Server
|
||||
scleanup func()
|
||||
grpcs *grpc.Server
|
||||
conn *grpc.ClientConn
|
||||
c pb.PieceStoreRoutesClient
|
||||
k crypto.PrivateKey
|
||||
}
|
||||
|
||||
func NewTestServer(t *testing.T, ids []storj.NodeID) *TestServer {
|
||||
check := func(e error) {
|
||||
if !assert.NoError(t, e) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
caS, err := testidentity.NewTestCA(context.Background())
|
||||
check(err)
|
||||
fiS, err := caS.NewIdentity()
|
||||
check(err)
|
||||
so, err := fiS.ServerOption()
|
||||
check(err)
|
||||
|
||||
caC, err := testidentity.NewTestCA(context.Background())
|
||||
check(err)
|
||||
fiC, err := caC.NewIdentity()
|
||||
check(err)
|
||||
co, err := fiC.DialOption(storj.NodeID{})
|
||||
check(err)
|
||||
|
||||
s, cleanup := newTestServerStruct(t, ids)
|
||||
grpcs := grpc.NewServer(so)
|
||||
|
||||
k, ok := fiC.Key.(*ecdsa.PrivateKey)
|
||||
assert.True(t, ok)
|
||||
ts := &TestServer{s: s, scleanup: cleanup, grpcs: grpcs, k: k}
|
||||
addr := ts.start()
|
||||
ts.c, ts.conn = connect(addr, co)
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
func (TS *TestServer) start() (addr string) {
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
func writeFile(s *Server, pieceID string) error {
|
||||
file, err := s.storage.Writer(pieceID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
return err
|
||||
}
|
||||
pb.RegisterPieceStoreRoutesServer(TS.grpcs, TS.s)
|
||||
|
||||
go func() {
|
||||
if err := TS.grpcs.Serve(lis); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
}()
|
||||
return lis.Addr().String()
|
||||
}
|
||||
|
||||
func (TS *TestServer) Stop() {
|
||||
if err := TS.conn.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
TS.grpcs.Stop()
|
||||
TS.scleanup()
|
||||
}
|
||||
|
||||
func serializeData(ba *pb.RenterBandwidthAllocation_Data) []byte {
|
||||
data, _ := proto.Marshal(ba)
|
||||
return data
|
||||
_, err = file.Write([]byte("xyzwq"))
|
||||
return errs.Combine(err, file.Close())
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ const IDLength = 20
|
||||
// Errors
|
||||
var (
|
||||
Error = errs.Class("piecestore error")
|
||||
MkDir = errs.Class("piecestore MkdirAll")
|
||||
Open = errs.Class("piecestore OpenFile")
|
||||
)
|
||||
|
||||
// PiecePath creates piece storage path from id and dir
|
||||
@ -58,7 +60,6 @@ func (storage *Storage) PiecePath(pieceID string) (string, error) {
|
||||
if len(pieceID) < IDLength {
|
||||
return "", Error.New("invalid id length")
|
||||
}
|
||||
|
||||
folder1, folder2, filename := pieceID[0:2], pieceID[2:4], pieceID[4:]
|
||||
return filepath.Join(storage.dir, folder1, folder2, filename), nil
|
||||
}
|
||||
@ -69,16 +70,13 @@ func (storage *Storage) Writer(pieceID string) (io.WriteCloser, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(filepath.Dir(path), 0700); err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
return nil, MkDir.Wrap(err)
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
return nil, Open.Wrap(err)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
@ -88,30 +86,24 @@ func (storage *Storage) Reader(ctx context.Context, pieceID string, offset int64
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if offset >= info.Size() || offset < 0 {
|
||||
return nil, Error.New("invalid offset: %v", offset)
|
||||
}
|
||||
|
||||
if length <= -1 {
|
||||
length = info.Size()
|
||||
}
|
||||
|
||||
// If trying to read past the end of the file, just read to the end
|
||||
if info.Size() < offset+length {
|
||||
length = info.Size() - offset
|
||||
}
|
||||
|
||||
rr, err := ranger.FileRanger(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rr.Range(ctx, offset, length)
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ package pointerdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/x509"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
@ -15,7 +13,6 @@ import (
|
||||
"storj.io/storj/pkg/auth"
|
||||
"storj.io/storj/pkg/identity"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/peertls"
|
||||
)
|
||||
|
||||
// AllocationSigner structure
|
||||
@ -38,21 +35,10 @@ func (allocation *AllocationSigner) PayerBandwidthAllocation(ctx context.Context
|
||||
return nil, Error.New("missing peer identity")
|
||||
}
|
||||
|
||||
pk, ok := peerIdentity.Leaf.PublicKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, peertls.ErrUnsupportedKey.New("%T", peerIdentity.Leaf.PublicKey)
|
||||
}
|
||||
|
||||
pubbytes, err := x509.MarshalPKIXPublicKey(pk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serialNum, err := uuid.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
created := time.Now().Unix()
|
||||
|
||||
// convert ttl from days to seconds
|
||||
@ -66,7 +52,6 @@ func (allocation *AllocationSigner) PayerBandwidthAllocation(ctx context.Context
|
||||
ExpirationUnixSec: created + int64(ttl),
|
||||
Action: action,
|
||||
SerialNumber: serialNum.String(),
|
||||
PubKey: pubbytes,
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(pbad)
|
||||
@ -77,5 +62,6 @@ func (allocation *AllocationSigner) PayerBandwidthAllocation(ctx context.Context
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.PayerBandwidthAllocation{Signature: signature, Data: data}, nil
|
||||
certs := allocation.satelliteIdentity.ChainRaw()
|
||||
return &pb.PayerBandwidthAllocation{Signature: signature, Data: data, Certs: certs}, nil
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package storj
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"math/bits"
|
||||
|
||||
"github.com/btcsuite/btcutil/base58"
|
||||
@ -21,7 +22,7 @@ var (
|
||||
)
|
||||
|
||||
// NodeID is a unique node identifier
|
||||
type NodeID [32]byte
|
||||
type NodeID [sha256.Size]byte
|
||||
|
||||
// NodeIDList is a slice of NodeIDs (implements sort)
|
||||
type NodeIDList []NodeID
|
||||
|
@ -289,7 +289,8 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, config *Config) (*
|
||||
}
|
||||
|
||||
{ // setup agreements
|
||||
peer.Agreements.Endpoint = bwagreement.NewServer(peer.DB.BandwidthAgreement(), peer.Log.Named("agreements"), peer.Identity.Leaf.PublicKey)
|
||||
bwServer := bwagreement.NewServer(peer.DB.BandwidthAgreement(), peer.Log.Named("agreements"), peer.Identity.ID)
|
||||
peer.Agreements.Endpoint = bwServer
|
||||
pb.RegisterBandwidthServer(peer.Public.Server.GRPC(), peer.Agreements.Endpoint)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user