Add statdb to overlay cache (node selection) (#711)

* make overlay node rep consistent with statdb node rep

* add statdb to testplanet

* add statdb to overlay cache

* tests
This commit is contained in:
Maximillian von Briesen 2018-11-27 12:46:12 -05:00 committed by GitHub
parent 376bd74bed
commit 7cf16503b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 158 additions and 114 deletions

View File

@ -48,5 +48,5 @@ func (c cacheConfig) open() (*overlay.Cache, error) {
// add logger
db = storelogger.New(zap.L(), db)
return overlay.NewOverlayCache(db, nil), nil
return overlay.NewOverlayCache(db, nil, nil), nil
}

View File

@ -5,7 +5,9 @@ package testplanet
import (
"context"
"fmt"
"io"
"math/rand"
"net"
"go.uber.org/zap"
@ -17,6 +19,7 @@ import (
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/pointerdb/pdbclient"
"storj.io/storj/pkg/provider"
"storj.io/storj/pkg/statdb"
"storj.io/storj/pkg/transport"
"storj.io/storj/pkg/utils"
"storj.io/storj/storage/teststore"
@ -31,6 +34,7 @@ type Node struct {
Listener net.Listener
Provider *provider.Provider
Kademlia *kademlia.Kademlia
StatDB *statdb.Server
Overlay *overlay.Cache
Dependencies []io.Closer
@ -145,8 +149,20 @@ func (node *Node) initOverlay(planet *Planet) error {
}
node.Kademlia = kad
node.Overlay = overlay.NewOverlayCache(teststore.New(), node.Kademlia)
node.Overlay = overlay.NewOverlayCache(teststore.New(), node.Kademlia, node.StatDB)
return nil
}
// initStatDB creates statdb for a given planet
func (node *Node) initStatDB() error {
dbPath := fmt.Sprintf("file:memdb%d?mode=memory&cache=shared", rand.Int63())
sdb, err := statdb.NewServer("sqlite3", dbPath, "", zap.NewNop())
if err != nil {
return err
}
node.StatDB = sdb
return nil
}

View File

@ -83,7 +83,11 @@ func New(t zaptest.TestingT, satelliteCount, storageNodeCount, uplinkCount int)
}
for _, node := range planet.nodes {
err := node.initOverlay(planet)
err := node.initStatDB()
if err != nil {
return nil, utils.CombineErrors(err, planet.Shutdown())
}
err = node.initOverlay(planet)
if err != nil {
return nil, utils.CombineErrors(err, planet.Shutdown())
}

View File

@ -128,7 +128,7 @@ func TestAuditSegment(t *testing.T) {
db := teststore.New()
c := pointerdb.Config{MaxInlineSegmentSize: 8000}
cache := overlay.NewOverlayCache(teststore.New(), nil)
cache := overlay.NewOverlayCache(teststore.New(), nil, nil)
pdbw := newPointerDBWrapper(pointerdb.NewServer(db, cache, zap.NewNop(), c, identity))
pointers := pdbclient.New(pdbw)

View File

@ -12,6 +12,7 @@ import (
"storj.io/storj/pkg/dht"
"storj.io/storj/pkg/node"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/statdb"
"storj.io/storj/storage"
)
@ -31,13 +32,14 @@ var OverlayError = errs.Class("Overlay Error")
// Cache is used to store overlay data in Redis
type Cache struct {
DB storage.KeyValueStore
DHT dht.DHT
DB storage.KeyValueStore
DHT dht.DHT
StatDB *statdb.Server
}
// NewOverlayCache returns a new Cache
func NewOverlayCache(db storage.KeyValueStore, dht dht.DHT) *Cache {
return &Cache{DB: db, DHT: dht}
func NewOverlayCache(db storage.KeyValueStore, dht dht.DHT, sdb *statdb.Server) *Cache {
return &Cache{DB: db, DHT: dht, StatDB: sdb}
}
// Get looks up the provided nodeID from the overlay cache

View File

@ -303,7 +303,7 @@ func newServer(ctx context.Context) (*grpc.Server, *Server, error) {
}
grpcServer := grpc.NewServer(identOpt)
s := &Server{cache: NewOverlayCache(teststore.New(), nil)}
s := &Server{cache: NewOverlayCache(teststore.New(), nil, nil)}
pb.RegisterOverlayServer(grpcServer, s)

View File

@ -14,6 +14,7 @@ import (
"storj.io/storj/pkg/kademlia"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/provider"
"storj.io/storj/pkg/statdb"
"storj.io/storj/pkg/utils"
"storj.io/storj/storage"
"storj.io/storj/storage/boltdb"
@ -52,6 +53,11 @@ func (c Config) Run(ctx context.Context, server *provider.Provider) (
return Error.New("programmer error: kademlia responsibility unstarted")
}
sdb := statdb.LoadFromContext(ctx)
if sdb == nil {
return Error.New("programmer error: statdb responsibility unstarted")
}
dburl, err := utils.ParseURL(c.DatabaseURL)
if err != nil {
return Error.Wrap(err)
@ -76,7 +82,7 @@ func (c Config) Run(ctx context.Context, server *provider.Provider) (
return Error.New("database scheme not supported: %s", dburl.Scheme)
}
cache := NewOverlayCache(db, kad)
cache := NewOverlayCache(db, kad, sdb)
go func() {
err = cache.Bootstrap(ctx)

View File

@ -9,12 +9,19 @@ import (
"github.com/stretchr/testify/assert"
"storj.io/storj/pkg/kademlia"
"storj.io/storj/pkg/statdb"
)
func TestRun(t *testing.T) {
bctx := context.Background()
kad := &kademlia.Kademlia{}
var kadKey kademlia.CtxKey
ctxWithKad := context.WithValue(context.Background(), kadKey, kad)
ctx := context.WithValue(bctx, kadKey, kad)
sdb := &statdb.Server{}
var statKey statdb.CtxKey
ctx = context.WithValue(ctx, statKey, sdb)
// run with nil
err := Config{}.Run(context.Background(), nil)
@ -22,17 +29,17 @@ func TestRun(t *testing.T) {
assert.Equal(t, "overlay error: programmer error: kademlia responsibility unstarted", err.Error())
// run with nil, pass pointer to Kademlia in context
err = Config{}.Run(ctxWithKad, nil)
err = Config{}.Run(ctx, nil)
assert.Error(t, err)
assert.Equal(t, "overlay error: database scheme not supported: ", err.Error())
// db scheme redis conn fail
err = Config{DatabaseURL: "redis://somedir/overlay.db/?db=1"}.Run(ctxWithKad, nil)
err = Config{DatabaseURL: "redis://somedir/overlay.db/?db=1"}.Run(ctx, nil)
assert.Error(t, err)
assert.Equal(t, "redis error: ping failed: dial tcp: address somedir: missing port in address", err.Error())
// db scheme bolt conn fail
err = Config{DatabaseURL: "bolt://somedir/overlay.db"}.Run(ctxWithKad, nil)
err = Config{DatabaseURL: "bolt://somedir/overlay.db"}.Run(ctx, nil)
assert.Error(t, err)
}

View File

@ -40,7 +40,7 @@ func (x NodeTransport) String() string {
return proto.EnumName(NodeTransport_name, int32(x))
}
func (NodeTransport) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{0}
return fileDescriptor_overlay_94858445011884fe, []int{0}
}
// NodeType is an enum of possible node types
@ -64,7 +64,7 @@ func (x NodeType) String() string {
return proto.EnumName(NodeType_name, int32(x))
}
func (NodeType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{1}
return fileDescriptor_overlay_94858445011884fe, []int{1}
}
type Restriction_Operator int32
@ -96,7 +96,7 @@ func (x Restriction_Operator) String() string {
return proto.EnumName(Restriction_Operator_name, int32(x))
}
func (Restriction_Operator) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{16, 0}
return fileDescriptor_overlay_94858445011884fe, []int{16, 0}
}
type Restriction_Operand int32
@ -119,7 +119,7 @@ func (x Restriction_Operand) String() string {
return proto.EnumName(Restriction_Operand_name, int32(x))
}
func (Restriction_Operand) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{16, 1}
return fileDescriptor_overlay_94858445011884fe, []int{16, 1}
}
// LookupRequest is is request message for the lookup rpc call
@ -134,7 +134,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_0979f23babec84b8, []int{0}
return fileDescriptor_overlay_94858445011884fe, []int{0}
}
func (m *LookupRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupRequest.Unmarshal(m, b)
@ -173,7 +173,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_0979f23babec84b8, []int{1}
return fileDescriptor_overlay_94858445011884fe, []int{1}
}
func (m *LookupResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupResponse.Unmarshal(m, b)
@ -212,7 +212,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_0979f23babec84b8, []int{2}
return fileDescriptor_overlay_94858445011884fe, []int{2}
}
func (m *LookupRequests) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupRequests.Unmarshal(m, b)
@ -251,7 +251,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_0979f23babec84b8, []int{3}
return fileDescriptor_overlay_94858445011884fe, []int{3}
}
func (m *LookupResponses) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LookupResponses.Unmarshal(m, b)
@ -290,7 +290,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_0979f23babec84b8, []int{4}
return fileDescriptor_overlay_94858445011884fe, []int{4}
}
func (m *FindStorageNodesResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FindStorageNodesResponse.Unmarshal(m, b)
@ -333,7 +333,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_0979f23babec84b8, []int{5}
return fileDescriptor_overlay_94858445011884fe, []int{5}
}
func (m *FindStorageNodesRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FindStorageNodesRequest.Unmarshal(m, b)
@ -401,7 +401,7 @@ func (m *NodeAddress) Reset() { *m = NodeAddress{} }
func (m *NodeAddress) String() string { return proto.CompactTextString(m) }
func (*NodeAddress) ProtoMessage() {}
func (*NodeAddress) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{6}
return fileDescriptor_overlay_94858445011884fe, []int{6}
}
func (m *NodeAddress) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeAddress.Unmarshal(m, b)
@ -452,7 +452,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_0979f23babec84b8, []int{7}
return fileDescriptor_overlay_94858445011884fe, []int{7}
}
func (m *OverlayOptions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OverlayOptions.Unmarshal(m, b)
@ -516,9 +516,9 @@ func (m *OverlayOptions) GetExcludedNodes() []string {
// NodeRep is the reputation characteristics of a node
type NodeRep struct {
UptimeRatio float32 `protobuf:"fixed32,1,opt,name=uptime_ratio,json=uptimeRatio,proto3" json:"uptime_ratio,omitempty"`
AuditSuccessRatio float32 `protobuf:"fixed32,2,opt,name=audit_success_ratio,json=auditSuccessRatio,proto3" json:"audit_success_ratio,omitempty"`
AuditCount int64 `protobuf:"varint,3,opt,name=audit_count,json=auditCount,proto3" json:"audit_count,omitempty"`
UptimeRatio float64 `protobuf:"fixed64,1,opt,name=uptimeRatio,proto3" json:"uptimeRatio,omitempty"`
AuditSuccessRatio float64 `protobuf:"fixed64,2,opt,name=auditSuccessRatio,proto3" json:"auditSuccessRatio,omitempty"`
AuditCount int64 `protobuf:"varint,3,opt,name=auditCount,proto3" json:"auditCount,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -528,7 +528,7 @@ func (m *NodeRep) Reset() { *m = NodeRep{} }
func (m *NodeRep) String() string { return proto.CompactTextString(m) }
func (*NodeRep) ProtoMessage() {}
func (*NodeRep) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{8}
return fileDescriptor_overlay_94858445011884fe, []int{8}
}
func (m *NodeRep) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeRep.Unmarshal(m, b)
@ -548,14 +548,14 @@ func (m *NodeRep) XXX_DiscardUnknown() {
var xxx_messageInfo_NodeRep proto.InternalMessageInfo
func (m *NodeRep) GetUptimeRatio() float32 {
func (m *NodeRep) GetUptimeRatio() float64 {
if m != nil {
return m.UptimeRatio
}
return 0
}
func (m *NodeRep) GetAuditSuccessRatio() float32 {
func (m *NodeRep) GetAuditSuccessRatio() float64 {
if m != nil {
return m.AuditSuccessRatio
}
@ -582,7 +582,7 @@ func (m *NodeRestrictions) Reset() { *m = NodeRestrictions{} }
func (m *NodeRestrictions) String() string { return proto.CompactTextString(m) }
func (*NodeRestrictions) ProtoMessage() {}
func (*NodeRestrictions) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{9}
return fileDescriptor_overlay_94858445011884fe, []int{9}
}
func (m *NodeRestrictions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeRestrictions.Unmarshal(m, b)
@ -623,6 +623,7 @@ type Node struct {
Type NodeType `protobuf:"varint,3,opt,name=type,proto3,enum=overlay.NodeType" json:"type,omitempty"`
Restrictions *NodeRestrictions `protobuf:"bytes,4,opt,name=restrictions" json:"restrictions,omitempty"`
Metadata *NodeMetadata `protobuf:"bytes,5,opt,name=metadata" json:"metadata,omitempty"`
Reputation *NodeRep `protobuf:"bytes,6,opt,name=reputation" json:"reputation,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -632,7 +633,7 @@ func (m *Node) Reset() { *m = Node{} }
func (m *Node) String() string { return proto.CompactTextString(m) }
func (*Node) ProtoMessage() {}
func (*Node) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{10}
return fileDescriptor_overlay_94858445011884fe, []int{10}
}
func (m *Node) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Node.Unmarshal(m, b)
@ -687,6 +688,13 @@ func (m *Node) GetMetadata() *NodeMetadata {
return nil
}
func (m *Node) GetReputation() *NodeRep {
if m != nil {
return m.Reputation
}
return nil
}
type NodeMetadata struct {
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
Wallet string `protobuf:"bytes,2,opt,name=wallet,proto3" json:"wallet,omitempty"`
@ -699,7 +707,7 @@ func (m *NodeMetadata) Reset() { *m = NodeMetadata{} }
func (m *NodeMetadata) String() string { return proto.CompactTextString(m) }
func (*NodeMetadata) ProtoMessage() {}
func (*NodeMetadata) Descriptor() ([]byte, []int) {
return fileDescriptor_overlay_0979f23babec84b8, []int{11}
return fileDescriptor_overlay_94858445011884fe, []int{11}
}
func (m *NodeMetadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeMetadata.Unmarshal(m, b)
@ -747,7 +755,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_0979f23babec84b8, []int{12}
return fileDescriptor_overlay_94858445011884fe, []int{12}
}
func (m *QueryRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryRequest.Unmarshal(m, b)
@ -807,7 +815,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_0979f23babec84b8, []int{13}
return fileDescriptor_overlay_94858445011884fe, []int{13}
}
func (m *QueryResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryResponse.Unmarshal(m, b)
@ -851,7 +859,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_0979f23babec84b8, []int{14}
return fileDescriptor_overlay_94858445011884fe, []int{14}
}
func (m *PingRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PingRequest.Unmarshal(m, b)
@ -881,7 +889,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_0979f23babec84b8, []int{15}
return fileDescriptor_overlay_94858445011884fe, []int{15}
}
func (m *PingResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PingResponse.Unmarshal(m, b)
@ -914,7 +922,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_0979f23babec84b8, []int{16}
return fileDescriptor_overlay_94858445011884fe, []int{16}
}
func (m *Restriction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Restriction.Unmarshal(m, b)
@ -1220,77 +1228,77 @@ var _Nodes_serviceDesc = grpc.ServiceDesc{
Metadata: "overlay.proto",
}
func init() { proto.RegisterFile("overlay.proto", fileDescriptor_overlay_0979f23babec84b8) }
func init() { proto.RegisterFile("overlay.proto", fileDescriptor_overlay_94858445011884fe) }
var fileDescriptor_overlay_0979f23babec84b8 = []byte{
// 1099 bytes of a gzipped FileDescriptorProto
var fileDescriptor_overlay_94858445011884fe = []byte{
// 1100 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xdb, 0x6e, 0xdb, 0x46,
0x13, 0x36, 0x75, 0xd6, 0x48, 0xa2, 0x99, 0xfd, 0x13, 0x5b, 0xbf, 0x7a, 0x88, 0xcd, 0xd6, 0xa8,
0x9b, 0x16, 0x0a, 0x2a, 0x07, 0x29, 0x52, 0x34, 0x48, 0x6d, 0x4b, 0x71, 0x8d, 0x28, 0xb6, 0xb3,
0x12, 0x1a, 0xa0, 0x40, 0x41, 0xac, 0xc4, 0x8d, 0xc2, 0x8a, 0x22, 0x59, 0xee, 0x32, 0xb1, 0x03,
0xf4, 0x15, 0xfa, 0x1e, 0x7d, 0xa9, 0xf4, 0x3d, 0x7a, 0x55, 0xec, 0x81, 0x94, 0xe8, 0x43, 0xd0,
0x5e, 0x71, 0xe7, 0x9b, 0x6f, 0x86, 0x73, 0xda, 0x59, 0x68, 0x85, 0x6f, 0x68, 0xec, 0x93, 0x8b,
0x6e, 0x14, 0x87, 0x3c, 0x44, 0x55, 0x2d, 0x76, 0x3e, 0x9d, 0x85, 0xe1, 0xcc, 0xa7, 0xf7, 0x25,
0x3c, 0x49, 0x5e, 0xdd, 0x77, 0x93, 0x98, 0x70, 0x2f, 0x0c, 0x14, 0xd1, 0xfe, 0x02, 0x5a, 0xc3,
0x30, 0x9c, 0x27, 0x11, 0xa6, 0xbf, 0x25, 0x94, 0x71, 0xb4, 0x01, 0x95, 0x20, 0x74, 0xe9, 0x71,
0xbf, 0x6d, 0x6c, 0x19, 0xbb, 0x75, 0xac, 0x25, 0x7b, 0x0f, 0xcc, 0x94, 0xc8, 0xa2, 0x30, 0x60,
0x14, 0x6d, 0x43, 0x49, 0xe8, 0x24, 0xaf, 0xd1, 0x6b, 0x75, 0xd3, 0x08, 0x4e, 0x42, 0x97, 0x62,
0xa9, 0xb2, 0x4f, 0x97, 0x46, 0xd2, 0x3b, 0x43, 0x8f, 0xc1, 0xf4, 0x25, 0xe2, 0xc4, 0x0a, 0x6a,
0x1b, 0x5b, 0xc5, 0xdd, 0x46, 0x6f, 0x23, 0x33, 0xcf, 0x19, 0xe0, 0x96, 0xbf, 0x2a, 0xda, 0x23,
0x58, 0xcf, 0x47, 0xc1, 0xd0, 0x0f, 0xb0, 0x9e, 0x79, 0x54, 0x98, 0x76, 0xb9, 0x79, 0xc5, 0xa5,
0x52, 0x63, 0xd3, 0xcf, 0xc9, 0xf6, 0x13, 0x68, 0x3f, 0xf5, 0x02, 0x77, 0xc4, 0xc3, 0x98, 0xcc,
0xa8, 0x08, 0x9f, 0x65, 0x49, 0x7e, 0x06, 0x65, 0x91, 0x09, 0xd3, 0x3e, 0x2f, 0x65, 0xa9, 0x74,
0xf6, 0x7b, 0x03, 0x36, 0xaf, 0x7a, 0x50, 0xf5, 0xbc, 0x0b, 0x8d, 0x70, 0xf2, 0x2b, 0x9d, 0x72,
0x87, 0x79, 0xef, 0x54, 0xb1, 0x8a, 0x18, 0x14, 0x34, 0xf2, 0xde, 0x51, 0x74, 0x00, 0xeb, 0xd3,
0x30, 0xe0, 0x31, 0x99, 0x72, 0xc7, 0xa7, 0xc1, 0x8c, 0xbf, 0x6e, 0x17, 0x64, 0x45, 0xff, 0xdf,
0x55, 0xbd, 0xeb, 0xa6, 0xbd, 0xeb, 0xf6, 0x75, 0xef, 0xb0, 0x99, 0x5a, 0x0c, 0xa5, 0x01, 0xfa,
0x0a, 0x4a, 0x61, 0xc4, 0x59, 0xbb, 0x28, 0x0d, 0x97, 0x89, 0x9f, 0xaa, 0xef, 0x69, 0x24, 0xac,
0x18, 0x96, 0x24, 0x74, 0x1b, 0xca, 0x8c, 0x93, 0x98, 0xb7, 0x4b, 0x5b, 0xc6, 0x6e, 0x13, 0x2b,
0x01, 0x7d, 0x04, 0xf5, 0x05, 0x39, 0x77, 0x54, 0xb2, 0x65, 0x19, 0x65, 0x6d, 0x41, 0xce, 0x65,
0x2e, 0xf6, 0x2f, 0xd0, 0x10, 0x87, 0x7d, 0xd7, 0x8d, 0x29, 0x63, 0xe8, 0x01, 0xd4, 0x79, 0x4c,
0x02, 0x16, 0x85, 0x31, 0x97, 0x19, 0x99, 0x2b, 0xfd, 0x13, 0xc4, 0x71, 0xaa, 0xc5, 0x4b, 0x22,
0x6a, 0x43, 0x95, 0x28, 0x07, 0x32, 0xc1, 0x3a, 0x4e, 0x45, 0xfb, 0xcf, 0x02, 0x98, 0xf9, 0x50,
0xd1, 0x77, 0xd0, 0x10, 0xe1, 0xf8, 0x84, 0xd3, 0x60, 0x7a, 0xa1, 0x67, 0xec, 0x03, 0x15, 0x81,
0x05, 0x39, 0x1f, 0x2a, 0x32, 0xfa, 0x16, 0xcc, 0x85, 0x17, 0x38, 0x31, 0x8d, 0x12, 0x2e, 0xb5,
0xba, 0xa0, 0x56, 0xbe, 0x79, 0x34, 0xc2, 0xad, 0x85, 0x17, 0xe0, 0x8c, 0x86, 0x3e, 0x57, 0x86,
0x2c, 0xa2, 0xd4, 0x75, 0xe6, 0x93, 0x48, 0x15, 0xb4, 0x88, 0x9b, 0x0b, 0x2f, 0x18, 0x09, 0xf0,
0xd9, 0x24, 0x62, 0xe2, 0x86, 0x90, 0x45, 0x98, 0x04, 0xaa, 0x80, 0x45, 0xac, 0x25, 0xf4, 0x18,
0x9a, 0x31, 0x65, 0x3c, 0xf6, 0xa6, 0x32, 0x05, 0x59, 0x44, 0x11, 0x73, 0xfe, 0xa7, 0x4b, 0x02,
0xce, 0xd1, 0xd1, 0x0e, 0x98, 0xf4, 0x7c, 0xea, 0x27, 0x2e, 0x75, 0x75, 0x17, 0x2a, 0x5b, 0xc5,
0xdd, 0x3a, 0x6e, 0xa5, 0xa8, 0x6a, 0xc5, 0xef, 0x50, 0xd5, 0xd1, 0xa3, 0x6d, 0x68, 0x26, 0x11,
0xf7, 0x16, 0xd4, 0x91, 0x45, 0x90, 0x45, 0x2a, 0xe0, 0x86, 0xc2, 0xb0, 0x80, 0x50, 0x17, 0xfe,
0x47, 0x12, 0xd7, 0xe3, 0x0e, 0x4b, 0xa6, 0x53, 0xca, 0x98, 0x66, 0x16, 0x24, 0xf3, 0x96, 0x54,
0x8d, 0x94, 0x46, 0xf1, 0xef, 0x42, 0x43, 0xf1, 0xa7, 0x32, 0x41, 0x95, 0x3e, 0x48, 0xe8, 0x50,
0x20, 0xf6, 0x4f, 0x60, 0x5d, 0xce, 0x43, 0x44, 0xfe, 0x2a, 0xa6, 0xd4, 0x99, 0x90, 0xc0, 0x7d,
0xeb, 0xb9, 0xfc, 0xb5, 0x9e, 0xf2, 0x96, 0x40, 0x0f, 0x52, 0x50, 0x4c, 0x98, 0xa4, 0xb9, 0x1e,
0x9b, 0xcb, 0x08, 0x8a, 0xb8, 0x26, 0x80, 0xbe, 0xc7, 0xe6, 0xf6, 0x5f, 0x06, 0x94, 0x84, 0x63,
0x64, 0x42, 0xc1, 0x73, 0xf5, 0xee, 0x29, 0x78, 0x2e, 0xea, 0xe6, 0xa7, 0xa6, 0xd1, 0xbb, 0x9d,
0x2b, 0xa8, 0x1e, 0xc9, 0x6c, 0x96, 0xd0, 0x0e, 0x94, 0xf8, 0x45, 0x44, 0x65, 0xe8, 0x66, 0xef,
0x56, 0x7e, 0x2c, 0x2f, 0x22, 0x8a, 0xa5, 0xfa, 0x4a, 0xb3, 0x4a, 0xff, 0xad, 0x59, 0xdf, 0x40,
0x6d, 0x41, 0x39, 0x71, 0x09, 0x27, 0xba, 0xcf, 0x77, 0x72, 0xa6, 0xcf, 0xb5, 0x12, 0x67, 0x34,
0xfb, 0x7b, 0x68, 0xae, 0x6a, 0xc4, 0x35, 0xa4, 0x0b, 0xe2, 0xf9, 0x3a, 0x57, 0x25, 0x88, 0xe1,
0x7a, 0x4b, 0x7c, 0x9f, 0x72, 0x7d, 0x47, 0xb4, 0x64, 0xff, 0x61, 0x40, 0xf3, 0x45, 0x42, 0xe3,
0x8b, 0x74, 0xaf, 0xec, 0x40, 0x85, 0xd1, 0xc0, 0xa5, 0xf1, 0xf5, 0xfb, 0x57, 0x2b, 0x05, 0x8d,
0x93, 0x78, 0xa6, 0xfd, 0x5d, 0xa5, 0x29, 0xa5, 0x08, 0xc6, 0xf7, 0x16, 0x5e, 0xda, 0x71, 0x25,
0xa0, 0x0e, 0xd4, 0x22, 0x2f, 0x98, 0x4d, 0xc8, 0x74, 0x2e, 0x0b, 0x54, 0xc3, 0x99, 0x6c, 0x13,
0x68, 0xe9, 0x78, 0xf4, 0xa6, 0xfc, 0x97, 0x01, 0x7d, 0x09, 0xb5, 0x6c, 0x4f, 0x17, 0xae, 0xdb,
0xa9, 0x99, 0xda, 0x6e, 0x41, 0xe3, 0xcc, 0x0b, 0x66, 0xe9, 0xee, 0x37, 0xa1, 0xa9, 0x44, 0xad,
0xfe, 0xdb, 0x80, 0xc6, 0x4a, 0x8b, 0xd0, 0x23, 0xa8, 0x85, 0x11, 0x8d, 0x09, 0x0f, 0x63, 0xbd,
0x94, 0x3e, 0xc9, 0x3c, 0xaf, 0xf0, 0xba, 0xa7, 0x9a, 0x84, 0x33, 0x3a, 0x7a, 0x08, 0x55, 0x79,
0x0e, 0x5c, 0x59, 0x26, 0xb3, 0xf7, 0xf1, 0xcd, 0x96, 0x81, 0x8b, 0x53, 0xb2, 0x28, 0xdb, 0x1b,
0xe2, 0x27, 0x34, 0x2d, 0x9b, 0x14, 0xec, 0x07, 0x50, 0x4b, 0xff, 0x81, 0x2a, 0x50, 0x18, 0x8e,
0xad, 0x35, 0xf1, 0x1d, 0xbc, 0xb0, 0x0c, 0xf1, 0x3d, 0x1a, 0x5b, 0x05, 0x54, 0x85, 0xe2, 0x70,
0x3c, 0xb0, 0x8a, 0xe2, 0x70, 0x34, 0x1e, 0x58, 0x25, 0xfb, 0x6b, 0xa8, 0x6a, 0xff, 0x08, 0x81,
0xf9, 0x14, 0x0f, 0x06, 0xce, 0xc1, 0xfe, 0x49, 0xff, 0xe5, 0x71, 0x7f, 0xfc, 0xa3, 0xb5, 0x86,
0x5a, 0x50, 0x97, 0x58, 0xff, 0x78, 0xf4, 0xcc, 0x32, 0xee, 0x6d, 0x43, 0x2b, 0xb7, 0x68, 0x91,
0x05, 0xcd, 0xf1, 0xe1, 0x99, 0x33, 0x1e, 0x8e, 0x9c, 0x23, 0x7c, 0x76, 0x68, 0xad, 0xdd, 0xb3,
0xa1, 0x96, 0x0e, 0x3d, 0xaa, 0x43, 0x79, 0xbf, 0xff, 0xfc, 0xf8, 0xc4, 0x5a, 0x43, 0x0d, 0xa8,
0x8e, 0xc6, 0xa7, 0x78, 0xff, 0x68, 0x60, 0x19, 0xbd, 0xf7, 0x06, 0x54, 0xf5, 0xe6, 0x45, 0x8f,
0xa0, 0xa2, 0x1e, 0x4a, 0x74, 0xc3, 0x63, 0xdc, 0xb9, 0xe9, 0x45, 0x45, 0x4f, 0x00, 0x0e, 0x12,
0x7f, 0xae, 0xcd, 0x37, 0xaf, 0x37, 0x67, 0x9d, 0xf6, 0x0d, 0xf6, 0x0c, 0xbd, 0x04, 0xeb, 0xf2,
0x03, 0x8a, 0xb6, 0x32, 0xf6, 0x0d, 0x6f, 0x6b, 0x67, 0xfb, 0x03, 0x0c, 0xe5, 0xb9, 0xc7, 0xa1,
0xac, 0xbc, 0x3d, 0x84, 0xb2, 0x9c, 0x57, 0xb4, 0xbc, 0xa8, 0xab, 0xf7, 0xa9, 0xb3, 0x71, 0x19,
0xd6, 0xa9, 0xed, 0x41, 0x49, 0x4c, 0x1d, 0x5a, 0xae, 0x9d, 0x95, 0x99, 0xec, 0xdc, 0xb9, 0x84,
0x2a, 0xa3, 0x83, 0xd2, 0xcf, 0x85, 0x68, 0x32, 0xa9, 0xc8, 0x67, 0x6a, 0xef, 0x9f, 0x00, 0x00,
0x00, 0xff, 0xff, 0xca, 0x59, 0x96, 0x6f, 0x9c, 0x09, 0x00, 0x00,
0x13, 0x36, 0x75, 0xd6, 0x48, 0x62, 0x98, 0x45, 0x12, 0xeb, 0xd7, 0xdf, 0xa6, 0x32, 0x5b, 0xa3,
0x6e, 0x1a, 0x28, 0xad, 0x1c, 0xa4, 0x48, 0xd1, 0x20, 0xb5, 0x2d, 0xc5, 0x35, 0xa2, 0xd8, 0xce,
0x4a, 0x68, 0x80, 0x02, 0x85, 0xb0, 0x12, 0x37, 0x0a, 0x2b, 0x8a, 0x64, 0xb9, 0xcb, 0xc4, 0xca,
0x43, 0x14, 0xe8, 0x63, 0xf4, 0xa5, 0xf2, 0x20, 0xbd, 0x2a, 0xf6, 0x40, 0x4a, 0xb4, 0xad, 0xa0,
0xbd, 0xe2, 0xce, 0x37, 0xdf, 0x0c, 0xe7, 0xb4, 0xb3, 0xd0, 0x08, 0xde, 0xd2, 0xc8, 0x23, 0xcb,
0x4e, 0x18, 0x05, 0x3c, 0x40, 0x65, 0x2d, 0xb6, 0xee, 0xce, 0x82, 0x60, 0xe6, 0xd1, 0x07, 0x12,
0x9e, 0xc4, 0xaf, 0x1f, 0x38, 0x71, 0x44, 0xb8, 0x1b, 0xf8, 0x8a, 0x68, 0x7f, 0x09, 0x8d, 0x41,
0x10, 0xcc, 0xe3, 0x10, 0xd3, 0xdf, 0x63, 0xca, 0x38, 0xba, 0x03, 0x25, 0x3f, 0x70, 0xe8, 0x49,
0xaf, 0x69, 0xb4, 0x8d, 0xbd, 0x2a, 0xd6, 0x92, 0xbd, 0x0f, 0x66, 0x42, 0x64, 0x61, 0xe0, 0x33,
0x8a, 0x76, 0xa0, 0x20, 0x74, 0x92, 0x57, 0xeb, 0x36, 0x3a, 0x49, 0x04, 0xa7, 0x81, 0x43, 0xb1,
0x54, 0xd9, 0x67, 0x2b, 0x23, 0xe9, 0x9d, 0xa1, 0x27, 0x60, 0x7a, 0x12, 0x19, 0x47, 0x0a, 0x6a,
0x1a, 0xed, 0xfc, 0x5e, 0xad, 0x7b, 0x27, 0x35, 0xcf, 0x18, 0xe0, 0x86, 0xb7, 0x2e, 0xda, 0x43,
0xb8, 0x91, 0x8d, 0x82, 0xa1, 0x1f, 0xe1, 0x46, 0xea, 0x51, 0x61, 0xda, 0xe5, 0xf6, 0x15, 0x97,
0x4a, 0x8d, 0x4d, 0x2f, 0x23, 0xdb, 0x4f, 0xa1, 0xf9, 0xcc, 0xf5, 0x9d, 0x21, 0x0f, 0x22, 0x32,
0xa3, 0x22, 0x7c, 0x96, 0x26, 0xf9, 0x39, 0x14, 0x45, 0x26, 0x4c, 0xfb, 0xbc, 0x94, 0xa5, 0xd2,
0xd9, 0x1f, 0x0c, 0xd8, 0xbe, 0xea, 0x41, 0xd5, 0xf3, 0x33, 0xa8, 0x05, 0x93, 0xdf, 0xe8, 0x94,
0x8f, 0x99, 0xfb, 0x5e, 0x15, 0x2b, 0x8f, 0x41, 0x41, 0x43, 0xf7, 0x3d, 0x45, 0x87, 0x70, 0x63,
0x1a, 0xf8, 0x3c, 0x22, 0x53, 0x3e, 0xf6, 0xa8, 0x3f, 0xe3, 0x6f, 0x9a, 0x39, 0x59, 0xd1, 0xff,
0x75, 0x54, 0xef, 0x3a, 0x49, 0xef, 0x3a, 0x3d, 0xdd, 0x3b, 0x6c, 0x26, 0x16, 0x03, 0x69, 0x80,
0xbe, 0x86, 0x42, 0x10, 0x72, 0xd6, 0xcc, 0x4b, 0xc3, 0x55, 0xe2, 0x67, 0xea, 0x7b, 0x16, 0x0a,
0x2b, 0x86, 0x25, 0x09, 0xdd, 0x82, 0x22, 0xe3, 0x24, 0xe2, 0xcd, 0x42, 0xdb, 0xd8, 0xab, 0x63,
0x25, 0xa0, 0xff, 0x43, 0x75, 0x41, 0x2e, 0xc6, 0x2a, 0xd9, 0xa2, 0x8c, 0xb2, 0xb2, 0x20, 0x17,
0x32, 0x17, 0xfb, 0x57, 0xa8, 0x89, 0xc3, 0x81, 0xe3, 0x44, 0x94, 0x31, 0xf4, 0x10, 0xaa, 0x3c,
0x22, 0x3e, 0x0b, 0x83, 0x88, 0xcb, 0x8c, 0xcc, 0xb5, 0xfe, 0x09, 0xe2, 0x28, 0xd1, 0xe2, 0x15,
0x11, 0x35, 0xa1, 0x4c, 0x94, 0x03, 0x99, 0x60, 0x15, 0x27, 0xa2, 0xfd, 0x57, 0x0e, 0xcc, 0x6c,
0xa8, 0xe8, 0x7b, 0xa8, 0x89, 0x70, 0x3c, 0xc2, 0xa9, 0x3f, 0x5d, 0xea, 0x19, 0xfb, 0x48, 0x45,
0x60, 0x41, 0x2e, 0x06, 0x8a, 0x8c, 0xbe, 0x03, 0x73, 0xe1, 0xfa, 0xe3, 0x88, 0x86, 0x31, 0x97,
0x5a, 0x5d, 0x50, 0x2b, 0xdb, 0x3c, 0x1a, 0xe2, 0xc6, 0xc2, 0xf5, 0x71, 0x4a, 0x43, 0x5f, 0x28,
0x43, 0x16, 0x52, 0xea, 0x8c, 0xe7, 0x93, 0x50, 0x15, 0x34, 0x8f, 0xeb, 0x0b, 0xd7, 0x1f, 0x0a,
0xf0, 0xf9, 0x24, 0x64, 0xe2, 0x86, 0x90, 0x45, 0x10, 0xfb, 0xaa, 0x80, 0x79, 0xac, 0x25, 0xf4,
0x04, 0xea, 0x11, 0x65, 0x3c, 0x72, 0xa7, 0x32, 0x05, 0x59, 0x44, 0x11, 0x73, 0xf6, 0xa7, 0x2b,
0x02, 0xce, 0xd0, 0xd1, 0x2e, 0x98, 0xf4, 0x62, 0xea, 0xc5, 0x0e, 0x75, 0x74, 0x17, 0x4a, 0xed,
0xfc, 0x5e, 0x15, 0x37, 0x12, 0x54, 0xb5, 0x62, 0x09, 0x65, 0x1d, 0x3d, 0x6a, 0x43, 0x2d, 0x0e,
0xb9, 0xbb, 0xa0, 0x58, 0x84, 0x2f, 0x6b, 0x64, 0xe0, 0x75, 0x08, 0xdd, 0x87, 0x9b, 0x24, 0x76,
0x5c, 0x3e, 0x8c, 0xa7, 0x53, 0xca, 0x98, 0xe2, 0xe5, 0x24, 0xef, 0xaa, 0x02, 0xdd, 0x05, 0x90,
0xe0, 0x91, 0x4c, 0x4e, 0xa5, 0xbe, 0x86, 0xd8, 0x3f, 0x83, 0x75, 0x39, 0x07, 0x11, 0xf5, 0xeb,
0x88, 0xd2, 0xf1, 0x84, 0xf8, 0xce, 0x3b, 0xd7, 0xe1, 0x6f, 0xf4, 0x84, 0x37, 0x04, 0x7a, 0x98,
0x80, 0x62, 0xba, 0x24, 0xcd, 0x71, 0xd9, 0x5c, 0x06, 0x90, 0xc7, 0x15, 0x01, 0xf4, 0x5c, 0x36,
0xb7, 0xff, 0xcc, 0x41, 0x41, 0x38, 0x46, 0x26, 0xe4, 0x5c, 0x47, 0xef, 0x9d, 0x9c, 0xeb, 0xa0,
0x4e, 0x76, 0x62, 0x6a, 0xdd, 0x5b, 0x99, 0x62, 0xea, 0x71, 0x4c, 0xe7, 0x08, 0xed, 0x42, 0x81,
0x2f, 0x43, 0x2a, 0x43, 0x37, 0xbb, 0x37, 0xb3, 0x23, 0xb9, 0x0c, 0x29, 0x96, 0xea, 0x2b, 0x8d,
0x2a, 0xfc, 0xb7, 0x46, 0x7d, 0x0b, 0x95, 0x05, 0xe5, 0xc4, 0x21, 0x9c, 0xe8, 0x1e, 0xdf, 0xce,
0x98, 0xbe, 0xd0, 0x4a, 0x9c, 0xd2, 0xd0, 0x37, 0x00, 0x6b, 0xd3, 0x58, 0xda, 0x30, 0x8d, 0x6b,
0x1c, 0xfb, 0x07, 0xa8, 0xaf, 0xfb, 0x12, 0x97, 0x96, 0x2e, 0x88, 0xeb, 0xe9, 0xea, 0x28, 0x41,
0x8c, 0xe2, 0x3b, 0xe2, 0x79, 0x94, 0xeb, 0x1b, 0xa5, 0x25, 0xfb, 0x0f, 0x03, 0xea, 0x2f, 0x63,
0x1a, 0x2d, 0x93, 0x2d, 0xb4, 0x0b, 0x25, 0x46, 0x7d, 0x87, 0x46, 0xd7, 0x6f, 0x6b, 0xad, 0x14,
0x34, 0x4e, 0xa2, 0x99, 0xf6, 0x77, 0x95, 0xa6, 0x94, 0x22, 0x18, 0xcf, 0x5d, 0xb8, 0xc9, 0x8c,
0x28, 0x01, 0xb5, 0xa0, 0x12, 0xba, 0xfe, 0x6c, 0x42, 0xa6, 0x73, 0x59, 0xd2, 0x0a, 0x4e, 0x65,
0x9b, 0x40, 0x43, 0xc7, 0xa3, 0xf7, 0xea, 0xbf, 0x0c, 0xe8, 0x2b, 0xa8, 0xa4, 0x5b, 0x3d, 0x77,
0xdd, 0x06, 0x4e, 0xd5, 0x76, 0x03, 0x6a, 0xe7, 0xae, 0x3f, 0x4b, 0x5e, 0x0a, 0x13, 0xea, 0x4a,
0xd4, 0xea, 0xbf, 0x0d, 0xa8, 0xad, 0x35, 0x15, 0x3d, 0x86, 0x4a, 0x10, 0xd2, 0x88, 0xf0, 0x20,
0xd2, 0x2b, 0xec, 0xd3, 0xd4, 0xf3, 0x1a, 0xaf, 0x73, 0xa6, 0x49, 0x38, 0xa5, 0xa3, 0x47, 0x50,
0x96, 0x67, 0xdf, 0x91, 0x65, 0x32, 0xbb, 0x9f, 0x6c, 0xb6, 0xf4, 0x1d, 0x9c, 0x90, 0x45, 0xd9,
0xde, 0x12, 0x2f, 0xa6, 0x49, 0xd9, 0xa4, 0x60, 0x3f, 0x84, 0x4a, 0xf2, 0x0f, 0x54, 0x82, 0xdc,
0x60, 0x64, 0x6d, 0x89, 0x6f, 0xff, 0xa5, 0x65, 0x88, 0xef, 0xf1, 0xc8, 0xca, 0xa1, 0x32, 0xe4,
0x07, 0xa3, 0xbe, 0x95, 0x17, 0x87, 0xe3, 0x51, 0xdf, 0x2a, 0xd8, 0xf7, 0xa1, 0xac, 0xfd, 0x23,
0x04, 0xe6, 0x33, 0xdc, 0xef, 0x8f, 0x0f, 0x0f, 0x4e, 0x7b, 0xaf, 0x4e, 0x7a, 0xa3, 0x9f, 0xac,
0x2d, 0xd4, 0x80, 0xaa, 0xc4, 0x7a, 0x27, 0xc3, 0xe7, 0x96, 0x71, 0x6f, 0x07, 0x1a, 0x99, 0xb5,
0x8c, 0x2c, 0xa8, 0x8f, 0x8e, 0xce, 0xc7, 0xa3, 0xc1, 0x70, 0x7c, 0x8c, 0xcf, 0x8f, 0xac, 0xad,
0x7b, 0x36, 0x54, 0x92, 0x6b, 0x82, 0xaa, 0x50, 0x3c, 0xe8, 0xbd, 0x38, 0x39, 0xb5, 0xb6, 0x50,
0x0d, 0xca, 0xc3, 0xd1, 0x19, 0x3e, 0x38, 0xee, 0x5b, 0x46, 0xf7, 0x83, 0x01, 0x65, 0xbd, 0xa7,
0xd1, 0x63, 0x28, 0xa9, 0x67, 0x15, 0x6d, 0x78, 0xba, 0x5b, 0x9b, 0xde, 0x5f, 0xf4, 0x14, 0xe0,
0x30, 0xf6, 0xe6, 0xda, 0x7c, 0xfb, 0x7a, 0x73, 0xd6, 0x6a, 0x6e, 0xb0, 0x67, 0xe8, 0x15, 0x58,
0x97, 0x9f, 0x5b, 0xd4, 0x4e, 0xd9, 0x1b, 0x5e, 0xe2, 0xd6, 0xce, 0x47, 0x18, 0xca, 0x73, 0x97,
0x43, 0x51, 0x79, 0x7b, 0x04, 0x45, 0x39, 0xaf, 0x68, 0x75, 0xb5, 0xd7, 0xef, 0x53, 0xeb, 0xce,
0x65, 0x58, 0xa7, 0xb6, 0x0f, 0x05, 0x31, 0x75, 0x68, 0xb5, 0xa8, 0xd6, 0x66, 0xb2, 0x75, 0xfb,
0x12, 0xaa, 0x8c, 0x0e, 0x0b, 0xbf, 0xe4, 0xc2, 0xc9, 0xa4, 0x24, 0x1f, 0xb5, 0xfd, 0x7f, 0x02,
0x00, 0x00, 0xff, 0xff, 0x5e, 0xda, 0x93, 0x25, 0xca, 0x09, 0x00, 0x00,
}

View File

@ -81,9 +81,9 @@ message OverlayOptions {
// NodeRep is the reputation characteristics of a node
message NodeRep {
float uptime_ratio = 1;
float audit_success_ratio = 2;
int64 audit_count = 3;
double uptimeRatio = 1;
double auditSuccessRatio = 2;
int64 auditCount = 3;
}
// NodeRestrictions contains all relevant data about a nodes ability to store data
@ -99,6 +99,7 @@ message Node {
NodeType type = 3;
NodeRestrictions restrictions = 4;
NodeMetadata metadata = 5;
NodeRep reputation = 6;
}
// NodeType is an enum of possible node types