1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-08 05:57:03 +09:00

commonfile

This commit is contained in:
Sergey Cherepanov 2022-12-12 20:49:43 +03:00 committed by Mikhail Iudin
parent a894f42e05
commit 5d3e79e506
No known key found for this signature in database
GPG key ID: FAAAA8BAABDFF1C0
37 changed files with 4320 additions and 95 deletions

View file

@ -17,6 +17,8 @@ proto:
$(GOGO_START) protoc --gogofaster_out=:. $(P_TEST_CHANGES_PATH_PB)/proto/*.proto
$(eval PKGMAP := $$(P_TREE_CHANGES),$$(P_ACL_RECORDS))
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. commonspace/spacesyncproto/protos/*.proto
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. commonfile/fileproto/protos/*.proto
test:
go test ./... --cover

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,268 @@
// Code generated by protoc-gen-go-drpc. DO NOT EDIT.
// protoc-gen-go-drpc version: v0.0.32
// source: commonfile/fileproto/protos/file.proto
package fileproto
import (
bytes "bytes"
context "context"
errors "errors"
jsonpb "github.com/gogo/protobuf/jsonpb"
proto "github.com/gogo/protobuf/proto"
drpc "storj.io/drpc"
drpcerr "storj.io/drpc/drpcerr"
)
type drpcEncoding_File_commonfile_fileproto_protos_file_proto struct{}
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) Marshal(msg drpc.Message) ([]byte, error) {
return proto.Marshal(msg.(proto.Message))
}
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) Unmarshal(buf []byte, msg drpc.Message) error {
return proto.Unmarshal(buf, msg.(proto.Message))
}
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) JSONMarshal(msg drpc.Message) ([]byte, error) {
var buf bytes.Buffer
err := new(jsonpb.Marshaler).Marshal(&buf, msg.(proto.Message))
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) JSONUnmarshal(buf []byte, msg drpc.Message) error {
return jsonpb.Unmarshal(bytes.NewReader(buf), msg.(proto.Message))
}
type DRPCFileClient interface {
DRPCConn() drpc.Conn
GetBlocks(ctx context.Context) (DRPCFile_GetBlocksClient, error)
PushBlock(ctx context.Context, in *PushBlockRequest) (*PushBlockResponse, error)
DeleteBlocks(ctx context.Context, in *DeleteBlocksRequest) (*DeleteBlocksResponse, error)
Check(ctx context.Context, in *CheckRequest) (*CheckResponse, error)
}
type drpcFileClient struct {
cc drpc.Conn
}
func NewDRPCFileClient(cc drpc.Conn) DRPCFileClient {
return &drpcFileClient{cc}
}
func (c *drpcFileClient) DRPCConn() drpc.Conn { return c.cc }
func (c *drpcFileClient) GetBlocks(ctx context.Context) (DRPCFile_GetBlocksClient, error) {
stream, err := c.cc.NewStream(ctx, "/anySpace.File/GetBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
if err != nil {
return nil, err
}
x := &drpcFile_GetBlocksClient{stream}
return x, nil
}
type DRPCFile_GetBlocksClient interface {
drpc.Stream
Send(*GetBlockRequest) error
Recv() (*GetBlockResponse, error)
}
type drpcFile_GetBlocksClient struct {
drpc.Stream
}
func (x *drpcFile_GetBlocksClient) Send(m *GetBlockRequest) error {
return x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
}
func (x *drpcFile_GetBlocksClient) Recv() (*GetBlockResponse, error) {
m := new(GetBlockResponse)
if err := x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
return nil, err
}
return m, nil
}
func (x *drpcFile_GetBlocksClient) RecvMsg(m *GetBlockResponse) error {
return x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
}
func (c *drpcFileClient) PushBlock(ctx context.Context, in *PushBlockRequest) (*PushBlockResponse, error) {
out := new(PushBlockResponse)
err := c.cc.Invoke(ctx, "/anySpace.File/PushBlock", drpcEncoding_File_commonfile_fileproto_protos_file_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
func (c *drpcFileClient) DeleteBlocks(ctx context.Context, in *DeleteBlocksRequest) (*DeleteBlocksResponse, error) {
out := new(DeleteBlocksResponse)
err := c.cc.Invoke(ctx, "/anySpace.File/DeleteBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
func (c *drpcFileClient) Check(ctx context.Context, in *CheckRequest) (*CheckResponse, error) {
out := new(CheckResponse)
err := c.cc.Invoke(ctx, "/anySpace.File/Check", drpcEncoding_File_commonfile_fileproto_protos_file_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
type DRPCFileServer interface {
GetBlocks(DRPCFile_GetBlocksStream) error
PushBlock(context.Context, *PushBlockRequest) (*PushBlockResponse, error)
DeleteBlocks(context.Context, *DeleteBlocksRequest) (*DeleteBlocksResponse, error)
Check(context.Context, *CheckRequest) (*CheckResponse, error)
}
type DRPCFileUnimplementedServer struct{}
func (s *DRPCFileUnimplementedServer) GetBlocks(DRPCFile_GetBlocksStream) error {
return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
func (s *DRPCFileUnimplementedServer) PushBlock(context.Context, *PushBlockRequest) (*PushBlockResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
func (s *DRPCFileUnimplementedServer) DeleteBlocks(context.Context, *DeleteBlocksRequest) (*DeleteBlocksResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
func (s *DRPCFileUnimplementedServer) Check(context.Context, *CheckRequest) (*CheckResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
type DRPCFileDescription struct{}
func (DRPCFileDescription) NumMethods() int { return 4 }
func (DRPCFileDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
case 0:
return "/anySpace.File/GetBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return nil, srv.(DRPCFileServer).
GetBlocks(
&drpcFile_GetBlocksStream{in1.(drpc.Stream)},
)
}, DRPCFileServer.GetBlocks, true
case 1:
return "/anySpace.File/PushBlock", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCFileServer).
PushBlock(
ctx,
in1.(*PushBlockRequest),
)
}, DRPCFileServer.PushBlock, true
case 2:
return "/anySpace.File/DeleteBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCFileServer).
DeleteBlocks(
ctx,
in1.(*DeleteBlocksRequest),
)
}, DRPCFileServer.DeleteBlocks, true
case 3:
return "/anySpace.File/Check", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCFileServer).
Check(
ctx,
in1.(*CheckRequest),
)
}, DRPCFileServer.Check, true
default:
return "", nil, nil, nil, false
}
}
func DRPCRegisterFile(mux drpc.Mux, impl DRPCFileServer) error {
return mux.Register(impl, DRPCFileDescription{})
}
type DRPCFile_GetBlocksStream interface {
drpc.Stream
Send(*GetBlockResponse) error
Recv() (*GetBlockRequest, error)
}
type drpcFile_GetBlocksStream struct {
drpc.Stream
}
func (x *drpcFile_GetBlocksStream) Send(m *GetBlockResponse) error {
return x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
}
func (x *drpcFile_GetBlocksStream) Recv() (*GetBlockRequest, error) {
m := new(GetBlockRequest)
if err := x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
return nil, err
}
return m, nil
}
func (x *drpcFile_GetBlocksStream) RecvMsg(m *GetBlockRequest) error {
return x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
}
type DRPCFile_PushBlockStream interface {
drpc.Stream
SendAndClose(*PushBlockResponse) error
}
type drpcFile_PushBlockStream struct {
drpc.Stream
}
func (x *drpcFile_PushBlockStream) SendAndClose(m *PushBlockResponse) error {
if err := x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
return err
}
return x.CloseSend()
}
type DRPCFile_DeleteBlocksStream interface {
drpc.Stream
SendAndClose(*DeleteBlocksResponse) error
}
type drpcFile_DeleteBlocksStream struct {
drpc.Stream
}
func (x *drpcFile_DeleteBlocksStream) SendAndClose(m *DeleteBlocksResponse) error {
if err := x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
return err
}
return x.CloseSend()
}
type DRPCFile_CheckStream interface {
drpc.Stream
SendAndClose(*CheckResponse) error
}
type drpcFile_CheckStream struct {
drpc.Stream
}
func (x *drpcFile_CheckStream) SendAndClose(m *CheckResponse) error {
if err := x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
return err
}
return x.CloseSend()
}

View file

@ -0,0 +1,60 @@
syntax = "proto3";
package anySpace;
option go_package = "commonfile/fileproto";
enum ErrCodes {
Unexpected = 0;
CIDNotFound = 1;
ErrorOffset = 200;
}
service File {
// GetBlocks streams ipfs blocks from server to client
rpc GetBlocks(stream GetBlockRequest) returns (stream GetBlockResponse);
// PushBlock pushes one block to server
rpc PushBlock(PushBlockRequest) returns (PushBlockResponse);
// DeleteBlock deletes block from space
rpc DeleteBlocks(DeleteBlocksRequest) returns (DeleteBlocksResponse);
// Ping checks the connection
rpc Check(CheckRequest) returns (CheckResponse);
}
message GetBlockRequest {
string spaceId = 1;
bytes cid = 2;
}
message GetBlockResponse {
bytes cid = 1;
bytes data = 2;
CIDError code = 3;
}
message PushBlockRequest {
string spaceId = 1;
bytes cid = 2;
bytes data = 3;
}
message PushBlockResponse {}
message DeleteBlocksRequest {
string spaceId = 1;
repeated bytes cid = 2;
}
message DeleteBlocksResponse {}
message CheckRequest {}
message CheckResponse {
repeated string spaceIds = 1;
}
enum CIDError {
CIDErrorOk = 0;
CIDErrorNotFound = 1;
CIDErrorUnexpected = 2;
}

View file

@ -8,8 +8,13 @@ import (
"go.uber.org/zap"
)
type IPFSStoreExistsCIDs interface {
IPFSStore
ExistsCids(ctx context.Context, ks []cid.Cid) (exists []cid.Cid, err error)
}
type CacheStore struct {
Cache IPFSStore
Cache IPFSStoreExistsCIDs
Origin IPFSStore
}
@ -90,10 +95,6 @@ func (c *CacheStore) GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Bl
return results
}
func (c *CacheStore) ExistsCids(ctx context.Context, ks []cid.Cid) (exists []cid.Cid, err error) {
return c.Cache.ExistsCids(ctx, ks)
}
func (c *CacheStore) Add(ctx context.Context, b []blocks.Block) error {
if localErr := c.Cache.Add(ctx, b); localErr != nil {
log.Error("cache add error", zap.Error(localErr))

View file

@ -12,7 +12,6 @@ var log = logger.NewNamed("filenode.ipfsstore")
type IPFSStore interface {
Get(ctx context.Context, k cid.Cid) (blocks.Block, error)
GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Block
ExistsCids(ctx context.Context, ks []cid.Cid) (exists []cid.Cid, err error)
Add(ctx context.Context, b []blocks.Block) error
Delete(ctx context.Context, c cid.Cid) error
Close() (err error)

View file

@ -0,0 +1,275 @@
package rpcstore
import (
"context"
"errors"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/fileproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
"github.com/cheggaaa/mb/v3"
"github.com/ipfs/go-cid"
"go.uber.org/zap"
"sync"
"time"
)
var (
ErrCIDNotFound = errors.New("CID not found")
ErrCIDUnexpected = errors.New("CID unexpected error")
ErrClientClosed = errors.New("file client closed")
)
const defaultMaxInFlightCIDs = 10
func newClient(ctx context.Context, s *service, peerId string, tq *mb.MB[*task]) (*client, error) {
c := &client{
peerId: peerId,
taskQueue: tq,
waitCIDs: map[string]*task{},
waitCIDCap: make(chan struct{}, defaultMaxInFlightCIDs),
opLoopDone: make(chan struct{}),
stat: newStat(),
s: s,
}
if err := c.checkConnectivity(ctx); err != nil {
return nil, err
}
var runCtx context.Context
runCtx, c.opLoopCtxCancel = context.WithCancel(context.Background())
go c.opLoop(runCtx)
return c, nil
}
// client gets and executes tasks from taskQueue
// it has an internal queue for a waiting CIDs
type client struct {
peerId string
spaceIds []string
taskQueue *mb.MB[*task]
blocksStream fileproto.DRPCFile_GetBlocksClient
blocksStreamMu sync.Mutex
waitCIDs map[string]*task
waitCIDCap chan struct{}
waitCIDMu sync.Mutex
opLoopDone chan struct{}
opLoopCtxCancel context.CancelFunc
stat *stat
s *service
}
// opLoop gets tasks from taskQueue
func (c *client) opLoop(ctx context.Context) {
defer close(c.opLoopDone)
c.waitCIDMu.Lock()
spaceIds := c.spaceIds
c.waitCIDMu.Unlock()
cond := c.taskQueue.NewCond().WithFilter(func(t *task) bool {
if slice.FindPos(t.denyPeerIds, c.peerId) != -1 {
return false
}
if len(spaceIds) > 0 && slice.FindPos(spaceIds, t.spaceId) == -1 {
return false
}
return true
})
for {
t, err := cond.WithPriority(c.stat.Score()).WaitOne(ctx)
if err != nil {
return
}
t.peerId = c.peerId
switch t.op {
case taskOpGet:
err = c.get(ctx, t)
case taskOpDelete:
err = c.delete(ctx, t)
case taskOpPut:
err = c.put(ctx, t)
default:
err = fmt.Errorf("unexpected task op type: %v", t.op)
}
if err != nil {
t.err = err
t.ready <- t
}
}
}
func (c *client) delete(ctx context.Context, t *task) (err error) {
p, err := c.s.pool.Get(ctx, c.peerId)
if err != nil {
return
}
if _, err = fileproto.NewDRPCFileClient(p).DeleteBlocks(ctx, &fileproto.DeleteBlocksRequest{
SpaceId: t.spaceId,
Cid: [][]byte{t.cid.Bytes()},
}); err != nil {
return
}
t.ready <- t
c.stat.UpdateLastUsage()
return
}
func (c *client) put(ctx context.Context, t *task) (err error) {
p, err := c.s.pool.Get(ctx, c.peerId)
if err != nil {
return
}
st := time.Now()
if _, err = fileproto.NewDRPCFileClient(p).PushBlock(ctx, &fileproto.PushBlockRequest{
SpaceId: t.spaceId,
Cid: t.cid.Bytes(),
Data: t.data,
}); err != nil {
return
}
t.ready <- t
c.stat.Add(st, len(t.data))
return
}
// get sends the get request to the stream and adds task to waiting list
func (c *client) get(ctx context.Context, t *task) (err error) {
select {
case <-ctx.Done():
return ctx.Err()
case c.waitCIDCap <- struct{}{}:
}
c.waitCIDMu.Lock()
t.startTime = time.Now()
c.waitCIDs[t.cid.String()] = t
c.waitCIDMu.Unlock()
defer func() {
if err != nil {
c.waitCIDMu.Lock()
delete(c.waitCIDs, t.cid.String())
c.waitCIDMu.Unlock()
<-c.waitCIDCap
}
}()
bs, err := c.getStream(ctx)
if err != nil {
return
}
if err = bs.Send(&fileproto.GetBlockRequest{
SpaceId: t.spaceId,
Cid: t.cid.Bytes(),
}); err != nil {
return
}
return
}
func (c *client) readStream() {
var err error
defer func() {
log.Info("readStream closed", zap.String("peerId", c.peerId), zap.Error(err))
c.waitCIDMu.Lock()
c.blocksStream = nil
c.waitCIDMu.Unlock()
}()
for {
var resp *fileproto.GetBlockResponse
resp, err = c.blocksStream.Recv()
if err != nil {
return
}
var t *task
t, err = c.receiveCID(resp)
if err != nil {
log.Warn("cid receive error", zap.Error(err))
} else {
t.ready <- t
}
}
}
// receiveCID handles stream response, finds cid in waiting list and sets data to task
func (c *client) receiveCID(resp *fileproto.GetBlockResponse) (t *task, err error) {
_, rCid, err := cid.CidFromBytes(resp.Cid)
if err != nil {
return nil, fmt.Errorf("got invalid CID from node: %v", err)
}
c.waitCIDMu.Lock()
defer c.waitCIDMu.Unlock()
t, ok := c.waitCIDs[rCid.String()]
if !ok {
return nil, fmt.Errorf("got unexpected CID from node: %v", rCid.String())
}
switch resp.Code {
case fileproto.CIDError_CIDErrorOk:
t.data = resp.Data
t.err = nil
case fileproto.CIDError_CIDErrorNotFound:
t.err = ErrCIDNotFound
default:
t.err = ErrCIDUnexpected
}
delete(c.waitCIDs, rCid.String())
if t.err == nil {
c.stat.Add(t.startTime, len(t.data))
}
<-c.waitCIDCap
return
}
func (c *client) getStream(ctx context.Context) (fileproto.DRPCFile_GetBlocksClient, error) {
c.blocksStreamMu.Lock()
defer c.blocksStreamMu.Unlock()
if c.blocksStream != nil {
return c.blocksStream, nil
}
peer, err := c.s.pool.Dial(ctx, c.peerId)
if err != nil {
return nil, err
}
if c.blocksStream, err = fileproto.NewDRPCFileClient(peer).GetBlocks(context.Background()); err != nil {
return nil, err
}
go c.readStream()
return c.blocksStream, nil
}
func (c *client) checkConnectivity(ctx context.Context) (err error) {
p, err := c.s.pool.Get(ctx, c.peerId)
if err != nil {
return
}
resp, err := fileproto.NewDRPCFileClient(p).Check(ctx, &fileproto.CheckRequest{})
if err != nil {
return
}
c.waitCIDMu.Lock()
defer c.waitCIDMu.Unlock()
c.spaceIds = resp.SpaceIds
return
}
func (c *client) LastUsage() time.Time {
return c.stat.LastUsage()
}
func (c *client) Close() error {
// stop receiving tasks
c.opLoopCtxCancel()
<-c.opLoopDone
c.blocksStreamMu.Lock()
// close stream
if c.blocksStream != nil {
_ = c.blocksStream.CloseSend()
c.blocksStream = nil
}
c.blocksStreamMu.Unlock()
// cleanup waiting list
c.waitCIDMu.Lock()
for id, t := range c.waitCIDs {
t.err = ErrClientClosed
t.ready <- t
delete(c.waitCIDs, id)
}
c.waitCIDMu.Unlock()
return nil
}

View file

@ -0,0 +1,110 @@
package rpcstore
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
"github.com/cheggaaa/mb/v3"
"go.uber.org/zap"
"math/rand"
"sync"
"time"
)
const (
maxConnections = 10
maxTasks = 1000
)
var (
clientCreateTimeout = time.Second * 10
)
func newClientManager(s *service) *clientManager {
cm := &clientManager{
mb: mb.New[*task](maxTasks),
ocache: ocache.New(
func(ctx context.Context, id string) (value ocache.Object, err error) {
return nil, fmt.Errorf("load func shouldn't be used")
},
ocache.WithTTL(time.Minute*5),
ocache.WithRefCounter(false),
ocache.WithLogger(log.Sugar()),
ocache.WithGCPeriod(0),
),
s: s,
}
cm.ctx, cm.ctxCancel = context.WithCancel(context.Background())
go cm.checkPeerLoop()
return cm
}
// clientManager manages clients, removes unused ones, and adds new ones if necessary
type clientManager struct {
mb *mb.MB[*task]
ctx context.Context
ctxCancel context.CancelFunc
ocache ocache.OCache
s *service
mu sync.RWMutex
}
func (m *clientManager) Add(ctx context.Context, ts ...*task) (err error) {
return m.mb.Add(ctx, ts...)
}
func (m *clientManager) checkPeerLoop() {
m.checkPeers()
ticker := time.NewTicker(time.Minute)
defer ticker.Stop()
for {
select {
case <-m.ctx.Done():
return
case <-ticker.C:
m.checkPeers()
}
}
}
func (m *clientManager) checkPeers() {
// start GC to remove unused clients
m.ocache.GC()
if m.ocache.Len() >= maxConnections {
// reached connection limit, can't add new peers
return
}
if m.ocache.Len() != 0 && m.mb.Len() == 0 {
// has empty queue, no need new peers
return
}
// try to add new peers
peerIds := m.s.filePeers()
rand.Shuffle(len(peerIds), func(i, j int) {
peerIds[i], peerIds[j] = peerIds[j], peerIds[i]
})
for _, peerId := range peerIds {
if _, cerr := m.ocache.Pick(m.ctx, peerId); cerr == ocache.ErrNotExists {
ctx, cancel := context.WithTimeout(m.ctx, clientCreateTimeout)
cl, err := newClient(ctx, m.s, peerId, m.mb)
if err != nil {
log.Info("can't create client", zap.Error(err))
cancel()
continue
}
_ = m.ocache.Add(peerId, cl)
cancel()
return
}
}
}
func (m *clientManager) Close() (err error) {
m.ctxCancel()
if err = m.mb.Close(); err != nil {
log.Error("mb close error", zap.Error(err))
}
return m.ocache.Close()
}

View file

@ -0,0 +1,49 @@
package rpcstore
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/ipfsstore"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
)
const CName = "common.commonfile.rpcstore"
var log = logger.NewNamed(CName)
func New() Service {
return &service{}
}
type Service interface {
NewStore() ipfsstore.IPFSStore
app.Component
}
type service struct {
pool pool.Pool
nodeconf nodeconf.Service
}
func (s *service) Init(a *app.App) (err error) {
s.pool = a.MustComponent(pool.CName).(pool.Pool)
s.nodeconf = a.MustComponent(nodeconf.CName).(nodeconf.Service)
return
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) NewStore() ipfsstore.IPFSStore {
cm := newClientManager(s)
return &store{
s: s,
cm: cm,
}
}
func (s *service) filePeers() []string {
return s.nodeconf.GetLast().FilePeers()
}

View file

@ -0,0 +1,55 @@
package rpcstore
import (
"github.com/VividCortex/ewma"
"sync"
"time"
)
// defaultSpeedScore - initial value in Kb/s, it should be relatively high to test fresh client soon
const defaultSpeedScore = 10 * 1024
func newStat() *stat {
s := &stat{
ewma: &ewma.SimpleEWMA{},
lastUsage: time.Now(),
}
s.ewma.Set(float64(defaultSpeedScore))
return s
}
// stat calculates EWMA download/upload speed
type stat struct {
// TODO: rewrite to atomics
ewma *ewma.SimpleEWMA
mu sync.Mutex
lastUsage time.Time
}
// Score returns average download/upload speed in Kb/s
func (s *stat) Score() float64 {
s.mu.Lock()
defer s.mu.Unlock()
return s.ewma.Value()
}
// Add adds new sample to the stat
func (s *stat) Add(startTime time.Time, byteLen int) {
s.mu.Lock()
defer s.mu.Unlock()
dur := time.Since(startTime).Seconds()
s.ewma.Add(float64(byteLen) / 1024 / dur)
s.lastUsage = time.Now()
}
func (s *stat) LastUsage() time.Time {
s.mu.Lock()
defer s.mu.Unlock()
return s.lastUsage
}
func (s *stat) UpdateLastUsage() {
s.mu.Lock()
defer s.mu.Unlock()
s.lastUsage = time.Now()
}

View file

@ -0,0 +1,99 @@
package rpcstore
import (
"context"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"go.uber.org/multierr"
"go.uber.org/zap"
"sync"
)
var closedBlockChan chan blocks.Block
func init() {
closedBlockChan = make(chan blocks.Block)
close(closedBlockChan)
}
type store struct {
s *service
cm *clientManager
mu sync.RWMutex
}
func (s *store) Get(ctx context.Context, k cid.Cid) (b blocks.Block, err error) {
t := newTask(ctx, taskOpGet, k, nil)
if err = s.cm.Add(ctx, t); err != nil {
return
}
<-t.ready
if err = t.Validate(); err != nil {
return
}
return t.Block()
}
func (s *store) GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
var readyCh = make(chan *task)
var tasks = make([]*task, len(ks))
for i, k := range ks {
tasks[i] = newTask(ctx, taskOpGet, k, readyCh)
}
if err := s.cm.Add(ctx, tasks...); err != nil {
log.Error("getMany: can't add tasks", zap.Error(err))
return closedBlockChan
}
var result = make(chan blocks.Block)
go func() {
defer close(result)
for i := 0; i < len(tasks); i++ {
var t *task
select {
case <-ctx.Done():
return
case t = <-readyCh:
}
if err := t.Validate(); err != nil {
// TODO: fallback
log.Warn("received not valid block", zap.Error(err))
}
b, _ := t.Block()
result <- b
}
}()
return result
}
func (s *store) Add(ctx context.Context, bs []blocks.Block) error {
var readyCh = make(chan *task)
var tasks = make([]*task, len(bs))
for i, b := range bs {
tasks[i] = newTask(ctx, taskOpPut, b.Cid(), readyCh)
tasks[i].data = b.RawData()
}
if err := s.cm.Add(ctx, tasks...); err != nil {
return err
}
var errs []error
for i := 0; i < len(tasks); i++ {
t := <-readyCh
if t.err != nil {
errs = append(errs, t.err)
}
}
return multierr.Combine(errs...)
}
func (s *store) Delete(ctx context.Context, c cid.Cid) error {
t := newTask(ctx, taskOpDelete, c, nil)
if err := s.cm.Add(ctx, t); err != nil {
return err
}
<-t.ready
return t.err
}
func (s *store) Close() (err error) {
return s.cm.Close()
}

View file

@ -0,0 +1,190 @@
package rpcstore
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/fileproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpctest"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sort"
"sync"
"testing"
)
var ctx = context.Background()
func TestStore_Put(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
bs := []blocks.Block{
blocks.NewBlock([]byte{'1'}),
blocks.NewBlock([]byte{'2'}),
blocks.NewBlock([]byte{'3'}),
}
err := fx.Add(ctx, bs)
assert.NoError(t, err)
for _, b := range bs {
assert.NotNil(t, fx.serv.data[string(b.Cid().Bytes())])
}
}
func TestStore_Delete(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
bs := []blocks.Block{
blocks.NewBlock([]byte{'1'}),
}
err := fx.Add(ctx, bs)
require.NoError(t, err)
assert.Len(t, fx.serv.data, 1)
require.NoError(t, fx.Delete(ctx, bs[0].Cid()))
assert.Len(t, fx.serv.data, 0)
}
func TestStore_Get(t *testing.T) {
t.Run("success", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
bs := []blocks.Block{
blocks.NewBlock([]byte{'1'}),
}
err := fx.Add(ctx, bs)
require.NoError(t, err)
b, err := fx.Get(ctx, bs[0].Cid())
require.NoError(t, err)
assert.Equal(t, []byte{'1'}, b.RawData())
})
t.Run("not found", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
bs := []blocks.Block{
blocks.NewBlock([]byte{'1'}),
}
b, err := fx.Get(ctx, bs[0].Cid())
assert.Nil(t, b)
assert.ErrorIs(t, err, ErrCIDNotFound)
})
}
func TestStore_GetMany(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
bs := []blocks.Block{
blocks.NewBlock([]byte{'1'}),
blocks.NewBlock([]byte{'2'}),
blocks.NewBlock([]byte{'3'}),
}
err := fx.Add(ctx, bs)
assert.NoError(t, err)
res := fx.GetMany(ctx, []cid.Cid{
bs[0].Cid(),
bs[1].Cid(),
bs[2].Cid(),
})
var resBlocks []blocks.Block
for b := range res {
resBlocks = append(resBlocks, b)
}
require.Len(t, resBlocks, 3)
sort.Slice(resBlocks, func(i, j int) bool {
return string(resBlocks[i].RawData()) < string(resBlocks[j].RawData())
})
assert.Equal(t, bs, resBlocks)
}
func newFixture(t *testing.T) *fixture {
fx := &fixture{
a: new(app.App),
s: New().(*service),
serv: &testServer{
data: make(map[string][]byte),
},
}
conf := &config.Config{}
for i := 0; i < 11; i++ {
conf.Nodes = append(conf.Nodes, config.Node{
PeerId: fmt.Sprint(i),
Types: []config.NodeType{config.NodeTypeFile},
})
}
rserv := rpctest.NewTestServer()
require.NoError(t, fileproto.DRPCRegisterFile(rserv.Mux, fx.serv))
fx.a.Register(fx.s).
Register(rpctest.NewTestPool().WithServer(rserv)).
Register(nodeconf.New()).
Register(conf)
require.NoError(t, fx.a.Start(ctx))
fx.store = fx.s.NewStore().(*store)
return fx
}
type fixture struct {
*store
s *service
a *app.App
serv *testServer
}
func (fx *fixture) Finish(t *testing.T) {
assert.NoError(t, fx.store.Close())
assert.NoError(t, fx.a.Close(ctx))
}
type testServer struct {
mu sync.Mutex
data map[string][]byte
}
func (t *testServer) GetBlocks(stream fileproto.DRPCFile_GetBlocksStream) error {
for {
req, err := stream.Recv()
if err != nil {
return err
}
t.mu.Lock()
resp := &fileproto.GetBlockResponse{
Cid: req.Cid,
}
if data, ok := t.data[string(req.Cid)]; ok {
resp.Data = data
} else {
resp.Code = fileproto.CIDError_CIDErrorNotFound
}
t.mu.Unlock()
if err = stream.Send(resp); err != nil {
return err
}
}
}
func (t *testServer) PushBlock(ctx context.Context, req *fileproto.PushBlockRequest) (*fileproto.PushBlockResponse, error) {
t.mu.Lock()
defer t.mu.Unlock()
t.data[string(req.Cid)] = req.Data
return &fileproto.PushBlockResponse{}, nil
}
func (t *testServer) DeleteBlocks(ctx context.Context, req *fileproto.DeleteBlocksRequest) (*fileproto.DeleteBlocksResponse, error) {
t.mu.Lock()
defer t.mu.Unlock()
for _, c := range req.Cid {
delete(t.data, string(c))
}
return &fileproto.DeleteBlocksResponse{}, nil
}
func (t *testServer) Check(ctx context.Context, req *fileproto.CheckRequest) (*fileproto.CheckResponse, error) {
return &fileproto.CheckResponse{}, nil
}

View file

@ -0,0 +1,60 @@
package rpcstore
import (
"context"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"time"
)
type taskOp uint
const (
taskOpGet taskOp = iota
taskOpPut
taskOpDelete
)
func newTask(ctx context.Context, op taskOp, c cid.Cid, readyCh chan *task) *task {
t := &task{
cid: c,
ctx: ctx,
ready: readyCh,
op: op,
}
if t.ready == nil {
t.ready = make(chan *task)
}
return t
}
type task struct {
op taskOp
ctx context.Context
cid cid.Cid
data []byte
peerId string
spaceId string
denyPeerIds []string
ready chan *task
startTime time.Time
err error
}
func (t *task) Validate() error {
if t.err != nil {
return t.err
}
chkc, err := t.cid.Prefix().Sum(t.data)
if err != nil {
return err
}
if !chkc.Equals(t.cid) {
return blocks.ErrWrongHash
}
return nil
}
func (t *task) Block() (blocks.Block, error) {
return blocks.NewBlockWithCid(t.data, t.cid)
}

View file

@ -1,9 +1,26 @@
package config
type NodeType string
const (
NodeTypeTree NodeType = "tree"
NodeTypeConsensus NodeType = "consensus"
NodeTypeFile NodeType = "file"
)
type Node struct {
PeerId string `yaml:"peerId"`
Address string `yaml:"address"`
SigningKey string `yaml:"signingKey,omitempty"`
EncryptionKey string `yaml:"encryptionKey,omitempty"`
IsConsensus bool `yaml:"isConsensus,omitempty"`
PeerId string `yaml:"peerId"`
Address string `yaml:"address"`
SigningKey string `yaml:"signingKey,omitempty"`
EncryptionKey string `yaml:"encryptionKey,omitempty"`
Types []NodeType `yaml:"types,omitempty"`
}
func (n Node) HasType(t NodeType) bool {
for _, nt := range n.Types {
if nt == t {
return true
}
}
return false
}

View file

@ -29,8 +29,11 @@ require (
)
require (
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cheggaaa/mb/v2 v2.1.0-alpha // indirect
github.com/cheggaaa/mb/v3 v3.0.0-20221122160120-e9034545510c // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/fogleman/gg v1.3.0 // indirect

View file

@ -35,6 +35,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -58,6 +60,14 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/mb/v2 v2.1.0-alpha h1:GN2R1eUrImfd8lwmx6VfX6E4RqXoOjUBdZLo9aqw87o=
github.com/cheggaaa/mb/v2 v2.1.0-alpha/go.mod h1:XGeZw20Iqgjky26KL0mvCwk3+4NyZCUbshSo6ALne+c=
github.com/cheggaaa/mb/v3 v3.0.0-20221116073802-28877f0c7d6c h1:qgBgvJEmHz9Jhe2Aso0y1djx9RpQo6AiC1k1ScCyQTc=
github.com/cheggaaa/mb/v3 v3.0.0-20221116073802-28877f0c7d6c/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI=
github.com/cheggaaa/mb/v3 v3.0.0-20221116093702-e509afb93b07 h1:iApZflWEqUGURwq88cOgAA5+I686xFabUj4YvPCKfUo=
github.com/cheggaaa/mb/v3 v3.0.0-20221116093702-e509afb93b07/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI=
github.com/cheggaaa/mb/v3 v3.0.0-20221122160120-e9034545510c h1:+bD75daSbsxyTzkKpNplC4xls+7/tGwty+zruzOnOmk=
github.com/cheggaaa/mb/v3 v3.0.0-20221122160120-e9034545510c/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=

View file

@ -5,10 +5,6 @@ import (
"github.com/anytypeio/go-chash"
)
func New() Service {
return new(service)
}
type Configuration interface {
// Id returns current nodeconf id
Id() string
@ -16,12 +12,18 @@ type Configuration interface {
NodeIds(spaceId string) []string
// IsResponsible checks if current account responsible for given spaceId
IsResponsible(spaceId string) bool
// FilePeers returns list of filenodes
FilePeers() []string
// ConsensusPeers returns list of consensusnodes
ConsensusPeers() []string
}
type configuration struct {
id string
accountId string
chash chash.CHash
id string
accountId string
filePeers []string
consensusPeers []string
chash chash.CHash
}
func (c *configuration) Id() string {
@ -47,3 +49,11 @@ func (c *configuration) IsResponsible(spaceId string) bool {
}
return false
}
func (c *configuration) FilePeers() []string {
return c.filePeers
}
func (c *configuration) ConsensusPeers() []string {
return c.consensusPeers
}

View file

@ -37,20 +37,6 @@ func (m *MockService) EXPECT() *MockServiceMockRecorder {
return m.recorder
}
// ConsensusPeers mocks base method.
func (m *MockService) ConsensusPeers() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ConsensusPeers")
ret0, _ := ret[0].([]string)
return ret0
}
// ConsensusPeers indicates an expected call of ConsensusPeers.
func (mr *MockServiceMockRecorder) ConsensusPeers() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusPeers", reflect.TypeOf((*MockService)(nil).ConsensusPeers))
}
// GetById mocks base method.
func (m *MockService) GetById(arg0 string) nodeconf.Configuration {
m.ctrl.T.Helper()
@ -130,6 +116,34 @@ func (m *MockConfiguration) EXPECT() *MockConfigurationMockRecorder {
return m.recorder
}
// ConsensusPeers mocks base method.
func (m *MockConfiguration) ConsensusPeers() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ConsensusPeers")
ret0, _ := ret[0].([]string)
return ret0
}
// ConsensusPeers indicates an expected call of ConsensusPeers.
func (mr *MockConfigurationMockRecorder) ConsensusPeers() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusPeers", reflect.TypeOf((*MockConfiguration)(nil).ConsensusPeers))
}
// FilePeers mocks base method.
func (m *MockConfiguration) FilePeers() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FilePeers")
ret0, _ := ret[0].([]string)
return ret0
}
// FilePeers indicates an expected call of FilePeers.
func (mr *MockConfigurationMockRecorder) FilePeers() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilePeers", reflect.TypeOf((*MockConfiguration)(nil).FilePeers))
}
// Id mocks base method.
func (m *MockConfiguration) Id() string {
m.ctrl.T.Helper()

View file

@ -19,18 +19,19 @@ const (
var log = logger.NewNamed(CName)
func New() Service {
return new(service)
}
type Service interface {
GetLast() Configuration
GetById(id string) Configuration
ConsensusPeers() []string
app.Component
}
type service struct {
accountId string
consensusPeers []string
last Configuration
last Configuration
}
type Node struct {
@ -52,11 +53,11 @@ func (s *service) Init(a *app.App) (err error) {
conf := a.MustComponent(config.CName).(*config.Config)
s.accountId = conf.Account.PeerId
config := &configuration{
fileConfig := &configuration{
id: "config",
accountId: s.accountId,
}
if config.chash, err = chash.New(chash.Config{
if fileConfig.chash, err = chash.New(chash.Config{
PartitionCount: partitionCount,
ReplicationFactor: replicationFactor,
}); err != nil {
@ -64,21 +65,28 @@ func (s *service) Init(a *app.App) (err error) {
}
members := make([]chash.Member, 0, len(conf.Nodes))
for _, n := range conf.Nodes {
if n.IsConsensus {
s.consensusPeers = append(s.consensusPeers, n.PeerId)
if n.HasType(config.NodeTypeTree) {
var member *Node
member, err = nodeFromConfigNode(n)
if err != nil {
return
}
members = append(members, member)
}
if n.PeerId == s.accountId {
continue
}
var member *Node
member, err = nodeFromConfigNode(n)
if err != nil {
return
if n.HasType(config.NodeTypeConsensus) {
fileConfig.consensusPeers = append(fileConfig.consensusPeers, n.PeerId)
}
if n.HasType(config.NodeTypeFile) {
fileConfig.filePeers = append(fileConfig.filePeers, n.PeerId)
}
members = append(members, member)
}
if err = config.chash.AddMembers(members...); err != nil {
if err = fileConfig.chash.AddMembers(members...); err != nil {
return
}
s.last = config
s.last = fileConfig
return
}
@ -95,10 +103,6 @@ func (s *service) GetById(id string) Configuration {
panic("implement me")
}
func (s *service) ConsensusPeers() []string {
return s.consensusPeers
}
func nodeFromConfigNode(
n config.Node) (*Node, error) {
decodedSigningKey, err := keys.DecodeKeyFromString(

View file

@ -63,7 +63,7 @@ func New(loadFunc LoadFunc, opts ...Option) OCache {
for _, o := range opts {
o(c)
}
if c.ttl != 0 {
if c.ttl != 0 && c.gc != 0 {
go c.ticker()
}
return c

View file

@ -75,7 +75,7 @@ func (s *service) Run(_ context.Context) error {
}
func (s *service) getClient(ctx context.Context) (consensusproto.DRPCConsensusClient, error) {
peer, err := s.pool.GetOneOf(ctx, s.nodeconf.ConsensusPeers())
peer, err := s.pool.GetOneOf(ctx, s.nodeconf.GetLast().ConsensusPeers())
if err != nil {
return nil, err
}
@ -83,7 +83,7 @@ func (s *service) getClient(ctx context.Context) (consensusproto.DRPCConsensusCl
}
func (s *service) dialClient(ctx context.Context) (consensusproto.DRPCConsensusClient, error) {
peer, err := s.pool.DialOneOf(ctx, s.nodeconf.ConsensusPeers())
peer, err := s.pool.DialOneOf(ctx, s.nodeconf.GetLast().ConsensusPeers())
if err != nil {
return nil, err
}

View file

@ -4,10 +4,10 @@ import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpctest"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf/mock_nodeconf"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto/consensuserr"
"github.com/golang/mock/gomock"
@ -131,22 +131,34 @@ func newFixture(t *testing.T) *fixture {
stream: make(chan consensusproto.DRPCConsensus_WatchLogStream),
releaseStream: make(chan error),
},
nodeconf: nodeconf.New(),
}
fx.nodeconf = mock_nodeconf.NewMockService(fx.ctrl)
fx.nodeconf.EXPECT().Init(gomock.Any())
fx.nodeconf.EXPECT().Name().Return(nodeconf.CName).AnyTimes()
fx.nodeconf.EXPECT().ConsensusPeers().Return([]string{"c1", "c2"}).AnyTimes()
fx.drpcTS = rpctest.NewTestServer()
require.NoError(t, consensusproto.DRPCRegisterConsensus(fx.drpcTS.Mux, fx.testServer))
fx.a.Register(fx.Service).
Register(fx.nodeconf).
Register(rpctest.NewTestPool().WithServer(fx.drpcTS))
Register(rpctest.NewTestPool().WithServer(fx.drpcTS)).
Register(&config.Config{Nodes: []config.Node{
{
PeerId: "c1",
Types: []config.NodeType{config.NodeTypeConsensus},
},
{
PeerId: "c2",
Types: []config.NodeType{config.NodeTypeConsensus},
},
{
PeerId: "c3",
Types: []config.NodeType{config.NodeTypeConsensus},
},
}})
return fx
}
type fixture struct {
Service
nodeconf *mock_nodeconf.MockService
nodeconf nodeconf.Service
a *app.App
ctrl *gomock.Controller
testServer *testServer

View file

@ -1,15 +1,16 @@
package consensusclient
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/cheggaaa/mb/v2"
"github.com/cheggaaa/mb/v3"
"sync"
)
func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream {
st := &stream{
rpcStream: rpcStream,
mb: mb.New((*consensusproto.WatchLogEvent)(nil), 100),
mb: mb.New[*consensusproto.WatchLogEvent](100),
}
go st.readStream()
return st
@ -35,7 +36,8 @@ func (s *stream) UnwatchIds(logIds [][]byte) (err error) {
}
func (s *stream) WaitLogs() []*consensusproto.WatchLogEvent {
return s.mb.Wait()
events, _ := s.mb.Wait(context.TODO())
return events
}
func (s *stream) Err() error {
@ -54,7 +56,7 @@ func (s *stream) readStream() {
s.mu.Unlock()
return
}
if err = s.mb.Add(event); err != nil {
if err = s.mb.Add(s.rpcStream.Context(), event); err != nil {
return
}
}

View file

@ -8,7 +8,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/db"
"github.com/cheggaaa/mb/v2"
"github.com/cheggaaa/mb/v3"
"github.com/mr-tron/base58"
"go.uber.org/zap"
"sync/atomic"
@ -74,7 +74,7 @@ func (s *service) NewStream() *Stream {
return &Stream{
id: atomic.AddUint64(&s.lastStreamId, 1),
logIds: make(map[string]struct{}),
mb: mb.New(consensus.Log{}, 100),
mb: mb.New[consensus.Log](100),
s: s,
}
}

View file

@ -3,7 +3,7 @@ package stream
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus"
"github.com/cheggaaa/mb/v2"
"github.com/cheggaaa/mb/v3"
"go.uber.org/zap"
"sync"
)
@ -30,13 +30,14 @@ func (s *Stream) LogIds() [][]byte {
// AddRecords adds new records to stream, called by objects
func (s *Stream) AddRecords(logId []byte, records []consensus.Record) (err error) {
return s.mb.Add(consensus.Log{Id: logId, Records: records})
return s.mb.Add(context.TODO(), consensus.Log{Id: logId, Records: records})
}
// WaitLogs wait for new log records
// empty returned slice means that stream is closed
func (s *Stream) WaitLogs() []consensus.Log {
return s.mb.Wait()
logs, _ := s.mb.Wait(context.TODO())
return logs
}
// WatchIds adds given ids to subscription
@ -49,7 +50,7 @@ func (s *Stream) WatchIds(ctx context.Context, logIds [][]byte) {
s.logIds[logIdKey] = struct{}{}
if addErr := s.s.AddStream(ctx, logId, s); addErr != nil {
log.Info("can't add stream for log", zap.Binary("logId", logId), zap.Error(addErr))
_ = s.mb.Add(consensus.Log{
_ = s.mb.Add(ctx, consensus.Log{
Id: logId,
Err: addErr,
})

View file

@ -16,14 +16,17 @@ nodes:
address: 127.0.0.1:4430
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
types : ["tree", "file"]
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
types : ["tree", "file"]
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
types : ["tree", "file"]
space:
gcTTL: 60
syncPeriod: 10

View file

@ -16,14 +16,17 @@ nodes:
address: 127.0.0.1:4430
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
types : ["tree", "file"]
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
types : ["tree", "file"]
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
types : ["tree", "file"]
space:
gcTTL: 60
syncPeriod: 10

View file

@ -16,14 +16,17 @@ nodes:
address: 127.0.0.1:4430
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
types : ["tree", "file"]
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
types : ["tree", "file"]
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
types : ["tree", "file"]
space:
gcTTL: 60
syncPeriod: 10

View file

@ -16,14 +16,17 @@ nodes:
address: 127.0.0.1:4430
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
types : ["tree", "file"]
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
types : ["tree", "file"]
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
types : ["tree", "file"]
space:
gcTTL: 60
syncPeriod: 10

View file

@ -16,14 +16,17 @@ nodes:
address: 127.0.0.1:4430
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
types : ["tree", "file"]
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
types : ["tree", "file"]
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
types : ["tree", "file"]
space:
gcTTL: 60
syncPeriod: 10

View file

@ -0,0 +1,46 @@
package fileservice
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/ipfsstore"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
exchange "github.com/ipfs/go-ipfs-exchange-interface"
)
type blockService struct {
store ipfsstore.IPFSStore
}
func (bs *blockService) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) {
return bs.store.Get(ctx, c)
}
func (bs *blockService) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
return bs.store.GetMany(ctx, ks)
}
func (bs *blockService) Blockstore() blockstore.Blockstore {
return nil
}
func (bs *blockService) Exchange() exchange.Interface {
return nil
}
func (bs *blockService) AddBlock(ctx context.Context, b blocks.Block) error {
return bs.store.Add(ctx, []blocks.Block{b})
}
func (bs *blockService) AddBlocks(ctx context.Context, b []blocks.Block) error {
return bs.store.Add(ctx, b)
}
func (bs *blockService) DeleteBlock(ctx context.Context, c cid.Cid) error {
return bs.store.Delete(ctx, c)
}
func (bs *blockService) Close() error {
return bs.store.Close()
}

View file

@ -0,0 +1,36 @@
package fileservice
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
ipld "github.com/ipfs/go-ipld-format"
"github.com/ipfs/go-merkledag"
)
const CName = "filenode.fileservice"
type FileService interface {
app.ComponentRunnable
}
type fileService struct {
blockService *blockService
dagService ipld.DAGService
}
func (fs *fileService) Init(a *app.App) (err error) {
fs.dagService = merkledag.NewDAGService(fs.blockService)
return
}
func (fs *fileService) Name() string {
return CName
}
func (fs *fileService) Run(ctx context.Context) (err error) {
return
}
func (fs *fileService) Close(ctx context.Context) (err error) {
return
}

54
filenode/go.mod Normal file
View file

@ -0,0 +1,54 @@
module github.com/anytypeio/go-anytype-infrastructure-experiments/filenode
go 1.19
replace github.com/anytypeio/go-anytype-infrastructure-experiments/common => ../common
require github.com/anytypeio/go-anytype-infrastructure-experiments/common v0.0.0-00010101000000-000000000000
require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-block-format v0.0.3 // indirect
github.com/ipfs/go-blockservice v0.3.0 // indirect
github.com/ipfs/go-cid v0.3.2 // indirect
github.com/ipfs/go-datastore v0.5.0 // indirect
github.com/ipfs/go-ipfs-blockstore v1.2.0 // indirect
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
github.com/ipfs/go-ipfs-exchange-interface v0.1.0 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipfs/go-ipld-cbor v0.0.5 // indirect
github.com/ipfs/go-ipld-format v0.4.0 // indirect
github.com/ipfs/go-ipld-legacy v0.1.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/ipfs/go-merkledag v0.8.0 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
github.com/ipfs/go-verifcid v0.0.1 // indirect
github.com/ipld/go-codec-dagpb v1.3.1 // indirect
github.com/ipld/go-ipld-prime v0.16.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.1.0 // indirect
github.com/multiformats/go-multibase v0.1.1 // indirect
github.com/multiformats/go-multihash v0.2.1 // indirect
github.com/multiformats/go-varint v0.0.6 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.23.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
)

1115
filenode/go.sum Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,10 @@
go 1.19
use (
./client
./common
./consensus
./filenode
./node
./client
./util
)

View file

@ -7,8 +7,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUu
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w=
github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=
@ -49,19 +47,19 @@ github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQy
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99 h1:Ak8CrdlwwXwAZxzS66vgPt4U8yUZX7JwLvVR58FN5jM=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro=
github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=

View file

@ -10,16 +10,6 @@ message BlockSync {
message Msg {
}
service Space {
rpc Diff(Msg) returns (Msg);
// subscription service:
// service.Broadcast(ss)
rpc ObjectSyncStream(stream Msg) returns (stream Msg);
}
service File {
@ -27,12 +17,3 @@ service File {
rpc PushCID(Msg) returns (Msg);
}
service StrongLog { // ACL Log
rpc PushACL(Msg) returns (Msg);
rpc StartTransaction();
}
service Replication {
//
}