new node selection in overlay (#1136)

This commit is contained in:
Natalie Villasana 2019-01-29 14:42:43 -05:00 committed by GitHub
parent 1df81b1460
commit 8d7944bcf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 537 additions and 258 deletions

View File

@ -267,6 +267,8 @@ func (planet *Planet) newSatellites(count int) ([]*satellite.Peer, error) {
UptimeCount: 0,
AuditSuccessRatio: 0,
AuditCount: 0,
NewNodeAuditThreshold: 0,
NewNodePercentage: 0,
},
},
Discovery: discovery.Config{

View File

@ -35,6 +35,8 @@ var OverlayError = errs.Class("Overlay Error")
// DB implements the database for overlay.Cache
type DB interface {
// FilterNodes looks up nodes based on reputation requirements
FilterNodes(ctx context.Context, filterNodesRequest *FilterNodesRequest) ([]*pb.Node, error)
// Get looks up the node by nodeID
Get(ctx context.Context, nodeID storj.NodeID) (*pb.Node, error)
// GetAll looks up nodes based on the ids from the overlay cache

View File

@ -47,7 +47,7 @@ func TestChoose(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
planet, err := testplanet.New(t, 1, 4, 1)
planet, err := testplanet.New(t, 1, 8, 1)
require.NoError(t, err)
planet.Start(ctx)
@ -60,41 +60,15 @@ func TestChoose(t *testing.T) {
t.Fatal(err)
}
n1 := &pb.Node{Id: storj.NodeID{1}, Type: pb.NodeType_STORAGE}
n2 := &pb.Node{Id: storj.NodeID{2}, Type: pb.NodeType_STORAGE}
n3 := &pb.Node{Id: storj.NodeID{3}, Type: pb.NodeType_STORAGE}
n4 := &pb.Node{Id: storj.NodeID{4}, Type: pb.NodeType_STORAGE}
n5 := &pb.Node{Id: storj.NodeID{5}, Type: pb.NodeType_STORAGE}
n6 := &pb.Node{Id: storj.NodeID{6}, Type: pb.NodeType_STORAGE}
n7 := &pb.Node{Id: storj.NodeID{7}, Type: pb.NodeType_STORAGE}
n8 := &pb.Node{Id: storj.NodeID{8}, Type: pb.NodeType_STORAGE}
id1 := storj.NodeID{1}
id2 := storj.NodeID{2}
id3 := storj.NodeID{3}
id4 := storj.NodeID{4}
cases := []struct {
limit int
space int64
bandwidth int64
uptime float64
uptimeCount int64
auditSuccess float64
auditCount int64
allNodes []*pb.Node
excluded storj.NodeIDList
}{
{
limit: 4,
space: 0,
bandwidth: 0,
uptime: 0,
uptimeCount: 0,
auditSuccess: 0,
auditCount: 0,
allNodes: []*pb.Node{n1, n2, n3, n4, n5, n6, n7, n8},
excluded: storj.NodeIDList{id1, id2, id3, id4},
},
}
@ -102,28 +76,13 @@ func TestChoose(t *testing.T) {
newNodes, err := oc.Choose(ctx, overlay.Options{
Amount: v.limit,
Space: v.space,
Uptime: v.uptime,
UptimeCount: v.uptimeCount,
AuditSuccess: v.auditSuccess,
AuditCount: v.auditCount,
Excluded: v.excluded,
})
assert.NoError(t, err)
excludedNodes := make(map[storj.NodeID]bool)
for _, e := range v.excluded {
excludedNodes[e] = true
}
assert.Len(t, newNodes, v.limit)
for _, n := range newNodes {
assert.NotContains(t, excludedNodes, n.Id)
assert.True(t, n.GetRestrictions().GetFreeDisk() >= v.space)
assert.True(t, n.GetRestrictions().GetFreeBandwidth() >= v.bandwidth)
assert.True(t, n.GetReputation().GetUptimeRatio() >= v.uptime)
assert.True(t, n.GetReputation().GetUptimeCount() >= v.uptimeCount)
assert.True(t, n.GetReputation().GetAuditSuccessRatio() >= v.auditSuccess)
assert.True(t, n.GetReputation().GetAuditCount() >= v.auditCount)
}
}
}

View File

@ -40,6 +40,8 @@ type NodeSelectionConfig struct {
UptimeCount int64 `help:"the number of times a node's uptime has been checked" default:"0"`
AuditSuccessRatio float64 `help:"a node's ratio of successful audits" default:"0"`
AuditCount int64 `help:"the number of times a node has been audited" default:"0"`
NewNodeAuditThreshold int64 `help:"the number of audits a node must have to not be considered a New Node" default:"0"`
NewNodePercentage float64 `help:"the percentage of new nodes allowed per request" default:"0.05"`
}
// ParseIDs converts the base58check encoded node ID strings from the config into node IDs

View File

@ -4,9 +4,7 @@
package overlay
import (
"bytes"
"context"
"fmt"
"github.com/zeebo/errs"
"go.uber.org/zap"
@ -26,16 +24,16 @@ type Server struct {
log *zap.Logger
cache *Cache
metrics *monkit.Registry
nodeStats *pb.NodeStats
nodeSelectionConfig *NodeSelectionConfig
}
// NewServer creates a new Overlay Server
func NewServer(log *zap.Logger, cache *Cache, nodeStats *pb.NodeStats) *Server {
func NewServer(log *zap.Logger, cache *Cache, nodeSelectionConfig *NodeSelectionConfig) *Server {
return &Server{
cache: cache,
log: log,
metrics: monkit.Default,
nodeStats: nodeStats,
nodeSelectionConfig: nodeSelectionConfig,
}
}
@ -69,120 +67,50 @@ func (server *Server) BulkLookup(ctx context.Context, reqs *pb.LookupRequests) (
return nodesToLookupResponses(ns), nil
}
// FilterNodesRequest are the requirements for nodes from the overlay cache
type FilterNodesRequest struct {
MinReputation *pb.NodeStats
MinNodes int64
Opts *pb.OverlayOptions
NewNodePercentage float64
NewNodeAuditThreshold int64
}
// FindStorageNodes searches the overlay network for nodes that meet the provided requirements
func (server *Server) FindStorageNodes(ctx context.Context, req *pb.FindStorageNodesRequest) (resp *pb.FindStorageNodesResponse, err error) {
defer mon.Task()(&ctx)(&err)
opts := req.GetOpts()
maxNodes := req.GetMaxNodes()
if maxNodes <= 0 {
maxNodes = opts.GetAmount()
minStats := &pb.NodeStats{
AuditCount: server.nodeSelectionConfig.AuditCount,
AuditSuccessRatio: server.nodeSelectionConfig.AuditSuccessRatio,
UptimeCount: server.nodeSelectionConfig.UptimeCount,
UptimeRatio: server.nodeSelectionConfig.UptimeRatio,
}
excluded := opts.ExcludedNodes
restrictions := opts.GetRestrictions()
reputation := server.nodeStats
filterNodesReq := &FilterNodesRequest{
MinReputation: minStats,
MinNodes: req.GetMinNodes(),
Opts: req.GetOpts(),
NewNodePercentage: server.nodeSelectionConfig.NewNodePercentage,
NewNodeAuditThreshold: server.nodeSelectionConfig.NewNodeAuditThreshold,
}
var startID storj.NodeID
result := []*pb.Node{}
for {
var nodes []*pb.Node
nodes, startID, err = server.populate(ctx, req.Start, maxNodes, restrictions, reputation, excluded)
foundNodes, err := server.cache.db.FilterNodes(ctx, filterNodesReq)
if err != nil {
stat, _ := status.FromError(err)
if stat.Code() == codes.ResourceExhausted {
return &pb.FindStorageNodesResponse{
Nodes: foundNodes,
}, err
}
return nil, Error.Wrap(err)
}
resultNodes := []*pb.Node{}
usedAddrs := make(map[string]bool)
for _, n := range nodes {
addr := n.Address.GetAddress()
excluded = append(excluded, n.Id) // exclude all nodes on next iteration
if !usedAddrs[addr] {
resultNodes = append(resultNodes, n)
usedAddrs[addr] = true
}
}
if len(resultNodes) <= 0 {
break
}
result = append(result, resultNodes...)
if len(result) >= int(maxNodes) || startID == (storj.NodeID{}) {
break
}
}
if len(result) < int(maxNodes) {
return nil, status.Errorf(codes.ResourceExhausted, fmt.Sprintf("requested %d nodes, only %d nodes matched the criteria requested", maxNodes, len(result)))
}
if len(result) > int(maxNodes) {
result = result[:maxNodes]
}
return &pb.FindStorageNodesResponse{
Nodes: result,
Nodes: foundNodes,
}, nil
}
// TODO: nicer method arguments
func (server *Server) populate(ctx context.Context,
startID storj.NodeID, maxNodes int64,
minRestrictions *pb.NodeRestrictions,
minReputation *pb.NodeStats,
excluded storj.NodeIDList) ([]*pb.Node, storj.NodeID, error) {
// TODO: move the query into db
limit := int(maxNodes * 2)
nodes, err := server.cache.db.List(ctx, startID, limit)
if err != nil {
server.log.Error("Error listing nodes", zap.Error(err))
return nil, storj.NodeID{}, Error.Wrap(err)
}
var nextStart storj.NodeID
result := []*pb.Node{}
for _, v := range nodes {
if v == nil {
continue
}
nextStart = v.Id
if v.Type != pb.NodeType_STORAGE {
continue
}
restrictions := v.GetRestrictions()
reputation := v.GetReputation()
if restrictions.GetFreeBandwidth() < minRestrictions.GetFreeBandwidth() ||
restrictions.GetFreeDisk() < minRestrictions.GetFreeDisk() ||
reputation.GetUptimeRatio() < minReputation.GetUptimeRatio() ||
reputation.GetUptimeCount() < minReputation.GetUptimeCount() ||
reputation.GetAuditSuccessRatio() < minReputation.GetAuditSuccessRatio() ||
reputation.GetAuditCount() < minReputation.GetAuditCount() ||
contains(excluded, v.Id) {
continue
}
result = append(result, v)
}
return result, nextStart, nil
}
// contains checks if item exists in list
func contains(nodeIDs storj.NodeIDList, searchID storj.NodeID) bool {
for _, id := range nodeIDs {
if bytes.Equal(id.Bytes(), searchID.Bytes()) {
return true
}
}
return false
}
// lookupRequestsToNodeIDs returns the nodeIDs from the LookupRequests
func lookupRequestsToNodeIDs(reqs *pb.LookupRequests) (ids storj.NodeIDList) {
for _, v := range reqs.LookupRequest {

View File

@ -4,14 +4,18 @@
package overlay_test
import (
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"storj.io/storj/internal/testcontext"
"storj.io/storj/internal/testplanet"
"storj.io/storj/pkg/overlay"
"storj.io/storj/pkg/pb"
)
@ -33,15 +37,6 @@ func TestServer(t *testing.T) {
server := satellite.Overlay.Endpoint
// TODO: handle cleanup
{ // FindStorageNodes
result, err := server.FindStorageNodes(ctx, &pb.FindStorageNodesRequest{
Opts: &pb.OverlayOptions{Amount: 2},
})
require.NoError(t, err)
require.NotNil(t, result)
assert.Len(t, result.Nodes, 2)
}
{ // Lookup
result, err := server.Lookup(ctx, &pb.LookupRequest{
NodeId: planet.StorageNodes[0].ID(),
@ -71,3 +66,177 @@ func TestServer(t *testing.T) {
}
}
}
func TestNewNodeFiltering(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
var totalNodes int
totalNodes = 10
planet, err := testplanet.New(t, 1, totalNodes, 1)
if err != nil {
t.Fatal(err)
}
planet.Start(ctx)
defer ctx.Check(planet.Shutdown)
// we wait a second for all the nodes to complete bootstrapping off the satellite
time.Sleep(5 * time.Second)
satellite := planet.Satellites[0]
// This sets a reputable audit count for a certain number of nodes.
for i, node := range planet.StorageNodes {
for j := 0; j < i; j++ {
_, err := satellite.DB.StatDB().UpdateAuditSuccess(ctx, node.ID(), true)
assert.NoError(t, err)
}
}
for _, tt := range []struct {
name string
newNodeAuditThreshold int64
newNodePercentage float64
requestedNodeAmt int64
expectedResultLength int
excludedAmt int
notEnoughRepNodes bool
}{
{
name: "case: all reputable nodes, only reputable nodes requested",
newNodeAuditThreshold: 0,
newNodePercentage: 0,
requestedNodeAmt: 5,
expectedResultLength: 5,
},
{
name: "case: all reputable nodes, reputable and new nodes requested",
newNodeAuditThreshold: 0,
newNodePercentage: 1,
requestedNodeAmt: 5,
expectedResultLength: 5,
},
{
name: "case: all reputable nodes except one, reputable and new nodes requested",
newNodeAuditThreshold: 1,
newNodePercentage: 1,
requestedNodeAmt: 5,
expectedResultLength: 6,
},
{
name: "case: 50-50 reputable and new nodes, reputable and new nodes requested (new node % 1)",
newNodeAuditThreshold: 5,
newNodePercentage: 1,
requestedNodeAmt: 2,
expectedResultLength: 4,
},
{
name: "case: 50-50 reputable and new nodes, reputable and new nodes requested (new node % .5)",
newNodeAuditThreshold: 5,
newNodePercentage: 0.5,
requestedNodeAmt: 4,
expectedResultLength: 6,
},
{
name: "case: all new nodes except one, reputable and new nodes requested (happy path)",
newNodeAuditThreshold: 8,
newNodePercentage: 1,
requestedNodeAmt: 1,
expectedResultLength: 2,
},
{
name: "case: all new nodes except one, reputable and new nodes requested (not happy path)",
newNodeAuditThreshold: 9,
newNodePercentage: 1,
requestedNodeAmt: 2,
expectedResultLength: 3,
notEnoughRepNodes: true,
},
{
name: "case: all new nodes, reputable and new nodes requested",
newNodeAuditThreshold: 50,
newNodePercentage: 1,
requestedNodeAmt: 2,
expectedResultLength: 2,
notEnoughRepNodes: true,
},
{
name: "case: audit threshold edge case (1)",
newNodeAuditThreshold: 9,
newNodePercentage: 0,
requestedNodeAmt: 1,
expectedResultLength: 1,
},
{
name: "case: audit threshold edge case (2)",
newNodeAuditThreshold: 0,
newNodePercentage: 1,
requestedNodeAmt: 1,
expectedResultLength: 1,
},
{
name: "case: excluded node ids being excluded",
excludedAmt: 7,
newNodeAuditThreshold: 5,
newNodePercentage: 0,
requestedNodeAmt: 5,
expectedResultLength: 3,
notEnoughRepNodes: true,
},
} {
nodeSelectionConfig := &overlay.NodeSelectionConfig{
UptimeCount: 0,
UptimeRatio: 0,
AuditSuccessRatio: 0,
AuditCount: 0,
NewNodeAuditThreshold: tt.newNodeAuditThreshold,
NewNodePercentage: tt.newNodePercentage,
}
server := overlay.NewServer(satellite.Log.Named("overlay"), satellite.Overlay.Service, nodeSelectionConfig)
var excludedNodes []pb.NodeID
for i := range planet.StorageNodes {
address := "127.0.0.1:555" + strconv.Itoa(i)
n := &pb.Node{
Id: planet.StorageNodes[i].ID(),
Address: &pb.NodeAddress{Address: address},
}
if tt.excludedAmt != 0 && i < tt.excludedAmt {
excludedNodes = append(excludedNodes, n.Id)
}
err = satellite.Overlay.Service.Put(ctx, n.Id, *n)
assert.NoError(t, err, tt.name)
}
result, err := server.FindStorageNodes(ctx,
&pb.FindStorageNodesRequest{
Opts: &pb.OverlayOptions{
Restrictions: &pb.NodeRestrictions{
FreeBandwidth: 0,
FreeDisk: 0,
},
Amount: tt.requestedNodeAmt,
ExcludedNodes: excludedNodes,
},
})
if tt.notEnoughRepNodes {
stat, ok := status.FromError(err)
assert.Equal(t, true, ok, tt.name)
assert.Equal(t, codes.ResourceExhausted, stat.Code(), tt.name)
} else {
assert.NoError(t, err, tt.name)
}
assert.Equal(t, tt.expectedResultLength, len(result.GetNodes()), tt.name)
}
}

View File

@ -54,7 +54,7 @@ func (x Restriction_Operator) String() string {
return proto.EnumName(Restriction_Operator_name, int32(x))
}
func (Restriction_Operator) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{11, 0}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{11, 0}
}
type Restriction_Operand int32
@ -77,7 +77,7 @@ func (x Restriction_Operand) String() string {
return proto.EnumName(Restriction_Operand_name, int32(x))
}
func (Restriction_Operand) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{11, 1}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{11, 1}
}
// LookupRequest is is request message for the lookup rpc call
@ -92,7 +92,7 @@ func (m *LookupRequest) Reset() { *m = LookupRequest{} }
func (m *LookupRequest) String() string { return proto.CompactTextString(m) }
func (*LookupRequest) ProtoMessage() {}
func (*LookupRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{0}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{0}
}
func (m *LookupRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupRequest.Unmarshal(m, b)
@ -124,7 +124,7 @@ func (m *LookupResponse) Reset() { *m = LookupResponse{} }
func (m *LookupResponse) String() string { return proto.CompactTextString(m) }
func (*LookupResponse) ProtoMessage() {}
func (*LookupResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{1}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{1}
}
func (m *LookupResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupResponse.Unmarshal(m, b)
@ -163,7 +163,7 @@ func (m *LookupRequests) Reset() { *m = LookupRequests{} }
func (m *LookupRequests) String() string { return proto.CompactTextString(m) }
func (*LookupRequests) ProtoMessage() {}
func (*LookupRequests) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{2}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{2}
}
func (m *LookupRequests) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupRequests.Unmarshal(m, b)
@ -202,7 +202,7 @@ func (m *LookupResponses) Reset() { *m = LookupResponses{} }
func (m *LookupResponses) String() string { return proto.CompactTextString(m) }
func (*LookupResponses) ProtoMessage() {}
func (*LookupResponses) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{3}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{3}
}
func (m *LookupResponses) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupResponses.Unmarshal(m, b)
@ -241,7 +241,7 @@ func (m *FindStorageNodesResponse) Reset() { *m = FindStorageNodesRespon
func (m *FindStorageNodesResponse) String() string { return proto.CompactTextString(m) }
func (*FindStorageNodesResponse) ProtoMessage() {}
func (*FindStorageNodesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{4}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{4}
}
func (m *FindStorageNodesResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FindStorageNodesResponse.Unmarshal(m, b)
@ -274,7 +274,7 @@ type FindStorageNodesRequest struct {
ContractLength *duration.Duration `protobuf:"bytes,2,opt,name=contract_length,json=contractLength,proto3" json:"contract_length,omitempty"`
Opts *OverlayOptions `protobuf:"bytes,3,opt,name=opts,proto3" json:"opts,omitempty"`
Start NodeID `protobuf:"bytes,4,opt,name=start,proto3,customtype=NodeID" json:"start"`
MaxNodes int64 `protobuf:"varint,5,opt,name=max_nodes,json=maxNodes,proto3" json:"max_nodes,omitempty"`
MinNodes int64 `protobuf:"varint,5,opt,name=min_nodes,json=minNodes,proto3" json:"min_nodes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -284,7 +284,7 @@ func (m *FindStorageNodesRequest) Reset() { *m = FindStorageNodesRequest
func (m *FindStorageNodesRequest) String() string { return proto.CompactTextString(m) }
func (*FindStorageNodesRequest) ProtoMessage() {}
func (*FindStorageNodesRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{5}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{5}
}
func (m *FindStorageNodesRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FindStorageNodesRequest.Unmarshal(m, b)
@ -325,9 +325,9 @@ func (m *FindStorageNodesRequest) GetOpts() *OverlayOptions {
return nil
}
func (m *FindStorageNodesRequest) GetMaxNodes() int64 {
func (m *FindStorageNodesRequest) GetMinNodes() int64 {
if m != nil {
return m.MaxNodes
return m.MinNodes
}
return 0
}
@ -349,7 +349,7 @@ func (m *OverlayOptions) Reset() { *m = OverlayOptions{} }
func (m *OverlayOptions) String() string { return proto.CompactTextString(m) }
func (*OverlayOptions) ProtoMessage() {}
func (*OverlayOptions) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{6}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{6}
}
func (m *OverlayOptions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OverlayOptions.Unmarshal(m, b)
@ -418,7 +418,7 @@ func (m *QueryRequest) Reset() { *m = QueryRequest{} }
func (m *QueryRequest) String() string { return proto.CompactTextString(m) }
func (*QueryRequest) ProtoMessage() {}
func (*QueryRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{7}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{7}
}
func (m *QueryRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryRequest.Unmarshal(m, b)
@ -478,7 +478,7 @@ func (m *QueryResponse) Reset() { *m = QueryResponse{} }
func (m *QueryResponse) String() string { return proto.CompactTextString(m) }
func (*QueryResponse) ProtoMessage() {}
func (*QueryResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{8}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{8}
}
func (m *QueryResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryResponse.Unmarshal(m, b)
@ -522,7 +522,7 @@ func (m *PingRequest) Reset() { *m = PingRequest{} }
func (m *PingRequest) String() string { return proto.CompactTextString(m) }
func (*PingRequest) ProtoMessage() {}
func (*PingRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{9}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{9}
}
func (m *PingRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PingRequest.Unmarshal(m, b)
@ -552,7 +552,7 @@ func (m *PingResponse) Reset() { *m = PingResponse{} }
func (m *PingResponse) String() string { return proto.CompactTextString(m) }
func (*PingResponse) ProtoMessage() {}
func (*PingResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{10}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{10}
}
func (m *PingResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PingResponse.Unmarshal(m, b)
@ -585,7 +585,7 @@ func (m *Restriction) Reset() { *m = Restriction{} }
func (m *Restriction) String() string { return proto.CompactTextString(m) }
func (*Restriction) ProtoMessage() {}
func (*Restriction) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_490501b0d22ed92e, []int{11}
return fileDescriptor_overlay_b711a2281a37fa0c, []int{11}
}
func (m *Restriction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Restriction.Unmarshal(m, b)
@ -884,61 +884,61 @@ var _Nodes_serviceDesc = grpc.ServiceDesc{
Metadata: "overlay.proto",
}
func init() { proto.RegisterFile("overlay.proto", fileDescriptor_overlay_490501b0d22ed92e) }
func init() { proto.RegisterFile("overlay.proto", fileDescriptor_overlay_b711a2281a37fa0c) }
var fileDescriptor_overlay_490501b0d22ed92e = []byte{
// 845 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xdd, 0x8e, 0xdb, 0x44,
0x14, 0x5e, 0xe7, 0xc7, 0xc9, 0x9e, 0x24, 0x5e, 0x6b, 0xd4, 0xee, 0x06, 0x03, 0xdd, 0x60, 0x55,
0xb0, 0x12, 0x55, 0x0a, 0x29, 0xaa, 0x68, 0x05, 0x02, 0xa2, 0xa4, 0x65, 0xd5, 0xa8, 0x4b, 0x27,
0x91, 0x2a, 0xc1, 0x85, 0xe5, 0xc4, 0x83, 0x31, 0xeb, 0x78, 0x8c, 0x67, 0x5c, 0xed, 0xf6, 0x09,
0x78, 0x13, 0x5e, 0x85, 0x67, 0xe0, 0x62, 0x1f, 0x81, 0x07, 0xe0, 0x0a, 0xcd, 0x8f, 0x1d, 0x67,
0x77, 0x53, 0xf5, 0x6a, 0xe6, 0x9c, 0xf3, 0x7d, 0x67, 0xe6, 0x3b, 0x73, 0xe6, 0x40, 0x8f, 0xbe,
0x21, 0x59, 0xec, 0x5f, 0x0e, 0xd3, 0x8c, 0x72, 0x8a, 0x5a, 0xda, 0x74, 0xee, 0x85, 0x94, 0x86,
0x31, 0x79, 0x28, 0xdd, 0xcb, 0xfc, 0xd7, 0x87, 0x41, 0x9e, 0xf9, 0x3c, 0xa2, 0x89, 0x02, 0x3a,
0x10, 0xd2, 0x90, 0x16, 0xfb, 0x84, 0x06, 0x44, 0xed, 0xdd, 0xaf, 0xa1, 0x37, 0xa3, 0xf4, 0x3c,
0x4f, 0x31, 0xf9, 0x23, 0x27, 0x8c, 0xa3, 0xcf, 0xa0, 0x25, 0xc2, 0x5e, 0x14, 0xf4, 0x8d, 0x81,
0x71, 0xd2, 0x1d, 0x5b, 0x7f, 0x5f, 0x1d, 0xef, 0xfd, 0x73, 0x75, 0x6c, 0xbe, 0xa4, 0x01, 0x39,
0x9d, 0x60, 0x53, 0x84, 0x4f, 0x03, 0xf7, 0x0b, 0xb0, 0x0a, 0x26, 0x4b, 0x69, 0xc2, 0x08, 0xba,
0x07, 0x0d, 0x11, 0x93, 0xbc, 0xce, 0x08, 0x86, 0xf2, 0x18, 0xc1, 0xc2, 0xd2, 0xef, 0x9e, 0x6d,
0x18, 0xf2, 0x2c, 0x86, 0xbe, 0x05, 0x2b, 0x96, 0x1e, 0x2f, 0x53, 0xae, 0xbe, 0x31, 0xa8, 0x9f,
0x74, 0x46, 0x87, 0xc3, 0x42, 0xe6, 0x16, 0x01, 0xf7, 0xe2, 0xaa, 0xe9, 0xce, 0xe1, 0x60, 0xfb,
0x0a, 0x0c, 0x7d, 0x0f, 0x07, 0x65, 0x46, 0xe5, 0xd3, 0x29, 0x8f, 0x6e, 0xa4, 0x54, 0x61, 0x6c,
0xc5, 0x5b, 0xb6, 0xfb, 0x0d, 0xf4, 0x9f, 0x45, 0x49, 0x30, 0xe7, 0x34, 0xf3, 0x43, 0x22, 0xae,
0xcf, 0x4a, 0x85, 0x03, 0x68, 0x0a, 0x25, 0x4c, 0xe7, 0xac, 0x4a, 0x54, 0x01, 0xf7, 0x5f, 0x03,
0x8e, 0x6e, 0xd2, 0x55, 0x69, 0x8f, 0xa1, 0x43, 0x97, 0xbf, 0x93, 0x15, 0xf7, 0x58, 0xf4, 0x56,
0x95, 0xa9, 0x8e, 0x41, 0xb9, 0xe6, 0xd1, 0x5b, 0x82, 0xc6, 0x70, 0xb0, 0xa2, 0x09, 0xcf, 0xfc,
0x15, 0xf7, 0x62, 0x92, 0x84, 0xfc, 0xb7, 0x7e, 0x4d, 0xd6, 0xf2, 0x83, 0xa1, 0x7a, 0xde, 0x61,
0xf1, 0xbc, 0xc3, 0x89, 0x7e, 0x5e, 0x6c, 0x15, 0x8c, 0x99, 0x24, 0xa0, 0xcf, 0xa1, 0x41, 0x53,
0xce, 0xfa, 0x75, 0x49, 0xdc, 0xa8, 0x3e, 0x53, 0xeb, 0x59, 0x2a, 0x58, 0x0c, 0x4b, 0x10, 0xba,
0x0f, 0x4d, 0xc6, 0xfd, 0x8c, 0xf7, 0x1b, 0xb7, 0x3e, 0xb5, 0x0a, 0xa2, 0x0f, 0x61, 0x7f, 0xed,
0x5f, 0x78, 0x4a, 0x79, 0x53, 0xde, 0xba, 0xbd, 0xf6, 0x2f, 0xa4, 0x36, 0xf7, 0xaf, 0x1a, 0x58,
0xdb, 0xb9, 0xd1, 0x53, 0xe8, 0x08, 0x7c, 0xec, 0x73, 0x92, 0xac, 0x2e, 0x75, 0x3b, 0xbc, 0x43,
0x02, 0xac, 0xfd, 0x8b, 0x99, 0x02, 0xa3, 0x07, 0xb0, 0xbf, 0x8e, 0x12, 0x8f, 0x71, 0x9f, 0x33,
0x2d, 0xfe, 0x60, 0x53, 0xe5, 0xb9, 0x70, 0xe3, 0xf6, 0x3a, 0x4a, 0xe4, 0x0e, 0xdd, 0x07, 0x4b,
0xa2, 0x53, 0x42, 0x02, 0xef, 0x7c, 0x99, 0x2a, 0xd9, 0x75, 0xdc, 0x15, 0x08, 0xe1, 0x7c, 0xb1,
0x4c, 0x19, 0x3a, 0x04, 0xd3, 0x5f, 0xd3, 0x3c, 0x51, 0x32, 0xeb, 0x58, 0x5b, 0xe8, 0x29, 0x74,
0x33, 0xc2, 0x78, 0x16, 0xad, 0xe4, 0xbd, 0xa5, 0x34, 0xd1, 0x7b, 0x9b, 0x47, 0xad, 0x44, 0xf1,
0x16, 0x16, 0x7d, 0x09, 0x16, 0xb9, 0x58, 0xc5, 0x79, 0x40, 0x02, 0x5d, 0x18, 0x73, 0x50, 0x3f,
0xe9, 0x8e, 0xa1, 0x52, 0xbe, 0x5e, 0x81, 0x50, 0x95, 0xfa, 0xd3, 0x80, 0xee, 0xab, 0x9c, 0x64,
0x97, 0x45, 0x3f, 0xb8, 0x60, 0x32, 0x92, 0x04, 0x24, 0xbb, 0xe5, 0xc7, 0xe8, 0x88, 0xc0, 0x70,
0x3f, 0x0b, 0x09, 0xd7, 0xc5, 0xd8, 0xc2, 0xa8, 0x08, 0xba, 0x03, 0xcd, 0x38, 0x5a, 0x47, 0x5c,
0x8b, 0x57, 0x06, 0x72, 0xa0, 0x9d, 0x46, 0x49, 0xb8, 0xf4, 0x57, 0xe7, 0x52, 0x77, 0x1b, 0x97,
0xb6, 0xfb, 0x0b, 0xf4, 0xf4, 0x4d, 0x74, 0x63, 0xbf, 0xcf, 0x55, 0x3e, 0x85, 0x76, 0xf9, 0xa7,
0x6a, 0x37, 0xfa, 0xbf, 0x8c, 0xb9, 0x3d, 0xe8, 0xfc, 0x14, 0x25, 0x61, 0xf1, 0x49, 0x2d, 0xe8,
0x2a, 0x53, 0x87, 0xff, 0x33, 0xa0, 0x53, 0x29, 0x2c, 0x7a, 0x02, 0x6d, 0x9a, 0x92, 0xcc, 0xe7,
0x54, 0x1d, 0x6e, 0x8d, 0x3e, 0x2e, 0x9b, 0xb6, 0x82, 0x1b, 0x9e, 0x69, 0x10, 0x2e, 0xe1, 0xe8,
0x31, 0xb4, 0xe4, 0x3e, 0x09, 0x64, 0x75, 0xac, 0xd1, 0x47, 0xbb, 0x99, 0x49, 0x80, 0x0b, 0xb0,
0x28, 0xd8, 0x1b, 0x3f, 0xce, 0x49, 0x51, 0x30, 0x69, 0xb8, 0x5f, 0x41, 0xbb, 0x38, 0x03, 0x99,
0x50, 0x9b, 0x2d, 0xec, 0x3d, 0xb1, 0x4e, 0x5f, 0xd9, 0x86, 0x58, 0x9f, 0x2f, 0xec, 0x1a, 0x6a,
0x41, 0x7d, 0xb6, 0x98, 0xda, 0x75, 0xb1, 0x79, 0xbe, 0x98, 0xda, 0x0d, 0xf7, 0x01, 0xb4, 0x74,
0x7e, 0x84, 0xc0, 0x7a, 0x86, 0xa7, 0x53, 0x6f, 0xfc, 0xc3, 0xcb, 0xc9, 0xeb, 0xd3, 0xc9, 0xe2,
0x47, 0x7b, 0x0f, 0xf5, 0x60, 0x5f, 0xfa, 0x26, 0xa7, 0xf3, 0x17, 0xb6, 0x31, 0xba, 0x32, 0xa0,
0xa5, 0x7f, 0x0b, 0x7a, 0x02, 0xa6, 0x1a, 0x45, 0x68, 0xc7, 0xb8, 0x73, 0x76, 0xcd, 0x2c, 0xf4,
0x1d, 0xc0, 0x38, 0x8f, 0xcf, 0x35, 0xfd, 0xe8, 0x76, 0x3a, 0x73, 0xfa, 0x3b, 0xf8, 0x0c, 0xbd,
0x06, 0xfb, 0xfa, 0x94, 0x42, 0x83, 0x12, 0xbd, 0x63, 0x80, 0x39, 0x9f, 0xbc, 0x03, 0xa1, 0x32,
0x8f, 0x38, 0x34, 0x55, 0xb6, 0xc7, 0xd0, 0x94, 0x2d, 0x86, 0xee, 0x96, 0xa4, 0x6a, 0xf3, 0x3b,
0x87, 0xd7, 0xdd, 0x5a, 0xda, 0x23, 0x68, 0x88, 0x76, 0x41, 0x77, 0xca, 0x78, 0xa5, 0x99, 0x9c,
0xbb, 0xd7, 0xbc, 0x8a, 0x34, 0x6e, 0xfc, 0x5c, 0x4b, 0x97, 0x4b, 0x53, 0x8e, 0x96, 0x47, 0xff,
0x07, 0x00, 0x00, 0xff, 0xff, 0xae, 0x57, 0x27, 0x55, 0x24, 0x07, 0x00, 0x00,
var fileDescriptor_overlay_b711a2281a37fa0c = []byte{
// 841 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xef, 0x8e, 0xdb, 0x44,
0x10, 0x3f, 0xc7, 0x89, 0x93, 0x4e, 0x12, 0x9f, 0xb5, 0x6a, 0xef, 0x82, 0x81, 0x5e, 0xb0, 0x2a,
0x38, 0x89, 0x2a, 0x85, 0x14, 0x55, 0xb4, 0x02, 0x01, 0x51, 0xd2, 0x72, 0x6a, 0xd4, 0x50, 0x27,
0x52, 0x25, 0xf8, 0x60, 0x39, 0xf1, 0x62, 0x4c, 0x1c, 0xaf, 0xf1, 0xae, 0xab, 0xbb, 0x3e, 0x01,
0x6f, 0xc2, 0xab, 0xf0, 0x0c, 0x7c, 0xb8, 0x47, 0xe0, 0x01, 0xf8, 0x84, 0xf6, 0x8f, 0x1d, 0xe7,
0xee, 0x72, 0xea, 0xa7, 0xdd, 0x99, 0xf9, 0xfd, 0x66, 0xf7, 0x37, 0x3b, 0x3b, 0xd0, 0x25, 0x6f,
0x71, 0x16, 0xfb, 0x17, 0x83, 0x34, 0x23, 0x8c, 0xa0, 0xa6, 0x32, 0xed, 0xfb, 0x21, 0x21, 0x61,
0x8c, 0x1f, 0x09, 0xf7, 0x32, 0xff, 0xf5, 0x51, 0x90, 0x67, 0x3e, 0x8b, 0x48, 0x22, 0x81, 0x36,
0x84, 0x24, 0x24, 0xc5, 0x3e, 0x21, 0x01, 0x96, 0x7b, 0xe7, 0x6b, 0xe8, 0x4e, 0x09, 0x59, 0xe7,
0xa9, 0x8b, 0xff, 0xc8, 0x31, 0x65, 0xe8, 0x33, 0x68, 0xf2, 0xb0, 0x17, 0x05, 0x3d, 0xad, 0xaf,
0x9d, 0x76, 0x46, 0xe6, 0xdf, 0x97, 0x27, 0x07, 0xff, 0x5c, 0x9e, 0x18, 0xaf, 0x48, 0x80, 0xcf,
0xc6, 0xae, 0xc1, 0xc3, 0x67, 0x81, 0xf3, 0x05, 0x98, 0x05, 0x93, 0xa6, 0x24, 0xa1, 0x18, 0xdd,
0x87, 0x3a, 0x8f, 0x09, 0x5e, 0x7b, 0x08, 0x03, 0x71, 0x0c, 0x67, 0xb9, 0xc2, 0xef, 0xcc, 0xb6,
0x0c, 0x71, 0x16, 0x45, 0xdf, 0x82, 0x19, 0x0b, 0x8f, 0x97, 0x49, 0x57, 0x4f, 0xeb, 0xeb, 0xa7,
0xed, 0xe1, 0xd1, 0xa0, 0x90, 0xb9, 0x43, 0x70, 0xbb, 0x71, 0xd5, 0x74, 0xe6, 0x70, 0xb8, 0x7b,
0x05, 0x8a, 0xbe, 0x87, 0xc3, 0x32, 0xa3, 0xf4, 0xa9, 0x94, 0xc7, 0xd7, 0x52, 0xca, 0xb0, 0x6b,
0xc6, 0x3b, 0xb6, 0xf3, 0x0d, 0xf4, 0x9e, 0x47, 0x49, 0x30, 0x67, 0x24, 0xf3, 0x43, 0xcc, 0xaf,
0x4f, 0x4b, 0x85, 0x7d, 0x68, 0x70, 0x25, 0x54, 0xe5, 0xac, 0x4a, 0x94, 0x01, 0xe7, 0x5f, 0x0d,
0x8e, 0xaf, 0xd3, 0x65, 0x69, 0x4f, 0xa0, 0x4d, 0x96, 0xbf, 0xe3, 0x15, 0xf3, 0x68, 0xf4, 0x4e,
0x96, 0x49, 0x77, 0x41, 0xba, 0xe6, 0xd1, 0x3b, 0x8c, 0x46, 0x70, 0xb8, 0x22, 0x09, 0xcb, 0xfc,
0x15, 0xf3, 0x62, 0x9c, 0x84, 0xec, 0xb7, 0x5e, 0x4d, 0xd4, 0xf2, 0x83, 0x81, 0x7c, 0xde, 0x41,
0xf1, 0xbc, 0x83, 0xb1, 0x7a, 0x5e, 0xd7, 0x2c, 0x18, 0x53, 0x41, 0x40, 0x9f, 0x43, 0x9d, 0xa4,
0x8c, 0xf6, 0x74, 0x41, 0xdc, 0xaa, 0x9e, 0xc9, 0x75, 0x96, 0x72, 0x16, 0x75, 0x05, 0x08, 0x3d,
0x80, 0x06, 0x65, 0x7e, 0xc6, 0x7a, 0xf5, 0x1b, 0x9f, 0x5a, 0x06, 0xd1, 0x87, 0x70, 0x67, 0x13,
0x25, 0x9e, 0x54, 0xde, 0x10, 0xb7, 0x6e, 0x6d, 0xa2, 0x44, 0x68, 0x73, 0xfe, 0xaa, 0x81, 0xb9,
0x9b, 0x1b, 0x3d, 0x83, 0xf6, 0xc6, 0x3f, 0xf7, 0x62, 0x9f, 0xe1, 0x64, 0x75, 0xa1, 0xda, 0xe1,
0x16, 0x09, 0xb0, 0xf1, 0xcf, 0xa7, 0x12, 0x8c, 0x1e, 0xca, 0xb3, 0x28, 0xf3, 0x19, 0x55, 0xe2,
0x0f, 0xb7, 0x55, 0x9e, 0x73, 0xb7, 0x38, 0x5c, 0xec, 0xd0, 0x03, 0x30, 0x05, 0x3a, 0xc5, 0x38,
0xf0, 0xd6, 0xcb, 0x54, 0xca, 0xd6, 0xdd, 0x0e, 0x47, 0x70, 0xe7, 0xcb, 0x65, 0x4a, 0xd1, 0x11,
0x18, 0xfe, 0x86, 0xe4, 0x89, 0x94, 0xa9, 0xbb, 0xca, 0x42, 0xcf, 0xa0, 0x93, 0x61, 0xca, 0xb2,
0x68, 0x25, 0xee, 0x2d, 0xa4, 0xf1, 0xde, 0xdb, 0x3e, 0x6a, 0x25, 0xea, 0xee, 0x60, 0xd1, 0x97,
0x60, 0xe2, 0xf3, 0x55, 0x9c, 0x07, 0x38, 0x50, 0x85, 0x31, 0xfa, 0xfa, 0x69, 0x67, 0x04, 0x95,
0xf2, 0x75, 0x0b, 0x84, 0xac, 0xd4, 0x9f, 0x1a, 0x74, 0x5e, 0xe7, 0x38, 0xbb, 0x28, 0xfa, 0xc1,
0x01, 0x83, 0xe2, 0x24, 0xc0, 0xd9, 0x0d, 0x3f, 0x46, 0x45, 0x38, 0x86, 0xf9, 0x59, 0x88, 0x99,
0x2a, 0xc6, 0x0e, 0x46, 0x46, 0xd0, 0x5d, 0x68, 0xc4, 0xd1, 0x26, 0x62, 0x4a, 0xbc, 0x34, 0x90,
0x0d, 0xad, 0x34, 0x4a, 0xc2, 0xa5, 0xbf, 0x5a, 0x0b, 0xdd, 0x2d, 0xb7, 0xb4, 0x9d, 0x5f, 0xa0,
0xab, 0x6e, 0xa2, 0x1a, 0xfb, 0x7d, 0xae, 0xf2, 0x29, 0xb4, 0xca, 0x3f, 0x55, 0xbb, 0xd6, 0xff,
0x65, 0xcc, 0xe9, 0x42, 0xfb, 0xa7, 0x28, 0x09, 0x8b, 0x4f, 0x6a, 0x42, 0x47, 0x9a, 0x2a, 0xfc,
0x9f, 0x06, 0xed, 0x4a, 0x61, 0xd1, 0x53, 0x68, 0x91, 0x14, 0x67, 0x3e, 0x23, 0xf2, 0x70, 0x73,
0xf8, 0x71, 0xd9, 0xb4, 0x15, 0xdc, 0x60, 0xa6, 0x40, 0x6e, 0x09, 0x47, 0x4f, 0xa0, 0x29, 0xf6,
0x49, 0x20, 0xaa, 0x63, 0x0e, 0x3f, 0xda, 0xcf, 0x4c, 0x02, 0xb7, 0x00, 0xf3, 0x82, 0xbd, 0xf5,
0xe3, 0x1c, 0x17, 0x05, 0x13, 0x86, 0xf3, 0x15, 0xb4, 0x8a, 0x33, 0x90, 0x01, 0xb5, 0xe9, 0xc2,
0x3a, 0xe0, 0xeb, 0xe4, 0xb5, 0xa5, 0xf1, 0xf5, 0xc5, 0xc2, 0xaa, 0xa1, 0x26, 0xe8, 0xd3, 0xc5,
0xc4, 0xd2, 0xf9, 0xe6, 0xc5, 0x62, 0x62, 0xd5, 0x9d, 0x87, 0xd0, 0x54, 0xf9, 0x11, 0x02, 0xf3,
0xb9, 0x3b, 0x99, 0x78, 0xa3, 0x1f, 0x5e, 0x8d, 0xdf, 0x9c, 0x8d, 0x17, 0x3f, 0x5a, 0x07, 0xa8,
0x0b, 0x77, 0x84, 0x6f, 0x7c, 0x36, 0x7f, 0x69, 0x69, 0xc3, 0x4b, 0x0d, 0x9a, 0xea, 0xb7, 0xa0,
0xa7, 0x60, 0xc8, 0x51, 0x84, 0xf6, 0x8c, 0x3b, 0x7b, 0xdf, 0xcc, 0x42, 0xdf, 0x01, 0x8c, 0xf2,
0x78, 0xad, 0xe8, 0xc7, 0x37, 0xd3, 0xa9, 0xdd, 0xdb, 0xc3, 0xa7, 0xe8, 0x0d, 0x58, 0x57, 0xa7,
0x14, 0xea, 0x97, 0xe8, 0x3d, 0x03, 0xcc, 0xfe, 0xe4, 0x16, 0x84, 0xcc, 0x3c, 0x64, 0xd0, 0x90,
0xd9, 0x9e, 0x40, 0x43, 0xb4, 0x18, 0xba, 0x57, 0x92, 0xaa, 0xcd, 0x6f, 0x1f, 0x5d, 0x75, 0x2b,
0x69, 0x8f, 0xa1, 0xce, 0xdb, 0x05, 0xdd, 0x2d, 0xe3, 0x95, 0x66, 0xb2, 0xef, 0x5d, 0xf1, 0x4a,
0xd2, 0xa8, 0xfe, 0x73, 0x2d, 0x5d, 0x2e, 0x0d, 0x31, 0x5a, 0x1e, 0xff, 0x1f, 0x00, 0x00, 0xff,
0xff, 0x7b, 0x95, 0x8a, 0xf4, 0x24, 0x07, 0x00, 0x00,
}

View File

@ -57,7 +57,7 @@ message FindStorageNodesRequest {
google.protobuf.Duration contract_length = 2;
OverlayOptions opts = 3;
bytes start = 4 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false];
int64 max_nodes = 5;
int64 min_nodes = 5;
}
// OverlayOptions is a set of criteria that a node must meet to be considered for a storage opportunity

View File

@ -250,14 +250,16 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, config *Config) (*
config := config.Overlay
peer.Overlay.Service = overlay.NewCache(peer.DB.OverlayCache(), peer.DB.StatDB())
ns := &pb.NodeStats{
nodeSelectionConfig := &overlay.NodeSelectionConfig{
UptimeCount: config.Node.UptimeCount,
UptimeRatio: config.Node.UptimeRatio,
AuditSuccessRatio: config.Node.AuditSuccessRatio,
AuditCount: config.Node.AuditCount,
NewNodeAuditThreshold: config.Node.NewNodeAuditThreshold,
NewNodePercentage: config.Node.NewNodePercentage,
}
peer.Overlay.Endpoint = overlay.NewServer(peer.Log.Named("overlay:endpoint"), peer.Overlay.Service, ns)
peer.Overlay.Endpoint = overlay.NewServer(peer.Log.Named("overlay:endpoint"), peer.Overlay.Service, nodeSelectionConfig)
pb.RegisterOverlayServer(peer.Public.Server.GRPC(), peer.Overlay.Endpoint)
peer.Overlay.Inspector = overlay.NewInspector(peer.Overlay.Service)

View File

@ -459,6 +459,13 @@ type lockedOverlayCache struct {
db overlay.DB
}
// FilterNodes looks up nodes based on reputation requirements
func (m *lockedOverlayCache) FilterNodes(ctx context.Context, req *overlay.FilterNodesRequest) ([]*pb.Node, error) {
m.Lock()
defer m.Unlock()
return m.db.FilterNodes(ctx, req)
}
// Delete deletes node based on id
func (m *lockedOverlayCache) Delete(ctx context.Context, id storj.NodeID) error {
m.Lock()

View File

@ -6,12 +6,17 @@ package satellitedb
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeebo/errs"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"storj.io/storj/pkg/overlay"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/storj"
"storj.io/storj/pkg/utils"
dbx "storj.io/storj/satellite/satellitedb/dbx"
"storj.io/storj/storage"
)
@ -22,6 +27,209 @@ type overlaycache struct {
db *dbx.DB
}
type getNodesRequest struct {
minReputation *pb.NodeStats
freeBandwidth int64
freeDisk int64
excluded []pb.NodeID
reputableNodeAmount int64
newNodeAmount int64
newNodeAuditThreshold int64
}
// FilterNodes looks up nodes based on reputation requirements
func (cache *overlaycache) FilterNodes(ctx context.Context, req *overlay.FilterNodesRequest) ([]*pb.Node, error) {
reputableNodeAmount := req.MinNodes
if reputableNodeAmount <= 0 {
reputableNodeAmount = req.Opts.GetAmount()
}
getReputableReq := &getNodesRequest{
minReputation: req.MinReputation,
freeBandwidth: req.Opts.GetRestrictions().FreeBandwidth,
freeDisk: req.Opts.GetRestrictions().FreeDisk,
excluded: req.Opts.ExcludedNodes,
reputableNodeAmount: reputableNodeAmount,
newNodeAuditThreshold: req.NewNodeAuditThreshold,
}
reputableNodes, err := cache.getReputableNodes(ctx, getReputableReq)
if err != nil {
return nil, err
}
newNodeAmount := int64(float64(reputableNodeAmount) * req.NewNodePercentage)
getNewReq := &getNodesRequest{
freeBandwidth: req.Opts.GetRestrictions().FreeBandwidth,
freeDisk: req.Opts.GetRestrictions().FreeDisk,
excluded: req.Opts.ExcludedNodes,
newNodeAmount: newNodeAmount,
newNodeAuditThreshold: req.NewNodeAuditThreshold,
}
newNodes, err := cache.getNewNodes(ctx, getNewReq)
if err != nil {
return nil, err
}
var allNodes []*pb.Node
allNodes = append(allNodes, reputableNodes...)
allNodes = append(allNodes, newNodes...)
if int64(len(reputableNodes)) < reputableNodeAmount {
err := status.Errorf(codes.ResourceExhausted, fmt.Sprintf("requested %d reputable nodes, only %d reputable nodes matched the criteria requested",
reputableNodeAmount, len(reputableNodes)))
return allNodes, err
}
return allNodes, nil
}
func (cache *overlaycache) getReputableNodes(ctx context.Context, req *getNodesRequest) ([]*pb.Node, error) {
rows, err := cache.findReputableNodesQuery(ctx, req)
if err != nil {
return nil, err
}
defer func() {
err = utils.CombineErrors(err, rows.Close())
}()
reputableNodes, err := sqlRowsToNodes(rows)
if err != nil {
return nil, err
}
return reputableNodes, nil
}
func (cache *overlaycache) getNewNodes(ctx context.Context, req *getNodesRequest) ([]*pb.Node, error) {
rows, err := cache.findNewNodesQuery(ctx, req)
if err != nil {
return nil, err
}
defer func() {
err = utils.CombineErrors(err, rows.Close())
}()
newNodes, err := sqlRowsToNodes(rows)
if err != nil {
return nil, err
}
return newNodes, nil
}
func sqlRowsToNodes(rows *sql.Rows) (nodes []*pb.Node, err error) {
for rows.Next() {
overlayNode := &dbx.OverlayCacheNode{}
err = rows.Scan(&overlayNode.NodeId, &overlayNode.NodeType,
&overlayNode.Address, &overlayNode.FreeBandwidth, &overlayNode.FreeDisk,
&overlayNode.AuditSuccessRatio, &overlayNode.AuditUptimeRatio,
&overlayNode.AuditCount, &overlayNode.AuditSuccessCount,
&overlayNode.UptimeCount, &overlayNode.UptimeSuccessCount)
if err != nil {
return nil, err
}
node, err := convertOverlayNode(overlayNode)
if err != nil {
return nil, err
}
nodes = append(nodes, node)
}
return nodes, nil
}
func (cache *overlaycache) findReputableNodesQuery(ctx context.Context, req *getNodesRequest) (*sql.Rows, error) {
auditCount := req.minReputation.AuditCount
if req.newNodeAuditThreshold > auditCount {
auditCount = req.newNodeAuditThreshold
}
auditSuccessRatio := req.minReputation.AuditSuccessRatio
uptimeCount := req.minReputation.UptimeCount
uptimeRatio := req.minReputation.UptimeRatio
nodeAmt := req.reputableNodeAmount
var rows *sql.Rows
var err error
var nodeTypeStorage int32 = 2
args := make([]interface{}, len(req.excluded))
for i, id := range req.excluded {
args[i] = id.Bytes()
}
args = append(args, auditCount, auditSuccessRatio, uptimeCount, uptimeRatio,
req.freeBandwidth, req.freeDisk, nodeTypeStorage, nodeAmt)
// This queries for nodes whose audit counts are greater than or equal to
// the new node audit threshold and the minimum reputation audit count.
rows, err = cache.db.Query(`SELECT node_id,
node_type, address, free_bandwidth, free_disk, audit_success_ratio,
audit_uptime_ratio, audit_count, audit_success_count, uptime_count,
uptime_success_count
FROM overlay_cache_nodes
WHERE node_id NOT IN (`+strings.Join(sliceOfCopies("?", len(req.excluded)), ", ")+`)
AND audit_count >= ?
AND audit_success_ratio >= ?
AND uptime_count >= ?
AND audit_uptime_ratio >= ?
AND free_bandwidth >= ?
AND free_disk >= ?
AND node_type == ?
LIMIT ?
`,
args...)
if err != nil {
return nil, err
}
return rows, nil
}
func sliceOfCopies(val string, count int) []string {
slice := make([]string, count)
for i := range slice {
slice[i] = val
}
return slice
}
func (cache *overlaycache) findNewNodesQuery(ctx context.Context, req *getNodesRequest) (*sql.Rows, error) {
var rows *sql.Rows
var err error
var nodeTypeStorage int32 = 2
args := make([]interface{}, len(req.excluded))
for i, id := range req.excluded {
args[i] = id.Bytes()
}
args = append(args, req.newNodeAuditThreshold, req.freeBandwidth,
req.freeDisk, nodeTypeStorage, req.newNodeAmount)
rows, err = cache.db.Query(cache.db.Rebind(`SELECT node_id,
node_type, address, free_bandwidth, free_disk, audit_success_ratio,
audit_uptime_ratio, audit_count, audit_success_count, uptime_count,
uptime_success_count
FROM overlay_cache_nodes
WHERE node_id NOT IN (`+strings.Join(sliceOfCopies("?", len(req.excluded)), ", ")+`)
AND audit_count < ?
AND free_bandwidth >= ?
AND free_disk >= ?
AND node_type == ?
LIMIT ?
`),
args...)
if err != nil {
return nil, err
}
return rows, nil
}
// Get looks up the node by nodeID
func (cache *overlaycache) Get(ctx context.Context, id storj.NodeID) (*pb.Node, error) {
if id.IsZero() {