Merge pull request #14 from anytypeio/add-client-functionality
This commit is contained in:
commit
8263bbfde2
7
.gitignore
vendored
7
.gitignore
vendored
@ -8,12 +8,19 @@
|
|||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
# Golang vendor folder
|
# Golang vendor folder
|
||||||
vendor
|
vendor
|
||||||
|
|
||||||
|
# database
|
||||||
|
db
|
||||||
|
|
||||||
|
# artefacts for Intelli-J fleet
|
||||||
|
.fleet
|
||||||
|
|
||||||
# Intelli-J files
|
# Intelli-J files
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,125 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/document"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
type Controller interface {
|
type Controller interface {
|
||||||
// DeriveSpace derives the space from current account
|
// DeriveSpace derives the space from current account
|
||||||
DeriveSpace() (id string, err error)
|
DeriveSpace() (id string, err error)
|
||||||
// CreateSpace creates new space with random data
|
// CreateSpace creates new space with random data
|
||||||
CreateSpace() (id string, err error)
|
CreateSpace() (id string, err error)
|
||||||
GetAllSpacesIds() (ids []string, err error)
|
// AllSpaceIds returns ids of all spaces
|
||||||
|
AllSpaceIds() (ids []string, err error)
|
||||||
// LoadSpace asks node to load a particular space
|
// LoadSpace asks node to load a particular space
|
||||||
LoadSpace(id string) (err error)
|
LoadSpace(id string) (err error)
|
||||||
|
|
||||||
|
// CreateDocument creates new document in space
|
||||||
CreateDocument(spaceId string) (id string, err error)
|
CreateDocument(spaceId string) (id string, err error)
|
||||||
GetAllDocumentIds(spaceId string) (ids []string, err error)
|
// AllDocumentIds gets all ids of documents in space
|
||||||
AddText(documentId, text string) (err error)
|
AllDocumentIds(spaceId string) (ids []string, err error)
|
||||||
DumpDocumentTree(documentId string) (err error)
|
// AddText adds text to space document
|
||||||
|
AddText(spaceId, documentId, text string) (err error)
|
||||||
|
// DumpDocumentTree dumps the tree data into string
|
||||||
|
DumpDocumentTree(spaceId, documentId string) (dump string, err error)
|
||||||
|
|
||||||
GetValidInvites(spaceId string) (invites []string, err error)
|
ValidInvites(spaceId string) (invites []string, err error)
|
||||||
GenerateInvite(spaceId string) (invite string, err error)
|
GenerateInvite(spaceId string) (invite string, err error)
|
||||||
JoinSpace(invite string) (err error)
|
JoinSpace(invite string) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type controller struct {
|
||||||
|
spaceService clientspace.Service
|
||||||
|
storageService storage.ClientStorage
|
||||||
|
docService document.Service
|
||||||
|
account account.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func newController(spaceService clientspace.Service,
|
||||||
|
storageService storage.ClientStorage,
|
||||||
|
docService document.Service,
|
||||||
|
account account.Service) Controller {
|
||||||
|
return &controller{
|
||||||
|
spaceService: spaceService,
|
||||||
|
storageService: storageService,
|
||||||
|
docService: docService,
|
||||||
|
account: account,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) DeriveSpace() (id string, err error) {
|
||||||
|
sp, err := c.spaceService.DeriveSpace(context.Background(), commonspace.SpaceDerivePayload{
|
||||||
|
SigningKey: c.account.Account().SignKey,
|
||||||
|
EncryptionKey: c.account.Account().EncKey,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id = sp.Id()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) CreateSpace() (id string, err error) {
|
||||||
|
key, err := symmetric.NewRandom()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sp, err := c.spaceService.CreateSpace(context.Background(), commonspace.SpaceCreatePayload{
|
||||||
|
SigningKey: c.account.Account().SignKey,
|
||||||
|
EncryptionKey: c.account.Account().EncKey,
|
||||||
|
ReadKey: key.Bytes(),
|
||||||
|
ReplicationKey: rand.Uint64(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id = sp.Id()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) AllSpaceIds() (ids []string, err error) {
|
||||||
|
return c.storageService.AllSpaceIds()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) LoadSpace(id string) (err error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) CreateDocument(spaceId string) (id string, err error) {
|
||||||
|
return c.docService.CreateDocument(spaceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) AllDocumentIds(spaceId string) (ids []string, err error) {
|
||||||
|
return c.docService.AllDocumentIds(spaceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) AddText(spaceId, documentId, text string) (err error) {
|
||||||
|
return c.docService.AddText(spaceId, documentId, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) DumpDocumentTree(spaceId, documentId string) (dump string, err error) {
|
||||||
|
return c.docService.DumpDocumentTree(spaceId, documentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) ValidInvites(spaceId string) (invites []string, err error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) GenerateInvite(spaceId string) (invite string, err error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) JoinSpace(invite string) (err error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|||||||
169
client/api/service.go
Normal file
169
client/api/service.go
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/document"
|
||||||
|
clientstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/client/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
|
"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/commonspace/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CName = "api.service"
|
||||||
|
|
||||||
|
var log = logger.NewNamed("api")
|
||||||
|
|
||||||
|
func New() Service {
|
||||||
|
return &service{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service interface {
|
||||||
|
app.ComponentRunnable
|
||||||
|
}
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
controller Controller
|
||||||
|
srv *http.Server
|
||||||
|
cfg *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
|
s.controller = newController(
|
||||||
|
a.MustComponent(clientspace.CName).(clientspace.Service),
|
||||||
|
a.MustComponent(storage.CName).(clientstorage.ClientStorage),
|
||||||
|
a.MustComponent(document.CName).(document.Service),
|
||||||
|
a.MustComponent(account.CName).(account.Service))
|
||||||
|
s.cfg = a.MustComponent(config.CName).(*config.Config)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Name() (name string) {
|
||||||
|
return CName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Run(ctx context.Context) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
log.With(zap.String("port", s.cfg.APIServer.Port)).Info("api server started running")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
s.srv = &http.Server{
|
||||||
|
Addr: fmt.Sprintf(":%s", s.cfg.APIServer.Port),
|
||||||
|
}
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/deriveSpace", s.deriveSpace)
|
||||||
|
mux.HandleFunc("/createSpace", s.createSpace)
|
||||||
|
mux.HandleFunc("/allSpaceIds", s.allSpaceIds)
|
||||||
|
mux.HandleFunc("/createDocument", s.createDocument)
|
||||||
|
mux.HandleFunc("/allDocumentIds", s.allDocumentIds)
|
||||||
|
mux.HandleFunc("/addText", s.addText)
|
||||||
|
mux.HandleFunc("/dumpDocumentTree", s.dumpDocumentTree)
|
||||||
|
s.srv.Handler = mux
|
||||||
|
|
||||||
|
go s.runServer()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) runServer() {
|
||||||
|
err := s.srv.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
log.With(zap.Error(err)).Error("could not run api server")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Close(ctx context.Context) (err error) {
|
||||||
|
return s.srv.Shutdown(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) deriveSpace(w http.ResponseWriter, req *http.Request) {
|
||||||
|
id, err := s.controller.DeriveSpace()
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) createSpace(w http.ResponseWriter, req *http.Request) {
|
||||||
|
id, err := s.controller.CreateSpace()
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) allSpaceIds(w http.ResponseWriter, req *http.Request) {
|
||||||
|
ids, err := s.controller.AllSpaceIds()
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, strings.Join(ids, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) createDocument(w http.ResponseWriter, req *http.Request) {
|
||||||
|
query := req.URL.Query()
|
||||||
|
spaceId := query.Get("spaceId")
|
||||||
|
id, err := s.controller.CreateDocument(spaceId)
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) allDocumentIds(w http.ResponseWriter, req *http.Request) {
|
||||||
|
query := req.URL.Query()
|
||||||
|
spaceId := query.Get("spaceId")
|
||||||
|
ids, err := s.controller.AllDocumentIds(spaceId)
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, strings.Join(ids, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) addText(w http.ResponseWriter, req *http.Request) {
|
||||||
|
query := req.URL.Query()
|
||||||
|
spaceId := query.Get("spaceId")
|
||||||
|
documentId := query.Get("documentId")
|
||||||
|
text := query.Get("text")
|
||||||
|
err := s.controller.AddText(spaceId, documentId, text)
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, "Text added")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) dumpDocumentTree(w http.ResponseWriter, req *http.Request) {
|
||||||
|
query := req.URL.Query()
|
||||||
|
spaceId := query.Get("spaceId")
|
||||||
|
documentId := query.Get("documentId")
|
||||||
|
dump, err := s.controller.DumpDocumentTree(spaceId, documentId)
|
||||||
|
if err != nil {
|
||||||
|
sendText(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendText(w, http.StatusOK, dump)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendText(r http.ResponseWriter, code int, body string) {
|
||||||
|
r.Header().Set("Content-Type", "text/plain")
|
||||||
|
r.WriteHeader(code)
|
||||||
|
|
||||||
|
_, err := io.WriteString(r, fmt.Sprintf("%s\n", body))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("writing response failed", zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,6 +18,10 @@ type service struct {
|
|||||||
db *badger.DB
|
db *badger.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func New() BadgerProvider {
|
||||||
|
return &service{}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *service) Init(a *app.App) (err error) {
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
cfg := a.MustComponent(config.CName).(*config.Config)
|
cfg := a.MustComponent(config.CName).(*config.Config)
|
||||||
s.db, err = badger.Open(badger.DefaultOptions(cfg.Storage.Path))
|
s.db, err = badger.Open(badger.DefaultOptions(cfg.Storage.Path))
|
||||||
|
|||||||
@ -3,11 +3,15 @@ package clientcache
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/document/textdocument"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
"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/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||||
|
"go.uber.org/zap"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,10 +25,33 @@ const spaceKey ctxKey = 0
|
|||||||
type treeCache struct {
|
type treeCache struct {
|
||||||
gcttl int
|
gcttl int
|
||||||
cache ocache.OCache
|
cache ocache.OCache
|
||||||
|
account account.Service
|
||||||
clientService clientspace.Service
|
clientService clientspace.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ttl int) cache.TreeCache {
|
type TreeCache interface {
|
||||||
|
treegetter.TreeGetter
|
||||||
|
GetDocument(ctx context.Context, spaceId, id string) (doc textdocument.TextDocument, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateListener struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *updateListener) Update(tree tree.ObjectTree) {
|
||||||
|
log.With(
|
||||||
|
zap.Strings("heads", tree.Heads()),
|
||||||
|
zap.String("tree id", tree.ID())).
|
||||||
|
Debug("updating tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *updateListener) Rebuild(tree tree.ObjectTree) {
|
||||||
|
log.With(
|
||||||
|
zap.Strings("heads", tree.Heads()),
|
||||||
|
zap.String("tree id", tree.ID())).
|
||||||
|
Debug("rebuilding tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ttl int) TreeCache {
|
||||||
return &treeCache{
|
return &treeCache{
|
||||||
gcttl: ttl,
|
gcttl: ttl,
|
||||||
}
|
}
|
||||||
@ -40,6 +67,7 @@ func (c *treeCache) Close(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
func (c *treeCache) Init(a *app.App) (err error) {
|
func (c *treeCache) Init(a *app.App) (err error) {
|
||||||
c.clientService = a.MustComponent(clientspace.CName).(clientspace.Service)
|
c.clientService = a.MustComponent(clientspace.CName).(clientspace.Service)
|
||||||
|
c.account = a.MustComponent(account.CName).(account.Service)
|
||||||
c.cache = ocache.New(
|
c.cache = ocache.New(
|
||||||
func(ctx context.Context, id string) (value ocache.Object, err error) {
|
func(ctx context.Context, id string) (value ocache.Object, err error) {
|
||||||
spaceId := ctx.Value(spaceKey).(string)
|
spaceId := ctx.Value(spaceKey).(string)
|
||||||
@ -47,39 +75,34 @@ func (c *treeCache) Init(a *app.App) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return space.BuildTree(ctx, id, nil)
|
return textdocument.NewTextDocument(context.Background(), space, id, &updateListener{}, c.account)
|
||||||
},
|
},
|
||||||
ocache.WithLogger(log.Sugar()),
|
ocache.WithLogger(log.Sugar()),
|
||||||
ocache.WithGCPeriod(time.Minute),
|
ocache.WithGCPeriod(time.Minute),
|
||||||
ocache.WithTTL(time.Duration(c.gcttl)*time.Second),
|
ocache.WithTTL(time.Duration(c.gcttl)*time.Second),
|
||||||
ocache.WithRefCounter(false),
|
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *treeCache) Name() (name string) {
|
func (c *treeCache) Name() (name string) {
|
||||||
return cache.CName
|
return treegetter.CName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *treeCache) GetTree(ctx context.Context, spaceId, id string) (res cache.TreeResult, err error) {
|
func (c *treeCache) GetDocument(ctx context.Context, spaceId, id string) (doc textdocument.TextDocument, err error) {
|
||||||
var cacheRes ocache.Object
|
|
||||||
ctx = context.WithValue(ctx, spaceKey, spaceId)
|
ctx = context.WithValue(ctx, spaceKey, spaceId)
|
||||||
cacheRes, err = c.cache.Get(ctx, id)
|
v, err := c.cache.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cache.TreeResult{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
treeContainer, ok := cacheRes.(cache.TreeContainer)
|
|
||||||
if !ok {
|
|
||||||
err = ErrCacheObjectWithoutTree
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
doc = v.(textdocument.TextDocument)
|
||||||
res = cache.TreeResult{
|
return
|
||||||
Release: func() {
|
}
|
||||||
c.cache.Release(id)
|
|
||||||
},
|
func (c *treeCache) GetTree(ctx context.Context, spaceId, id string) (tr tree.ObjectTree, err error) {
|
||||||
TreeContainer: treeContainer,
|
doc, err := c.GetDocument(ctx, spaceId, id)
|
||||||
}
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tr = doc.Tree()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,10 @@ package clientspace
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rpcHandler struct {
|
type rpcHandler struct {
|
||||||
@ -17,16 +18,19 @@ func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpac
|
|||||||
err = spacesyncproto.ErrSpaceExists
|
err = spacesyncproto.ErrSpaceExists
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err != cache.ErrSpaceNotFound {
|
if err != treegetter.ErrSpaceNotFound {
|
||||||
err = spacesyncproto.ErrUnexpected
|
err = spacesyncproto.ErrUnexpected
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
payload := storage.SpaceStorageCreatePayload{
|
payload := storage.SpaceStorageCreatePayload{
|
||||||
RecWithId: req.AclRoot,
|
RecWithId: &aclrecordproto.RawACLRecordWithId{
|
||||||
|
Payload: req.AclPayload,
|
||||||
|
Id: req.AclPayloadId,
|
||||||
|
},
|
||||||
SpaceHeaderWithId: req.SpaceHeader,
|
SpaceHeaderWithId: req.SpaceHeader,
|
||||||
}
|
}
|
||||||
_, err = r.s.spaceStorageProvider.CreateSpaceStorage(payload)
|
st, err := r.s.spaceStorageProvider.CreateSpaceStorage(payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = spacesyncproto.ErrUnexpected
|
err = spacesyncproto.ErrUnexpected
|
||||||
if err == storage.ErrSpaceStorageExists {
|
if err == storage.ErrSpaceStorageExists {
|
||||||
@ -34,6 +38,7 @@ func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpac
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
st.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,6 @@ func (s *service) Init(a *app.App) (err error) {
|
|||||||
ocache.WithLogger(log.Sugar()),
|
ocache.WithLogger(log.Sugar()),
|
||||||
ocache.WithGCPeriod(time.Minute),
|
ocache.WithGCPeriod(time.Minute),
|
||||||
ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second),
|
ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second),
|
||||||
ocache.WithRefCounter(false),
|
|
||||||
)
|
)
|
||||||
return spacesyncproto.DRPCRegisterSpace(a.MustComponent(server.CName).(server.DRPCServer), &rpcHandler{s})
|
return spacesyncproto.DRPCRegisterSpace(a.MustComponent(server.CName).(server.DRPCServer), &rpcHandler{s})
|
||||||
}
|
}
|
||||||
@ -56,43 +55,39 @@ func (s *service) Name() (name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Run(ctx context.Context) (err error) {
|
func (s *service) Run(ctx context.Context) (err error) {
|
||||||
go func() {
|
|
||||||
time.Sleep(time.Second * 5)
|
|
||||||
_, _ = s.GetSpace(ctx, "testDSpace")
|
|
||||||
}()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) CreateSpace(ctx context.Context, payload commonspace.SpaceCreatePayload) (space commonspace.Space, err error) {
|
func (s *service) CreateSpace(ctx context.Context, payload commonspace.SpaceCreatePayload) (container commonspace.Space, err error) {
|
||||||
id, err := s.commonSpace.CreateSpace(ctx, payload)
|
id, err := s.commonSpace.CreateSpace(ctx, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
obj, err := s.commonSpace.GetSpace(ctx, id)
|
obj, err := s.spaceCache.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return obj.(commonspace.Space), nil
|
return obj.(commonspace.Space), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) DeriveSpace(ctx context.Context, payload commonspace.SpaceDerivePayload) (space commonspace.Space, err error) {
|
func (s *service) DeriveSpace(ctx context.Context, payload commonspace.SpaceDerivePayload) (container commonspace.Space, err error) {
|
||||||
id, err := s.commonSpace.DeriveSpace(ctx, payload)
|
id, err := s.commonSpace.DeriveSpace(ctx, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
obj, err := s.commonSpace.GetSpace(ctx, id)
|
obj, err := s.spaceCache.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return obj.(commonspace.Space), nil
|
return obj.(commonspace.Space), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) GetSpace(ctx context.Context, id string) (commonspace.Space, error) {
|
func (s *service) GetSpace(ctx context.Context, id string) (container commonspace.Space, err error) {
|
||||||
v, err := s.spaceCache.Get(ctx, id)
|
v, err := s.spaceCache.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
return v.(commonspace.Space), nil
|
return v.(commonspace.Space), nil
|
||||||
}
|
}
|
||||||
|
|||||||
112
client/cmd/client.go
Normal file
112
client/cmd/client.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/account"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/api"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/badgerprovider"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace/clientcache"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/document"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/storage"
|
||||||
|
"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/commonspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/metric"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/dialer"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/secure"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var log = logger.NewNamed("main")
|
||||||
|
|
||||||
|
var (
|
||||||
|
flagConfigFile = flag.String("c", "etc/client.yml", "path to config file")
|
||||||
|
// we can't use "v" here because of glog init (through badger) setting flag.Bool with "v"
|
||||||
|
flagVersion = flag.Bool("ver", false, "show version and exit")
|
||||||
|
flagHelp = flag.Bool("h", false, "show help and exit")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *flagVersion {
|
||||||
|
fmt.Println(app.VersionDescription())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if *flagHelp {
|
||||||
|
flag.PrintDefaults()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug, ok := os.LookupEnv("ANYPROF"); ok && debug != "" {
|
||||||
|
go func() {
|
||||||
|
http.ListenAndServe(debug, nil)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// create app
|
||||||
|
ctx := context.Background()
|
||||||
|
a := new(app.App)
|
||||||
|
|
||||||
|
// open config file
|
||||||
|
conf, err := config.NewFromFile(*flagConfigFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("can't open config file", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// bootstrap components
|
||||||
|
a.Register(conf)
|
||||||
|
Bootstrap(a)
|
||||||
|
|
||||||
|
// start app
|
||||||
|
if err := a.Start(ctx); err != nil {
|
||||||
|
log.Fatal("can't start app", zap.Error(err))
|
||||||
|
}
|
||||||
|
log.Info("app started", zap.String("version", a.Version()))
|
||||||
|
|
||||||
|
// wait exit signal
|
||||||
|
exit := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(exit, os.Interrupt, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
|
sig := <-exit
|
||||||
|
log.Info("received exit signal, stop app...", zap.String("signal", fmt.Sprint(sig)))
|
||||||
|
|
||||||
|
// close app
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
if err := a.Close(ctx); err != nil {
|
||||||
|
log.Fatal("close error", zap.Error(err))
|
||||||
|
} else {
|
||||||
|
log.Info("goodbye!")
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second / 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bootstrap(a *app.App) {
|
||||||
|
a.Register(account.New()).
|
||||||
|
Register(nodeconf.New()).
|
||||||
|
Register(metric.New()).
|
||||||
|
Register(badgerprovider.New()).
|
||||||
|
Register(storage.New()).
|
||||||
|
Register(clientcache.New(200)).
|
||||||
|
Register(secure.New()).
|
||||||
|
Register(dialer.New()).
|
||||||
|
Register(pool.New()).
|
||||||
|
Register(commonspace.New()).
|
||||||
|
Register(clientspace.New()).
|
||||||
|
Register(server.New()).
|
||||||
|
Register(document.New()).
|
||||||
|
Register(api.New())
|
||||||
|
}
|
||||||
@ -1,13 +1,83 @@
|
|||||||
package document
|
package document
|
||||||
|
|
||||||
import "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace/clientcache"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/document/textdocument"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
|
"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/commonspace/treegetter"
|
||||||
|
)
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
app.Component
|
app.Component
|
||||||
CreateDocument(spaceId string) (id string, err error)
|
CreateDocument(spaceId string) (id string, err error)
|
||||||
GetAllDocumentIds(spaceId string) (ids []string, err error)
|
AllDocumentIds(spaceId string) (ids []string, err error)
|
||||||
AddText(documentId, text string) (err error)
|
AddText(spaceId, documentId, text string) (err error)
|
||||||
DumpDocumentTree(documentId string) (err error)
|
DumpDocumentTree(spaceId, documentId string) (dump string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CName = "client.document"
|
const CName = "client.document"
|
||||||
|
|
||||||
|
var log = logger.NewNamed(CName)
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
account account.Service
|
||||||
|
spaceService clientspace.Service
|
||||||
|
cache clientcache.TreeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() Service {
|
||||||
|
return &service{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
|
s.account = a.MustComponent(account.CName).(account.Service)
|
||||||
|
s.spaceService = a.MustComponent(clientspace.CName).(clientspace.Service)
|
||||||
|
s.cache = a.MustComponent(treegetter.CName).(clientcache.TreeCache)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Name() (name string) {
|
||||||
|
return CName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) CreateDocument(spaceId string) (id string, err error) {
|
||||||
|
space, err := s.spaceService.GetSpace(context.Background(), spaceId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
doc, err := textdocument.CreateTextDocument(context.Background(), space, s.account, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id = doc.Tree().ID()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) AllDocumentIds(spaceId string) (ids []string, err error) {
|
||||||
|
space, err := s.spaceService.GetSpace(context.Background(), spaceId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ids = space.StoredIds()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) AddText(spaceId, documentId, text string) (err error) {
|
||||||
|
doc, err := s.cache.GetDocument(context.Background(), spaceId, documentId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return doc.AddText(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) DumpDocumentTree(spaceId, documentId string) (dump string, err error) {
|
||||||
|
doc, err := s.cache.GetDocument(context.Background(), spaceId, documentId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return doc.Tree().DebugDump()
|
||||||
|
}
|
||||||
|
|||||||
116
client/document/textdocument/textdocument.go
Normal file
116
client/document/textdocument/textdocument.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package textdocument
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
|
testchanges "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/testutils/testchanges/proto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TextDocument interface {
|
||||||
|
Tree() tree.ObjectTree
|
||||||
|
AddText(text string) error
|
||||||
|
Text() (string, error)
|
||||||
|
TreeDump() string
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type textDocument struct {
|
||||||
|
objTree tree.ObjectTree
|
||||||
|
account account.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTextDocument(
|
||||||
|
ctx context.Context,
|
||||||
|
space commonspace.Space,
|
||||||
|
account account.Service,
|
||||||
|
listener updatelistener.UpdateListener) (doc TextDocument, err error) {
|
||||||
|
payload := tree.ObjectTreeCreatePayload{
|
||||||
|
SignKey: account.Account().SignKey,
|
||||||
|
SpaceId: space.Id(),
|
||||||
|
Identity: account.Account().Identity,
|
||||||
|
}
|
||||||
|
t, err := space.CreateTree(ctx, payload, listener)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return &textDocument{
|
||||||
|
objTree: t,
|
||||||
|
account: account,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTextDocument(ctx context.Context, space commonspace.Space, id string, listener updatelistener.UpdateListener, account account.Service) (doc TextDocument, err error) {
|
||||||
|
t, err := space.BuildTree(ctx, id, listener)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return &textDocument{
|
||||||
|
objTree: t,
|
||||||
|
account: account,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *textDocument) Tree() tree.ObjectTree {
|
||||||
|
return t.objTree
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *textDocument) AddText(text string) (err error) {
|
||||||
|
content := &testchanges.TextContent_TextAppend{
|
||||||
|
TextAppend: &testchanges.TextAppend{Text: text},
|
||||||
|
}
|
||||||
|
change := &testchanges.TextData{
|
||||||
|
Content: []*testchanges.TextContent{
|
||||||
|
{content},
|
||||||
|
},
|
||||||
|
Snapshot: nil,
|
||||||
|
}
|
||||||
|
res, err := change.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.objTree.Lock()
|
||||||
|
defer t.objTree.Unlock()
|
||||||
|
_, err = t.objTree.AddContent(context.Background(), tree.SignableChangeContent{
|
||||||
|
Data: res,
|
||||||
|
Key: t.account.Account().SignKey,
|
||||||
|
Identity: t.account.Account().Identity,
|
||||||
|
IsSnapshot: false,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *textDocument) Text() (text string, err error) {
|
||||||
|
t.objTree.RLock()
|
||||||
|
defer t.objTree.RUnlock()
|
||||||
|
|
||||||
|
err = t.objTree.Iterate(
|
||||||
|
func(decrypted []byte) (any, error) {
|
||||||
|
textChange := &testchanges.TextData{}
|
||||||
|
err = proto.Unmarshal(decrypted, textChange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, cnt := range textChange.Content {
|
||||||
|
if cnt.GetTextAppend() != nil {
|
||||||
|
text += cnt.GetTextAppend().Text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textChange, nil
|
||||||
|
}, func(change *tree.Change) bool {
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *textDocument) TreeDump() string {
|
||||||
|
return t.TreeDump()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *textDocument) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -2,10 +2,70 @@ module github.com/anytypeio/go-anytype-infrastructure-experiments/client
|
|||||||
|
|
||||||
replace github.com/anytypeio/go-anytype-infrastructure-experiments/common => ../common
|
replace github.com/anytypeio/go-anytype-infrastructure-experiments/common => ../common
|
||||||
|
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/anytypeio/go-anytype-infrastructure-experiments/common v0.0.0-00010101000000-000000000000
|
github.com/anytypeio/go-anytype-infrastructure-experiments/common v0.0.0-00010101000000-000000000000
|
||||||
github.com/dgraph-io/badger/v3 v3.2103.3
|
github.com/dgraph-io/badger/v3 v3.2103.3
|
||||||
|
github.com/gogo/protobuf v1.3.2
|
||||||
|
go.uber.org/zap v1.23.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/anytypeio/go-chash v0.0.0-20220629194632-4ad1154fe232 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/cespare/xxhash v1.1.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||||
|
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||||
|
github.com/fogleman/gg v1.3.0 // indirect
|
||||||
|
github.com/goccy/go-graphviz v0.0.9 // indirect
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/golang/snappy v0.0.3 // indirect
|
||||||
|
github.com/google/flatbuffers v1.12.1 // indirect
|
||||||
|
github.com/huandu/skiplist v1.2.0 // indirect
|
||||||
|
github.com/ipfs/go-cid v0.3.2 // indirect
|
||||||
|
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||||
|
github.com/klauspost/compress v1.15.10 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p v0.23.2 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-core v0.20.1 // indirect
|
||||||
|
github.com/libp2p/go-openssl v0.1.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
|
github.com/mattn/go-pointer v0.0.1 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // 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-multiaddr v0.7.0 // indirect
|
||||||
|
github.com/multiformats/go-multibase v0.1.1 // indirect
|
||||||
|
github.com/multiformats/go-multicodec v0.6.0 // indirect
|
||||||
|
github.com/multiformats/go-multihash v0.2.1 // indirect
|
||||||
|
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.13.0 // indirect
|
||||||
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
|
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
|
github.com/zeebo/errs v1.3.0 // indirect
|
||||||
|
go.opencensus.io v0.23.0 // indirect
|
||||||
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||||
|
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20220920183852-bf014ff85ad5 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect
|
||||||
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
lukechampine.com/blake3 v1.1.7 // indirect
|
||||||
|
storj.io/drpc v0.0.32 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@ -65,7 +65,7 @@ type spaceKeys struct {
|
|||||||
|
|
||||||
func newSpaceKeys(spaceId string) spaceKeys {
|
func newSpaceKeys(spaceId string) spaceKeys {
|
||||||
return spaceKeys{
|
return spaceKeys{
|
||||||
headerKey: storage.JoinStringsToBytes("space", spaceId),
|
headerKey: storage.JoinStringsToBytes("space", "header", spaceId),
|
||||||
treePrefixKey: storage.JoinStringsToBytes("space", spaceId, "t", "rootId"),
|
treePrefixKey: storage.JoinStringsToBytes("space", spaceId, "t", "rootId"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,3 +77,15 @@ func (s spaceKeys) HeaderKey() []byte {
|
|||||||
func (s spaceKeys) TreeRootPrefix() []byte {
|
func (s spaceKeys) TreeRootPrefix() []byte {
|
||||||
return s.treePrefixKey
|
return s.treePrefixKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type storageServiceKeys struct {
|
||||||
|
spacePrefix []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStorageServiceKeys() storageServiceKeys {
|
||||||
|
return storageServiceKeys{spacePrefix: []byte("space/header")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s storageServiceKeys) SpacePrefix() []byte {
|
||||||
|
return s.spacePrefix
|
||||||
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func newListStorage(spaceId string, db *badger.DB, txn *badger.Txn) (ls storage.
|
|||||||
|
|
||||||
ls = &listStorage{
|
ls = &listStorage{
|
||||||
db: db,
|
db: db,
|
||||||
keys: aclKeys{},
|
keys: newACLKeys(spaceId),
|
||||||
id: stringId,
|
id: stringId,
|
||||||
root: rootWithId,
|
root: rootWithId,
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ func createListStorage(spaceId string, db *badger.DB, txn *badger.Txn, root *acl
|
|||||||
|
|
||||||
ls = &listStorage{
|
ls = &listStorage{
|
||||||
db: db,
|
db: db,
|
||||||
keys: aclKeys{},
|
keys: newACLKeys(spaceId),
|
||||||
id: root.Id,
|
id: root.Id,
|
||||||
root: root,
|
root: root,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,5 +125,5 @@ func (s *spaceStorage) StoredIds() (ids []string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *spaceStorage) Close() (err error) {
|
func (s *spaceStorage) Close() (err error) {
|
||||||
return s.objDb.Close()
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,32 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/badgerprovider"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/badgerprovider"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
"github.com/dgraph-io/badger/v3"
|
"github.com/dgraph-io/badger/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type storageService struct {
|
type storageService struct {
|
||||||
db *badger.DB
|
keys storageServiceKeys
|
||||||
|
db *badger.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() storage.SpaceStorageProvider {
|
type ClientStorage interface {
|
||||||
|
storage.SpaceStorageProvider
|
||||||
|
app.ComponentRunnable
|
||||||
|
AllSpaceIds() (ids []string, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() ClientStorage {
|
||||||
return &storageService{}
|
return &storageService{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storageService) Init(a *app.App) (err error) {
|
func (s *storageService) Init(a *app.App) (err error) {
|
||||||
provider := a.MustComponent(badgerprovider.CName).(badgerprovider.BadgerProvider)
|
provider := a.MustComponent(badgerprovider.CName).(badgerprovider.BadgerProvider)
|
||||||
s.db = provider.Badger()
|
s.db = provider.Badger()
|
||||||
|
s.keys = newStorageServiceKeys()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,3 +41,34 @@ func (s *storageService) SpaceStorage(id string) (storage.SpaceStorage, error) {
|
|||||||
func (s *storageService) CreateSpaceStorage(payload storage.SpaceStorageCreatePayload) (storage.SpaceStorage, error) {
|
func (s *storageService) CreateSpaceStorage(payload storage.SpaceStorageCreatePayload) (storage.SpaceStorage, error) {
|
||||||
return createSpaceStorage(s.db, payload)
|
return createSpaceStorage(s.db, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *storageService) AllSpaceIds() (ids []string, err error) {
|
||||||
|
err = s.db.View(func(txn *badger.Txn) error {
|
||||||
|
opts := badger.DefaultIteratorOptions
|
||||||
|
opts.PrefetchValues = false
|
||||||
|
opts.Prefix = s.keys.SpacePrefix()
|
||||||
|
|
||||||
|
it := txn.NewIterator(opts)
|
||||||
|
defer it.Close()
|
||||||
|
|
||||||
|
for it.Rewind(); it.Valid(); it.Next() {
|
||||||
|
item := it.Item()
|
||||||
|
id := item.Key()
|
||||||
|
if len(id) <= len(s.keys.SpacePrefix())+1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
id = id[len(s.keys.SpacePrefix())+1:]
|
||||||
|
ids = append(ids, string(id))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storageService) Run(ctx context.Context) (err error) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storageService) Close(ctx context.Context) (err error) {
|
||||||
|
return s.db.Close()
|
||||||
|
}
|
||||||
|
|||||||
30
common/commonspace/cache/treecache.go
vendored
30
common/commonspace/cache/treecache.go
vendored
@ -1,30 +0,0 @@
|
|||||||
//go:generate mockgen -destination mock_cache/mock_cache.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache TreeCache
|
|
||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
)
|
|
||||||
|
|
||||||
const CName = "commonspace.cache"
|
|
||||||
|
|
||||||
var ErrSpaceNotFound = errors.New("space not found")
|
|
||||||
|
|
||||||
type TreeContainer interface {
|
|
||||||
Tree() tree.ObjectTree
|
|
||||||
}
|
|
||||||
|
|
||||||
type TreeResult struct {
|
|
||||||
Release func()
|
|
||||||
TreeContainer TreeContainer
|
|
||||||
}
|
|
||||||
|
|
||||||
type BuildFunc = func(ctx context.Context, id string, listener updatelistener.UpdateListener) (tree.ObjectTree, error)
|
|
||||||
|
|
||||||
type TreeCache interface {
|
|
||||||
app.ComponentRunnable
|
|
||||||
GetTree(ctx context.Context, spaceId, treeId string) (TreeResult, error)
|
|
||||||
}
|
|
||||||
35
common/commonspace/commongetter.go
Normal file
35
common/commonspace/commongetter.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package commonspace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/objectgetter"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncacl"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type commonSpaceGetter struct {
|
||||||
|
spaceId string
|
||||||
|
aclList *syncacl.SyncACL
|
||||||
|
treeGetter treegetter.TreeGetter
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCommonSpaceGetter(spaceId string, aclList *syncacl.SyncACL, treeGetter treegetter.TreeGetter) objectgetter.ObjectGetter {
|
||||||
|
return &commonSpaceGetter{
|
||||||
|
spaceId: spaceId,
|
||||||
|
aclList: aclList,
|
||||||
|
treeGetter: treeGetter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *commonSpaceGetter) GetObject(ctx context.Context, objectId string) (obj objectgetter.Object, err error) {
|
||||||
|
if c.aclList.ID() == objectId {
|
||||||
|
obj = c.aclList
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t, err := c.treeGetter.GetTree(ctx, c.spaceId, objectId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
obj = t.(objectgetter.Object)
|
||||||
|
return
|
||||||
|
}
|
||||||
@ -3,10 +3,10 @@ package diffservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/remotediff"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/remotediff"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -14,9 +14,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DiffService interface {
|
type DiffService interface {
|
||||||
|
HeadNotifiable
|
||||||
HandleRangeRequest(ctx context.Context, req *spacesyncproto.HeadSyncRequest) (resp *spacesyncproto.HeadSyncResponse, err error)
|
HandleRangeRequest(ctx context.Context, req *spacesyncproto.HeadSyncRequest) (resp *spacesyncproto.HeadSyncResponse, err error)
|
||||||
UpdateHeads(id string, heads []string)
|
|
||||||
RemoveObject(id string)
|
RemoveObject(id string)
|
||||||
|
AllIds() []string
|
||||||
|
|
||||||
Init(objectIds []string)
|
Init(objectIds []string)
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
@ -37,7 +38,7 @@ func NewDiffService(
|
|||||||
syncPeriod int,
|
syncPeriod int,
|
||||||
storage storage.SpaceStorage,
|
storage storage.SpaceStorage,
|
||||||
confConnector nodeconf.ConfConnector,
|
confConnector nodeconf.ConfConnector,
|
||||||
cache cache.TreeCache,
|
cache treegetter.TreeGetter,
|
||||||
log *zap.Logger) DiffService {
|
log *zap.Logger) DiffService {
|
||||||
|
|
||||||
diff := ldiff.New(16, 16)
|
diff := ldiff.New(16, 16)
|
||||||
@ -72,6 +73,10 @@ func (d *diffService) UpdateHeads(id string, heads []string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *diffService) AllIds() []string {
|
||||||
|
return d.diff.Ids()
|
||||||
|
}
|
||||||
|
|
||||||
func (d *diffService) RemoveObject(id string) {
|
func (d *diffService) RemoveObject(id string) {
|
||||||
// TODO: add space document to remove ids
|
// TODO: add space document to remove ids
|
||||||
d.diff.RemoveId(id)
|
d.diff.RemoveId(id)
|
||||||
|
|||||||
@ -2,10 +2,10 @@ package diffservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/remotediff"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/remotediff"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpcerr"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpcerr"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
@ -22,7 +22,7 @@ func newDiffSyncer(
|
|||||||
spaceId string,
|
spaceId string,
|
||||||
diff ldiff.Diff,
|
diff ldiff.Diff,
|
||||||
confConnector nodeconf.ConfConnector,
|
confConnector nodeconf.ConfConnector,
|
||||||
cache cache.TreeCache,
|
cache treegetter.TreeGetter,
|
||||||
storage storage.SpaceStorage,
|
storage storage.SpaceStorage,
|
||||||
clientFactory spacesyncproto.ClientFactory,
|
clientFactory spacesyncproto.ClientFactory,
|
||||||
log *zap.Logger) DiffSyncer {
|
log *zap.Logger) DiffSyncer {
|
||||||
@ -41,7 +41,7 @@ type diffSyncer struct {
|
|||||||
spaceId string
|
spaceId string
|
||||||
diff ldiff.Diff
|
diff ldiff.Diff
|
||||||
confConnector nodeconf.ConfConnector
|
confConnector nodeconf.ConfConnector
|
||||||
cache cache.TreeCache
|
cache treegetter.TreeGetter
|
||||||
storage storage.SpaceStorage
|
storage storage.SpaceStorage
|
||||||
clientFactory spacesyncproto.ClientFactory
|
clientFactory spacesyncproto.ClientFactory
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
@ -77,6 +77,7 @@ func (d *diffSyncer) syncWithPeer(ctx context.Context, p peer.Peer) (err error)
|
|||||||
|
|
||||||
d.pingTreesInCache(ctx, newIds)
|
d.pingTreesInCache(ctx, newIds)
|
||||||
d.pingTreesInCache(ctx, changedIds)
|
d.pingTreesInCache(ctx, changedIds)
|
||||||
|
d.pingTreesInCache(ctx, removedIds)
|
||||||
|
|
||||||
d.log.Info("sync done:", zap.Int("newIds", len(newIds)),
|
d.log.Info("sync done:", zap.Int("newIds", len(newIds)),
|
||||||
zap.Int("changedIds", len(changedIds)),
|
zap.Int("changedIds", len(changedIds)),
|
||||||
@ -107,8 +108,9 @@ func (d *diffSyncer) sendPushSpaceRequest(ctx context.Context, cl spacesyncproto
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = cl.PushSpace(ctx, &spacesyncproto.PushSpaceRequest{
|
_, err = cl.PushSpace(ctx, &spacesyncproto.PushSpaceRequest{
|
||||||
SpaceHeader: header,
|
SpaceHeader: header,
|
||||||
AclRoot: root,
|
AclPayload: root.Payload,
|
||||||
|
AclPayloadId: root.Id,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache/mock_cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/remotediff"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/remotediff"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto/mock_spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto/mock_spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage/mock_storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage/mock_storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter/mock_treegetter"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf/mock_nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf/mock_nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
||||||
@ -24,7 +23,7 @@ import (
|
|||||||
|
|
||||||
type pushSpaceRequestMatcher struct {
|
type pushSpaceRequestMatcher struct {
|
||||||
spaceId string
|
spaceId string
|
||||||
aclRoot *aclrecordproto.RawACLRecordWithId
|
aclRootId string
|
||||||
spaceHeader *spacesyncproto.RawSpaceHeaderWithId
|
spaceHeader *spacesyncproto.RawSpaceHeaderWithId
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ func (p pushSpaceRequestMatcher) Matches(x interface{}) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.AclRoot == p.aclRoot && res.SpaceHeader == p.spaceHeader
|
return res.AclPayloadId == p.aclRootId && res.SpaceHeader == p.spaceHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pushSpaceRequestMatcher) String() string {
|
func (p pushSpaceRequestMatcher) String() string {
|
||||||
@ -72,11 +71,11 @@ func (m mockPeer) NewStream(ctx context.Context, rpc string, enc drpc.Encoding)
|
|||||||
|
|
||||||
func newPushSpaceRequestMatcher(
|
func newPushSpaceRequestMatcher(
|
||||||
spaceId string,
|
spaceId string,
|
||||||
aclRoot *aclrecordproto.RawACLRecordWithId,
|
aclRootId string,
|
||||||
spaceHeader *spacesyncproto.RawSpaceHeaderWithId) *pushSpaceRequestMatcher {
|
spaceHeader *spacesyncproto.RawSpaceHeaderWithId) *pushSpaceRequestMatcher {
|
||||||
return &pushSpaceRequestMatcher{
|
return &pushSpaceRequestMatcher{
|
||||||
spaceId: spaceId,
|
spaceId: spaceId,
|
||||||
aclRoot: aclRoot,
|
aclRootId: aclRootId,
|
||||||
spaceHeader: spaceHeader,
|
spaceHeader: spaceHeader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,13 +88,14 @@ func TestDiffSyncer_Sync(t *testing.T) {
|
|||||||
|
|
||||||
diffMock := mock_ldiff.NewMockDiff(ctrl)
|
diffMock := mock_ldiff.NewMockDiff(ctrl)
|
||||||
connectorMock := mock_nodeconf.NewMockConfConnector(ctrl)
|
connectorMock := mock_nodeconf.NewMockConfConnector(ctrl)
|
||||||
cacheMock := mock_cache.NewMockTreeCache(ctrl)
|
cacheMock := mock_treegetter.NewMockTreeGetter(ctrl)
|
||||||
stMock := mock_storage.NewMockSpaceStorage(ctrl)
|
stMock := mock_storage.NewMockSpaceStorage(ctrl)
|
||||||
clientMock := mock_spacesyncproto.NewMockDRPCSpaceClient(ctrl)
|
clientMock := mock_spacesyncproto.NewMockDRPCSpaceClient(ctrl)
|
||||||
factory := spacesyncproto.ClientFactoryFunc(func(cc drpc.Conn) spacesyncproto.DRPCSpaceClient {
|
factory := spacesyncproto.ClientFactoryFunc(func(cc drpc.Conn) spacesyncproto.DRPCSpaceClient {
|
||||||
return clientMock
|
return clientMock
|
||||||
})
|
})
|
||||||
spaceId := "spaceId"
|
spaceId := "spaceId"
|
||||||
|
aclRootId := "aclRootId"
|
||||||
l := logger.NewNamed(spaceId)
|
l := logger.NewNamed(spaceId)
|
||||||
diffSyncer := newDiffSyncer(spaceId, diffMock, connectorMock, cacheMock, stMock, factory, l)
|
diffSyncer := newDiffSyncer(spaceId, diffMock, connectorMock, cacheMock, stMock, factory, l)
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ func TestDiffSyncer_Sync(t *testing.T) {
|
|||||||
for _, arg := range []string{"new", "changed"} {
|
for _, arg := range []string{"new", "changed"} {
|
||||||
cacheMock.EXPECT().
|
cacheMock.EXPECT().
|
||||||
GetTree(gomock.Any(), spaceId, arg).
|
GetTree(gomock.Any(), spaceId, arg).
|
||||||
Return(cache.TreeResult{}, nil)
|
Return(nil, nil)
|
||||||
}
|
}
|
||||||
require.NoError(t, diffSyncer.Sync(ctx))
|
require.NoError(t, diffSyncer.Sync(ctx))
|
||||||
})
|
})
|
||||||
@ -124,7 +124,9 @@ func TestDiffSyncer_Sync(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("diff syncer sync space missing", func(t *testing.T) {
|
t.Run("diff syncer sync space missing", func(t *testing.T) {
|
||||||
aclStorageMock := mock_aclstorage.NewMockListStorage(ctrl)
|
aclStorageMock := mock_aclstorage.NewMockListStorage(ctrl)
|
||||||
aclRoot := &aclrecordproto.RawACLRecordWithId{}
|
aclRoot := &aclrecordproto.RawACLRecordWithId{
|
||||||
|
Id: aclRootId,
|
||||||
|
}
|
||||||
spaceHeader := &spacesyncproto.RawSpaceHeaderWithId{}
|
spaceHeader := &spacesyncproto.RawSpaceHeaderWithId{}
|
||||||
|
|
||||||
connectorMock.EXPECT().
|
connectorMock.EXPECT().
|
||||||
@ -143,7 +145,7 @@ func TestDiffSyncer_Sync(t *testing.T) {
|
|||||||
Root().
|
Root().
|
||||||
Return(aclRoot, nil)
|
Return(aclRoot, nil)
|
||||||
clientMock.EXPECT().
|
clientMock.EXPECT().
|
||||||
PushSpace(gomock.Any(), newPushSpaceRequestMatcher(spaceId, aclRoot, spaceHeader)).
|
PushSpace(gomock.Any(), newPushSpaceRequestMatcher(spaceId, aclRootId, spaceHeader)).
|
||||||
Return(nil, nil)
|
Return(nil, nil)
|
||||||
|
|
||||||
require.NoError(t, diffSyncer.Sync(ctx))
|
require.NoError(t, diffSyncer.Sync(ctx))
|
||||||
|
|||||||
5
common/commonspace/diffservice/headnotifiable.go
Normal file
5
common/commonspace/diffservice/headnotifiable.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package diffservice
|
||||||
|
|
||||||
|
type HeadNotifiable interface {
|
||||||
|
UpdateHeads(id string, heads []string)
|
||||||
|
}
|
||||||
14
common/commonspace/objectgetter/objectgetter.go
Normal file
14
common/commonspace/objectgetter/objectgetter.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package objectgetter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Object interface {
|
||||||
|
synchandler.SyncHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type ObjectGetter interface {
|
||||||
|
GetObject(ctx context.Context, objectId string) (Object, error)
|
||||||
|
}
|
||||||
@ -19,5 +19,5 @@ func (r *rpcHandler) HeadSync(ctx context.Context, req *spacesyncproto.HeadSyncR
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *rpcHandler) Stream(stream spacesyncproto.DRPCSpace_StreamStream) (err error) {
|
func (r *rpcHandler) Stream(stream spacesyncproto.DRPCSpace_StreamStream) (err error) {
|
||||||
return r.s.SyncService().SyncClient().AddAndReadStreamSync(stream)
|
return r.s.SyncService().StreamPool().AddAndReadStreamSync(stream)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,13 @@ package commonspace
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
"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/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
config2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
config2 "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/pool"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
@ -30,17 +31,19 @@ type Service interface {
|
|||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
config config2.Space
|
config config2.Space
|
||||||
|
account account.Service
|
||||||
configurationService nodeconf.Service
|
configurationService nodeconf.Service
|
||||||
storageProvider storage.SpaceStorageProvider
|
storageProvider storage.SpaceStorageProvider
|
||||||
cache cache.TreeCache
|
treeGetter treegetter.TreeGetter
|
||||||
pool pool.Pool
|
pool pool.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Init(a *app.App) (err error) {
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
s.config = a.MustComponent(config2.CName).(*config2.Config).Space
|
s.config = a.MustComponent(config2.CName).(*config2.Config).Space
|
||||||
|
s.account = a.MustComponent(account.CName).(account.Service)
|
||||||
s.storageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
|
s.storageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
|
||||||
s.configurationService = a.MustComponent(nodeconf.CName).(nodeconf.Service)
|
s.configurationService = a.MustComponent(nodeconf.CName).(nodeconf.Service)
|
||||||
s.cache = a.MustComponent(cache.CName).(cache.TreeCache)
|
s.treeGetter = a.MustComponent(treegetter.CName).(treegetter.TreeGetter)
|
||||||
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -84,16 +87,19 @@ func (s *service) GetSpace(ctx context.Context, id string) (Space, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lastConfiguration := s.configurationService.GetLast()
|
lastConfiguration := s.configurationService.GetLast()
|
||||||
confConnector := nodeconf.NewConfConnector(lastConfiguration, s.pool)
|
confConnector := nodeconf.NewConfConnector(lastConfiguration, s.pool)
|
||||||
diffService := diffservice.NewDiffService(id, s.config.SyncPeriod, st, confConnector, s.cache, log)
|
diffService := diffservice.NewDiffService(id, s.config.SyncPeriod, st, confConnector, s.treeGetter, log)
|
||||||
syncService := syncservice.NewSyncService(id, diffService, s.cache, lastConfiguration, confConnector)
|
syncService := syncservice.NewSyncService(id, confConnector)
|
||||||
sp := &space{
|
sp := &space{
|
||||||
id: id,
|
id: id,
|
||||||
syncService: syncService,
|
syncService: syncService,
|
||||||
diffService: diffService,
|
diffService: diffService,
|
||||||
cache: s.cache,
|
cache: s.treeGetter,
|
||||||
storage: st,
|
account: s.account,
|
||||||
|
configuration: lastConfiguration,
|
||||||
|
storage: st,
|
||||||
}
|
}
|
||||||
if err := sp.Init(ctx); err != nil {
|
if err := sp.Init(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -2,22 +2,29 @@ package commonspace
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncacl"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
tree2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
|
||||||
|
"go.uber.org/zap"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrSpaceClosed = errors.New("space is closed")
|
||||||
|
|
||||||
type SpaceCreatePayload struct {
|
type SpaceCreatePayload struct {
|
||||||
// SigningKey is the signing key of the owner
|
// SigningKey is the signing key of the owner
|
||||||
SigningKey signingkey.PrivKey
|
SigningKey signingkey.PrivKey
|
||||||
@ -44,12 +51,13 @@ func NewSpaceId(id string, repKey uint64) string {
|
|||||||
|
|
||||||
type Space interface {
|
type Space interface {
|
||||||
Id() string
|
Id() string
|
||||||
|
StoredIds() []string
|
||||||
|
|
||||||
SpaceSyncRpc() RpcHandler
|
SpaceSyncRpc() RpcHandler
|
||||||
|
|
||||||
DeriveTree(ctx context.Context, payload tree2.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tree2.ObjectTree, error)
|
DeriveTree(ctx context.Context, payload tree.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tree.ObjectTree, error)
|
||||||
CreateTree(ctx context.Context, payload tree2.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tree2.ObjectTree, error)
|
CreateTree(ctx context.Context, payload tree.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tree.ObjectTree, error)
|
||||||
BuildTree(ctx context.Context, id string, listener updatelistener.UpdateListener) (tree2.ObjectTree, error)
|
BuildTree(ctx context.Context, id string, listener updatelistener.UpdateListener) (tree.ObjectTree, error)
|
||||||
|
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
@ -60,11 +68,19 @@ type space struct {
|
|||||||
|
|
||||||
rpc *rpcHandler
|
rpc *rpcHandler
|
||||||
|
|
||||||
syncService syncservice.SyncService
|
syncService syncservice.SyncService
|
||||||
diffService diffservice.DiffService
|
diffService diffservice.DiffService
|
||||||
storage storage.SpaceStorage
|
storage storage.SpaceStorage
|
||||||
cache cache.TreeCache
|
cache treegetter.TreeGetter
|
||||||
aclList list.ACLList
|
account account.Service
|
||||||
|
aclList *syncacl.SyncACL
|
||||||
|
configuration nodeconf.Configuration
|
||||||
|
|
||||||
|
isClosed atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *space) LastUsage() time.Time {
|
||||||
|
return s.syncService.LastUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) Id() string {
|
func (s *space) Id() string {
|
||||||
@ -77,8 +93,18 @@ func (s *space) Init(ctx context.Context) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
aclStorage, err := s.storage.ACLStorage()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
aclList, err := list.BuildACLListWithIdentity(s.account.Account(), aclStorage)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.aclList = syncacl.NewSyncACL(aclList, s.syncService.StreamPool())
|
||||||
|
objectGetter := newCommonSpaceGetter(s.id, s.aclList, s.cache)
|
||||||
|
s.syncService.Init(objectGetter)
|
||||||
s.diffService.Init(initialIds)
|
s.diffService.Init(initialIds)
|
||||||
s.syncService.Init()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,62 +120,69 @@ func (s *space) DiffService() diffservice.DiffService {
|
|||||||
return s.diffService
|
return s.diffService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) DeriveTree(ctx context.Context, payload tree2.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tree2.ObjectTree, error) {
|
func (s *space) StoredIds() []string {
|
||||||
return synctree.DeriveSyncTree(ctx, payload, s.syncService.SyncClient(), listener, s.aclList, s.storage.CreateTreeStorage)
|
return s.diffService.AllIds()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) CreateTree(ctx context.Context, payload tree2.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tree2.ObjectTree, error) {
|
func (s *space) DeriveTree(ctx context.Context, payload tree.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tr tree.ObjectTree, err error) {
|
||||||
return synctree.CreateSyncTree(ctx, payload, s.syncService.SyncClient(), listener, s.aclList, s.storage.CreateTreeStorage)
|
if s.isClosed.Load() {
|
||||||
}
|
err = ErrSpaceClosed
|
||||||
|
|
||||||
func (s *space) BuildTree(ctx context.Context, id string, listener updatelistener.UpdateListener) (t tree2.ObjectTree, err error) {
|
|
||||||
getTreeRemote := func() (*spacesyncproto.ObjectSyncMessage, error) {
|
|
||||||
// TODO: add empty context handling (when this is not happening due to head update)
|
|
||||||
peerId, err := syncservice.GetPeerIdFromStreamContext(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.syncService.SyncClient().SendSync(
|
|
||||||
peerId,
|
|
||||||
s.syncService.SyncClient().CreateNewTreeRequest(id),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
store, err := s.storage.TreeStorage(id)
|
|
||||||
if err != nil && err != storage2.ErrUnknownTreeId {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
deps := synctree.CreateDeps{
|
||||||
if err == storage2.ErrUnknownTreeId {
|
SpaceId: s.id,
|
||||||
var resp *spacesyncproto.ObjectSyncMessage
|
Payload: payload,
|
||||||
resp, err = getTreeRemote()
|
StreamPool: s.syncService.StreamPool(),
|
||||||
if err != nil {
|
Configuration: s.configuration,
|
||||||
return
|
HeadNotifiable: s.diffService,
|
||||||
}
|
Listener: listener,
|
||||||
fullSyncResp := resp.GetContent().GetFullSyncResponse()
|
AclList: s.aclList,
|
||||||
|
CreateStorage: s.storage.CreateTreeStorage,
|
||||||
payload := storage2.TreeStorageCreatePayload{
|
|
||||||
TreeId: resp.TreeId,
|
|
||||||
RootRawChange: resp.RootChange,
|
|
||||||
Changes: fullSyncResp.Changes,
|
|
||||||
Heads: fullSyncResp.Heads,
|
|
||||||
}
|
|
||||||
|
|
||||||
// basically building tree with inmemory storage and validating that it was without errors
|
|
||||||
err = tree2.ValidateRawTree(payload, s.aclList)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// now we are sure that we can save it to the storage
|
|
||||||
store, err = s.storage.CreateTreeStorage(payload)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return synctree.BuildSyncTree(ctx, s.syncService.SyncClient(), store.(storage2.TreeStorage), listener, s.aclList)
|
return synctree.DeriveSyncTree(ctx, deps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *space) CreateTree(ctx context.Context, payload tree.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tr tree.ObjectTree, err error) {
|
||||||
|
if s.isClosed.Load() {
|
||||||
|
err = ErrSpaceClosed
|
||||||
|
return
|
||||||
|
}
|
||||||
|
deps := synctree.CreateDeps{
|
||||||
|
SpaceId: s.id,
|
||||||
|
Payload: payload,
|
||||||
|
StreamPool: s.syncService.StreamPool(),
|
||||||
|
Configuration: s.configuration,
|
||||||
|
HeadNotifiable: s.diffService,
|
||||||
|
Listener: listener,
|
||||||
|
AclList: s.aclList,
|
||||||
|
CreateStorage: s.storage.CreateTreeStorage,
|
||||||
|
}
|
||||||
|
return synctree.CreateSyncTree(ctx, deps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *space) BuildTree(ctx context.Context, id string, listener updatelistener.UpdateListener) (t tree.ObjectTree, err error) {
|
||||||
|
if s.isClosed.Load() {
|
||||||
|
err = ErrSpaceClosed
|
||||||
|
return
|
||||||
|
}
|
||||||
|
deps := synctree.BuildDeps{
|
||||||
|
SpaceId: s.id,
|
||||||
|
StreamPool: s.syncService.StreamPool(),
|
||||||
|
Configuration: s.configuration,
|
||||||
|
HeadNotifiable: s.diffService,
|
||||||
|
Listener: listener,
|
||||||
|
AclList: s.aclList,
|
||||||
|
SpaceStorage: s.storage,
|
||||||
|
}
|
||||||
|
return synctree.BuildSyncTreeOrGetRemote(ctx, id, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) Close() error {
|
func (s *space) Close() error {
|
||||||
|
log.With(zap.String("id", s.id)).Debug("space is closing")
|
||||||
|
defer func() {
|
||||||
|
s.isClosed.Store(true)
|
||||||
|
log.With(zap.String("id", s.id)).Debug("space closed")
|
||||||
|
}()
|
||||||
s.diffService.Close()
|
s.diffService.Close()
|
||||||
s.syncService.Close()
|
s.syncService.Close()
|
||||||
return s.storage.Close()
|
return s.storage.Close()
|
||||||
|
|||||||
@ -2,8 +2,6 @@ syntax = "proto3";
|
|||||||
package anySpace;
|
package anySpace;
|
||||||
|
|
||||||
option go_package = "commonspace/spacesyncproto";
|
option go_package = "commonspace/spacesyncproto";
|
||||||
import "pkg/acl/treechangeproto/protos/treechange.proto";
|
|
||||||
import "pkg/acl/aclrecordproto/protos/aclrecord.proto";
|
|
||||||
|
|
||||||
enum ErrCodes {
|
enum ErrCodes {
|
||||||
Unexpected = 0;
|
Unexpected = 0;
|
||||||
@ -55,55 +53,18 @@ message HeadSyncResponse {
|
|||||||
// ObjectSyncMessage is a message sent on object sync
|
// ObjectSyncMessage is a message sent on object sync
|
||||||
message ObjectSyncMessage {
|
message ObjectSyncMessage {
|
||||||
string spaceId = 1;
|
string spaceId = 1;
|
||||||
ObjectSyncContentValue content = 2;
|
string replyId = 2;
|
||||||
treechange.RawTreeChangeWithId rootChange = 3;
|
bytes payload = 3;
|
||||||
string treeId = 4;
|
string objectId = 4;
|
||||||
string trackingId = 5;
|
|
||||||
|
|
||||||
// string identity = 5;
|
// string identity = 5;
|
||||||
// string peerSignature = 6;
|
// string peerSignature = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectSyncContentValue provides different types for object sync
|
|
||||||
message ObjectSyncContentValue {
|
|
||||||
oneof value {
|
|
||||||
ObjectHeadUpdate headUpdate = 1;
|
|
||||||
ObjectFullSyncRequest fullSyncRequest = 2;
|
|
||||||
ObjectFullSyncResponse fullSyncResponse = 3;
|
|
||||||
ObjectErrorResponse errorResponse = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectHeadUpdate is a message sent on document head update
|
|
||||||
message ObjectHeadUpdate {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated treechange.RawTreeChangeWithId changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectHeadUpdate is a message sent when document needs full sync
|
|
||||||
message ObjectFullSyncRequest {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated treechange.RawTreeChangeWithId changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
|
||||||
message ObjectFullSyncResponse {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated treechange.RawTreeChangeWithId changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectErrorResponse is an error sent as a response for a full sync request
|
|
||||||
message ObjectErrorResponse {
|
|
||||||
string error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PushSpaceRequest is a request to add space on a node containing only one acl record
|
// PushSpaceRequest is a request to add space on a node containing only one acl record
|
||||||
message PushSpaceRequest {
|
message PushSpaceRequest {
|
||||||
RawSpaceHeaderWithId spaceHeader = 2;
|
RawSpaceHeaderWithId spaceHeader = 1;
|
||||||
aclrecord.RawACLRecordWithId aclRoot = 3;
|
bytes aclPayload = 2;
|
||||||
|
string aclPayloadId = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushSpaceResponse is an empty response
|
// PushSpaceResponse is an empty response
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
package spacesyncproto
|
package spacesyncproto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
|
||||||
"storj.io/drpc"
|
"storj.io/drpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,43 +16,3 @@ func (c ClientFactoryFunc) Client(cc drpc.Conn) DRPCSpaceClient {
|
|||||||
type ClientFactory interface {
|
type ClientFactory interface {
|
||||||
Client(cc drpc.Conn) DRPCSpaceClient
|
Client(cc drpc.Conn) DRPCSpaceClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapHeadUpdate(update *ObjectHeadUpdate, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_HeadUpdate{HeadUpdate: update},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapFullRequest(request *ObjectFullSyncRequest, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_FullSyncRequest{FullSyncRequest: request},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapFullResponse(response *ObjectFullSyncResponse, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_FullSyncResponse{FullSyncResponse: response},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapError(err error, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_ErrorResponse{ErrorResponse: &ObjectErrorResponse{Error: err.Error()}},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -5,12 +5,12 @@
|
|||||||
package mock_storage
|
package mock_storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
app "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
app "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||||
spacesyncproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
spacesyncproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
|
storage0 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -119,10 +119,10 @@ func (m *MockSpaceStorage) EXPECT() *MockSpaceStorageMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ACLStorage mocks base method.
|
// ACLStorage mocks base method.
|
||||||
func (m *MockSpaceStorage) ACLStorage() (storage2.ListStorage, error) {
|
func (m *MockSpaceStorage) ACLStorage() (storage0.ListStorage, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ACLStorage")
|
ret := m.ctrl.Call(m, "ACLStorage")
|
||||||
ret0, _ := ret[0].(storage2.ListStorage)
|
ret0, _ := ret[0].(storage0.ListStorage)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
@ -148,10 +148,10 @@ func (mr *MockSpaceStorageMockRecorder) Close() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateTreeStorage mocks base method.
|
// CreateTreeStorage mocks base method.
|
||||||
func (m *MockSpaceStorage) CreateTreeStorage(arg0 storage2.TreeStorageCreatePayload) (storage2.TreeStorage, error) {
|
func (m *MockSpaceStorage) CreateTreeStorage(arg0 storage0.TreeStorageCreatePayload) (storage0.TreeStorage, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CreateTreeStorage", arg0)
|
ret := m.ctrl.Call(m, "CreateTreeStorage", arg0)
|
||||||
ret0, _ := ret[0].(storage2.TreeStorage)
|
ret0, _ := ret[0].(storage0.TreeStorage)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
@ -208,10 +208,10 @@ func (mr *MockSpaceStorageMockRecorder) StoredIds() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TreeStorage mocks base method.
|
// TreeStorage mocks base method.
|
||||||
func (m *MockSpaceStorage) TreeStorage(arg0 string) (storage2.TreeStorage, error) {
|
func (m *MockSpaceStorage) TreeStorage(arg0 string) (storage0.TreeStorage, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "TreeStorage", arg0)
|
ret := m.ctrl.Call(m, "TreeStorage", arg0)
|
||||||
ret0, _ := ret[0].(storage2.TreeStorage)
|
ret0, _ := ret[0].(storage0.TreeStorage)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|||||||
21
common/commonspace/syncacl/syncacl.go
Normal file
21
common/commonspace/syncacl/syncacl.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package syncacl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncACL struct {
|
||||||
|
list.ACLList
|
||||||
|
synchandler.SyncHandler
|
||||||
|
streamPool syncservice.StreamPool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncACL(aclList list.ACLList, streamPool syncservice.StreamPool) *SyncACL {
|
||||||
|
return &SyncACL{
|
||||||
|
ACLList: aclList,
|
||||||
|
SyncHandler: nil,
|
||||||
|
streamPool: streamPool,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,206 +0,0 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
|
||||||
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice (interfaces: SyncClient)
|
|
||||||
|
|
||||||
// Package mock_syncservice is a generated GoMock package.
|
|
||||||
package mock_syncservice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
|
||||||
reflect "reflect"
|
|
||||||
|
|
||||||
spacesyncproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MockSyncClient is a mock of SyncClient interface.
|
|
||||||
type MockSyncClient struct {
|
|
||||||
ctrl *gomock.Controller
|
|
||||||
recorder *MockSyncClientMockRecorder
|
|
||||||
}
|
|
||||||
|
|
||||||
// MockSyncClientMockRecorder is the mock recorder for MockSyncClient.
|
|
||||||
type MockSyncClientMockRecorder struct {
|
|
||||||
mock *MockSyncClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMockSyncClient creates a new mock instance.
|
|
||||||
func NewMockSyncClient(ctrl *gomock.Controller) *MockSyncClient {
|
|
||||||
mock := &MockSyncClient{ctrl: ctrl}
|
|
||||||
mock.recorder = &MockSyncClientMockRecorder{mock}
|
|
||||||
return mock
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
|
||||||
func (m *MockSyncClient) EXPECT() *MockSyncClientMockRecorder {
|
|
||||||
return m.recorder
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAndReadStreamAsync mocks base method.
|
|
||||||
func (m *MockSyncClient) AddAndReadStreamAsync(arg0 spacesyncproto.DRPCSpace_StreamStream) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
m.ctrl.Call(m, "AddAndReadStreamAsync", arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAndReadStreamAsync indicates an expected call of AddAndReadStreamAsync.
|
|
||||||
func (mr *MockSyncClientMockRecorder) AddAndReadStreamAsync(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAndReadStreamAsync", reflect.TypeOf((*MockSyncClient)(nil).AddAndReadStreamAsync), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAndReadStreamSync mocks base method.
|
|
||||||
func (m *MockSyncClient) AddAndReadStreamSync(arg0 spacesyncproto.DRPCSpace_StreamStream) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "AddAndReadStreamSync", arg0)
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAndReadStreamSync indicates an expected call of AddAndReadStreamSync.
|
|
||||||
func (mr *MockSyncClientMockRecorder) AddAndReadStreamSync(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAndReadStreamSync", reflect.TypeOf((*MockSyncClient)(nil).AddAndReadStreamSync), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BroadcastAsync mocks base method.
|
|
||||||
func (m *MockSyncClient) BroadcastAsync(arg0 *spacesyncproto.ObjectSyncMessage) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "BroadcastAsync", arg0)
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// BroadcastAsync indicates an expected call of BroadcastAsync.
|
|
||||||
func (mr *MockSyncClientMockRecorder) BroadcastAsync(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BroadcastAsync", reflect.TypeOf((*MockSyncClient)(nil).BroadcastAsync), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BroadcastAsyncOrSendResponsible mocks base method.
|
|
||||||
func (m *MockSyncClient) BroadcastAsyncOrSendResponsible(arg0 *spacesyncproto.ObjectSyncMessage) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "BroadcastAsyncOrSendResponsible", arg0)
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// BroadcastAsyncOrSendResponsible indicates an expected call of BroadcastAsyncOrSendResponsible.
|
|
||||||
func (mr *MockSyncClientMockRecorder) BroadcastAsyncOrSendResponsible(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BroadcastAsyncOrSendResponsible", reflect.TypeOf((*MockSyncClient)(nil).BroadcastAsyncOrSendResponsible), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close mocks base method.
|
|
||||||
func (m *MockSyncClient) Close() error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "Close")
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close indicates an expected call of Close.
|
|
||||||
func (mr *MockSyncClientMockRecorder) Close() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSyncClient)(nil).Close))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFullSyncRequest mocks base method.
|
|
||||||
func (m *MockSyncClient) CreateFullSyncRequest(arg0 tree.ObjectTree, arg1, arg2 []string, arg3 string) (*spacesyncproto.ObjectSyncMessage, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "CreateFullSyncRequest", arg0, arg1, arg2, arg3)
|
|
||||||
ret0, _ := ret[0].(*spacesyncproto.ObjectSyncMessage)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFullSyncRequest indicates an expected call of CreateFullSyncRequest.
|
|
||||||
func (mr *MockSyncClientMockRecorder) CreateFullSyncRequest(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFullSyncRequest", reflect.TypeOf((*MockSyncClient)(nil).CreateFullSyncRequest), arg0, arg1, arg2, arg3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFullSyncResponse mocks base method.
|
|
||||||
func (m *MockSyncClient) CreateFullSyncResponse(arg0 tree.ObjectTree, arg1, arg2 []string, arg3 string) (*spacesyncproto.ObjectSyncMessage, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "CreateFullSyncResponse", arg0, arg1, arg2, arg3)
|
|
||||||
ret0, _ := ret[0].(*spacesyncproto.ObjectSyncMessage)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFullSyncResponse indicates an expected call of CreateFullSyncResponse.
|
|
||||||
func (mr *MockSyncClientMockRecorder) CreateFullSyncResponse(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFullSyncResponse", reflect.TypeOf((*MockSyncClient)(nil).CreateFullSyncResponse), arg0, arg1, arg2, arg3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateHeadUpdate mocks base method.
|
|
||||||
func (m *MockSyncClient) CreateHeadUpdate(arg0 tree.ObjectTree, arg1 []*treechangeproto.RawTreeChangeWithId) *spacesyncproto.ObjectSyncMessage {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "CreateHeadUpdate", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(*spacesyncproto.ObjectSyncMessage)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateHeadUpdate indicates an expected call of CreateHeadUpdate.
|
|
||||||
func (mr *MockSyncClientMockRecorder) CreateHeadUpdate(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateHeadUpdate", reflect.TypeOf((*MockSyncClient)(nil).CreateHeadUpdate), arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewTreeRequest mocks base method.
|
|
||||||
func (m *MockSyncClient) CreateNewTreeRequest(arg0 string) *spacesyncproto.ObjectSyncMessage {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "CreateNewTreeRequest", arg0)
|
|
||||||
ret0, _ := ret[0].(*spacesyncproto.ObjectSyncMessage)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewTreeRequest indicates an expected call of CreateNewTreeRequest.
|
|
||||||
func (mr *MockSyncClientMockRecorder) CreateNewTreeRequest(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNewTreeRequest", reflect.TypeOf((*MockSyncClient)(nil).CreateNewTreeRequest), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasActiveStream mocks base method.
|
|
||||||
func (m *MockSyncClient) HasActiveStream(arg0 string) bool {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "HasActiveStream", arg0)
|
|
||||||
ret0, _ := ret[0].(bool)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasActiveStream indicates an expected call of HasActiveStream.
|
|
||||||
func (mr *MockSyncClientMockRecorder) HasActiveStream(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasActiveStream", reflect.TypeOf((*MockSyncClient)(nil).HasActiveStream), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendAsync mocks base method.
|
|
||||||
func (m *MockSyncClient) SendAsync(arg0 []string, arg1 *spacesyncproto.ObjectSyncMessage) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "SendAsync", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendAsync indicates an expected call of SendAsync.
|
|
||||||
func (mr *MockSyncClientMockRecorder) SendAsync(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendAsync", reflect.TypeOf((*MockSyncClient)(nil).SendAsync), arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendSync mocks base method.
|
|
||||||
func (m *MockSyncClient) SendSync(arg0 string, arg1 *spacesyncproto.ObjectSyncMessage) (*spacesyncproto.ObjectSyncMessage, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "SendSync", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(*spacesyncproto.ObjectSyncMessage)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendSync indicates an expected call of SendSync.
|
|
||||||
func (mr *MockSyncClientMockRecorder) SendSync(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendSync", reflect.TypeOf((*MockSyncClient)(nil).SendSync), arg0, arg1)
|
|
||||||
}
|
|
||||||
@ -5,30 +5,34 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||||
"github.com/libp2p/go-libp2p/core/sec"
|
"github.com/libp2p/go-libp2p/core/sec"
|
||||||
"storj.io/drpc/drpcctx"
|
"storj.io/drpc/drpcctx"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrEmptyPeer = errors.New("don't have such a peer")
|
var ErrEmptyPeer = errors.New("don't have such a peer")
|
||||||
var ErrStreamClosed = errors.New("stream is already closed")
|
var ErrStreamClosed = errors.New("stream is already closed")
|
||||||
|
|
||||||
const maxSimultaneousOperationsPerStream = 10
|
var maxSimultaneousOperationsPerStream = 10
|
||||||
|
var syncWaitPeriod = 2 * time.Second
|
||||||
|
|
||||||
|
var ErrSyncTimeout = errors.New("too long wait on sync receive")
|
||||||
|
|
||||||
// StreamPool can be made generic to work with different streams
|
// StreamPool can be made generic to work with different streams
|
||||||
type StreamPool interface {
|
type StreamPool interface {
|
||||||
Sender
|
ocache.ObjectLastUsage
|
||||||
AddAndReadStreamSync(stream spacesyncproto.SpaceStream) (err error)
|
AddAndReadStreamSync(stream spacesyncproto.SpaceStream) (err error)
|
||||||
AddAndReadStreamAsync(stream spacesyncproto.SpaceStream)
|
AddAndReadStreamAsync(stream spacesyncproto.SpaceStream)
|
||||||
HasActiveStream(peerId string) bool
|
|
||||||
Close() (err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sender interface {
|
|
||||||
SendSync(peerId string, message *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error)
|
SendSync(peerId string, message *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error)
|
||||||
SendAsync(peers []string, message *spacesyncproto.ObjectSyncMessage) (err error)
|
SendAsync(peers []string, message *spacesyncproto.ObjectSyncMessage) (err error)
|
||||||
BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error)
|
BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error)
|
||||||
|
|
||||||
|
HasActiveStream(peerId string) bool
|
||||||
|
Close() (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageHandler func(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error)
|
type MessageHandler func(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error)
|
||||||
@ -44,15 +48,23 @@ type streamPool struct {
|
|||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
waiters map[string]responseWaiter
|
waiters map[string]responseWaiter
|
||||||
waitersMx sync.Mutex
|
waitersMx sync.Mutex
|
||||||
counter uint64
|
counter atomic.Uint64
|
||||||
|
lastUsage atomic.Int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStreamPool(messageHandler MessageHandler) StreamPool {
|
func newStreamPool(messageHandler MessageHandler) StreamPool {
|
||||||
return &streamPool{
|
s := &streamPool{
|
||||||
peerStreams: make(map[string]spacesyncproto.SpaceStream),
|
peerStreams: make(map[string]spacesyncproto.SpaceStream),
|
||||||
messageHandler: messageHandler,
|
messageHandler: messageHandler,
|
||||||
|
waiters: make(map[string]responseWaiter),
|
||||||
wg: &sync.WaitGroup{},
|
wg: &sync.WaitGroup{},
|
||||||
}
|
}
|
||||||
|
s.lastUsage.Store(time.Now().Unix())
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *streamPool) LastUsage() time.Time {
|
||||||
|
return time.Unix(s.lastUsage.Load(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *streamPool) HasActiveStream(peerId string) (res bool) {
|
func (s *streamPool) HasActiveStream(peerId string) (res bool) {
|
||||||
@ -65,26 +77,39 @@ func (s *streamPool) HasActiveStream(peerId string) (res bool) {
|
|||||||
func (s *streamPool) SendSync(
|
func (s *streamPool) SendSync(
|
||||||
peerId string,
|
peerId string,
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error) {
|
msg *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error) {
|
||||||
newCounter := atomic.AddUint64(&s.counter, 1)
|
newCounter := s.counter.Add(1)
|
||||||
msg.TrackingId = genStreamPoolKey(peerId, msg.TreeId, newCounter)
|
msg.ReplyId = genStreamPoolKey(peerId, msg.ObjectId, newCounter)
|
||||||
|
|
||||||
s.waitersMx.Lock()
|
s.waitersMx.Lock()
|
||||||
waiter := responseWaiter{
|
waiter := responseWaiter{
|
||||||
ch: make(chan *spacesyncproto.ObjectSyncMessage),
|
ch: make(chan *spacesyncproto.ObjectSyncMessage, 1),
|
||||||
}
|
}
|
||||||
s.waiters[msg.TrackingId] = waiter
|
s.waiters[msg.ReplyId] = waiter
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
|
|
||||||
err = s.SendAsync([]string{peerId}, msg)
|
err = s.SendAsync([]string{peerId}, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
delay := time.NewTimer(syncWaitPeriod)
|
||||||
|
select {
|
||||||
|
case <-delay.C:
|
||||||
|
s.waitersMx.Lock()
|
||||||
|
delete(s.waiters, msg.ReplyId)
|
||||||
|
s.waitersMx.Unlock()
|
||||||
|
|
||||||
reply = <-waiter.ch
|
log.With("replyId", msg.ReplyId).Error("time elapsed when waiting")
|
||||||
|
err = ErrSyncTimeout
|
||||||
|
case reply = <-waiter.ch:
|
||||||
|
if !delay.Stop() {
|
||||||
|
<-delay.C
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *streamPool) SendAsync(peers []string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
func (s *streamPool) SendAsync(peers []string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
|
s.lastUsage.Store(time.Now().Unix())
|
||||||
getStreams := func() (streams []spacesyncproto.SpaceStream) {
|
getStreams := func() (streams []spacesyncproto.SpaceStream) {
|
||||||
for _, pId := range peers {
|
for _, pId := range peers {
|
||||||
stream, err := s.getOrDeleteStream(pId)
|
stream, err := s.getOrDeleteStream(pId)
|
||||||
@ -100,10 +125,13 @@ func (s *streamPool) SendAsync(peers []string, message *spacesyncproto.ObjectSyn
|
|||||||
streams := getStreams()
|
streams := getStreams()
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
|
log.With("objectId", message.ObjectId).
|
||||||
|
Debugf("sending message to %d peers", len(streams))
|
||||||
for _, s := range streams {
|
for _, s := range streams {
|
||||||
if len(peers) == 1 {
|
err = s.Send(message)
|
||||||
err = s.Send(message)
|
}
|
||||||
}
|
if len(peers) != 1 {
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -145,6 +173,8 @@ Loop:
|
|||||||
|
|
||||||
func (s *streamPool) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
func (s *streamPool) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
streams := s.getAllStreams()
|
streams := s.getAllStreams()
|
||||||
|
log.With("objectId", message.ObjectId).
|
||||||
|
Debugf("broadcasting message to %d peers", len(streams))
|
||||||
for _, stream := range streams {
|
for _, stream := range streams {
|
||||||
if err = stream.Send(message); err != nil {
|
if err = stream.Send(message); err != nil {
|
||||||
// TODO: add logging
|
// TODO: add logging
|
||||||
@ -191,21 +221,24 @@ func (s *streamPool) readPeerLoop(peerId string, stream spacesyncproto.SpaceStre
|
|||||||
}
|
}
|
||||||
|
|
||||||
process := func(msg *spacesyncproto.ObjectSyncMessage) {
|
process := func(msg *spacesyncproto.ObjectSyncMessage) {
|
||||||
if msg.TrackingId == "" {
|
s.lastUsage.Store(time.Now().Unix())
|
||||||
|
if msg.ReplyId == "" {
|
||||||
s.messageHandler(stream.Context(), peerId, msg)
|
s.messageHandler(stream.Context(), peerId, msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.With("replyId", msg.ReplyId).Debug("getting message with reply id")
|
||||||
s.waitersMx.Lock()
|
s.waitersMx.Lock()
|
||||||
waiter, exists := s.waiters[msg.TrackingId]
|
waiter, exists := s.waiters[msg.ReplyId]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
|
log.With("replyId", msg.ReplyId).Debug("reply id not exists")
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
s.messageHandler(stream.Context(), peerId, msg)
|
s.messageHandler(stream.Context(), peerId, msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.With("replyId", msg.ReplyId).Debug("reply id exists")
|
||||||
|
|
||||||
delete(s.waiters, msg.TrackingId)
|
delete(s.waiters, msg.ReplyId)
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
waiter.ch <- msg
|
waiter.ch <- msg
|
||||||
}
|
}
|
||||||
@ -213,6 +246,7 @@ func (s *streamPool) readPeerLoop(peerId string, stream spacesyncproto.SpaceStre
|
|||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
msg, err := stream.Recv()
|
msg, err := stream.Recv()
|
||||||
|
s.lastUsage.Store(time.Now().Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
package syncservice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SyncClient interface {
|
|
||||||
StreamPool
|
|
||||||
RequestFactory
|
|
||||||
BroadcastAsyncOrSendResponsible(message *spacesyncproto.ObjectSyncMessage) (err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncClient struct {
|
|
||||||
StreamPool
|
|
||||||
RequestFactory
|
|
||||||
spaceId string
|
|
||||||
notifiable HeadNotifiable
|
|
||||||
configuration nodeconf.Configuration
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSyncClient(spaceId string, pool StreamPool, notifiable HeadNotifiable, factory RequestFactory, configuration nodeconf.Configuration) SyncClient {
|
|
||||||
return &syncClient{
|
|
||||||
StreamPool: pool,
|
|
||||||
RequestFactory: factory,
|
|
||||||
notifiable: notifiable,
|
|
||||||
configuration: configuration,
|
|
||||||
spaceId: spaceId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncClient) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
|
||||||
s.notifyIfNeeded(message)
|
|
||||||
return s.BroadcastAsync(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncClient) BroadcastAsyncOrSendResponsible(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
|
||||||
if s.configuration.IsResponsible(s.spaceId) {
|
|
||||||
return s.SendAsync(s.configuration.NodeIds(s.spaceId), message)
|
|
||||||
}
|
|
||||||
return s.BroadcastAsync(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncClient) notifyIfNeeded(message *spacesyncproto.ObjectSyncMessage) {
|
|
||||||
if message.GetContent().GetHeadUpdate() != nil {
|
|
||||||
update := message.GetContent().GetHeadUpdate()
|
|
||||||
s.notifiable.UpdateHeads(message.TreeId, update.Heads)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,172 +0,0 @@
|
|||||||
package syncservice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
|
||||||
)
|
|
||||||
|
|
||||||
type syncHandler struct {
|
|
||||||
spaceId string
|
|
||||||
treeCache cache.TreeCache
|
|
||||||
syncClient SyncClient
|
|
||||||
}
|
|
||||||
|
|
||||||
type SyncHandler interface {
|
|
||||||
HandleMessage(ctx context.Context, senderId string, request *spacesyncproto.ObjectSyncMessage) (err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSyncHandler(spaceId string, treeCache cache.TreeCache, syncClient SyncClient) *syncHandler {
|
|
||||||
return &syncHandler{
|
|
||||||
spaceId: spaceId,
|
|
||||||
treeCache: treeCache,
|
|
||||||
syncClient: syncClient,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncHandler) HandleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) error {
|
|
||||||
content := msg.GetContent()
|
|
||||||
switch {
|
|
||||||
case content.GetFullSyncRequest() != nil:
|
|
||||||
return s.handleFullSyncRequest(ctx, senderId, content.GetFullSyncRequest(), msg)
|
|
||||||
case content.GetFullSyncResponse() != nil:
|
|
||||||
return s.handleFullSyncResponse(ctx, senderId, content.GetFullSyncResponse(), msg)
|
|
||||||
case content.GetHeadUpdate() != nil:
|
|
||||||
return s.handleHeadUpdate(ctx, senderId, content.GetHeadUpdate(), msg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncHandler) handleHeadUpdate(
|
|
||||||
ctx context.Context,
|
|
||||||
senderId string,
|
|
||||||
update *spacesyncproto.ObjectHeadUpdate,
|
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
|
||||||
|
|
||||||
var (
|
|
||||||
fullRequest *spacesyncproto.ObjectSyncMessage
|
|
||||||
isEmptyUpdate = len(update.Changes) == 0
|
|
||||||
)
|
|
||||||
res, err := s.treeCache.GetTree(ctx, s.spaceId, msg.TreeId)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = func() error {
|
|
||||||
objTree := res.TreeContainer.Tree()
|
|
||||||
objTree.Lock()
|
|
||||||
defer res.Release()
|
|
||||||
defer objTree.Unlock()
|
|
||||||
|
|
||||||
// isEmptyUpdate is sent when the tree is brought up from cache
|
|
||||||
if isEmptyUpdate {
|
|
||||||
if slice.UnsortedEquals(objTree.Heads(), update.Heads) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// we need to sync in any case
|
|
||||||
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath, msg.TrackingId)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.alreadyHasHeads(objTree, update.Heads) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = objTree.AddRawChanges(ctx, update.Changes...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.alreadyHasHeads(objTree, update.Heads) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath, msg.TrackingId)
|
|
||||||
return err
|
|
||||||
}()
|
|
||||||
|
|
||||||
if fullRequest != nil {
|
|
||||||
return s.syncClient.SendAsync([]string{senderId}, fullRequest)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncHandler) handleFullSyncRequest(
|
|
||||||
ctx context.Context,
|
|
||||||
senderId string,
|
|
||||||
request *spacesyncproto.ObjectFullSyncRequest,
|
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
|
||||||
var (
|
|
||||||
fullResponse *spacesyncproto.ObjectSyncMessage
|
|
||||||
header = msg.RootChange
|
|
||||||
)
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
s.syncClient.SendAsync([]string{senderId}, spacesyncproto.WrapError(err, header, msg.TreeId, msg.TrackingId))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
res, err := s.treeCache.GetTree(ctx, s.spaceId, msg.TreeId)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = func() error {
|
|
||||||
objTree := res.TreeContainer.Tree()
|
|
||||||
objTree.Lock()
|
|
||||||
defer res.Release()
|
|
||||||
defer objTree.Unlock()
|
|
||||||
|
|
||||||
if header == nil {
|
|
||||||
header = objTree.Header()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(request.Changes) != 0 && !s.alreadyHasHeads(objTree, request.Heads) {
|
|
||||||
_, err = objTree.AddRawChanges(ctx, request.Changes...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fullResponse, err = s.syncClient.CreateFullSyncResponse(objTree, request.Heads, request.SnapshotPath, msg.TrackingId)
|
|
||||||
return err
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return s.syncClient.SendAsync([]string{senderId}, fullResponse)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncHandler) handleFullSyncResponse(
|
|
||||||
ctx context.Context,
|
|
||||||
senderId string,
|
|
||||||
response *spacesyncproto.ObjectFullSyncResponse,
|
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
|
||||||
res, err := s.treeCache.GetTree(ctx, s.spaceId, msg.TreeId)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = func() error {
|
|
||||||
objTree := res.TreeContainer.Tree()
|
|
||||||
objTree.Lock()
|
|
||||||
defer res.Release()
|
|
||||||
defer objTree.Unlock()
|
|
||||||
|
|
||||||
if s.alreadyHasHeads(objTree, response.Heads) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = objTree.AddRawChanges(ctx, response.Changes...)
|
|
||||||
return err
|
|
||||||
}()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncHandler) alreadyHasHeads(t tree.ObjectTree, heads []string) bool {
|
|
||||||
return slice.UnsortedEquals(t.Heads(), heads) || t.HasChanges(heads...)
|
|
||||||
}
|
|
||||||
10
common/commonspace/syncservice/synchandler/synchhandler.go
Normal file
10
common/commonspace/syncservice/synchandler/synchhandler.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package synchandler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncHandler interface {
|
||||||
|
HandleMessage(ctx context.Context, senderId string, request *spacesyncproto.ObjectSyncMessage) (err error)
|
||||||
|
}
|
||||||
@ -1,36 +1,36 @@
|
|||||||
//go:generate mockgen -destination mock_syncservice/mock_syncservice.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice SyncClient
|
|
||||||
package syncservice
|
package syncservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/objectgetter"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpcerr"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpcerr"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logger.NewNamed("syncservice").Sugar()
|
var log = logger.NewNamed("syncservice").Sugar()
|
||||||
|
|
||||||
type SyncService interface {
|
type SyncService interface {
|
||||||
SyncClient() SyncClient
|
ocache.ObjectLastUsage
|
||||||
|
synchandler.SyncHandler
|
||||||
|
StreamPool() StreamPool
|
||||||
|
|
||||||
Init()
|
Init(getter objectgetter.ObjectGetter)
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeadNotifiable interface {
|
|
||||||
UpdateHeads(id string, heads []string)
|
|
||||||
}
|
|
||||||
|
|
||||||
const respPeersStreamCheckInterval = time.Second * 10
|
const respPeersStreamCheckInterval = time.Second * 10
|
||||||
|
|
||||||
type syncService struct {
|
type syncService struct {
|
||||||
spaceId string
|
spaceId string
|
||||||
|
|
||||||
syncClient SyncClient
|
streamPool StreamPool
|
||||||
clientFactory spacesyncproto.ClientFactory
|
clientFactory spacesyncproto.ClientFactory
|
||||||
|
objectGetter objectgetter.ObjectGetter
|
||||||
|
|
||||||
streamLoopCtx context.Context
|
streamLoopCtx context.Context
|
||||||
stopStreamLoop context.CancelFunc
|
stopStreamLoop context.CancelFunc
|
||||||
@ -40,31 +40,25 @@ type syncService struct {
|
|||||||
|
|
||||||
func NewSyncService(
|
func NewSyncService(
|
||||||
spaceId string,
|
spaceId string,
|
||||||
headNotifiable HeadNotifiable,
|
confConnector nodeconf.ConfConnector) (syncService SyncService) {
|
||||||
cache cache.TreeCache,
|
|
||||||
configuration nodeconf.Configuration,
|
|
||||||
confConnector nodeconf.ConfConnector) SyncService {
|
|
||||||
var syncHandler SyncHandler
|
|
||||||
streamPool := newStreamPool(func(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
streamPool := newStreamPool(func(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
return syncHandler.HandleMessage(ctx, senderId, message)
|
return syncService.HandleMessage(ctx, senderId, message)
|
||||||
})
|
})
|
||||||
factory := newRequestFactory()
|
syncService = newSyncService(
|
||||||
syncClient := newSyncClient(spaceId, streamPool, headNotifiable, factory, configuration)
|
|
||||||
syncHandler = newSyncHandler(spaceId, cache, syncClient)
|
|
||||||
return newSyncService(
|
|
||||||
spaceId,
|
spaceId,
|
||||||
syncClient,
|
streamPool,
|
||||||
spacesyncproto.ClientFactoryFunc(spacesyncproto.NewDRPCSpaceClient),
|
spacesyncproto.ClientFactoryFunc(spacesyncproto.NewDRPCSpaceClient),
|
||||||
confConnector)
|
confConnector)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSyncService(
|
func newSyncService(
|
||||||
spaceId string,
|
spaceId string,
|
||||||
syncClient SyncClient,
|
streamPool StreamPool,
|
||||||
clientFactory spacesyncproto.ClientFactory,
|
clientFactory spacesyncproto.ClientFactory,
|
||||||
connector nodeconf.ConfConnector) *syncService {
|
connector nodeconf.ConfConnector) *syncService {
|
||||||
return &syncService{
|
return &syncService{
|
||||||
syncClient: syncClient,
|
streamPool: streamPool,
|
||||||
connector: connector,
|
connector: connector,
|
||||||
clientFactory: clientFactory,
|
clientFactory: clientFactory,
|
||||||
spaceId: spaceId,
|
spaceId: spaceId,
|
||||||
@ -72,7 +66,8 @@ func newSyncService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncService) Init() {
|
func (s *syncService) Init(objectGetter objectgetter.ObjectGetter) {
|
||||||
|
s.objectGetter = objectGetter
|
||||||
s.streamLoopCtx, s.stopStreamLoop = context.WithCancel(context.Background())
|
s.streamLoopCtx, s.stopStreamLoop = context.WithCancel(context.Background())
|
||||||
go s.responsibleStreamCheckLoop(s.streamLoopCtx)
|
go s.responsibleStreamCheckLoop(s.streamLoopCtx)
|
||||||
}
|
}
|
||||||
@ -80,7 +75,19 @@ func (s *syncService) Init() {
|
|||||||
func (s *syncService) Close() (err error) {
|
func (s *syncService) Close() (err error) {
|
||||||
s.stopStreamLoop()
|
s.stopStreamLoop()
|
||||||
<-s.streamLoopDone
|
<-s.streamLoopDone
|
||||||
return s.syncClient.Close()
|
return s.streamPool.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncService) LastUsage() time.Time {
|
||||||
|
return s.streamPool.LastUsage()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncService) HandleMessage(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
|
obj, err := s.objectGetter.GetObject(ctx, message.ObjectId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return obj.HandleMessage(ctx, senderId, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
||||||
@ -91,7 +98,7 @@ func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, peer := range respPeers {
|
for _, peer := range respPeers {
|
||||||
if s.syncClient.HasActiveStream(peer.Id()) {
|
if s.streamPool.HasActiveStream(peer.Id()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stream, err := s.clientFactory.Client(peer).Stream(ctx)
|
stream, err := s.clientFactory.Client(peer).Stream(ctx)
|
||||||
@ -109,7 +116,7 @@ func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
|||||||
log.With("spaceId", s.spaceId).Errorf("failed to send first message to stream: %v", err)
|
log.With("spaceId", s.spaceId).Errorf("failed to send first message to stream: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.syncClient.AddAndReadStreamAsync(stream)
|
s.streamPool.AddAndReadStreamAsync(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +133,6 @@ func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncService) SyncClient() SyncClient {
|
func (s *syncService) StreamPool() StreamPool {
|
||||||
return s.syncClient
|
return s.streamPool
|
||||||
}
|
}
|
||||||
|
|||||||
151
common/commonspace/synctree/mock_synctree/mock_synctree.go
Normal file
151
common/commonspace/synctree/mock_synctree/mock_synctree.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree (interfaces: SyncClient)
|
||||||
|
|
||||||
|
// Package mock_synctree is a generated GoMock package.
|
||||||
|
package mock_synctree
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
time "time"
|
||||||
|
|
||||||
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
|
treechangeproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockSyncClient is a mock of SyncClient interface.
|
||||||
|
type MockSyncClient struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockSyncClientMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockSyncClientMockRecorder is the mock recorder for MockSyncClient.
|
||||||
|
type MockSyncClientMockRecorder struct {
|
||||||
|
mock *MockSyncClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockSyncClient creates a new mock instance.
|
||||||
|
func NewMockSyncClient(ctrl *gomock.Controller) *MockSyncClient {
|
||||||
|
mock := &MockSyncClient{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockSyncClientMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockSyncClient) EXPECT() *MockSyncClientMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastAsync mocks base method.
|
||||||
|
func (m *MockSyncClient) BroadcastAsync(arg0 *treechangeproto.TreeSyncMessage) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "BroadcastAsync", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastAsync indicates an expected call of BroadcastAsync.
|
||||||
|
func (mr *MockSyncClientMockRecorder) BroadcastAsync(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BroadcastAsync", reflect.TypeOf((*MockSyncClient)(nil).BroadcastAsync), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastAsyncOrSendResponsible mocks base method.
|
||||||
|
func (m *MockSyncClient) BroadcastAsyncOrSendResponsible(arg0 *treechangeproto.TreeSyncMessage) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "BroadcastAsyncOrSendResponsible", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastAsyncOrSendResponsible indicates an expected call of BroadcastAsyncOrSendResponsible.
|
||||||
|
func (mr *MockSyncClientMockRecorder) BroadcastAsyncOrSendResponsible(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BroadcastAsyncOrSendResponsible", reflect.TypeOf((*MockSyncClient)(nil).BroadcastAsyncOrSendResponsible), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFullSyncRequest mocks base method.
|
||||||
|
func (m *MockSyncClient) CreateFullSyncRequest(arg0 tree.ObjectTree, arg1, arg2 []string) (*treechangeproto.TreeSyncMessage, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CreateFullSyncRequest", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(*treechangeproto.TreeSyncMessage)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFullSyncRequest indicates an expected call of CreateFullSyncRequest.
|
||||||
|
func (mr *MockSyncClientMockRecorder) CreateFullSyncRequest(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFullSyncRequest", reflect.TypeOf((*MockSyncClient)(nil).CreateFullSyncRequest), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFullSyncResponse mocks base method.
|
||||||
|
func (m *MockSyncClient) CreateFullSyncResponse(arg0 tree.ObjectTree, arg1, arg2 []string) (*treechangeproto.TreeSyncMessage, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CreateFullSyncResponse", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(*treechangeproto.TreeSyncMessage)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFullSyncResponse indicates an expected call of CreateFullSyncResponse.
|
||||||
|
func (mr *MockSyncClientMockRecorder) CreateFullSyncResponse(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFullSyncResponse", reflect.TypeOf((*MockSyncClient)(nil).CreateFullSyncResponse), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHeadUpdate mocks base method.
|
||||||
|
func (m *MockSyncClient) CreateHeadUpdate(arg0 tree.ObjectTree, arg1 []*treechangeproto.RawTreeChangeWithId) *treechangeproto.TreeSyncMessage {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CreateHeadUpdate", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(*treechangeproto.TreeSyncMessage)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHeadUpdate indicates an expected call of CreateHeadUpdate.
|
||||||
|
func (mr *MockSyncClientMockRecorder) CreateHeadUpdate(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateHeadUpdate", reflect.TypeOf((*MockSyncClient)(nil).CreateHeadUpdate), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewTreeRequest mocks base method.
|
||||||
|
func (m *MockSyncClient) CreateNewTreeRequest() *treechangeproto.TreeSyncMessage {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CreateNewTreeRequest")
|
||||||
|
ret0, _ := ret[0].(*treechangeproto.TreeSyncMessage)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewTreeRequest indicates an expected call of CreateNewTreeRequest.
|
||||||
|
func (mr *MockSyncClientMockRecorder) CreateNewTreeRequest() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNewTreeRequest", reflect.TypeOf((*MockSyncClient)(nil).CreateNewTreeRequest))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastUsage mocks base method.
|
||||||
|
func (m *MockSyncClient) LastUsage() time.Time {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "LastUsage")
|
||||||
|
ret0, _ := ret[0].(time.Time)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastUsage indicates an expected call of LastUsage.
|
||||||
|
func (mr *MockSyncClientMockRecorder) LastUsage() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastUsage", reflect.TypeOf((*MockSyncClient)(nil).LastUsage))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendAsync mocks base method.
|
||||||
|
func (m *MockSyncClient) SendAsync(arg0 string, arg1 *treechangeproto.TreeSyncMessage, arg2 string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SendAsync", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendAsync indicates an expected call of SendAsync.
|
||||||
|
func (mr *MockSyncClientMockRecorder) SendAsync(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendAsync", reflect.TypeOf((*MockSyncClient)(nil).SendAsync), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
@ -1,40 +1,41 @@
|
|||||||
package syncservice
|
package synctree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestFactory interface {
|
type RequestFactory interface {
|
||||||
CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *spacesyncproto.ObjectSyncMessage)
|
CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *treechangeproto.TreeSyncMessage)
|
||||||
CreateNewTreeRequest(id string) (msg *spacesyncproto.ObjectSyncMessage)
|
CreateNewTreeRequest() (msg *treechangeproto.TreeSyncMessage)
|
||||||
CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (req *spacesyncproto.ObjectSyncMessage, err error)
|
CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (req *treechangeproto.TreeSyncMessage, err error)
|
||||||
CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (*spacesyncproto.ObjectSyncMessage, error)
|
CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (*treechangeproto.TreeSyncMessage, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRequestFactory() RequestFactory {
|
var sharedFactory = &requestFactory{}
|
||||||
return &requestFactory{}
|
|
||||||
|
func GetRequestFactory() RequestFactory {
|
||||||
|
return sharedFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
type requestFactory struct{}
|
type requestFactory struct{}
|
||||||
|
|
||||||
func (r *requestFactory) CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *spacesyncproto.ObjectSyncMessage) {
|
func (r *requestFactory) CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *treechangeproto.TreeSyncMessage) {
|
||||||
return spacesyncproto.WrapHeadUpdate(&spacesyncproto.ObjectHeadUpdate{
|
return treechangeproto.WrapHeadUpdate(&treechangeproto.TreeHeadUpdate{
|
||||||
Heads: t.Heads(),
|
Heads: t.Heads(),
|
||||||
Changes: added,
|
Changes: added,
|
||||||
SnapshotPath: t.SnapshotPath(),
|
SnapshotPath: t.SnapshotPath(),
|
||||||
}, t.Header(), t.ID(), "")
|
}, t.Header())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *requestFactory) CreateNewTreeRequest(id string) (msg *spacesyncproto.ObjectSyncMessage) {
|
func (r *requestFactory) CreateNewTreeRequest() (msg *treechangeproto.TreeSyncMessage) {
|
||||||
return spacesyncproto.WrapFullRequest(&spacesyncproto.ObjectFullSyncRequest{}, nil, id, "")
|
return treechangeproto.WrapFullRequest(&treechangeproto.TreeFullSyncRequest{}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *requestFactory) CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (msg *spacesyncproto.ObjectSyncMessage, err error) {
|
func (r *requestFactory) CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (msg *treechangeproto.TreeSyncMessage, err error) {
|
||||||
req := &spacesyncproto.ObjectFullSyncRequest{}
|
req := &treechangeproto.TreeFullSyncRequest{}
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil, fmt.Errorf("tree should not be empty")
|
return nil, fmt.Errorf("tree should not be empty")
|
||||||
}
|
}
|
||||||
@ -49,17 +50,17 @@ func (r *requestFactory) CreateFullSyncRequest(t tree.ObjectTree, theirHeads, th
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.Changes = changesAfterSnapshot
|
req.Changes = changesAfterSnapshot
|
||||||
msg = spacesyncproto.WrapFullRequest(req, t.Header(), t.ID(), trackingId)
|
msg = treechangeproto.WrapFullRequest(req, t.Header())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *requestFactory) CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (msg *spacesyncproto.ObjectSyncMessage, err error) {
|
func (r *requestFactory) CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (msg *treechangeproto.TreeSyncMessage, err error) {
|
||||||
resp := &spacesyncproto.ObjectFullSyncResponse{
|
resp := &treechangeproto.TreeFullSyncResponse{
|
||||||
Heads: t.Heads(),
|
Heads: t.Heads(),
|
||||||
SnapshotPath: t.SnapshotPath(),
|
SnapshotPath: t.SnapshotPath(),
|
||||||
}
|
}
|
||||||
if slice.UnsortedEquals(theirHeads, t.Heads()) {
|
if slice.UnsortedEquals(theirHeads, t.Heads()) {
|
||||||
msg = spacesyncproto.WrapFullResponse(resp, t.Header(), t.ID(), trackingId)
|
msg = treechangeproto.WrapFullResponse(resp, t.Header())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +69,6 @@ func (r *requestFactory) CreateFullSyncResponse(t tree.ObjectTree, theirHeads, t
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp.Changes = ourChanges
|
resp.Changes = ourChanges
|
||||||
msg = spacesyncproto.WrapFullResponse(resp, t.Header(), t.ID(), trackingId)
|
msg = treechangeproto.WrapFullResponse(resp, t.Header())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
89
common/commonspace/synctree/syncclient.go
Normal file
89
common/commonspace/synctree/syncclient.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//go:generate mockgen -destination mock_synctree/mock_synctree.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree SyncClient
|
||||||
|
package synctree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncClient interface {
|
||||||
|
RequestFactory
|
||||||
|
BroadcastAsync(message *treechangeproto.TreeSyncMessage) (err error)
|
||||||
|
BroadcastAsyncOrSendResponsible(message *treechangeproto.TreeSyncMessage) (err error)
|
||||||
|
SendAsync(peerId string, message *treechangeproto.TreeSyncMessage, replyId string) (err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type syncClient struct {
|
||||||
|
syncservice.StreamPool
|
||||||
|
RequestFactory
|
||||||
|
spaceId string
|
||||||
|
notifiable diffservice.HeadNotifiable
|
||||||
|
configuration nodeconf.Configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSyncClient(
|
||||||
|
spaceId string,
|
||||||
|
pool syncservice.StreamPool,
|
||||||
|
notifiable diffservice.HeadNotifiable,
|
||||||
|
factory RequestFactory,
|
||||||
|
configuration nodeconf.Configuration) SyncClient {
|
||||||
|
return &syncClient{
|
||||||
|
StreamPool: pool,
|
||||||
|
RequestFactory: factory,
|
||||||
|
notifiable: notifiable,
|
||||||
|
configuration: configuration,
|
||||||
|
spaceId: spaceId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncClient) BroadcastAsync(message *treechangeproto.TreeSyncMessage) (err error) {
|
||||||
|
s.notifyIfNeeded(message)
|
||||||
|
objMsg, err := marshallTreeMessage(message, message.RootChange.Id, "")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return s.StreamPool.BroadcastAsync(objMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncClient) SendAsync(peerId string, message *treechangeproto.TreeSyncMessage, replyId string) (err error) {
|
||||||
|
objMsg, err := marshallTreeMessage(message, message.RootChange.Id, replyId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return s.StreamPool.SendAsync([]string{peerId}, objMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncClient) BroadcastAsyncOrSendResponsible(message *treechangeproto.TreeSyncMessage) (err error) {
|
||||||
|
s.notifyIfNeeded(message)
|
||||||
|
objMsg, err := marshallTreeMessage(message, message.RootChange.Id, "")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.configuration.IsResponsible(s.spaceId) {
|
||||||
|
return s.StreamPool.SendAsync(s.configuration.NodeIds(s.spaceId), objMsg)
|
||||||
|
}
|
||||||
|
return s.BroadcastAsync(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncClient) notifyIfNeeded(message *treechangeproto.TreeSyncMessage) {
|
||||||
|
if message.GetContent().GetHeadUpdate() != nil {
|
||||||
|
update := message.GetContent().GetHeadUpdate()
|
||||||
|
s.notifiable.UpdateHeads(message.RootChange.Id, update.Heads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshallTreeMessage(message *treechangeproto.TreeSyncMessage, id, replyId string) (objMsg *spacesyncproto.ObjectSyncMessage, err error) {
|
||||||
|
payload, err := message.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
objMsg = &spacesyncproto.ObjectSyncMessage{
|
||||||
|
ReplyId: replyId,
|
||||||
|
Payload: payload,
|
||||||
|
ObjectId: id,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@ -2,41 +2,84 @@ package synctree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
|
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
tree2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrSyncTreeClosed = errors.New("sync tree is closed")
|
||||||
|
|
||||||
// SyncTree sends head updates to sync service and also sends new changes to update listener
|
// SyncTree sends head updates to sync service and also sends new changes to update listener
|
||||||
type SyncTree struct {
|
type SyncTree struct {
|
||||||
tree2.ObjectTree
|
tree.ObjectTree
|
||||||
syncClient syncservice.SyncClient
|
synchandler.SyncHandler
|
||||||
|
syncClient SyncClient
|
||||||
listener updatelistener.UpdateListener
|
listener updatelistener.UpdateListener
|
||||||
|
isClosed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var createDerivedObjectTree = tree2.CreateDerivedObjectTree
|
var log = logger.NewNamed("commonspace.synctree").Sugar()
|
||||||
var createObjectTree = tree2.CreateObjectTree
|
|
||||||
var buildObjectTree = tree2.BuildObjectTree
|
var createDerivedObjectTree = tree.CreateDerivedObjectTree
|
||||||
|
var createObjectTree = tree.CreateObjectTree
|
||||||
|
var buildObjectTree = tree.BuildObjectTree
|
||||||
|
var createSyncClient = newSyncClient
|
||||||
|
|
||||||
|
type CreateDeps struct {
|
||||||
|
SpaceId string
|
||||||
|
Payload tree.ObjectTreeCreatePayload
|
||||||
|
Configuration nodeconf.Configuration
|
||||||
|
HeadNotifiable diffservice.HeadNotifiable
|
||||||
|
StreamPool syncservice.StreamPool
|
||||||
|
Listener updatelistener.UpdateListener
|
||||||
|
AclList list.ACLList
|
||||||
|
CreateStorage storage.TreeStorageCreatorFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildDeps struct {
|
||||||
|
SpaceId string
|
||||||
|
StreamPool syncservice.StreamPool
|
||||||
|
Configuration nodeconf.Configuration
|
||||||
|
HeadNotifiable diffservice.HeadNotifiable
|
||||||
|
Listener updatelistener.UpdateListener
|
||||||
|
AclList list.ACLList
|
||||||
|
SpaceStorage spacestorage.SpaceStorage
|
||||||
|
TreeStorage storage.TreeStorage
|
||||||
|
}
|
||||||
|
|
||||||
func DeriveSyncTree(
|
func DeriveSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
payload tree2.ObjectTreeCreatePayload,
|
deps CreateDeps) (t tree.ObjectTree, err error) {
|
||||||
syncClient syncservice.SyncClient,
|
t, err = createDerivedObjectTree(deps.Payload, deps.AclList, deps.CreateStorage)
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList,
|
|
||||||
createStorage storage.TreeStorageCreatorFunc) (t tree2.ObjectTree, err error) {
|
|
||||||
t, err = createDerivedObjectTree(payload, aclList, createStorage)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = &SyncTree{
|
syncClient := createSyncClient(
|
||||||
|
deps.SpaceId,
|
||||||
|
deps.StreamPool,
|
||||||
|
deps.HeadNotifiable,
|
||||||
|
sharedFactory,
|
||||||
|
deps.Configuration)
|
||||||
|
syncTree := &SyncTree{
|
||||||
ObjectTree: t,
|
ObjectTree: t,
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
listener: listener,
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
|
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
||||||
|
syncTree.SyncHandler = syncHandler
|
||||||
|
t = syncTree
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = syncClient.BroadcastAsync(headUpdate)
|
||||||
@ -45,58 +88,134 @@ func DeriveSyncTree(
|
|||||||
|
|
||||||
func CreateSyncTree(
|
func CreateSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
payload tree2.ObjectTreeCreatePayload,
|
deps CreateDeps) (t tree.ObjectTree, err error) {
|
||||||
syncClient syncservice.SyncClient,
|
t, err = createObjectTree(deps.Payload, deps.AclList, deps.CreateStorage)
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList,
|
|
||||||
createStorage storage.TreeStorageCreatorFunc) (t tree2.ObjectTree, err error) {
|
|
||||||
t, err = createObjectTree(payload, aclList, createStorage)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = &SyncTree{
|
syncClient := createSyncClient(
|
||||||
|
deps.SpaceId,
|
||||||
|
deps.StreamPool,
|
||||||
|
deps.HeadNotifiable,
|
||||||
|
GetRequestFactory(),
|
||||||
|
deps.Configuration)
|
||||||
|
syncTree := &SyncTree{
|
||||||
ObjectTree: t,
|
ObjectTree: t,
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
listener: listener,
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
|
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
||||||
|
syncTree.SyncHandler = syncHandler
|
||||||
|
t = syncTree
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = syncClient.BroadcastAsync(headUpdate)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildSyncTree(
|
func BuildSyncTreeOrGetRemote(ctx context.Context, id string, deps BuildDeps) (t tree.ObjectTree, err error) {
|
||||||
ctx context.Context,
|
getTreeRemote := func() (msg *treechangeproto.TreeSyncMessage, err error) {
|
||||||
syncClient syncservice.SyncClient,
|
// TODO: add empty context handling (when this is not happening due to head update)
|
||||||
treeStorage storage.TreeStorage,
|
peerId, err := syncservice.GetPeerIdFromStreamContext(ctx)
|
||||||
listener updatelistener.UpdateListener,
|
if err != nil {
|
||||||
aclList list.ACLList) (t tree2.ObjectTree, err error) {
|
return
|
||||||
return buildSyncTree(ctx, syncClient, treeStorage, listener, aclList)
|
}
|
||||||
|
newTreeRequest := GetRequestFactory().CreateNewTreeRequest()
|
||||||
|
objMsg, err := marshallTreeMessage(newTreeRequest, id, "")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := deps.StreamPool.SendSync(peerId, objMsg)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg = &treechangeproto.TreeSyncMessage{}
|
||||||
|
err = proto.Unmarshal(resp.Payload, msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
deps.TreeStorage, err = deps.SpaceStorage.TreeStorage(id)
|
||||||
|
if err == nil {
|
||||||
|
return buildSyncTree(ctx, false, deps)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && err != storage.ErrUnknownTreeId {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := getTreeRemote()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.GetContent().GetFullSyncResponse() == nil {
|
||||||
|
err = fmt.Errorf("expected to get full sync response, but got something else")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fullSyncResp := resp.GetContent().GetFullSyncResponse()
|
||||||
|
|
||||||
|
payload := storage.TreeStorageCreatePayload{
|
||||||
|
TreeId: id,
|
||||||
|
RootRawChange: resp.RootChange,
|
||||||
|
Changes: fullSyncResp.Changes,
|
||||||
|
Heads: fullSyncResp.Heads,
|
||||||
|
}
|
||||||
|
|
||||||
|
// basically building tree with in-memory storage and validating that it was without errors
|
||||||
|
log.With(zap.String("id", id)).Debug("validating tree")
|
||||||
|
err = tree.ValidateRawTree(payload, deps.AclList)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// now we are sure that we can save it to the storage
|
||||||
|
deps.TreeStorage, err = deps.SpaceStorage.CreateTreeStorage(payload)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return buildSyncTree(ctx, true, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSyncTree(
|
func buildSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
syncClient syncservice.SyncClient,
|
isFirstBuild bool,
|
||||||
treeStorage storage.TreeStorage,
|
deps BuildDeps) (t tree.ObjectTree, err error) {
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList) (t tree2.ObjectTree, err error) {
|
t, err = buildObjectTree(deps.TreeStorage, deps.AclList)
|
||||||
t, err = buildObjectTree(treeStorage, aclList)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = &SyncTree{
|
syncClient := createSyncClient(
|
||||||
|
deps.SpaceId,
|
||||||
|
deps.StreamPool,
|
||||||
|
deps.HeadNotifiable,
|
||||||
|
GetRequestFactory(),
|
||||||
|
deps.Configuration)
|
||||||
|
syncTree := &SyncTree{
|
||||||
ObjectTree: t,
|
ObjectTree: t,
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
listener: listener,
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
|
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
||||||
|
syncTree.SyncHandler = syncHandler
|
||||||
|
t = syncTree
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := syncTree.syncClient.CreateHeadUpdate(t, nil)
|
||||||
// here we will have different behaviour based on who is sending this update
|
// here we will have different behaviour based on who is sending this update
|
||||||
err = syncClient.BroadcastAsyncOrSendResponsible(headUpdate)
|
if isFirstBuild {
|
||||||
|
// send to everybody, because everybody should know that the node or client got new tree
|
||||||
|
err = syncTree.syncClient.BroadcastAsync(headUpdate)
|
||||||
|
} else {
|
||||||
|
// send either to everybody if client or to replica set if node
|
||||||
|
err = syncTree.syncClient.BroadcastAsyncOrSendResponsible(headUpdate)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SyncTree) AddContent(ctx context.Context, content tree2.SignableChangeContent) (res tree2.AddResult, err error) {
|
func (s *SyncTree) AddContent(ctx context.Context, content tree.SignableChangeContent) (res tree.AddResult, err error) {
|
||||||
|
if s.isClosed {
|
||||||
|
err = ErrSyncTreeClosed
|
||||||
|
return
|
||||||
|
}
|
||||||
res, err = s.ObjectTree.AddContent(ctx, content)
|
res, err = s.ObjectTree.AddContent(ctx, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -106,25 +225,41 @@ func (s *SyncTree) AddContent(ctx context.Context, content tree2.SignableChangeC
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SyncTree) AddRawChanges(ctx context.Context, changes ...*treechangeproto.RawTreeChangeWithId) (res tree2.AddResult, err error) {
|
func (s *SyncTree) AddRawChanges(ctx context.Context, changes ...*treechangeproto.RawTreeChangeWithId) (res tree.AddResult, err error) {
|
||||||
|
if s.isClosed {
|
||||||
|
err = ErrSyncTreeClosed
|
||||||
|
return
|
||||||
|
}
|
||||||
res, err = s.ObjectTree.AddRawChanges(ctx, changes...)
|
res, err = s.ObjectTree.AddRawChanges(ctx, changes...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch res.Mode {
|
if s.listener != nil {
|
||||||
case tree2.Nothing:
|
switch res.Mode {
|
||||||
return
|
case tree.Nothing:
|
||||||
case tree2.Append:
|
return
|
||||||
s.listener.Update(s)
|
case tree.Append:
|
||||||
case tree2.Rebuild:
|
s.listener.Update(s)
|
||||||
s.listener.Rebuild(s)
|
case tree.Rebuild:
|
||||||
|
s.listener.Rebuild(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//if res.Mode != tree.Nothing {
|
||||||
headUpdate := s.syncClient.CreateHeadUpdate(s, res.Added)
|
headUpdate := s.syncClient.CreateHeadUpdate(s, res.Added)
|
||||||
err = s.syncClient.BroadcastAsync(headUpdate)
|
err = s.syncClient.BroadcastAsync(headUpdate)
|
||||||
|
//}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SyncTree) Tree() tree2.ObjectTree {
|
func (s *SyncTree) Close() (err error) {
|
||||||
return s
|
log.With("id", s.ID()).Debug("closing sync tree")
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
log.With("id", s.ID()).Debug("taken lock on sync tree")
|
||||||
|
if s.isClosed {
|
||||||
|
err = ErrSyncTreeClosed
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.isClosed = true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,16 +2,16 @@ package synctree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/mock_syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/mock_synctree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener/mock_updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener/mock_updatelistener"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list/mock_list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list/mock_list"
|
||||||
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage/mock_storage"
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
tree2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree/mock_objecttree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree/mock_objecttree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@ -20,8 +20,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type syncTreeMatcher struct {
|
type syncTreeMatcher struct {
|
||||||
objTree tree2.ObjectTree
|
objTree tree.ObjectTree
|
||||||
client syncservice.SyncClient
|
client SyncClient
|
||||||
listener updatelistener.UpdateListener
|
listener updatelistener.UpdateListener
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,21 +43,25 @@ func Test_DeriveSyncTree(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
updateListenerMock := mock_updatelistener.NewMockUpdateListener(ctrl)
|
updateListenerMock := mock_updatelistener.NewMockUpdateListener(ctrl)
|
||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
syncClientMock := mock_synctree.NewMockSyncClient(ctrl)
|
||||||
aclListMock := mock_list.NewMockACLList(ctrl)
|
aclListMock := mock_list.NewMockACLList(ctrl)
|
||||||
createStorage := storage2.TreeStorageCreatorFunc(func(payload storage2.TreeStorageCreatePayload) (storage2.TreeStorage, error) {
|
|
||||||
return nil, nil
|
|
||||||
})
|
|
||||||
objTreeMock := mock_tree.NewMockObjectTree(ctrl)
|
objTreeMock := mock_tree.NewMockObjectTree(ctrl)
|
||||||
createDerivedObjectTree = func(payload tree2.ObjectTreeCreatePayload, l list.ACLList, create storage2.TreeStorageCreatorFunc) (objTree tree2.ObjectTree, err error) {
|
spaceId := "spaceId"
|
||||||
|
expectedPayload := tree.ObjectTreeCreatePayload{SpaceId: spaceId}
|
||||||
|
createDerivedObjectTree = func(payload tree.ObjectTreeCreatePayload, l list.ACLList, create storage2.TreeStorageCreatorFunc) (objTree tree.ObjectTree, err error) {
|
||||||
require.Equal(t, l, aclListMock)
|
require.Equal(t, l, aclListMock)
|
||||||
|
require.Equal(t, expectedPayload, payload)
|
||||||
return objTreeMock, nil
|
return objTreeMock, nil
|
||||||
}
|
}
|
||||||
headUpdate := &spacesyncproto.ObjectSyncMessage{}
|
createSyncClient = func(spaceId string, pool syncservice.StreamPool, notifiable diffservice.HeadNotifiable, factory RequestFactory, configuration nodeconf.Configuration) SyncClient {
|
||||||
|
return syncClientMock
|
||||||
|
}
|
||||||
|
headUpdate := &treechangeproto.TreeSyncMessage{}
|
||||||
syncClientMock.EXPECT().CreateHeadUpdate(syncTreeMatcher{objTreeMock, syncClientMock, updateListenerMock}, gomock.Nil()).Return(headUpdate)
|
syncClientMock.EXPECT().CreateHeadUpdate(syncTreeMatcher{objTreeMock, syncClientMock, updateListenerMock}, gomock.Nil()).Return(headUpdate)
|
||||||
syncClientMock.EXPECT().BroadcastAsync(gomock.Eq(headUpdate)).Return(nil)
|
syncClientMock.EXPECT().BroadcastAsync(gomock.Eq(headUpdate)).Return(nil)
|
||||||
|
deps := CreateDeps{AclList: aclListMock, SpaceId: spaceId, Payload: expectedPayload, Listener: updateListenerMock}
|
||||||
|
|
||||||
_, err := DeriveSyncTree(ctx, tree2.ObjectTreeCreatePayload{}, syncClientMock, updateListenerMock, aclListMock, createStorage)
|
_, err := DeriveSyncTree(ctx, deps)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,21 +71,25 @@ func Test_CreateSyncTree(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
updateListenerMock := mock_updatelistener.NewMockUpdateListener(ctrl)
|
updateListenerMock := mock_updatelistener.NewMockUpdateListener(ctrl)
|
||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
syncClientMock := mock_synctree.NewMockSyncClient(ctrl)
|
||||||
aclListMock := mock_list.NewMockACLList(ctrl)
|
aclListMock := mock_list.NewMockACLList(ctrl)
|
||||||
createStorage := storage2.TreeStorageCreatorFunc(func(payload storage2.TreeStorageCreatePayload) (storage2.TreeStorage, error) {
|
|
||||||
return nil, nil
|
|
||||||
})
|
|
||||||
objTreeMock := mock_tree.NewMockObjectTree(ctrl)
|
objTreeMock := mock_tree.NewMockObjectTree(ctrl)
|
||||||
createObjectTree = func(payload tree2.ObjectTreeCreatePayload, l list.ACLList, create storage2.TreeStorageCreatorFunc) (objTree tree2.ObjectTree, err error) {
|
spaceId := "spaceId"
|
||||||
|
expectedPayload := tree.ObjectTreeCreatePayload{SpaceId: spaceId}
|
||||||
|
createObjectTree = func(payload tree.ObjectTreeCreatePayload, l list.ACLList, create storage2.TreeStorageCreatorFunc) (objTree tree.ObjectTree, err error) {
|
||||||
require.Equal(t, l, aclListMock)
|
require.Equal(t, l, aclListMock)
|
||||||
|
require.Equal(t, expectedPayload, payload)
|
||||||
return objTreeMock, nil
|
return objTreeMock, nil
|
||||||
}
|
}
|
||||||
headUpdate := &spacesyncproto.ObjectSyncMessage{}
|
createSyncClient = func(spaceId string, pool syncservice.StreamPool, notifiable diffservice.HeadNotifiable, factory RequestFactory, configuration nodeconf.Configuration) SyncClient {
|
||||||
|
return syncClientMock
|
||||||
|
}
|
||||||
|
headUpdate := &treechangeproto.TreeSyncMessage{}
|
||||||
syncClientMock.EXPECT().CreateHeadUpdate(syncTreeMatcher{objTreeMock, syncClientMock, updateListenerMock}, gomock.Nil()).Return(headUpdate)
|
syncClientMock.EXPECT().CreateHeadUpdate(syncTreeMatcher{objTreeMock, syncClientMock, updateListenerMock}, gomock.Nil()).Return(headUpdate)
|
||||||
syncClientMock.EXPECT().BroadcastAsync(gomock.Eq(headUpdate)).Return(nil)
|
syncClientMock.EXPECT().BroadcastAsync(gomock.Eq(headUpdate)).Return(nil)
|
||||||
|
deps := CreateDeps{AclList: aclListMock, SpaceId: spaceId, Payload: expectedPayload, Listener: updateListenerMock}
|
||||||
|
|
||||||
_, err := CreateSyncTree(ctx, tree2.ObjectTreeCreatePayload{}, syncClientMock, updateListenerMock, aclListMock, createStorage)
|
_, err := CreateSyncTree(ctx, deps)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,27 +99,22 @@ func Test_BuildSyncTree(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
updateListenerMock := mock_updatelistener.NewMockUpdateListener(ctrl)
|
updateListenerMock := mock_updatelistener.NewMockUpdateListener(ctrl)
|
||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
syncClientMock := mock_synctree.NewMockSyncClient(ctrl)
|
||||||
aclListMock := mock_list.NewMockACLList(ctrl)
|
|
||||||
storageMock := mock_storage.NewMockTreeStorage(ctrl)
|
|
||||||
objTreeMock := mock_tree.NewMockObjectTree(ctrl)
|
objTreeMock := mock_tree.NewMockObjectTree(ctrl)
|
||||||
buildObjectTree = func(store storage2.TreeStorage, l list.ACLList) (objTree tree2.ObjectTree, err error) {
|
tr := &SyncTree{
|
||||||
require.Equal(t, aclListMock, l)
|
ObjectTree: objTreeMock,
|
||||||
require.Equal(t, store, storageMock)
|
SyncHandler: nil,
|
||||||
return objTreeMock, nil
|
syncClient: syncClientMock,
|
||||||
|
listener: updateListenerMock,
|
||||||
|
isClosed: false,
|
||||||
}
|
}
|
||||||
headUpdate := &spacesyncproto.ObjectSyncMessage{}
|
|
||||||
syncClientMock.EXPECT().CreateHeadUpdate(syncTreeMatcher{objTreeMock, syncClientMock, updateListenerMock}, gomock.Nil()).Return(headUpdate)
|
|
||||||
syncClientMock.EXPECT().BroadcastAsyncOrSendResponsible(gomock.Eq(headUpdate)).Return(nil)
|
|
||||||
|
|
||||||
tr, err := BuildSyncTree(ctx, syncClientMock, storageMock, updateListenerMock, aclListMock)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
|
headUpdate := &treechangeproto.TreeSyncMessage{}
|
||||||
t.Run("AddRawChanges update", func(t *testing.T) {
|
t.Run("AddRawChanges update", func(t *testing.T) {
|
||||||
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
||||||
expectedRes := tree2.AddResult{
|
expectedRes := tree.AddResult{
|
||||||
Added: changes,
|
Added: changes,
|
||||||
Mode: tree2.Append,
|
Mode: tree.Append,
|
||||||
}
|
}
|
||||||
objTreeMock.EXPECT().AddRawChanges(gomock.Any(), gomock.Eq(changes)).
|
objTreeMock.EXPECT().AddRawChanges(gomock.Any(), gomock.Eq(changes)).
|
||||||
Return(expectedRes, nil)
|
Return(expectedRes, nil)
|
||||||
@ -126,9 +129,9 @@ func Test_BuildSyncTree(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("AddRawChanges rebuild", func(t *testing.T) {
|
t.Run("AddRawChanges rebuild", func(t *testing.T) {
|
||||||
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
||||||
expectedRes := tree2.AddResult{
|
expectedRes := tree.AddResult{
|
||||||
Added: changes,
|
Added: changes,
|
||||||
Mode: tree2.Rebuild,
|
Mode: tree.Rebuild,
|
||||||
}
|
}
|
||||||
objTreeMock.EXPECT().AddRawChanges(gomock.Any(), gomock.Eq(changes)).
|
objTreeMock.EXPECT().AddRawChanges(gomock.Any(), gomock.Eq(changes)).
|
||||||
Return(expectedRes, nil)
|
Return(expectedRes, nil)
|
||||||
@ -143,9 +146,9 @@ func Test_BuildSyncTree(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("AddRawChanges nothing", func(t *testing.T) {
|
t.Run("AddRawChanges nothing", func(t *testing.T) {
|
||||||
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
||||||
expectedRes := tree2.AddResult{
|
expectedRes := tree.AddResult{
|
||||||
Added: changes,
|
Added: changes,
|
||||||
Mode: tree2.Nothing,
|
Mode: tree.Nothing,
|
||||||
}
|
}
|
||||||
objTreeMock.EXPECT().AddRawChanges(gomock.Any(), gomock.Eq(changes)).
|
objTreeMock.EXPECT().AddRawChanges(gomock.Any(), gomock.Eq(changes)).
|
||||||
Return(expectedRes, nil)
|
Return(expectedRes, nil)
|
||||||
@ -157,11 +160,11 @@ func Test_BuildSyncTree(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("AddContent", func(t *testing.T) {
|
t.Run("AddContent", func(t *testing.T) {
|
||||||
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
changes := []*treechangeproto.RawTreeChangeWithId{{Id: "some"}}
|
||||||
content := tree2.SignableChangeContent{
|
content := tree.SignableChangeContent{
|
||||||
Data: []byte("abcde"),
|
Data: []byte("abcde"),
|
||||||
}
|
}
|
||||||
expectedRes := tree2.AddResult{
|
expectedRes := tree.AddResult{
|
||||||
Mode: tree2.Append,
|
Mode: tree.Append,
|
||||||
Added: changes,
|
Added: changes,
|
||||||
}
|
}
|
||||||
objTreeMock.EXPECT().AddContent(gomock.Any(), gomock.Eq(content)).
|
objTreeMock.EXPECT().AddContent(gomock.Any(), gomock.Eq(content)).
|
||||||
|
|||||||
184
common/commonspace/synctree/synctreehandler.go
Normal file
184
common/commonspace/synctree/synctreehandler.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package synctree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type syncTreeHandler struct {
|
||||||
|
objTree tree.ObjectTree
|
||||||
|
syncClient SyncClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSyncTreeHandler(objTree tree.ObjectTree, syncClient SyncClient) synchandler.SyncHandler {
|
||||||
|
return &syncTreeHandler{
|
||||||
|
objTree: objTree,
|
||||||
|
syncClient: syncClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncTreeHandler) HandleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
|
unmarshalled := &treechangeproto.TreeSyncMessage{}
|
||||||
|
err = proto.Unmarshal(msg.Payload, unmarshalled)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content := unmarshalled.GetContent()
|
||||||
|
switch {
|
||||||
|
case content.GetHeadUpdate() != nil:
|
||||||
|
return s.handleHeadUpdate(ctx, senderId, content.GetHeadUpdate(), msg.ReplyId)
|
||||||
|
case content.GetFullSyncRequest() != nil:
|
||||||
|
return s.handleFullSyncRequest(ctx, senderId, content.GetFullSyncRequest(), msg.ReplyId)
|
||||||
|
case content.GetFullSyncResponse() != nil:
|
||||||
|
return s.handleFullSyncResponse(ctx, senderId, content.GetFullSyncResponse())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncTreeHandler) handleHeadUpdate(
|
||||||
|
ctx context.Context,
|
||||||
|
senderId string,
|
||||||
|
update *treechangeproto.TreeHeadUpdate,
|
||||||
|
replyId string) (err error) {
|
||||||
|
log.With("senderId", senderId).
|
||||||
|
With("heads", update.Heads).
|
||||||
|
With("treeId", s.objTree.ID()).
|
||||||
|
Debug("received head update message")
|
||||||
|
var (
|
||||||
|
fullRequest *treechangeproto.TreeSyncMessage
|
||||||
|
isEmptyUpdate = len(update.Changes) == 0
|
||||||
|
objTree = s.objTree
|
||||||
|
)
|
||||||
|
|
||||||
|
err = func() error {
|
||||||
|
objTree.Lock()
|
||||||
|
defer objTree.Unlock()
|
||||||
|
|
||||||
|
// isEmptyUpdate is sent when the tree is brought up from cache
|
||||||
|
if isEmptyUpdate {
|
||||||
|
log.With("treeId", objTree.ID()).Debug("is empty update")
|
||||||
|
if slice.UnsortedEquals(objTree.Heads(), update.Heads) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// we need to sync in any case
|
||||||
|
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.alreadyHasHeads(objTree, update.Heads) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = objTree.AddRawChanges(ctx, update.Changes...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.alreadyHasHeads(objTree, update.Heads) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath)
|
||||||
|
return err
|
||||||
|
}()
|
||||||
|
|
||||||
|
if fullRequest != nil {
|
||||||
|
log.With("senderId", senderId).
|
||||||
|
With("heads", objTree.Heads()).
|
||||||
|
With("treeId", objTree.ID()).
|
||||||
|
Debug("sending full sync request")
|
||||||
|
return s.syncClient.SendAsync(senderId, fullRequest, replyId)
|
||||||
|
}
|
||||||
|
log.With("senderId", senderId).
|
||||||
|
With("heads", update.Heads).
|
||||||
|
With("treeId", objTree.ID()).
|
||||||
|
Debug("head update finished correctly")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncTreeHandler) handleFullSyncRequest(
|
||||||
|
ctx context.Context,
|
||||||
|
senderId string,
|
||||||
|
request *treechangeproto.TreeFullSyncRequest,
|
||||||
|
replyId string) (err error) {
|
||||||
|
log.With("senderId", senderId).
|
||||||
|
With("heads", request.Heads).
|
||||||
|
With("treeId", s.objTree.ID()).
|
||||||
|
With("trackingId", replyId).
|
||||||
|
Debug("received full sync request message")
|
||||||
|
var (
|
||||||
|
fullResponse *treechangeproto.TreeSyncMessage
|
||||||
|
header = s.objTree.Header()
|
||||||
|
objTree = s.objTree
|
||||||
|
)
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
s.syncClient.SendAsync(senderId, treechangeproto.WrapError(err, header), replyId)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = func() error {
|
||||||
|
objTree.Lock()
|
||||||
|
defer objTree.Unlock()
|
||||||
|
|
||||||
|
if len(request.Changes) != 0 && !s.alreadyHasHeads(objTree, request.Heads) {
|
||||||
|
_, err = objTree.AddRawChanges(ctx, request.Changes...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fullResponse, err = s.syncClient.CreateFullSyncResponse(objTree, request.Heads, request.SnapshotPath)
|
||||||
|
return err
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return s.syncClient.SendAsync(senderId, fullResponse, replyId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncTreeHandler) handleFullSyncResponse(
|
||||||
|
ctx context.Context,
|
||||||
|
senderId string,
|
||||||
|
response *treechangeproto.TreeFullSyncResponse) (err error) {
|
||||||
|
log.With("senderId", senderId).
|
||||||
|
With("heads", response.Heads).
|
||||||
|
With("treeId", s.objTree.ID()).
|
||||||
|
Debug("received full sync response message")
|
||||||
|
objTree := s.objTree
|
||||||
|
if err != nil {
|
||||||
|
log.With("senderId", senderId).
|
||||||
|
With("heads", response.Heads).
|
||||||
|
With("treeId", s.objTree.ID()).
|
||||||
|
Debug("failed to find the tree in full sync response")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = func() error {
|
||||||
|
objTree.Lock()
|
||||||
|
defer objTree.Unlock()
|
||||||
|
|
||||||
|
if s.alreadyHasHeads(objTree, response.Heads) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = objTree.AddRawChanges(ctx, response.Changes...)
|
||||||
|
return err
|
||||||
|
}()
|
||||||
|
log.With("error", err != nil).
|
||||||
|
With("heads", response.Heads).
|
||||||
|
With("treeId", s.objTree.ID()).
|
||||||
|
Debug("finished full sync response")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncTreeHandler) alreadyHasHeads(t tree.ObjectTree, heads []string) bool {
|
||||||
|
return slice.UnsortedEquals(t.Heads(), heads) || t.HasChanges(heads...)
|
||||||
|
}
|
||||||
@ -1,29 +1,19 @@
|
|||||||
package syncservice
|
package synctree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/mock_synctree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache/mock_cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/mock_syncservice"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree/mock_objecttree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree/mock_objecttree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/zap"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type treeContainer struct {
|
|
||||||
objTree tree.ObjectTree
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t treeContainer) Tree() tree.ObjectTree {
|
|
||||||
return t.objTree
|
|
||||||
}
|
|
||||||
|
|
||||||
type testObjTreeMock struct {
|
type testObjTreeMock struct {
|
||||||
*mock_tree.MockObjectTree
|
*mock_tree.MockObjectTree
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
@ -48,28 +38,26 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
spaceId := "spaceId"
|
syncClientMock := mock_synctree.NewMockSyncClient(ctrl)
|
||||||
cacheMock := mock_cache.NewMockTreeCache(ctrl)
|
|
||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
|
||||||
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
||||||
|
|
||||||
syncHandler := newSyncHandler(spaceId, cacheMock, syncClientMock)
|
syncHandler := newSyncTreeHandler(objectTreeMock, syncClientMock)
|
||||||
|
log = zap.NewNop().Sugar()
|
||||||
|
|
||||||
t.Run("head update non empty all heads added", func(t *testing.T) {
|
t.Run("head update non empty all heads added", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
headUpdate := &spacesyncproto.ObjectHeadUpdate{
|
headUpdate := &treechangeproto.TreeHeadUpdate{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}
|
}
|
||||||
msg := spacesyncproto.WrapHeadUpdate(headUpdate, chWithId, treeId, "")
|
treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId)
|
||||||
cacheMock.EXPECT().
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{
|
objectTreeMock.EXPECT().
|
||||||
Release: func() {},
|
ID().AnyTimes().Return(treeId)
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h2"})
|
Return([]string{"h2"})
|
||||||
@ -86,7 +74,7 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
HasChanges(gomock.Eq([]string{"h1"})).
|
HasChanges(gomock.Eq([]string{"h1"})).
|
||||||
Return(true)
|
Return(true)
|
||||||
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,19 +82,17 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
headUpdate := &spacesyncproto.ObjectHeadUpdate{
|
headUpdate := &treechangeproto.TreeHeadUpdate{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}
|
}
|
||||||
fullRequest := &spacesyncproto.ObjectSyncMessage{}
|
treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId)
|
||||||
msg := spacesyncproto.WrapHeadUpdate(headUpdate, chWithId, treeId, "")
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
cacheMock.EXPECT().
|
fullRequest := &treechangeproto.TreeSyncMessage{}
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{
|
objectTreeMock.EXPECT().
|
||||||
Release: func() {},
|
ID().AnyTimes().Return(treeId)
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h2"})
|
Return([]string{"h2"})
|
||||||
@ -123,11 +109,15 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
HasChanges(gomock.Eq([]string{"h1"})).
|
HasChanges(gomock.Eq([]string{"h1"})).
|
||||||
Return(false)
|
Return(false)
|
||||||
syncClientMock.EXPECT().
|
syncClientMock.EXPECT().
|
||||||
CreateFullSyncRequest(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"}), gomock.Eq("")).
|
CreateFullSyncRequest(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})).
|
||||||
Return(fullRequest, nil)
|
Return(fullRequest, nil)
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
Heads().
|
||||||
|
Return([]string{"h2"})
|
||||||
|
|
||||||
syncClientMock.EXPECT().SendAsync(gomock.Eq([]string{senderId}), gomock.Eq(fullRequest))
|
syncClientMock.EXPECT().SendAsync(gomock.Eq(senderId), gomock.Eq(fullRequest), gomock.Eq(""))
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
|
||||||
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -135,23 +125,21 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
headUpdate := &spacesyncproto.ObjectHeadUpdate{
|
headUpdate := &treechangeproto.TreeHeadUpdate{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}
|
}
|
||||||
msg := spacesyncproto.WrapHeadUpdate(headUpdate, chWithId, treeId, "")
|
treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId)
|
||||||
cacheMock.EXPECT().
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{
|
objectTreeMock.EXPECT().
|
||||||
Release: func() {},
|
ID().AnyTimes().Return(treeId)
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h1"})
|
Return([]string{"h1"})
|
||||||
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -159,28 +147,30 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
headUpdate := &spacesyncproto.ObjectHeadUpdate{
|
headUpdate := &treechangeproto.TreeHeadUpdate{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: nil,
|
Changes: nil,
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}
|
}
|
||||||
fullRequest := &spacesyncproto.ObjectSyncMessage{}
|
treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId)
|
||||||
msg := spacesyncproto.WrapHeadUpdate(headUpdate, chWithId, treeId, "")
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
cacheMock.EXPECT().
|
fullRequest := &treechangeproto.TreeSyncMessage{}
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{
|
objectTreeMock.EXPECT().
|
||||||
Release: func() {},
|
ID().AnyTimes().Return(treeId)
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h2"})
|
Return([]string{"h2"})
|
||||||
syncClientMock.EXPECT().
|
syncClientMock.EXPECT().
|
||||||
CreateFullSyncRequest(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"}), gomock.Eq("")).
|
CreateFullSyncRequest(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})).
|
||||||
Return(fullRequest, nil)
|
Return(fullRequest, nil)
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
Heads().
|
||||||
|
Return([]string{"h2"})
|
||||||
|
|
||||||
syncClientMock.EXPECT().SendAsync(gomock.Eq([]string{senderId}), gomock.Eq(fullRequest))
|
syncClientMock.EXPECT().SendAsync(gomock.Eq(senderId), gomock.Eq(fullRequest), gomock.Eq(""))
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
|
||||||
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -188,24 +178,21 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
headUpdate := &spacesyncproto.ObjectHeadUpdate{
|
headUpdate := &treechangeproto.TreeHeadUpdate{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: nil,
|
Changes: nil,
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}
|
}
|
||||||
msg := spacesyncproto.WrapHeadUpdate(headUpdate, chWithId, treeId, "")
|
treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId)
|
||||||
cacheMock.EXPECT().
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{
|
|
||||||
Release: func() {},
|
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
|
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
ID().AnyTimes().Return(treeId)
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h1"})
|
Return([]string{"h1"})
|
||||||
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -215,29 +202,26 @@ func TestSyncHandler_HandleFullSyncRequest(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
spaceId := "spaceId"
|
syncClientMock := mock_synctree.NewMockSyncClient(ctrl)
|
||||||
cacheMock := mock_cache.NewMockTreeCache(ctrl)
|
|
||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
|
||||||
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
||||||
|
|
||||||
syncHandler := newSyncHandler(spaceId, cacheMock, syncClientMock)
|
syncHandler := newSyncTreeHandler(objectTreeMock, syncClientMock)
|
||||||
|
log = zap.NewNop().Sugar()
|
||||||
t.Run("full sync request with change", func(t *testing.T) {
|
t.Run("full sync request with change", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
msg := spacesyncproto.WrapFullRequest(&spacesyncproto.ObjectFullSyncRequest{
|
fullSyncRequest := &treechangeproto.TreeFullSyncRequest{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}, chWithId, treeId, "")
|
}
|
||||||
fullRequest := &spacesyncproto.ObjectSyncMessage{}
|
treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId)
|
||||||
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
cacheMock.EXPECT().
|
fullResponse := &treechangeproto.TreeSyncMessage{}
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
objectTreeMock.EXPECT().
|
||||||
Return(cache.TreeResult{
|
ID().AnyTimes().Return(treeId)
|
||||||
Release: func() {},
|
objectTreeMock.EXPECT().Header().Return(nil)
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h2"})
|
Return([]string{"h2"})
|
||||||
@ -248,11 +232,10 @@ func TestSyncHandler_HandleFullSyncRequest(t *testing.T) {
|
|||||||
AddRawChanges(gomock.Any(), gomock.Eq([]*treechangeproto.RawTreeChangeWithId{chWithId})).
|
AddRawChanges(gomock.Any(), gomock.Eq([]*treechangeproto.RawTreeChangeWithId{chWithId})).
|
||||||
Return(tree.AddResult{}, nil)
|
Return(tree.AddResult{}, nil)
|
||||||
syncClientMock.EXPECT().
|
syncClientMock.EXPECT().
|
||||||
CreateFullSyncResponse(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"}), gomock.Eq("")).
|
CreateFullSyncResponse(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})).
|
||||||
Return(fullRequest, nil)
|
Return(fullResponse, nil)
|
||||||
|
syncClientMock.EXPECT().SendAsync(gomock.Eq(senderId), gomock.Eq(fullResponse), gomock.Eq(""))
|
||||||
syncClientMock.EXPECT().SendAsync(gomock.Eq([]string{senderId}), gomock.Eq(fullRequest))
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -260,72 +243,76 @@ func TestSyncHandler_HandleFullSyncRequest(t *testing.T) {
|
|||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
msg := spacesyncproto.WrapFullRequest(&spacesyncproto.ObjectFullSyncRequest{
|
fullSyncRequest := &treechangeproto.TreeFullSyncRequest{
|
||||||
Heads: []string{"h2"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h2"},
|
SnapshotPath: []string{"h1"},
|
||||||
}, chWithId, treeId, "")
|
}
|
||||||
fullRequest := &spacesyncproto.ObjectSyncMessage{}
|
treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId)
|
||||||
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
|
fullResponse := &treechangeproto.TreeSyncMessage{}
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
ID().AnyTimes().Return(treeId)
|
||||||
|
objectTreeMock.EXPECT().Header().Return(nil)
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
Heads().
|
||||||
|
Return([]string{"h1"})
|
||||||
|
syncClientMock.EXPECT().
|
||||||
|
CreateFullSyncResponse(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})).
|
||||||
|
Return(fullResponse, nil)
|
||||||
|
syncClientMock.EXPECT().SendAsync(gomock.Eq(senderId), gomock.Eq(fullResponse), gomock.Eq(""))
|
||||||
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
cacheMock.EXPECT().
|
t.Run("full sync request without change but with reply id", func(t *testing.T) {
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
treeId := "treeId"
|
||||||
Return(cache.TreeResult{
|
senderId := "senderId"
|
||||||
Release: func() {},
|
replyId := "replyId"
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
}, nil)
|
fullSyncRequest := &treechangeproto.TreeFullSyncRequest{
|
||||||
|
Heads: []string{"h1"},
|
||||||
|
SnapshotPath: []string{"h1"},
|
||||||
|
}
|
||||||
|
treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId)
|
||||||
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, replyId)
|
||||||
|
fullResponse := &treechangeproto.TreeSyncMessage{}
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
ID().AnyTimes().Return(treeId)
|
||||||
|
objectTreeMock.EXPECT().Header().Return(nil)
|
||||||
|
syncClientMock.EXPECT().
|
||||||
|
CreateFullSyncResponse(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})).
|
||||||
|
Return(fullResponse, nil)
|
||||||
|
syncClientMock.EXPECT().SendAsync(gomock.Eq(senderId), gomock.Eq(fullResponse), gomock.Eq(replyId))
|
||||||
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("full sync request with add raw changes error", func(t *testing.T) {
|
||||||
|
treeId := "treeId"
|
||||||
|
senderId := "senderId"
|
||||||
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
|
fullSyncRequest := &treechangeproto.TreeFullSyncRequest{
|
||||||
|
Heads: []string{"h1"},
|
||||||
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
|
SnapshotPath: []string{"h1"},
|
||||||
|
}
|
||||||
|
treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId)
|
||||||
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, "")
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
|
ID().AnyTimes().Return(treeId)
|
||||||
|
objectTreeMock.EXPECT().Header().Return(nil)
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h2"})
|
Return([]string{"h2"})
|
||||||
syncClientMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
CreateFullSyncResponse(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h2"}), gomock.Eq([]string{"h2"}), gomock.Eq("")).
|
HasChanges(gomock.Eq([]string{"h1"})).
|
||||||
Return(fullRequest, nil)
|
Return(false)
|
||||||
|
objectTreeMock.EXPECT().
|
||||||
syncClientMock.EXPECT().SendAsync(gomock.Eq([]string{senderId}), gomock.Eq(fullRequest))
|
AddRawChanges(gomock.Any(), gomock.Eq([]*treechangeproto.RawTreeChangeWithId{chWithId})).
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
Return(tree.AddResult{}, fmt.Errorf(""))
|
||||||
require.NoError(t, err)
|
syncClientMock.EXPECT().SendAsync(gomock.Eq(senderId), gomock.Any(), gomock.Eq(""))
|
||||||
})
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
|
|
||||||
t.Run("full sync request without change", func(t *testing.T) {
|
|
||||||
treeId := "treeId"
|
|
||||||
senderId := "senderId"
|
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
|
||||||
msg := spacesyncproto.WrapFullRequest(&spacesyncproto.ObjectFullSyncRequest{
|
|
||||||
Heads: []string{"h1"},
|
|
||||||
SnapshotPath: []string{"h1"},
|
|
||||||
}, chWithId, treeId, "")
|
|
||||||
fullRequest := &spacesyncproto.ObjectSyncMessage{}
|
|
||||||
|
|
||||||
cacheMock.EXPECT().
|
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{
|
|
||||||
Release: func() {},
|
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
syncClientMock.EXPECT().
|
|
||||||
CreateFullSyncResponse(gomock.Eq(objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"}), gomock.Eq("")).
|
|
||||||
Return(fullRequest, nil)
|
|
||||||
|
|
||||||
syncClientMock.EXPECT().SendAsync(gomock.Eq([]string{senderId}), gomock.Eq(fullRequest))
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("full sync request with get tree error", func(t *testing.T) {
|
|
||||||
treeId := "treeId"
|
|
||||||
senderId := "senderId"
|
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
|
||||||
msg := spacesyncproto.WrapFullRequest(&spacesyncproto.ObjectFullSyncRequest{
|
|
||||||
Heads: []string{"h1"},
|
|
||||||
SnapshotPath: []string{"h1"},
|
|
||||||
}, chWithId, treeId, "")
|
|
||||||
|
|
||||||
cacheMock.EXPECT().
|
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
|
||||||
Return(cache.TreeResult{}, fmt.Errorf("some"))
|
|
||||||
|
|
||||||
syncClientMock.EXPECT().
|
|
||||||
SendAsync(gomock.Eq([]string{senderId}), gomock.Any())
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -335,28 +322,25 @@ func TestSyncHandler_HandleFullSyncResponse(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
spaceId := "spaceId"
|
syncClientMock := mock_synctree.NewMockSyncClient(ctrl)
|
||||||
cacheMock := mock_cache.NewMockTreeCache(ctrl)
|
|
||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
|
||||||
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
||||||
|
|
||||||
syncHandler := newSyncHandler(spaceId, cacheMock, syncClientMock)
|
syncHandler := newSyncTreeHandler(objectTreeMock, syncClientMock)
|
||||||
|
log = zap.NewNop().Sugar()
|
||||||
|
|
||||||
t.Run("full sync response with change", func(t *testing.T) {
|
t.Run("full sync response with change", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
|
replyId := "replyId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
msg := spacesyncproto.WrapFullResponse(&spacesyncproto.ObjectFullSyncResponse{
|
fullSyncResponse := &treechangeproto.TreeFullSyncResponse{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}, chWithId, treeId, "")
|
}
|
||||||
|
treeMsg := treechangeproto.WrapFullResponse(fullSyncResponse, chWithId)
|
||||||
cacheMock.EXPECT().
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, replyId)
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
objectTreeMock.EXPECT().ID().AnyTimes().Return(treeId)
|
||||||
Return(cache.TreeResult{
|
|
||||||
Release: func() {},
|
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h2"})
|
Return([]string{"h2"})
|
||||||
@ -367,31 +351,28 @@ func TestSyncHandler_HandleFullSyncResponse(t *testing.T) {
|
|||||||
AddRawChanges(gomock.Any(), gomock.Eq([]*treechangeproto.RawTreeChangeWithId{chWithId})).
|
AddRawChanges(gomock.Any(), gomock.Eq([]*treechangeproto.RawTreeChangeWithId{chWithId})).
|
||||||
Return(tree.AddResult{}, nil)
|
Return(tree.AddResult{}, nil)
|
||||||
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("full sync response same heads", func(t *testing.T) {
|
t.Run("full sync response with same heads", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
|
replyId := "replyId"
|
||||||
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
chWithId := &treechangeproto.RawTreeChangeWithId{}
|
||||||
msg := spacesyncproto.WrapFullResponse(&spacesyncproto.ObjectFullSyncResponse{
|
fullSyncResponse := &treechangeproto.TreeFullSyncResponse{
|
||||||
Heads: []string{"h1"},
|
Heads: []string{"h1"},
|
||||||
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
Changes: []*treechangeproto.RawTreeChangeWithId{chWithId},
|
||||||
SnapshotPath: []string{"h1"},
|
SnapshotPath: []string{"h1"},
|
||||||
}, chWithId, treeId, "")
|
}
|
||||||
|
treeMsg := treechangeproto.WrapFullResponse(fullSyncResponse, chWithId)
|
||||||
cacheMock.EXPECT().
|
objectMsg, _ := marshallTreeMessage(treeMsg, treeId, replyId)
|
||||||
GetTree(gomock.Any(), spaceId, treeId).
|
objectTreeMock.EXPECT().ID().AnyTimes().Return(treeId)
|
||||||
Return(cache.TreeResult{
|
|
||||||
Release: func() {},
|
|
||||||
TreeContainer: treeContainer{objectTreeMock},
|
|
||||||
}, nil)
|
|
||||||
objectTreeMock.EXPECT().
|
objectTreeMock.EXPECT().
|
||||||
Heads().
|
Heads().
|
||||||
Return([]string{"h1"})
|
Return([]string{"h1"})
|
||||||
|
|
||||||
err := syncHandler.HandleMessage(ctx, senderId, msg)
|
err := syncHandler.HandleMessage(ctx, senderId, objectMsg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -5,9 +5,9 @@
|
|||||||
package mock_updatelistener
|
package mock_updatelistener
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -1,43 +1,43 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache (interfaces: TreeCache)
|
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter (interfaces: TreeGetter)
|
||||||
|
|
||||||
// Package mock_cache is a generated GoMock package.
|
// Package mock_treegetter is a generated GoMock package.
|
||||||
package mock_cache
|
package mock_treegetter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
app "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
app "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||||
cache "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockTreeCache is a mock of TreeCache interface.
|
// MockTreeGetter is a mock of TreeGetter interface.
|
||||||
type MockTreeCache struct {
|
type MockTreeGetter struct {
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockTreeCacheMockRecorder
|
recorder *MockTreeGetterMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockTreeCacheMockRecorder is the mock recorder for MockTreeCache.
|
// MockTreeGetterMockRecorder is the mock recorder for MockTreeGetter.
|
||||||
type MockTreeCacheMockRecorder struct {
|
type MockTreeGetterMockRecorder struct {
|
||||||
mock *MockTreeCache
|
mock *MockTreeGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockTreeCache creates a new mock instance.
|
// NewMockTreeGetter creates a new mock instance.
|
||||||
func NewMockTreeCache(ctrl *gomock.Controller) *MockTreeCache {
|
func NewMockTreeGetter(ctrl *gomock.Controller) *MockTreeGetter {
|
||||||
mock := &MockTreeCache{ctrl: ctrl}
|
mock := &MockTreeGetter{ctrl: ctrl}
|
||||||
mock.recorder = &MockTreeCacheMockRecorder{mock}
|
mock.recorder = &MockTreeGetterMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockTreeCache) EXPECT() *MockTreeCacheMockRecorder {
|
func (m *MockTreeGetter) EXPECT() *MockTreeGetterMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close mocks base method.
|
// Close mocks base method.
|
||||||
func (m *MockTreeCache) Close(arg0 context.Context) error {
|
func (m *MockTreeGetter) Close(arg0 context.Context) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Close", arg0)
|
ret := m.ctrl.Call(m, "Close", arg0)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
@ -45,28 +45,28 @@ func (m *MockTreeCache) Close(arg0 context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close indicates an expected call of Close.
|
// Close indicates an expected call of Close.
|
||||||
func (mr *MockTreeCacheMockRecorder) Close(arg0 interface{}) *gomock.Call {
|
func (mr *MockTreeGetterMockRecorder) Close(arg0 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockTreeCache)(nil).Close), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockTreeGetter)(nil).Close), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTree mocks base method.
|
// GetTree mocks base method.
|
||||||
func (m *MockTreeCache) GetTree(arg0 context.Context, arg1, arg2 string) (cache.TreeResult, error) {
|
func (m *MockTreeGetter) GetTree(arg0 context.Context, arg1, arg2 string) (tree.ObjectTree, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetTree", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "GetTree", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].(cache.TreeResult)
|
ret0, _ := ret[0].(tree.ObjectTree)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTree indicates an expected call of GetTree.
|
// GetTree indicates an expected call of GetTree.
|
||||||
func (mr *MockTreeCacheMockRecorder) GetTree(arg0, arg1, arg2 interface{}) *gomock.Call {
|
func (mr *MockTreeGetterMockRecorder) GetTree(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTree", reflect.TypeOf((*MockTreeCache)(nil).GetTree), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTree", reflect.TypeOf((*MockTreeGetter)(nil).GetTree), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init mocks base method.
|
// Init mocks base method.
|
||||||
func (m *MockTreeCache) Init(arg0 *app.App) error {
|
func (m *MockTreeGetter) Init(arg0 *app.App) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Init", arg0)
|
ret := m.ctrl.Call(m, "Init", arg0)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
@ -74,13 +74,13 @@ func (m *MockTreeCache) Init(arg0 *app.App) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init indicates an expected call of Init.
|
// Init indicates an expected call of Init.
|
||||||
func (mr *MockTreeCacheMockRecorder) Init(arg0 interface{}) *gomock.Call {
|
func (mr *MockTreeGetterMockRecorder) Init(arg0 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockTreeCache)(nil).Init), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockTreeGetter)(nil).Init), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name mocks base method.
|
// Name mocks base method.
|
||||||
func (m *MockTreeCache) Name() string {
|
func (m *MockTreeGetter) Name() string {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Name")
|
ret := m.ctrl.Call(m, "Name")
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(string)
|
||||||
@ -88,13 +88,13 @@ func (m *MockTreeCache) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name indicates an expected call of Name.
|
// Name indicates an expected call of Name.
|
||||||
func (mr *MockTreeCacheMockRecorder) Name() *gomock.Call {
|
func (mr *MockTreeGetterMockRecorder) Name() *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockTreeCache)(nil).Name))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockTreeGetter)(nil).Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run mocks base method.
|
// Run mocks base method.
|
||||||
func (m *MockTreeCache) Run(arg0 context.Context) error {
|
func (m *MockTreeGetter) Run(arg0 context.Context) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Run", arg0)
|
ret := m.ctrl.Call(m, "Run", arg0)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
@ -102,7 +102,7 @@ func (m *MockTreeCache) Run(arg0 context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run indicates an expected call of Run.
|
// Run indicates an expected call of Run.
|
||||||
func (mr *MockTreeCacheMockRecorder) Run(arg0 interface{}) *gomock.Call {
|
func (mr *MockTreeGetterMockRecorder) Run(arg0 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockTreeCache)(nil).Run), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockTreeGetter)(nil).Run), arg0)
|
||||||
}
|
}
|
||||||
18
common/commonspace/treegetter/treegetter.go
Normal file
18
common/commonspace/treegetter/treegetter.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//go:generate mockgen -destination mock_treegetter/mock_treegetter.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter TreeGetter
|
||||||
|
package treegetter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CName = "commonspace.treeGetter"
|
||||||
|
|
||||||
|
var ErrSpaceNotFound = errors.New("space not found")
|
||||||
|
|
||||||
|
type TreeGetter interface {
|
||||||
|
app.ComponentRunnable
|
||||||
|
GetTree(ctx context.Context, spaceId, treeId string) (tree.ObjectTree, error)
|
||||||
|
}
|
||||||
@ -54,3 +54,7 @@ func (c Config) GetGRPCServer() GrpcServer {
|
|||||||
func (c Config) GetAccount() Account {
|
func (c Config) GetAccount() Account {
|
||||||
return c.Account
|
return c.Account
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Config) GetMetric() Metric {
|
||||||
|
return c.Metric
|
||||||
|
}
|
||||||
|
|||||||
@ -54,7 +54,6 @@ func (p *pool) Init(a *app.App) (err error) {
|
|||||||
ocache.WithLogger(log.Sugar()),
|
ocache.WithLogger(log.Sugar()),
|
||||||
ocache.WithGCPeriod(time.Minute),
|
ocache.WithGCPeriod(time.Minute),
|
||||||
ocache.WithTTL(time.Minute*5),
|
ocache.WithTTL(time.Minute*5),
|
||||||
ocache.WithRefCounter(false),
|
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,20 +63,17 @@ message ACLUserAdd {
|
|||||||
ACLUserPermissions permissions = 4;
|
ACLUserPermissions permissions = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// signing accept key
|
|
||||||
// rsa encryption key -> read keys
|
|
||||||
|
|
||||||
// accept key, encrypt key, invite id
|
// accept key, encrypt key, invite id
|
||||||
// GetSpace(id) -> ... (space header + acl root) -> diff
|
// GetSpace(id) -> ... (space header + acl root) -> diff
|
||||||
// Join(ACLJoinRecord) -> Ok
|
// Join(ACLJoinRecord) -> Ok
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
message ACLUserInvite {
|
message ACLUserInvite {
|
||||||
bytes acceptPublicKey = 1;
|
bytes acceptPublicKey = 1;
|
||||||
|
// TODO: change to read key
|
||||||
bytes encryptPublicKey = 2;
|
bytes encryptPublicKey = 2;
|
||||||
repeated bytes encryptedReadKeys = 3;
|
repeated bytes encryptedReadKeys = 3;
|
||||||
ACLUserPermissions permissions = 4;
|
ACLUserPermissions permissions = 4;
|
||||||
|
// TODO: either derive inviteId from pub keys or think if it is possible to just use ACL record id
|
||||||
string inviteId = 5;
|
string inviteId = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,10 +5,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
aclrecordproto2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
|
||||||
signingkey2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -30,17 +30,17 @@ var ErrIncorrectRoot = errors.New("incorrect root")
|
|||||||
|
|
||||||
type UserPermissionPair struct {
|
type UserPermissionPair struct {
|
||||||
Identity string
|
Identity string
|
||||||
Permission aclrecordproto2.ACLUserPermissions
|
Permission aclrecordproto.ACLUserPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
type ACLState struct {
|
type ACLState struct {
|
||||||
id string
|
id string
|
||||||
currentReadKeyHash uint64
|
currentReadKeyHash uint64
|
||||||
userReadKeys map[uint64]*symmetric.Key
|
userReadKeys map[uint64]*symmetric.Key
|
||||||
userStates map[string]*aclrecordproto2.ACLUserState
|
userStates map[string]*aclrecordproto.ACLUserState
|
||||||
userInvites map[string]*aclrecordproto2.ACLUserInvite
|
userInvites map[string]*aclrecordproto.ACLUserInvite
|
||||||
encryptionKey encryptionkey.PrivKey
|
encryptionKey encryptionkey.PrivKey
|
||||||
signingKey signingkey2.PrivKey
|
signingKey signingkey.PrivKey
|
||||||
|
|
||||||
identity string
|
identity string
|
||||||
permissionsAtRecord map[string][]UserPermissionPair
|
permissionsAtRecord map[string][]UserPermissionPair
|
||||||
@ -50,9 +50,9 @@ type ACLState struct {
|
|||||||
|
|
||||||
func newACLStateWithKeys(
|
func newACLStateWithKeys(
|
||||||
id string,
|
id string,
|
||||||
signingKey signingkey2.PrivKey,
|
signingKey signingkey.PrivKey,
|
||||||
encryptionKey encryptionkey.PrivKey) (*ACLState, error) {
|
encryptionKey encryptionkey.PrivKey) (*ACLState, error) {
|
||||||
identity, err := signingKey.Raw()
|
identity, err := signingKey.GetPublic().Raw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -62,8 +62,8 @@ func newACLStateWithKeys(
|
|||||||
signingKey: signingKey,
|
signingKey: signingKey,
|
||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||||
userStates: make(map[string]*aclrecordproto2.ACLUserState),
|
userStates: make(map[string]*aclrecordproto.ACLUserState),
|
||||||
userInvites: make(map[string]*aclrecordproto2.ACLUserInvite),
|
userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -72,8 +72,8 @@ func newACLState(id string) *ACLState {
|
|||||||
return &ACLState{
|
return &ACLState{
|
||||||
id: id,
|
id: id,
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||||
userStates: make(map[string]*aclrecordproto2.ACLUserState),
|
userStates: make(map[string]*aclrecordproto.ACLUserState),
|
||||||
userInvites: make(map[string]*aclrecordproto2.ACLUserInvite),
|
userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,16 +111,19 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
|
|||||||
|
|
||||||
func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
|
func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
|
||||||
if record.Id == st.id {
|
if record.Id == st.id {
|
||||||
root, ok := record.Model.(*aclrecordproto2.ACLRoot)
|
root, ok := record.Model.(*aclrecordproto.ACLRoot)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrIncorrectRoot
|
return ErrIncorrectRoot
|
||||||
}
|
}
|
||||||
|
st.permissionsAtRecord[record.Id] = []UserPermissionPair{
|
||||||
|
{Identity: string(root.Identity), Permission: aclrecordproto.ACLUserPermissions_Admin},
|
||||||
|
}
|
||||||
return st.applyRoot(root)
|
return st.applyRoot(root)
|
||||||
}
|
}
|
||||||
aclData := &aclrecordproto2.ACLData{}
|
aclData := &aclrecordproto.ACLData{}
|
||||||
|
|
||||||
if record.Model != nil {
|
if record.Model != nil {
|
||||||
aclData = record.Model.(*aclrecordproto2.ACLData)
|
aclData = record.Model.(*aclrecordproto.ACLData)
|
||||||
} else {
|
} else {
|
||||||
err = proto.Unmarshal(record.Data, aclData)
|
err = proto.Unmarshal(record.Data, aclData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -148,8 +151,8 @@ func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyRoot(root *aclrecordproto2.ACLRoot) (err error) {
|
func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
|
||||||
if st.signingKey != nil && st.encryptionKey != nil {
|
if st.signingKey != nil && st.encryptionKey != nil && st.identity == string(root.Identity) {
|
||||||
err = st.saveReadKeyFromRoot(root)
|
err = st.saveReadKeyFromRoot(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -157,16 +160,16 @@ func (st *ACLState) applyRoot(root *aclrecordproto2.ACLRoot) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adding user to the list
|
// adding user to the list
|
||||||
userState := &aclrecordproto2.ACLUserState{
|
userState := &aclrecordproto.ACLUserState{
|
||||||
Identity: root.Identity,
|
Identity: root.Identity,
|
||||||
EncryptionKey: root.EncryptionKey,
|
EncryptionKey: root.EncryptionKey,
|
||||||
Permissions: aclrecordproto2.ACLUserPermissions_Admin,
|
Permissions: aclrecordproto.ACLUserPermissions_Admin,
|
||||||
}
|
}
|
||||||
st.userStates[string(root.Identity)] = userState
|
st.userStates[string(root.Identity)] = userState
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto2.ACLRoot) (err error) {
|
func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.ACLRoot) (err error) {
|
||||||
var readKey *symmetric.Key
|
var readKey *symmetric.Key
|
||||||
if len(root.GetDerivationScheme()) != 0 {
|
if len(root.GetDerivationScheme()) != 0 {
|
||||||
var encPubKey []byte
|
var encPubKey []byte
|
||||||
@ -175,7 +178,7 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto2.ACLRoot) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
readKey, err = aclrecordproto2.ACLReadKeyDerive([]byte(st.identity), encPubKey)
|
readKey, err = aclrecordproto.ACLReadKeyDerive([]byte(st.identity), encPubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -199,7 +202,7 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto2.ACLRoot) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeData(changeData *aclrecordproto2.ACLData, hash uint64, identity []byte) (err error) {
|
func (st *ACLState) applyChangeData(changeData *aclrecordproto.ACLData, hash uint64, identity []byte) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -214,7 +217,7 @@ func (st *ACLState) applyChangeData(changeData *aclrecordproto2.ACLData, hash ui
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !st.hasPermission(identity, aclrecordproto2.ACLUserPermissions_Admin) {
|
if !st.hasPermission(identity, aclrecordproto.ACLUserPermissions_Admin) {
|
||||||
err = fmt.Errorf("user %s must have admin permissions", identity)
|
err = fmt.Errorf("user %s must have admin permissions", identity)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -230,7 +233,7 @@ func (st *ACLState) applyChangeData(changeData *aclrecordproto2.ACLData, hash ui
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeContent(ch *aclrecordproto2.ACLContentValue) error {
|
func (st *ACLState) applyChangeContent(ch *aclrecordproto.ACLContentValue) error {
|
||||||
switch {
|
switch {
|
||||||
case ch.GetUserPermissionChange() != nil:
|
case ch.GetUserPermissionChange() != nil:
|
||||||
return st.applyUserPermissionChange(ch.GetUserPermissionChange())
|
return st.applyUserPermissionChange(ch.GetUserPermissionChange())
|
||||||
@ -247,7 +250,7 @@ func (st *ACLState) applyChangeContent(ch *aclrecordproto2.ACLContentValue) erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto2.ACLUserPermissionChange) error {
|
func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto.ACLUserPermissionChange) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
state, exists := st.userStates[chIdentity]
|
state, exists := st.userStates[chIdentity]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -258,12 +261,12 @@ func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto2.ACLUserPermiss
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserInvite(ch *aclrecordproto2.ACLUserInvite) error {
|
func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error {
|
||||||
st.userInvites[ch.InviteId] = ch
|
st.userInvites[ch.InviteId] = ch
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
|
func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
|
||||||
invite, exists := st.userInvites[ch.InviteId]
|
invite, exists := st.userInvites[ch.InviteId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return fmt.Errorf("no such invite with id %s", ch.InviteId)
|
return fmt.Errorf("no such invite with id %s", ch.InviteId)
|
||||||
@ -276,12 +279,12 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
|
|||||||
|
|
||||||
// validating signature
|
// validating signature
|
||||||
signature := ch.GetAcceptSignature()
|
signature := ch.GetAcceptSignature()
|
||||||
verificationKey, err := signingkey2.NewSigningEd25519PubKeyFromBytes(invite.AcceptPublicKey)
|
verificationKey, err := signingkey.NewSigningEd25519PubKeyFromBytes(invite.AcceptPublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err)
|
return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := verificationKey.(signingkey2.PubKey).Verify(ch.Identity, signature)
|
res, err := verificationKey.(signingkey.PubKey).Verify(ch.Identity, signature)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("verification returned error: %w", err)
|
return fmt.Errorf("verification returned error: %w", err)
|
||||||
}
|
}
|
||||||
@ -302,7 +305,7 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adding user to the list
|
// adding user to the list
|
||||||
userState := &aclrecordproto2.ACLUserState{
|
userState := &aclrecordproto.ACLUserState{
|
||||||
Identity: ch.Identity,
|
Identity: ch.Identity,
|
||||||
EncryptionKey: ch.EncryptionKey,
|
EncryptionKey: ch.EncryptionKey,
|
||||||
Permissions: invite.Permissions,
|
Permissions: invite.Permissions,
|
||||||
@ -311,13 +314,13 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserAdd(ch *aclrecordproto2.ACLUserAdd) error {
|
func (st *ACLState) applyUserAdd(ch *aclrecordproto.ACLUserAdd) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
if _, exists := st.userStates[chIdentity]; exists {
|
if _, exists := st.userStates[chIdentity]; exists {
|
||||||
return ErrUserAlreadyExists
|
return ErrUserAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
st.userStates[chIdentity] = &aclrecordproto2.ACLUserState{
|
st.userStates[chIdentity] = &aclrecordproto.ACLUserState{
|
||||||
Identity: ch.Identity,
|
Identity: ch.Identity,
|
||||||
EncryptionKey: ch.EncryptionKey,
|
EncryptionKey: ch.EncryptionKey,
|
||||||
Permissions: ch.Permissions,
|
Permissions: ch.Permissions,
|
||||||
@ -337,7 +340,7 @@ func (st *ACLState) applyUserAdd(ch *aclrecordproto2.ACLUserAdd) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserRemove(ch *aclrecordproto2.ACLUserRemove) error {
|
func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
if chIdentity == st.identity {
|
if chIdentity == st.identity {
|
||||||
return ErrDocumentForbidden
|
return ErrDocumentForbidden
|
||||||
@ -381,7 +384,7 @@ func (st *ACLState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e
|
|||||||
return key, hasher.Sum64(), nil
|
return key, hasher.Sum64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto2.ACLUserPermissions) bool {
|
func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto.ACLUserPermissions) bool {
|
||||||
state, exists := st.userStates[string(identity)]
|
state, exists := st.userStates[string(identity)]
|
||||||
if !exists {
|
if !exists {
|
||||||
return false
|
return false
|
||||||
@ -390,17 +393,17 @@ func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto2.AC
|
|||||||
return state.Permissions == permission
|
return state.Permissions == permission
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) isUserJoin(data *aclrecordproto2.ACLData) bool {
|
func (st *ACLState) isUserJoin(data *aclrecordproto.ACLData) bool {
|
||||||
// if we have a UserJoin, then it should always be the first one applied
|
// if we have a UserJoin, then it should always be the first one applied
|
||||||
return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil
|
return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) isUserAdd(data *aclrecordproto2.ACLData, identity []byte) bool {
|
func (st *ACLState) isUserAdd(data *aclrecordproto.ACLData, identity []byte) bool {
|
||||||
// if we have a UserAdd, then it should always be the first one applied
|
// if we have a UserAdd, then it should always be the first one applied
|
||||||
userAdd := data.GetAclContent()[0].GetUserAdd()
|
userAdd := data.GetAclContent()[0].GetUserAdd()
|
||||||
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0
|
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) GetUserStates() map[string]*aclrecordproto2.ACLUserState {
|
func (st *ACLState) GetUserStates() map[string]*aclrecordproto.ACLUserState {
|
||||||
return st.userStates
|
return st.userStates
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
package mock_list
|
package mock_list
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
|
||||||
list2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
aclrecordproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
||||||
|
list "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,10 +36,10 @@ func (m *MockACLList) EXPECT() *MockACLListMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ACLState mocks base method.
|
// ACLState mocks base method.
|
||||||
func (m *MockACLList) ACLState() *list2.ACLState {
|
func (m *MockACLList) ACLState() *list.ACLState {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ACLState")
|
ret := m.ctrl.Call(m, "ACLState")
|
||||||
ret0, _ := ret[0].(*list2.ACLState)
|
ret0, _ := ret[0].(*list.ACLState)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,10 +64,10 @@ func (mr *MockACLListMockRecorder) Close() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get mocks base method.
|
// Get mocks base method.
|
||||||
func (m *MockACLList) Get(arg0 string) (*list2.ACLRecord, error) {
|
func (m *MockACLList) Get(arg0 string) (*list.ACLRecord, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Get", arg0)
|
ret := m.ctrl.Call(m, "Get", arg0)
|
||||||
ret0, _ := ret[0].(*list2.ACLRecord)
|
ret0, _ := ret[0].(*list.ACLRecord)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
@ -79,10 +79,10 @@ func (mr *MockACLListMockRecorder) Get(arg0 interface{}) *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Head mocks base method.
|
// Head mocks base method.
|
||||||
func (m *MockACLList) Head() *list2.ACLRecord {
|
func (m *MockACLList) Head() *list.ACLRecord {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Head")
|
ret := m.ctrl.Call(m, "Head")
|
||||||
ret0, _ := ret[0].(*list2.ACLRecord)
|
ret0, _ := ret[0].(*list.ACLRecord)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ func (mr *MockACLListMockRecorder) IsAfter(arg0, arg1 interface{}) *gomock.Call
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterate mocks base method.
|
// Iterate mocks base method.
|
||||||
func (m *MockACLList) Iterate(arg0 func(*list2.ACLRecord) bool) {
|
func (m *MockACLList) Iterate(arg0 func(*list.ACLRecord) bool) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "Iterate", arg0)
|
m.ctrl.Call(m, "Iterate", arg0)
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ func (mr *MockACLListMockRecorder) Iterate(arg0 interface{}) *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IterateFrom mocks base method.
|
// IterateFrom mocks base method.
|
||||||
func (m *MockACLList) IterateFrom(arg0 string, arg1 func(*list2.ACLRecord) bool) {
|
func (m *MockACLList) IterateFrom(arg0 string, arg1 func(*list.ACLRecord) bool) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "IterateFrom", arg0, arg1)
|
m.ctrl.Call(m, "IterateFrom", arg0, arg1)
|
||||||
}
|
}
|
||||||
@ -182,10 +182,10 @@ func (mr *MockACLListMockRecorder) RUnlock() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Records mocks base method.
|
// Records mocks base method.
|
||||||
func (m *MockACLList) Records() []*list2.ACLRecord {
|
func (m *MockACLList) Records() []*list.ACLRecord {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Records")
|
ret := m.ctrl.Call(m, "Records")
|
||||||
ret0, _ := ret[0].([]*list2.ACLRecord)
|
ret0, _ := ret[0].([]*list.ACLRecord)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,10 @@ package mock_storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
aclrecordproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
||||||
|
treechangeproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -22,61 +22,25 @@ var _ = math.Inf
|
|||||||
// proto package needs to be updated.
|
// proto package needs to be updated.
|
||||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||||
|
|
||||||
type PlainTextChange struct {
|
type TextContent struct {
|
||||||
}
|
|
||||||
|
|
||||||
func (m *PlainTextChange) Reset() { *m = PlainTextChange{} }
|
|
||||||
func (m *PlainTextChange) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*PlainTextChange) ProtoMessage() {}
|
|
||||||
func (*PlainTextChange) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0}
|
|
||||||
}
|
|
||||||
func (m *PlainTextChange) XXX_Unmarshal(b []byte) error {
|
|
||||||
return m.Unmarshal(b)
|
|
||||||
}
|
|
||||||
func (m *PlainTextChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
if deterministic {
|
|
||||||
return xxx_messageInfo_PlainTextChange.Marshal(b, m, deterministic)
|
|
||||||
} else {
|
|
||||||
b = b[:cap(b)]
|
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b[:n], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (m *PlainTextChange) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_PlainTextChange.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *PlainTextChange) XXX_Size() int {
|
|
||||||
return m.Size()
|
|
||||||
}
|
|
||||||
func (m *PlainTextChange) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_PlainTextChange.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChange proto.InternalMessageInfo
|
|
||||||
|
|
||||||
type PlainTextChange_Content struct {
|
|
||||||
// Types that are valid to be assigned to Value:
|
// Types that are valid to be assigned to Value:
|
||||||
//
|
//
|
||||||
// *PlainTextChange_Content_TextAppend
|
// *TextContent_TextAppend
|
||||||
Value isPlainTextChange_Content_Value `protobuf_oneof:"value"`
|
Value isTextContent_Value `protobuf_oneof:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) Reset() { *m = PlainTextChange_Content{} }
|
func (m *TextContent) Reset() { *m = TextContent{} }
|
||||||
func (m *PlainTextChange_Content) String() string { return proto.CompactTextString(m) }
|
func (m *TextContent) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChange_Content) ProtoMessage() {}
|
func (*TextContent) ProtoMessage() {}
|
||||||
func (*PlainTextChange_Content) Descriptor() ([]byte, []int) {
|
func (*TextContent) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 0}
|
return fileDescriptor_37f33c266ada4318, []int{0}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Content) XXX_Unmarshal(b []byte) error {
|
func (m *TextContent) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Content) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *TextContent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChange_Content.Marshal(b, m, deterministic)
|
return xxx_messageInfo_TextContent.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -86,67 +50,67 @@ func (m *PlainTextChange_Content) XXX_Marshal(b []byte, deterministic bool) ([]b
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Content) XXX_Merge(src proto.Message) {
|
func (m *TextContent) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChange_Content.Merge(m, src)
|
xxx_messageInfo_TextContent.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Content) XXX_Size() int {
|
func (m *TextContent) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Content) XXX_DiscardUnknown() {
|
func (m *TextContent) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChange_Content.DiscardUnknown(m)
|
xxx_messageInfo_TextContent.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChange_Content proto.InternalMessageInfo
|
var xxx_messageInfo_TextContent proto.InternalMessageInfo
|
||||||
|
|
||||||
type isPlainTextChange_Content_Value interface {
|
type isTextContent_Value interface {
|
||||||
isPlainTextChange_Content_Value()
|
isTextContent_Value()
|
||||||
MarshalTo([]byte) (int, error)
|
MarshalTo([]byte) (int, error)
|
||||||
Size() int
|
Size() int
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChange_Content_TextAppend struct {
|
type TextContent_TextAppend struct {
|
||||||
TextAppend *PlainTextChange_TextAppend `protobuf:"bytes,1,opt,name=textAppend,proto3,oneof" json:"textAppend,omitempty"`
|
TextAppend *TextAppend `protobuf:"bytes,1,opt,name=textAppend,proto3,oneof" json:"textAppend,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*PlainTextChange_Content_TextAppend) isPlainTextChange_Content_Value() {}
|
func (*TextContent_TextAppend) isTextContent_Value() {}
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) GetValue() isPlainTextChange_Content_Value {
|
func (m *TextContent) GetValue() isTextContent_Value {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Value
|
return m.Value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) GetTextAppend() *PlainTextChange_TextAppend {
|
func (m *TextContent) GetTextAppend() *TextAppend {
|
||||||
if x, ok := m.GetValue().(*PlainTextChange_Content_TextAppend); ok {
|
if x, ok := m.GetValue().(*TextContent_TextAppend); ok {
|
||||||
return x.TextAppend
|
return x.TextAppend
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX_OneofWrappers is for the internal use of the proto package.
|
// XXX_OneofWrappers is for the internal use of the proto package.
|
||||||
func (*PlainTextChange_Content) XXX_OneofWrappers() []interface{} {
|
func (*TextContent) XXX_OneofWrappers() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
(*PlainTextChange_Content_TextAppend)(nil),
|
(*TextContent_TextAppend)(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChange_TextAppend struct {
|
type TextAppend struct {
|
||||||
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_TextAppend) Reset() { *m = PlainTextChange_TextAppend{} }
|
func (m *TextAppend) Reset() { *m = TextAppend{} }
|
||||||
func (m *PlainTextChange_TextAppend) String() string { return proto.CompactTextString(m) }
|
func (m *TextAppend) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChange_TextAppend) ProtoMessage() {}
|
func (*TextAppend) ProtoMessage() {}
|
||||||
func (*PlainTextChange_TextAppend) Descriptor() ([]byte, []int) {
|
func (*TextAppend) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 1}
|
return fileDescriptor_37f33c266ada4318, []int{1}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) XXX_Unmarshal(b []byte) error {
|
func (m *TextAppend) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *TextAppend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChange_TextAppend.Marshal(b, m, deterministic)
|
return xxx_messageInfo_TextAppend.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -156,41 +120,41 @@ func (m *PlainTextChange_TextAppend) XXX_Marshal(b []byte, deterministic bool) (
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) XXX_Merge(src proto.Message) {
|
func (m *TextAppend) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChange_TextAppend.Merge(m, src)
|
xxx_messageInfo_TextAppend.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) XXX_Size() int {
|
func (m *TextAppend) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) XXX_DiscardUnknown() {
|
func (m *TextAppend) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChange_TextAppend.DiscardUnknown(m)
|
xxx_messageInfo_TextAppend.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChange_TextAppend proto.InternalMessageInfo
|
var xxx_messageInfo_TextAppend proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *PlainTextChange_TextAppend) GetText() string {
|
func (m *TextAppend) GetText() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Text
|
return m.Text
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChange_Snapshot struct {
|
type TextSnapshot struct {
|
||||||
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Snapshot) Reset() { *m = PlainTextChange_Snapshot{} }
|
func (m *TextSnapshot) Reset() { *m = TextSnapshot{} }
|
||||||
func (m *PlainTextChange_Snapshot) String() string { return proto.CompactTextString(m) }
|
func (m *TextSnapshot) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChange_Snapshot) ProtoMessage() {}
|
func (*TextSnapshot) ProtoMessage() {}
|
||||||
func (*PlainTextChange_Snapshot) Descriptor() ([]byte, []int) {
|
func (*TextSnapshot) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 2}
|
return fileDescriptor_37f33c266ada4318, []int{2}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Snapshot) XXX_Unmarshal(b []byte) error {
|
func (m *TextSnapshot) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *TextSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChange_Snapshot.Marshal(b, m, deterministic)
|
return xxx_messageInfo_TextSnapshot.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -200,42 +164,42 @@ func (m *PlainTextChange_Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Snapshot) XXX_Merge(src proto.Message) {
|
func (m *TextSnapshot) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChange_Snapshot.Merge(m, src)
|
xxx_messageInfo_TextSnapshot.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Snapshot) XXX_Size() int {
|
func (m *TextSnapshot) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Snapshot) XXX_DiscardUnknown() {
|
func (m *TextSnapshot) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChange_Snapshot.DiscardUnknown(m)
|
xxx_messageInfo_TextSnapshot.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChange_Snapshot proto.InternalMessageInfo
|
var xxx_messageInfo_TextSnapshot proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *PlainTextChange_Snapshot) GetText() string {
|
func (m *TextSnapshot) GetText() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Text
|
return m.Text
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChange_Data struct {
|
type TextData struct {
|
||||||
Content []*PlainTextChange_Content `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
|
Content []*TextContent `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
|
||||||
Snapshot *PlainTextChange_Snapshot `protobuf:"bytes,2,opt,name=snapshot,proto3" json:"snapshot,omitempty"`
|
Snapshot *TextSnapshot `protobuf:"bytes,2,opt,name=snapshot,proto3" json:"snapshot,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) Reset() { *m = PlainTextChange_Data{} }
|
func (m *TextData) Reset() { *m = TextData{} }
|
||||||
func (m *PlainTextChange_Data) String() string { return proto.CompactTextString(m) }
|
func (m *TextData) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChange_Data) ProtoMessage() {}
|
func (*TextData) ProtoMessage() {}
|
||||||
func (*PlainTextChange_Data) Descriptor() ([]byte, []int) {
|
func (*TextData) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 3}
|
return fileDescriptor_37f33c266ada4318, []int{3}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Data) XXX_Unmarshal(b []byte) error {
|
func (m *TextData) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Data) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *TextData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChange_Data.Marshal(b, m, deterministic)
|
return xxx_messageInfo_TextData.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -245,26 +209,26 @@ func (m *PlainTextChange_Data) XXX_Marshal(b []byte, deterministic bool) ([]byte
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Data) XXX_Merge(src proto.Message) {
|
func (m *TextData) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChange_Data.Merge(m, src)
|
xxx_messageInfo_TextData.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Data) XXX_Size() int {
|
func (m *TextData) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Data) XXX_DiscardUnknown() {
|
func (m *TextData) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChange_Data.DiscardUnknown(m)
|
xxx_messageInfo_TextData.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChange_Data proto.InternalMessageInfo
|
var xxx_messageInfo_TextData proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) GetContent() []*PlainTextChange_Content {
|
func (m *TextData) GetContent() []*TextContent {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Content
|
return m.Content
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) GetSnapshot() *PlainTextChange_Snapshot {
|
func (m *TextData) GetSnapshot() *TextSnapshot {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Snapshot
|
return m.Snapshot
|
||||||
}
|
}
|
||||||
@ -272,11 +236,10 @@ func (m *PlainTextChange_Data) GetSnapshot() *PlainTextChange_Snapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*PlainTextChange)(nil), "anytype.PlainTextChange")
|
proto.RegisterType((*TextContent)(nil), "anytype.TextContent")
|
||||||
proto.RegisterType((*PlainTextChange_Content)(nil), "anytype.PlainTextChange.Content")
|
proto.RegisterType((*TextAppend)(nil), "anytype.TextAppend")
|
||||||
proto.RegisterType((*PlainTextChange_TextAppend)(nil), "anytype.PlainTextChange.TextAppend")
|
proto.RegisterType((*TextSnapshot)(nil), "anytype.TextSnapshot")
|
||||||
proto.RegisterType((*PlainTextChange_Snapshot)(nil), "anytype.PlainTextChange.Snapshot")
|
proto.RegisterType((*TextData)(nil), "anytype.TextData")
|
||||||
proto.RegisterType((*PlainTextChange_Data)(nil), "anytype.PlainTextChange.Data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -284,27 +247,26 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_37f33c266ada4318 = []byte{
|
var fileDescriptor_37f33c266ada4318 = []byte{
|
||||||
// 266 bytes of a gzipped FileDescriptorProto
|
// 252 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2b, 0xc8, 0x4e, 0xd7,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2b, 0xc8, 0x4e, 0xd7,
|
||||||
0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x49, 0x2d, 0x2e, 0x29, 0x2d, 0xc9, 0xcc, 0x29, 0x06, 0xb3, 0x92,
|
0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x49, 0x2d, 0x2e, 0x29, 0x2d, 0xc9, 0xcc, 0x29, 0x06, 0xb3, 0x92,
|
||||||
0x33, 0x12, 0xf3, 0xd2, 0x53, 0x8b, 0xf5, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0xc1, 0x22, 0x7a, 0x60,
|
0x33, 0x12, 0xf3, 0xd2, 0x53, 0x8b, 0xf5, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0xc1, 0x22, 0x7a, 0x60,
|
||||||
0xa6, 0x10, 0x7b, 0x62, 0x5e, 0x65, 0x49, 0x65, 0x41, 0xaa, 0xd2, 0x26, 0x26, 0x2e, 0xfe, 0x80,
|
0xa6, 0x10, 0x7b, 0x62, 0x5e, 0x65, 0x49, 0x65, 0x41, 0xaa, 0x92, 0x2f, 0x17, 0x77, 0x48, 0x6a,
|
||||||
0x9c, 0xc4, 0xcc, 0xbc, 0x90, 0xd4, 0x8a, 0x12, 0x67, 0xb0, 0x72, 0xa9, 0x48, 0x2e, 0x76, 0xe7,
|
0x45, 0x89, 0x73, 0x7e, 0x5e, 0x49, 0x6a, 0x5e, 0x89, 0x90, 0x29, 0x17, 0x57, 0x49, 0x6a, 0x45,
|
||||||
0xfc, 0xbc, 0x92, 0xd4, 0xbc, 0x12, 0x21, 0x57, 0x2e, 0xae, 0x92, 0xd4, 0x8a, 0x12, 0xc7, 0x82,
|
0x89, 0x63, 0x41, 0x41, 0x6a, 0x5e, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, 0xb0, 0x1e,
|
||||||
0x82, 0xd4, 0xbc, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x65, 0x3d, 0xa8, 0x66, 0x3d,
|
0x54, 0xb1, 0x5e, 0x08, 0x5c, 0xca, 0x83, 0x21, 0x08, 0x49, 0xa1, 0x13, 0x3b, 0x17, 0x6b, 0x59,
|
||||||
0x34, 0x8d, 0x7a, 0x21, 0x70, 0xa5, 0x1e, 0x0c, 0x41, 0x48, 0x1a, 0x9d, 0xd8, 0xb9, 0x58, 0xcb,
|
0x62, 0x4e, 0x69, 0xaa, 0x92, 0x02, 0x17, 0x17, 0x42, 0x91, 0x90, 0x10, 0x17, 0x0b, 0x48, 0x11,
|
||||||
0x12, 0x73, 0x4a, 0x53, 0xa5, 0x14, 0xb8, 0xb8, 0x10, 0x8a, 0x84, 0x84, 0xb8, 0x58, 0x40, 0x8a,
|
0xd8, 0x1c, 0xce, 0x20, 0x30, 0x5b, 0x49, 0x89, 0x8b, 0x07, 0xa4, 0x22, 0x38, 0x2f, 0xb1, 0xa0,
|
||||||
0xc0, 0xe6, 0x72, 0x06, 0x81, 0xd9, 0x52, 0x72, 0x5c, 0x1c, 0xc1, 0x79, 0x89, 0x05, 0xc5, 0x19,
|
0x38, 0x23, 0xbf, 0x04, 0xab, 0x9a, 0x5c, 0x2e, 0x0e, 0x90, 0x1a, 0x97, 0xc4, 0x92, 0x44, 0x21,
|
||||||
0xf9, 0x25, 0x58, 0xe5, 0x1b, 0x19, 0xb9, 0x58, 0x5c, 0x12, 0x4b, 0x12, 0x85, 0xac, 0xb8, 0xd8,
|
0x3d, 0x2e, 0xf6, 0x64, 0x88, 0xe3, 0x24, 0x18, 0x15, 0x98, 0x35, 0xb8, 0x8d, 0x44, 0x50, 0x9c,
|
||||||
0x93, 0x21, 0xae, 0x94, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x52, 0xc0, 0xe9, 0x2e, 0xa8, 0x6f,
|
0x03, 0x75, 0x78, 0x10, 0x4c, 0x91, 0x90, 0x21, 0x17, 0x47, 0x31, 0xd4, 0x6c, 0x09, 0x26, 0xb0,
|
||||||
0x82, 0x60, 0x1a, 0x84, 0x6c, 0xb9, 0x38, 0x8a, 0xa1, 0x96, 0x48, 0x30, 0x81, 0x3d, 0xa5, 0x88,
|
0xfb, 0x45, 0x51, 0x34, 0xc0, 0x2c, 0x0e, 0x82, 0x2b, 0x73, 0x52, 0x3d, 0xf1, 0x48, 0x8e, 0xf1,
|
||||||
0x53, 0x33, 0xcc, 0x35, 0x41, 0x70, 0x2d, 0x4e, 0xaa, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24,
|
0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e,
|
||||||
0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78,
|
0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x6e, 0xa4, 0x40, 0x4c, 0x62, 0x03, 0x07, 0x9d, 0x31, 0x20,
|
||||||
0x2c, 0xc7, 0x10, 0xc5, 0x8d, 0x14, 0xea, 0x49, 0x6c, 0xe0, 0xb0, 0x36, 0x06, 0x04, 0x00, 0x00,
|
0x00, 0x00, 0xff, 0xff, 0xdc, 0xbf, 0x78, 0xe5, 0x6c, 0x01, 0x00, 0x00,
|
||||||
0xff, 0xff, 0xf8, 0x8c, 0x6a, 0x1d, 0x9d, 0x01, 0x00, 0x00,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange) Marshal() (dAtA []byte, err error) {
|
func (m *TextContent) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -314,35 +276,12 @@ func (m *PlainTextChange) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange) MarshalTo(dAtA []byte) (int, error) {
|
func (m *TextContent) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *TextContent) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
|
||||||
_ = i
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
return len(dAtA) - i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) Marshal() (dAtA []byte, err error) {
|
|
||||||
size := m.Size()
|
|
||||||
dAtA = make([]byte, size)
|
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dAtA[:n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) MarshalTo(dAtA []byte) (int, error) {
|
|
||||||
size := m.Size()
|
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -359,12 +298,12 @@ func (m *PlainTextChange_Content) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Content_TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
func (m *TextContent_TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Content_TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *TextContent_TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
if m.TextAppend != nil {
|
if m.TextAppend != nil {
|
||||||
{
|
{
|
||||||
@ -380,7 +319,7 @@ func (m *PlainTextChange_Content_TextAppend) MarshalToSizedBuffer(dAtA []byte) (
|
|||||||
}
|
}
|
||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) Marshal() (dAtA []byte, err error) {
|
func (m *TextAppend) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -390,12 +329,12 @@ func (m *PlainTextChange_TextAppend) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
func (m *TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -410,7 +349,7 @@ func (m *PlainTextChange_TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, err
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Snapshot) Marshal() (dAtA []byte, err error) {
|
func (m *TextSnapshot) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -420,12 +359,12 @@ func (m *PlainTextChange_Snapshot) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Snapshot) MarshalTo(dAtA []byte) (int, error) {
|
func (m *TextSnapshot) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *TextSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -440,7 +379,7 @@ func (m *PlainTextChange_Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) Marshal() (dAtA []byte, err error) {
|
func (m *TextData) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -450,12 +389,12 @@ func (m *PlainTextChange_Data) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) MarshalTo(dAtA []byte) (int, error) {
|
func (m *TextData) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *TextData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -500,16 +439,7 @@ func encodeVarintTest(dAtA []byte, offset int, v uint64) int {
|
|||||||
dAtA[offset] = uint8(v)
|
dAtA[offset] = uint8(v)
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange) Size() (n int) {
|
func (m *TextContent) Size() (n int) {
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *PlainTextChange_Content) Size() (n int) {
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -521,7 +451,7 @@ func (m *PlainTextChange_Content) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Content_TextAppend) Size() (n int) {
|
func (m *TextContent_TextAppend) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -533,7 +463,7 @@ func (m *PlainTextChange_Content_TextAppend) Size() (n int) {
|
|||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) Size() (n int) {
|
func (m *TextAppend) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -546,7 +476,7 @@ func (m *PlainTextChange_TextAppend) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Snapshot) Size() (n int) {
|
func (m *TextSnapshot) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -559,7 +489,7 @@ func (m *PlainTextChange_Snapshot) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChange_Data) Size() (n int) {
|
func (m *TextData) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -584,7 +514,7 @@ func sovTest(x uint64) (n int) {
|
|||||||
func sozTest(x uint64) (n int) {
|
func sozTest(x uint64) (n int) {
|
||||||
return sovTest(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
return sovTest(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange) Unmarshal(dAtA []byte) error {
|
func (m *TextContent) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -607,60 +537,10 @@ func (m *PlainTextChange) Unmarshal(dAtA []byte) error {
|
|||||||
fieldNum := int32(wire >> 3)
|
fieldNum := int32(wire >> 3)
|
||||||
wireType := int(wire & 0x7)
|
wireType := int(wire & 0x7)
|
||||||
if wireType == 4 {
|
if wireType == 4 {
|
||||||
return fmt.Errorf("proto: PlainTextChange: wiretype end group for non-group")
|
return fmt.Errorf("proto: TextContent: wiretype end group for non-group")
|
||||||
}
|
}
|
||||||
if fieldNum <= 0 {
|
if fieldNum <= 0 {
|
||||||
return fmt.Errorf("proto: PlainTextChange: illegal tag %d (wire type %d)", fieldNum, wire)
|
return fmt.Errorf("proto: TextContent: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
}
|
|
||||||
switch fieldNum {
|
|
||||||
default:
|
|
||||||
iNdEx = preIndex
|
|
||||||
skippy, err := skipTest(dAtA[iNdEx:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
|
||||||
return ErrInvalidLengthTest
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx += skippy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iNdEx > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (m *PlainTextChange_Content) Unmarshal(dAtA []byte) error {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
preIndex := iNdEx
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowTest
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldNum := int32(wire >> 3)
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
if wireType == 4 {
|
|
||||||
return fmt.Errorf("proto: Content: wiretype end group for non-group")
|
|
||||||
}
|
|
||||||
if fieldNum <= 0 {
|
|
||||||
return fmt.Errorf("proto: Content: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
||||||
}
|
}
|
||||||
switch fieldNum {
|
switch fieldNum {
|
||||||
case 1:
|
case 1:
|
||||||
@ -692,11 +572,11 @@ func (m *PlainTextChange_Content) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
v := &PlainTextChange_TextAppend{}
|
v := &TextAppend{}
|
||||||
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.Value = &PlainTextChange_Content_TextAppend{v}
|
m.Value = &TextContent_TextAppend{v}
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
@ -719,7 +599,7 @@ func (m *PlainTextChange_Content) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_TextAppend) Unmarshal(dAtA []byte) error {
|
func (m *TextAppend) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -801,7 +681,7 @@ func (m *PlainTextChange_TextAppend) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Snapshot) Unmarshal(dAtA []byte) error {
|
func (m *TextSnapshot) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -824,10 +704,10 @@ func (m *PlainTextChange_Snapshot) Unmarshal(dAtA []byte) error {
|
|||||||
fieldNum := int32(wire >> 3)
|
fieldNum := int32(wire >> 3)
|
||||||
wireType := int(wire & 0x7)
|
wireType := int(wire & 0x7)
|
||||||
if wireType == 4 {
|
if wireType == 4 {
|
||||||
return fmt.Errorf("proto: Snapshot: wiretype end group for non-group")
|
return fmt.Errorf("proto: TextSnapshot: wiretype end group for non-group")
|
||||||
}
|
}
|
||||||
if fieldNum <= 0 {
|
if fieldNum <= 0 {
|
||||||
return fmt.Errorf("proto: Snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
|
return fmt.Errorf("proto: TextSnapshot: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
}
|
}
|
||||||
switch fieldNum {
|
switch fieldNum {
|
||||||
case 1:
|
case 1:
|
||||||
@ -883,7 +763,7 @@ func (m *PlainTextChange_Snapshot) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChange_Data) Unmarshal(dAtA []byte) error {
|
func (m *TextData) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -906,10 +786,10 @@ func (m *PlainTextChange_Data) Unmarshal(dAtA []byte) error {
|
|||||||
fieldNum := int32(wire >> 3)
|
fieldNum := int32(wire >> 3)
|
||||||
wireType := int(wire & 0x7)
|
wireType := int(wire & 0x7)
|
||||||
if wireType == 4 {
|
if wireType == 4 {
|
||||||
return fmt.Errorf("proto: Data: wiretype end group for non-group")
|
return fmt.Errorf("proto: TextData: wiretype end group for non-group")
|
||||||
}
|
}
|
||||||
if fieldNum <= 0 {
|
if fieldNum <= 0 {
|
||||||
return fmt.Errorf("proto: Data: illegal tag %d (wire type %d)", fieldNum, wire)
|
return fmt.Errorf("proto: TextData: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
}
|
}
|
||||||
switch fieldNum {
|
switch fieldNum {
|
||||||
case 1:
|
case 1:
|
||||||
@ -941,7 +821,7 @@ func (m *PlainTextChange_Data) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
m.Content = append(m.Content, &PlainTextChange_Content{})
|
m.Content = append(m.Content, &TextContent{})
|
||||||
if err := m.Content[len(m.Content)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Content[len(m.Content)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -976,7 +856,7 @@ func (m *PlainTextChange_Data) Unmarshal(dAtA []byte) error {
|
|||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if m.Snapshot == nil {
|
if m.Snapshot == nil {
|
||||||
m.Snapshot = &PlainTextChange_Snapshot{}
|
m.Snapshot = &TextSnapshot{}
|
||||||
}
|
}
|
||||||
if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -2,23 +2,21 @@ syntax = "proto3";
|
|||||||
package anytype;
|
package anytype;
|
||||||
option go_package = "testchanges";
|
option go_package = "testchanges";
|
||||||
|
|
||||||
message PlainTextChange {
|
message TextContent {
|
||||||
message Content {
|
oneof value {
|
||||||
oneof value {
|
TextAppend textAppend = 1;
|
||||||
TextAppend textAppend = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message TextAppend {
|
message TextAppend {
|
||||||
string text = 1;
|
string text = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Snapshot {
|
message TextSnapshot {
|
||||||
string text = 1;
|
string text = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Data {
|
message TextData {
|
||||||
repeated Content content = 1;
|
repeated TextContent content = 1;
|
||||||
Snapshot snapshot = 2;
|
TextSnapshot snapshot = 2;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -71,6 +71,10 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChang
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ch, err = c.unmarshallRawChange(raw, rawIdChange.Id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if verify {
|
if verify {
|
||||||
var identityKey signingkey.PubKey
|
var identityKey signingkey.PubKey
|
||||||
@ -90,8 +94,7 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChang
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
return c.unmarshallRawChange(raw, rawIdChange.Id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {
|
func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {
|
||||||
|
|||||||
@ -53,6 +53,10 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list2.ACLList,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Id == tree.RootId() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// checking if the change refers to later acl heads than its previous ids
|
// checking if the change refers to later acl heads than its previous ids
|
||||||
for _, id := range c.PreviousIds {
|
for _, id := range c.PreviousIds {
|
||||||
prevChange := tree.attached[id]
|
prevChange := tree.attached[id]
|
||||||
|
|||||||
@ -6,11 +6,11 @@ package mock_tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
|
||||||
tree2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
|
treechangeproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,10 +38,10 @@ func (m *MockObjectTree) EXPECT() *MockObjectTreeMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddContent mocks base method.
|
// AddContent mocks base method.
|
||||||
func (m *MockObjectTree) AddContent(arg0 context.Context, arg1 tree2.SignableChangeContent) (tree2.AddResult, error) {
|
func (m *MockObjectTree) AddContent(arg0 context.Context, arg1 tree.SignableChangeContent) (tree.AddResult, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "AddContent", arg0, arg1)
|
ret := m.ctrl.Call(m, "AddContent", arg0, arg1)
|
||||||
ret0, _ := ret[0].(tree2.AddResult)
|
ret0, _ := ret[0].(tree.AddResult)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
@ -53,14 +53,14 @@ func (mr *MockObjectTreeMockRecorder) AddContent(arg0, arg1 interface{}) *gomock
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddRawChanges mocks base method.
|
// AddRawChanges mocks base method.
|
||||||
func (m *MockObjectTree) AddRawChanges(arg0 context.Context, arg1 ...*treechangeproto.RawTreeChangeWithId) (tree2.AddResult, error) {
|
func (m *MockObjectTree) AddRawChanges(arg0 context.Context, arg1 ...*treechangeproto.RawTreeChangeWithId) (tree.AddResult, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
varargs := []interface{}{arg0}
|
varargs := []interface{}{arg0}
|
||||||
for _, a := range arg1 {
|
for _, a := range arg1 {
|
||||||
varargs = append(varargs, a)
|
varargs = append(varargs, a)
|
||||||
}
|
}
|
||||||
ret := m.ctrl.Call(m, "AddRawChanges", varargs...)
|
ret := m.ctrl.Call(m, "AddRawChanges", varargs...)
|
||||||
ret0, _ := ret[0].(tree2.AddResult)
|
ret0, _ := ret[0].(tree.AddResult)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ func (mr *MockObjectTreeMockRecorder) ID() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterate mocks base method.
|
// Iterate mocks base method.
|
||||||
func (m *MockObjectTree) Iterate(arg0 func([]byte) (interface{}, error), arg1 func(*tree2.Change) bool) error {
|
func (m *MockObjectTree) Iterate(arg0 func([]byte) (interface{}, error), arg1 func(*tree.Change) bool) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Iterate", arg0, arg1)
|
ret := m.ctrl.Call(m, "Iterate", arg0, arg1)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
@ -191,7 +191,7 @@ func (mr *MockObjectTreeMockRecorder) Iterate(arg0, arg1 interface{}) *gomock.Ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IterateFrom mocks base method.
|
// IterateFrom mocks base method.
|
||||||
func (m *MockObjectTree) IterateFrom(arg0 string, arg1 func([]byte) (interface{}, error), arg2 func(*tree2.Change) bool) error {
|
func (m *MockObjectTree) IterateFrom(arg0 string, arg1 func([]byte) (interface{}, error), arg2 func(*tree.Change) bool) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "IterateFrom", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "IterateFrom", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
@ -241,10 +241,10 @@ func (mr *MockObjectTreeMockRecorder) RUnlock() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Root mocks base method.
|
// Root mocks base method.
|
||||||
func (m *MockObjectTree) Root() *tree2.Change {
|
func (m *MockObjectTree) Root() *tree.Change {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Root")
|
ret := m.ctrl.Call(m, "Root")
|
||||||
ret0, _ := ret[0].(*tree2.Change)
|
ret0, _ := ret[0].(*tree.Change)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -177,6 +177,8 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont
|
|||||||
Added: []*treechangeproto.RawTreeChangeWithId{rawChange},
|
Added: []*treechangeproto.RawTreeChangeWithId{rawChange},
|
||||||
Mode: Append,
|
Mode: Append,
|
||||||
}
|
}
|
||||||
|
log.With("treeId", ot.id).With("head", objChange.Id).
|
||||||
|
Debug("finished adding content")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package tree
|
package tree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
@ -54,10 +55,7 @@ func createObjectTree(
|
|||||||
aclList list.ACLList,
|
aclList list.ACLList,
|
||||||
createStorage storage2.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
|
createStorage storage2.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
|
||||||
aclList.RLock()
|
aclList.RLock()
|
||||||
var (
|
aclHeadId := aclList.Head().Id
|
||||||
deps = defaultObjectTreeDeps(nil, nil, aclList)
|
|
||||||
aclHeadId = aclList.Head().Id
|
|
||||||
)
|
|
||||||
aclList.RUnlock()
|
aclList.RUnlock()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -73,11 +71,10 @@ func createObjectTree(
|
|||||||
Seed: seed,
|
Seed: seed,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, raw, err := deps.changeBuilder.BuildInitialContent(cnt)
|
_, raw, err := newChangeBuilder(common.NewKeychain(), nil).BuildInitialContent(cnt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deps.changeBuilder.SetRootRawChange(raw)
|
|
||||||
|
|
||||||
// create storage
|
// create storage
|
||||||
st, err := createStorage(storage2.TreeStorageCreatePayload{
|
st, err := createStorage(storage2.TreeStorageCreatePayload{
|
||||||
@ -90,8 +87,7 @@ func createObjectTree(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
deps.treeStorage = st
|
return BuildObjectTree(st, aclList)
|
||||||
return buildObjectTree(deps)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
||||||
|
|||||||
@ -73,7 +73,9 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*treech
|
|||||||
// now starting from breakpoints
|
// now starting from breakpoints
|
||||||
stack = stack[:0]
|
stack = stack[:0]
|
||||||
for _, h := range breakpoints {
|
for _, h := range breakpoints {
|
||||||
stack = append(stack, t.attached[h])
|
if c, exists := t.attached[h]; exists {
|
||||||
|
stack = append(stack, c)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// doing another dfs to get all changes before breakpoints, we need to exclude them from results
|
// doing another dfs to get all changes before breakpoints, we need to exclude them from results
|
||||||
|
|||||||
@ -53,3 +53,44 @@ message RawTreeChangeWithId {
|
|||||||
// Id is a cid made from rawChange payload
|
// Id is a cid made from rawChange payload
|
||||||
string id = 2;
|
string id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message TreeSyncMessage {
|
||||||
|
TreeSyncContentValue content = 1;
|
||||||
|
RawTreeChangeWithId rootChange = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeSyncContentValue provides different types for tree sync
|
||||||
|
message TreeSyncContentValue {
|
||||||
|
oneof value {
|
||||||
|
TreeHeadUpdate headUpdate = 1;
|
||||||
|
TreeFullSyncRequest fullSyncRequest = 2;
|
||||||
|
TreeFullSyncResponse fullSyncResponse = 3;
|
||||||
|
TreeErrorResponse errorResponse = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeHeadUpdate is a message sent on document head update
|
||||||
|
message TreeHeadUpdate {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeHeadUpdate is a message sent when document needs full sync
|
||||||
|
message TreeFullSyncRequest {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeFullSyncResponse is a message sent as a response for a specific full sync
|
||||||
|
message TreeFullSyncResponse {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeErrorResponse is an error sent as a response for a full sync request
|
||||||
|
message TreeErrorResponse {
|
||||||
|
string error = 1;
|
||||||
|
}
|
||||||
|
|||||||
37
common/pkg/acl/treechangeproto/treechange.go
Normal file
37
common/pkg/acl/treechangeproto/treechange.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package treechangeproto
|
||||||
|
|
||||||
|
func WrapHeadUpdate(update *TreeHeadUpdate, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_HeadUpdate{HeadUpdate: update},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WrapFullRequest(request *TreeFullSyncRequest, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_FullSyncRequest{FullSyncRequest: request},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WrapFullResponse(response *TreeFullSyncResponse, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_FullSyncResponse{FullSyncResponse: response},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WrapError(err error, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_ErrorResponse{ErrorResponse: &TreeErrorResponse{Error: err.Error()}},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
//go:generate mockgen -destination mock_ldiff/mock_ldiff.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff Diff,Remote
|
|
||||||
// Package ldiff provides a container of elements with fixed id and changeable content.
|
// Package ldiff provides a container of elements with fixed id and changeable content.
|
||||||
// Diff can calculate the difference with another diff container (you can make it remote) with minimum hops and traffic.
|
// Diff can calculate the difference with another diff container (you can make it remote) with minimum hops and traffic.
|
||||||
|
//
|
||||||
|
//go:generate mockgen -destination mock_ldiff/mock_ldiff.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff Diff,Remote
|
||||||
package ldiff
|
package ldiff
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -84,6 +85,10 @@ type Diff interface {
|
|||||||
RemoveId(id string) error
|
RemoveId(id string) error
|
||||||
// Diff makes diff with remote container
|
// Diff makes diff with remote container
|
||||||
Diff(ctx context.Context, dl Remote) (newIds, changedIds, removedIds []string, err error)
|
Diff(ctx context.Context, dl Remote) (newIds, changedIds, removedIds []string, err error)
|
||||||
|
// Elements retrieves all elements in the Diff
|
||||||
|
Elements() []Element
|
||||||
|
// Ids retrieves ids of all elements in the Diff
|
||||||
|
Ids() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remote interface for using in the Diff
|
// Remote interface for using in the Diff
|
||||||
@ -134,6 +139,36 @@ func (d *diff) Set(elements ...Element) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *diff) Ids() (ids []string) {
|
||||||
|
d.mu.RLock()
|
||||||
|
defer d.mu.RUnlock()
|
||||||
|
|
||||||
|
ids = make([]string, 0, d.sl.Len())
|
||||||
|
|
||||||
|
cur := d.sl.Front()
|
||||||
|
for cur != nil {
|
||||||
|
el := cur.Key().(*element).Element
|
||||||
|
ids = append(ids, el.Id)
|
||||||
|
cur = cur.Next()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diff) Elements() (elements []Element) {
|
||||||
|
d.mu.RLock()
|
||||||
|
defer d.mu.RUnlock()
|
||||||
|
|
||||||
|
elements = make([]Element, 0, d.sl.Len())
|
||||||
|
|
||||||
|
cur := d.sl.Front()
|
||||||
|
for cur != nil {
|
||||||
|
el := cur.Key().(*element).Element
|
||||||
|
elements = append(elements, el)
|
||||||
|
cur = cur.Next()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveId removes element by id
|
// RemoveId removes element by id
|
||||||
func (d *diff) RemoveId(id string) error {
|
func (d *diff) RemoveId(id string) error {
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
@ -182,6 +217,7 @@ func (d *diff) getRange(r Range) (rr RangeResult) {
|
|||||||
func (d *diff) Ranges(ctx context.Context, ranges []Range, resBuf []RangeResult) (results []RangeResult, err error) {
|
func (d *diff) Ranges(ctx context.Context, ranges []Range, resBuf []RangeResult) (results []RangeResult, err error) {
|
||||||
d.mu.RLock()
|
d.mu.RLock()
|
||||||
defer d.mu.RUnlock()
|
defer d.mu.RUnlock()
|
||||||
|
|
||||||
results = resBuf[:0]
|
results = resBuf[:0]
|
||||||
for _, r := range ranges {
|
for _, r := range ranges {
|
||||||
results = append(results, d.getRange(r))
|
results = append(results, d.getRange(r))
|
||||||
@ -200,9 +236,6 @@ var errMismatched = errors.New("query and results mismatched")
|
|||||||
|
|
||||||
// Diff makes diff with remote container
|
// Diff makes diff with remote container
|
||||||
func (d *diff) Diff(ctx context.Context, dl Remote) (newIds, changedIds, removedIds []string, err error) {
|
func (d *diff) Diff(ctx context.Context, dl Remote) (newIds, changedIds, removedIds []string, err error) {
|
||||||
d.mu.RLock()
|
|
||||||
defer d.mu.RUnlock()
|
|
||||||
|
|
||||||
dctx := &diffCtx{}
|
dctx := &diffCtx{}
|
||||||
dctx.toSend = append(dctx.toSend, Range{
|
dctx.toSend = append(dctx.toSend, Range{
|
||||||
From: 0,
|
From: 0,
|
||||||
@ -216,10 +249,10 @@ func (d *diff) Diff(ctx context.Context, dl Remote) (newIds, changedIds, removed
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if dctx.myRes, err = d.Ranges(ctx, dctx.toSend, dctx.myRes); err != nil {
|
if dctx.otherRes, err = dl.Ranges(ctx, dctx.toSend, dctx.otherRes); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dctx.otherRes, err = dl.Ranges(ctx, dctx.toSend, dctx.otherRes); err != nil {
|
if dctx.myRes, err = d.Ranges(ctx, dctx.toSend, dctx.myRes); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(dctx.otherRes) != len(dctx.toSend) || len(dctx.myRes) != len(dctx.toSend) {
|
if len(dctx.otherRes) != len(dctx.toSend) || len(dctx.myRes) != len(dctx.toSend) {
|
||||||
|
|||||||
@ -6,9 +6,9 @@ package mock_ldiff
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
ldiff "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +52,34 @@ func (mr *MockDiffMockRecorder) Diff(arg0, arg1 interface{}) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Diff", reflect.TypeOf((*MockDiff)(nil).Diff), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Diff", reflect.TypeOf((*MockDiff)(nil).Diff), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Elements mocks base method.
|
||||||
|
func (m *MockDiff) Elements() []ldiff.Element {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Elements")
|
||||||
|
ret0, _ := ret[0].([]ldiff.Element)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elements indicates an expected call of Elements.
|
||||||
|
func (mr *MockDiffMockRecorder) Elements() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Elements", reflect.TypeOf((*MockDiff)(nil).Elements))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ids mocks base method.
|
||||||
|
func (m *MockDiff) Ids() []string {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Ids")
|
||||||
|
ret0, _ := ret[0].([]string)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ids indicates an expected call of Ids.
|
||||||
|
func (mr *MockDiffMockRecorder) Ids() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ids", reflect.TypeOf((*MockDiff)(nil).Ids))
|
||||||
|
}
|
||||||
|
|
||||||
// Ranges mocks base method.
|
// Ranges mocks base method.
|
||||||
func (m *MockDiff) Ranges(arg0 context.Context, arg1 []ldiff.Range, arg2 []ldiff.RangeResult) ([]ldiff.RangeResult, error) {
|
func (m *MockDiff) Ranges(arg0 context.Context, arg1 []ldiff.Range, arg2 []ldiff.RangeResult) ([]ldiff.RangeResult, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@ -46,7 +46,7 @@ var WithGCPeriod = func(gcPeriod time.Duration) Option {
|
|||||||
|
|
||||||
var WithRefCounter = func(enable bool) Option {
|
var WithRefCounter = func(enable bool) Option {
|
||||||
return func(cache *oCache) {
|
return func(cache *oCache) {
|
||||||
cache.noRefCounter = !enable
|
cache.refCounter = enable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,17 +131,17 @@ type OCache interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type oCache struct {
|
type oCache struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
data map[string]*entry
|
data map[string]*entry
|
||||||
loadFunc LoadFunc
|
loadFunc LoadFunc
|
||||||
timeNow func() time.Time
|
timeNow func() time.Time
|
||||||
ttl time.Duration
|
ttl time.Duration
|
||||||
gc time.Duration
|
gc time.Duration
|
||||||
closed bool
|
closed bool
|
||||||
closeCh chan struct{}
|
closeCh chan struct{}
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
metrics *metrics
|
metrics *metrics
|
||||||
noRefCounter bool
|
refCounter bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) {
|
func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) {
|
||||||
@ -167,7 +167,7 @@ Load:
|
|||||||
closing := e.isClosing
|
closing := e.isClosing
|
||||||
if !e.isClosing {
|
if !e.isClosing {
|
||||||
e.lastUsage = c.timeNow()
|
e.lastUsage = c.timeNow()
|
||||||
if !c.noRefCounter {
|
if c.refCounter {
|
||||||
e.refCount++
|
e.refCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ func (c *oCache) Release(id string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if e, ok := c.data[id]; ok {
|
if e, ok := c.data[id]; ok {
|
||||||
if !c.noRefCounter && e.refCount > 0 {
|
if c.refCounter && e.refCount > 0 {
|
||||||
e.refCount--
|
e.refCount--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,7 +119,7 @@ func TestOCache_GC(t *testing.T) {
|
|||||||
t.Run("test without close wait", func(t *testing.T) {
|
t.Run("test without close wait", func(t *testing.T) {
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
return &testObject{name: id}, nil
|
return &testObject{name: id}, nil
|
||||||
}, WithTTL(time.Millisecond*10))
|
}, WithTTL(time.Millisecond*10), WithRefCounter(true))
|
||||||
val, err := c.Get(context.TODO(), "id")
|
val, err := c.Get(context.TODO(), "id")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, val)
|
require.NotNil(t, val)
|
||||||
@ -140,7 +140,7 @@ func TestOCache_GC(t *testing.T) {
|
|||||||
|
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
return NewTestObject(id, closeCh), nil
|
return NewTestObject(id, closeCh), nil
|
||||||
}, WithTTL(time.Millisecond*10))
|
}, WithTTL(time.Millisecond*10), WithRefCounter(true))
|
||||||
val, err := c.Get(context.TODO(), "id")
|
val, err := c.Get(context.TODO(), "id")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, val)
|
require.NotNil(t, val)
|
||||||
|
|||||||
@ -48,10 +48,8 @@ type service struct {
|
|||||||
|
|
||||||
func (s *service) Init(a *app.App) (err error) {
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
s.db = a.MustComponent(db.CName).(db.Service)
|
s.db = a.MustComponent(db.CName).(db.Service)
|
||||||
|
|
||||||
cacheOpts := []ocache.Option{
|
cacheOpts := []ocache.Option{
|
||||||
ocache.WithTTL(cacheTTL),
|
ocache.WithTTL(cacheTTL),
|
||||||
ocache.WithRefCounter(false),
|
|
||||||
ocache.WithLogger(log.Named("cache").Sugar()),
|
ocache.WithLogger(log.Named("cache").Sugar()),
|
||||||
}
|
}
|
||||||
if ms := a.Component(metric.CName); ms != nil {
|
if ms := a.Component(metric.CName); ms != nil {
|
||||||
|
|||||||
36
etc/client.yml
Normal file
36
etc/client.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
anytype:
|
||||||
|
swarmKey: /key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec
|
||||||
|
grpcServer:
|
||||||
|
listenAddrs:
|
||||||
|
- 127.0.0.1:4630
|
||||||
|
tls: false
|
||||||
|
account:
|
||||||
|
peerId: 12D3KooWC2SctmKSLWqmzsKCpQBo4iqNzbZhWivM3jbhovB4JFug
|
||||||
|
signingKey: Maen+w6qwWuS79RZyMbuW7wnWAox0+rMinAb/gsOSl8gz2BLCfMlwXjlo8NLKfFFZFNUzl0ANTxbrK45Be7CPw==
|
||||||
|
encryptionKey: MIIEowIBAAKCAQEAonOsG0DzAzGlR7cd0u31DS0xoHihxdfJwut5JMtLKqGwkUC5RM+/eTa96hKYp8ED6B8Q4ZBhmt2gQnOUQJpoAnJ6uU/HgQVVhsJD7uMQcyVWr2KZbRK2GAohxOiW8JaB8pLiIRJbOxaeIu8dGRTrTTxYnh4IbIUgMu5x3iPW1/6YT/LCN1r/CBgHnPLtxMjAdUYzz9+LC13sZJsanUot83MTgl+5unEPh+ogbrSJ6P8FAAWW8HHD5lUSSb2l8NFRafYWP4o3vF9fqtmpt5I2nK6PaNh+4YXB7CX8Nak3AYuSO/aLGUtZMGYv9Qqwewjk/ewEGNWz33D/Hve8+hctXQIDAQABAoIBAQCNY7/XuJ/Jl9wSnv4GJ7Ww0jTvRg8G8tlYHTpDG+1AHZpf0cVubqJoDY0dvTHAT+3miaNXryJEd8CUFaRi1gDQoHLP9u/dC5d0wn/92wLmNQlNfLOsiyyRn7/kccttepF/XvgRcLiWpQjdvt/EhMCHaI54kAsk6Hkt2vqgLPFA66MH/5AMyf+8RmouYvc1m8jPUVmkIZVkoO4/6kh0tZS+rGdjxB65zDaoBx6CcXAMkTWe27Ce87vfGwCRySGVGRg7RuTJQR8VO3oSmsPVIZ8A48fKPQvryrl/5ztvE35lL4i3pdIbd/CJ9zTKIEM4nyPWSmxsaxs1yIllsj3BFpDBAoGBAMzWUEBYm5FH6wG2GXigkou4VSUBAoKCi5XmA2bwCUZx6CaG4uk43cbYpkbLpIRchfLHAeVCiaOYe5VFvYMth6o+OICEKfXWEwGqjtWeHkyIQIZ1Yo+BKk1rbzkYa/n3a7Mw+C6HsweFq1v01eTChmMr/PF6trFQiJJhTGkGKS2/AoGBAMsHKMEmgw1/hRqiEai73AVLSzXGoHSUWsM1vV05EzDyoxkk8Q/+sJR/BOp4HvJidXiM9B0hSOBhkPZjP3TZSQTKXwMGY+Hcs0XhwGxV5Eb9XdbD5rhCT6eVUeQeP9W9J34RdobJauG1Ld9E1U0nKEI+ls6VZf6/k+ixDOa3TaPjAoGADI+7/iYw7Bjf9YvoRfh65CyatBk6wSwmSTwAy2g++V304Z/1/F1rZE1W7RKB9UgDQt8nY5rP/ANW2NGdDJVXM357Uo5IUHYfVkPSXJFExGa6pkQ+lhRStsq22GaCAKNGrId9QMU7mmN9HbeHAm9XdG93JIvk9jy9E1T6LZqeHdsCgYAXsvQ856PwlWwSGcz550PdklZrJo5gTVjy5HkAQsNMuWX0b218MnymONV4ESF7paaUtc9g/xukpX7oY9lqaFqvpnfEwKA0IzEB/UIa40PMTZMAmMl7xLHLnBB9ElLdPkE35A3z2dsSEbYTE9PaN7HpWaj84E+RlwdK6C/bVpZHhQKBgBv8Up6nOfQyW4jiRo5CPOzXPYu+tXfsV0lKbYAjlp3rcczsi/BPXF6tLZ74/f5Cp2NJxx1GIitjqGzZ1mhkB8Eimuw1o+uNRBRh5BcmQTXPTxrrbOsYzjBJNb7n9HcHlGivcmDooxP7TgRJydEiFdpoBhjU+7yGJTJk7YdDLI3I
|
||||||
|
apiServer:
|
||||||
|
port: "8090"
|
||||||
|
nodes:
|
||||||
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
|
address: 127.0.0.1:4430
|
||||||
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
|
address: 127.0.0.1:4431
|
||||||
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
|
address: 127.0.0.1:4432
|
||||||
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
|
space:
|
||||||
|
gcTTL: 60
|
||||||
|
syncPeriod: 10
|
||||||
|
storage:
|
||||||
|
path: db
|
||||||
|
metric:
|
||||||
|
addr: ""
|
||||||
|
log:
|
||||||
|
production: false
|
||||||
|
defaultLevel: ""
|
||||||
|
namedLevels: {}
|
||||||
@ -5,41 +5,32 @@ grpcServer:
|
|||||||
- 127.0.0.1:4430
|
- 127.0.0.1:4430
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWNGRznbh4RCYY1hDnG1RLCtWviWwVnZGjKHtsXVgPckNk
|
peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
signingKey: buHKTg4VF6lskoFWDdjtjWNj2c/fz0zAxKrOW05pRRu4+aw/tClrubW5wpeCOJxPSMHJBTj/8bJ8icwKfe7yMQ==
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEAtoc/5YBUSzPUISHv/COa2wTeWpsuxuLGOd+IYLXe8xXIry0GHCqCN7orZq5iz7BFs2i6o0ttK2PpRa5xz/GnKtTkQowmfDNwh/f+jIlMo+CcL54Qq4sURexChBCg6z3XbSQK1C9yGA4QaNFRDgSzAs1IC8BCRFf7XDbK06zxWw/As7D3Bo1V3TO0LWi/URkV1PBZdQxX6unt5VplhTQ92o22xczb15zfBQW59qEZYyPa2apwUfmhZgjoAbSOIQm96U7P+HrLa8va1h9q9o+eYefco2N7wv40MYsDXll09Tfc/VhDEfmuKfwmSe5AEnpsg1gD94fX/4KVt7Usb7u6gwIDAQABAoIBAC7POqS5p2Rt0z33/RqVavY2JmvoFjPtHlbjK49ZtOZ0NLYv/rwkbqap+M1pdW+7zfQ3rH2KL2IMSluTZB6m428Jj8w9MvVxH6/O+pnB8ESqqoNPrwi/LyDLeTdzKEGL535W2uwVitX+bVjkLTxCGkJisNJKqPPr+EtqxdNJK9BlJ9VdOLFLi67mOsu3F6AtDtBC3VFXZJa8Wbocu0A7hm8QWa23AL7+EZdV9kJ8Dw2qEYXyYRwmhExuZWNsPsnMvNhlCj8By9IPuICDzW87SfcsIQd7vjSg3y60mmGvl9WGxJbpEkSa+MxCA175k3E30KP1tYMOBQyhlCr7qRYWpdkCgYEA4a7CJGqtdMB8KByzrfGazm8koI0Y+qcriYaOWeoZayoxshwmemqJQTEP29D5SumxOcobKnKRHhKBhhlJenc5xNwppgMIgexZtLLAB2pZzLZ/bIy39T+lAEVOQWIEWDUQ0MwqaGNvaZ2bXyM1Xq6Bovurs8gSwmRIQspskeD/fy8CgYEAzwxpLa/W+BcRPH7VpLSkwSPgsAXW+TCoxWuCMj/W7MmCplyohW8a8wc42RFwKCH4ULpyNbv0VWdCM910/U1sf+0s7B3+IeW/0oMlLIPOd/Z39Legm+h0o1l3rD7deWdL7AMnaJIJsMBOUp0DRBSE5Bj6iUr1MnIEMX/3zFqdxO0CgYEAo4FSZMHpA3JFQWZyAy7M4o0Bc1RmaYrd7xhOX/RMECkUsh7U/dHbuSCLhc1kH5Mp9F1pyxoP60KrFnWRl6lzcB22CvGdo0uSPmlW2MiDYN5DeWiGCqfeqlCL/rC9xw5DLZMNkm2gFVu7anT+wKcbgvJlFq54cN/ovoMbn6DsWr8CgYEAgUVIbgP5fdA5LMIr9bfrncMeyAf9XnwpA4nKMkF1mUV/UwtLFHR4KQB7V9vxYL1E4nJmWHJPbPsZdHRyVKyAb6bPg2R+hP+DMpY7IX3x7ShvYNU9a9pI6Kw1cc+WS/RYjLSzaDC16CtJO39YyKrfBeMqmYm5aZOSVq2FM4voMUkCgYBudtWqqwKvA/Ig32hPBa/pqh+R11LeN8F/NsjrCA3geo8MlDqD0To+r9FTv14AksR7BsAfhoGglbvpddTL+CqHgtA4igNWp2/UCaomfnCgnFl/rvo+OGiVR5DgaC4ALw9onsdfeNgrQ5PkqCCi2crb3txdRWGA2QyGvsBmb1u8+A==
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
apiServer:
|
apiServer:
|
||||||
port: "8080"
|
port: "8080"
|
||||||
nodes:
|
nodes:
|
||||||
- peerId: 12D3KooWNGRznbh4RCYY1hDnG1RLCtWviWwVnZGjKHtsXVgPckNk
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
address: 127.0.0.1:4430
|
address: 127.0.0.1:4430
|
||||||
signingKey: buHKTg4VF6lskoFWDdjtjWNj2c/fz0zAxKrOW05pRRu4+aw/tClrubW5wpeCOJxPSMHJBTj/8bJ8icwKfe7yMQ==
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEAtoc/5YBUSzPUISHv/COa2wTeWpsuxuLGOd+IYLXe8xXIry0GHCqCN7orZq5iz7BFs2i6o0ttK2PpRa5xz/GnKtTkQowmfDNwh/f+jIlMo+CcL54Qq4sURexChBCg6z3XbSQK1C9yGA4QaNFRDgSzAs1IC8BCRFf7XDbK06zxWw/As7D3Bo1V3TO0LWi/URkV1PBZdQxX6unt5VplhTQ92o22xczb15zfBQW59qEZYyPa2apwUfmhZgjoAbSOIQm96U7P+HrLa8va1h9q9o+eYefco2N7wv40MYsDXll09Tfc/VhDEfmuKfwmSe5AEnpsg1gD94fX/4KVt7Usb7u6gwIDAQABAoIBAC7POqS5p2Rt0z33/RqVavY2JmvoFjPtHlbjK49ZtOZ0NLYv/rwkbqap+M1pdW+7zfQ3rH2KL2IMSluTZB6m428Jj8w9MvVxH6/O+pnB8ESqqoNPrwi/LyDLeTdzKEGL535W2uwVitX+bVjkLTxCGkJisNJKqPPr+EtqxdNJK9BlJ9VdOLFLi67mOsu3F6AtDtBC3VFXZJa8Wbocu0A7hm8QWa23AL7+EZdV9kJ8Dw2qEYXyYRwmhExuZWNsPsnMvNhlCj8By9IPuICDzW87SfcsIQd7vjSg3y60mmGvl9WGxJbpEkSa+MxCA175k3E30KP1tYMOBQyhlCr7qRYWpdkCgYEA4a7CJGqtdMB8KByzrfGazm8koI0Y+qcriYaOWeoZayoxshwmemqJQTEP29D5SumxOcobKnKRHhKBhhlJenc5xNwppgMIgexZtLLAB2pZzLZ/bIy39T+lAEVOQWIEWDUQ0MwqaGNvaZ2bXyM1Xq6Bovurs8gSwmRIQspskeD/fy8CgYEAzwxpLa/W+BcRPH7VpLSkwSPgsAXW+TCoxWuCMj/W7MmCplyohW8a8wc42RFwKCH4ULpyNbv0VWdCM910/U1sf+0s7B3+IeW/0oMlLIPOd/Z39Legm+h0o1l3rD7deWdL7AMnaJIJsMBOUp0DRBSE5Bj6iUr1MnIEMX/3zFqdxO0CgYEAo4FSZMHpA3JFQWZyAy7M4o0Bc1RmaYrd7xhOX/RMECkUsh7U/dHbuSCLhc1kH5Mp9F1pyxoP60KrFnWRl6lzcB22CvGdo0uSPmlW2MiDYN5DeWiGCqfeqlCL/rC9xw5DLZMNkm2gFVu7anT+wKcbgvJlFq54cN/ovoMbn6DsWr8CgYEAgUVIbgP5fdA5LMIr9bfrncMeyAf9XnwpA4nKMkF1mUV/UwtLFHR4KQB7V9vxYL1E4nJmWHJPbPsZdHRyVKyAb6bPg2R+hP+DMpY7IX3x7ShvYNU9a9pI6Kw1cc+WS/RYjLSzaDC16CtJO39YyKrfBeMqmYm5aZOSVq2FM4voMUkCgYBudtWqqwKvA/Ig32hPBa/pqh+R11LeN8F/NsjrCA3geo8MlDqD0To+r9FTv14AksR7BsAfhoGglbvpddTL+CqHgtA4igNWp2/UCaomfnCgnFl/rvo+OGiVR5DgaC4ALw9onsdfeNgrQ5PkqCCi2crb3txdRWGA2QyGvsBmb1u8+A==
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
- peerId: 12D3KooWKtsepiMYrDtok7AU4itPcmHQaLuwzzfYYyjEW1KoLeXp
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
address: 127.0.0.1:4431
|
address: 127.0.0.1:4431
|
||||||
signingKey: bqnCY+BB93A2nTM59zyP1CGZg5seSIeoGM/ATCOMy4+VvIfB1kwEK2VM5QVx3ub8zV/kqND8xuuQCC2NIrAFxw==
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
encryptionKey: MIIEowIBAAKCAQEAxaNDIGlEwkYRtcw6eoM1wRReJJUgHbEPTGSazEHTIp9Vza0Ob5GqT0yTFbWQWec1+vfCCVj49Z0usKiIa78iViiZxN/EZtdbimM2b2LTOPPkHTBNM3KawuBtVd34CYOLyFFhc+m4dtquGTsOGC0q2YQlS/XF+vGNWO/j8LnriF47Vv3Vr2YDfYeLo3aMexjzLKDiL1TC8fxtcSHqwrJnhgkFEHV/BIadPBlCpVukTPPMusEaoMshHVViS2emStf7j7Iq6KDdbIMGRCTAKhLNMOnHDwmDlBo/RSS/iYtEXFEADDfiYPOeIKIExPnAfdbku5I1y3/IaxeSpk+jQDFfMQIDAQABAoIBACLEgsWL3z2x5+GsaMkuleE+fQVAeqLeiAtvU1AFcGgR0Z1aCUUVQfmrReC2zQsTwopA1ZChZ0KGATWwoDccK6UuhUZ9+uYAkqj4pRXZM8E8HnAIFDytt436vyEw6DZ8PrXhoxwqDHpUI/ZqTiNwpq4XMhx3wvlPTwdLRDUP7+BQK7EmmZLZPiU+oq7f8Fo3ag2gkRKakatPIjwKRDSXcLNW+Rz2YrxUOAdEir2KiK0CKYAkqmcZy/O1xBjQ0YgQpYgxgBXRHTgd5iIFjGG/bCIHsLyV+FkpMpgO7oFw0aJa6zISFeoZ3Zekpf0qqSQNrI+Tpc3uStSE8/95nIo+fxUCgYEAxuvt8VRl1W16ddYpGAFO7ytTdzFSg4e07rKPLvZbvQ4M21CASluNPPKn/S9KFaLZDagBM2jl2cjGYdHVfVlVu/fmM8nlTCIhxkjU9iHkyspJWXNxzUcnh12GEjcNb1i7Oc1QTof7HFjEG4TrsRmGdAee4ZjXYyIEPAHCgxAdc7sCgYEA/lkGdggdLfw6HkXceLaiuq8FA7asJ0JK7L5XCptAXZ9ci10oQuwC+58S8eFVkOUmnVwFovc7CF5EtWjUkSdI+AIL3WCnj2Xjm/S/ASNL1Urw7Q7A7QKu0kGawadUQ00/oSRApEC3f3XK0rdkRlryp8mj2WRfUyBEjh+NgLzgzAMCgYBHQK1Le3K6n2t1GBBCM/3FN9y+3iDzUkHiGn2lUcOMlaLPUCeT+vU9dqHr0+uSknFzLdG4S4PBneRJl7MEImLOYL7JoDENM1CryNzXiU59wTXC39JMuIcVOs/SaHvcfYka7EsuxhCRl84vGU6fckgx+aTUpD3KmZ2wrOSys6wJDwKBgC+VrjzE1di1mJXzUgUPfjBY8CI6uch6gZP7JEOqugcJ+oFkQ1UJ3KEAqMWx95UtGeVUwwUzJcsx/77ExwgFBoTHtTqMi6yrTkLuLhHjbZuQ8rQXD4cH+ncBqRdT29Lfj+jw5FsWdH4XJoP3pX34I++6LLpOKfteTRUd2BZev9vLAoGBAL24XaIkqAECCqdGLiID3PEIRLGacnjEoAqS7fT5A8CV0Cle1KKZzkJlJvxU/pzSgp5AjI1TwIiH4jYE/Xtc2+61Kx1C7jqK5tNK4lJ3BkHUY9d1Etr+HdnDZYKZ32XdGfh4nUU7dx+OI965oQJISsLVVmu2GBllsbg6sA+w3LnK
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
- peerId: 12D3KooWJ2259GQZxf1PBkLBR8J37QN4PMiLedBU9h5PNbUwfaXE
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
address: 127.0.0.1:4432
|
address: 127.0.0.1:4432
|
||||||
signingKey: RHl/cHYoPtAGXgJl7F3upI2OAnD4hd9aJztiqo08w/V52b3qKvFr2TWnpbNvBlXSxeyXpo4WB1jH+pMslW0irQ==
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA2vHQaQ5U/PzvNFTk3G9t/IMELaxM5OBFV0/HcjDnF3jtc/ADtqG4zsr/VCs7/tiXiEIxn5aMFrvS7APh2/EHLlAnyrjYLyyxvgwqUtV06Gf5K2V7HmFTLch7VFc5HckU4Zg1B61EYAtnWu5JTmsZAmP1v3afsnfpdwTA3LEH65oOyEAXqCeNUtrrwZXYnt77gk1zC0NSdtE4Hf25OJ5to0kckmQf+TMxj5seA5+u55Bg/Hd9sorFl0X0JrAkIxnVcWYt9lCNZk4frPHl1deX9BwOJ5KKrz1Af/617rl8b8H5F+KzkHXpgpJfxtMLWUnUuaX7qm+R3qe1HeMCIAmOLQIDAQABAoIBAGPVHT25/kC5KG1JRG3LFXCtYOtehFVceeG9C+liqQzH5CYYS+krxrPsVg5QBHRI2JeV70CgidIX5K4few4p0ido/yvtqw2fqJBKxcWtdTg/qJsEE+afZCkdIDct6mpNdQsEtzF/7QyKRp9sxdpO9UFkyPp7oYfkK31MmpBG3KCtb57dyIKqfBoIrp9E54X+MtHHQsqpVo7wgdSufUAWA5OtrebqrUGhWrZCRVT5l+BbPp5WliTN12jVU3jdA6rkUzrdyt5jyZQZ1eIm89mBi3wQod3arUx+DnXeICroyWW7eumXqvPdYO9Y2eaGpXY9sjXioGARi97vD/qCB9qB/sECgYEA8L169WaUBfPU6qlD+qZN1Be6PprjBqoTYu3clQikYhF1HGcXT4ri1/8CT8gf9QsUt2NHzNf0vkhyqJ3bD+mxG/c62C7ff4mhLRR2MRiDnqFaYKJL4snFG6eachD7IqgXEJ8Uw8s+LUqljhMa3NlXgDyCdrazVto/J3iDx6/B2/ECgYEA6NKniFEFrJBEVr7neEsMzKSuu8S7VT8bZGNY5yLIHM7+E1YeyJko1BtaQ2f+x9nnRzRPpjO5H+oVLeRWj496retGmvQ24K6VPCq8b7I9QUdYOvhzgo+go6sCM4dzfespIi932EAHGFA0frZ29o9W9a8rgFZUoigde9KAYxVLQf0CgYEAlfUBfZFLDTYoX4/WV3B2NHIfQlYKqqEQeGRALdl3Q9sp/uo8fADActlXIElBlsszOVSvaervegP44A2MYiood4oV7omsEG6zpjgDs2tYuVw6xszxxi/3BtXs/7aSKLFZxLHDJn8YmO/RlmFSL1V3CtsmTTpbFfPWuQh51c4mTJECgYBQEhqR9CN6bIdEOhWLNmxpeP2rEAbJU5HNHam2nCysU7fn2Idvv9Td1aZeZkamXtd+kowOAd3aDvxHsy7d4p9zbuXyZqj07rXeYmg6FdehOrMqXMYFEfZSM37nT981YAneeurBkYufHf5f0crqEvP6PMs+MPKcbiVtr0B+UxV11QKBgQCmNz/q1pPxEltFBOZmsyfmplKgeDyexB8nb0z1NNc00tpKtWL+hvLqGQwYnECJ7kcJDNetKM1J6rDCoLg6hObf/Ze6/BFXTZF8bM6Xqz1elQPYgHl5P+vlJ7yVI5FClVG8RgI73vxr67CZk+4zsZbvTLscaZ1ZPkPR9m+YMJWUrA==
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
- peerId: 12D3KooWNJdqtKLZAxT3szMrWoSLS1F1JkyKgJ4YQ1rAKfeVPMm6
|
|
||||||
address: 127.0.0.1:4530
|
|
||||||
signingKey: BwEWqy5XqOeEUy4BmMzv1WltI5TvLPfP2l2mtioxb+a5ijq4aSATKZSFfcm2hpbGDObWOzeyi06BarLOfQsTnQ==
|
|
||||||
encryptionKey: MIIEpQIBAAKCAQEA2sTIJSgwRRwPVINYyC5lHtZGsBth87wV+mwMVHkt1/Er8WVstudDFj7dvpO4wHE9vzOQi8+VobNT+xZSB1hlLbOuyBMDzdg+0vs1rMmYruKWb12VZ4+ir1xhnqpm5sKhPuPylZFp+m2GuyEeMHjUNnbQDgPSxkh9jNnTnlwG86h8r5BlhbiISZUs0Jh+IiAbgf55xTdYp0UmVREJYpmk8SBOQS4HfkWM7ih85zMrA0lzi6bfghN7CSABpAMYSgLJc9XeP3le8iMSKQsT+RRvXgUAniPT7ftbWg0tZMNjJ9CXF12Mp0ElC95UIwOnJJydgrLMLvQ0Lggie/WdN0PpCwIDAQABAoIBAQCvg37bqLGJUKjP8gzxlZ9VLS5LLbzZUgYEAlmmEA6CmB/cLLYay9Fb8JXwxw1Lf869Ln6CXMm8kGYJJPAsqnOKRgUsyWyc4igNFrQKazbO4EU3Fcq+6lLoA+Lh6+5gpre9AB5oduCipOqaCUjyNI51H79t7w1UPWZU8ZHBFC4TnpanTYTqyYwUThqDR/PExyV7mhYN5gEi3cg4W0cA7qlDaGgwaKBrMphRt2xwNlAlYAhdkwdgRmbnB/zrWb0FHqJAsz6biqqNh0N0EgIsF0ZMO0ZFGRt+Ou36500Z1cRpGurbO1zrpNV2R2Gg0Ssun2tfjoYJN22HqwwLY71s/xXRAoGBAOx5KeiD07zkRCUzfVa9oHd9CxFSpStz0mCauFDpW0nhzgonjSaOmEotGvVRLDF1eqbtji2QOx3WSPXdnNlncyYAsWFJMyupygqsxBxnVBX3yFFicOE6PCaZocwDVmdKNNfg/52U13qS4pxFFclUPHlVvEcovR1VAPP08MvyV4x5AoGBAOzVW7FmVgzAUc9E8ro6pXD4dFyNkE6Hasq5ApQzFbqcaHSUjbS2lF5dKhvur4OABy6XO/wgD78b/bC+vMryxC+yHm4FP+ANpQ+/DSrn+g2X80J0wqC2tIIVqYMOzn3L+gSfRnhW+28vEx5SSofa7aZl/NOoXtXD47amJELwYzijAoGAVH9vJDCG5oZCe3CMpwQXZNr/q272qjI2yGJA3likUCApuaMsYsytSkQXz/Tzb7Dk5OUZ2tog5aZ+Z6yKsXyvvrKcr4CykjWXhnz5jpS1jSv/HmWopDJk7/4RvI6svzfa7hDuBeb7oEcARorBIDHDci/amSrLeMG5F3M84AN2mTECgYEAvx+PV6JWXwP1AWeK2m7phDl87hPwGO9/ZwnW4vI23tnKEgqwMN4G7gARM2lzipOPODIj3luhWYClQjUq9jzjxfngRLlHyvA3/HUZkz6RtNajIUZIqpnHIhOJMJKKYUpzAbfnjsXjMt6ydw3Bx9ENZ/N2DPkbTzc+VO/O45ZK/DECgYEAvhovek7Jk4ZmC1OsxedqudrgQugNGTMnc6gFZR/CUXrtBs1vq4zKe003Nx5WPGaYooySVraSgBplamtsL+dUsVRqWjCyuUrSkuv7XtP6rdSuRJEHTs7vumnGsF2pp+I08W1Bg0zUFToGy0PqFX9pVeR1f63COI4Ca1Vy6+BIw1Q=
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWP2cwtzkokAGAr8UzdW1pmU4NS2D4dvHJtK2q75TBEeKq
|
|
||||||
address: 127.0.0.1:4531
|
|
||||||
signingKey: RyKkgbAlAmo+suhJf1mYau3uneQD93XO9Dks/a8lpXDES5wfPb3dO/8oefEFllI+c/m3bTVkAYBdTHtCZq7lYA==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEA6Dhjs/8s/uiTFIopCjoYLTq8JGIM3otbUktYXSnqpBVVUU4TwSJonpyeRCgcYy9FlDWrUPfCNEv/kG6ruNUZQs2UuPbaOMZ1Z5TZRokwZF26rlkmaTlwJLKmKy0wwT9koZT/e5G4NkRO4rOLK/O4NyDlZ/HvWaZPxQtcC4en0CDaaIcDSSKaL5OMz0fcXayQlWKiOsuuP7cSUYlBDybbJPLSPMVYUjGjzIBqZkV6nBgjKGIIBGlknqZpRwX1mgq4vG0UYTfGCOFF1iHQ4TiLM2EiiZw203PVA4ifSyvkZOkMngItBfYcnD5MRYtLXlps2LWW6auN6olAkyUwFQeHLwIDAQABAoIBAGq7kEfo3xuCdieYoOhMb1RKjLMERfn7f0vByal4XJpyG7a09itszz0nqy6UaQfFcGuAh289kQtMavhNhav8dhHYP6UMAJzbypaDOaJL5+wZkHYWD6uJdNvJKMrriF8p7ey+ePaosUxv9PoJn8vhxye/fPFbp7FC2aMtZ279OMpVjyhbBekWlHfAnRbmDaFjMH+7wHfaAArpYsmRaOJ+/ckqhHSWSCXHO7dOyTcRNx4J0NoZ+192J6VsD1bbGxfHEgtVac/3+fj0Uia3mjkA+e9+oe7kfiGAheLs7G+kC0rEht1VLkviwjM0oCPd3zcu50HjqSrQ1q+i4vKJLrPWQFECgYEA8Uz+PlwghCWcJ7c+TYL1Y4UpYMXavRYi+XCHyn5x2PtxLDgK9j38CbLtIJFDY739RxEDLsOAkC3ba5p71EAx2ZF8i4ylmw0ekTe8BhEo/PHhCmLL+12zUrDbmUqsb1/NJBRDVZ9975nqWiT1KWqm3XKrwfBRTvgiP3+dC3XrtiMCgYEA9l3KBUK0oc6RWftNQTbehrwMuG0M4wv05peTHHqlMsYV0b5nKCr1FWU+gA4zhEDNPcs7PkZRl+HHMalkKH/aLpxeafN5a4PkMsQD6ZK5Mz88IENzXbFswBjCI8s5NyAAK+aI4JqXiRoia6fRnWVp+VrC4A1o2dvD6GaZAta3bYUCgYALFhF8RflMePnirT2UjBbAGsca5hw1ocW7lhr3B7YtVOgPMwf15kUlIO5aF7Jz66+uSy7NQDgw55p0KCXWS5i+uTtyoeSd6g1keJ4P3Uv3yxkexAlBJD3v56Y/NboUZ99h7/hj/67mijjFKXuGCpteAz227Faf/TB9oFxTwXgx5wKBgEMOeCRCacP445soSXjMpHjrylKQbAeIg5oX+5Su1TQismGqf41xU9AFBKP6OY9vy+1b2b4ziZXbgEpGHtrfIdW5/gC8onnfJkejDqWOqBYIyibF9Sq1VjJbCsyPTf1xGlrYnrzzlvdcQ64luWor5lJWn+A4Bif2JzakZlVdeAO5AoGBAMynKpkB8vqTLU31yt5SzBroQj8TgZKGbzB2apO1a+2XE8WfmtFOxnS1/iQ67sMkv6Rh/N5SUxMnBLXjsYJFpuNkKjvE+RqO9f4PzklTIJuT49pexheAMKBA9zWv5YPEmMV8xGbqXooSuEP0ixlM07DiqaC7aBzSyIfGdTOvI5w/
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWMg5c9wHkuXQ48qyHVa72UKerKWAVZRC2dc1ibSadYxTQ
|
|
||||||
address: 127.0.0.1:4532
|
|
||||||
signingKey: gSyxSnCL8NsewJmdFwgVpjQ2hDwDvrbZrLnA1007ymCwLN67/Xd/42q4vsvZAovsXBrv4PuWuoQUqmXhX7OJrw==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAptyiobOzgLUuVfUQetYQD638+kOUAjf+V7uny+9Qhtt0LZM5v4lsJ8DK+NIbJU6fo9sMNJ8Mc2A7QNEZ6iyppI4zszUIMfF9Ixhew8g5zBlaDzieAf1XSGuEd89vj1ikM3Nhp8AXzxxoFOTsgUCMlnAzsHalcVyqXRzN/glAA1Ob6R0pIEIz4LchvMpnjhSLi5XEmBMy3b3XHu+T5nYyLzLxxMpO2fHH41/GpWmOEVrjoT1qP1JSv+ehuXiuMW0rM1833os6jMHCZijfDGh8blWI2nthjOLbr/KQKQhkIqOXKwdkVLY5x4/c78L8dV3eZ647SqurWC/N8kr5r4LvfwIDAQABAoIBABTPHSUHURJzBeVIW5bGDVi3PP5E4Tdpnjl4uJNRM/ytb46jdqcxTyCiBW4EXchIRtZbYelKEHZvANSzfwTaLwnLhh0KNwxrbkyrJF5MIREX9EhDqkjbPEBW0D1UzDfXORsFf5848H8urrg0WF5CG4ZDVd7i3P0HLmPQTMwqgSYo2pLexcj0LtiZZqJ6ta9kxAiJniZyoNshRJnAZMMnFYRhy/eDF+L6sJPHieYgwiQFU5e0CK9UgsLmmOQWCKWtPgvxOhqlbcTz1pJAqkyzOC0wK/ydJpVAh9RUqf46rEDFzL/l90ZOir3AMlYJIHf4PX0TWchXjFW7bbHn5Zvk1xECgYEAzpuGDfaerUl8QziD6F/OoIz1/EZwSumErCH2NXYMBcCyzKu4fBqVqj5tcLsNx42v6kAGaERAQqaC5ZZ9ZNhXiWasHAermQqv8DtlYVCUih4e87dX1/xTF5TzR8RhLwHPADd1rRafCKJMD9X6Qquer5LmSST8ej3mJ4mrflw837cCgYEAzsCoqFenGlCvAZoQrekxS1VmGJDCKBQ7LlbOwQaUkD4I23rjbAHG8J51jmaQQ4epm6lU0JLSma/LKp8dl9oDEP09vcgKj6xuHMZV+EmsA5c181zMrGoH+tSZiWQZjSmJVhd5T147vnbUunTbGKlOQByD0tWM913Dm2dqB3goXnkCgYBZax4dtPr/7KoHPdJ5I939xoQ/5wx6n454IUq54JlbdAbuZfO2Ypsbz2D2RT61ezEDpSogvklBj2dfjj4/AxL/uJwMlZVC60kyI8LA12syS88Bk/xE0kP0FNcl3GxjN9krMtWPUBcMWZGp2OYzLKvFOULJrWRIU7nkqsS6L5l5CQKBgBa/tg8HzfgkRo1LkWhBT041sE0lqGdWioh3vroYakJQwRK9O8bHj0cseEzZ1ifIBo59HDry3L9SS21+Inhx4YJ+CswV9auHUnpSDGWMXaPrgGEtpcuWwxgDSn2GiRUyK81QOeXUvYggdRmq/+x/vH9rY8nP+3nAVGSGBXGa8/4pAoGBAMB7EOk/RnsgQ+SotHbvgv18S0lbJuWsLYGnNp8EcuPxDIxz29fOFH94qzVOwAkk5cbHvAl3/5sl3SelmKM9LXhcOT+1zxoavyAYyVeAGZsrbBmbzj9yeZON0gHtpF3dMWxiguyWuiiHM/pL92gKzlyIXryC3andL/y8/6VpWbtt
|
|
||||||
isConsensus: true
|
|
||||||
space:
|
space:
|
||||||
gcTTL: 60
|
gcTTL: 60
|
||||||
syncPeriod: 10
|
syncPeriod: 10
|
||||||
storage:
|
storage:
|
||||||
path: db
|
path: db
|
||||||
|
metric:
|
||||||
|
addr: ""
|
||||||
|
log:
|
||||||
|
production: false
|
||||||
|
defaultLevel: ""
|
||||||
|
namedLevels: {}
|
||||||
|
|||||||
36
etc/configs/client1.yml
Executable file
36
etc/configs/client1.yml
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
anytype:
|
||||||
|
swarmKey: /key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec
|
||||||
|
grpcServer:
|
||||||
|
listenAddrs:
|
||||||
|
- 127.0.0.1:4630
|
||||||
|
tls: false
|
||||||
|
account:
|
||||||
|
peerId: 12D3KooWC2SctmKSLWqmzsKCpQBo4iqNzbZhWivM3jbhovB4JFug
|
||||||
|
signingKey: Maen+w6qwWuS79RZyMbuW7wnWAox0+rMinAb/gsOSl8gz2BLCfMlwXjlo8NLKfFFZFNUzl0ANTxbrK45Be7CPw==
|
||||||
|
encryptionKey: MIIEowIBAAKCAQEAonOsG0DzAzGlR7cd0u31DS0xoHihxdfJwut5JMtLKqGwkUC5RM+/eTa96hKYp8ED6B8Q4ZBhmt2gQnOUQJpoAnJ6uU/HgQVVhsJD7uMQcyVWr2KZbRK2GAohxOiW8JaB8pLiIRJbOxaeIu8dGRTrTTxYnh4IbIUgMu5x3iPW1/6YT/LCN1r/CBgHnPLtxMjAdUYzz9+LC13sZJsanUot83MTgl+5unEPh+ogbrSJ6P8FAAWW8HHD5lUSSb2l8NFRafYWP4o3vF9fqtmpt5I2nK6PaNh+4YXB7CX8Nak3AYuSO/aLGUtZMGYv9Qqwewjk/ewEGNWz33D/Hve8+hctXQIDAQABAoIBAQCNY7/XuJ/Jl9wSnv4GJ7Ww0jTvRg8G8tlYHTpDG+1AHZpf0cVubqJoDY0dvTHAT+3miaNXryJEd8CUFaRi1gDQoHLP9u/dC5d0wn/92wLmNQlNfLOsiyyRn7/kccttepF/XvgRcLiWpQjdvt/EhMCHaI54kAsk6Hkt2vqgLPFA66MH/5AMyf+8RmouYvc1m8jPUVmkIZVkoO4/6kh0tZS+rGdjxB65zDaoBx6CcXAMkTWe27Ce87vfGwCRySGVGRg7RuTJQR8VO3oSmsPVIZ8A48fKPQvryrl/5ztvE35lL4i3pdIbd/CJ9zTKIEM4nyPWSmxsaxs1yIllsj3BFpDBAoGBAMzWUEBYm5FH6wG2GXigkou4VSUBAoKCi5XmA2bwCUZx6CaG4uk43cbYpkbLpIRchfLHAeVCiaOYe5VFvYMth6o+OICEKfXWEwGqjtWeHkyIQIZ1Yo+BKk1rbzkYa/n3a7Mw+C6HsweFq1v01eTChmMr/PF6trFQiJJhTGkGKS2/AoGBAMsHKMEmgw1/hRqiEai73AVLSzXGoHSUWsM1vV05EzDyoxkk8Q/+sJR/BOp4HvJidXiM9B0hSOBhkPZjP3TZSQTKXwMGY+Hcs0XhwGxV5Eb9XdbD5rhCT6eVUeQeP9W9J34RdobJauG1Ld9E1U0nKEI+ls6VZf6/k+ixDOa3TaPjAoGADI+7/iYw7Bjf9YvoRfh65CyatBk6wSwmSTwAy2g++V304Z/1/F1rZE1W7RKB9UgDQt8nY5rP/ANW2NGdDJVXM357Uo5IUHYfVkPSXJFExGa6pkQ+lhRStsq22GaCAKNGrId9QMU7mmN9HbeHAm9XdG93JIvk9jy9E1T6LZqeHdsCgYAXsvQ856PwlWwSGcz550PdklZrJo5gTVjy5HkAQsNMuWX0b218MnymONV4ESF7paaUtc9g/xukpX7oY9lqaFqvpnfEwKA0IzEB/UIa40PMTZMAmMl7xLHLnBB9ElLdPkE35A3z2dsSEbYTE9PaN7HpWaj84E+RlwdK6C/bVpZHhQKBgBv8Up6nOfQyW4jiRo5CPOzXPYu+tXfsV0lKbYAjlp3rcczsi/BPXF6tLZ74/f5Cp2NJxx1GIitjqGzZ1mhkB8Eimuw1o+uNRBRh5BcmQTXPTxrrbOsYzjBJNb7n9HcHlGivcmDooxP7TgRJydEiFdpoBhjU+7yGJTJk7YdDLI3I
|
||||||
|
apiServer:
|
||||||
|
port: "8090"
|
||||||
|
nodes:
|
||||||
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
|
address: 127.0.0.1:4430
|
||||||
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
|
address: 127.0.0.1:4431
|
||||||
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
|
address: 127.0.0.1:4432
|
||||||
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
|
space:
|
||||||
|
gcTTL: 60
|
||||||
|
syncPeriod: 10
|
||||||
|
storage:
|
||||||
|
path: db
|
||||||
|
metric:
|
||||||
|
addr: ""
|
||||||
|
log:
|
||||||
|
production: false
|
||||||
|
defaultLevel: ""
|
||||||
|
namedLevels: {}
|
||||||
36
etc/configs/client2.yml
Executable file
36
etc/configs/client2.yml
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
anytype:
|
||||||
|
swarmKey: /key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec
|
||||||
|
grpcServer:
|
||||||
|
listenAddrs:
|
||||||
|
- 127.0.0.1:4631
|
||||||
|
tls: false
|
||||||
|
account:
|
||||||
|
peerId: 12D3KooWEycQPaaTbsZJ2rfZ7cKNFB57o44kKukwKkb7mUCo4Agh
|
||||||
|
signingKey: 2Lxt8Qy52wZHC1T/5zYvT3o4LhZY++4d0Km2gOj5R1hMqMH+Knnt+8cBGONe9r0QdtiXom/AxzWFFf0ol0bBOg==
|
||||||
|
encryptionKey: MIIEpQIBAAKCAQEAwsGthwrb3RDzzmnbgQ4OubKCYEfTWSor0Q3Q9R+atV5llOivw7OGoXZ9c2W51oqlSIfwkWPLb1MPq+sE3pUsLeU09lmpBIBWKVg+MMEMXbBKMV/8qvVjr6HLNCMgKqBf4Nvfpv7Cgy1QoXrE4YjGzRTAlyREJoSQVAGHT9hpy/QDlW0VdwAvHpWrxRcd+Ro8dY87wWFIS2tEhjWMSra9sSFeOOaelSfPwki33beqZog0p22s4pIONrU4EoZvvs/43LrxxaoqWwX15u8+Agh1Z62llDDPke9tul80lW8x+UIiuXjcUkvdaAd0xJ85rrmwCCeLrjQ1yoJmqk5idgysKwIDAQABAoIBAGV+Gxk57nQZBoU2Iz7w/XmGbm0QYTKhSG5Mfe2QB8amp9dfH2GkJ+/y2NOPWrZUUGgo95Q85mJgbdVQx5vbL0fHn78V4H/JBZ3ML7SmlfQpD7EFbZ4F/WokrcnA2F1+cBi1XKshLmq/7boJSZqi9b8gJnFdY+qSwMgWd9aDWDcBTMVmtjpnxdp9AH1vC1pF8IjOM8SG+z3Wln0CX7dKeeB8xMohqNDd5/nWIXgjKyhUNZL7hKz+H27UzGMidF3W5CHi5u6BYqzkAvagQF+1+tVwjgRUp3pZdf/7Nlw9rImACPXi2kA3zpjRxnBNZWnjmPxt+6ISIzi3ZAmmpA5YmbECgYEA0ewToWwF2kHnUFCh/rm1lsH+jKR1McyuNhTM2gx1LO+IJ+GCHd5POMjBzdowbLv0BgTT7ncARwfryznkbJM/SZ+Llf5oDfsuRmf/8AnatLv9Yt/YYg3Uk+s9Wl6FG2I+Hb0WcLLAWBpV0ZhH5JI/dZepsRezoTnWnC4t98g3cpkCgYEA7YFqk4JFiKH7xdZ9UQJS2p2Ho9OWG00Yi9ddwxp+JtuHWRWo2zaRKiHBamXWPFQPmWrNURHB+NtjXMLQahVrxqg88SoKnIiRo7U1m0e6TNBzsSlkmD+2+co0u0ECxe9gxIBJkE56kR6Wl06VKLJ7HwcK6DjeMRN3UrIyBM4qE2MCgYEAhdKctRQ7KudGgfHVQ6C5/XCQSLJyr5uPF5Ts/rhgXpQY1WuyWj4lfMqmmgdVRYwQRWIAhQ3B1IZdMAIo93prJxEZmDZFuVv+JQ4Zn7l4fi01nDmdJO0yLlYRl7GX41wewzCOxKt/aOro+KO+eR0ubVWQ7P9yGP7ZLFlYHpS5nEkCgYEAxWnO9nFP7rQFnHoei9lMmR5bglb67BJ3FrWa3/MDbLUImYmhYyTGIKkSJagkHN0aYkEeDAagnoNs4cukhKjtfqCUlziEvXve4p5awokqV3Lk1xs63DoJkzL6BbOR5IiGfI7Nlr9ErZ8pOPc+kCdao32tGT07ors1cW1gmhHrc1UCgYEAn3pEkmfJL+ufWYZ/t685mrdUqhp/HcwXTByPLSIr+nP6xXod94uusufVTuMXfYzKgnmsIlt8zk1wu2kSJJUcQjL5Q5rK8suYnJB0Z+x5wa2XTwajThPK29DSpjTY4qjOx7ZCgaZuwJNIFzxp0QrV6QA/0y1CmvhpPYiW2wesug0=
|
||||||
|
apiServer:
|
||||||
|
port: "8091"
|
||||||
|
nodes:
|
||||||
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
|
address: 127.0.0.1:4430
|
||||||
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
|
address: 127.0.0.1:4431
|
||||||
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
|
address: 127.0.0.1:4432
|
||||||
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
|
space:
|
||||||
|
gcTTL: 60
|
||||||
|
syncPeriod: 10
|
||||||
|
storage:
|
||||||
|
path: db
|
||||||
|
metric:
|
||||||
|
addr: ""
|
||||||
|
log:
|
||||||
|
production: false
|
||||||
|
defaultLevel: ""
|
||||||
|
namedLevels: {}
|
||||||
@ -3,9 +3,9 @@ grpcServer:
|
|||||||
- 127.0.0.1:4530
|
- 127.0.0.1:4530
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWJpE9AtG4RX4Dwm4vhrCGqiUhKj6Mvbqj2V4rV4diyksT
|
peerId: 12D3KooWAB7hjh7KWdLz1nxkb8VQ4BU9ZfMwjAFNyBB9NnJCw7AP
|
||||||
signingKey: 6tA9VizrAMtsZlzBXXnsg+LzwSwBLU7oiVP1qOHN4PaFsBslV0nt2aKBXfcfxp17V/bvydNfyYbGu50F6spLCg==
|
signingKey: vE+fJjNKXf7y8hW7IXerySK+Fr8b/9WRThM5/tBxww4FUNczjvzd67XXrdvOdZtYQ+QTDfwItNbLwbzLTEMOeA==
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtsYet7J4bNo9zSPFZVFkkInUoAW7os8PtZH6qMUEOKcLAi1PDbkBBCmzHdfuzik8H8DgQl36/0gCqRPM6nhQlbF59mV7brI8/kH3Eiw0rxqWAe0+C6CzDyEqtKC7pJyC3FJe0MZRRtDXiDYlVurHrsW22fA03rJY5++eW6bXiqL7WB44zxMrztkvPljlhDf2XTAcrZWI10oXKjSZMW051Figbhdl06R1ZiW1F1LmUEd3ufiYoevpq8jAHWIToTZrYNX0sfrdNaf/CPCq9ZDSqISf8CZ/bE1VxYRPEnjmX1hZQ132S1KCEQwpBWxpcvePonEMPGp+5F7h4k+46f16vQIDAQABAoIBAEa8np7Rv7HBNTHzqi3wNk+KSHQ2Q8xa/uVyveQbe+rBG42YI4RYGYCW8u+V5qJ7av2PFDwbS00JfZ4aP7BvKCEHMwCdfgv1h42P0iOCYFF0pKHSQ7UUWLh+SZzmqDipKixC5NdAKaySnxfkfMcKzoVhl8b5JD0cITSClHM8Oyc4DR5DeB9MlgrVqV/fcdzR10J6TeEPyJjs7CF+Y4OFUEf8FnNxfx5btWm8dIxRMiFUqdI1SVHmOJo0wO2z36RKZ2f8eHApafpJ/1MWccCCSB34Kry4WjDLn8yfOZ5GavXKDVKnE2won5ZhpZGTaLVHLR8QzvkzuBHDk1j1kSi2RjECgYEAzwjnJc5F8XdOkNNPKpftnUVlijhEx0lSknL/j1wIE7bdqbGvIhW+OlIP3bc6O5h0QGSoB71cAiurzro9rsZnSZ4qqjyeGh55j8I4RoZHGDu8BoUOXzrIL1nw3JWxrsNxu5hV9bcYAOJDG9BOcm7F9g00+f+p2zR7BvZMYm3d0vsCgYEA4gBSbChHTMHs15wppaTqV5iQEbfAU/oweRBnflQTHVdezMDt85BpZv0ik2vTuhMJuiaISMvb5l2fHI+LIKoZgCBfymQ50Yv6dZqOMeY5XwUQiQ8DtVtoetYBwwPIS3hSntTu/a4Q9tZbmmWYG6rZ7X58UrtVHY5DfFMS8MOrO6cCgYEAgDkGV57KKMN4cC+/DyUrL8VEHve8eSSLNFJuvs4D3pnZ7Pgz/Es1Fo+ubeXF9hT0otD0VF7NtjZv4Mft3enZHHoN+IM0c/690PA7xEnzjCmqyOrtPMN+Kf1tNGCtvAwly0aMrnKoNhvr7jTz8OF0T3BciBz0iOOW8nfmVOuwf7MCgYB9va4eDR72XuMWZwVo6uOTTwfBQ9oXHxk/ElhymfZ0mbrd8u2xWQS7z1UgbprDaXo8/tlOn1W+yxIOwvKmft1nQxvosHDW3KnCKva4Xp5G9rtndloa2ju8NDuQtBcJnm1hf5lkvSclHsiik6nYoutTTs9+/El0A0Ya8uGT4Vnw+wKBgDq6yliV5g56J3+gHB4w8yQSoIx4AjHoGkYbaVNiCNLfH02VVIGINnlBk+6xurHUwBg68cAsMSAPWqky3BMvhpAAoyPDBycrWEYKHvKvVsH5R0JRDymVJ3UHJVzCp49+CHIoOElnR+IueVluljtxTrB4JgJj0NOLKOHiTNHW6emJ
|
encryptionKey: MIIEowIBAAKCAQEAtYh4UPVQGLUx9sGYEbItTysmrM/MIpNHnZQaGhEROw6n3Uta5NI6nUCQ7IvqGB9ewNKOsED+7zY2QjZ0RGB/qn7cdRbizxDydx+UxFZy18J2aN4zbK2eoxwn16pGVk6asatzChcfYnI11Is3T9p+5/+gqqfhb2NYA2xU09g4V1nnsyZYWCj4mHcz+AHjhCjFrp53XXp/A8KkBC/gzPH1ic4sRxtjAXG5De/d3YpSD7ejnc/YeifilOJj7wPBo+DkpEZHGu/tRYQgDBWlVIc3oQ+KygXsC/inGODrhg0tLlVSLYFdTsktweKyCA9LKR1y/JNC6F8HbqN9ke/ENsvlSQIDAQABAoIBADmHWyHE7DI4UfIyHeAVyDgbo7EGVVnrtLlicvcpy30cwuPlepOjcAHfsU3VdUVZw6x1zdRbdK8YTg+jtCrrLeo5M+JDc3NNmplXv8yM3O41aVMIf+GEEA7+4D1/b7TwSiPeAqIC++Y17YtC5y9+PdOF9kO+2jlzkTPcg/Fyx0Ae7CIXnfZNZwsZo6fyhstYH6bKe1pJuJeWxQmSMXZO34Nz1qXpTu/E8cevu0iQtAOfyXEzB90i0+JdEe7Ckp3Pv9iCBTMVEZJgNRfXHdyuTr6e0/Tjl5ezUJg3IE7tlP2B251j8cC8nUNuXL34aZ1FPwLKf+OUkTJp+7cGdA8BMwECgYEA1NcKU7/wgT+vfv8i+ENrz75DCRt6MJ1R5agkApjed5T1ExYk7Y/qVBVNOCZeK37z9ehCJ7zft711g4o9XB4FZF8gJFD7TBbK9XzljuIcYartPdRYuugv5T0/xTb3xKQp20xPBmgLO/ZazPrRq83dEISwBXsx3o2t2leQLUm/bmkCgYEA2lg5QTPuZQYplDCeiwmH3C2wo5VMwQQyfT/EfMJ8wkBKoe1ndCLNxPvFramD7gJs6iG4nwynOcdBCpmlxvSm4qQo8AEWNcexRZPVCenw6dgjOvRswfeodZcM++HHByaAy9PtSX6YM70py6GbjV1DKreR9BkFT/C1wyosxKZno+ECgYEAoVr1RVC58AJr9YdO54+VaEUBZSIjnD9oGwdBZYanAVk4AmRDUqZMK7qKdAsCUU9JfB+8J4wUvqMvN63RnshTpihHocCTArg03a72CUB568E9YiZdrjTgOpYYhlaJt9YMtWhAcMbn3WmCpOtxkSHcee1d1In04JfgOSsw7mR+cCECgYBUbu9dDnburA5iFtcITxwxgZ2f9Hkk3rmjg4g48oCKIZB6w7JQz7CgrvfHaxjwbhGuDHI3Vw5Hooy9S6M2p57tX6vQ+6qaC2m6zSsB1WxrEUC2aJSyAVIsfsfvk2SCmFoP+Bj3ZbP3tfu2mfzsEpeJqkkPiqlqO1weZ22+cdb8IQKBgA0hmqgzYG3X7/BifZfrm57xNU7d7B/ffjbQwKHMV3Op7VQiCcGc87Da1IJiKmm/lk7lgWNDTxFnkQhqUEYo1/ty9JmNeq/OClTkomYiUE+4xs1H1f3oZ1kT8iJga03dS3XvxJOux8UDjJymqFfs8xBsbvBP0i1grc/fZNLkEtfa
|
||||||
mongo:
|
mongo:
|
||||||
connect: mongodb://localhost:27017/?w=majority
|
connect: mongodb://localhost:27017/?w=majority
|
||||||
database: consensus
|
database: consensus
|
||||||
|
|||||||
@ -3,9 +3,9 @@ grpcServer:
|
|||||||
- 127.0.0.1:4531
|
- 127.0.0.1:4531
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWCeSDwgmdmLMweWKf1avCqaBYuzEo5GpMGa8MBBskBmen
|
peerId: 12D3KooWG3ZrWs8Q3kQhQeXp8RWw8FKb2cThTFwD1nbRMMNzf2xW
|
||||||
signingKey: N8fkrWmuf1wVxL72XE4Di8pSyTaQpev/9NV4eznVcfoqB9Z+urz0kg1NKJjWisC/nUGdJP9EB5ZhgPyuQfqIvw==
|
signingKey: P3a0z3Um1QJ2lEwqcaNkVXwMaFz/Xmb2na4RqO79Lw5ch+KZVitiA6jifmRQkPm4z8e1wIf7Eel1VnhuhRuZVw==
|
||||||
encryptionKey: MIIEowIBAAKCAQEAx9vwNRbEUtOuJ+UxXsvepKC1VY76RNv+SnnUIQE2/fXo/1iUEevydpWWD+V4n0DjxMsCViOv/kIOuXArIntFqr5xyRdIFE1nbiSW20IppRZO2Vw2fZwN+5DOl1Z3MfiZsqD2dbdtVLuUP9On1lqPWgW/ZHzweCcVMz2ZZ/txubSBE889bbSoZcNlgXS0fJSaw/6XApgtL++sZBqxwp2lkf918ZM3SFuAVHYU56tAOnZrCbyHcbDk4OOJ1q7NzrxWg71S02yqesuDSjIW6BzIXbDVjS2yvhKRJrrKXSIYepIczPwHPPCs7/pCPE7XQ6sYB9d8BL9/U+doLTJToAhHwwIDAQABAoIBAEZwU9bCMWtnw8e31ZCtlci8A20mOTqvto4VJhiDzxfu5bGpTHaMjCYTTpJHtB2cxyoCys4FQfAA5COjTvCWNdWZzYysMfFF3qBJMQoR5Y+TrzKYd3QJ3ju9q7JW/SeVkMYOSQ7wGQ52FifwtwSrYj6+K9iE2FPgom4u1bR6QHjMcAf9+eDJMUJk6Jg62SATPmiiN3b3OktNSsqvAf06I2K3ob1xIai0aTVcNsEoLbdDTejgFkkU3BHIzY9IXYkfipHV9+51cpRFb8q/Hl4boolgSPUSfe+pC11sm56QZZ7Gt0CF2ejhWyJKiyV50B1enKeeVN50KIMdtQn3VpTN65ECgYEA4wiKX/72Ca9wld+moywqexXNuh0a0gS/cWX4gFRv27jUScR7KTDM2jSPUxUK7F/hONOBBevfA7DMxsNNoPHoK9U2iwCO5fI9n1oWrUUjq9srJvrvsz2n2RmQ2deqmosLs0Gbb/I13+qEkunS7pfIIdul0LFE28PK5BhCDRdOUe8CgYEA4VvSWswkXQP4eNDTe78+GItQ78TluU26b+HOnkPRQlA2lUyxkUZT3VJQcgIptJJ20K13NZypJazJm6QELZPd/WcUAWKZqTSQxXUBwPVuoW5Aw0glXCfUOEG+LU+Ue8tvNCdqrAJopuYkYniT1LsQAOYMbJvL9PGkJosJfq4X620CgYARmgLoaGL440IuTHWl5vGwM0OM716586ZIC2jVwjYd6dmDkpkd22u2aybFgTckllZmyncRV3Ul2xo1OsUU+kxOwawF4NgzWbGPXjOt4VNfqpFQ51mYIuqVeVbynLbcXnVcw3RinHuyzYLTxQ8WcmwQu+/CG0xEYYykXIEadLkcvwKBgQCB5RovicFf99ztTnjHuCjDnvGs8lHzaDERMheVM8PXNELx9X3YHbBTPpHt1P9S/KUNjR7MQRtiAuFGG9joqHVpDVQDpGCrngfgOJwlK5Jz7AfaR6h5IN/6+TH0Dg2o+U6Ewj+DG/RUVw0b0SJsmNIVooQAyiBadDnImZWEdjaFVQKBgDnrnvtTMZFvJofnDNSQfOsDru5Mc9c/WRfegq58ocf8XaMMJyFCZGw90TLgQgWkxDCjQ4qnigFRWRCJ3sWB9LS8uFW5Gif0GtP6foL9rWlsQpCUqVApJRnVFFqW5f5FC4MZHtDTlZUk5lDQuvZjvQjJ+3vmusxEUIP0IS74Gr5+
|
encryptionKey: MIIEowIBAAKCAQEAmi8Yvv3F9/ddTHj4GscR37pr38/NbbDfOtqoervlG1SE7zJglpnwEI6ThhjiAPaXr9UgzvIne8uyGk3ioQz0zDO7X0Omq8wPc1rPDmy4E8mcJyaLyQD4RiTDIuiOKO9+sfWzOwK8zGfPEmBqnfccGOlRelBuREvm4IZnP6HXKetRxxdIexe+W4ZRZN+AuaD5+k3+CPs1l52cIEuBWJ27piiX8oL8indy5gVdNyFPKoTeysJb6pCDYoMoe2EobovSX7hK/28okyJa5SGAVzJpSZCAzn+VljXu4UDMMiWOntiOElsvHuekySg5dAs/LO3lohDdPo9ITAs54P63MHN5cwIDAQABAoIBABDaEu9VF10p2TWxhxSOK4LzgjTdJovVqCBro7x+auUY0MrAC9SKELYOj0s5zwHh8eRS/BoCV5RtSBMd7iZCH0NuaA1afI4MaKfoBfeCpH/tKjcRPHgEth4ciIN5PYh13Lggra1GeFIzCmvsw9puFtEWN0SSI+stDJf/uKs4yiaXmU8xgKplOx97hpTXYLV007mQ2AAZ9ZB3xvUAfADHTtOI46yeO9HMkjoQP2noHyFtKoPXzvra9HBq9M83ohPEE7bew8FAzgxeuiJ+CNU0MSvrW4JVPVcxQbxqsbWJSY+y4HZ6bqFRx9xz6e4iQqVH/XiQWQkET25/iJ+PPi0PP0kCgYEAzF4pY/F8nFnDmi3H4v3p2g8xlLknJaQmvMP0o2L0elZSFJ6YPvL0iOVM1T/5nFjThDOXtux0lSis3C5CZK7LRGQLut8G/5OC290vkwKr+BqqZZ3KIPjBO+RWsOUD2+MBBjQBGQQBy35oQ1Gv+MEUjar7gXRYRhqOY3epQROp0YUCgYEAwSM1cprDtsyqKRpcAFf72D9K0P5F3i/Q0BuitJmV+FaIBa+y1C2H2FxW1rqqScw2zmKeTYz/L4s8paShM8b3SjkzK5dvJ33BN0tqJGVSW06LffLjkh7GVIFQGhPy8qLPDgVY3goDphrnMH6g3gH3ewqRWispu7jwxW6Xn8YIlJcCgYALg1J5muUWOchXKzUTiJJgAnMcmcGm0TSNdcyWV8DGE47UMosJIM69140Yhl4dfLONwwpM980pif0S+lgrK92voKM4h8/xHfJFSJShh4kAlR/8UYNNkDXylc58cKpi/MrV+qAFNMCVIi3lfPiY3ue1g2hfxpoieOSEnf0e+WibsQKBgQCB4tXM7vvz8Yv1/H4m1QTPlzEPgBEorWt2qT8wyaEr07XCbTiMrNoQzXixC/P9kVLCVVw0tz/ej3sHwsGOep5P0kvxYvQj0NSiBRuqwmEyeo4g87nLyNqEdjqSbxwRxSAOQ9ZR7NYrXShhWqeA5j2zB5Zc125HisaRYCCkGKAonQKBgB5CGTP982bbrlmh7bwJFQjQFD6ufXhEr6X8O90yw15sdktp2+bwr+pd85602kqfyN0Ksdm2w43AeV08OxJBQDDSvI6LspS/v3aLXhWT6LPqEtH/Qq8KH4I5UTUsoa2rT/iyAZZ3zjT5W1D63RbPsMsr2ZMTC0bRrCvaCVKfX8ys
|
||||||
mongo:
|
mongo:
|
||||||
connect: mongodb://localhost:27017/?w=majority
|
connect: mongodb://localhost:27017/?w=majority
|
||||||
database: consensus
|
database: consensus
|
||||||
|
|||||||
@ -3,9 +3,9 @@ grpcServer:
|
|||||||
- 127.0.0.1:4532
|
- 127.0.0.1:4532
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWGqsXf6No926wTb2eZdauqDcEkoAdKCeYkNzT6yrL3YDE
|
peerId: 12D3KooWS6PKUYH6Jedkjsut9ajgWSvn53Qz1LLACoPJX6dUbtCg
|
||||||
signingKey: fSLDcrMD0v+yzQwHG+KWdCkuZ5HPvx3vIb+5MecREc5oZJZfrN9P2z8gBU8HqZH/noB4aJRjXRVZsy4M5jPcwQ==
|
signingKey: 11vXVlqQr2e/XMKALUPhMgnJEtZ1HKaDerxXvhNvYfXx1ZWt16PoEMpy/+ZHA1gw3ErI9+2/6auhjGC9InHskQ==
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtM7k4K2spm+GZa13SkRbDuFpPVAdPmR1+aN8IAtmSAISxw2vb4ET47Ck8vDfNtQ9rAvoAn2c3GxJb5Sb0pL9rofeIYYN/qS08zFVP2+FRM5CfuBbfVbwMZ2WvBJD02LzDrHRm0blc8JZDs3xFi5o+mWfeM2SZXVCJHFSNS+v1TRgVfQzu0uKlTD00CLPNz+uzDG6VntlzzEzkF4jVRA59BmkzqAI2ZgtB0cG5ztMnUhnZCX8I0b9CCb0UHjq9j97Xuot/hMAEGVQhNY3iyJx5gAR0t5PipgQZz5j0EXBGPy9T2+VA1QFLHVsUDmd2iV5fmTZziOWn7988Co+ZVMB4wIDAQABAoIBADbQ5ukLHmXTN/7JiXn1oVmwkzRofoU09eN6Yh5g9mBsaH76si5vBrWoD0osJrA7xnrLnUpsBMt69QSkHF3J/KkWPg0R1FpYWxfD5CF4UQIcOmK26GXmnqmcKl/YdcG3pRLWbELUSqo+yLtJSoc8CM2pU6DPSkwCMcxUouTHEVrkpL+Ic6RNGVFjX7E/HjfX9U/BKH0bzwj9CEPQEm9bqc3Zq+EmcE/CHXfRnHdG1cSp65qNHDfyEBjudR4ddItzwpmxLsW6+2Ywlg2pG/vfvRkGvwtAySkVs05J0vrpwSJlPy0NvKAbHAnmNBnmRH4E/myXf5MFcl/nz55J+yJs6QECgYEA1b6fp4FeIBfhvrRseLJeAepZhvmXkRegT61No5632SpcHymz3WnO+EsrL5O6+Ldpa8Gv/LmiVBQjvQeTvx97kINXKPLxmvdxRo+i7YUCAec8AZH7WEkxa0vvi3FLVoZZ8/P5fjvUscwxBeOvwhXnyXsFB9pJduYu6wzuMJe7HmMCgYEA2I1k0YjcTCqOk2Vp1lvHLtnMcmpm4FDMl9uws0HX4UO8i9tXlLZmWqDvPpvhxZVY+1hXOEid67712q1fiei440AGGNxc/xbq8Htw1GBzKyTd9dCQCVwWGX3VUO8EKAKVXdVIyqW+YUqD5PXUcPA41ll+nJdx5Z/liSNJvpxCJoECgYBv2P5GcuXEOXsBhfw09HFI407R2I29ePWEfBVih02BMC9ghzv9or6RIxSIIu/18lQR9RqYTrNo99jzs6FWo6zPJEtZvDc9djoqSENjsvQn9s5pq/AwdKyNjwDcoP5hWpB7nbFyovBb0ZPdlxWDpF7UCbHKOCm1NCJdETka6GscLQKBgQCGh8CcU5PYVY/hjd0kaDvjpTbX1bY3oLqZlMe/dSYyMayOjiNopbAMmXJHyPuHjfKLoyP8OVCyRh3iTlbODB/gPcQL6cp0Rr6Jy4YayhiCMxMZRQpWZjjseTnuX66LVJ+KfZgNHM6bDnnF4dqqlvIYZ9y6V3NQnfcxLRUBL34BAQKBgElDMZD0rP/u6Xch33udIlzdai30QUNWS9MgSrPBz1s8+u1e0g3UnbfCH7e5q0ofSmd+Ot21i03cLgUgJAFmoVmoJ794aveBo/bPbDrlbolxOUX4dFODvvOKzCcUHeOJzc9JE/Ci3LuHyEcqv49uRIe4BFc8c/ssDpj9h7Cyx+qq
|
encryptionKey: MIIEpAIBAAKCAQEAy4PQ8dL0gUmtumZQ3GBmHW7CHsuu/VIMWZSmfEIWgMDqrUDkIQxOZ0+hEDUbtCbAdbklgVmvFWUL/F9frBp14gqyMQG3sG/2l9UsQ3p5Z/jRM/peFCtnUj8Xa4ktsOcKFrjEDuBylqanBCpVXGKMDN5Tx+c8ODaXgdRj4x9vY3BN3w+vxXBXIYDyN6H4SesD988VobW42mveVKl3vaOFDf38LRZUe5T0SUDt4wdeAN/pzpFnH4RR//HYujarhF1yIrs3eVu2ltwrHBQoPTboIW+n13B5eqLVTJcXMAsIM+jA3XNu2ZrgmBLEKn0NZNhAgVvGPwMuUpgFz79rvJvrIwIDAQABAoIBAErRKdZNBGAnUvvMs3tg4Ql+91RU8v7j0/B2yoGx1g39XgjVa0iO+p/WUVLhA09GU8iziQs1ij0mSbK86TIfBClWX03O4NW3Q4Nr9frUop9LhLVEHKPzlOdSlGyPIMIBHd9ei40gjF+/4nSQj5MIE46DiW9bHfNYdnhfOV185/k430Ojm12gi6MMlm9CTysNSdleUlO0udmm5JxkvhosPENLG37Wm8JpbesmPiYZiT+jyu8YOaawAXZeGc8NSDBwovzjAAJ++/yRoKKPcsQUV6EYx47PGibV7aXEwbZ+2133C5tm7KDDfvS7sEQjVBXh9Iea4tmdAu3q/0wn+L5ACpkCgYEA5aIIUDdRUERJly9z0eD+iBA2DRNxi6Lpl/wERMkNWrUhnIVV2wDuKiJK80D5DDbszT/gXvY5oj2diKaakGMkj4UCGyFVRy1/2nvjVUugK5ABf2acWbFrgH00UUuUUwFf4UAjypIsJ4Ue52/l8YTVLAfDWXCw1Bh3h9XznS43gvUCgYEA4uIOAOaZwlLI8OKJcJJsDgJEFfm18tCq3zvC7z1z31CcjG6C30ggE35q5hceznom2gLZBLAMQpwthyLjZoVGESEDBdK6d+qtTN95qz3DBtijVOQ8VuP1q9YLMU2IfFeftlRnaR6eYZpAMh3+/fDXpjKaIYImJQalrivfB4nTVrcCgYEAvheAIkdovLWK5eiWTCuhCSnCVNi/qgRWs0YgkoCM2YYQKO4HwJ/oiGCTAwPKJt5g8RfruTDDTRcMjc69LMGlxlkpASR6380+hbMA4d8U3Hr9gmWDEIzanScIZDPYuU3t/R2Hg221t5Fvn8713xVDEovqnuO2vhzy9jOa04cq1PECgYEAhzuEa0cICQq9GM9+amnsHCF/obWYnOWBo9OEKoNviIEM/qt0OFBORjBI2WKYiyvF8pZV8nRYqm9at7y03Eu96sHJgnQLjySDLVnatJX4pCEGobf0uznfGhBX1YhIPQ0hdlUy2jZU4wpFD1pPvd8LOtXYhvaDc/hVUs51fpHJNVsCgYBUZ9fVCoSni9m/eTlDSsWtk+sL/0LkHT0/ym41wTdeFgefCdZMGFBu91z8Td5ol0yclJjxNr3tGUvINCuSzsM4WRh2f9zSjOka+M841WK31DCUmlhekjmKmYw8Ie147d0P2waVmEIdUs40aCiJW/hcV0ld+H5jg7Od+Yb0rDIWPg==
|
||||||
mongo:
|
mongo:
|
||||||
connect: mongodb://localhost:27017/?w=majority
|
connect: mongodb://localhost:27017/?w=majority
|
||||||
database: consensus
|
database: consensus
|
||||||
|
|||||||
@ -5,39 +5,24 @@ grpcServer:
|
|||||||
- 127.0.0.1:4430
|
- 127.0.0.1:4430
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWRqbgXAdsP9zzBeKv6qjqmW9qfo7TbQfTi4eYYCcpFBwT
|
peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
signingKey: 4JPubXZ2chIF3SFYiEGHvdTs7/B+IbrdUCHWYkNH/E7uC9nsnBle8q/FaG/7b6pNKjXukTGaXnDrSixZw343/g==
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA3xGRPt9EXpes27462scV4Wm71KUZ/mqf6re/x8LW+ZPvuuq1R5bj2AhUYj7oamVvqnpO8N3UxOSQB0N3eKtmi/I4M2OdLhkZHKBdGi/XG+eGRcCaM5kGBdot52dgFkqXunnU1h2khCk8XeWrJL2mnm9eSgSzvxExkQQfx3nCwYLq/ZmgGT+wBHZECxIlzxjpcgGjnCCIthb409YUitF/tnkwkcM9KBZJFJyJxTAmPaISrcpb30xNfxjuI4khst/s55XYsptyqRLzWMvr3fKUg2qN+GUCv4uAEQYLOGde0nVLq7zqofkH3jqXta13q1zi5OBiW75dCXmjtCtdBeMcNwIDAQABAoIBABV/b+wLQF+NZo9W6f0jqqwqsHtx3etzAy5vvv/VezpaU4REEmxv0k2Dn/5H6cY3OGfJmcoE1viSvn60tdLfUeay1U++jetfZ9gmbFKVwbliusIGKdZHLRlrSXk/sTb0wWKrUyO/f5dtEfBKrg/AZ0plmUSw51HGqmw7ZYSn62kSstB3VKEiM0nWQAh2D9R4APMaaBEo3XPJ+l706T+VPK07rD9oBdQmEkhA2Dks1jYzWVGeMY1aNhndPPVKy34BcYJa+z8X41bwUDsE4mNFId2nPVofgaGJiby4A/3adlvLzosBC5kYxj/V9icNH/iEYtwVV2rIjPLXgt54k1L8SQECgYEA5OWewIuAluIIt7RnClmpd6LPQAc24NsfaC+edGj63b1m9VPV1Vyve/+Mp642FUbp1zmFeTfTBOg+577rnrlI2Arfy1vRrHrSRFLEXfyGA6SSpssvDrHmJtJBh/H3kUgLeqsQlX+ov8mtZEelUF2oWSbmP9k5JaoXoN67gGVrAiECgYEA+XtHB2sZOWV8jOCN6ZU4GfjjymNtCRsH2jWs1fBJ5Sfpei9TK/ZemJ7n+vnANiFLycNoQ00EFlOYaTBCCig+vc6/jX+Ecmh4fUb/ZAuYx+GOA1TltcD+OWBrUEqNdrXwICtUWo8/m+As+ntbCmDSZRUIGRny/N549sGEipufA1cCgYEAsA6NlLu4JFWnLuVre+KLHqHzluP1qe3gslouHovAqV1NG9Vn27x2nYFpxm+Q2by5j/mGWD4/6L5Z5BZNVMBe7w0uJVRyaZ/uqu6ea0wYKCUlR3VwtHTQ+XsvPEk4il5Htgptrw+J1DpjS4Zv+OiQ3EG3R9Tkx7uUgP/QaGmZbQECgYAT2xvsGzoGt20SSU0CKj4s0wJOOVuUPfKCC4OWA2neMy8B6oJUHWep/fu4negOZtgBVuwVbyvEGyMmPBEFfe6AbNQSDvQbpvTwA5aP/9xJDEqhOUCPFq0lI+dmnIhlylUyOkCcdIo7fbwWs3qreMlGAkaCuO398jbubLh/z6L4QQKBgQDKUzTECIr75cLiFbUFxcseYFZEc1weYtlp3E28H0rceSD1GakQfu0osi294lLFzWbc4JfZ29F2rFnOAeZ55f4AtFh5xxoY2robre7C5pOklG5zTcHXakvqdWXPtYfi0o2dI/JBRNnS14ZDJqVmROGmMXsdm1et/qARKBI86wORUw==
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
apiServer:
|
apiServer:
|
||||||
port: "8080"
|
port: "8080"
|
||||||
nodes:
|
nodes:
|
||||||
- peerId: 12D3KooWRqbgXAdsP9zzBeKv6qjqmW9qfo7TbQfTi4eYYCcpFBwT
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
address: 127.0.0.1:4430
|
address: 127.0.0.1:4430
|
||||||
signingKey: 4JPubXZ2chIF3SFYiEGHvdTs7/B+IbrdUCHWYkNH/E7uC9nsnBle8q/FaG/7b6pNKjXukTGaXnDrSixZw343/g==
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA3xGRPt9EXpes27462scV4Wm71KUZ/mqf6re/x8LW+ZPvuuq1R5bj2AhUYj7oamVvqnpO8N3UxOSQB0N3eKtmi/I4M2OdLhkZHKBdGi/XG+eGRcCaM5kGBdot52dgFkqXunnU1h2khCk8XeWrJL2mnm9eSgSzvxExkQQfx3nCwYLq/ZmgGT+wBHZECxIlzxjpcgGjnCCIthb409YUitF/tnkwkcM9KBZJFJyJxTAmPaISrcpb30xNfxjuI4khst/s55XYsptyqRLzWMvr3fKUg2qN+GUCv4uAEQYLOGde0nVLq7zqofkH3jqXta13q1zi5OBiW75dCXmjtCtdBeMcNwIDAQABAoIBABV/b+wLQF+NZo9W6f0jqqwqsHtx3etzAy5vvv/VezpaU4REEmxv0k2Dn/5H6cY3OGfJmcoE1viSvn60tdLfUeay1U++jetfZ9gmbFKVwbliusIGKdZHLRlrSXk/sTb0wWKrUyO/f5dtEfBKrg/AZ0plmUSw51HGqmw7ZYSn62kSstB3VKEiM0nWQAh2D9R4APMaaBEo3XPJ+l706T+VPK07rD9oBdQmEkhA2Dks1jYzWVGeMY1aNhndPPVKy34BcYJa+z8X41bwUDsE4mNFId2nPVofgaGJiby4A/3adlvLzosBC5kYxj/V9icNH/iEYtwVV2rIjPLXgt54k1L8SQECgYEA5OWewIuAluIIt7RnClmpd6LPQAc24NsfaC+edGj63b1m9VPV1Vyve/+Mp642FUbp1zmFeTfTBOg+577rnrlI2Arfy1vRrHrSRFLEXfyGA6SSpssvDrHmJtJBh/H3kUgLeqsQlX+ov8mtZEelUF2oWSbmP9k5JaoXoN67gGVrAiECgYEA+XtHB2sZOWV8jOCN6ZU4GfjjymNtCRsH2jWs1fBJ5Sfpei9TK/ZemJ7n+vnANiFLycNoQ00EFlOYaTBCCig+vc6/jX+Ecmh4fUb/ZAuYx+GOA1TltcD+OWBrUEqNdrXwICtUWo8/m+As+ntbCmDSZRUIGRny/N549sGEipufA1cCgYEAsA6NlLu4JFWnLuVre+KLHqHzluP1qe3gslouHovAqV1NG9Vn27x2nYFpxm+Q2by5j/mGWD4/6L5Z5BZNVMBe7w0uJVRyaZ/uqu6ea0wYKCUlR3VwtHTQ+XsvPEk4il5Htgptrw+J1DpjS4Zv+OiQ3EG3R9Tkx7uUgP/QaGmZbQECgYAT2xvsGzoGt20SSU0CKj4s0wJOOVuUPfKCC4OWA2neMy8B6oJUHWep/fu4negOZtgBVuwVbyvEGyMmPBEFfe6AbNQSDvQbpvTwA5aP/9xJDEqhOUCPFq0lI+dmnIhlylUyOkCcdIo7fbwWs3qreMlGAkaCuO398jbubLh/z6L4QQKBgQDKUzTECIr75cLiFbUFxcseYFZEc1weYtlp3E28H0rceSD1GakQfu0osi294lLFzWbc4JfZ29F2rFnOAeZ55f4AtFh5xxoY2robre7C5pOklG5zTcHXakvqdWXPtYfi0o2dI/JBRNnS14ZDJqVmROGmMXsdm1et/qARKBI86wORUw==
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
- peerId: 12D3KooWFYTh59WMXGLDqS8EXfTjHvrS9uXrcYJuE6yDyL1hh45R
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
address: 127.0.0.1:4431
|
address: 127.0.0.1:4431
|
||||||
signingKey: g673H1+gh/KSbRat4m+E+UBTxEmcbxNJ2ZEwdBnQKiFVExLIU7FUXhx7F7xw2QJOw4CInWK6tNZZRNAzOWcD7A==
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
encryptionKey: MIIEpgIBAAKCAQEAwrKCiqwW7ZGgxfG/t/GgPZ/shmbXEtZjDiZKuLugfSOedERYdsPZ4PmPZkVxo1rIoZjZOnoo7qeC5LWk1A0N33LudQF7Qg50O0QyiV5QTRxkv9IUvAeXyUR5TrxD5oRdFKuCbyDUQYaoAOYCBeqSI1ub5HdFt1fDMqgHXVW/p9kMwHEXpHM7ZaARFf5ri9/FIIodb5+IkduSK3/qBPlvt6dy2MlKlHRkzHef4q8YFKuDyzsyF7fdtjhhHk6p86JBnMaQpP+mi3e+qUxhdWEIY1s7Jo1Yal+GDQ0NtRrZp4GdlpFT7Kgp1Sm5OzSrtEQduluc0GWJFAVpolHg8e7QlQIDAQABAoIBAQCTZjIOalqxYR8mvO84g2WdQgX/erw5NrWncLYBRYsrMlw0Ccovn/bDrCw0cT6nPYPHU8Ch1PpIM+mU3S/8miV2lbySOJzoVakJdYgNF6oTtvtPfezUrarsZTqxsTZ2vp75lx8YovIO6bMnevrtH7mjqydKwEG3nGnbX/qzXsfKeeZgd4kvnjlxGTDUen12Pl0kPLcBgyckZLDJmXYtvxuK1sZTjifyHoeGVYpOOLYi3rRSEoZnVS4z/fM1sG5aUM6eA/7HaXDAe5sT0rgmPt0mu6Mo13dF3rWkP/MCqEVdBLfQLXEfqKp/9QuZ7szdsM0b0WPDXP/YXDLALLvL5/vBAoGBAOPeOrG+JyyS85//wKy+ZRZND5IdxBWoPDfItKnQJtMzOMiYcpwF0J0j3VqdulQlz4zX0Zly0iEYtFtNozVLStDn4IPrqg/vJI+vkikDrY/r1lseVFGR0euVtpRth3BybzhR9llfqK1tuR7cCg7NaxnoIkwtbZDumKDPRoXSQmAvAoGBANq76w8ZMdduxQhroE4Hs4uP5g3Yx9bDlimwGBwX0afGoO82kvgxpol4Z/3sXC7dAKoBqLTTpVDq44AkMhSXgT/CGALsebRxqc45orafe3s+rTFoQsR8eXu9pRw6TxjwATMMxZHjIkV2DeQuKIOTZcvd9E1PVmUB3VSwihje7oZ7AoGBAJGSi1S58jTbvKBetyykhdf1axkhwv9C9xV8N061F9idRI2CNtXOMTPykZsuYLcZYLrNta2eWPej3LTnqHiHnUhQmnIsv/xl/ql8tJdXLi5fsBWODrf9vGoQvw+b2YbQ1JTaZ9M49X22Nymr0REb0mw+jIq2CuUoSIGTaa5cYOMpAoGBAK6tnZUsKKqDsmP8F0PZUKAmpbDvKwAup8/Y6hgdSXfz3vfKHGqKtBVai6mzxRZDtdEOjB0EXCQXwODHhxr8tuIk7aoAEV1x3Apt6qxvBlyw+/zV52Qkh5uzIpU9V4dxu3N6Qpkzy12vXn6YAhC5eHTrZrsKndMCPy/v4Ajml5PbAoGBAKugn3Gh4BLUOW9Tvnc9UIwITp8p8+Dx9yQJugHSDzBFGuAZ1FUciCrK8SGarDCyyzY+XBKVuNZEj7D4P2+JiTKv8nweRVj0DdXYUwIsX6cWgPF5i8dm0Nl5PbsR27L+TxficuO4IQRHMz+Loho5itbSuDY9Y07PvKLKJfu7Cd9l
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
- peerId: 12D3KooWHgeiz7EyY59t5fEZnkdg2gJxk3YvJmxpVibEcX2EtUcp
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
address: 127.0.0.1:4432
|
address: 127.0.0.1:4432
|
||||||
signingKey: Tr1OaCpnYVkdeuyoBHAETn3DHWbQZELK2x5xuvd5301045GYTnQdWWT/05UB61dmu1NcY4yznm90baj36GrgUQ==
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA6FzTxWImBPJL+dhVbCUWqcuxBmbR7npbgHNOTJFh38InqxEkGwrulenCyy7bewIQXLMfzxroxm17GpWWV3hMcAzQUOojUSylJPguhrWOOtsJyxxDXyG7MEleaFX51MF+SNEo9ivBYbbwJiFrGv9tGW6D4dGSMl1Xf8yKyKWCJVBah0Pzc57I8e93qOZjaCHRmsgC7DdzD8FyIPnAuxYxNs8iSaYPP/UjcZT/SA+Ldu0vyNxdnHCSs/+3FwbmPyhYrn+uBOUUidfzraVn9ra/xtcCZQXbf4fhJ6iwfp0wJoaDU5akN40910XGQqbF6FLfqZZx220vIcJkHc3McbtiaQIDAQABAoIBAQDjTLMIOduxKQgzTnE5igpibNQty/T+UQkjXSgx9GGGzlmZmPn1zjrXwUUBF0QyTzGMTNkH8m3UdZJfzga0aAR188Lv9Co6JO8je/efZQjOACjTXEF3VPrU4GCOtdPfUKxlNN3Z+bGBEcBXvIcWcNjbcOVnyGc4B2Eprf/xCR6Hufa289Awnf1ixe33VdlBMsuua7qc+gydRF9BNpvTop7n4bGkrPJkpuNp1063QEh6Gi9Za5gM+bd573FsYMhHdECcSWS1ogtTTNsVyLPo+x/Naj1pC3UTmAFXyiseeVJ82ibMCOBywr13I0WlknNoxGevU/een4sxX4K3CFH0YGZRAoGBAPVz2qhTDSplq0EVnUVEINfvNTEDLgUMBbdrwpO6FeMR/QBohGB+Yzoen4rBNqnLOOSsetaWYN1u2XgyA9RyL6wnO7hOhlpgY9m5+CCKOwKhPwIBGOOsaFwKLzwDcACK8rg5S/EGDRYCT2SfKv2bSdyLxVt4bXjvMZBQ0lt86R8tAoGBAPJY+Yb5vwiyMlQk16spB/KoQ/hZmjuWUt6tIDf/B9/LM/vMfguJJRq+tmBa2JxvYmUj3lIt7Sg5RiFECIiZ9MW3H7rCu+SHRN5HaDjKOkFX8qTTPJJu5LyBcCnHHxQBi4t5bVTAbKfpBXTi7lr5aAhUIztUVc9Poyz9mm410TWtAoGBAPCaOnLZxoQS2UaZW2r0l4VUNL3wsgG8gTYFadzJgn7tuSXXTjwQaFAmiJnJQD48uW5fLKKBEj69VGugC2UK8XQ9mSrXvpeE+RwKUhIDrkirq0nZrX4wGLRwP1ECxZ2ilr7DW4/OMLGsXgryg3/J4yNP14wMhrMPNXST5UBNN2+ZAoGAcfb7aMjbWBiMaFtm/DtwXGFajVh9mhXn5IVfiFWq+0fQq1GP2Jbm1vvmQcuW34HVsKA8dULZqre8TfpzVOGpZKzoA+h9eUtPTIQh88rNuFrGZVJcwrPZZvgrqcnUyJCtcappiphuwEtpYH0y/58XmAsRAl53d+UIZCjiTX+LYYUCgYBWuUASFeKBWp8/jRO6xgcKT7DErnMZr3TRYkduH9miIlqhx4NH+K/hkgkIFk77ov1swj2XrPL/rMMtWDRsn8fvwhRYkU25FCNAdmSg3G2iaW3Pd99d/fsdJtE+VjVQv58R6nxp5aiVH2rX9l/tspdUsupoYdFDDHYDkL+lIu2ZIA==
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
- peerId: 12D3KooWJpE9AtG4RX4Dwm4vhrCGqiUhKj6Mvbqj2V4rV4diyksT
|
|
||||||
address: 127.0.0.1:4530
|
|
||||||
signingKey: 6tA9VizrAMtsZlzBXXnsg+LzwSwBLU7oiVP1qOHN4PaFsBslV0nt2aKBXfcfxp17V/bvydNfyYbGu50F6spLCg==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtsYet7J4bNo9zSPFZVFkkInUoAW7os8PtZH6qMUEOKcLAi1PDbkBBCmzHdfuzik8H8DgQl36/0gCqRPM6nhQlbF59mV7brI8/kH3Eiw0rxqWAe0+C6CzDyEqtKC7pJyC3FJe0MZRRtDXiDYlVurHrsW22fA03rJY5++eW6bXiqL7WB44zxMrztkvPljlhDf2XTAcrZWI10oXKjSZMW051Figbhdl06R1ZiW1F1LmUEd3ufiYoevpq8jAHWIToTZrYNX0sfrdNaf/CPCq9ZDSqISf8CZ/bE1VxYRPEnjmX1hZQ132S1KCEQwpBWxpcvePonEMPGp+5F7h4k+46f16vQIDAQABAoIBAEa8np7Rv7HBNTHzqi3wNk+KSHQ2Q8xa/uVyveQbe+rBG42YI4RYGYCW8u+V5qJ7av2PFDwbS00JfZ4aP7BvKCEHMwCdfgv1h42P0iOCYFF0pKHSQ7UUWLh+SZzmqDipKixC5NdAKaySnxfkfMcKzoVhl8b5JD0cITSClHM8Oyc4DR5DeB9MlgrVqV/fcdzR10J6TeEPyJjs7CF+Y4OFUEf8FnNxfx5btWm8dIxRMiFUqdI1SVHmOJo0wO2z36RKZ2f8eHApafpJ/1MWccCCSB34Kry4WjDLn8yfOZ5GavXKDVKnE2won5ZhpZGTaLVHLR8QzvkzuBHDk1j1kSi2RjECgYEAzwjnJc5F8XdOkNNPKpftnUVlijhEx0lSknL/j1wIE7bdqbGvIhW+OlIP3bc6O5h0QGSoB71cAiurzro9rsZnSZ4qqjyeGh55j8I4RoZHGDu8BoUOXzrIL1nw3JWxrsNxu5hV9bcYAOJDG9BOcm7F9g00+f+p2zR7BvZMYm3d0vsCgYEA4gBSbChHTMHs15wppaTqV5iQEbfAU/oweRBnflQTHVdezMDt85BpZv0ik2vTuhMJuiaISMvb5l2fHI+LIKoZgCBfymQ50Yv6dZqOMeY5XwUQiQ8DtVtoetYBwwPIS3hSntTu/a4Q9tZbmmWYG6rZ7X58UrtVHY5DfFMS8MOrO6cCgYEAgDkGV57KKMN4cC+/DyUrL8VEHve8eSSLNFJuvs4D3pnZ7Pgz/Es1Fo+ubeXF9hT0otD0VF7NtjZv4Mft3enZHHoN+IM0c/690PA7xEnzjCmqyOrtPMN+Kf1tNGCtvAwly0aMrnKoNhvr7jTz8OF0T3BciBz0iOOW8nfmVOuwf7MCgYB9va4eDR72XuMWZwVo6uOTTwfBQ9oXHxk/ElhymfZ0mbrd8u2xWQS7z1UgbprDaXo8/tlOn1W+yxIOwvKmft1nQxvosHDW3KnCKva4Xp5G9rtndloa2ju8NDuQtBcJnm1hf5lkvSclHsiik6nYoutTTs9+/El0A0Ya8uGT4Vnw+wKBgDq6yliV5g56J3+gHB4w8yQSoIx4AjHoGkYbaVNiCNLfH02VVIGINnlBk+6xurHUwBg68cAsMSAPWqky3BMvhpAAoyPDBycrWEYKHvKvVsH5R0JRDymVJ3UHJVzCp49+CHIoOElnR+IueVluljtxTrB4JgJj0NOLKOHiTNHW6emJ
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWCeSDwgmdmLMweWKf1avCqaBYuzEo5GpMGa8MBBskBmen
|
|
||||||
address: 127.0.0.1:4531
|
|
||||||
signingKey: N8fkrWmuf1wVxL72XE4Di8pSyTaQpev/9NV4eznVcfoqB9Z+urz0kg1NKJjWisC/nUGdJP9EB5ZhgPyuQfqIvw==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAx9vwNRbEUtOuJ+UxXsvepKC1VY76RNv+SnnUIQE2/fXo/1iUEevydpWWD+V4n0DjxMsCViOv/kIOuXArIntFqr5xyRdIFE1nbiSW20IppRZO2Vw2fZwN+5DOl1Z3MfiZsqD2dbdtVLuUP9On1lqPWgW/ZHzweCcVMz2ZZ/txubSBE889bbSoZcNlgXS0fJSaw/6XApgtL++sZBqxwp2lkf918ZM3SFuAVHYU56tAOnZrCbyHcbDk4OOJ1q7NzrxWg71S02yqesuDSjIW6BzIXbDVjS2yvhKRJrrKXSIYepIczPwHPPCs7/pCPE7XQ6sYB9d8BL9/U+doLTJToAhHwwIDAQABAoIBAEZwU9bCMWtnw8e31ZCtlci8A20mOTqvto4VJhiDzxfu5bGpTHaMjCYTTpJHtB2cxyoCys4FQfAA5COjTvCWNdWZzYysMfFF3qBJMQoR5Y+TrzKYd3QJ3ju9q7JW/SeVkMYOSQ7wGQ52FifwtwSrYj6+K9iE2FPgom4u1bR6QHjMcAf9+eDJMUJk6Jg62SATPmiiN3b3OktNSsqvAf06I2K3ob1xIai0aTVcNsEoLbdDTejgFkkU3BHIzY9IXYkfipHV9+51cpRFb8q/Hl4boolgSPUSfe+pC11sm56QZZ7Gt0CF2ejhWyJKiyV50B1enKeeVN50KIMdtQn3VpTN65ECgYEA4wiKX/72Ca9wld+moywqexXNuh0a0gS/cWX4gFRv27jUScR7KTDM2jSPUxUK7F/hONOBBevfA7DMxsNNoPHoK9U2iwCO5fI9n1oWrUUjq9srJvrvsz2n2RmQ2deqmosLs0Gbb/I13+qEkunS7pfIIdul0LFE28PK5BhCDRdOUe8CgYEA4VvSWswkXQP4eNDTe78+GItQ78TluU26b+HOnkPRQlA2lUyxkUZT3VJQcgIptJJ20K13NZypJazJm6QELZPd/WcUAWKZqTSQxXUBwPVuoW5Aw0glXCfUOEG+LU+Ue8tvNCdqrAJopuYkYniT1LsQAOYMbJvL9PGkJosJfq4X620CgYARmgLoaGL440IuTHWl5vGwM0OM716586ZIC2jVwjYd6dmDkpkd22u2aybFgTckllZmyncRV3Ul2xo1OsUU+kxOwawF4NgzWbGPXjOt4VNfqpFQ51mYIuqVeVbynLbcXnVcw3RinHuyzYLTxQ8WcmwQu+/CG0xEYYykXIEadLkcvwKBgQCB5RovicFf99ztTnjHuCjDnvGs8lHzaDERMheVM8PXNELx9X3YHbBTPpHt1P9S/KUNjR7MQRtiAuFGG9joqHVpDVQDpGCrngfgOJwlK5Jz7AfaR6h5IN/6+TH0Dg2o+U6Ewj+DG/RUVw0b0SJsmNIVooQAyiBadDnImZWEdjaFVQKBgDnrnvtTMZFvJofnDNSQfOsDru5Mc9c/WRfegq58ocf8XaMMJyFCZGw90TLgQgWkxDCjQ4qnigFRWRCJ3sWB9LS8uFW5Gif0GtP6foL9rWlsQpCUqVApJRnVFFqW5f5FC4MZHtDTlZUk5lDQuvZjvQjJ+3vmusxEUIP0IS74Gr5+
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWGqsXf6No926wTb2eZdauqDcEkoAdKCeYkNzT6yrL3YDE
|
|
||||||
address: 127.0.0.1:4532
|
|
||||||
signingKey: fSLDcrMD0v+yzQwHG+KWdCkuZ5HPvx3vIb+5MecREc5oZJZfrN9P2z8gBU8HqZH/noB4aJRjXRVZsy4M5jPcwQ==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtM7k4K2spm+GZa13SkRbDuFpPVAdPmR1+aN8IAtmSAISxw2vb4ET47Ck8vDfNtQ9rAvoAn2c3GxJb5Sb0pL9rofeIYYN/qS08zFVP2+FRM5CfuBbfVbwMZ2WvBJD02LzDrHRm0blc8JZDs3xFi5o+mWfeM2SZXVCJHFSNS+v1TRgVfQzu0uKlTD00CLPNz+uzDG6VntlzzEzkF4jVRA59BmkzqAI2ZgtB0cG5ztMnUhnZCX8I0b9CCb0UHjq9j97Xuot/hMAEGVQhNY3iyJx5gAR0t5PipgQZz5j0EXBGPy9T2+VA1QFLHVsUDmd2iV5fmTZziOWn7988Co+ZVMB4wIDAQABAoIBADbQ5ukLHmXTN/7JiXn1oVmwkzRofoU09eN6Yh5g9mBsaH76si5vBrWoD0osJrA7xnrLnUpsBMt69QSkHF3J/KkWPg0R1FpYWxfD5CF4UQIcOmK26GXmnqmcKl/YdcG3pRLWbELUSqo+yLtJSoc8CM2pU6DPSkwCMcxUouTHEVrkpL+Ic6RNGVFjX7E/HjfX9U/BKH0bzwj9CEPQEm9bqc3Zq+EmcE/CHXfRnHdG1cSp65qNHDfyEBjudR4ddItzwpmxLsW6+2Ywlg2pG/vfvRkGvwtAySkVs05J0vrpwSJlPy0NvKAbHAnmNBnmRH4E/myXf5MFcl/nz55J+yJs6QECgYEA1b6fp4FeIBfhvrRseLJeAepZhvmXkRegT61No5632SpcHymz3WnO+EsrL5O6+Ldpa8Gv/LmiVBQjvQeTvx97kINXKPLxmvdxRo+i7YUCAec8AZH7WEkxa0vvi3FLVoZZ8/P5fjvUscwxBeOvwhXnyXsFB9pJduYu6wzuMJe7HmMCgYEA2I1k0YjcTCqOk2Vp1lvHLtnMcmpm4FDMl9uws0HX4UO8i9tXlLZmWqDvPpvhxZVY+1hXOEid67712q1fiei440AGGNxc/xbq8Htw1GBzKyTd9dCQCVwWGX3VUO8EKAKVXdVIyqW+YUqD5PXUcPA41ll+nJdx5Z/liSNJvpxCJoECgYBv2P5GcuXEOXsBhfw09HFI407R2I29ePWEfBVih02BMC9ghzv9or6RIxSIIu/18lQR9RqYTrNo99jzs6FWo6zPJEtZvDc9djoqSENjsvQn9s5pq/AwdKyNjwDcoP5hWpB7nbFyovBb0ZPdlxWDpF7UCbHKOCm1NCJdETka6GscLQKBgQCGh8CcU5PYVY/hjd0kaDvjpTbX1bY3oLqZlMe/dSYyMayOjiNopbAMmXJHyPuHjfKLoyP8OVCyRh3iTlbODB/gPcQL6cp0Rr6Jy4YayhiCMxMZRQpWZjjseTnuX66LVJ+KfZgNHM6bDnnF4dqqlvIYZ9y6V3NQnfcxLRUBL34BAQKBgElDMZD0rP/u6Xch33udIlzdai30QUNWS9MgSrPBz1s8+u1e0g3UnbfCH7e5q0ofSmd+Ot21i03cLgUgJAFmoVmoJ794aveBo/bPbDrlbolxOUX4dFODvvOKzCcUHeOJzc9JE/Ci3LuHyEcqv49uRIe4BFc8c/ssDpj9h7Cyx+qq
|
|
||||||
isConsensus: true
|
|
||||||
space:
|
space:
|
||||||
gcTTL: 60
|
gcTTL: 60
|
||||||
syncPeriod: 10
|
syncPeriod: 10
|
||||||
|
|||||||
@ -5,39 +5,24 @@ grpcServer:
|
|||||||
- 127.0.0.1:4431
|
- 127.0.0.1:4431
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWFYTh59WMXGLDqS8EXfTjHvrS9uXrcYJuE6yDyL1hh45R
|
peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
signingKey: g673H1+gh/KSbRat4m+E+UBTxEmcbxNJ2ZEwdBnQKiFVExLIU7FUXhx7F7xw2QJOw4CInWK6tNZZRNAzOWcD7A==
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
encryptionKey: MIIEpgIBAAKCAQEAwrKCiqwW7ZGgxfG/t/GgPZ/shmbXEtZjDiZKuLugfSOedERYdsPZ4PmPZkVxo1rIoZjZOnoo7qeC5LWk1A0N33LudQF7Qg50O0QyiV5QTRxkv9IUvAeXyUR5TrxD5oRdFKuCbyDUQYaoAOYCBeqSI1ub5HdFt1fDMqgHXVW/p9kMwHEXpHM7ZaARFf5ri9/FIIodb5+IkduSK3/qBPlvt6dy2MlKlHRkzHef4q8YFKuDyzsyF7fdtjhhHk6p86JBnMaQpP+mi3e+qUxhdWEIY1s7Jo1Yal+GDQ0NtRrZp4GdlpFT7Kgp1Sm5OzSrtEQduluc0GWJFAVpolHg8e7QlQIDAQABAoIBAQCTZjIOalqxYR8mvO84g2WdQgX/erw5NrWncLYBRYsrMlw0Ccovn/bDrCw0cT6nPYPHU8Ch1PpIM+mU3S/8miV2lbySOJzoVakJdYgNF6oTtvtPfezUrarsZTqxsTZ2vp75lx8YovIO6bMnevrtH7mjqydKwEG3nGnbX/qzXsfKeeZgd4kvnjlxGTDUen12Pl0kPLcBgyckZLDJmXYtvxuK1sZTjifyHoeGVYpOOLYi3rRSEoZnVS4z/fM1sG5aUM6eA/7HaXDAe5sT0rgmPt0mu6Mo13dF3rWkP/MCqEVdBLfQLXEfqKp/9QuZ7szdsM0b0WPDXP/YXDLALLvL5/vBAoGBAOPeOrG+JyyS85//wKy+ZRZND5IdxBWoPDfItKnQJtMzOMiYcpwF0J0j3VqdulQlz4zX0Zly0iEYtFtNozVLStDn4IPrqg/vJI+vkikDrY/r1lseVFGR0euVtpRth3BybzhR9llfqK1tuR7cCg7NaxnoIkwtbZDumKDPRoXSQmAvAoGBANq76w8ZMdduxQhroE4Hs4uP5g3Yx9bDlimwGBwX0afGoO82kvgxpol4Z/3sXC7dAKoBqLTTpVDq44AkMhSXgT/CGALsebRxqc45orafe3s+rTFoQsR8eXu9pRw6TxjwATMMxZHjIkV2DeQuKIOTZcvd9E1PVmUB3VSwihje7oZ7AoGBAJGSi1S58jTbvKBetyykhdf1axkhwv9C9xV8N061F9idRI2CNtXOMTPykZsuYLcZYLrNta2eWPej3LTnqHiHnUhQmnIsv/xl/ql8tJdXLi5fsBWODrf9vGoQvw+b2YbQ1JTaZ9M49X22Nymr0REb0mw+jIq2CuUoSIGTaa5cYOMpAoGBAK6tnZUsKKqDsmP8F0PZUKAmpbDvKwAup8/Y6hgdSXfz3vfKHGqKtBVai6mzxRZDtdEOjB0EXCQXwODHhxr8tuIk7aoAEV1x3Apt6qxvBlyw+/zV52Qkh5uzIpU9V4dxu3N6Qpkzy12vXn6YAhC5eHTrZrsKndMCPy/v4Ajml5PbAoGBAKugn3Gh4BLUOW9Tvnc9UIwITp8p8+Dx9yQJugHSDzBFGuAZ1FUciCrK8SGarDCyyzY+XBKVuNZEj7D4P2+JiTKv8nweRVj0DdXYUwIsX6cWgPF5i8dm0Nl5PbsR27L+TxficuO4IQRHMz+Loho5itbSuDY9Y07PvKLKJfu7Cd9l
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
apiServer:
|
apiServer:
|
||||||
port: "8081"
|
port: "8081"
|
||||||
nodes:
|
nodes:
|
||||||
- peerId: 12D3KooWRqbgXAdsP9zzBeKv6qjqmW9qfo7TbQfTi4eYYCcpFBwT
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
address: 127.0.0.1:4430
|
address: 127.0.0.1:4430
|
||||||
signingKey: 4JPubXZ2chIF3SFYiEGHvdTs7/B+IbrdUCHWYkNH/E7uC9nsnBle8q/FaG/7b6pNKjXukTGaXnDrSixZw343/g==
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA3xGRPt9EXpes27462scV4Wm71KUZ/mqf6re/x8LW+ZPvuuq1R5bj2AhUYj7oamVvqnpO8N3UxOSQB0N3eKtmi/I4M2OdLhkZHKBdGi/XG+eGRcCaM5kGBdot52dgFkqXunnU1h2khCk8XeWrJL2mnm9eSgSzvxExkQQfx3nCwYLq/ZmgGT+wBHZECxIlzxjpcgGjnCCIthb409YUitF/tnkwkcM9KBZJFJyJxTAmPaISrcpb30xNfxjuI4khst/s55XYsptyqRLzWMvr3fKUg2qN+GUCv4uAEQYLOGde0nVLq7zqofkH3jqXta13q1zi5OBiW75dCXmjtCtdBeMcNwIDAQABAoIBABV/b+wLQF+NZo9W6f0jqqwqsHtx3etzAy5vvv/VezpaU4REEmxv0k2Dn/5H6cY3OGfJmcoE1viSvn60tdLfUeay1U++jetfZ9gmbFKVwbliusIGKdZHLRlrSXk/sTb0wWKrUyO/f5dtEfBKrg/AZ0plmUSw51HGqmw7ZYSn62kSstB3VKEiM0nWQAh2D9R4APMaaBEo3XPJ+l706T+VPK07rD9oBdQmEkhA2Dks1jYzWVGeMY1aNhndPPVKy34BcYJa+z8X41bwUDsE4mNFId2nPVofgaGJiby4A/3adlvLzosBC5kYxj/V9icNH/iEYtwVV2rIjPLXgt54k1L8SQECgYEA5OWewIuAluIIt7RnClmpd6LPQAc24NsfaC+edGj63b1m9VPV1Vyve/+Mp642FUbp1zmFeTfTBOg+577rnrlI2Arfy1vRrHrSRFLEXfyGA6SSpssvDrHmJtJBh/H3kUgLeqsQlX+ov8mtZEelUF2oWSbmP9k5JaoXoN67gGVrAiECgYEA+XtHB2sZOWV8jOCN6ZU4GfjjymNtCRsH2jWs1fBJ5Sfpei9TK/ZemJ7n+vnANiFLycNoQ00EFlOYaTBCCig+vc6/jX+Ecmh4fUb/ZAuYx+GOA1TltcD+OWBrUEqNdrXwICtUWo8/m+As+ntbCmDSZRUIGRny/N549sGEipufA1cCgYEAsA6NlLu4JFWnLuVre+KLHqHzluP1qe3gslouHovAqV1NG9Vn27x2nYFpxm+Q2by5j/mGWD4/6L5Z5BZNVMBe7w0uJVRyaZ/uqu6ea0wYKCUlR3VwtHTQ+XsvPEk4il5Htgptrw+J1DpjS4Zv+OiQ3EG3R9Tkx7uUgP/QaGmZbQECgYAT2xvsGzoGt20SSU0CKj4s0wJOOVuUPfKCC4OWA2neMy8B6oJUHWep/fu4negOZtgBVuwVbyvEGyMmPBEFfe6AbNQSDvQbpvTwA5aP/9xJDEqhOUCPFq0lI+dmnIhlylUyOkCcdIo7fbwWs3qreMlGAkaCuO398jbubLh/z6L4QQKBgQDKUzTECIr75cLiFbUFxcseYFZEc1weYtlp3E28H0rceSD1GakQfu0osi294lLFzWbc4JfZ29F2rFnOAeZ55f4AtFh5xxoY2robre7C5pOklG5zTcHXakvqdWXPtYfi0o2dI/JBRNnS14ZDJqVmROGmMXsdm1et/qARKBI86wORUw==
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
- peerId: 12D3KooWFYTh59WMXGLDqS8EXfTjHvrS9uXrcYJuE6yDyL1hh45R
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
address: 127.0.0.1:4431
|
address: 127.0.0.1:4431
|
||||||
signingKey: g673H1+gh/KSbRat4m+E+UBTxEmcbxNJ2ZEwdBnQKiFVExLIU7FUXhx7F7xw2QJOw4CInWK6tNZZRNAzOWcD7A==
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
encryptionKey: MIIEpgIBAAKCAQEAwrKCiqwW7ZGgxfG/t/GgPZ/shmbXEtZjDiZKuLugfSOedERYdsPZ4PmPZkVxo1rIoZjZOnoo7qeC5LWk1A0N33LudQF7Qg50O0QyiV5QTRxkv9IUvAeXyUR5TrxD5oRdFKuCbyDUQYaoAOYCBeqSI1ub5HdFt1fDMqgHXVW/p9kMwHEXpHM7ZaARFf5ri9/FIIodb5+IkduSK3/qBPlvt6dy2MlKlHRkzHef4q8YFKuDyzsyF7fdtjhhHk6p86JBnMaQpP+mi3e+qUxhdWEIY1s7Jo1Yal+GDQ0NtRrZp4GdlpFT7Kgp1Sm5OzSrtEQduluc0GWJFAVpolHg8e7QlQIDAQABAoIBAQCTZjIOalqxYR8mvO84g2WdQgX/erw5NrWncLYBRYsrMlw0Ccovn/bDrCw0cT6nPYPHU8Ch1PpIM+mU3S/8miV2lbySOJzoVakJdYgNF6oTtvtPfezUrarsZTqxsTZ2vp75lx8YovIO6bMnevrtH7mjqydKwEG3nGnbX/qzXsfKeeZgd4kvnjlxGTDUen12Pl0kPLcBgyckZLDJmXYtvxuK1sZTjifyHoeGVYpOOLYi3rRSEoZnVS4z/fM1sG5aUM6eA/7HaXDAe5sT0rgmPt0mu6Mo13dF3rWkP/MCqEVdBLfQLXEfqKp/9QuZ7szdsM0b0WPDXP/YXDLALLvL5/vBAoGBAOPeOrG+JyyS85//wKy+ZRZND5IdxBWoPDfItKnQJtMzOMiYcpwF0J0j3VqdulQlz4zX0Zly0iEYtFtNozVLStDn4IPrqg/vJI+vkikDrY/r1lseVFGR0euVtpRth3BybzhR9llfqK1tuR7cCg7NaxnoIkwtbZDumKDPRoXSQmAvAoGBANq76w8ZMdduxQhroE4Hs4uP5g3Yx9bDlimwGBwX0afGoO82kvgxpol4Z/3sXC7dAKoBqLTTpVDq44AkMhSXgT/CGALsebRxqc45orafe3s+rTFoQsR8eXu9pRw6TxjwATMMxZHjIkV2DeQuKIOTZcvd9E1PVmUB3VSwihje7oZ7AoGBAJGSi1S58jTbvKBetyykhdf1axkhwv9C9xV8N061F9idRI2CNtXOMTPykZsuYLcZYLrNta2eWPej3LTnqHiHnUhQmnIsv/xl/ql8tJdXLi5fsBWODrf9vGoQvw+b2YbQ1JTaZ9M49X22Nymr0REb0mw+jIq2CuUoSIGTaa5cYOMpAoGBAK6tnZUsKKqDsmP8F0PZUKAmpbDvKwAup8/Y6hgdSXfz3vfKHGqKtBVai6mzxRZDtdEOjB0EXCQXwODHhxr8tuIk7aoAEV1x3Apt6qxvBlyw+/zV52Qkh5uzIpU9V4dxu3N6Qpkzy12vXn6YAhC5eHTrZrsKndMCPy/v4Ajml5PbAoGBAKugn3Gh4BLUOW9Tvnc9UIwITp8p8+Dx9yQJugHSDzBFGuAZ1FUciCrK8SGarDCyyzY+XBKVuNZEj7D4P2+JiTKv8nweRVj0DdXYUwIsX6cWgPF5i8dm0Nl5PbsR27L+TxficuO4IQRHMz+Loho5itbSuDY9Y07PvKLKJfu7Cd9l
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
- peerId: 12D3KooWHgeiz7EyY59t5fEZnkdg2gJxk3YvJmxpVibEcX2EtUcp
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
address: 127.0.0.1:4432
|
address: 127.0.0.1:4432
|
||||||
signingKey: Tr1OaCpnYVkdeuyoBHAETn3DHWbQZELK2x5xuvd5301045GYTnQdWWT/05UB61dmu1NcY4yznm90baj36GrgUQ==
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA6FzTxWImBPJL+dhVbCUWqcuxBmbR7npbgHNOTJFh38InqxEkGwrulenCyy7bewIQXLMfzxroxm17GpWWV3hMcAzQUOojUSylJPguhrWOOtsJyxxDXyG7MEleaFX51MF+SNEo9ivBYbbwJiFrGv9tGW6D4dGSMl1Xf8yKyKWCJVBah0Pzc57I8e93qOZjaCHRmsgC7DdzD8FyIPnAuxYxNs8iSaYPP/UjcZT/SA+Ldu0vyNxdnHCSs/+3FwbmPyhYrn+uBOUUidfzraVn9ra/xtcCZQXbf4fhJ6iwfp0wJoaDU5akN40910XGQqbF6FLfqZZx220vIcJkHc3McbtiaQIDAQABAoIBAQDjTLMIOduxKQgzTnE5igpibNQty/T+UQkjXSgx9GGGzlmZmPn1zjrXwUUBF0QyTzGMTNkH8m3UdZJfzga0aAR188Lv9Co6JO8je/efZQjOACjTXEF3VPrU4GCOtdPfUKxlNN3Z+bGBEcBXvIcWcNjbcOVnyGc4B2Eprf/xCR6Hufa289Awnf1ixe33VdlBMsuua7qc+gydRF9BNpvTop7n4bGkrPJkpuNp1063QEh6Gi9Za5gM+bd573FsYMhHdECcSWS1ogtTTNsVyLPo+x/Naj1pC3UTmAFXyiseeVJ82ibMCOBywr13I0WlknNoxGevU/een4sxX4K3CFH0YGZRAoGBAPVz2qhTDSplq0EVnUVEINfvNTEDLgUMBbdrwpO6FeMR/QBohGB+Yzoen4rBNqnLOOSsetaWYN1u2XgyA9RyL6wnO7hOhlpgY9m5+CCKOwKhPwIBGOOsaFwKLzwDcACK8rg5S/EGDRYCT2SfKv2bSdyLxVt4bXjvMZBQ0lt86R8tAoGBAPJY+Yb5vwiyMlQk16spB/KoQ/hZmjuWUt6tIDf/B9/LM/vMfguJJRq+tmBa2JxvYmUj3lIt7Sg5RiFECIiZ9MW3H7rCu+SHRN5HaDjKOkFX8qTTPJJu5LyBcCnHHxQBi4t5bVTAbKfpBXTi7lr5aAhUIztUVc9Poyz9mm410TWtAoGBAPCaOnLZxoQS2UaZW2r0l4VUNL3wsgG8gTYFadzJgn7tuSXXTjwQaFAmiJnJQD48uW5fLKKBEj69VGugC2UK8XQ9mSrXvpeE+RwKUhIDrkirq0nZrX4wGLRwP1ECxZ2ilr7DW4/OMLGsXgryg3/J4yNP14wMhrMPNXST5UBNN2+ZAoGAcfb7aMjbWBiMaFtm/DtwXGFajVh9mhXn5IVfiFWq+0fQq1GP2Jbm1vvmQcuW34HVsKA8dULZqre8TfpzVOGpZKzoA+h9eUtPTIQh88rNuFrGZVJcwrPZZvgrqcnUyJCtcappiphuwEtpYH0y/58XmAsRAl53d+UIZCjiTX+LYYUCgYBWuUASFeKBWp8/jRO6xgcKT7DErnMZr3TRYkduH9miIlqhx4NH+K/hkgkIFk77ov1swj2XrPL/rMMtWDRsn8fvwhRYkU25FCNAdmSg3G2iaW3Pd99d/fsdJtE+VjVQv58R6nxp5aiVH2rX9l/tspdUsupoYdFDDHYDkL+lIu2ZIA==
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
- peerId: 12D3KooWJpE9AtG4RX4Dwm4vhrCGqiUhKj6Mvbqj2V4rV4diyksT
|
|
||||||
address: 127.0.0.1:4530
|
|
||||||
signingKey: 6tA9VizrAMtsZlzBXXnsg+LzwSwBLU7oiVP1qOHN4PaFsBslV0nt2aKBXfcfxp17V/bvydNfyYbGu50F6spLCg==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtsYet7J4bNo9zSPFZVFkkInUoAW7os8PtZH6qMUEOKcLAi1PDbkBBCmzHdfuzik8H8DgQl36/0gCqRPM6nhQlbF59mV7brI8/kH3Eiw0rxqWAe0+C6CzDyEqtKC7pJyC3FJe0MZRRtDXiDYlVurHrsW22fA03rJY5++eW6bXiqL7WB44zxMrztkvPljlhDf2XTAcrZWI10oXKjSZMW051Figbhdl06R1ZiW1F1LmUEd3ufiYoevpq8jAHWIToTZrYNX0sfrdNaf/CPCq9ZDSqISf8CZ/bE1VxYRPEnjmX1hZQ132S1KCEQwpBWxpcvePonEMPGp+5F7h4k+46f16vQIDAQABAoIBAEa8np7Rv7HBNTHzqi3wNk+KSHQ2Q8xa/uVyveQbe+rBG42YI4RYGYCW8u+V5qJ7av2PFDwbS00JfZ4aP7BvKCEHMwCdfgv1h42P0iOCYFF0pKHSQ7UUWLh+SZzmqDipKixC5NdAKaySnxfkfMcKzoVhl8b5JD0cITSClHM8Oyc4DR5DeB9MlgrVqV/fcdzR10J6TeEPyJjs7CF+Y4OFUEf8FnNxfx5btWm8dIxRMiFUqdI1SVHmOJo0wO2z36RKZ2f8eHApafpJ/1MWccCCSB34Kry4WjDLn8yfOZ5GavXKDVKnE2won5ZhpZGTaLVHLR8QzvkzuBHDk1j1kSi2RjECgYEAzwjnJc5F8XdOkNNPKpftnUVlijhEx0lSknL/j1wIE7bdqbGvIhW+OlIP3bc6O5h0QGSoB71cAiurzro9rsZnSZ4qqjyeGh55j8I4RoZHGDu8BoUOXzrIL1nw3JWxrsNxu5hV9bcYAOJDG9BOcm7F9g00+f+p2zR7BvZMYm3d0vsCgYEA4gBSbChHTMHs15wppaTqV5iQEbfAU/oweRBnflQTHVdezMDt85BpZv0ik2vTuhMJuiaISMvb5l2fHI+LIKoZgCBfymQ50Yv6dZqOMeY5XwUQiQ8DtVtoetYBwwPIS3hSntTu/a4Q9tZbmmWYG6rZ7X58UrtVHY5DfFMS8MOrO6cCgYEAgDkGV57KKMN4cC+/DyUrL8VEHve8eSSLNFJuvs4D3pnZ7Pgz/Es1Fo+ubeXF9hT0otD0VF7NtjZv4Mft3enZHHoN+IM0c/690PA7xEnzjCmqyOrtPMN+Kf1tNGCtvAwly0aMrnKoNhvr7jTz8OF0T3BciBz0iOOW8nfmVOuwf7MCgYB9va4eDR72XuMWZwVo6uOTTwfBQ9oXHxk/ElhymfZ0mbrd8u2xWQS7z1UgbprDaXo8/tlOn1W+yxIOwvKmft1nQxvosHDW3KnCKva4Xp5G9rtndloa2ju8NDuQtBcJnm1hf5lkvSclHsiik6nYoutTTs9+/El0A0Ya8uGT4Vnw+wKBgDq6yliV5g56J3+gHB4w8yQSoIx4AjHoGkYbaVNiCNLfH02VVIGINnlBk+6xurHUwBg68cAsMSAPWqky3BMvhpAAoyPDBycrWEYKHvKvVsH5R0JRDymVJ3UHJVzCp49+CHIoOElnR+IueVluljtxTrB4JgJj0NOLKOHiTNHW6emJ
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWCeSDwgmdmLMweWKf1avCqaBYuzEo5GpMGa8MBBskBmen
|
|
||||||
address: 127.0.0.1:4531
|
|
||||||
signingKey: N8fkrWmuf1wVxL72XE4Di8pSyTaQpev/9NV4eznVcfoqB9Z+urz0kg1NKJjWisC/nUGdJP9EB5ZhgPyuQfqIvw==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAx9vwNRbEUtOuJ+UxXsvepKC1VY76RNv+SnnUIQE2/fXo/1iUEevydpWWD+V4n0DjxMsCViOv/kIOuXArIntFqr5xyRdIFE1nbiSW20IppRZO2Vw2fZwN+5DOl1Z3MfiZsqD2dbdtVLuUP9On1lqPWgW/ZHzweCcVMz2ZZ/txubSBE889bbSoZcNlgXS0fJSaw/6XApgtL++sZBqxwp2lkf918ZM3SFuAVHYU56tAOnZrCbyHcbDk4OOJ1q7NzrxWg71S02yqesuDSjIW6BzIXbDVjS2yvhKRJrrKXSIYepIczPwHPPCs7/pCPE7XQ6sYB9d8BL9/U+doLTJToAhHwwIDAQABAoIBAEZwU9bCMWtnw8e31ZCtlci8A20mOTqvto4VJhiDzxfu5bGpTHaMjCYTTpJHtB2cxyoCys4FQfAA5COjTvCWNdWZzYysMfFF3qBJMQoR5Y+TrzKYd3QJ3ju9q7JW/SeVkMYOSQ7wGQ52FifwtwSrYj6+K9iE2FPgom4u1bR6QHjMcAf9+eDJMUJk6Jg62SATPmiiN3b3OktNSsqvAf06I2K3ob1xIai0aTVcNsEoLbdDTejgFkkU3BHIzY9IXYkfipHV9+51cpRFb8q/Hl4boolgSPUSfe+pC11sm56QZZ7Gt0CF2ejhWyJKiyV50B1enKeeVN50KIMdtQn3VpTN65ECgYEA4wiKX/72Ca9wld+moywqexXNuh0a0gS/cWX4gFRv27jUScR7KTDM2jSPUxUK7F/hONOBBevfA7DMxsNNoPHoK9U2iwCO5fI9n1oWrUUjq9srJvrvsz2n2RmQ2deqmosLs0Gbb/I13+qEkunS7pfIIdul0LFE28PK5BhCDRdOUe8CgYEA4VvSWswkXQP4eNDTe78+GItQ78TluU26b+HOnkPRQlA2lUyxkUZT3VJQcgIptJJ20K13NZypJazJm6QELZPd/WcUAWKZqTSQxXUBwPVuoW5Aw0glXCfUOEG+LU+Ue8tvNCdqrAJopuYkYniT1LsQAOYMbJvL9PGkJosJfq4X620CgYARmgLoaGL440IuTHWl5vGwM0OM716586ZIC2jVwjYd6dmDkpkd22u2aybFgTckllZmyncRV3Ul2xo1OsUU+kxOwawF4NgzWbGPXjOt4VNfqpFQ51mYIuqVeVbynLbcXnVcw3RinHuyzYLTxQ8WcmwQu+/CG0xEYYykXIEadLkcvwKBgQCB5RovicFf99ztTnjHuCjDnvGs8lHzaDERMheVM8PXNELx9X3YHbBTPpHt1P9S/KUNjR7MQRtiAuFGG9joqHVpDVQDpGCrngfgOJwlK5Jz7AfaR6h5IN/6+TH0Dg2o+U6Ewj+DG/RUVw0b0SJsmNIVooQAyiBadDnImZWEdjaFVQKBgDnrnvtTMZFvJofnDNSQfOsDru5Mc9c/WRfegq58ocf8XaMMJyFCZGw90TLgQgWkxDCjQ4qnigFRWRCJ3sWB9LS8uFW5Gif0GtP6foL9rWlsQpCUqVApJRnVFFqW5f5FC4MZHtDTlZUk5lDQuvZjvQjJ+3vmusxEUIP0IS74Gr5+
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWGqsXf6No926wTb2eZdauqDcEkoAdKCeYkNzT6yrL3YDE
|
|
||||||
address: 127.0.0.1:4532
|
|
||||||
signingKey: fSLDcrMD0v+yzQwHG+KWdCkuZ5HPvx3vIb+5MecREc5oZJZfrN9P2z8gBU8HqZH/noB4aJRjXRVZsy4M5jPcwQ==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtM7k4K2spm+GZa13SkRbDuFpPVAdPmR1+aN8IAtmSAISxw2vb4ET47Ck8vDfNtQ9rAvoAn2c3GxJb5Sb0pL9rofeIYYN/qS08zFVP2+FRM5CfuBbfVbwMZ2WvBJD02LzDrHRm0blc8JZDs3xFi5o+mWfeM2SZXVCJHFSNS+v1TRgVfQzu0uKlTD00CLPNz+uzDG6VntlzzEzkF4jVRA59BmkzqAI2ZgtB0cG5ztMnUhnZCX8I0b9CCb0UHjq9j97Xuot/hMAEGVQhNY3iyJx5gAR0t5PipgQZz5j0EXBGPy9T2+VA1QFLHVsUDmd2iV5fmTZziOWn7988Co+ZVMB4wIDAQABAoIBADbQ5ukLHmXTN/7JiXn1oVmwkzRofoU09eN6Yh5g9mBsaH76si5vBrWoD0osJrA7xnrLnUpsBMt69QSkHF3J/KkWPg0R1FpYWxfD5CF4UQIcOmK26GXmnqmcKl/YdcG3pRLWbELUSqo+yLtJSoc8CM2pU6DPSkwCMcxUouTHEVrkpL+Ic6RNGVFjX7E/HjfX9U/BKH0bzwj9CEPQEm9bqc3Zq+EmcE/CHXfRnHdG1cSp65qNHDfyEBjudR4ddItzwpmxLsW6+2Ywlg2pG/vfvRkGvwtAySkVs05J0vrpwSJlPy0NvKAbHAnmNBnmRH4E/myXf5MFcl/nz55J+yJs6QECgYEA1b6fp4FeIBfhvrRseLJeAepZhvmXkRegT61No5632SpcHymz3WnO+EsrL5O6+Ldpa8Gv/LmiVBQjvQeTvx97kINXKPLxmvdxRo+i7YUCAec8AZH7WEkxa0vvi3FLVoZZ8/P5fjvUscwxBeOvwhXnyXsFB9pJduYu6wzuMJe7HmMCgYEA2I1k0YjcTCqOk2Vp1lvHLtnMcmpm4FDMl9uws0HX4UO8i9tXlLZmWqDvPpvhxZVY+1hXOEid67712q1fiei440AGGNxc/xbq8Htw1GBzKyTd9dCQCVwWGX3VUO8EKAKVXdVIyqW+YUqD5PXUcPA41ll+nJdx5Z/liSNJvpxCJoECgYBv2P5GcuXEOXsBhfw09HFI407R2I29ePWEfBVih02BMC9ghzv9or6RIxSIIu/18lQR9RqYTrNo99jzs6FWo6zPJEtZvDc9djoqSENjsvQn9s5pq/AwdKyNjwDcoP5hWpB7nbFyovBb0ZPdlxWDpF7UCbHKOCm1NCJdETka6GscLQKBgQCGh8CcU5PYVY/hjd0kaDvjpTbX1bY3oLqZlMe/dSYyMayOjiNopbAMmXJHyPuHjfKLoyP8OVCyRh3iTlbODB/gPcQL6cp0Rr6Jy4YayhiCMxMZRQpWZjjseTnuX66LVJ+KfZgNHM6bDnnF4dqqlvIYZ9y6V3NQnfcxLRUBL34BAQKBgElDMZD0rP/u6Xch33udIlzdai30QUNWS9MgSrPBz1s8+u1e0g3UnbfCH7e5q0ofSmd+Ot21i03cLgUgJAFmoVmoJ794aveBo/bPbDrlbolxOUX4dFODvvOKzCcUHeOJzc9JE/Ci3LuHyEcqv49uRIe4BFc8c/ssDpj9h7Cyx+qq
|
|
||||||
isConsensus: true
|
|
||||||
space:
|
space:
|
||||||
gcTTL: 60
|
gcTTL: 60
|
||||||
syncPeriod: 10
|
syncPeriod: 10
|
||||||
|
|||||||
@ -5,39 +5,24 @@ grpcServer:
|
|||||||
- 127.0.0.1:4432
|
- 127.0.0.1:4432
|
||||||
tls: false
|
tls: false
|
||||||
account:
|
account:
|
||||||
peerId: 12D3KooWHgeiz7EyY59t5fEZnkdg2gJxk3YvJmxpVibEcX2EtUcp
|
peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
signingKey: Tr1OaCpnYVkdeuyoBHAETn3DHWbQZELK2x5xuvd5301045GYTnQdWWT/05UB61dmu1NcY4yznm90baj36GrgUQ==
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA6FzTxWImBPJL+dhVbCUWqcuxBmbR7npbgHNOTJFh38InqxEkGwrulenCyy7bewIQXLMfzxroxm17GpWWV3hMcAzQUOojUSylJPguhrWOOtsJyxxDXyG7MEleaFX51MF+SNEo9ivBYbbwJiFrGv9tGW6D4dGSMl1Xf8yKyKWCJVBah0Pzc57I8e93qOZjaCHRmsgC7DdzD8FyIPnAuxYxNs8iSaYPP/UjcZT/SA+Ldu0vyNxdnHCSs/+3FwbmPyhYrn+uBOUUidfzraVn9ra/xtcCZQXbf4fhJ6iwfp0wJoaDU5akN40910XGQqbF6FLfqZZx220vIcJkHc3McbtiaQIDAQABAoIBAQDjTLMIOduxKQgzTnE5igpibNQty/T+UQkjXSgx9GGGzlmZmPn1zjrXwUUBF0QyTzGMTNkH8m3UdZJfzga0aAR188Lv9Co6JO8je/efZQjOACjTXEF3VPrU4GCOtdPfUKxlNN3Z+bGBEcBXvIcWcNjbcOVnyGc4B2Eprf/xCR6Hufa289Awnf1ixe33VdlBMsuua7qc+gydRF9BNpvTop7n4bGkrPJkpuNp1063QEh6Gi9Za5gM+bd573FsYMhHdECcSWS1ogtTTNsVyLPo+x/Naj1pC3UTmAFXyiseeVJ82ibMCOBywr13I0WlknNoxGevU/een4sxX4K3CFH0YGZRAoGBAPVz2qhTDSplq0EVnUVEINfvNTEDLgUMBbdrwpO6FeMR/QBohGB+Yzoen4rBNqnLOOSsetaWYN1u2XgyA9RyL6wnO7hOhlpgY9m5+CCKOwKhPwIBGOOsaFwKLzwDcACK8rg5S/EGDRYCT2SfKv2bSdyLxVt4bXjvMZBQ0lt86R8tAoGBAPJY+Yb5vwiyMlQk16spB/KoQ/hZmjuWUt6tIDf/B9/LM/vMfguJJRq+tmBa2JxvYmUj3lIt7Sg5RiFECIiZ9MW3H7rCu+SHRN5HaDjKOkFX8qTTPJJu5LyBcCnHHxQBi4t5bVTAbKfpBXTi7lr5aAhUIztUVc9Poyz9mm410TWtAoGBAPCaOnLZxoQS2UaZW2r0l4VUNL3wsgG8gTYFadzJgn7tuSXXTjwQaFAmiJnJQD48uW5fLKKBEj69VGugC2UK8XQ9mSrXvpeE+RwKUhIDrkirq0nZrX4wGLRwP1ECxZ2ilr7DW4/OMLGsXgryg3/J4yNP14wMhrMPNXST5UBNN2+ZAoGAcfb7aMjbWBiMaFtm/DtwXGFajVh9mhXn5IVfiFWq+0fQq1GP2Jbm1vvmQcuW34HVsKA8dULZqre8TfpzVOGpZKzoA+h9eUtPTIQh88rNuFrGZVJcwrPZZvgrqcnUyJCtcappiphuwEtpYH0y/58XmAsRAl53d+UIZCjiTX+LYYUCgYBWuUASFeKBWp8/jRO6xgcKT7DErnMZr3TRYkduH9miIlqhx4NH+K/hkgkIFk77ov1swj2XrPL/rMMtWDRsn8fvwhRYkU25FCNAdmSg3G2iaW3Pd99d/fsdJtE+VjVQv58R6nxp5aiVH2rX9l/tspdUsupoYdFDDHYDkL+lIu2ZIA==
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
apiServer:
|
apiServer:
|
||||||
port: "8082"
|
port: "8082"
|
||||||
nodes:
|
nodes:
|
||||||
- peerId: 12D3KooWRqbgXAdsP9zzBeKv6qjqmW9qfo7TbQfTi4eYYCcpFBwT
|
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz
|
||||||
address: 127.0.0.1:4430
|
address: 127.0.0.1:4430
|
||||||
signingKey: 4JPubXZ2chIF3SFYiEGHvdTs7/B+IbrdUCHWYkNH/E7uC9nsnBle8q/FaG/7b6pNKjXukTGaXnDrSixZw343/g==
|
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA3xGRPt9EXpes27462scV4Wm71KUZ/mqf6re/x8LW+ZPvuuq1R5bj2AhUYj7oamVvqnpO8N3UxOSQB0N3eKtmi/I4M2OdLhkZHKBdGi/XG+eGRcCaM5kGBdot52dgFkqXunnU1h2khCk8XeWrJL2mnm9eSgSzvxExkQQfx3nCwYLq/ZmgGT+wBHZECxIlzxjpcgGjnCCIthb409YUitF/tnkwkcM9KBZJFJyJxTAmPaISrcpb30xNfxjuI4khst/s55XYsptyqRLzWMvr3fKUg2qN+GUCv4uAEQYLOGde0nVLq7zqofkH3jqXta13q1zi5OBiW75dCXmjtCtdBeMcNwIDAQABAoIBABV/b+wLQF+NZo9W6f0jqqwqsHtx3etzAy5vvv/VezpaU4REEmxv0k2Dn/5H6cY3OGfJmcoE1viSvn60tdLfUeay1U++jetfZ9gmbFKVwbliusIGKdZHLRlrSXk/sTb0wWKrUyO/f5dtEfBKrg/AZ0plmUSw51HGqmw7ZYSn62kSstB3VKEiM0nWQAh2D9R4APMaaBEo3XPJ+l706T+VPK07rD9oBdQmEkhA2Dks1jYzWVGeMY1aNhndPPVKy34BcYJa+z8X41bwUDsE4mNFId2nPVofgaGJiby4A/3adlvLzosBC5kYxj/V9icNH/iEYtwVV2rIjPLXgt54k1L8SQECgYEA5OWewIuAluIIt7RnClmpd6LPQAc24NsfaC+edGj63b1m9VPV1Vyve/+Mp642FUbp1zmFeTfTBOg+577rnrlI2Arfy1vRrHrSRFLEXfyGA6SSpssvDrHmJtJBh/H3kUgLeqsQlX+ov8mtZEelUF2oWSbmP9k5JaoXoN67gGVrAiECgYEA+XtHB2sZOWV8jOCN6ZU4GfjjymNtCRsH2jWs1fBJ5Sfpei9TK/ZemJ7n+vnANiFLycNoQ00EFlOYaTBCCig+vc6/jX+Ecmh4fUb/ZAuYx+GOA1TltcD+OWBrUEqNdrXwICtUWo8/m+As+ntbCmDSZRUIGRny/N549sGEipufA1cCgYEAsA6NlLu4JFWnLuVre+KLHqHzluP1qe3gslouHovAqV1NG9Vn27x2nYFpxm+Q2by5j/mGWD4/6L5Z5BZNVMBe7w0uJVRyaZ/uqu6ea0wYKCUlR3VwtHTQ+XsvPEk4il5Htgptrw+J1DpjS4Zv+OiQ3EG3R9Tkx7uUgP/QaGmZbQECgYAT2xvsGzoGt20SSU0CKj4s0wJOOVuUPfKCC4OWA2neMy8B6oJUHWep/fu4negOZtgBVuwVbyvEGyMmPBEFfe6AbNQSDvQbpvTwA5aP/9xJDEqhOUCPFq0lI+dmnIhlylUyOkCcdIo7fbwWs3qreMlGAkaCuO398jbubLh/z6L4QQKBgQDKUzTECIr75cLiFbUFxcseYFZEc1weYtlp3E28H0rceSD1GakQfu0osi294lLFzWbc4JfZ29F2rFnOAeZ55f4AtFh5xxoY2robre7C5pOklG5zTcHXakvqdWXPtYfi0o2dI/JBRNnS14ZDJqVmROGmMXsdm1et/qARKBI86wORUw==
|
encryptionKey: MIIEowIBAAKCAQEA5zUOQ42SFUYJyX86llYopUE4Q+RQvbCakTPd9LBKt6pBWyW3PA9sjFisxVFFwYOVwghzF8QDSRrWdkjGmRPPOSRNmNiJFGtk6wb26eihenFECdb4nJyTDZVhvayHpByCKleAl7dHLjHCIsVaaFfn5rntm47IdDSNFgZnNDrNrdS2SchXWHamcfWBJSQirdp+8kSh5RC6/J53LVa+Sff6D49BsF8VsevcjvFcdlpxG6GKhr6kzvnEwCCk8DIqjpF3geUVj/QbT9tGa12bAgDQuckW4DavIN1zT7BAUbZPcbFZ9Bd2bbKzXDFNt2mRXafDPL07KhnXSZ2YAxHf5M4s7QIDAQABAoIBABV5aQy/Lm1JZwlPBtsFv5qxtw8fOpyTtZd88MWURixO5OkZVK6AZD2Y0ts01DzIAvXVoRL5ArEcjATKd5+qJloRVB+5JOo/m0z1BaPuFmlv8bjUPZ0WMdZWJJDgYGzOtQxHukrdHABfYL+oAuCkIYbdiAMlvNqGMwBzscw5FfdqGBRwC0bus+YD103Hhc8pN0REwLZmiOvHR6b4Agwv4ruFsqthg13EwcqDVTnS1/sZyodLZaAGBUXlqUxuFakI/9CqpPuOkDgxelTYdXbS4yhfRF4zwoBGZx1462iJs4XM8TXhDcZpTRwCChM5Qf7jvvgbi7+gYTX9B1dxg7gZUyUCgYEA/cd/NqOyx7bn0twiuMEdq8bCi5Y/GvWLrQ3pf58DPanIydGPJU5/obKZw5Tv5LWbE5rUEeC2YpFleNh01oc0xHCveIR6JNGihN8u0DZPmcx2B1lwEzdYefRJfGcYXYhm/nCpzYn3VH0TfKA6qci+KLarYaeDpUCXAihZMUZxSfcCgYEA6Tr+fSXmHIYoKcewIpwSTvcFOJ6spMRSG+mxQAFit8vUQTw2e/aTESEECo24XJ/SKVK01CSoWXrw3t9eBgziyHI3GaaZ5LaXMZLLZhmGUT5kZiTR7083h+9bHt2+MzRXpaAEEc1FNgV3T2sSl1S+oKDL1MAcR42JaQtC1P2epzsCgYBKDdD9bL9ar/DuAvbO2uuBmLpkaS94+nYLxaeBajFT6RuCaPhQdpuf37Im9GscXjImgmOn497U3ICzxtYxU7r+J7PMgzvxSosWItpSP8bypks60cp2kQvsanCXMK5XfNoxHUcvhzb5HJZ3I3p62O1EjClukadErZhjNMryKhAc+QKBgFwvpUdyI3JC1L0u4L/NUK9FlBq9HSBDOPEvfY/+/DYJquveEOsOmzK6Cg7h1W1G/pq2xiLUGnbD0VFGmLNrhHgWLRFGeK2ePkSp8Rt6G00hjC2TgCdG+HwSb8HTg8pZdgtRJEqlCCZCItaRS9fk9zQmWmrNRGBD4XxTpybo2DzhAoGBAIxRN8WZc9HYVq8t20MieKP3pp5Nrl0wj9Z9EPvC60CwQRdv/FvWzDwF5/9Kg79rvbguZgjD6FNy35BGC5sN/24awWJ/mKYosctRwZVFpogoZ0qAdOwxowfAJXLRC5Chgim8vCFFdKdrMo2a6V+MQuhrTv06QAV1sYAH5P7abfPy
|
||||||
- peerId: 12D3KooWFYTh59WMXGLDqS8EXfTjHvrS9uXrcYJuE6yDyL1hh45R
|
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y
|
||||||
address: 127.0.0.1:4431
|
address: 127.0.0.1:4431
|
||||||
signingKey: g673H1+gh/KSbRat4m+E+UBTxEmcbxNJ2ZEwdBnQKiFVExLIU7FUXhx7F7xw2QJOw4CInWK6tNZZRNAzOWcD7A==
|
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg==
|
||||||
encryptionKey: MIIEpgIBAAKCAQEAwrKCiqwW7ZGgxfG/t/GgPZ/shmbXEtZjDiZKuLugfSOedERYdsPZ4PmPZkVxo1rIoZjZOnoo7qeC5LWk1A0N33LudQF7Qg50O0QyiV5QTRxkv9IUvAeXyUR5TrxD5oRdFKuCbyDUQYaoAOYCBeqSI1ub5HdFt1fDMqgHXVW/p9kMwHEXpHM7ZaARFf5ri9/FIIodb5+IkduSK3/qBPlvt6dy2MlKlHRkzHef4q8YFKuDyzsyF7fdtjhhHk6p86JBnMaQpP+mi3e+qUxhdWEIY1s7Jo1Yal+GDQ0NtRrZp4GdlpFT7Kgp1Sm5OzSrtEQduluc0GWJFAVpolHg8e7QlQIDAQABAoIBAQCTZjIOalqxYR8mvO84g2WdQgX/erw5NrWncLYBRYsrMlw0Ccovn/bDrCw0cT6nPYPHU8Ch1PpIM+mU3S/8miV2lbySOJzoVakJdYgNF6oTtvtPfezUrarsZTqxsTZ2vp75lx8YovIO6bMnevrtH7mjqydKwEG3nGnbX/qzXsfKeeZgd4kvnjlxGTDUen12Pl0kPLcBgyckZLDJmXYtvxuK1sZTjifyHoeGVYpOOLYi3rRSEoZnVS4z/fM1sG5aUM6eA/7HaXDAe5sT0rgmPt0mu6Mo13dF3rWkP/MCqEVdBLfQLXEfqKp/9QuZ7szdsM0b0WPDXP/YXDLALLvL5/vBAoGBAOPeOrG+JyyS85//wKy+ZRZND5IdxBWoPDfItKnQJtMzOMiYcpwF0J0j3VqdulQlz4zX0Zly0iEYtFtNozVLStDn4IPrqg/vJI+vkikDrY/r1lseVFGR0euVtpRth3BybzhR9llfqK1tuR7cCg7NaxnoIkwtbZDumKDPRoXSQmAvAoGBANq76w8ZMdduxQhroE4Hs4uP5g3Yx9bDlimwGBwX0afGoO82kvgxpol4Z/3sXC7dAKoBqLTTpVDq44AkMhSXgT/CGALsebRxqc45orafe3s+rTFoQsR8eXu9pRw6TxjwATMMxZHjIkV2DeQuKIOTZcvd9E1PVmUB3VSwihje7oZ7AoGBAJGSi1S58jTbvKBetyykhdf1axkhwv9C9xV8N061F9idRI2CNtXOMTPykZsuYLcZYLrNta2eWPej3LTnqHiHnUhQmnIsv/xl/ql8tJdXLi5fsBWODrf9vGoQvw+b2YbQ1JTaZ9M49X22Nymr0REb0mw+jIq2CuUoSIGTaa5cYOMpAoGBAK6tnZUsKKqDsmP8F0PZUKAmpbDvKwAup8/Y6hgdSXfz3vfKHGqKtBVai6mzxRZDtdEOjB0EXCQXwODHhxr8tuIk7aoAEV1x3Apt6qxvBlyw+/zV52Qkh5uzIpU9V4dxu3N6Qpkzy12vXn6YAhC5eHTrZrsKndMCPy/v4Ajml5PbAoGBAKugn3Gh4BLUOW9Tvnc9UIwITp8p8+Dx9yQJugHSDzBFGuAZ1FUciCrK8SGarDCyyzY+XBKVuNZEj7D4P2+JiTKv8nweRVj0DdXYUwIsX6cWgPF5i8dm0Nl5PbsR27L+TxficuO4IQRHMz+Loho5itbSuDY9Y07PvKLKJfu7Cd9l
|
encryptionKey: MIIEogIBAAKCAQEAuJcCEM4sM5I1Aj2y0HDgR/UrKEVF1iZ1CYWv4jVOt/e1avDn7XjF9ArB7lngq7lOTxpCNeLMQXeBl1gY1SBCPeTrs+tltyAUeSOZStwP9qhjUhI9TntfW3QfVlC2lB17liGa4b2F10x9vW/0f3R7m5xgz8NyqcFOZip0Ehe9UJbNFwPr00by0D4/XptkDT44wAIDlw7lgOmXWR3RpCYAYFonYeE2HK7FFNTIOJucfJ8kbK7wLp5EZRARYfCDUFq7czFu97FIrmQfS4Fyg8ESB+R28+dJIQ6G8U1MicX4Ibf9IkufK+r2fMYPv13F33omrwSGhNIWtX9WjAQ4bjmA6wIDAQABAoIBACHuaEvMimWEd8gMrWURirjPgXpqmXbPJO52K6mqYOkCWM/qrseBTuoYXCPDU8BdVN7Hleov4ZobLLA0WoQ65NJZ1VYCbHUoKXtHJvOS1kBiHbfFcI2PsiyugOAuABHkBYbIcJ8UZpj4D5kWDlyrfdlR+p3WcKpxxUaUgTeeM4evkMg2dg1/S4psgu1SKdGYMtafKBgvxxE0R/fjfP9MRD260/ydcUT0gRE+uUu6WFm92MLV72W3hoKfNqgGnQWCTG8UJGGK3KC/c9lAvLiDygo3GJLEjhnrIGkSbbd0uHtAYD8Uc+gq3z3o5Rger4P/FyWSbJ6Vz20iYHTeYUEDkKECgYEA5KK5/Z6XQHwsEGXSSCXKvUjJ7ZOV5k3D2im0F1dTtQaOjFgwZ9SPW/k7tQfcwfZLeDSm5V98FXSAu9XgT/Zrd+/RrfbgmKLMcNVet+l2OPq1cOeKE7io7wAXlkO5CmiMXMCRVcgqaENutUSTsmadFqd2NE7/gEUjeNIQLGkSsXECgYEAzq6+HtOxhfbTEC8ZUz6Y7+CphmtYiuX7G42lwv70mg+sap7mVlZzOHNNM1p9BOVEo2K1RKNWtXMgXDbt/KakBLCab9sR4R68tS7JX281I8RK/kYOLqlVE0CahujcCJATZAsDLMCpjeN85vwqJ9Cy1errf69thZwo1QI1BvRIahsCgYAkmz1GMycqZvczJOpXLN3aEpZqGHAusJLEEltIRW4clNEr/U66wRi29B+wK3MYBxQsSdnS7cfTM5UM/gBtLRol2NrsjJOHPMGY60DAF3wbQWDdk+TSpYU+xvf/0hYFaZnXm+lpH6RSj0FhenpfXPiX0PYnB+L2qZs1VATM54HbsQKBgG9nVwkMuCpqUXfuuyrYmdzqbtYKdG5h6kj+v7Nsc3G7MwdBYQx2iqKJ27nrc2m5HpcmtGgr1qf1RyMNZJgDRnNUsdnK7kc2pybN8jMjoTQHMRj/r9NM6JN5BhHj3/4pkpohKXPs4TeewAtNLnfJkSum9Yscht82vfeaufRmpcWzAoGAfxcnMvi2EhE6uNjDENqnFH9XD2zAAeKhiQumz2ts3cSUd1QOfPMeytsBML/jdmOMQNaTbMryhWPaqTewHky8P+l/7oVbMTTFnaaaZRZCSOSXe+2R3mJkRQzE+DkVhgfpEku/BVGRHRvltM+ehk3m64j5vHWC97cP52qZ0bkxKHo=
|
||||||
- peerId: 12D3KooWHgeiz7EyY59t5fEZnkdg2gJxk3YvJmxpVibEcX2EtUcp
|
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd
|
||||||
address: 127.0.0.1:4432
|
address: 127.0.0.1:4432
|
||||||
signingKey: Tr1OaCpnYVkdeuyoBHAETn3DHWbQZELK2x5xuvd5301045GYTnQdWWT/05UB61dmu1NcY4yznm90baj36GrgUQ==
|
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA==
|
||||||
encryptionKey: MIIEpAIBAAKCAQEA6FzTxWImBPJL+dhVbCUWqcuxBmbR7npbgHNOTJFh38InqxEkGwrulenCyy7bewIQXLMfzxroxm17GpWWV3hMcAzQUOojUSylJPguhrWOOtsJyxxDXyG7MEleaFX51MF+SNEo9ivBYbbwJiFrGv9tGW6D4dGSMl1Xf8yKyKWCJVBah0Pzc57I8e93qOZjaCHRmsgC7DdzD8FyIPnAuxYxNs8iSaYPP/UjcZT/SA+Ldu0vyNxdnHCSs/+3FwbmPyhYrn+uBOUUidfzraVn9ra/xtcCZQXbf4fhJ6iwfp0wJoaDU5akN40910XGQqbF6FLfqZZx220vIcJkHc3McbtiaQIDAQABAoIBAQDjTLMIOduxKQgzTnE5igpibNQty/T+UQkjXSgx9GGGzlmZmPn1zjrXwUUBF0QyTzGMTNkH8m3UdZJfzga0aAR188Lv9Co6JO8je/efZQjOACjTXEF3VPrU4GCOtdPfUKxlNN3Z+bGBEcBXvIcWcNjbcOVnyGc4B2Eprf/xCR6Hufa289Awnf1ixe33VdlBMsuua7qc+gydRF9BNpvTop7n4bGkrPJkpuNp1063QEh6Gi9Za5gM+bd573FsYMhHdECcSWS1ogtTTNsVyLPo+x/Naj1pC3UTmAFXyiseeVJ82ibMCOBywr13I0WlknNoxGevU/een4sxX4K3CFH0YGZRAoGBAPVz2qhTDSplq0EVnUVEINfvNTEDLgUMBbdrwpO6FeMR/QBohGB+Yzoen4rBNqnLOOSsetaWYN1u2XgyA9RyL6wnO7hOhlpgY9m5+CCKOwKhPwIBGOOsaFwKLzwDcACK8rg5S/EGDRYCT2SfKv2bSdyLxVt4bXjvMZBQ0lt86R8tAoGBAPJY+Yb5vwiyMlQk16spB/KoQ/hZmjuWUt6tIDf/B9/LM/vMfguJJRq+tmBa2JxvYmUj3lIt7Sg5RiFECIiZ9MW3H7rCu+SHRN5HaDjKOkFX8qTTPJJu5LyBcCnHHxQBi4t5bVTAbKfpBXTi7lr5aAhUIztUVc9Poyz9mm410TWtAoGBAPCaOnLZxoQS2UaZW2r0l4VUNL3wsgG8gTYFadzJgn7tuSXXTjwQaFAmiJnJQD48uW5fLKKBEj69VGugC2UK8XQ9mSrXvpeE+RwKUhIDrkirq0nZrX4wGLRwP1ECxZ2ilr7DW4/OMLGsXgryg3/J4yNP14wMhrMPNXST5UBNN2+ZAoGAcfb7aMjbWBiMaFtm/DtwXGFajVh9mhXn5IVfiFWq+0fQq1GP2Jbm1vvmQcuW34HVsKA8dULZqre8TfpzVOGpZKzoA+h9eUtPTIQh88rNuFrGZVJcwrPZZvgrqcnUyJCtcappiphuwEtpYH0y/58XmAsRAl53d+UIZCjiTX+LYYUCgYBWuUASFeKBWp8/jRO6xgcKT7DErnMZr3TRYkduH9miIlqhx4NH+K/hkgkIFk77ov1swj2XrPL/rMMtWDRsn8fvwhRYkU25FCNAdmSg3G2iaW3Pd99d/fsdJtE+VjVQv58R6nxp5aiVH2rX9l/tspdUsupoYdFDDHYDkL+lIu2ZIA==
|
encryptionKey: MIIEpAIBAAKCAQEA2T4/6T5etB9W7qzJ1sNfWFdOTa2koXKcQkaLBUTervApLPZtaVsbNtyVFtqqdsck1qpu+AVif19EFlYqSRtn/dxEN5/2myqVA6lZMm0Bd9mWpfoDQx20KAYwWBwzKSH1EQiTte0bw1zf0RpztxQ3nCOLCU4Y6x2lfk6Ea2XEayPxx0FDmeY3JSqUDOwx33Sz8Imx8R7+Dfjl6Og3DEqGxXoPfZ6hj9LynqNswjRIdmMZPsuEHguKXMbp+cncErGWcyzH417XYSDPoRn/3awpLfQ9F+KSjAe5cUltC7M4veSZW+t3VcJypvfRlU4ayTZMuvMHPlMcl/0jP5w0Q2+2pQIDAQABAoIBAGMvmrqBcXfHv0cluNnHRebtpaCtoTbdPx67WonDUfCJUiNnN7kckaZQu/k9SQsGDXm9QwEWZExHUKzqFlBepPIw+Sx0aoGZxYNwdHsjbcIspC2PoqGoFDMZ8ESqS2mCSYPHaLltUnm2E7JC44Y5QtKVH8vVzma6mG68ppTqV+2aGfGiPDq8cAYeH9/8Ys8/S28IwCp/M7lnXZhJ38bHD3YyPpcgbyGI/Zr5xaPd0hqHH08Z+S9V7QPJUGY0Y21s99DhkUGctb4B17d0/3Nzk/iWY1rp7A/kbdBeWonsHrTc6OnmbdiOcjC8seOIKMJ/WE3JznqnI1oydFb/dp6raNkCgYEA+pn1akGIKnVP0oFh5PZfUpuZtVV9u9xccIXyeFmCAXyFuUz1KYbfwwqZnm9r6kHAO+aBtRtVsCVle5oVWNQq1pdv117hPhRnVrDtvL80z50a5L9gEVu4Yz24Q3vs3RglcVpafSaRuyPbiYHMmQ4Ly+9nbwEbOVDbzK5A3Wrny2cCgYEA3exS3aG7+7mbSnNTYkkTgl7goLXZgEST/0EM2CvayxZ2QUS94Vq5HjGRpWnni3YttLiYlgCLe3CqeiIh6E3n6b9sory8Oy6lik/elj28kcZIuNvPU0xVcqrmGCg/KEnYkXjsGKsBDk6SV9nKH7880oIe0Rh3gc0hHHIl0Z4CshMCgYBifXHLkffPIA4AIKN11jJ+h/LwJqpk0+Vsv+gczqjepq7ztcBA0uZMhHT9pLLX/YFsyVo+8IBL21a4LkWnhLNVZW0qSvrhaCl5E85LuSYrVoaEUoaSK+ca8d3if+kGt/+3PhiESU1LLHuS3nWnzbJrMysGoHuvmgzYs7+AhgyVjwKBgQCoVgrFc1lUqIXTA4fMlgHmcnGRdl91nI9mn8FOeHWOd4tcFvixaE/jR1ZjUuIAN7ST0TJtFhy3lc66tgliXTX9aObOyrs9aTTIpa0B6fKP4QhosNOjK9PlFx1SVbUSqnFMZ50vWQeEArWfTeS0ECviwjD+CsEcBK2JFkz5pBIHYQKBgQD3zcYdYwvGkolLXNN3vbgTVnbNe2YMUBwgp5i1XGzAiG8XpwKTi4vDFIYgCZAG5wsyqUPdTOY2wyLjHwGdUfl7P3tCsHVzVh/xvuSl3nzW3OdCniKaBBdtZS6+s25Ijzdwiwnp21NWE6XU2BptIwTMHrKOc7BpZykgHsORMtptsQ==
|
||||||
- peerId: 12D3KooWJpE9AtG4RX4Dwm4vhrCGqiUhKj6Mvbqj2V4rV4diyksT
|
|
||||||
address: 127.0.0.1:4530
|
|
||||||
signingKey: 6tA9VizrAMtsZlzBXXnsg+LzwSwBLU7oiVP1qOHN4PaFsBslV0nt2aKBXfcfxp17V/bvydNfyYbGu50F6spLCg==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtsYet7J4bNo9zSPFZVFkkInUoAW7os8PtZH6qMUEOKcLAi1PDbkBBCmzHdfuzik8H8DgQl36/0gCqRPM6nhQlbF59mV7brI8/kH3Eiw0rxqWAe0+C6CzDyEqtKC7pJyC3FJe0MZRRtDXiDYlVurHrsW22fA03rJY5++eW6bXiqL7WB44zxMrztkvPljlhDf2XTAcrZWI10oXKjSZMW051Figbhdl06R1ZiW1F1LmUEd3ufiYoevpq8jAHWIToTZrYNX0sfrdNaf/CPCq9ZDSqISf8CZ/bE1VxYRPEnjmX1hZQ132S1KCEQwpBWxpcvePonEMPGp+5F7h4k+46f16vQIDAQABAoIBAEa8np7Rv7HBNTHzqi3wNk+KSHQ2Q8xa/uVyveQbe+rBG42YI4RYGYCW8u+V5qJ7av2PFDwbS00JfZ4aP7BvKCEHMwCdfgv1h42P0iOCYFF0pKHSQ7UUWLh+SZzmqDipKixC5NdAKaySnxfkfMcKzoVhl8b5JD0cITSClHM8Oyc4DR5DeB9MlgrVqV/fcdzR10J6TeEPyJjs7CF+Y4OFUEf8FnNxfx5btWm8dIxRMiFUqdI1SVHmOJo0wO2z36RKZ2f8eHApafpJ/1MWccCCSB34Kry4WjDLn8yfOZ5GavXKDVKnE2won5ZhpZGTaLVHLR8QzvkzuBHDk1j1kSi2RjECgYEAzwjnJc5F8XdOkNNPKpftnUVlijhEx0lSknL/j1wIE7bdqbGvIhW+OlIP3bc6O5h0QGSoB71cAiurzro9rsZnSZ4qqjyeGh55j8I4RoZHGDu8BoUOXzrIL1nw3JWxrsNxu5hV9bcYAOJDG9BOcm7F9g00+f+p2zR7BvZMYm3d0vsCgYEA4gBSbChHTMHs15wppaTqV5iQEbfAU/oweRBnflQTHVdezMDt85BpZv0ik2vTuhMJuiaISMvb5l2fHI+LIKoZgCBfymQ50Yv6dZqOMeY5XwUQiQ8DtVtoetYBwwPIS3hSntTu/a4Q9tZbmmWYG6rZ7X58UrtVHY5DfFMS8MOrO6cCgYEAgDkGV57KKMN4cC+/DyUrL8VEHve8eSSLNFJuvs4D3pnZ7Pgz/Es1Fo+ubeXF9hT0otD0VF7NtjZv4Mft3enZHHoN+IM0c/690PA7xEnzjCmqyOrtPMN+Kf1tNGCtvAwly0aMrnKoNhvr7jTz8OF0T3BciBz0iOOW8nfmVOuwf7MCgYB9va4eDR72XuMWZwVo6uOTTwfBQ9oXHxk/ElhymfZ0mbrd8u2xWQS7z1UgbprDaXo8/tlOn1W+yxIOwvKmft1nQxvosHDW3KnCKva4Xp5G9rtndloa2ju8NDuQtBcJnm1hf5lkvSclHsiik6nYoutTTs9+/El0A0Ya8uGT4Vnw+wKBgDq6yliV5g56J3+gHB4w8yQSoIx4AjHoGkYbaVNiCNLfH02VVIGINnlBk+6xurHUwBg68cAsMSAPWqky3BMvhpAAoyPDBycrWEYKHvKvVsH5R0JRDymVJ3UHJVzCp49+CHIoOElnR+IueVluljtxTrB4JgJj0NOLKOHiTNHW6emJ
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWCeSDwgmdmLMweWKf1avCqaBYuzEo5GpMGa8MBBskBmen
|
|
||||||
address: 127.0.0.1:4531
|
|
||||||
signingKey: N8fkrWmuf1wVxL72XE4Di8pSyTaQpev/9NV4eznVcfoqB9Z+urz0kg1NKJjWisC/nUGdJP9EB5ZhgPyuQfqIvw==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAx9vwNRbEUtOuJ+UxXsvepKC1VY76RNv+SnnUIQE2/fXo/1iUEevydpWWD+V4n0DjxMsCViOv/kIOuXArIntFqr5xyRdIFE1nbiSW20IppRZO2Vw2fZwN+5DOl1Z3MfiZsqD2dbdtVLuUP9On1lqPWgW/ZHzweCcVMz2ZZ/txubSBE889bbSoZcNlgXS0fJSaw/6XApgtL++sZBqxwp2lkf918ZM3SFuAVHYU56tAOnZrCbyHcbDk4OOJ1q7NzrxWg71S02yqesuDSjIW6BzIXbDVjS2yvhKRJrrKXSIYepIczPwHPPCs7/pCPE7XQ6sYB9d8BL9/U+doLTJToAhHwwIDAQABAoIBAEZwU9bCMWtnw8e31ZCtlci8A20mOTqvto4VJhiDzxfu5bGpTHaMjCYTTpJHtB2cxyoCys4FQfAA5COjTvCWNdWZzYysMfFF3qBJMQoR5Y+TrzKYd3QJ3ju9q7JW/SeVkMYOSQ7wGQ52FifwtwSrYj6+K9iE2FPgom4u1bR6QHjMcAf9+eDJMUJk6Jg62SATPmiiN3b3OktNSsqvAf06I2K3ob1xIai0aTVcNsEoLbdDTejgFkkU3BHIzY9IXYkfipHV9+51cpRFb8q/Hl4boolgSPUSfe+pC11sm56QZZ7Gt0CF2ejhWyJKiyV50B1enKeeVN50KIMdtQn3VpTN65ECgYEA4wiKX/72Ca9wld+moywqexXNuh0a0gS/cWX4gFRv27jUScR7KTDM2jSPUxUK7F/hONOBBevfA7DMxsNNoPHoK9U2iwCO5fI9n1oWrUUjq9srJvrvsz2n2RmQ2deqmosLs0Gbb/I13+qEkunS7pfIIdul0LFE28PK5BhCDRdOUe8CgYEA4VvSWswkXQP4eNDTe78+GItQ78TluU26b+HOnkPRQlA2lUyxkUZT3VJQcgIptJJ20K13NZypJazJm6QELZPd/WcUAWKZqTSQxXUBwPVuoW5Aw0glXCfUOEG+LU+Ue8tvNCdqrAJopuYkYniT1LsQAOYMbJvL9PGkJosJfq4X620CgYARmgLoaGL440IuTHWl5vGwM0OM716586ZIC2jVwjYd6dmDkpkd22u2aybFgTckllZmyncRV3Ul2xo1OsUU+kxOwawF4NgzWbGPXjOt4VNfqpFQ51mYIuqVeVbynLbcXnVcw3RinHuyzYLTxQ8WcmwQu+/CG0xEYYykXIEadLkcvwKBgQCB5RovicFf99ztTnjHuCjDnvGs8lHzaDERMheVM8PXNELx9X3YHbBTPpHt1P9S/KUNjR7MQRtiAuFGG9joqHVpDVQDpGCrngfgOJwlK5Jz7AfaR6h5IN/6+TH0Dg2o+U6Ewj+DG/RUVw0b0SJsmNIVooQAyiBadDnImZWEdjaFVQKBgDnrnvtTMZFvJofnDNSQfOsDru5Mc9c/WRfegq58ocf8XaMMJyFCZGw90TLgQgWkxDCjQ4qnigFRWRCJ3sWB9LS8uFW5Gif0GtP6foL9rWlsQpCUqVApJRnVFFqW5f5FC4MZHtDTlZUk5lDQuvZjvQjJ+3vmusxEUIP0IS74Gr5+
|
|
||||||
isConsensus: true
|
|
||||||
- peerId: 12D3KooWGqsXf6No926wTb2eZdauqDcEkoAdKCeYkNzT6yrL3YDE
|
|
||||||
address: 127.0.0.1:4532
|
|
||||||
signingKey: fSLDcrMD0v+yzQwHG+KWdCkuZ5HPvx3vIb+5MecREc5oZJZfrN9P2z8gBU8HqZH/noB4aJRjXRVZsy4M5jPcwQ==
|
|
||||||
encryptionKey: MIIEowIBAAKCAQEAtM7k4K2spm+GZa13SkRbDuFpPVAdPmR1+aN8IAtmSAISxw2vb4ET47Ck8vDfNtQ9rAvoAn2c3GxJb5Sb0pL9rofeIYYN/qS08zFVP2+FRM5CfuBbfVbwMZ2WvBJD02LzDrHRm0blc8JZDs3xFi5o+mWfeM2SZXVCJHFSNS+v1TRgVfQzu0uKlTD00CLPNz+uzDG6VntlzzEzkF4jVRA59BmkzqAI2ZgtB0cG5ztMnUhnZCX8I0b9CCb0UHjq9j97Xuot/hMAEGVQhNY3iyJx5gAR0t5PipgQZz5j0EXBGPy9T2+VA1QFLHVsUDmd2iV5fmTZziOWn7988Co+ZVMB4wIDAQABAoIBADbQ5ukLHmXTN/7JiXn1oVmwkzRofoU09eN6Yh5g9mBsaH76si5vBrWoD0osJrA7xnrLnUpsBMt69QSkHF3J/KkWPg0R1FpYWxfD5CF4UQIcOmK26GXmnqmcKl/YdcG3pRLWbELUSqo+yLtJSoc8CM2pU6DPSkwCMcxUouTHEVrkpL+Ic6RNGVFjX7E/HjfX9U/BKH0bzwj9CEPQEm9bqc3Zq+EmcE/CHXfRnHdG1cSp65qNHDfyEBjudR4ddItzwpmxLsW6+2Ywlg2pG/vfvRkGvwtAySkVs05J0vrpwSJlPy0NvKAbHAnmNBnmRH4E/myXf5MFcl/nz55J+yJs6QECgYEA1b6fp4FeIBfhvrRseLJeAepZhvmXkRegT61No5632SpcHymz3WnO+EsrL5O6+Ldpa8Gv/LmiVBQjvQeTvx97kINXKPLxmvdxRo+i7YUCAec8AZH7WEkxa0vvi3FLVoZZ8/P5fjvUscwxBeOvwhXnyXsFB9pJduYu6wzuMJe7HmMCgYEA2I1k0YjcTCqOk2Vp1lvHLtnMcmpm4FDMl9uws0HX4UO8i9tXlLZmWqDvPpvhxZVY+1hXOEid67712q1fiei440AGGNxc/xbq8Htw1GBzKyTd9dCQCVwWGX3VUO8EKAKVXdVIyqW+YUqD5PXUcPA41ll+nJdx5Z/liSNJvpxCJoECgYBv2P5GcuXEOXsBhfw09HFI407R2I29ePWEfBVih02BMC9ghzv9or6RIxSIIu/18lQR9RqYTrNo99jzs6FWo6zPJEtZvDc9djoqSENjsvQn9s5pq/AwdKyNjwDcoP5hWpB7nbFyovBb0ZPdlxWDpF7UCbHKOCm1NCJdETka6GscLQKBgQCGh8CcU5PYVY/hjd0kaDvjpTbX1bY3oLqZlMe/dSYyMayOjiNopbAMmXJHyPuHjfKLoyP8OVCyRh3iTlbODB/gPcQL6cp0Rr6Jy4YayhiCMxMZRQpWZjjseTnuX66LVJ+KfZgNHM6bDnnF4dqqlvIYZ9y6V3NQnfcxLRUBL34BAQKBgElDMZD0rP/u6Xch33udIlzdai30QUNWS9MgSrPBz1s8+u1e0g3UnbfCH7e5q0ofSmd+Ot21i03cLgUgJAFmoVmoJ794aveBo/bPbDrlbolxOUX4dFODvvOKzCcUHeOJzc9JE/Ci3LuHyEcqv49uRIe4BFc8c/ssDpj9h7Cyx+qq
|
|
||||||
isConsensus: true
|
|
||||||
space:
|
space:
|
||||||
gcTTL: 60
|
gcTTL: 60
|
||||||
syncPeriod: 10
|
syncPeriod: 10
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/metric"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/dialer"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/dialer"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server"
|
||||||
@ -91,6 +92,7 @@ func main() {
|
|||||||
|
|
||||||
func Bootstrap(a *app.App) {
|
func Bootstrap(a *app.App) {
|
||||||
a.Register(account.New()).
|
a.Register(account.New()).
|
||||||
|
Register(metric.New()).
|
||||||
Register(storage.New()).
|
Register(storage.New()).
|
||||||
Register(nodecache.New(200)).
|
Register(nodecache.New(200)).
|
||||||
Register(nodeconf.New()).
|
Register(nodeconf.New()).
|
||||||
@ -100,10 +102,4 @@ func Bootstrap(a *app.App) {
|
|||||||
Register(nodespace.New()).
|
Register(nodespace.New()).
|
||||||
Register(commonspace.New()).
|
Register(commonspace.New()).
|
||||||
Register(server.New())
|
Register(server.New())
|
||||||
|
|
||||||
//Register(document.New()).
|
|
||||||
//Register(message.New()).
|
|
||||||
//Register(requesthandler.New()).
|
|
||||||
//Register(treecache.New()).
|
|
||||||
//Register(api.New())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
"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/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/node/nodespace"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/node/nodespace"
|
||||||
"time"
|
"time"
|
||||||
@ -24,7 +25,7 @@ type treeCache struct {
|
|||||||
nodeService nodespace.Service
|
nodeService nodespace.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ttl int) cache.TreeCache {
|
func New(ttl int) treegetter.TreeGetter {
|
||||||
return &treeCache{
|
return &treeCache{
|
||||||
gcttl: ttl,
|
gcttl: ttl,
|
||||||
}
|
}
|
||||||
@ -52,34 +53,20 @@ func (c *treeCache) Init(a *app.App) (err error) {
|
|||||||
ocache.WithLogger(log.Sugar()),
|
ocache.WithLogger(log.Sugar()),
|
||||||
ocache.WithGCPeriod(time.Minute),
|
ocache.WithGCPeriod(time.Minute),
|
||||||
ocache.WithTTL(time.Duration(c.gcttl)*time.Second),
|
ocache.WithTTL(time.Duration(c.gcttl)*time.Second),
|
||||||
ocache.WithRefCounter(false),
|
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *treeCache) Name() (name string) {
|
func (c *treeCache) Name() (name string) {
|
||||||
return cache.CName
|
return treegetter.CName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *treeCache) GetTree(ctx context.Context, spaceId, id string) (res cache.TreeResult, err error) {
|
func (c *treeCache) GetTree(ctx context.Context, spaceId, id string) (tr tree.ObjectTree, err error) {
|
||||||
var cacheRes ocache.Object
|
|
||||||
ctx = context.WithValue(ctx, spaceKey, spaceId)
|
ctx = context.WithValue(ctx, spaceKey, spaceId)
|
||||||
cacheRes, err = c.cache.Get(ctx, id)
|
value, err := c.cache.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cache.TreeResult{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
treeContainer, ok := cacheRes.(cache.TreeContainer)
|
|
||||||
if !ok {
|
|
||||||
err = ErrCacheObjectWithoutTree
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
tr = value.(tree.ObjectTree)
|
||||||
res = cache.TreeResult{
|
|
||||||
Release: func() {
|
|
||||||
c.cache.Release(id)
|
|
||||||
},
|
|
||||||
TreeContainer: treeContainer,
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,9 @@ package nodespace
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rpcHandler struct {
|
type rpcHandler struct {
|
||||||
@ -17,16 +17,19 @@ func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpac
|
|||||||
err = spacesyncproto.ErrSpaceExists
|
err = spacesyncproto.ErrSpaceExists
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err != cache.ErrSpaceNotFound {
|
if err != storage.ErrSpaceStorageMissing {
|
||||||
err = spacesyncproto.ErrUnexpected
|
err = spacesyncproto.ErrUnexpected
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
payload := storage.SpaceStorageCreatePayload{
|
payload := storage.SpaceStorageCreatePayload{
|
||||||
RecWithId: req.AclRoot,
|
RecWithId: &aclrecordproto.RawACLRecordWithId{
|
||||||
|
Payload: req.AclPayload,
|
||||||
|
Id: req.AclPayloadId,
|
||||||
|
},
|
||||||
SpaceHeaderWithId: req.SpaceHeader,
|
SpaceHeaderWithId: req.SpaceHeader,
|
||||||
}
|
}
|
||||||
_, err = r.s.spaceStorageProvider.CreateSpaceStorage(payload)
|
st, err := r.s.spaceStorageProvider.CreateSpaceStorage(payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = spacesyncproto.ErrUnexpected
|
err = spacesyncproto.ErrUnexpected
|
||||||
if err == storage.ErrSpaceStorageExists {
|
if err == storage.ErrSpaceStorageExists {
|
||||||
@ -34,6 +37,7 @@ func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpac
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
st.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,6 @@ func (s *service) Init(a *app.App) (err error) {
|
|||||||
ocache.WithLogger(log.Sugar()),
|
ocache.WithLogger(log.Sugar()),
|
||||||
ocache.WithGCPeriod(time.Minute),
|
ocache.WithGCPeriod(time.Minute),
|
||||||
ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second),
|
ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second),
|
||||||
ocache.WithRefCounter(false),
|
|
||||||
)
|
)
|
||||||
return spacesyncproto.DRPCRegisterSpace(a.MustComponent(server.CName).(server.DRPCServer), &rpcHandler{s})
|
return spacesyncproto.DRPCRegisterSpace(a.MustComponent(server.CName).(server.DRPCServer), &rpcHandler{s})
|
||||||
}
|
}
|
||||||
@ -54,10 +53,6 @@ func (s *service) Name() (name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Run(ctx context.Context) (err error) {
|
func (s *service) Run(ctx context.Context) (err error) {
|
||||||
go func() {
|
|
||||||
time.Sleep(time.Second * 5)
|
|
||||||
_, _ = s.GetSpace(ctx, "testDSpace")
|
|
||||||
}()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -62,5 +62,5 @@ func (s spaceKeys) HeaderKey() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isRootIdKey(key string) bool {
|
func isRootIdKey(key string) bool {
|
||||||
return strings.HasPrefix(key, "t/") && strings.HasSuffix(key, "rootId")
|
return strings.HasPrefix(key, "t/") && strings.HasSuffix(key, "heads")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,11 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/akrylysov/pogreb"
|
"github.com/akrylysov/pogreb"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
|
"go.uber.org/zap"
|
||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -14,6 +16,8 @@ var defPogrebOptions = &pogreb.Options{
|
|||||||
BackgroundCompactionInterval: time.Minute * 5,
|
BackgroundCompactionInterval: time.Minute * 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var log = logger.NewNamed("storage.spacestorage")
|
||||||
|
|
||||||
type spaceStorage struct {
|
type spaceStorage struct {
|
||||||
spaceId string
|
spaceId string
|
||||||
objDb *pogreb.DB
|
objDb *pogreb.DB
|
||||||
@ -24,6 +28,7 @@ type spaceStorage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newSpaceStorage(rootPath string, spaceId string) (store spacestorage.SpaceStorage, err error) {
|
func newSpaceStorage(rootPath string, spaceId string) (store spacestorage.SpaceStorage, err error) {
|
||||||
|
log.With(zap.String("id", spaceId)).Debug("space storage opening with new")
|
||||||
dbPath := path.Join(rootPath, spaceId)
|
dbPath := path.Join(rootPath, spaceId)
|
||||||
objDb, err := pogreb.Open(dbPath, defPogrebOptions)
|
objDb, err := pogreb.Open(dbPath, defPogrebOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -32,6 +37,7 @@ func newSpaceStorage(rootPath string, spaceId string) (store spacestorage.SpaceS
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.With(zap.String("id", spaceId), zap.Error(err)).Warn("failed to open storage")
|
||||||
objDb.Close()
|
objDb.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -74,6 +80,7 @@ func newSpaceStorage(rootPath string, spaceId string) (store spacestorage.SpaceS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createSpaceStorage(rootPath string, payload spacestorage.SpaceStorageCreatePayload) (store spacestorage.SpaceStorage, err error) {
|
func createSpaceStorage(rootPath string, payload spacestorage.SpaceStorageCreatePayload) (store spacestorage.SpaceStorage, err error) {
|
||||||
|
log.With(zap.String("id", payload.SpaceHeaderWithId.Id)).Debug("space storage creating")
|
||||||
dbPath := path.Join(rootPath, payload.SpaceHeaderWithId.Id)
|
dbPath := path.Join(rootPath, payload.SpaceHeaderWithId.Id)
|
||||||
db, err := pogreb.Open(dbPath, defPogrebOptions)
|
db, err := pogreb.Open(dbPath, defPogrebOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -81,6 +88,7 @@ func createSpaceStorage(rootPath string, payload spacestorage.SpaceStorageCreate
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
log.With(zap.String("id", payload.SpaceHeaderWithId.Id), zap.Error(err)).Warn("failed to create storage")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
db.Close()
|
db.Close()
|
||||||
}
|
}
|
||||||
@ -165,5 +173,6 @@ func (s *spaceStorage) StoredIds() (ids []string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *spaceStorage) Close() (err error) {
|
func (s *spaceStorage) Close() (err error) {
|
||||||
|
log.With(zap.String("id", s.spaceId)).Debug("space storage closed")
|
||||||
return s.objDb.Close()
|
return s.objDb.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,7 +99,7 @@ func (t *treeStorage) Heads() (heads []string, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if heads == nil {
|
if headsBytes == nil {
|
||||||
err = storage2.ErrUnknownTreeId
|
err = storage2.ErrUnknownTreeId
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
flagNodeMap = flag.String("n", "cmd/nodesgen/nodemap.yml", "path to nodes map file")
|
flagNodeMap = flag.String("n", "util/cmd/nodesgen/nodemap.yml", "path to nodes map file")
|
||||||
flagEtcPath = flag.String("e", "etc", "path to etc directory")
|
flagEtcPath = flag.String("e", "etc", "path to etc directory")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,6 +27,10 @@ type NodesMap struct {
|
|||||||
Consensus []struct {
|
Consensus []struct {
|
||||||
Addresses []string `yaml:"grpcAddresses"`
|
Addresses []string `yaml:"grpcAddresses"`
|
||||||
}
|
}
|
||||||
|
Clients []struct {
|
||||||
|
Addresses []string `yaml:"grpcAddresses"`
|
||||||
|
APIPort string `yaml:"apiPort"`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -60,6 +64,15 @@ func main() {
|
|||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var clientConfigs []config2.Config
|
||||||
|
for _, c := range nodesMap.Clients {
|
||||||
|
cfg, err := genClientConfig(c.Addresses, c.APIPort)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("could not generate the config file: %s", err.Error()))
|
||||||
|
}
|
||||||
|
clientConfigs = append(clientConfigs, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
var consConfigs []cconfig.Config
|
var consConfigs []cconfig.Config
|
||||||
for _, n := range nodesMap.Consensus {
|
for _, n := range nodesMap.Consensus {
|
||||||
cfg, err := genConsensusConfig(n.Addresses)
|
cfg, err := genConsensusConfig(n.Addresses)
|
||||||
@ -67,19 +80,13 @@ func main() {
|
|||||||
panic(fmt.Sprintf("could not generate the config file: %s", err.Error()))
|
panic(fmt.Sprintf("could not generate the config file: %s", err.Error()))
|
||||||
}
|
}
|
||||||
consConfigs = append(consConfigs, cfg)
|
consConfigs = append(consConfigs, cfg)
|
||||||
|
|
||||||
node := config2.Node{
|
|
||||||
PeerId: cfg.Account.PeerId,
|
|
||||||
Address: cfg.GrpcServer.ListenAddrs[0],
|
|
||||||
SigningKey: cfg.Account.SigningKey,
|
|
||||||
EncryptionKey: cfg.Account.EncryptionKey,
|
|
||||||
IsConsensus: true,
|
|
||||||
}
|
|
||||||
nodes = append(nodes, node)
|
|
||||||
}
|
}
|
||||||
for idx := range configs {
|
for idx := range configs {
|
||||||
configs[idx].Nodes = nodes
|
configs[idx].Nodes = nodes
|
||||||
}
|
}
|
||||||
|
for idx := range clientConfigs {
|
||||||
|
clientConfigs[idx].Nodes = nodes
|
||||||
|
}
|
||||||
|
|
||||||
// saving configs
|
// saving configs
|
||||||
configsPath := fmt.Sprintf("%s/configs", *flagEtcPath)
|
configsPath := fmt.Sprintf("%s/configs", *flagEtcPath)
|
||||||
@ -110,6 +117,18 @@ func main() {
|
|||||||
panic(fmt.Sprintf("could not write the config to file: %v", err))
|
panic(fmt.Sprintf("could not write the config to file: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for idx, cfg := range clientConfigs {
|
||||||
|
path := fmt.Sprintf("%s/client%d.yml", configsPath, idx+1)
|
||||||
|
bytes, err := yaml.Marshal(cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("could not marshal the keys: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(path, bytes, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("could not write the config to file: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
for idx, cfg := range consConfigs {
|
for idx, cfg := range consConfigs {
|
||||||
path := fmt.Sprintf("%s/cons%d.yml", configsPath, idx+1)
|
path := fmt.Sprintf("%s/cons%d.yml", configsPath, idx+1)
|
||||||
bytes, err := yaml.Marshal(cfg)
|
bytes, err := yaml.Marshal(cfg)
|
||||||
@ -172,6 +191,54 @@ func genNodeConfig(addresses []string, apiPort string) (config2.Config, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func genClientConfig(addresses []string, apiPort string) (config2.Config, error) {
|
||||||
|
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
|
||||||
|
if err != nil {
|
||||||
|
return config2.Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
signKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
|
||||||
|
if err != nil {
|
||||||
|
return config2.Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encEncKey, err := keys.EncodeKeyToString(encKey)
|
||||||
|
if err != nil {
|
||||||
|
return config2.Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encSignKey, err := keys.EncodeKeyToString(signKey)
|
||||||
|
if err != nil {
|
||||||
|
return config2.Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
peerID, err := peer.IDFromSigningPubKey(signKey.GetPublic())
|
||||||
|
if err != nil {
|
||||||
|
return config2.Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return config2.Config{
|
||||||
|
Anytype: config2.Anytype{SwarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"},
|
||||||
|
GrpcServer: config2.GrpcServer{
|
||||||
|
ListenAddrs: addresses,
|
||||||
|
TLS: false,
|
||||||
|
},
|
||||||
|
Storage: config2.Storage{Path: "db"},
|
||||||
|
Account: config2.Account{
|
||||||
|
PeerId: peerID.String(),
|
||||||
|
SigningKey: encSignKey,
|
||||||
|
EncryptionKey: encEncKey,
|
||||||
|
},
|
||||||
|
APIServer: config2.APIServer{
|
||||||
|
Port: apiPort,
|
||||||
|
},
|
||||||
|
Space: config2.Space{
|
||||||
|
GCTTL: 60,
|
||||||
|
SyncPeriod: 10,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func genConsensusConfig(addresses []string) (cconfig.Config, error) {
|
func genConsensusConfig(addresses []string) (cconfig.Config, error) {
|
||||||
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
|
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -15,3 +15,10 @@ consensus:
|
|||||||
- "127.0.0.1:4531"
|
- "127.0.0.1:4531"
|
||||||
- grpcAddresses:
|
- grpcAddresses:
|
||||||
- "127.0.0.1:4532"
|
- "127.0.0.1:4532"
|
||||||
|
clients:
|
||||||
|
- grpcAddresses:
|
||||||
|
- "127.0.0.1:4630"
|
||||||
|
apiPort: "8090"
|
||||||
|
- grpcAddresses:
|
||||||
|
- "127.0.0.1:4631"
|
||||||
|
apiPort: "8091"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user