Merge pull request #16 from anytypeio/acl-invite

This commit is contained in:
Mikhail Rakhmanov 2022-11-07 15:56:05 +01:00 committed by GitHub
commit 92bdf7d57b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
87 changed files with 3227 additions and 936 deletions

5
.gitignore vendored
View File

@ -8,6 +8,11 @@
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test *.test
# playground folder for testing different clients
playground
# .paw folder for macos paw client
.paw
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out

View File

@ -42,6 +42,14 @@ func (s *service) Init(a *app.App) (err error) {
return err return err
} }
decodedPeerKey, err := keys.DecodeKeyFromString(
acc.PeerKey,
signingkey.NewSigningEd25519PrivKeyFromBytes,
nil)
if err != nil {
return err
}
identity, err := decodedSigningKey.GetPublic().Raw() identity, err := decodedSigningKey.GetPublic().Raw()
if err != nil { if err != nil {
return err return err
@ -49,6 +57,7 @@ func (s *service) Init(a *app.App) (err error) {
s.accountData = &account.AccountData{ s.accountData = &account.AccountData{
Identity: identity, Identity: identity,
PeerKey: decodedPeerKey,
SignKey: decodedSigningKey, SignKey: decodedSigningKey,
EncKey: decodedEncryptionKey, EncKey: decodedEncryptionKey,
} }

View File

@ -89,8 +89,8 @@ func (c *controller) AllSpaceIds() (ids []string, err error) {
} }
func (c *controller) LoadSpace(id string) (err error) { func (c *controller) LoadSpace(id string) (err error) {
//TODO implement me _, err = c.spaceService.GetSpace(context.Background(), id)
panic("implement me") return
} }
func (c *controller) CreateDocument(spaceId string) (id string, err error) { func (c *controller) CreateDocument(spaceId string) (id string, err error) {

View File

@ -62,6 +62,7 @@ func (s *service) Run(ctx context.Context) (err error) {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/deriveSpace", s.deriveSpace) mux.HandleFunc("/deriveSpace", s.deriveSpace)
mux.HandleFunc("/createSpace", s.createSpace) mux.HandleFunc("/createSpace", s.createSpace)
mux.HandleFunc("/loadSpace", s.loadSpace)
mux.HandleFunc("/allSpaceIds", s.allSpaceIds) mux.HandleFunc("/allSpaceIds", s.allSpaceIds)
mux.HandleFunc("/createDocument", s.createDocument) mux.HandleFunc("/createDocument", s.createDocument)
mux.HandleFunc("/allDocumentIds", s.allDocumentIds) mux.HandleFunc("/allDocumentIds", s.allDocumentIds)
@ -93,6 +94,17 @@ func (s *service) deriveSpace(w http.ResponseWriter, req *http.Request) {
sendText(w, http.StatusOK, id) sendText(w, http.StatusOK, id)
} }
func (s *service) loadSpace(w http.ResponseWriter, req *http.Request) {
query := req.URL.Query()
spaceId := query.Get("spaceId")
err := s.controller.LoadSpace(query.Get("spaceId"))
if err != nil {
sendText(w, http.StatusInternalServerError, err.Error())
return
}
sendText(w, http.StatusOK, spaceId)
}
func (s *service) createSpace(w http.ResponseWriter, req *http.Request) { func (s *service) createSpace(w http.ResponseWriter, req *http.Request) {
id, err := s.controller.CreateSpace() id, err := s.controller.CreateSpace()
if err != nil { if err != nil {

View File

@ -75,7 +75,7 @@ func (c *treeCache) Init(a *app.App) (err error) {
if err != nil { if err != nil {
return return
} }
return textdocument.NewTextDocument(context.Background(), space, id, &updateListener{}, c.account) return textdocument.NewTextDocument(ctx, space, id, &updateListener{}, c.account)
}, },
ocache.WithLogger(log.Sugar()), ocache.WithLogger(log.Sugar()),
ocache.WithGCPeriod(time.Minute), ocache.WithGCPeriod(time.Minute),

View File

@ -2,43 +2,43 @@ package clientspace
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
"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/treegetter"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
) )
type rpcHandler struct { type rpcHandler struct {
s *service s *service
} }
func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpaceRequest) (resp *spacesyncproto.PushSpaceResponse, err error) { func (r *rpcHandler) PullSpace(ctx context.Context, request *spacesyncproto.PullSpaceRequest) (resp *spacesyncproto.PullSpaceResponse, err error) {
_, err = r.s.GetSpace(ctx, req.SpaceHeader.Id) sp, err := r.s.GetSpace(ctx, request.Id)
if err == nil {
err = spacesyncproto.ErrSpaceExists
return
}
if err != treegetter.ErrSpaceNotFound {
err = spacesyncproto.ErrUnexpected
return
}
payload := storage.SpaceStorageCreatePayload{
RecWithId: &aclrecordproto.RawACLRecordWithId{
Payload: req.AclPayload,
Id: req.AclPayloadId,
},
SpaceHeaderWithId: req.SpaceHeader,
}
st, err := r.s.spaceStorageProvider.CreateSpaceStorage(payload)
if err != nil { if err != nil {
err = spacesyncproto.ErrUnexpected if err != spacesyncproto.ErrSpaceMissing {
if err == storage.ErrSpaceStorageExists { err = spacesyncproto.ErrUnexpected
err = spacesyncproto.ErrSpaceExists
} }
return return
} }
st.Close()
description := sp.Description()
resp = &spacesyncproto.PullSpaceResponse{
SpaceHeader: description.SpaceHeader,
AclPayload: description.AclPayload,
AclPayloadId: description.AclId,
}
return
}
func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpaceRequest) (resp *spacesyncproto.PushSpaceResponse, err error) {
description := commonspace.SpaceDescription{
SpaceHeader: req.SpaceHeader,
AclId: req.AclPayloadId,
AclPayload: req.AclPayload,
}
err = r.s.AddSpace(ctx, description)
if err != nil {
return
}
resp = &spacesyncproto.PushSpaceResponse{}
return return
} }

View File

@ -23,6 +23,7 @@ func New() Service {
type Service interface { type Service interface {
GetSpace(ctx context.Context, id string) (commonspace.Space, error) GetSpace(ctx context.Context, id string) (commonspace.Space, error)
AddSpace(ctx context.Context, description commonspace.SpaceDescription) (err error)
CreateSpace(ctx context.Context, payload commonspace.SpaceCreatePayload) (commonspace.Space, error) CreateSpace(ctx context.Context, payload commonspace.SpaceCreatePayload) (commonspace.Space, error)
DeriveSpace(ctx context.Context, payload commonspace.SpaceDerivePayload) (commonspace.Space, error) DeriveSpace(ctx context.Context, payload commonspace.SpaceDerivePayload) (commonspace.Space, error)
app.ComponentRunnable app.ComponentRunnable
@ -40,9 +41,7 @@ func (s *service) Init(a *app.App) (err error) {
s.commonSpace = a.MustComponent(commonspace.CName).(commonspace.Service) s.commonSpace = a.MustComponent(commonspace.CName).(commonspace.Service)
s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider) s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
s.spaceCache = ocache.New( s.spaceCache = ocache.New(
func(ctx context.Context, id string) (value ocache.Object, err error) { s.loadSpace,
return s.commonSpace.GetSpace(ctx, id)
},
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),
@ -92,6 +91,25 @@ func (s *service) GetSpace(ctx context.Context, id string) (container commonspac
return v.(commonspace.Space), nil return v.(commonspace.Space), nil
} }
func (s *service) AddSpace(ctx context.Context, description commonspace.SpaceDescription) (err error) {
return s.commonSpace.AddSpace(ctx, description)
}
func (s *service) loadSpace(ctx context.Context, id string) (value ocache.Object, err error) {
cc, err := s.commonSpace.NewSpace(ctx, id)
if err != nil {
return
}
ns, err := newClientSpace(cc)
if err != nil {
return
}
if err = ns.Init(ctx); err != nil {
return
}
return ns, nil
}
func (s *service) Close(ctx context.Context) (err error) { func (s *service) Close(ctx context.Context) (err error) {
return s.spaceCache.Close() return s.spaceCache.Close()
} }

View File

@ -0,0 +1,22 @@
package clientspace
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
)
func newClientSpace(cc commonspace.Space) (commonspace.Space, error) {
return &clientSpace{cc}, nil
}
type clientSpace struct {
commonspace.Space
}
func (s *clientSpace) Init(ctx context.Context) (err error) {
return s.Space.Init(ctx)
}
func (s *clientSpace) Close() (err error) {
return s.Space.Close()
}

View File

@ -77,7 +77,7 @@ func createListStorage(spaceId string, db *badger.DB, txn *badger.Txn, root *acl
return return
} }
func (l *listStorage) ID() string { func (l *listStorage) Id() string {
return l.id return l.id
} }

View File

@ -10,7 +10,7 @@ import (
) )
func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) { func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) {
require.Equal(t, store.ID(), root.Id) require.Equal(t, store.Id(), root.Id)
aclRoot, err := store.Root() aclRoot, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -3,7 +3,7 @@ package storage
import ( import (
"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" storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"github.com/dgraph-io/badger/v3" "github.com/dgraph-io/badger/v3"
"sync" "sync"
) )
@ -12,7 +12,7 @@ type spaceStorage struct {
spaceId string spaceId string
objDb *badger.DB objDb *badger.DB
keys spaceKeys keys spaceKeys
aclStorage storage2.ListStorage aclStorage storage.ListStorage
header *spacesyncproto.RawSpaceHeaderWithId header *spacesyncproto.RawSpaceHeaderWithId
mx sync.Mutex mx sync.Mutex
} }
@ -77,15 +77,15 @@ func createSpaceStorage(db *badger.DB, payload spacestorage.SpaceStorageCreatePa
return return
} }
func (s *spaceStorage) ID() string { func (s *spaceStorage) Id() string {
return s.spaceId return s.spaceId
} }
func (s *spaceStorage) TreeStorage(id string) (storage2.TreeStorage, error) { func (s *spaceStorage) TreeStorage(id string) (storage.TreeStorage, error) {
return newTreeStorage(s.objDb, s.spaceId, id) return newTreeStorage(s.objDb, s.spaceId, id)
} }
func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePayload) (ts storage2.TreeStorage, err error) { func (s *spaceStorage) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
// we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation // we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation
s.mx.Lock() s.mx.Lock()
defer s.mx.Unlock() defer s.mx.Unlock()
@ -93,7 +93,7 @@ func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePaylo
return createTreeStorage(s.objDb, s.spaceId, payload) return createTreeStorage(s.objDb, s.spaceId, payload)
} }
func (s *spaceStorage) ACLStorage() (storage2.ListStorage, error) { func (s *spaceStorage) ACLStorage() (storage.ListStorage, error) {
return s.aclStorage, nil return s.aclStorage, nil
} }

View File

@ -2,7 +2,7 @@ package storage
import ( import (
"context" "context"
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "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"
"github.com/dgraph-io/badger/v3" "github.com/dgraph-io/badger/v3"
) )
@ -40,6 +40,9 @@ func newTreeStorage(db *badger.DB, spaceId, treeId string) (ts storage.TreeStora
} }
return nil return nil
}) })
if err == badger.ErrKeyNotFound {
err = storage.ErrUnknownTreeId
}
return return
} }
@ -85,7 +88,7 @@ func createTreeStorage(db *badger.DB, spaceId string, payload storage.TreeStorag
return return
} }
func (t *treeStorage) ID() string { func (t *treeStorage) Id() string {
return t.id return t.id
} }

View File

@ -27,7 +27,7 @@ type fixture struct {
} }
func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) { func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) {
require.Equal(t, payload.RootRawChange.Id, store.ID()) require.Equal(t, payload.RootRawChange.Id, store.Id())
root, err := store.Root() root, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -75,6 +75,7 @@ func (d *diffSyncer) syncWithPeer(ctx context.Context, p peer.Peer) (err error)
return d.sendPushSpaceRequest(ctx, cl) return d.sendPushSpaceRequest(ctx, cl)
} }
ctx = peer.CtxWithPeerId(ctx, p.Id())
d.pingTreesInCache(ctx, newIds) d.pingTreesInCache(ctx, newIds)
d.pingTreesInCache(ctx, changedIds) d.pingTreesInCache(ctx, changedIds)
d.pingTreesInCache(ctx, removedIds) d.pingTreesInCache(ctx, removedIds)

View File

@ -15,6 +15,7 @@ import (
mock_aclstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage/mock_storage" mock_aclstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage/mock_storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff/mock_ldiff" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ldiff/mock_ldiff"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/libp2p/go-libp2p/core/sec"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"storj.io/drpc" "storj.io/drpc"
"testing" "testing"
@ -50,6 +51,10 @@ func (m mockPeer) LastUsage() time.Time {
return time.Time{} return time.Time{}
} }
func (m mockPeer) Secure() sec.SecureConn {
return nil
}
func (m mockPeer) UpdateLastUsage() { func (m mockPeer) UpdateLastUsage() {
} }

View File

@ -6,12 +6,15 @@ import (
"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/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/syncservice" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
config2 "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/net/peer"
"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"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
) )
const CName = "common.commonspace" const CName = "common.commonspace"
@ -25,12 +28,13 @@ func New() Service {
type Service interface { type Service interface {
DeriveSpace(ctx context.Context, payload SpaceDerivePayload) (string, error) DeriveSpace(ctx context.Context, payload SpaceDerivePayload) (string, error)
CreateSpace(ctx context.Context, payload SpaceCreatePayload) (string, error) CreateSpace(ctx context.Context, payload SpaceCreatePayload) (string, error)
GetSpace(ctx context.Context, id string) (sp Space, err error) NewSpace(ctx context.Context, id string) (sp Space, err error)
AddSpace(ctx context.Context, spaceDescription SpaceDescription) (err error)
app.Component app.Component
} }
type service struct { type service struct {
config config2.Space config config.Space
account account.Service account account.Service
configurationService nodeconf.Service configurationService nodeconf.Service
storageProvider storage.SpaceStorageProvider storageProvider storage.SpaceStorageProvider
@ -39,7 +43,7 @@ type service struct {
} }
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(config.CName).(*config.Config).Space
s.account = a.MustComponent(account.CName).(account.Service) 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)
@ -52,9 +56,7 @@ func (s *service) Name() (name string) {
return CName return CName
} }
func (s *service) CreateSpace( func (s *service) CreateSpace(ctx context.Context, payload SpaceCreatePayload) (id string, err error) {
ctx context.Context,
payload SpaceCreatePayload) (id string, err error) {
storageCreate, err := storagePayloadForSpaceCreate(payload) storageCreate, err := storagePayloadForSpaceCreate(payload)
if err != nil { if err != nil {
return return
@ -64,12 +66,10 @@ func (s *service) CreateSpace(
return return
} }
return store.ID(), nil return store.Id(), nil
} }
func (s *service) DeriveSpace( func (s *service) DeriveSpace(ctx context.Context, payload SpaceDerivePayload) (id string, err error) {
ctx context.Context,
payload SpaceDerivePayload) (id string, err error) {
storageCreate, err := storagePayloadForSpaceDerive(payload) storageCreate, err := storagePayloadForSpaceDerive(payload)
if err != nil { if err != nil {
return return
@ -79,13 +79,51 @@ func (s *service) DeriveSpace(
return return
} }
return store.ID(), nil return store.Id(), nil
} }
func (s *service) GetSpace(ctx context.Context, id string) (Space, error) { func (s *service) AddSpace(ctx context.Context, spaceDescription SpaceDescription) (err error) {
_, err = s.storageProvider.SpaceStorage(spaceDescription.SpaceHeader.Id)
if err == nil {
err = spacesyncproto.ErrSpaceExists
return
}
if err != storage.ErrSpaceStorageMissing {
err = spacesyncproto.ErrUnexpected
return
}
payload := storage.SpaceStorageCreatePayload{
RecWithId: &aclrecordproto.RawACLRecordWithId{
Payload: spaceDescription.AclPayload,
Id: spaceDescription.AclId,
},
SpaceHeaderWithId: spaceDescription.SpaceHeader,
}
st, err := s.storageProvider.CreateSpaceStorage(payload)
if err != nil {
err = spacesyncproto.ErrUnexpected
if err == storage.ErrSpaceStorageExists {
err = spacesyncproto.ErrSpaceExists
}
return
}
err = st.Close()
return
}
func (s *service) NewSpace(ctx context.Context, id string) (Space, error) {
st, err := s.storageProvider.SpaceStorage(id) st, err := s.storageProvider.SpaceStorage(id)
if err != nil { if err != nil {
return nil, err if err != spacesyncproto.ErrSpaceMissing {
return nil, err
}
st, err = s.getSpaceStorageFromRemote(ctx, id)
if err != nil {
err = storage.ErrSpaceStorageMissing
return nil, err
}
} }
lastConfiguration := s.configurationService.GetLast() lastConfiguration := s.configurationService.GetLast()
@ -101,8 +139,34 @@ func (s *service) GetSpace(ctx context.Context, id string) (Space, error) {
configuration: lastConfiguration, configuration: lastConfiguration,
storage: st, storage: st,
} }
if err := sp.Init(ctx); err != nil {
return nil, err
}
return sp, nil return sp, nil
} }
func (s *service) getSpaceStorageFromRemote(ctx context.Context, id string) (st storage.SpaceStorage, err error) {
var p peer.Peer
lastConfiguration := s.configurationService.GetLast()
// for nodes we always get remote space only if we have id in the context
if lastConfiguration.IsResponsible(id) {
err = spacesyncproto.ErrSpaceMissing
return
}
p, err = s.pool.DialOneOf(ctx, lastConfiguration.NodeIds(id))
if err != nil {
return
}
cl := spacesyncproto.NewDRPCSpaceClient(p)
res, err := cl.PullSpace(ctx, &spacesyncproto.PullSpaceRequest{Id: id})
if err != nil {
return
}
st, err = s.storageProvider.CreateSpaceStorage(storage.SpaceStorageCreatePayload{
RecWithId: &aclrecordproto.RawACLRecordWithId{
Payload: res.AclPayload,
Id: res.AclPayloadId,
},
SpaceHeaderWithId: res.SpaceHeader,
})
return
}

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account" "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/syncacl"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
@ -14,9 +15,10 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter" "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/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
tree "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/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"
"github.com/zeebo/errs"
"go.uber.org/zap" "go.uber.org/zap"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -45,13 +47,22 @@ type SpaceDerivePayload struct {
EncryptionKey encryptionkey.PrivKey EncryptionKey encryptionkey.PrivKey
} }
type SpaceDescription struct {
SpaceHeader *spacesyncproto.RawSpaceHeaderWithId
AclId string
AclPayload []byte
}
func NewSpaceId(id string, repKey uint64) string { func NewSpaceId(id string, repKey uint64) string {
return fmt.Sprintf("%s.%d", id, repKey) return fmt.Sprintf("%s.%d", id, repKey)
} }
type Space interface { type Space interface {
Id() string Id() string
Init(ctx context.Context) error
StoredIds() []string StoredIds() []string
Description() SpaceDescription
SpaceSyncRpc() RpcHandler SpaceSyncRpc() RpcHandler
@ -63,8 +74,9 @@ type Space interface {
} }
type space struct { type space struct {
id string id string
mu sync.RWMutex mu sync.RWMutex
header *spacesyncproto.RawSpaceHeaderWithId
rpc *rpcHandler rpc *rpcHandler
@ -87,7 +99,21 @@ func (s *space) Id() string {
return s.id return s.id
} }
func (s *space) Description() SpaceDescription {
root := s.aclList.Root()
return SpaceDescription{
SpaceHeader: s.header,
AclId: root.Id,
AclPayload: root.Payload,
}
}
func (s *space) Init(ctx context.Context) (err error) { func (s *space) Init(ctx context.Context) (err error) {
header, err := s.storage.SpaceHeader()
if err != nil {
return
}
s.header = header
s.rpc = &rpcHandler{s: s} s.rpc = &rpcHandler{s: s}
initialIds, err := s.storage.StoredIds() initialIds, err := s.storage.StoredIds()
if err != nil { if err != nil {
@ -183,7 +209,18 @@ func (s *space) Close() error {
s.isClosed.Store(true) s.isClosed.Store(true)
log.With(zap.String("id", s.id)).Debug("space closed") log.With(zap.String("id", s.id)).Debug("space closed")
}() }()
s.diffService.Close() var mError errs.Group
s.syncService.Close() if err := s.diffService.Close(); err != nil {
return s.storage.Close() mError.Add(err)
}
if err := s.syncService.Close(); err != nil {
mError.Add(err)
}
if err := s.aclList.Close(); err != nil {
mError.Add(err)
}
if err := s.storage.Close(); err != nil {
mError.Add(err)
}
return mError.Err()
} }

View File

@ -65,6 +65,21 @@ func (mr *MockDRPCSpaceClientMockRecorder) HeadSync(arg0, arg1 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeadSync", reflect.TypeOf((*MockDRPCSpaceClient)(nil).HeadSync), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeadSync", reflect.TypeOf((*MockDRPCSpaceClient)(nil).HeadSync), arg0, arg1)
} }
// PullSpace mocks base method.
func (m *MockDRPCSpaceClient) PullSpace(arg0 context.Context, arg1 *spacesyncproto.PullSpaceRequest) (*spacesyncproto.PullSpaceResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PullSpace", arg0, arg1)
ret0, _ := ret[0].(*spacesyncproto.PullSpaceResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PullSpace indicates an expected call of PullSpace.
func (mr *MockDRPCSpaceClientMockRecorder) PullSpace(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PullSpace", reflect.TypeOf((*MockDRPCSpaceClient)(nil).PullSpace), arg0, arg1)
}
// PushSpace mocks base method. // PushSpace mocks base method.
func (m *MockDRPCSpaceClient) PushSpace(arg0 context.Context, arg1 *spacesyncproto.PushSpaceRequest) (*spacesyncproto.PushSpaceResponse, error) { func (m *MockDRPCSpaceClient) PushSpace(arg0 context.Context, arg1 *spacesyncproto.PushSpaceRequest) (*spacesyncproto.PushSpaceResponse, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -15,6 +15,8 @@ service Space {
rpc HeadSync(HeadSyncRequest) returns (HeadSyncResponse); rpc HeadSync(HeadSyncRequest) returns (HeadSyncResponse);
// PushSpace sends new space to the node // PushSpace sends new space to the node
rpc PushSpace(PushSpaceRequest) returns (PushSpaceResponse); rpc PushSpace(PushSpaceRequest) returns (PushSpaceResponse);
// PullSpace gets space from the remote peer
rpc PullSpace(PullSpaceRequest) returns (PullSpaceResponse);
// Stream opens object sync stream with node or client // Stream opens object sync stream with node or client
rpc Stream(stream ObjectSyncMessage) returns (stream ObjectSyncMessage); rpc Stream(stream ObjectSyncMessage) returns (stream ObjectSyncMessage);
} }
@ -70,6 +72,18 @@ message PushSpaceRequest {
// PushSpaceResponse is an empty response // PushSpaceResponse is an empty response
message PushSpaceResponse {} message PushSpaceResponse {}
// PullSpaceRequest is a request to request a space on a node that doesn't have it
message PullSpaceRequest {
string id = 1;
}
// PullSpaceResponse is a response with header and acl root
message PullSpaceResponse {
RawSpaceHeaderWithId spaceHeader = 1;
bytes aclPayload = 2;
string aclPayloadId = 3;
}
// SpaceHeader is a header for a space // SpaceHeader is a header for a space
message SpaceHeader { message SpaceHeader {
bytes identity = 1; bytes identity = 1;

View File

@ -493,6 +493,112 @@ func (m *PushSpaceResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_PushSpaceResponse proto.InternalMessageInfo var xxx_messageInfo_PushSpaceResponse proto.InternalMessageInfo
// PullSpaceRequest is a request to request a space on a node that doesn't have it
type PullSpaceRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
}
func (m *PullSpaceRequest) Reset() { *m = PullSpaceRequest{} }
func (m *PullSpaceRequest) String() string { return proto.CompactTextString(m) }
func (*PullSpaceRequest) ProtoMessage() {}
func (*PullSpaceRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{8}
}
func (m *PullSpaceRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PullSpaceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PullSpaceRequest.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 *PullSpaceRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_PullSpaceRequest.Merge(m, src)
}
func (m *PullSpaceRequest) XXX_Size() int {
return m.Size()
}
func (m *PullSpaceRequest) XXX_DiscardUnknown() {
xxx_messageInfo_PullSpaceRequest.DiscardUnknown(m)
}
var xxx_messageInfo_PullSpaceRequest proto.InternalMessageInfo
func (m *PullSpaceRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
// PullSpaceResponse is a response with header and acl root
type PullSpaceResponse struct {
SpaceHeader *RawSpaceHeaderWithId `protobuf:"bytes,1,opt,name=spaceHeader,proto3" json:"spaceHeader,omitempty"`
AclPayload []byte `protobuf:"bytes,2,opt,name=aclPayload,proto3" json:"aclPayload,omitempty"`
AclPayloadId string `protobuf:"bytes,3,opt,name=aclPayloadId,proto3" json:"aclPayloadId,omitempty"`
}
func (m *PullSpaceResponse) Reset() { *m = PullSpaceResponse{} }
func (m *PullSpaceResponse) String() string { return proto.CompactTextString(m) }
func (*PullSpaceResponse) ProtoMessage() {}
func (*PullSpaceResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{9}
}
func (m *PullSpaceResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PullSpaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PullSpaceResponse.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 *PullSpaceResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_PullSpaceResponse.Merge(m, src)
}
func (m *PullSpaceResponse) XXX_Size() int {
return m.Size()
}
func (m *PullSpaceResponse) XXX_DiscardUnknown() {
xxx_messageInfo_PullSpaceResponse.DiscardUnknown(m)
}
var xxx_messageInfo_PullSpaceResponse proto.InternalMessageInfo
func (m *PullSpaceResponse) GetSpaceHeader() *RawSpaceHeaderWithId {
if m != nil {
return m.SpaceHeader
}
return nil
}
func (m *PullSpaceResponse) GetAclPayload() []byte {
if m != nil {
return m.AclPayload
}
return nil
}
func (m *PullSpaceResponse) GetAclPayloadId() string {
if m != nil {
return m.AclPayloadId
}
return ""
}
// SpaceHeader is a header for a space // SpaceHeader is a header for a space
type SpaceHeader struct { type SpaceHeader struct {
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
@ -506,7 +612,7 @@ func (m *SpaceHeader) Reset() { *m = SpaceHeader{} }
func (m *SpaceHeader) String() string { return proto.CompactTextString(m) } func (m *SpaceHeader) String() string { return proto.CompactTextString(m) }
func (*SpaceHeader) ProtoMessage() {} func (*SpaceHeader) ProtoMessage() {}
func (*SpaceHeader) Descriptor() ([]byte, []int) { func (*SpaceHeader) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{8} return fileDescriptor_80e49f1f4ac27799, []int{10}
} }
func (m *SpaceHeader) XXX_Unmarshal(b []byte) error { func (m *SpaceHeader) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -579,7 +685,7 @@ func (m *RawSpaceHeader) Reset() { *m = RawSpaceHeader{} }
func (m *RawSpaceHeader) String() string { return proto.CompactTextString(m) } func (m *RawSpaceHeader) String() string { return proto.CompactTextString(m) }
func (*RawSpaceHeader) ProtoMessage() {} func (*RawSpaceHeader) ProtoMessage() {}
func (*RawSpaceHeader) Descriptor() ([]byte, []int) { func (*RawSpaceHeader) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{9} return fileDescriptor_80e49f1f4ac27799, []int{11}
} }
func (m *RawSpaceHeader) XXX_Unmarshal(b []byte) error { func (m *RawSpaceHeader) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -631,7 +737,7 @@ func (m *RawSpaceHeaderWithId) Reset() { *m = RawSpaceHeaderWithId{} }
func (m *RawSpaceHeaderWithId) String() string { return proto.CompactTextString(m) } func (m *RawSpaceHeaderWithId) String() string { return proto.CompactTextString(m) }
func (*RawSpaceHeaderWithId) ProtoMessage() {} func (*RawSpaceHeaderWithId) ProtoMessage() {}
func (*RawSpaceHeaderWithId) Descriptor() ([]byte, []int) { func (*RawSpaceHeaderWithId) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{10} return fileDescriptor_80e49f1f4ac27799, []int{12}
} }
func (m *RawSpaceHeaderWithId) XXX_Unmarshal(b []byte) error { func (m *RawSpaceHeaderWithId) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -684,6 +790,8 @@ func init() {
proto.RegisterType((*ObjectSyncMessage)(nil), "anySpace.ObjectSyncMessage") proto.RegisterType((*ObjectSyncMessage)(nil), "anySpace.ObjectSyncMessage")
proto.RegisterType((*PushSpaceRequest)(nil), "anySpace.PushSpaceRequest") proto.RegisterType((*PushSpaceRequest)(nil), "anySpace.PushSpaceRequest")
proto.RegisterType((*PushSpaceResponse)(nil), "anySpace.PushSpaceResponse") proto.RegisterType((*PushSpaceResponse)(nil), "anySpace.PushSpaceResponse")
proto.RegisterType((*PullSpaceRequest)(nil), "anySpace.PullSpaceRequest")
proto.RegisterType((*PullSpaceResponse)(nil), "anySpace.PullSpaceResponse")
proto.RegisterType((*SpaceHeader)(nil), "anySpace.SpaceHeader") proto.RegisterType((*SpaceHeader)(nil), "anySpace.SpaceHeader")
proto.RegisterType((*RawSpaceHeader)(nil), "anySpace.RawSpaceHeader") proto.RegisterType((*RawSpaceHeader)(nil), "anySpace.RawSpaceHeader")
proto.RegisterType((*RawSpaceHeaderWithId)(nil), "anySpace.RawSpaceHeaderWithId") proto.RegisterType((*RawSpaceHeaderWithId)(nil), "anySpace.RawSpaceHeaderWithId")
@ -694,50 +802,53 @@ func init() {
} }
var fileDescriptor_80e49f1f4ac27799 = []byte{ var fileDescriptor_80e49f1f4ac27799 = []byte{
// 685 bytes of a gzipped FileDescriptorProto // 721 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xcd, 0x4e, 0xdb, 0x4a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0xcd, 0x6e, 0xd3, 0x4a,
0x14, 0x8e, 0x4d, 0x80, 0xe4, 0x24, 0x84, 0x30, 0x97, 0xab, 0xeb, 0x9b, 0x56, 0x6e, 0xe4, 0x45, 0x14, 0x8e, 0xdd, 0xb4, 0x4d, 0x4e, 0xd2, 0x34, 0x9d, 0xdb, 0xab, 0xeb, 0x1b, 0x90, 0x89, 0xbc,
0x15, 0x75, 0x01, 0x6d, 0xda, 0x1d, 0x9b, 0xfe, 0x10, 0xd4, 0xa8, 0xa2, 0xa0, 0x49, 0xab, 0x4a, 0x40, 0x11, 0x8b, 0x16, 0x02, 0xbb, 0x6e, 0xf8, 0x69, 0x2a, 0x22, 0x54, 0x5a, 0x4d, 0x40, 0x48,
0x55, 0x37, 0x83, 0x3d, 0x24, 0x53, 0xc5, 0x1e, 0xd7, 0x33, 0x11, 0x78, 0xd1, 0x77, 0xe8, 0xb2, 0x88, 0xcd, 0xd4, 0x9e, 0x26, 0x46, 0xfe, 0xc3, 0x33, 0x51, 0xeb, 0x05, 0xef, 0xc0, 0x12, 0x36,
0xdb, 0xbe, 0x4d, 0x97, 0x2c, 0x59, 0x56, 0xf0, 0x22, 0xd5, 0x9c, 0xd8, 0x71, 0x02, 0x81, 0xcd, 0x48, 0xbc, 0x0d, 0xcb, 0x2e, 0x59, 0xa2, 0xf6, 0x45, 0xd0, 0x9c, 0xd8, 0xb1, 0x9d, 0xa6, 0x5d,
0x64, 0xce, 0x77, 0xfe, 0xbe, 0xf9, 0x72, 0x8e, 0xe1, 0x99, 0x2f, 0xc3, 0x50, 0x46, 0x2a, 0x66, 0xb3, 0x71, 0xe7, 0x7c, 0xe7, 0xef, 0x9b, 0x6f, 0xce, 0x69, 0xe0, 0x91, 0x1d, 0xfa, 0x7e, 0x18,
0x3e, 0xdf, 0xc5, 0x53, 0xa5, 0x91, 0x1f, 0x27, 0x52, 0xcb, 0x5d, 0x3c, 0x55, 0x81, 0xee, 0x20, 0x88, 0x88, 0xd9, 0x7c, 0x17, 0xbf, 0x22, 0x09, 0xec, 0x28, 0x0e, 0x65, 0xb8, 0x8b, 0x5f, 0x91,
0x40, 0x2a, 0x2c, 0x4a, 0x07, 0x06, 0xf3, 0xfa, 0xb0, 0xf1, 0x96, 0xb3, 0x60, 0x90, 0x46, 0x3e, 0xa3, 0x3b, 0x08, 0x90, 0x1a, 0x0b, 0x92, 0x91, 0xc2, 0xac, 0x21, 0x6c, 0xbc, 0xe4, 0xcc, 0x19,
0x65, 0xd1, 0x90, 0x13, 0x02, 0xe5, 0xd3, 0x44, 0x86, 0x8e, 0xd5, 0xb6, 0x3a, 0x65, 0x8a, 0x77, 0x25, 0x81, 0x4d, 0x59, 0x30, 0xe6, 0x84, 0x40, 0xf5, 0x34, 0x0e, 0x7d, 0x43, 0xeb, 0x6a, 0xbd,
0xd2, 0x00, 0x5b, 0x4b, 0xc7, 0x46, 0xc4, 0xd6, 0x92, 0x6c, 0xc3, 0xea, 0x58, 0x84, 0x42, 0x3b, 0x2a, 0xc5, 0x33, 0x69, 0x81, 0x2e, 0x43, 0x43, 0x47, 0x44, 0x97, 0x21, 0xd9, 0x86, 0x55, 0xcf,
0x2b, 0x6d, 0xab, 0xb3, 0x41, 0xa7, 0x86, 0x77, 0x06, 0x8d, 0x59, 0x29, 0xae, 0x26, 0x63, 0x6d, 0xf5, 0x5d, 0x69, 0xac, 0x74, 0xb5, 0xde, 0x06, 0x9d, 0x19, 0xd6, 0x19, 0xb4, 0xe6, 0xa5, 0xb8,
0x6a, 0x8d, 0x98, 0x1a, 0x61, 0xad, 0x3a, 0xc5, 0x3b, 0xd9, 0x83, 0x0a, 0x1f, 0xf3, 0x90, 0x47, 0x98, 0x7a, 0x52, 0xd5, 0x9a, 0x30, 0x31, 0xc1, 0x5a, 0x4d, 0x8a, 0x67, 0xb2, 0x07, 0x35, 0xee,
0x5a, 0x39, 0x76, 0x7b, 0xa5, 0x53, 0xeb, 0x3e, 0xda, 0xc9, 0xd9, 0xec, 0x2c, 0xe6, 0xf7, 0xa6, 0x71, 0x9f, 0x07, 0x52, 0x18, 0x7a, 0x77, 0xa5, 0xd7, 0xe8, 0xdf, 0xdb, 0xc9, 0xd8, 0xec, 0x94,
0x71, 0x74, 0x96, 0x60, 0x1a, 0xfb, 0x72, 0x12, 0xcd, 0x1a, 0xa3, 0xe1, 0xed, 0xc1, 0xbf, 0x4b, 0xf3, 0x07, 0xb3, 0x38, 0x3a, 0x4f, 0x50, 0x8d, 0xed, 0x70, 0x1a, 0xcc, 0x1b, 0xa3, 0x61, 0xed,
0x13, 0x0d, 0x6f, 0x11, 0x60, 0xf7, 0x2a, 0xb5, 0x45, 0x80, 0x7c, 0x38, 0x0b, 0xf0, 0x25, 0x55, 0xc1, 0xbf, 0x4b, 0x13, 0x15, 0x6f, 0xd7, 0xc1, 0xee, 0x75, 0xaa, 0xbb, 0x0e, 0xf2, 0xe1, 0xcc,
0x8a, 0x77, 0xef, 0x0b, 0x6c, 0x16, 0xc9, 0xdf, 0x26, 0x5c, 0x69, 0xe2, 0xc0, 0x3a, 0x0a, 0xd6, 0xc1, 0x9b, 0xd4, 0x29, 0x9e, 0xad, 0x0f, 0xb0, 0x99, 0x27, 0x7f, 0x9a, 0x72, 0x21, 0x89, 0x01,
0xcf, 0x73, 0x73, 0x93, 0xec, 0xc2, 0x5a, 0x62, 0x54, 0xca, 0xa9, 0xff, 0xb7, 0x84, 0xba, 0xf1, 0xeb, 0x28, 0xd8, 0x30, 0xcb, 0xcd, 0x4c, 0xb2, 0x0b, 0x6b, 0xb1, 0x52, 0x29, 0xa3, 0xfe, 0xdf,
0xd3, 0x2c, 0xcc, 0x3b, 0x80, 0xe6, 0x1c, 0xb5, 0x58, 0x46, 0x8a, 0x93, 0x2e, 0xac, 0x27, 0x48, 0x12, 0xea, 0xca, 0x4f, 0xd3, 0x30, 0xeb, 0x00, 0xda, 0x05, 0x6a, 0x51, 0x18, 0x08, 0x4e, 0xfa,
0x53, 0x39, 0x16, 0x56, 0x71, 0xee, 0x12, 0x80, 0xe6, 0x81, 0xde, 0x77, 0xd8, 0x3a, 0x3a, 0xf9, 0xb0, 0x1e, 0x23, 0x4d, 0x61, 0x68, 0x58, 0xc5, 0xb8, 0x49, 0x00, 0x9a, 0x05, 0x5a, 0x9f, 0x61,
0xca, 0x7d, 0x6d, 0x9c, 0x87, 0x5c, 0x29, 0x36, 0xe4, 0xf7, 0xf0, 0x74, 0x4c, 0x8b, 0x78, 0x9c, 0xeb, 0xe8, 0xe4, 0x23, 0xb7, 0xa5, 0x72, 0x1e, 0x72, 0x21, 0xd8, 0x98, 0xdf, 0xc2, 0xd3, 0x50,
0xf6, 0xf3, 0xb7, 0xe6, 0xa6, 0xf1, 0xc4, 0x2c, 0x1d, 0x4b, 0x16, 0xa0, 0x86, 0x75, 0x9a, 0x9b, 0x2d, 0x22, 0x2f, 0x19, 0x66, 0x77, 0xcd, 0x4c, 0xe5, 0x89, 0x58, 0xe2, 0x85, 0xcc, 0x41, 0x0d,
0xa4, 0x05, 0x15, 0x89, 0x2d, 0xfa, 0x81, 0x53, 0xc6, 0xa4, 0x99, 0xed, 0xfd, 0xb4, 0xa0, 0x79, 0x9b, 0x34, 0x33, 0x49, 0x07, 0x6a, 0x21, 0xb6, 0x18, 0x3a, 0x46, 0x15, 0x93, 0xe6, 0xb6, 0xf5,
0x3c, 0x51, 0x23, 0x24, 0x99, 0xcb, 0xf4, 0x12, 0x6a, 0xd8, 0xcf, 0x70, 0xe6, 0x09, 0x52, 0xa8, 0x55, 0x83, 0xf6, 0xf1, 0x54, 0x4c, 0x90, 0x64, 0x26, 0xd3, 0x53, 0x68, 0x60, 0x3f, 0xc5, 0x99,
0x75, 0xdd, 0xe2, 0x2d, 0x94, 0x9d, 0x0d, 0x0a, 0xff, 0x27, 0xa1, 0x47, 0xfd, 0x80, 0xce, 0xa7, 0xc7, 0x48, 0xa1, 0xd1, 0x37, 0xf3, 0xbb, 0x50, 0x76, 0x36, 0xca, 0xfd, 0xef, 0x5c, 0x39, 0x19,
0x10, 0x17, 0x80, 0xf9, 0xe3, 0xe3, 0x8c, 0x8f, 0x8d, 0x7c, 0xe6, 0x10, 0xe2, 0x41, 0xbd, 0xb0, 0x3a, 0xb4, 0x98, 0x42, 0x4c, 0x00, 0x66, 0x7b, 0xc7, 0x29, 0x1f, 0x1d, 0xf9, 0x14, 0x10, 0x62,
0xfa, 0x53, 0xc6, 0x55, 0xba, 0x80, 0x79, 0xff, 0xc0, 0xd6, 0x1c, 0xb3, 0xa9, 0xc4, 0xde, 0x2f, 0x41, 0x33, 0xb7, 0x86, 0x33, 0xc6, 0x75, 0x5a, 0xc2, 0xac, 0x7f, 0x60, 0xab, 0xc0, 0x6c, 0x26,
0x0b, 0x6a, 0x73, 0xbd, 0xcd, 0xdb, 0x44, 0xc0, 0x23, 0x2d, 0x74, 0x9a, 0x0d, 0xe3, 0xcc, 0x26, 0xb1, 0x65, 0x29, 0xba, 0x9e, 0x57, 0xa2, 0xbb, 0x30, 0x0c, 0xd6, 0x37, 0x4d, 0x65, 0xce, 0x83,
0x0f, 0xa1, 0xaa, 0x45, 0xc8, 0x95, 0x66, 0x61, 0x8c, 0x1c, 0x56, 0x68, 0x01, 0x18, 0x2f, 0x32, 0xd2, 0xc7, 0xf9, 0x3b, 0x2e, 0xf5, 0x43, 0x83, 0x46, 0xa1, 0x8d, 0x7a, 0x1b, 0xd7, 0xe1, 0x81,
0xfe, 0x90, 0xc6, 0x3c, 0xeb, 0x5f, 0x00, 0xe4, 0x31, 0x34, 0x8c, 0xb0, 0xc2, 0x67, 0x5a, 0xc8, 0x74, 0x65, 0x92, 0x2e, 0xd3, 0xdc, 0x26, 0x77, 0xa1, 0x2e, 0x5d, 0x9f, 0x0b, 0xc9, 0xfc, 0x08,
0xe8, 0x1d, 0x4f, 0x51, 0xb9, 0x32, 0xbd, 0x81, 0x9a, 0xc1, 0x53, 0x9c, 0x07, 0xce, 0xea, 0x74, 0xdb, 0xad, 0xd0, 0x1c, 0x50, 0x5e, 0x24, 0xf7, 0x26, 0x89, 0x78, 0xda, 0x2a, 0x07, 0xc8, 0x7d,
0x11, 0xcc, 0xdd, 0x3b, 0x86, 0xc6, 0xa2, 0x42, 0xa4, 0x7d, 0x5b, 0xd0, 0xfa, 0xa2, 0x60, 0x86, 0x68, 0xa9, 0xc1, 0x70, 0x6d, 0x26, 0xdd, 0x30, 0x78, 0xc5, 0x13, 0x7c, 0xf9, 0x2a, 0x5d, 0x40,
0x8d, 0x18, 0x46, 0x4c, 0x4f, 0x12, 0x9e, 0xe9, 0x55, 0x00, 0xde, 0x3e, 0x6c, 0x2f, 0xd3, 0xdc, 0xd5, 0xe2, 0x08, 0xce, 0x1d, 0x63, 0x75, 0xb6, 0xc8, 0xea, 0x6c, 0x1d, 0x43, 0xab, 0x2c, 0x06,
0x64, 0x25, 0xec, 0x6c, 0xa1, 0x6a, 0x01, 0x64, 0x4b, 0x62, 0xe7, 0x4b, 0xf2, 0xe4, 0x3d, 0x54, 0xe9, 0x5e, 0xd7, 0xae, 0x59, 0xd6, 0x46, 0xb1, 0x71, 0xc7, 0x01, 0x93, 0xd3, 0x98, 0xa7, 0xd2,
0x7a, 0x49, 0xf2, 0x46, 0x06, 0x5c, 0x91, 0x06, 0xc0, 0xc7, 0x88, 0x9f, 0xc7, 0xdc, 0xd7, 0x3c, 0xe4, 0x80, 0xb5, 0x0f, 0xdb, 0xcb, 0xe4, 0x55, 0x59, 0x31, 0x3b, 0x2b, 0x55, 0xcd, 0x81, 0xf4,
0x68, 0x96, 0x48, 0x13, 0xea, 0x58, 0xfe, 0x50, 0x28, 0x25, 0xa2, 0x61, 0xd3, 0x22, 0x9b, 0x99, 0x5d, 0xf5, 0xec, 0x5d, 0x1f, 0xbc, 0x86, 0xda, 0x20, 0x8e, 0x5f, 0x84, 0x0e, 0x17, 0xa4, 0x05,
0xd0, 0xbd, 0x73, 0xa1, 0xb4, 0x6a, 0xda, 0x06, 0xe8, 0x25, 0x89, 0x4c, 0x8e, 0x4e, 0x4f, 0x15, 0xf0, 0x36, 0xe0, 0xe7, 0x11, 0xb7, 0x25, 0x77, 0xda, 0x15, 0xd2, 0x86, 0x26, 0x96, 0x3f, 0x74,
0xd7, 0xcd, 0xa0, 0x7b, 0x69, 0xc1, 0x2a, 0x86, 0x90, 0x57, 0x50, 0xc9, 0xe7, 0x9b, 0xfc, 0xbf, 0x85, 0x70, 0x83, 0x71, 0x5b, 0x23, 0x9b, 0xa9, 0xd0, 0x83, 0x73, 0x57, 0x48, 0xd1, 0xd6, 0x15,
0x6c, 0xe6, 0x71, 0xae, 0x5a, 0xad, 0xa5, 0xeb, 0x30, 0xdd, 0x9d, 0x7d, 0xa8, 0xce, 0xfe, 0x6d, 0x30, 0x88, 0xe3, 0x30, 0x3e, 0x3a, 0x3d, 0x15, 0x5c, 0xb6, 0x9d, 0xfe, 0x77, 0x1d, 0x56, 0x31,
0x32, 0x17, 0x78, 0x73, 0x38, 0x5b, 0x0f, 0x96, 0xfa, 0xb2, 0x2a, 0x07, 0xb0, 0x36, 0xd0, 0x09, 0x84, 0x3c, 0x83, 0x5a, 0xb6, 0x9f, 0xe4, 0xff, 0x65, 0x3b, 0x8b, 0x83, 0xd6, 0xe9, 0x2c, 0x5d,
0x67, 0x21, 0x99, 0x0b, 0xbb, 0xb5, 0x5f, 0xad, 0xfb, 0x9c, 0x1d, 0xeb, 0xa9, 0xf5, 0xfa, 0xc5, 0xe7, 0xd9, 0x78, 0xed, 0x43, 0x7d, 0x3e, 0xad, 0xa4, 0x10, 0xb8, 0xb8, 0x5c, 0x9d, 0x3b, 0x4b,
0xef, 0x2b, 0xd7, 0xba, 0xb8, 0x72, 0xad, 0x3f, 0x57, 0xae, 0xf5, 0xe3, 0xda, 0x2d, 0x5d, 0x5c, 0x7d, 0xc5, 0x2a, 0xe9, 0xe4, 0x96, 0xab, 0x94, 0x67, 0xbe, 0x5c, 0x65, 0x71, 0xd4, 0x0f, 0x60,
0xbb, 0xa5, 0xcb, 0x6b, 0xb7, 0xf4, 0xb9, 0x75, 0xf7, 0x37, 0xf9, 0x64, 0x0d, 0x7f, 0x9e, 0xff, 0x6d, 0x24, 0x63, 0xce, 0x7c, 0x52, 0x08, 0xbb, 0xf6, 0x5f, 0xa6, 0x73, 0x9b, 0xb3, 0xa7, 0x3d,
0x0d, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x45, 0x08, 0x76, 0xb8, 0x05, 0x00, 0x00, 0xd4, 0x9e, 0x3f, 0xf9, 0x79, 0x69, 0x6a, 0x17, 0x97, 0xa6, 0xf6, 0xfb, 0xd2, 0xd4, 0xbe, 0x5c,
0x99, 0x95, 0x8b, 0x2b, 0xb3, 0xf2, 0xeb, 0xca, 0xac, 0xbc, 0xef, 0xdc, 0xfc, 0xcb, 0x74, 0xb2,
0x86, 0x7f, 0x1e, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x95, 0x5b, 0xbc, 0xbe, 0x06, 0x00,
0x00,
} }
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) { func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
@ -1068,6 +1179,85 @@ func (m *PushSpaceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *PullSpaceRequest) 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 *PullSpaceRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PullSpaceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Id) > 0 {
i -= len(m.Id)
copy(dAtA[i:], m.Id)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.Id)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *PullSpaceResponse) 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 *PullSpaceResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PullSpaceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.AclPayloadId) > 0 {
i -= len(m.AclPayloadId)
copy(dAtA[i:], m.AclPayloadId)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.AclPayloadId)))
i--
dAtA[i] = 0x1a
}
if len(m.AclPayload) > 0 {
i -= len(m.AclPayload)
copy(dAtA[i:], m.AclPayload)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.AclPayload)))
i--
dAtA[i] = 0x12
}
if m.SpaceHeader != nil {
{
size, err := m.SpaceHeader.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintSpacesync(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *SpaceHeader) Marshal() (dAtA []byte, err error) { func (m *SpaceHeader) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
dAtA = make([]byte, size) dAtA = make([]byte, size)
@ -1353,6 +1543,40 @@ func (m *PushSpaceResponse) Size() (n int) {
return n return n
} }
func (m *PullSpaceRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Id)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
return n
}
func (m *PullSpaceResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.SpaceHeader != nil {
l = m.SpaceHeader.Size()
n += 1 + l + sovSpacesync(uint64(l))
}
l = len(m.AclPayload)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
l = len(m.AclPayloadId)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
return n
}
func (m *SpaceHeader) Size() (n int) { func (m *SpaceHeader) Size() (n int) {
if m == nil { if m == nil {
return 0 return 0
@ -2360,6 +2584,240 @@ func (m *PushSpaceResponse) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *PullSpaceRequest) 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 ErrIntOverflowSpacesync
}
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: PullSpaceRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PullSpaceRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Id = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthSpacesync
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PullSpaceResponse) 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 ErrIntOverflowSpacesync
}
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: PullSpaceResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PullSpaceResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SpaceHeader", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.SpaceHeader == nil {
m.SpaceHeader = &RawSpaceHeaderWithId{}
}
if err := m.SpaceHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AclPayload", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AclPayload = append(m.AclPayload[:0], dAtA[iNdEx:postIndex]...)
if m.AclPayload == nil {
m.AclPayload = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AclPayloadId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AclPayloadId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthSpacesync
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *SpaceHeader) Unmarshal(dAtA []byte) error { func (m *SpaceHeader) Unmarshal(dAtA []byte) error {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -42,6 +42,7 @@ type DRPCSpaceClient interface {
HeadSync(ctx context.Context, in *HeadSyncRequest) (*HeadSyncResponse, error) HeadSync(ctx context.Context, in *HeadSyncRequest) (*HeadSyncResponse, error)
PushSpace(ctx context.Context, in *PushSpaceRequest) (*PushSpaceResponse, error) PushSpace(ctx context.Context, in *PushSpaceRequest) (*PushSpaceResponse, error)
PullSpace(ctx context.Context, in *PullSpaceRequest) (*PullSpaceResponse, error)
Stream(ctx context.Context) (DRPCSpace_StreamClient, error) Stream(ctx context.Context) (DRPCSpace_StreamClient, error)
} }
@ -73,6 +74,15 @@ func (c *drpcSpaceClient) PushSpace(ctx context.Context, in *PushSpaceRequest) (
return out, nil return out, nil
} }
func (c *drpcSpaceClient) PullSpace(ctx context.Context, in *PullSpaceRequest) (*PullSpaceResponse, error) {
out := new(PullSpaceResponse)
err := c.cc.Invoke(ctx, "/anySpace.Space/PullSpace", drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
func (c *drpcSpaceClient) Stream(ctx context.Context) (DRPCSpace_StreamClient, error) { func (c *drpcSpaceClient) Stream(ctx context.Context) (DRPCSpace_StreamClient, error) {
stream, err := c.cc.NewStream(ctx, "/anySpace.Space/Stream", drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{}) stream, err := c.cc.NewStream(ctx, "/anySpace.Space/Stream", drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{})
if err != nil { if err != nil {
@ -111,6 +121,7 @@ func (x *drpcSpace_StreamClient) RecvMsg(m *ObjectSyncMessage) error {
type DRPCSpaceServer interface { type DRPCSpaceServer interface {
HeadSync(context.Context, *HeadSyncRequest) (*HeadSyncResponse, error) HeadSync(context.Context, *HeadSyncRequest) (*HeadSyncResponse, error)
PushSpace(context.Context, *PushSpaceRequest) (*PushSpaceResponse, error) PushSpace(context.Context, *PushSpaceRequest) (*PushSpaceResponse, error)
PullSpace(context.Context, *PullSpaceRequest) (*PullSpaceResponse, error)
Stream(DRPCSpace_StreamStream) error Stream(DRPCSpace_StreamStream) error
} }
@ -124,13 +135,17 @@ func (s *DRPCSpaceUnimplementedServer) PushSpace(context.Context, *PushSpaceRequ
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
} }
func (s *DRPCSpaceUnimplementedServer) PullSpace(context.Context, *PullSpaceRequest) (*PullSpaceResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
func (s *DRPCSpaceUnimplementedServer) Stream(DRPCSpace_StreamStream) error { func (s *DRPCSpaceUnimplementedServer) Stream(DRPCSpace_StreamStream) error {
return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
} }
type DRPCSpaceDescription struct{} type DRPCSpaceDescription struct{}
func (DRPCSpaceDescription) NumMethods() int { return 3 } func (DRPCSpaceDescription) NumMethods() int { return 4 }
func (DRPCSpaceDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) { func (DRPCSpaceDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n { switch n {
@ -153,6 +168,15 @@ func (DRPCSpaceDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver,
) )
}, DRPCSpaceServer.PushSpace, true }, DRPCSpaceServer.PushSpace, true
case 2: case 2:
return "/anySpace.Space/PullSpace", drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCSpaceServer).
PullSpace(
ctx,
in1.(*PullSpaceRequest),
)
}, DRPCSpaceServer.PullSpace, true
case 3:
return "/anySpace.Space/Stream", drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{}, return "/anySpace.Space/Stream", drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return nil, srv.(DRPCSpaceServer). return nil, srv.(DRPCSpaceServer).
@ -201,6 +225,22 @@ func (x *drpcSpace_PushSpaceStream) SendAndClose(m *PushSpaceResponse) error {
return x.CloseSend() return x.CloseSend()
} }
type DRPCSpace_PullSpaceStream interface {
drpc.Stream
SendAndClose(*PullSpaceResponse) error
}
type drpcSpace_PullSpaceStream struct {
drpc.Stream
}
func (x *drpcSpace_PullSpaceStream) SendAndClose(m *PullSpaceResponse) error {
if err := x.MsgSend(m, drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{}); err != nil {
return err
}
return x.CloseSend()
}
type DRPCSpace_StreamStream interface { type DRPCSpace_StreamStream interface {
drpc.Stream drpc.Stream
Send(*ObjectSyncMessage) error Send(*ObjectSyncMessage) error

View File

@ -162,18 +162,18 @@ func (mr *MockSpaceStorageMockRecorder) CreateTreeStorage(arg0 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTreeStorage", reflect.TypeOf((*MockSpaceStorage)(nil).CreateTreeStorage), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTreeStorage", reflect.TypeOf((*MockSpaceStorage)(nil).CreateTreeStorage), arg0)
} }
// ID mocks base method. // Id mocks base method.
func (m *MockSpaceStorage) ID() string { func (m *MockSpaceStorage) Id() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID") ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
return ret0 return ret0
} }
// ID indicates an expected call of ID. // Id indicates an expected call of Id.
func (mr *MockSpaceStorageMockRecorder) ID() *gomock.Call { func (mr *MockSpaceStorageMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockSpaceStorage)(nil).ID)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockSpaceStorage)(nil).Id))
} }
// SpaceHeader mocks base method. // SpaceHeader mocks base method.

View File

@ -6,7 +6,7 @@ import (
"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/commonspace/spacesyncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
) )
const CName = "commonspace.storage" const CName = "commonspace.storage"
@ -16,7 +16,7 @@ var ErrSpaceStorageMissing = errors.New("space storage missing")
type SpaceStorage interface { type SpaceStorage interface {
storage.Provider storage.Provider
ID() string Id() string
ACLStorage() (storage.ListStorage, error) ACLStorage() (storage.ListStorage, error)
SpaceHeader() (*spacesyncproto.RawSpaceHeaderWithId, error) SpaceHeader() (*spacesyncproto.RawSpaceHeaderWithId, error)
StoredIds() ([]string, error) StoredIds() ([]string, error)

View File

@ -0,0 +1,31 @@
package syncacl
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
)
type syncAclHandler struct {
acl list.ACLList
}
func (s *syncAclHandler) HandleMessage(ctx context.Context, senderId string, req *spacesyncproto.ObjectSyncMessage) (err error) {
aclMsg := &aclrecordproto.ACLSyncMessage{}
if err = aclMsg.Unmarshal(req.Payload); err != nil {
return
}
content := aclMsg.GetContent()
switch {
case content.GetAddRecords() != nil:
return s.handleAddRecords(ctx, senderId, content.GetAddRecords())
default:
return fmt.Errorf("unexpected aclSync message: %T", content.Value)
}
}
func (s *syncAclHandler) handleAddRecords(ctx context.Context, senderId string, addRecord *aclrecordproto.ACLAddRecords) (err error) {
return
}

View File

@ -5,9 +5,8 @@ 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/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
"github.com/libp2p/go-libp2p/core/sec"
"storj.io/drpc/drpcctx"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -190,7 +189,7 @@ func (s *streamPool) AddAndReadStreamAsync(stream spacesyncproto.SpaceStream) {
func (s *streamPool) AddAndReadStreamSync(stream spacesyncproto.SpaceStream) (err error) { func (s *streamPool) AddAndReadStreamSync(stream spacesyncproto.SpaceStream) (err error) {
s.Lock() s.Lock()
peerId, err := GetPeerIdFromStreamContext(stream.Context()) peerId, err := peer.CtxPeerId(stream.Context())
if err != nil { if err != nil {
s.Unlock() s.Unlock()
return return
@ -199,7 +198,7 @@ func (s *streamPool) AddAndReadStreamSync(stream spacesyncproto.SpaceStream) (er
s.peerStreams[peerId] = stream s.peerStreams[peerId] = stream
s.wg.Add(1) s.wg.Add(1)
s.Unlock() s.Unlock()
log.With("peerId", peerId).Debug("reading stream from peer")
return s.readPeerLoop(peerId, stream) return s.readPeerLoop(peerId, stream)
} }
@ -261,6 +260,7 @@ Loop:
limiter <- struct{}{} limiter <- struct{}{}
}() }()
} }
log.With("peerId", peerId).Debug("stopped reading stream from peer")
s.removePeer(peerId) s.removePeer(peerId)
return return
} }
@ -276,15 +276,6 @@ func (s *streamPool) removePeer(peerId string) (err error) {
return return
} }
func GetPeerIdFromStreamContext(ctx context.Context) (string, error) {
conn, ok := ctx.Value(drpcctx.TransportKey{}).(sec.SecureConn)
if !ok {
return "", fmt.Errorf("incorrect connection type in stream")
}
return conn.RemotePeer().String(), nil
}
func genStreamPoolKey(peerId, treeId string, counter uint64) string { func genStreamPoolKey(peerId, treeId string, counter uint64) string {
return fmt.Sprintf("%s.%s.%d", peerId, treeId, counter) return fmt.Sprintf("%s.%s.%d", peerId, treeId, counter)
} }

View File

@ -3,9 +3,9 @@ package syncservice
import ( import (
"context" "context"
"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/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpctest" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpctest"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"testing" "testing"
"time" "time"
@ -27,6 +27,10 @@ func (t *testServer) PushSpace(ctx context.Context, request *spacesyncproto.Push
panic("implement me") panic("implement me")
} }
func (t *testServer) PullSpace(ctx context.Context, request *spacesyncproto.PullSpaceRequest) (*spacesyncproto.PullSpaceResponse, error) {
panic("implement me")
}
func (t *testServer) Stream(stream spacesyncproto.DRPCSpace_StreamStream) error { func (t *testServer) Stream(stream spacesyncproto.DRPCSpace_StreamStream) error {
t.stream <- stream t.stream <- stream
return <-t.releaseStream return <-t.releaseStream
@ -49,24 +53,23 @@ type fixture struct {
clientStream spacesyncproto.DRPCSpace_StreamStream clientStream spacesyncproto.DRPCSpace_StreamStream
serverStream spacesyncproto.DRPCSpace_StreamStream serverStream spacesyncproto.DRPCSpace_StreamStream
pool *streamPool pool *streamPool
localId peer.ID clientId string
remoteId peer.ID serverId string
} }
func newFixture(t *testing.T, localId, remoteId peer.ID, handler MessageHandler) *fixture { func newFixture(t *testing.T, clientId, serverId string, handler MessageHandler) *fixture {
fx := &fixture{ fx := &fixture{
testServer: &testServer{}, testServer: &testServer{},
drpcTS: rpctest.NewTestServer(), drpcTS: rpctest.NewTestServer(),
localId: localId, clientId: clientId,
remoteId: remoteId, serverId: serverId,
} }
fx.testServer.stream = make(chan spacesyncproto.DRPCSpace_StreamStream, 1) fx.testServer.stream = make(chan spacesyncproto.DRPCSpace_StreamStream, 1)
require.NoError(t, spacesyncproto.DRPCRegisterSpace(fx.drpcTS.Mux, fx.testServer)) require.NoError(t, spacesyncproto.DRPCRegisterSpace(fx.drpcTS.Mux, fx.testServer))
clientWrapper := rpctest.NewSecConnWrapper(nil, nil, localId, remoteId) fx.client = spacesyncproto.NewDRPCSpaceClient(fx.drpcTS.Dial(peer.CtxWithPeerId(context.Background(), clientId)))
fx.client = spacesyncproto.NewDRPCSpaceClient(fx.drpcTS.DialWrapConn(nil, clientWrapper))
var err error var err error
fx.clientStream, err = fx.client.Stream(context.Background()) fx.clientStream, err = fx.client.Stream(peer.CtxWithPeerId(context.Background(), serverId))
require.NoError(t, err) require.NoError(t, err)
fx.serverStream = fx.testServer.waitStream(t) fx.serverStream = fx.testServer.waitStream(t)
fx.pool = newStreamPool(handler).(*streamPool) fx.pool = newStreamPool(handler).(*streamPool)
@ -83,14 +86,14 @@ func (fx *fixture) run(t *testing.T) chan error {
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
fx.pool.Lock() fx.pool.Lock()
require.Equal(t, fx.pool.peerStreams[fx.remoteId.String()], fx.clientStream) require.Equal(t, fx.pool.peerStreams[fx.serverId], fx.clientStream)
fx.pool.Unlock() fx.pool.Unlock()
return waitCh return waitCh
} }
func TestStreamPool_AddAndReadStreamAsync(t *testing.T) { func TestStreamPool_AddAndReadStreamAsync(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("client close", func(t *testing.T) { t.Run("client close", func(t *testing.T) {
fx := newFixture(t, "", remId, nil) fx := newFixture(t, "", remId, nil)
@ -101,7 +104,7 @@ func TestStreamPool_AddAndReadStreamAsync(t *testing.T) {
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
t.Run("server close", func(t *testing.T) { t.Run("server close", func(t *testing.T) {
fx := newFixture(t, "", remId, nil) fx := newFixture(t, "", remId, nil)
@ -112,12 +115,12 @@ func TestStreamPool_AddAndReadStreamAsync(t *testing.T) {
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
} }
func TestStreamPool_Close(t *testing.T) { func TestStreamPool_Close(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("client close", func(t *testing.T) { t.Run("client close", func(t *testing.T) {
fx := newFixture(t, "", remId, nil) fx := newFixture(t, "", remId, nil)
@ -156,7 +159,7 @@ func TestStreamPool_Close(t *testing.T) {
} }
func TestStreamPool_ReceiveMessage(t *testing.T) { func TestStreamPool_ReceiveMessage(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("pool receive message from server", func(t *testing.T) { t.Run("pool receive message from server", func(t *testing.T) {
objectId := "objectId" objectId := "objectId"
msg := &spacesyncproto.ObjectSyncMessage{ msg := &spacesyncproto.ObjectSyncMessage{
@ -178,23 +181,23 @@ func TestStreamPool_ReceiveMessage(t *testing.T) {
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
} }
func TestStreamPool_HasActiveStream(t *testing.T) { func TestStreamPool_HasActiveStream(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("pool has active stream", func(t *testing.T) { t.Run("pool has active stream", func(t *testing.T) {
fx := newFixture(t, "", remId, nil) fx := newFixture(t, "", remId, nil)
waitCh := fx.run(t) waitCh := fx.run(t)
require.True(t, fx.pool.HasActiveStream(remId.String())) require.True(t, fx.pool.HasActiveStream(remId))
err := fx.clientStream.Close() err := fx.clientStream.Close()
require.NoError(t, err) require.NoError(t, err)
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
t.Run("pool has no active stream", func(t *testing.T) { t.Run("pool has no active stream", func(t *testing.T) {
fx := newFixture(t, "", remId, nil) fx := newFixture(t, "", remId, nil)
@ -203,13 +206,13 @@ func TestStreamPool_HasActiveStream(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.False(t, fx.pool.HasActiveStream(remId.String())) require.False(t, fx.pool.HasActiveStream(remId))
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
} }
func TestStreamPool_SendAsync(t *testing.T) { func TestStreamPool_SendAsync(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("pool send async to server", func(t *testing.T) { t.Run("pool send async to server", func(t *testing.T) {
objectId := "objectId" objectId := "objectId"
msg := &spacesyncproto.ObjectSyncMessage{ msg := &spacesyncproto.ObjectSyncMessage{
@ -225,7 +228,7 @@ func TestStreamPool_SendAsync(t *testing.T) {
}() }()
waitCh := fx.run(t) waitCh := fx.run(t)
err := fx.pool.SendAsync([]string{remId.String()}, msg) err := fx.pool.SendAsync([]string{remId}, msg)
require.NoError(t, err) require.NoError(t, err)
<-recvChan <-recvChan
err = fx.clientStream.Close() err = fx.clientStream.Close()
@ -233,12 +236,12 @@ func TestStreamPool_SendAsync(t *testing.T) {
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
} }
func TestStreamPool_SendSync(t *testing.T) { func TestStreamPool_SendSync(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("pool send sync to server", func(t *testing.T) { t.Run("pool send sync to server", func(t *testing.T) {
objectId := "objectId" objectId := "objectId"
payload := []byte("payload") payload := []byte("payload")
@ -256,7 +259,7 @@ func TestStreamPool_SendSync(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
}() }()
waitCh := fx.run(t) waitCh := fx.run(t)
res, err := fx.pool.SendSync(remId.String(), msg) res, err := fx.pool.SendSync(remId, msg)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, payload, res.Payload) require.Equal(t, payload, res.Payload)
err = fx.clientStream.Close() err = fx.clientStream.Close()
@ -264,7 +267,7 @@ func TestStreamPool_SendSync(t *testing.T) {
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
t.Run("pool send sync timeout", func(t *testing.T) { t.Run("pool send sync timeout", func(t *testing.T) {
@ -281,19 +284,19 @@ func TestStreamPool_SendSync(t *testing.T) {
require.NotEmpty(t, message.ReplyId) require.NotEmpty(t, message.ReplyId)
}() }()
waitCh := fx.run(t) waitCh := fx.run(t)
_, err := fx.pool.SendSync(remId.String(), msg) _, err := fx.pool.SendSync(remId, msg)
require.Equal(t, ErrSyncTimeout, err) require.Equal(t, ErrSyncTimeout, err)
err = fx.clientStream.Close() err = fx.clientStream.Close()
require.NoError(t, err) require.NoError(t, err)
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
} }
func TestStreamPool_BroadcastAsync(t *testing.T) { func TestStreamPool_BroadcastAsync(t *testing.T) {
remId := peer.ID("remoteId") remId := "remoteId"
t.Run("pool broadcast async to server", func(t *testing.T) { t.Run("pool broadcast async to server", func(t *testing.T) {
objectId := "objectId" objectId := "objectId"
msg := &spacesyncproto.ObjectSyncMessage{ msg := &spacesyncproto.ObjectSyncMessage{
@ -317,6 +320,6 @@ func TestStreamPool_BroadcastAsync(t *testing.T) {
err = <-waitCh err = <-waitCh
require.Error(t, err) require.Error(t, err)
require.Nil(t, fx.pool.peerStreams[remId.String()]) require.Nil(t, fx.pool.peerStreams[remId])
}) })
} }

View File

@ -97,11 +97,11 @@ func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
if err != nil { if err != nil {
return return
} }
for _, peer := range respPeers { for _, p := range respPeers {
if s.streamPool.HasActiveStream(peer.Id()) { if s.streamPool.HasActiveStream(p.Id()) {
continue continue
} }
stream, err := s.clientFactory.Client(peer).Stream(ctx) stream, err := s.clientFactory.Client(p).Stream(ctx)
if err != nil { if err != nil {
err = rpcerr.Unwrap(err) err = rpcerr.Unwrap(err)
log.With("spaceId", s.spaceId).Errorf("failed to open stream: %v", err) log.With("spaceId", s.spaceId).Errorf("failed to open stream: %v", err)

View File

@ -10,6 +10,7 @@ import (
"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/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/net/peer"
"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/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"
@ -111,8 +112,7 @@ func CreateSyncTree(ctx context.Context, deps CreateDeps) (t tree.ObjectTree, er
func BuildSyncTreeOrGetRemote(ctx context.Context, id string, deps BuildDeps) (t tree.ObjectTree, err error) { func BuildSyncTreeOrGetRemote(ctx context.Context, id string, deps BuildDeps) (t tree.ObjectTree, err error) {
getTreeRemote := func() (msg *treechangeproto.TreeSyncMessage, err error) { getTreeRemote := func() (msg *treechangeproto.TreeSyncMessage, err error) {
// TODO: add empty context handling (when this is not happening due to head update) peerId, err := peer.CtxPeerId(ctx)
peerId, err := syncservice.GetPeerIdFromStreamContext(ctx)
if err != nil { if err != nil {
return return
} }

View File

@ -2,6 +2,7 @@ package config
type Account struct { type Account struct {
PeerId string `yaml:"peerId"` PeerId string `yaml:"peerId"`
PeerKey string `yaml:"peerKey"`
SigningKey string `yaml:"signingKey"` SigningKey string `yaml:"signingKey"`
EncryptionKey string `yaml:"encryptionKey"` EncryptionKey string `yaml:"encryptionKey"`
} }

View File

@ -0,0 +1,32 @@
package peer
import (
"context"
"errors"
"github.com/libp2p/go-libp2p/core/sec"
"storj.io/drpc/drpcctx"
)
type contextKey uint
const (
contextKeyPeerId contextKey = iota
)
var ErrPeerIdNotFoundInContext = errors.New("peer id not found in context")
// CtxPeerId first tries to get peer id under our own key, but if it is not found tries to get through DRPC key
func CtxPeerId(ctx context.Context) (string, error) {
if peerId, ok := ctx.Value(contextKeyPeerId).(string); ok {
return peerId, nil
}
if conn, ok := ctx.Value(drpcctx.TransportKey{}).(sec.SecureConn); ok {
return conn.RemotePeer().String(), nil
}
return "", ErrPeerIdNotFoundInContext
}
// CtxWithPeerId sets peer id in the context
func CtxWithPeerId(ctx context.Context, peerId string) context.Context {
return context.WithValue(ctx, contextKeyPeerId, peerId)
}

View File

@ -36,7 +36,7 @@ func (t *TestPool) Get(ctx context.Context, id string) (peer.Peer, error) {
if t.ts == nil { if t.ts == nil {
return nil, ErrCantConnect return nil, ErrCantConnect
} }
return &testPeer{id: id, Conn: t.ts.Dial()}, nil return &testPeer{id: id, Conn: t.ts.Dial(ctx)}, nil
} }
func (t *TestPool) Dial(ctx context.Context, id string) (peer.Peer, error) { func (t *TestPool) Dial(ctx context.Context, id string) (peer.Peer, error) {
@ -45,7 +45,7 @@ func (t *TestPool) Dial(ctx context.Context, id string) (peer.Peer, error) {
if t.ts == nil { if t.ts == nil {
return nil, ErrCantConnect return nil, ErrCantConnect
} }
return &testPeer{id: id, Conn: t.ts.Dial()}, nil return &testPeer{id: id, Conn: t.ts.Dial(ctx)}, nil
} }
func (t *TestPool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { func (t *TestPool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) {
@ -54,7 +54,7 @@ func (t *TestPool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, e
if t.ts == nil { if t.ts == nil {
return nil, ErrCantConnect return nil, ErrCantConnect
} }
return &testPeer{id: peerIds[rand.Intn(len(peerIds))], Conn: t.ts.Dial()}, nil return &testPeer{id: peerIds[rand.Intn(len(peerIds))], Conn: t.ts.Dial(ctx)}, nil
} }
func (t *TestPool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { func (t *TestPool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) {
@ -63,7 +63,7 @@ func (t *TestPool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer,
if t.ts == nil { if t.ts == nil {
return nil, ErrCantConnect return nil, ErrCantConnect
} }
return &testPeer{id: peerIds[rand.Intn(len(peerIds))], Conn: t.ts.Dial()}, nil return &testPeer{id: peerIds[rand.Intn(len(peerIds))], Conn: t.ts.Dial(ctx)}, nil
} }
func (t *TestPool) Init(a *app.App) (err error) { func (t *TestPool) Init(a *app.App) (err error) {

View File

@ -2,8 +2,6 @@ package rpctest
import ( import (
"context" "context"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"net" "net"
"storj.io/drpc" "storj.io/drpc"
"storj.io/drpc/drpcconn" "storj.io/drpc/drpcconn"
@ -11,48 +9,6 @@ import (
"storj.io/drpc/drpcserver" "storj.io/drpc/drpcserver"
) )
type SecConnMock struct {
net.Conn
localPrivKey crypto.PrivKey
remotePubKey crypto.PubKey
localId peer.ID
remoteId peer.ID
}
func (s *SecConnMock) LocalPeer() peer.ID {
return s.localId
}
func (s *SecConnMock) LocalPrivateKey() crypto.PrivKey {
return s.localPrivKey
}
func (s *SecConnMock) RemotePeer() peer.ID {
return s.remoteId
}
func (s *SecConnMock) RemotePublicKey() crypto.PubKey {
return s.remotePubKey
}
type ConnWrapper func(conn net.Conn) net.Conn
func NewSecConnWrapper(
localPrivKey crypto.PrivKey,
remotePubKey crypto.PubKey,
localId peer.ID,
remoteId peer.ID) ConnWrapper {
return func(conn net.Conn) net.Conn {
return &SecConnMock{
Conn: conn,
localPrivKey: localPrivKey,
remotePubKey: remotePubKey,
localId: localId,
remoteId: remoteId,
}
}
}
func NewTestServer() *TesServer { func NewTestServer() *TesServer {
ts := &TesServer{ ts := &TesServer{
Mux: drpcmux.New(), Mux: drpcmux.New(),
@ -66,18 +22,8 @@ type TesServer struct {
*drpcserver.Server *drpcserver.Server
} }
func (ts *TesServer) Dial() drpc.Conn { func (ts *TesServer) Dial(ctx context.Context) drpc.Conn {
return ts.DialWrapConn(nil, nil)
}
func (ts *TesServer) DialWrapConn(serverWrapper ConnWrapper, clientWrapper ConnWrapper) drpc.Conn {
sc, cc := net.Pipe() sc, cc := net.Pipe()
if serverWrapper != nil { go ts.Server.ServeOne(ctx, sc)
sc = serverWrapper(sc)
}
if clientWrapper != nil {
cc = clientWrapper(cc)
}
go ts.Server.ServeOne(context.Background(), sc)
return drpcconn.New(cc) return drpcconn.New(cc)
} }

View File

@ -1,28 +0,0 @@
package secure
import (
"context"
"errors"
"github.com/libp2p/go-libp2p/core/sec"
)
var (
ErrSecureConnNotFoundInContext = errors.New("secure connection not found in context")
)
type contextKey uint
const (
contextKeySecureConn contextKey = iota
)
func CtxSecureConn(ctx context.Context) (sec.SecureConn, error) {
if conn, ok := ctx.Value(contextKeySecureConn).(sec.SecureConn); ok {
return conn, nil
}
return nil, ErrSecureConnNotFoundInContext
}
func ctxWithSecureConn(ctx context.Context, conn sec.SecureConn) context.Context {
return context.WithValue(ctx, contextKeySecureConn, conn)
}

View File

@ -2,6 +2,7 @@ package secure
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer"
"github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto"
libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls" libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls"
"net" "net"
@ -45,6 +46,6 @@ func (p *tlsListener) upgradeConn(ctx context.Context, conn net.Conn) (context.C
if err != nil { if err != nil {
return nil, nil, HandshakeError(err) return nil, nil, HandshakeError(err)
} }
ctx = ctxWithSecureConn(ctx, secure) ctx = peer.CtxWithPeerId(ctx, secure.RemotePeer().String())
return ctx, secure, nil return ctx, secure, nil
} }

View File

@ -36,7 +36,7 @@ type service struct {
func (s *service) Init(a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
account := a.MustComponent(config.CName).(commonaccount.ConfigGetter).GetAccount() account := a.MustComponent(config.CName).(commonaccount.ConfigGetter).GetAccount()
pkb, err := keys.DecodeBytesFromString(account.SigningKey) pkb, err := keys.DecodeBytesFromString(account.PeerKey)
if err != nil { if err != nil {
return return
} }

View File

@ -21,19 +21,19 @@ func NewConfConnector(conf Configuration, pool pool.Pool) ConfConnector {
} }
func (s *confConnector) GetResponsiblePeers(ctx context.Context, spaceId string) ([]peer.Peer, error) { func (s *confConnector) GetResponsiblePeers(ctx context.Context, spaceId string) ([]peer.Peer, error) {
return s.dialOrConnect(ctx, spaceId, s.pool.Get, s.pool.GetOneOf) return s.connectOneOrMany(ctx, spaceId, s.pool.Get, s.pool.GetOneOf)
} }
func (s *confConnector) DialResponsiblePeers(ctx context.Context, spaceId string) ([]peer.Peer, error) { func (s *confConnector) DialResponsiblePeers(ctx context.Context, spaceId string) ([]peer.Peer, error) {
return s.dialOrConnect(ctx, spaceId, s.pool.Dial, s.pool.DialOneOf) return s.connectOneOrMany(ctx, spaceId, s.pool.Dial, s.pool.DialOneOf)
} }
func (s *confConnector) dialOrConnect( func (s *confConnector) connectOneOrMany(
ctx context.Context, spaceId string, ctx context.Context, spaceId string,
connectOne func(context.Context, string) (peer.Peer, error), connectOne func(context.Context, string) (peer.Peer, error),
connectOneOf func(context.Context, []string) (peer.Peer, error)) (peers []peer.Peer, err error) { connectOneOf func(context.Context, []string) (peer.Peer, error)) (peers []peer.Peer, err error) {
allNodes := s.conf.NodeIds(spaceId) allNodes := s.conf.NodeIds(spaceId)
if !s.conf.IsResponsible(spaceId) { if s.conf.IsResponsible(spaceId) {
for _, id := range allNodes { for _, id := range allNodes {
var p peer.Peer var p peer.Peer
p, err = connectOne(ctx, id) p, err = connectOne(ctx, id)

View File

@ -7,6 +7,7 @@ import (
type AccountData struct { // TODO: create a convenient constructor for this type AccountData struct { // TODO: create a convenient constructor for this
Identity []byte // public key Identity []byte // public key
PeerKey signingkey.PrivKey
SignKey signingkey.PrivKey SignKey signingkey.PrivKey
EncKey encryptionkey.PrivKey EncKey encryptionkey.PrivKey
} }

File diff suppressed because it is too large Load Diff

View File

@ -3,106 +3,116 @@ package aclrecord;
option go_package = "pkg/acl/aclrecordproto"; option go_package = "pkg/acl/aclrecordproto";
message RawACLRecord { message RawACLRecord {
bytes payload = 1; bytes payload = 1;
bytes signature = 2; bytes signature = 2;
bytes acceptorIdentity = 3;
bytes acceptorSignature = 4;
} }
message RawACLRecordWithId { message RawACLRecordWithId {
bytes payload = 1; bytes payload = 1;
string id = 2; string id = 2;
} }
message ACLRecord { message ACLRecord {
string prevId = 1; string prevId = 1;
bytes identity = 2; bytes identity = 2;
bytes data = 3; bytes data = 3;
uint64 currentReadKeyHash = 4; uint64 currentReadKeyHash = 4;
int64 timestamp = 5; int64 timestamp = 5;
} }
message ACLRoot { message ACLRoot {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
string spaceId = 3; string spaceId = 3;
bytes encryptedReadKey = 4; bytes encryptedReadKey = 4;
string derivationScheme = 5; string derivationScheme = 5;
uint64 currentReadKeyHash = 6; uint64 currentReadKeyHash = 6;
int64 timestamp = 7; int64 timestamp = 7;
} }
message ACLContentValue { message ACLContentValue {
oneof value { oneof value {
ACLUserAdd userAdd = 1; ACLUserAdd userAdd = 1;
ACLUserRemove userRemove = 2; ACLUserRemove userRemove = 2;
ACLUserPermissionChange userPermissionChange = 3; ACLUserPermissionChange userPermissionChange = 3;
ACLUserInvite userInvite = 4; ACLUserInvite userInvite = 4;
ACLUserJoin userJoin = 5; ACLUserJoin userJoin = 5;
} }
} }
message ACLData { message ACLData {
repeated ACLContentValue aclContent = 1; repeated ACLContentValue aclContent = 1;
} }
message ACLState { message ACLState {
repeated uint64 readKeyHashes = 1; repeated uint64 readKeyHashes = 1;
repeated ACLUserState userStates = 2; repeated ACLUserState userStates = 2;
map<string, ACLUserInvite> invites = 3; map<string, ACLUserInvite> invites = 3;
} }
message ACLUserState { message ACLUserState {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
ACLUserPermissions permissions = 3; ACLUserPermissions permissions = 3;
} }
message ACLUserAdd { message ACLUserAdd {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
repeated bytes encryptedReadKeys = 3; repeated bytes encryptedReadKeys = 3;
ACLUserPermissions permissions = 4; ACLUserPermissions permissions = 4;
} }
// accept key, encrypt key, invite id
// GetSpace(id) -> ... (space header + acl root) -> diff
// Join(ACLJoinRecord) -> Ok
message ACLUserInvite { message ACLUserInvite {
bytes acceptPublicKey = 1; bytes acceptPublicKey = 1;
// TODO: change to read key uint64 encryptSymKeyHash = 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;
} }
message ACLUserJoin { message ACLUserJoin {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
bytes acceptSignature = 3; bytes acceptSignature = 3;
string inviteId = 4; bytes acceptPubKey = 4;
repeated bytes encryptedReadKeys = 5; repeated bytes encryptedReadKeys = 5;
} }
message ACLUserRemove { message ACLUserRemove {
bytes identity = 1; bytes identity = 1;
repeated ACLReadKeyReplace readKeyReplaces = 3; repeated ACLReadKeyReplace readKeyReplaces = 2;
} }
message ACLReadKeyReplace { message ACLReadKeyReplace {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
bytes encryptedReadKey = 3; bytes encryptedReadKey = 3;
} }
message ACLUserPermissionChange { message ACLUserPermissionChange {
bytes identity = 1; bytes identity = 1;
ACLUserPermissions permissions = 2; ACLUserPermissions permissions = 2;
} }
enum ACLUserPermissions { enum ACLUserPermissions {
Admin = 0; Admin = 0;
Writer = 1; Writer = 1;
Reader = 2; Reader = 2;
} }
message ACLSyncMessage {
ACLSyncContentValue content = 2;
}
// ACLSyncContentValue provides different types for acl sync
message ACLSyncContentValue {
oneof value {
ACLAddRecords addRecords = 1;
}
}
message ACLAddRecords {
repeated RawACLRecordWithId records = 1;
}

View File

@ -4,11 +4,16 @@ import (
"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/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"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/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"time"
) )
// remove interface
type ACLRecordBuilder interface { type ACLRecordBuilder interface {
ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error) ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error)
BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *ACLState) (rec *aclrecordproto.RawACLRecord, err error)
} }
type aclRecordBuilder struct { type aclRecordBuilder struct {
@ -23,6 +28,83 @@ func newACLRecordBuilder(id string, keychain *common.Keychain) ACLRecordBuilder
} }
} }
func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *ACLState) (rec *aclrecordproto.RawACLRecord, err error) {
acceptPrivKey, err := signingkey.NewSigningEd25519PrivKeyFromBytes(acceptPrivKeyBytes)
if err != nil {
return
}
acceptPubKeyBytes, err := acceptPrivKey.GetPublic().Raw()
if err != nil {
return
}
encSymKey, err := symmetric.FromBytes(encSymKeyBytes)
if err != nil {
return
}
invite, err := state.Invite(acceptPubKeyBytes)
if err != nil {
return
}
encPrivKey, signPrivKey := state.UserKeys()
var symKeys [][]byte
for _, rk := range invite.EncryptedReadKeys {
dec, err := encSymKey.Decrypt(rk)
if err != nil {
return nil, err
}
newEnc, err := encPrivKey.GetPublic().Encrypt(dec)
if err != nil {
return nil, err
}
symKeys = append(symKeys, newEnc)
}
idSignature, err := acceptPrivKey.Sign(state.Identity())
if err != nil {
return
}
encPubKeyBytes, err := encPrivKey.GetPublic().Raw()
if err != nil {
return
}
userJoin := &aclrecordproto.ACLUserJoin{
Identity: state.Identity(),
EncryptionKey: encPubKeyBytes,
AcceptSignature: idSignature,
AcceptPubKey: acceptPubKeyBytes,
EncryptedReadKeys: symKeys,
}
aclData := &aclrecordproto.ACLData{AclContent: []*aclrecordproto.ACLContentValue{
{Value: &aclrecordproto.ACLContentValue_UserJoin{UserJoin: userJoin}},
}}
marshalledJoin, err := aclData.Marshal()
if err != nil {
return
}
aclRecord := &aclrecordproto.ACLRecord{
PrevId: state.LastRecordId(),
Identity: state.Identity(),
Data: marshalledJoin,
CurrentReadKeyHash: state.CurrentReadKeyHash(),
Timestamp: time.Now().UnixNano(),
}
marshalledRecord, err := aclRecord.Marshal()
if err != nil {
return
}
recSignature, err := signPrivKey.Sign(marshalledRecord)
if err != nil {
return
}
rec = &aclrecordproto.RawACLRecord{
Payload: marshalledRecord,
Signature: recSignature,
}
return
}
func (a *aclRecordBuilder) ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error) { func (a *aclRecordBuilder) ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error) {
rawRec := &aclrecordproto.RawACLRecord{} rawRec := &aclrecordproto.RawACLRecord{}
err = proto.Unmarshal(rawIdRecord.Payload, rawRec) err = proto.Unmarshal(rawIdRecord.Payload, rawRec)

View File

@ -0,0 +1,50 @@
package list
import (
account "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/account"
"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/testutils/acllistbuilder"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
"github.com/stretchr/testify/require"
"testing"
)
func TestAclRecordBuilder_BuildUserJoin(t *testing.T) {
st, err := acllistbuilder.NewListStorageWithTestName("userjoinexample.yml")
require.NoError(t, err, "building storage should not result in error")
keychain := st.(*acllistbuilder.ACLListStorageBuilder).GetKeychain()
identity := keychain.GeneratedIdentities["D"]
signPrivKey := keychain.SigningKeysByYAMLName["D"]
encPrivKey := keychain.EncryptionKeysByYAMLName["D"]
acc := &account.AccountData{
Identity: []byte(identity),
SignKey: signPrivKey,
EncKey: encPrivKey,
}
aclList, err := BuildACLListWithIdentity(acc, st)
require.NoError(t, err, "building acl list should be without error")
recordBuilder := newACLRecordBuilder(aclList.ID(), common.NewKeychain())
rk, err := keychain.GetKey("key.Read.EncKey").(*acllistbuilder.SymKey).Key.Raw()
require.NoError(t, err)
privKey, err := keychain.GetKey("key.Sign.Onetime1").(signingkey.PrivKey).Raw()
require.NoError(t, err)
userJoin, err := recordBuilder.BuildUserJoin(privKey, rk, aclList.ACLState())
require.NoError(t, err)
marshalledJoin, err := userJoin.Marshal()
require.NoError(t, err)
id, err := cid.NewCIDFromBytes(marshalledJoin)
require.NoError(t, err)
rawRec := &aclrecordproto.RawACLRecordWithId{
Payload: marshalledJoin,
Id: id,
}
res, err := aclList.AddRawRecord(rawRec)
require.True(t, res)
require.NoError(t, err)
require.Equal(t, aclrecordproto.ACLUserPermissions_Writer, aclList.ACLState().UserStates()[identity].Permissions)
}

View File

@ -7,6 +7,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/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"
"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"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
@ -23,10 +24,13 @@ var ErrUserRemoved = errors.New("user was removed from the document")
var ErrDocumentForbidden = errors.New("your user was forbidden access to the document") var ErrDocumentForbidden = errors.New("your user was forbidden access to the document")
var ErrUserAlreadyExists = errors.New("user already exists") var ErrUserAlreadyExists = errors.New("user already exists")
var ErrNoSuchRecord = errors.New("no such record") var ErrNoSuchRecord = errors.New("no such record")
var ErrNoSuchInvite = errors.New("no such invite")
var ErrOldInvite = errors.New("invite is too old")
var ErrInsufficientPermissions = errors.New("insufficient permissions") var ErrInsufficientPermissions = errors.New("insufficient permissions")
var ErrNoReadKey = errors.New("acl state doesn't have a read key") var ErrNoReadKey = errors.New("acl state doesn't have a read key")
var ErrInvalidSignature = errors.New("signature is invalid") var ErrInvalidSignature = errors.New("signature is invalid")
var ErrIncorrectRoot = errors.New("incorrect root") var ErrIncorrectRoot = errors.New("incorrect root")
var ErrIncorrectRecordSequence = errors.New("incorrect prev id of a record")
type UserPermissionPair struct { type UserPermissionPair struct {
Identity string Identity string
@ -41,9 +45,11 @@ type ACLState struct {
userInvites map[string]*aclrecordproto.ACLUserInvite userInvites map[string]*aclrecordproto.ACLUserInvite
encryptionKey encryptionkey.PrivKey encryptionKey encryptionkey.PrivKey
signingKey signingkey.PrivKey signingKey signingkey.PrivKey
totalReadKeys int
identity string identity string
permissionsAtRecord map[string][]UserPermissionPair permissionsAtRecord map[string][]UserPermissionPair
lastRecordId string
keychain *common.Keychain keychain *common.Keychain
} }
@ -110,15 +116,28 @@ 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) {
defer func() {
if err == nil {
st.lastRecordId = record.Id
}
}()
if st.lastRecordId != record.PrevId {
err = ErrIncorrectRecordSequence
return
}
if record.Id == st.id { if record.Id == st.id {
root, ok := record.Model.(*aclrecordproto.ACLRoot) root, ok := record.Model.(*aclrecordproto.ACLRoot)
if !ok { if !ok {
return ErrIncorrectRoot return ErrIncorrectRoot
} }
err = st.applyRoot(root)
if err != nil {
return
}
st.permissionsAtRecord[record.Id] = []UserPermissionPair{ st.permissionsAtRecord[record.Id] = []UserPermissionPair{
{Identity: string(root.Identity), Permission: aclrecordproto.ACLUserPermissions_Admin}, {Identity: string(root.Identity), Permission: aclrecordproto.ACLUserPermissions_Admin},
} }
return st.applyRoot(root) return
} }
aclData := &aclrecordproto.ACLData{} aclData := &aclrecordproto.ACLData{}
@ -148,7 +167,7 @@ func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
} }
st.permissionsAtRecord[record.Id] = permissions st.permissionsAtRecord[record.Id] = permissions
return nil return
} }
func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) { func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
@ -165,20 +184,27 @@ func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
EncryptionKey: root.EncryptionKey, EncryptionKey: root.EncryptionKey,
Permissions: aclrecordproto.ACLUserPermissions_Admin, Permissions: aclrecordproto.ACLUserPermissions_Admin,
} }
st.currentReadKeyHash = root.CurrentReadKeyHash
st.userStates[string(root.Identity)] = userState st.userStates[string(root.Identity)] = userState
st.totalReadKeys++
return return
} }
func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.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 encPrivKey []byte
encPubKey, err = st.encryptionKey.GetPublic().Raw() encPrivKey, err = st.encryptionKey.Raw()
if err != nil {
return
}
var signPrivKey []byte
signPrivKey, err = st.signingKey.Raw()
if err != nil { if err != nil {
return return
} }
readKey, err = aclrecordproto.ACLReadKeyDerive([]byte(st.identity), encPubKey) readKey, err = aclrecordproto.ACLReadKeyDerive(signPrivKey, encPrivKey)
if err != nil { if err != nil {
return return
} }
@ -197,8 +223,8 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.ACLRoot) (err error
if hasher.Sum64() != root.CurrentReadKeyHash { if hasher.Sum64() != root.CurrentReadKeyHash {
return ErrIncorrectRoot return ErrIncorrectRoot
} }
st.currentReadKeyHash = root.CurrentReadKeyHash
st.userReadKeys[root.CurrentReadKeyHash] = readKey st.userReadKeys[root.CurrentReadKeyHash] = readKey
return return
} }
@ -207,7 +233,10 @@ func (st *ACLState) applyChangeData(changeData *aclrecordproto.ACLData, hash uin
if err != nil { if err != nil {
return return
} }
st.currentReadKeyHash = hash if hash != st.currentReadKeyHash {
st.totalReadKeys++
st.currentReadKeyHash = hash
}
}() }()
if !st.isUserJoin(changeData) { if !st.isUserJoin(changeData) {
@ -262,14 +291,14 @@ func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto.ACLUserPermissi
} }
func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error { func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error {
st.userInvites[ch.InviteId] = ch st.userInvites[string(ch.AcceptPublicKey)] = ch
return nil return nil
} }
func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error { func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
invite, exists := st.userInvites[ch.InviteId] invite, exists := st.userInvites[string(ch.AcceptPubKey)]
if !exists { if !exists {
return fmt.Errorf("no such invite with id %s", ch.InviteId) return fmt.Errorf("no such invite with such public key %s", keys.EncodeBytesToString(ch.AcceptPubKey))
} }
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
@ -284,7 +313,7 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
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.(signingkey.PubKey).Verify(ch.Identity, signature) res, err := verificationKey.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)
} }
@ -361,8 +390,8 @@ func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error {
return ErrFailedToDecrypt return ErrFailedToDecrypt
} }
st.currentReadKeyHash = hash st.userReadKeys[hash] = key
st.userReadKeys[st.currentReadKeyHash] = key break
} }
} }
return nil return nil
@ -404,6 +433,30 @@ func (st *ACLState) isUserAdd(data *aclrecordproto.ACLData, identity []byte) boo
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]*aclrecordproto.ACLUserState { func (st *ACLState) UserStates() map[string]*aclrecordproto.ACLUserState {
return st.userStates return st.userStates
} }
func (st *ACLState) Invite(acceptPubKey []byte) (invite *aclrecordproto.ACLUserInvite, err error) {
invite, exists := st.userInvites[string(acceptPubKey)]
if !exists {
err = ErrNoSuchInvite
return
}
if len(invite.EncryptedReadKeys) != st.totalReadKeys {
err = ErrOldInvite
}
return
}
func (st *ACLState) UserKeys() (encKey encryptionkey.PrivKey, signKey signingkey.PrivKey) {
return st.encryptionKey, st.signingKey
}
func (st *ACLState) Identity() []byte {
return []byte(st.identity)
}
func (st *ACLState) LastRecordId() string {
return st.lastRecordId
}

View File

@ -45,3 +45,13 @@ func (sb *aclStateBuilder) Build(records []*ACLRecord) (state *ACLState, err err
return state, err return state, err
} }
func (sb *aclStateBuilder) Append(state *ACLState, records []*ACLRecord) (err error) {
for _, rec := range records {
err = state.applyRecord(rec)
if err != nil {
return
}
}
return
}

View File

@ -25,7 +25,7 @@ type RWLocker interface {
type ACLList interface { type ACLList interface {
RWLocker RWLocker
ID() string ID() string
Root() *aclrecordproto.ACLRoot Root() *aclrecordproto.RawACLRecordWithId
Records() []*ACLRecord Records() []*ACLRecord
ACLState() *ACLState ACLState() *ACLState
IsAfter(first string, second string) (bool, error) IsAfter(first string, second string) (bool, error)
@ -33,44 +33,37 @@ type ACLList interface {
Get(id string) (*ACLRecord, error) Get(id string) (*ACLRecord, error)
Iterate(iterFunc IterFunc) Iterate(iterFunc IterFunc)
IterateFrom(startId string, iterFunc IterFunc) IterateFrom(startId string, iterFunc IterFunc)
AddRawRecord(rawRec *aclrecordproto.RawACLRecordWithId) (added bool, err error)
Close() (err error) Close() (err error)
} }
type aclList struct { type aclList struct {
root *aclrecordproto.ACLRoot root *aclrecordproto.RawACLRecordWithId
records []*ACLRecord records []*ACLRecord
indexes map[string]int indexes map[string]int
id string id string
builder *aclStateBuilder stateBuilder *aclStateBuilder
aclState *ACLState recordBuilder ACLRecordBuilder
keychain *common.Keychain aclState *ACLState
keychain *common.Keychain
storage storage.ListStorage
sync.RWMutex sync.RWMutex
} }
func BuildACLListWithIdentity(acc *account.AccountData, storage storage.ListStorage) (ACLList, error) { func BuildACLListWithIdentity(acc *account.AccountData, storage storage.ListStorage) (ACLList, error) {
id := storage.ID()
builder := newACLStateBuilderWithIdentity(acc) builder := newACLStateBuilderWithIdentity(acc)
return build(id, builder, newACLRecordBuilder(id, common.NewKeychain()), storage) return build(storage.Id(), builder, newACLRecordBuilder(storage.Id(), common.NewKeychain()), storage)
} }
func BuildACLList(storage storage.ListStorage) (ACLList, error) { func BuildACLList(storage storage.ListStorage) (ACLList, error) {
id := storage.ID() return build(storage.Id(), newACLStateBuilder(), newACLRecordBuilder(storage.Id(), common.NewKeychain()), storage)
return build(id, newACLStateBuilder(), newACLRecordBuilder(id, common.NewKeychain()), storage)
} }
func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder, storage storage.ListStorage) (list ACLList, err error) { func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder, storage storage.ListStorage) (list ACLList, err error) {
// TODO: need to add context here
rootWithId, err := storage.Root()
if err != nil {
return
}
aclRecRoot, err := recBuilder.ConvertFromRaw(rootWithId)
if err != nil {
return
}
head, err := storage.Head() head, err := storage.Head()
if err != nil { if err != nil {
return return
@ -87,7 +80,7 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder
} }
records := []*ACLRecord{record} records := []*ACLRecord{record}
for record.PrevId != "" && record.PrevId != id { for record.PrevId != "" {
rawRecordWithId, err = storage.GetRawRecord(context.Background(), record.PrevId) rawRecordWithId, err = storage.GetRawRecord(context.Background(), record.PrevId)
if err != nil { if err != nil {
return return
@ -99,8 +92,6 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder
} }
records = append(records, record) records = append(records, record)
} }
// adding root in the end, because we already parsed it
records = append(records, aclRecRoot)
indexes := make(map[string]int) indexes := make(map[string]int)
for i, j := 0, len(records)-1; i < j; i, j = i+1, j-1 { for i, j := 0, len(records)-1; i < j; i, j = i+1, j-1 {
@ -119,14 +110,21 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder
return return
} }
// TODO: check if this is correct (raw model instead of unmarshalled)
rootWithId, err := storage.Root()
if err != nil {
return
}
list = &aclList{ list = &aclList{
root: aclRecRoot.Model.(*aclrecordproto.ACLRoot), root: rootWithId,
records: records, records: records,
indexes: indexes, indexes: indexes,
builder: stateBuilder, stateBuilder: stateBuilder,
aclState: state, recordBuilder: recBuilder,
id: id, aclState: state,
RWMutex: sync.RWMutex{}, storage: storage,
id: id,
} }
return return
} }
@ -135,11 +133,42 @@ func (a *aclList) Records() []*ACLRecord {
return a.records return a.records
} }
func (a *aclList) AddRawRecord(rawRec *aclrecordproto.RawACLRecordWithId) (added bool, err error) {
if _, ok := a.indexes[rawRec.Id]; ok {
return
}
record, err := a.recordBuilder.ConvertFromRaw(rawRec)
if err != nil {
return
}
if err = a.aclState.applyRecord(record); err != nil {
return
}
a.records = append(a.records, record)
a.indexes[record.Id] = len(a.records) - 1
if err = a.storage.AddRawRecord(context.Background(), rawRec); err != nil {
return
}
if err = a.storage.SetHead(rawRec.Id); err != nil {
return
}
return true, nil
}
func (a *aclList) IsValidNext(rawRec *aclrecordproto.RawACLRecordWithId) (err error) {
_, err = a.recordBuilder.ConvertFromRaw(rawRec)
if err != nil {
return
}
// TODO: change state and add "check" method for records
return
}
func (a *aclList) ID() string { func (a *aclList) ID() string {
return a.id return a.id
} }
func (a *aclList) Root() *aclrecordproto.ACLRoot { func (a *aclList) Root() *aclrecordproto.RawACLRecordWithId {
return a.root return a.root
} }

View File

@ -22,9 +22,9 @@ func TestAclList_ACLState_UserInviteAndJoin(t *testing.T) {
idC := keychain.GetIdentity("C") idC := keychain.GetIdentity("C")
// checking final state // checking final state
assert.Equal(t, aclrecordproto.ACLUserPermissions_Admin, aclList.ACLState().GetUserStates()[idA].Permissions) assert.Equal(t, aclrecordproto.ACLUserPermissions_Admin, aclList.ACLState().UserStates()[idA].Permissions)
assert.Equal(t, aclrecordproto.ACLUserPermissions_Writer, aclList.ACLState().GetUserStates()[idB].Permissions) assert.Equal(t, aclrecordproto.ACLUserPermissions_Writer, aclList.ACLState().UserStates()[idB].Permissions)
assert.Equal(t, aclrecordproto.ACLUserPermissions_Reader, aclList.ACLState().GetUserStates()[idC].Permissions) assert.Equal(t, aclrecordproto.ACLUserPermissions_Reader, aclList.ACLState().UserStates()[idC].Permissions)
assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash()) assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash())
var records []*ACLRecord var records []*ACLRecord
@ -61,11 +61,11 @@ func TestAclList_ACLState_UserJoinAndRemove(t *testing.T) {
idC := keychain.GetIdentity("C") idC := keychain.GetIdentity("C")
// checking final state // checking final state
assert.Equal(t, aclrecordproto.ACLUserPermissions_Admin, aclList.ACLState().GetUserStates()[idA].Permissions) assert.Equal(t, aclrecordproto.ACLUserPermissions_Admin, aclList.ACLState().UserStates()[idA].Permissions)
assert.Equal(t, aclrecordproto.ACLUserPermissions_Reader, aclList.ACLState().GetUserStates()[idC].Permissions) assert.Equal(t, aclrecordproto.ACLUserPermissions_Reader, aclList.ACLState().UserStates()[idC].Permissions)
assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash()) assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash())
_, exists := aclList.ACLState().GetUserStates()[idB] _, exists := aclList.ACLState().UserStates()[idB]
assert.Equal(t, false, exists) assert.Equal(t, false, exists)
var records []*ACLRecord var records []*ACLRecord

View File

@ -49,6 +49,21 @@ func (mr *MockACLListMockRecorder) ACLState() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ACLState", reflect.TypeOf((*MockACLList)(nil).ACLState)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ACLState", reflect.TypeOf((*MockACLList)(nil).ACLState))
} }
// AddRawRecord mocks base method.
func (m *MockACLList) AddRawRecord(arg0 *aclrecordproto.RawACLRecordWithId) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddRawRecord", arg0)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddRawRecord indicates an expected call of AddRawRecord.
func (mr *MockACLListMockRecorder) AddRawRecord(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawRecord", reflect.TypeOf((*MockACLList)(nil).AddRawRecord), arg0)
}
// Close mocks base method. // Close mocks base method.
func (m *MockACLList) Close() error { func (m *MockACLList) Close() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -196,10 +211,10 @@ func (mr *MockACLListMockRecorder) Records() *gomock.Call {
} }
// Root mocks base method. // Root mocks base method.
func (m *MockACLList) Root() *aclrecordproto.ACLRoot { func (m *MockACLList) Root() *aclrecordproto.RawACLRecordWithId {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Root") ret := m.ctrl.Call(m, "Root")
ret0, _ := ret[0].(*aclrecordproto.ACLRoot) ret0, _ := ret[0].(*aclrecordproto.RawACLRecordWithId)
return ret0 return ret0
} }

View File

@ -9,8 +9,10 @@ import (
) )
type inMemoryACLListStorage struct { type inMemoryACLListStorage struct {
records []*aclrecordproto.RawACLRecordWithId
id string id string
root *aclrecordproto.RawACLRecordWithId
head string
records map[string]*aclrecordproto.RawACLRecordWithId
sync.RWMutex sync.RWMutex
} }
@ -18,48 +20,62 @@ type inMemoryACLListStorage struct {
func NewInMemoryACLListStorage( func NewInMemoryACLListStorage(
id string, id string,
records []*aclrecordproto.RawACLRecordWithId) (ListStorage, error) { records []*aclrecordproto.RawACLRecordWithId) (ListStorage, error) {
allRecords := make(map[string]*aclrecordproto.RawACLRecordWithId)
for _, ch := range records {
allRecords[ch.Id] = ch
}
root := records[0]
head := records[len(records)-1]
return &inMemoryACLListStorage{ return &inMemoryACLListStorage{
id: id, id: root.Id,
records: records, root: root,
RWMutex: sync.RWMutex{}, head: head.Id,
records: allRecords,
}, nil }, nil
} }
func (i *inMemoryACLListStorage) Root() (*aclrecordproto.RawACLRecordWithId, error) { func (t *inMemoryACLListStorage) Id() string {
i.RLock() t.RLock()
defer i.RUnlock() defer t.RUnlock()
return i.records[0], nil return t.id
} }
func (i *inMemoryACLListStorage) SetHead(headId string) error { func (t *inMemoryACLListStorage) Root() (*aclrecordproto.RawACLRecordWithId, error) {
panic("implement me") t.RLock()
defer t.RUnlock()
return t.root, nil
} }
func (i *inMemoryACLListStorage) Head() (string, error) { func (t *inMemoryACLListStorage) Head() (string, error) {
i.RLock() t.RLock()
defer i.RUnlock() defer t.RUnlock()
return i.records[len(i.records)-1].Id, nil return t.head, nil
} }
func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*aclrecordproto.RawACLRecordWithId, error) { func (t *inMemoryACLListStorage) SetHead(head string) error {
i.RLock() t.Lock()
defer i.RUnlock() defer t.Unlock()
for _, rec := range i.records { t.head = head
if rec.Id == id { return nil
return rec, nil }
}
func (t *inMemoryACLListStorage) AddRawRecord(ctx context.Context, record *aclrecordproto.RawACLRecordWithId) error {
t.Lock()
defer t.Unlock()
// TODO: better to do deep copy
t.records[record.Id] = record
return nil
}
func (t *inMemoryACLListStorage) GetRawRecord(ctx context.Context, recordId string) (*aclrecordproto.RawACLRecordWithId, error) {
t.RLock()
defer t.RUnlock()
if res, exists := t.records[recordId]; exists {
return res, nil
} }
return nil, fmt.Errorf("no such record") return nil, fmt.Errorf("could not get record with id: %s", recordId)
}
func (i *inMemoryACLListStorage) AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error {
panic("implement me")
}
func (i *inMemoryACLListStorage) ID() string {
i.RLock()
defer i.RUnlock()
return i.id
} }
type inMemoryTreeStorage struct { type inMemoryTreeStorage struct {
@ -95,7 +111,7 @@ func (t *inMemoryTreeStorage) HasChange(ctx context.Context, id string) (bool, e
return exists, nil return exists, nil
} }
func (t *inMemoryTreeStorage) ID() string { func (t *inMemoryTreeStorage) Id() string {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.id return t.id

View File

@ -12,7 +12,7 @@ var ErrACLExists = errors.New("acl already exists")
var ErrUnknownRecord = errors.New("record doesn't exist") var ErrUnknownRecord = errors.New("record doesn't exist")
type ListStorage interface { type ListStorage interface {
ID() string Id() string
Root() (*aclrecordproto.RawACLRecordWithId, error) Root() (*aclrecordproto.RawACLRecordWithId, error)
Head() (string, error) Head() (string, error)
SetHead(headId string) error SetHead(headId string) error

View File

@ -80,18 +80,18 @@ func (mr *MockListStorageMockRecorder) Head() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Head", reflect.TypeOf((*MockListStorage)(nil).Head)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Head", reflect.TypeOf((*MockListStorage)(nil).Head))
} }
// ID mocks base method. // Id mocks base method.
func (m *MockListStorage) ID() string { func (m *MockListStorage) Id() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID") ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
return ret0 return ret0
} }
// ID indicates an expected call of ID. // Id indicates an expected call of Id.
func (mr *MockListStorageMockRecorder) ID() *gomock.Call { func (mr *MockListStorageMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockListStorage)(nil).ID)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockListStorage)(nil).Id))
} }
// Root mocks base method. // Root mocks base method.
@ -205,18 +205,18 @@ func (mr *MockTreeStorageMockRecorder) Heads() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Heads", reflect.TypeOf((*MockTreeStorage)(nil).Heads)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Heads", reflect.TypeOf((*MockTreeStorage)(nil).Heads))
} }
// ID mocks base method. // Id mocks base method.
func (m *MockTreeStorage) ID() string { func (m *MockTreeStorage) Id() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID") ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
return ret0 return ret0
} }
// ID indicates an expected call of ID. // Id indicates an expected call of Id.
func (mr *MockTreeStorageMockRecorder) ID() *gomock.Call { func (mr *MockTreeStorageMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockTreeStorage)(nil).ID)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockTreeStorage)(nil).Id))
} }
// Root mocks base method. // Root mocks base method.

View File

@ -6,7 +6,7 @@ import (
) )
type TreeStorage interface { type TreeStorage interface {
ID() string Id() string
Root() (*treechangeproto.RawTreeChangeWithId, error) Root() (*treechangeproto.RawTreeChangeWithId, error)
Heads() ([]string, error) Heads() ([]string, error)
SetHeads(heads []string) error SetHeads(heads []string) error

View File

@ -16,28 +16,26 @@ type SymKey struct {
} }
type YAMLKeychain struct { type YAMLKeychain struct {
SigningKeysByYAMLIdentity map[string]signingkey2.PrivKey SigningKeysByYAMLName map[string]signingkey2.PrivKey
SigningKeysByRealIdentity map[string]signingkey2.PrivKey SigningKeysByRealIdentity map[string]signingkey2.PrivKey
EncryptionKeysByYAMLIdentity map[string]encryptionkey2.PrivKey EncryptionKeysByYAMLName map[string]encryptionkey2.PrivKey
ReadKeysByYAMLIdentity map[string]*SymKey ReadKeysByYAMLName map[string]*SymKey
ReadKeysByHash map[uint64]*SymKey ReadKeysByHash map[uint64]*SymKey
GeneratedIdentities map[string]string GeneratedIdentities map[string]string
DerivedIdentity string
} }
func NewKeychain() *YAMLKeychain { func NewKeychain() *YAMLKeychain {
return &YAMLKeychain{ return &YAMLKeychain{
SigningKeysByYAMLIdentity: map[string]signingkey2.PrivKey{}, SigningKeysByYAMLName: map[string]signingkey2.PrivKey{},
SigningKeysByRealIdentity: map[string]signingkey2.PrivKey{}, SigningKeysByRealIdentity: map[string]signingkey2.PrivKey{},
EncryptionKeysByYAMLIdentity: map[string]encryptionkey2.PrivKey{}, EncryptionKeysByYAMLName: map[string]encryptionkey2.PrivKey{},
GeneratedIdentities: map[string]string{}, GeneratedIdentities: map[string]string{},
ReadKeysByYAMLIdentity: map[string]*SymKey{}, ReadKeysByYAMLName: map[string]*SymKey{},
ReadKeysByHash: map[uint64]*SymKey{}, ReadKeysByHash: map[uint64]*SymKey{},
} }
} }
func (k *YAMLKeychain) ParseKeys(keys *Keys) { func (k *YAMLKeychain) ParseKeys(keys *Keys) {
k.DerivedIdentity = keys.Derived
for _, encKey := range keys.Enc { for _, encKey := range keys.Enc {
k.AddEncryptionKey(encKey) k.AddEncryptionKey(encKey)
} }
@ -52,7 +50,7 @@ func (k *YAMLKeychain) ParseKeys(keys *Keys) {
} }
func (k *YAMLKeychain) AddEncryptionKey(key *Key) { func (k *YAMLKeychain) AddEncryptionKey(key *Key) {
if _, exists := k.EncryptionKeysByYAMLIdentity[key.Name]; exists { if _, exists := k.EncryptionKeysByYAMLName[key.Name]; exists {
return return
} }
var ( var (
@ -70,11 +68,11 @@ func (k *YAMLKeychain) AddEncryptionKey(key *Key) {
panic(err) panic(err)
} }
} }
k.EncryptionKeysByYAMLIdentity[key.Name] = newPrivKey k.EncryptionKeysByYAMLName[key.Name] = newPrivKey
} }
func (k *YAMLKeychain) AddSigningKey(key *Key) { func (k *YAMLKeychain) AddSigningKey(key *Key) {
if _, exists := k.SigningKeysByYAMLIdentity[key.Name]; exists { if _, exists := k.SigningKeysByYAMLName[key.Name]; exists {
return return
} }
var ( var (
@ -95,7 +93,7 @@ func (k *YAMLKeychain) AddSigningKey(key *Key) {
pubKey = newPrivKey.GetPublic() pubKey = newPrivKey.GetPublic()
} }
k.SigningKeysByYAMLIdentity[key.Name] = newPrivKey k.SigningKeysByYAMLName[key.Name] = newPrivKey
rawPubKey, err := pubKey.Raw() rawPubKey, err := pubKey.Raw()
if err != nil { if err != nil {
panic(err) panic(err)
@ -107,7 +105,7 @@ func (k *YAMLKeychain) AddSigningKey(key *Key) {
} }
func (k *YAMLKeychain) AddReadKey(key *Key) { func (k *YAMLKeychain) AddReadKey(key *Key) {
if _, exists := k.ReadKeysByYAMLIdentity[key.Name]; exists { if _, exists := k.ReadKeysByYAMLName[key.Name]; exists {
return return
} }
@ -121,8 +119,8 @@ func (k *YAMLKeychain) AddReadKey(key *Key) {
panic("should be able to generate symmetric key") panic("should be able to generate symmetric key")
} }
} else if key.Value == "derived" { } else if key.Value == "derived" {
signKey, _ := k.SigningKeysByYAMLIdentity[k.DerivedIdentity].Raw() signKey, _ := k.SigningKeysByYAMLName[key.Name].Raw()
encKey, _ := k.EncryptionKeysByYAMLIdentity[k.DerivedIdentity].Raw() encKey, _ := k.EncryptionKeysByYAMLName[key.Name].Raw()
rkey, err = aclrecordproto.ACLReadKeyDerive(signKey, encKey) rkey, err = aclrecordproto.ACLReadKeyDerive(signKey, encKey)
if err != nil { if err != nil {
panic("should be able to derive symmetric key") panic("should be able to derive symmetric key")
@ -137,7 +135,7 @@ func (k *YAMLKeychain) AddReadKey(key *Key) {
hasher := fnv.New64() hasher := fnv.New64()
hasher.Write(rkey.Bytes()) hasher.Write(rkey.Bytes())
k.ReadKeysByYAMLIdentity[key.Name] = &SymKey{ k.ReadKeysByYAMLName[key.Name] = &SymKey{
Hash: hasher.Sum64(), Hash: hasher.Sum64(),
Key: rkey, Key: rkey,
} }
@ -174,15 +172,15 @@ func (k *YAMLKeychain) GetKey(key string) interface{} {
switch parts[1] { switch parts[1] {
case "Sign": case "Sign":
if key, exists := k.SigningKeysByYAMLIdentity[name]; exists { if key, exists := k.SigningKeysByYAMLName[name]; exists {
return key return key
} }
case "Enc": case "Enc":
if key, exists := k.EncryptionKeysByYAMLIdentity[name]; exists { if key, exists := k.EncryptionKeysByYAMLName[name]; exists {
return key return key
} }
case "Read": case "Read":
if key, exists := k.ReadKeysByYAMLIdentity[name]; exists { if key, exists := k.ReadKeysByYAMLName[name]; exists {
return key return key
} }
default: default:

View File

@ -3,13 +3,13 @@ package acllistbuilder
import ( import (
"context" "context"
"fmt" "fmt"
aclrecordproto2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto" aclrecordproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/testutils/yamltests" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/testutils/yamltests"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"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"
"hash/fnv" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
"io/ioutil" "io/ioutil"
"path" "path"
"time" "time"
@ -19,20 +19,12 @@ import (
) )
type ACLListStorageBuilder struct { type ACLListStorageBuilder struct {
aclList string storage.ListStorage
records []*aclrecordproto2.ACLRecord keychain *YAMLKeychain
rawRecords []*aclrecordproto2.RawACLRecordWithId
indexes map[string]int
keychain *YAMLKeychain
rawRoot *aclrecordproto2.RawACLRecordWithId
root *aclrecordproto2.ACLRoot
id string
} }
func NewACLListStorageBuilder(keychain *YAMLKeychain) *ACLListStorageBuilder { func NewACLListStorageBuilder(keychain *YAMLKeychain) *ACLListStorageBuilder {
return &ACLListStorageBuilder{ return &ACLListStorageBuilder{
records: make([]*aclrecordproto2.ACLRecord, 0),
indexes: make(map[string]int),
keychain: keychain, keychain: keychain,
} }
} }
@ -60,7 +52,7 @@ func NewACLListStorageBuilderFromFile(file string) (*ACLListStorageBuilder, erro
return tb, nil return tb, nil
} }
func (t *ACLListStorageBuilder) createRaw(rec proto.Marshaler, identity []byte) *aclrecordproto2.RawACLRecordWithId { func (t *ACLListStorageBuilder) createRaw(rec proto.Marshaler, identity []byte) *aclrecordproto.RawACLRecordWithId {
protoMarshalled, err := rec.Marshal() protoMarshalled, err := rec.Marshal()
if err != nil { if err != nil {
panic("should be able to marshal final acl message!") panic("should be able to marshal final acl message!")
@ -71,7 +63,7 @@ func (t *ACLListStorageBuilder) createRaw(rec proto.Marshaler, identity []byte)
panic("should be able to sign final acl message!") panic("should be able to sign final acl message!")
} }
rawRec := &aclrecordproto2.RawACLRecord{ rawRec := &aclrecordproto.RawACLRecord{
Payload: protoMarshalled, Payload: protoMarshalled,
Signature: signature, Signature: signature,
} }
@ -83,94 +75,62 @@ func (t *ACLListStorageBuilder) createRaw(rec proto.Marshaler, identity []byte)
id, _ := cid.NewCIDFromBytes(rawMarshalled) id, _ := cid.NewCIDFromBytes(rawMarshalled)
return &aclrecordproto2.RawACLRecordWithId{ return &aclrecordproto.RawACLRecordWithId{
Payload: rawMarshalled, Payload: rawMarshalled,
Id: id, Id: id,
} }
} }
func (t *ACLListStorageBuilder) Head() (string, error) {
l := len(t.records)
if l > 0 {
return t.rawRecords[l-1].Id, nil
}
return t.rawRoot.Id, nil
}
func (t *ACLListStorageBuilder) SetHead(headId string) error {
panic("SetHead is not implemented")
}
func (t *ACLListStorageBuilder) Root() (*aclrecordproto2.RawACLRecordWithId, error) {
return t.rawRoot, nil
}
func (t *ACLListStorageBuilder) GetRawRecord(ctx context.Context, id string) (*aclrecordproto2.RawACLRecordWithId, error) {
recIdx, ok := t.indexes[id]
if !ok {
if id == t.rawRoot.Id {
return t.rawRoot, nil
}
return nil, fmt.Errorf("no such record")
}
return t.rawRecords[recIdx], nil
}
func (t *ACLListStorageBuilder) AddRawRecord(ctx context.Context, rec *aclrecordproto2.RawACLRecordWithId) error {
panic("implement me")
}
func (t *ACLListStorageBuilder) ID() string {
return t.id
}
func (t *ACLListStorageBuilder) GetRawRecords() []*aclrecordproto2.RawACLRecordWithId {
return t.rawRecords
}
func (t *ACLListStorageBuilder) GetKeychain() *YAMLKeychain { func (t *ACLListStorageBuilder) GetKeychain() *YAMLKeychain {
return t.keychain return t.keychain
} }
func (t *ACLListStorageBuilder) Parse(tree *YMLList) { func (t *ACLListStorageBuilder) Parse(l *YMLList) {
// Just to clarify - we are generating new identities for the ones that // Just to clarify - we are generating new identities for the ones that
// are specified in the yml file, because our identities should be Ed25519 // are specified in the yml file, because our identities should be Ed25519
// the same thing is happening for the encryption keys // the same thing is happening for the encryption keys
t.keychain.ParseKeys(&tree.Keys) t.keychain.ParseKeys(&l.Keys)
t.parseRoot(tree.Root) rawRoot := t.parseRoot(l.Root)
prevId := t.id var err error
for idx, rec := range tree.Records { t.ListStorage, err = storage.NewInMemoryACLListStorage(rawRoot.Id, []*aclrecordproto.RawACLRecordWithId{rawRoot})
if err != nil {
panic(err)
}
prevId := rawRoot.Id
for _, rec := range l.Records {
newRecord := t.parseRecord(rec, prevId) newRecord := t.parseRecord(rec, prevId)
rawRecord := t.createRaw(newRecord, newRecord.Identity) rawRecord := t.createRaw(newRecord, newRecord.Identity)
t.records = append(t.records, newRecord) err = t.AddRawRecord(context.Background(), rawRecord)
t.rawRecords = append(t.rawRecords, rawRecord) if err != nil {
t.indexes[rawRecord.Id] = idx panic(err)
}
prevId = rawRecord.Id prevId = rawRecord.Id
} }
t.SetHead(prevId)
} }
func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclrecordproto2.ACLRecord { func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclrecordproto.ACLRecord {
k := t.keychain.GetKey(rec.ReadKey).(*SymKey) k := t.keychain.GetKey(rec.ReadKey).(*SymKey)
var aclChangeContents []*aclrecordproto2.ACLContentValue var aclChangeContents []*aclrecordproto.ACLContentValue
for _, ch := range rec.AclChanges { for _, ch := range rec.AclChanges {
aclChangeContent := t.parseACLChange(ch) aclChangeContent := t.parseACLChange(ch)
aclChangeContents = append(aclChangeContents, aclChangeContent) aclChangeContents = append(aclChangeContents, aclChangeContent)
} }
data := &aclrecordproto2.ACLData{ data := &aclrecordproto.ACLData{
AclContent: aclChangeContents, AclContent: aclChangeContents,
} }
bytes, _ := data.Marshal() bytes, _ := data.Marshal()
return &aclrecordproto2.ACLRecord{ return &aclrecordproto.ACLRecord{
PrevId: prevId, PrevId: prevId,
Identity: []byte(t.keychain.GetIdentity(rec.Identity)), Identity: []byte(t.keychain.GetIdentity(rec.Identity)),
Data: bytes, Data: bytes,
CurrentReadKeyHash: k.Hash, CurrentReadKeyHash: k.Hash,
Timestamp: time.Now().Unix(), Timestamp: time.Now().UnixNano(),
} }
} }
func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecordproto2.ACLContentValue) { func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecordproto.ACLContentValue) {
switch { switch {
case ch.UserAdd != nil: case ch.UserAdd != nil:
add := ch.UserAdd add := ch.UserAdd
@ -178,12 +138,12 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecord
encKey := t.keychain.GetKey(add.EncryptionKey).(encryptionkey.PrivKey) encKey := t.keychain.GetKey(add.EncryptionKey).(encryptionkey.PrivKey)
rawKey, _ := encKey.GetPublic().Raw() rawKey, _ := encKey.GetPublic().Raw()
convCh = &aclrecordproto2.ACLContentValue{ convCh = &aclrecordproto.ACLContentValue{
Value: &aclrecordproto2.ACLContentValue_UserAdd{ Value: &aclrecordproto.ACLContentValue_UserAdd{
UserAdd: &aclrecordproto2.ACLUserAdd{ UserAdd: &aclrecordproto.ACLUserAdd{
Identity: []byte(t.keychain.GetIdentity(add.Identity)), Identity: []byte(t.keychain.GetIdentity(add.Identity)),
EncryptionKey: rawKey, EncryptionKey: rawKey,
EncryptedReadKeys: t.encryptReadKeys(add.EncryptedReadKeys, encKey), EncryptedReadKeys: t.encryptReadKeysWithPubKey(add.EncryptedReadKeys, encKey),
Permissions: t.convertPermission(add.Permission), Permissions: t.convertPermission(add.Permission),
}, },
}, },
@ -191,52 +151,50 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecord
case ch.UserJoin != nil: case ch.UserJoin != nil:
join := ch.UserJoin join := ch.UserJoin
encKey := t.keychain. encKey := t.keychain.GetKey(join.EncryptionKey).(encryptionkey.PrivKey)
GetKey(join.EncryptionKey).(encryptionkey.PrivKey)
rawKey, _ := encKey.GetPublic().Raw() rawKey, _ := encKey.GetPublic().Raw()
idKey, _ := t.keychain.SigningKeysByYAMLIdentity[join.Identity].GetPublic().Raw() idKey, _ := t.keychain.SigningKeysByYAMLName[join.Identity].GetPublic().Raw()
signKey := t.keychain.GetKey(join.AcceptSignature).(signingkey.PrivKey) signKey := t.keychain.GetKey(join.AcceptKey).(signingkey.PrivKey)
signature, err := signKey.Sign(idKey) signature, err := signKey.Sign(idKey)
if err != nil { if err != nil {
panic(err) panic(err)
} }
acceptPubKey, _ := signKey.GetPublic().Raw()
convCh = &aclrecordproto2.ACLContentValue{ convCh = &aclrecordproto.ACLContentValue{
Value: &aclrecordproto2.ACLContentValue_UserJoin{ Value: &aclrecordproto.ACLContentValue_UserJoin{
UserJoin: &aclrecordproto2.ACLUserJoin{ UserJoin: &aclrecordproto.ACLUserJoin{
Identity: []byte(t.keychain.GetIdentity(join.Identity)), Identity: []byte(t.keychain.GetIdentity(join.Identity)),
EncryptionKey: rawKey, EncryptionKey: rawKey,
AcceptSignature: signature, AcceptSignature: signature,
InviteId: join.InviteId, AcceptPubKey: acceptPubKey,
EncryptedReadKeys: t.encryptReadKeys(join.EncryptedReadKeys, encKey), EncryptedReadKeys: t.encryptReadKeysWithPubKey(join.EncryptedReadKeys, encKey),
}, },
}, },
} }
case ch.UserInvite != nil: case ch.UserInvite != nil:
invite := ch.UserInvite invite := ch.UserInvite
rawAcceptKey, _ := t.keychain.GetKey(invite.AcceptKey).(signingkey.PrivKey).GetPublic().Raw() rawAcceptKey, _ := t.keychain.GetKey(invite.AcceptKey).(signingkey.PrivKey).GetPublic().Raw()
encKey := t.keychain. hash := t.keychain.GetKey(invite.EncryptionKey).(*SymKey).Hash
GetKey(invite.EncryptionKey).(encryptionkey.PrivKey) encKey := t.keychain.ReadKeysByHash[hash]
rawEncKey, _ := encKey.GetPublic().Raw()
convCh = &aclrecordproto2.ACLContentValue{ convCh = &aclrecordproto.ACLContentValue{
Value: &aclrecordproto2.ACLContentValue_UserInvite{ Value: &aclrecordproto.ACLContentValue_UserInvite{
UserInvite: &aclrecordproto2.ACLUserInvite{ UserInvite: &aclrecordproto.ACLUserInvite{
AcceptPublicKey: rawAcceptKey, AcceptPublicKey: rawAcceptKey,
EncryptPublicKey: rawEncKey, EncryptSymKeyHash: hash,
EncryptedReadKeys: t.encryptReadKeys(invite.EncryptedReadKeys, encKey), EncryptedReadKeys: t.encryptReadKeysWithSymKey(invite.EncryptedReadKeys, encKey.Key),
Permissions: t.convertPermission(invite.Permissions), Permissions: t.convertPermission(invite.Permissions),
InviteId: invite.InviteId,
}, },
}, },
} }
case ch.UserPermissionChange != nil: case ch.UserPermissionChange != nil:
permissionChange := ch.UserPermissionChange permissionChange := ch.UserPermissionChange
convCh = &aclrecordproto2.ACLContentValue{ convCh = &aclrecordproto.ACLContentValue{
Value: &aclrecordproto2.ACLContentValue_UserPermissionChange{ Value: &aclrecordproto.ACLContentValue_UserPermissionChange{
UserPermissionChange: &aclrecordproto2.ACLUserPermissionChange{ UserPermissionChange: &aclrecordproto.ACLUserPermissionChange{
Identity: []byte(t.keychain.GetIdentity(permissionChange.Identity)), Identity: []byte(t.keychain.GetIdentity(permissionChange.Identity)),
Permissions: t.convertPermission(permissionChange.Permission), Permissions: t.convertPermission(permissionChange.Permission),
}, },
@ -247,24 +205,24 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecord
newReadKey := t.keychain.GetKey(remove.NewReadKey).(*SymKey) newReadKey := t.keychain.GetKey(remove.NewReadKey).(*SymKey)
var replaces []*aclrecordproto2.ACLReadKeyReplace var replaces []*aclrecordproto.ACLReadKeyReplace
for _, id := range remove.IdentitiesLeft { for _, id := range remove.IdentitiesLeft {
encKey := t.keychain.EncryptionKeysByYAMLIdentity[id] encKey := t.keychain.EncryptionKeysByYAMLName[id]
rawEncKey, _ := encKey.GetPublic().Raw() rawEncKey, _ := encKey.GetPublic().Raw()
encReadKey, err := encKey.GetPublic().Encrypt(newReadKey.Key.Bytes()) encReadKey, err := encKey.GetPublic().Encrypt(newReadKey.Key.Bytes())
if err != nil { if err != nil {
panic(err) panic(err)
} }
replaces = append(replaces, &aclrecordproto2.ACLReadKeyReplace{ replaces = append(replaces, &aclrecordproto.ACLReadKeyReplace{
Identity: []byte(t.keychain.GetIdentity(id)), Identity: []byte(t.keychain.GetIdentity(id)),
EncryptionKey: rawEncKey, EncryptionKey: rawEncKey,
EncryptedReadKey: encReadKey, EncryptedReadKey: encReadKey,
}) })
} }
convCh = &aclrecordproto2.ACLContentValue{ convCh = &aclrecordproto.ACLContentValue{
Value: &aclrecordproto2.ACLContentValue_UserRemove{ Value: &aclrecordproto.ACLContentValue_UserRemove{
UserRemove: &aclrecordproto2.ACLUserRemove{ UserRemove: &aclrecordproto.ACLUserRemove{
Identity: []byte(t.keychain.GetIdentity(remove.RemovedIdentity)), Identity: []byte(t.keychain.GetIdentity(remove.RemovedIdentity)),
ReadKeyReplaces: replaces, ReadKeyReplaces: replaces,
}, },
@ -278,7 +236,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecord
return convCh return convCh
} }
func (t *ACLListStorageBuilder) encryptReadKeys(keys []string, encKey encryptionkey.PrivKey) (enc [][]byte) { func (t *ACLListStorageBuilder) encryptReadKeysWithPubKey(keys []string, encKey encryptionkey.PrivKey) (enc [][]byte) {
for _, k := range keys { for _, k := range keys {
realKey := t.keychain.GetKey(k).(*SymKey).Key.Bytes() realKey := t.keychain.GetKey(k).(*SymKey).Key.Bytes()
res, err := encKey.GetPublic().Encrypt(realKey) res, err := encKey.GetPublic().Encrypt(realKey)
@ -291,43 +249,47 @@ func (t *ACLListStorageBuilder) encryptReadKeys(keys []string, encKey encryption
return return
} }
func (t *ACLListStorageBuilder) convertPermission(perm string) aclrecordproto2.ACLUserPermissions { func (t *ACLListStorageBuilder) encryptReadKeysWithSymKey(keys []string, key *symmetric.Key) (enc [][]byte) {
for _, k := range keys {
realKey := t.keychain.GetKey(k).(*SymKey).Key.Bytes()
res, err := key.Encrypt(realKey)
if err != nil {
panic(err)
}
enc = append(enc, res)
}
return
}
func (t *ACLListStorageBuilder) convertPermission(perm string) aclrecordproto.ACLUserPermissions {
switch perm { switch perm {
case "admin": case "admin":
return aclrecordproto2.ACLUserPermissions_Admin return aclrecordproto.ACLUserPermissions_Admin
case "writer": case "writer":
return aclrecordproto2.ACLUserPermissions_Writer return aclrecordproto.ACLUserPermissions_Writer
case "reader": case "reader":
return aclrecordproto2.ACLUserPermissions_Reader return aclrecordproto.ACLUserPermissions_Reader
default: default:
panic(fmt.Sprintf("incorrect permission: %s", perm)) panic(fmt.Sprintf("incorrect permission: %s", perm))
} }
} }
func (t *ACLListStorageBuilder) traverseFromHead(f func(rec *aclrecordproto2.ACLRecord, id string) error) (err error) { func (t *ACLListStorageBuilder) traverseFromHead(f func(rec *aclrecordproto.ACLRecord, id string) error) (err error) {
for i := len(t.records) - 1; i >= 0; i-- { panic("this was removed, add if needed")
err = f(t.records[i], t.rawRecords[i].Id)
if err != nil {
return err
}
}
return nil
} }
func (t *ACLListStorageBuilder) parseRoot(root *Root) { func (t *ACLListStorageBuilder) parseRoot(root *Root) (rawRoot *aclrecordproto.RawACLRecordWithId) {
rawSignKey, _ := t.keychain.SigningKeysByYAMLIdentity[root.Identity].GetPublic().Raw() rawSignKey, _ := t.keychain.SigningKeysByYAMLName[root.Identity].GetPublic().Raw()
rawEncKey, _ := t.keychain.EncryptionKeysByYAMLIdentity[root.Identity].GetPublic().Raw() rawEncKey, _ := t.keychain.EncryptionKeysByYAMLName[root.Identity].GetPublic().Raw()
readKey, _ := aclrecordproto2.ACLReadKeyDerive(rawSignKey, rawEncKey) readKey := t.keychain.ReadKeysByYAMLName[root.Identity]
hasher := fnv.New64() aclRoot := &aclrecordproto.ACLRoot{
hasher.Write(readKey.Bytes())
t.root = &aclrecordproto2.ACLRoot{
Identity: rawSignKey, Identity: rawSignKey,
EncryptionKey: rawEncKey, EncryptionKey: rawEncKey,
SpaceId: root.SpaceId, SpaceId: root.SpaceId,
EncryptedReadKey: nil, EncryptedReadKey: nil,
DerivationScheme: "scheme", DerivationScheme: "scheme",
CurrentReadKeyHash: hasher.Sum64(), CurrentReadKeyHash: readKey.Hash,
} }
t.rawRoot = t.createRaw(t.root, rawSignKey) return t.createRaw(aclRoot, rawSignKey)
t.id = t.rawRoot.Id
} }

View File

@ -23,8 +23,7 @@ type ACLChange struct {
UserJoin *struct { UserJoin *struct {
Identity string `yaml:"identity"` Identity string `yaml:"identity"`
EncryptionKey string `yaml:"encryptionKey"` EncryptionKey string `yaml:"encryptionKey"`
AcceptSignature string `yaml:"acceptSignature"` AcceptKey string `yaml:"acceptKey"`
InviteId string `yaml:"inviteId"`
EncryptedReadKeys []string `yaml:"encryptedReadKeys"` EncryptedReadKeys []string `yaml:"encryptedReadKeys"`
} `yaml:"userJoin"` } `yaml:"userJoin"`
@ -33,7 +32,6 @@ type ACLChange struct {
EncryptionKey string `yaml:"encryptionKey"` EncryptionKey string `yaml:"encryptionKey"`
EncryptedReadKeys []string `yaml:"encryptedReadKeys"` EncryptedReadKeys []string `yaml:"encryptedReadKeys"`
Permissions string `yaml:"permissions"` Permissions string `yaml:"permissions"`
InviteId string `yaml:"inviteId"`
} `yaml:"userInvite"` } `yaml:"userInvite"`
UserRemove *struct { UserRemove *struct {

View File

@ -6,27 +6,24 @@ records:
aclChanges: aclChanges:
- userInvite: - userInvite:
acceptKey: key.Sign.Onetime1 acceptKey: key.Sign.Onetime1
encryptionKey: key.Enc.Onetime1 encryptionKey: key.Read.EncKey
encryptedReadKeys: [key.Read.1] encryptedReadKeys: [key.Read.A]
permissions: writer permissions: writer
inviteId: A.1.2
- userAdd: - userAdd:
identity: C identity: C
permission: reader permission: reader
encryptionKey: key.Enc.C encryptionKey: key.Enc.C
encryptedReadKeys: [key.Read.1] encryptedReadKeys: [key.Read.A]
readKey: key.Read.1 readKey: key.Read.A
- identity: B - identity: B
aclChanges: aclChanges:
- userJoin: - userJoin:
identity: B identity: B
encryptionKey: key.Enc.B encryptionKey: key.Enc.B
acceptSignature: key.Sign.Onetime1 acceptKey: key.Sign.Onetime1
inviteId: A.1.2 encryptedReadKeys: [key.Read.A]
encryptedReadKeys: [key.Read.1] readKey: key.Read.A
readKey: key.Read.1
keys: keys:
Derived: A
Enc: Enc:
- name: A - name: A
value: generated value: generated
@ -34,6 +31,8 @@ keys:
value: generated value: generated
- name: C - name: C
value: generated value: generated
- name: D
value: generated
- name: Onetime1 - name: Onetime1
value: generated value: generated
Sign: Sign:
@ -43,8 +42,12 @@ keys:
value: generated value: generated
- name: C - name: C
value: generated value: generated
- name: D
value: generated
- name: Onetime1 - name: Onetime1
value: generated value: generated
Read: Read:
- name: 1 - name: A
value: derived value: derived
- name: EncKey
value: generated

View File

@ -6,25 +6,23 @@ records:
aclChanges: aclChanges:
- userInvite: - userInvite:
acceptKey: key.Sign.Onetime1 acceptKey: key.Sign.Onetime1
encryptionKey: key.Enc.Onetime1 encryptionKey: key.Read.EncKey
encryptedReadKeys: [key.Read.1] encryptedReadKeys: [key.Read.A]
permissions: writer permissions: writer
inviteId: A.1.2
- userAdd: - userAdd:
identity: C identity: C
permission: reader permission: reader
encryptionKey: key.Enc.C encryptionKey: key.Enc.C
encryptedReadKeys: [key.Read.1] encryptedReadKeys: [key.Read.A]
readKey: key.Read.1 readKey: key.Read.A
- identity: B - identity: B
aclChanges: aclChanges:
- userJoin: - userJoin:
identity: B identity: B
encryptionKey: key.Enc.B encryptionKey: key.Enc.B
acceptSignature: key.Sign.Onetime1 acceptKey: key.Sign.Onetime1
inviteId: A.1.2 encryptedReadKeys: [key.Read.A]
encryptedReadKeys: [key.Read.1] readKey: key.Read.A
readKey: key.Read.1
- identity: A - identity: A
aclChanges: aclChanges:
- userRemove: - userRemove:
@ -33,7 +31,6 @@ records:
identitiesLeft: [A, C] identitiesLeft: [A, C]
readKey: key.Read.2 readKey: key.Read.2
keys: keys:
Derived: A
Enc: Enc:
- name: A - name: A
value: generated value: generated
@ -53,7 +50,9 @@ keys:
- name: Onetime1 - name: Onetime1
value: generated value: generated
Read: Read:
- name: 1 - name: A
value: derived value: derived
- name: 2 - name: 2
value: generated value: generated
- name: EncKey
value: generated

View File

@ -3,14 +3,14 @@ package tree
import ( import (
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
list2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
) )
type ObjectTreeValidator interface { type ObjectTreeValidator interface {
// ValidateFullTree should always be entered while holding a read lock on ACLList // ValidateFullTree should always be entered while holding a read lock on ACLList
ValidateFullTree(tree *Tree, aclList list2.ACLList) error ValidateFullTree(tree *Tree, aclList list.ACLList) error
// ValidateNewChanges should always be entered while holding a read lock on ACLList // ValidateNewChanges should always be entered while holding a read lock on ACLList
ValidateNewChanges(tree *Tree, aclList list2.ACLList, newChanges []*Change) error ValidateNewChanges(tree *Tree, aclList list.ACLList, newChanges []*Change) error
} }
type objectTreeValidator struct{} type objectTreeValidator struct{}
@ -19,7 +19,7 @@ func newTreeValidator() ObjectTreeValidator {
return &objectTreeValidator{} return &objectTreeValidator{}
} }
func (v *objectTreeValidator) ValidateFullTree(tree *Tree, aclList list2.ACLList) (err error) { func (v *objectTreeValidator) ValidateFullTree(tree *Tree, aclList list.ACLList) (err error) {
tree.Iterate(tree.RootId(), func(c *Change) (isContinue bool) { tree.Iterate(tree.RootId(), func(c *Change) (isContinue bool) {
err = v.validateChange(tree, aclList, c) err = v.validateChange(tree, aclList, c)
return err == nil return err == nil
@ -27,7 +27,7 @@ func (v *objectTreeValidator) ValidateFullTree(tree *Tree, aclList list2.ACLList
return err return err
} }
func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list2.ACLList, newChanges []*Change) (err error) { func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list.ACLList, newChanges []*Change) (err error) {
for _, c := range newChanges { for _, c := range newChanges {
err = v.validateChange(tree, aclList, c) err = v.validateChange(tree, aclList, c)
if err != nil { if err != nil {
@ -37,9 +37,9 @@ func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list2.ACLLi
return return
} }
func (v *objectTreeValidator) validateChange(tree *Tree, aclList list2.ACLList, c *Change) (err error) { func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c *Change) (err error) {
var ( var (
perm list2.UserPermissionPair perm list.UserPermissionPair
state = aclList.ACLState() state = aclList.ACLState()
) )
// checking if the user could write // checking if the user could write
@ -49,7 +49,7 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list2.ACLList,
} }
if perm.Permission != aclrecordproto.ACLUserPermissions_Writer && perm.Permission != aclrecordproto.ACLUserPermissions_Admin { if perm.Permission != aclrecordproto.ACLUserPermissions_Writer && perm.Permission != aclrecordproto.ACLUserPermissions_Admin {
err = list2.ErrInsufficientPermissions err = list.ErrInsufficientPermissions
return return
} }

View File

@ -126,7 +126,9 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
} }
} }
objTree.id = objTree.treeStorage.ID() objTree.id = objTree.treeStorage.Id()
objTree.id = objTree.treeStorage.Id()
objTree.root, err = objTree.treeStorage.Root() objTree.root, err = objTree.treeStorage.Root()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -0,0 +1,44 @@
package testaccount
import (
accountService "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/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
)
// AccountTestService provides service for test purposes, generates new random account every Init
type AccountTestService struct {
acc *account.AccountData
}
func (s *AccountTestService) Init(a *app.App) (err error) {
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
if err != nil {
return
}
signKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
if err != nil {
return
}
ident, err := signKey.GetPublic().Raw()
if err != nil {
return
}
s.acc = &account.AccountData{
Identity: ident,
SignKey: signKey,
EncKey: encKey,
}
return nil
}
func (s *AccountTestService) Name() (name string) {
return accountService.CName
}
func (s *AccountTestService) Account() *account.AccountData {
return s.acc
}

View File

@ -1,3 +1,4 @@
//go:generate mockgen -destination mock_consensusclient/mock_consensusclient.go github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient Service
package consensusclient package consensusclient
import ( import (

View File

@ -13,6 +13,7 @@ import (
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sync"
"testing" "testing"
"time" "time"
) )
@ -22,7 +23,7 @@ func TestService_Watch(t *testing.T) {
fx := newFixture(t).run(t) fx := newFixture(t).run(t)
defer fx.Finish() defer fx.Finish()
var logId = []byte{'1'} var logId = []byte{'1'}
w := &testWatcher{} w := &testWatcher{ready: make(chan struct{})}
require.NoError(t, fx.Watch(logId, w)) require.NoError(t, fx.Watch(logId, w))
st := fx.testServer.waitStream(t) st := fx.testServer.waitStream(t)
req, err := st.Recv() req, err := st.Recv()
@ -34,6 +35,7 @@ func TestService_Watch(t *testing.T) {
Error: consensusproto.ErrCodes_ErrorOffset + consensusproto.ErrCodes_LogNotFound, Error: consensusproto.ErrCodes_ErrorOffset + consensusproto.ErrCodes_LogNotFound,
}, },
})) }))
<-w.ready
assert.Equal(t, consensuserr.ErrLogNotFound, w.err) assert.Equal(t, consensuserr.ErrLogNotFound, w.err)
fx.testServer.releaseStream <- nil fx.testServer.releaseStream <- nil
}) })
@ -188,7 +190,6 @@ func (t *testServer) AddRecord(ctx context.Context, req *consensusproto.AddRecor
} }
func (t *testServer) WatchLog(stream consensusproto.DRPCConsensus_WatchLogStream) error { func (t *testServer) WatchLog(stream consensusproto.DRPCConsensus_WatchLogStream) error {
fmt.Println("watchLog", t.watchErrOnce)
if t.watchErrOnce { if t.watchErrOnce {
t.watchErrOnce = false t.watchErrOnce = false
return fmt.Errorf("error") return fmt.Errorf("error")
@ -208,14 +209,22 @@ func (t *testServer) waitStream(test *testing.T) consensusproto.DRPCConsensus_Wa
} }
type testWatcher struct { type testWatcher struct {
recs [][]*consensusproto.Record recs [][]*consensusproto.Record
err error err error
ready chan struct{}
once sync.Once
} }
func (t *testWatcher) AddConsensusRecords(recs []*consensusproto.Record) { func (t *testWatcher) AddConsensusRecords(recs []*consensusproto.Record) {
t.recs = append(t.recs, recs) t.recs = append(t.recs, recs)
t.once.Do(func() {
close(t.ready)
})
} }
func (t *testWatcher) AddConsensusError(err error) { func (t *testWatcher) AddConsensusError(err error) {
t.err = err t.err = err
t.once.Do(func() {
close(t.ready)
})
} }

View File

@ -0,0 +1,150 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient (interfaces: Service)
// Package mock_consensusclient is a generated GoMock package.
package mock_consensusclient
import (
context "context"
reflect "reflect"
app "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
consensusclient "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient"
consensusproto "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
gomock "github.com/golang/mock/gomock"
)
// MockService is a mock of Service interface.
type MockService struct {
ctrl *gomock.Controller
recorder *MockServiceMockRecorder
}
// MockServiceMockRecorder is the mock recorder for MockService.
type MockServiceMockRecorder struct {
mock *MockService
}
// NewMockService creates a new mock instance.
func NewMockService(ctrl *gomock.Controller) *MockService {
mock := &MockService{ctrl: ctrl}
mock.recorder = &MockServiceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockService) EXPECT() *MockServiceMockRecorder {
return m.recorder
}
// AddLog mocks base method.
func (m *MockService) AddLog(arg0 context.Context, arg1 *consensusproto.Log) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddLog", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// AddLog indicates an expected call of AddLog.
func (mr *MockServiceMockRecorder) AddLog(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddLog", reflect.TypeOf((*MockService)(nil).AddLog), arg0, arg1)
}
// AddRecord mocks base method.
func (m *MockService) AddRecord(arg0 context.Context, arg1 []byte, arg2 *consensusproto.Record) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddRecord", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// AddRecord indicates an expected call of AddRecord.
func (mr *MockServiceMockRecorder) AddRecord(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRecord", reflect.TypeOf((*MockService)(nil).AddRecord), arg0, arg1, arg2)
}
// Close mocks base method.
func (m *MockService) Close(arg0 context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close.
func (mr *MockServiceMockRecorder) Close(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockService)(nil).Close), arg0)
}
// Init mocks base method.
func (m *MockService) Init(arg0 *app.App) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Init", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Init indicates an expected call of Init.
func (mr *MockServiceMockRecorder) Init(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockService)(nil).Init), arg0)
}
// Name mocks base method.
func (m *MockService) Name() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Name")
ret0, _ := ret[0].(string)
return ret0
}
// Name indicates an expected call of Name.
func (mr *MockServiceMockRecorder) Name() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockService)(nil).Name))
}
// Run mocks base method.
func (m *MockService) Run(arg0 context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Run", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Run indicates an expected call of Run.
func (mr *MockServiceMockRecorder) Run(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockService)(nil).Run), arg0)
}
// UnWatch mocks base method.
func (m *MockService) UnWatch(arg0 []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UnWatch", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// UnWatch indicates an expected call of UnWatch.
func (mr *MockServiceMockRecorder) UnWatch(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnWatch", reflect.TypeOf((*MockService)(nil).UnWatch), arg0)
}
// Watch mocks base method.
func (m *MockService) Watch(arg0 []byte, arg1 consensusclient.Watcher) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Watch", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Watch indicates an expected call of Watch.
func (mr *MockServiceMockRecorder) Watch(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockService)(nil).Watch), arg0, arg1)
}

View File

@ -3,6 +3,7 @@ package consensusclient
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/cheggaaa/mb/v2" "github.com/cheggaaa/mb/v2"
"sync"
) )
func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream { func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream {
@ -17,6 +18,7 @@ func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream {
type stream struct { type stream struct {
rpcStream consensusproto.DRPCConsensus_WatchLogClient rpcStream consensusproto.DRPCConsensus_WatchLogClient
mb *mb.MB[*consensusproto.WatchLogEvent] mb *mb.MB[*consensusproto.WatchLogEvent]
mu sync.Mutex
err error err error
} }
@ -37,6 +39,8 @@ func (s *stream) WaitLogs() []*consensusproto.WatchLogEvent {
} }
func (s *stream) Err() error { func (s *stream) Err() error {
s.mu.Lock()
defer s.mu.Unlock()
return s.err return s.err
} }
@ -45,7 +49,9 @@ func (s *stream) readStream() {
for { for {
event, err := s.rpcStream.Recv() event, err := s.rpcStream.Recv()
if err != nil { if err != nil {
s.mu.Lock()
s.err = err s.err = err
s.mu.Unlock()
return return
} }
if err = s.mb.Add(event); err != nil { if err = s.mb.Add(event); err != nil {

View File

@ -5,24 +5,25 @@ grpcServer:
- 127.0.0.1:4630 - 127.0.0.1:4630
tls: false tls: false
account: account:
peerId: 12D3KooWC2SctmKSLWqmzsKCpQBo4iqNzbZhWivM3jbhovB4JFug peerId: 12D3KooWFqDLPcSZi74A1vVpDc8baTkGU6bd21AXcNxH8CFPMqp6
signingKey: Maen+w6qwWuS79RZyMbuW7wnWAox0+rMinAb/gsOSl8gz2BLCfMlwXjlo8NLKfFFZFNUzl0ANTxbrK45Be7CPw== peerKey: s6PUCRVry6ymxhyytNQcqSQVd2ECGyWNMIJB0FkyMUFZXbbOYSBb2yYPeQXrA9jdFdZDXyUSxtvzasvpSMpa6w==
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 signingKey: +UF/Do2KPeBLA0joKvnJj43jiH975JcHGjkLIkLR0p7FCFHnR1r/w4xLSa4RTjhEAQ3sDefjktShOJpalXnGvg==
encryptionKey: MIIEpQIBAAKCAQEA7NiHF065o9BfTTAWtAItg3KLqvFnRN2WVQMkjMZ/BukIj4UAd196ppexh2tnDvvqW53qVxFtXcW8oFqX9GmDJx61nnN/ce2FhXNB3aPMa7g3AchlVVB9RHyS8Z49HTkn3DVRi8I8EnbpWer35BjnpGOQ257O/kFpD1P5FzvxyTQ2gF50SyiwoDzibyT2VxgQqaDErr9BfFQKBZb8SEBeLACOlzjb2u0mCv7NeoZNfzl2KsqBC8tiCyfNahhauGfU9ZB7PtHMC1pJKTtPhXhNhQI8Rp39dd+Fr3kiTJl3Fe1f4bg4GDI7LbqCARVBbtCjsLEMi1BMzMS63bFPrPL9ewIDAQABAoIBAQCA261j+Oj3Pz8ad7diaGzqvz9N2dkdlpFb30HbdYNW9yI5M1t1lvTb/lwQGVcQx+5RujDs/gZKpnJhq+hQibdZaVPWyW/lRB0I5hRHyf5F/QuwZJ79M7VztXMdEcKeS6JsJHYhW6PjR97dlQEZkJM21RTS6CwmGOBX/o/fHDYICNxIqt4x7x1Hu+A9Qcs3LWvWq0qAkO48jSYBDeIFJ56BdXZacfIv9A7aCGWoVvih2vFIFEwdn+3z69FHmcW8JzVDK+WdkegtOlvuPcFGgDjS8cHq4zuKyEckur9EVm2Wer+GRdY2v7i9ypxiy/Ej4qJCqJLIa5rtWHmB9Dz7IyFBAoGBAPlIMpu9vAhAhJUeO48vsuEDdCn2ztyq2h4GwYcuNmfZUAnFdKRHHAfb48P7nR1uVCEEvnJYF9uUFkot8zljkDCoqc3J30sOd54PT2Jqn2vPhSWpjNJGW4Ku3CmZq/vfCH15z+bcr7whtlEswshE31bykbZlzCOSyW1tgfz2I+ydAoGBAPM6iEV6M74X+M4GoVCwUn9JMFRUX/JONOu4nfNT+1jDeABeXzVS3gzLSMJ/Vk/+1a/g6NFm73bt5PYHR8jG/jrT3xcTBPUiFj038w1MAM5Fsj2jSnIFRYFxwH8q0RfejWvKJRyWKUyTt7m43VRY9P01+YDfgt+VoLs94rV0PNr3AoGAahmWoL8S5xg+1hE2HG2a3zbPHIVV6oo1qA4MFPNQaMcPz/jg+oLhpV6sBOB1MO+ikyMnxBdGoEjZa90+5rA/0NYY3+QKTDHuK7IsgaEMFaEP9MXDkEQt8uNmBbbIgr2dKXrNSF+p1JMsvEQm64KU5Lb92fpd9s4lOZQgfYBuLekCgYEAwNvPg6+S6Y7edJZjQLSepVjmHmfMsDd81M/NRkx4Bvju5PPvcDul3+UsazRGvyVkUJH4aVnCVL3rB33cWIIYwZKP2R72llyR37bGXOu/088FtsQMWn59j1cf+HV91/xajHZ7mMAkPRj/3B6OOLxUfZZXoO0ZO6nMCcvXQGPLgR8CgYEA2W644EHrSwb4qsDsUmIEeKnjSejS8Vej4S5/g1YOyVzfWEr/5rtejw09Fv4U92SeYhp7Xp3C0UnRCduZKrpXIZJVPO8KgWLDtPi9KvHqDPzpQNRHMNrsXLpOLLv+bnnymWXjcyG8fRecU4sggaH4r1C/QyLPr+s/fLDyVUt7bC8=
apiServer: apiServer:
port: "8090" port: "8090"
nodes: nodes:
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz - peerId: 12D3KooWLn13hDrZ6YRGM517fHf2zS6qhPNRu18inLMpRqn1YGKu
address: 127.0.0.1:4430 address: 127.0.0.1:4430
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w== signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
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 encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y - peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431 address: 127.0.0.1:4431
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg== signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
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= encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd - peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432 address: 127.0.0.1:4432
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA== signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
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== encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
space: space:
gcTTL: 60 gcTTL: 60
syncPeriod: 10 syncPeriod: 10

View File

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

View File

@ -5,24 +5,25 @@ grpcServer:
- 127.0.0.1:4630 - 127.0.0.1:4630
tls: false tls: false
account: account:
peerId: 12D3KooWC2SctmKSLWqmzsKCpQBo4iqNzbZhWivM3jbhovB4JFug peerId: 12D3KooWFqDLPcSZi74A1vVpDc8baTkGU6bd21AXcNxH8CFPMqp6
signingKey: Maen+w6qwWuS79RZyMbuW7wnWAox0+rMinAb/gsOSl8gz2BLCfMlwXjlo8NLKfFFZFNUzl0ANTxbrK45Be7CPw== peerKey: s6PUCRVry6ymxhyytNQcqSQVd2ECGyWNMIJB0FkyMUFZXbbOYSBb2yYPeQXrA9jdFdZDXyUSxtvzasvpSMpa6w==
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 signingKey: +UF/Do2KPeBLA0joKvnJj43jiH975JcHGjkLIkLR0p7FCFHnR1r/w4xLSa4RTjhEAQ3sDefjktShOJpalXnGvg==
encryptionKey: MIIEpQIBAAKCAQEA7NiHF065o9BfTTAWtAItg3KLqvFnRN2WVQMkjMZ/BukIj4UAd196ppexh2tnDvvqW53qVxFtXcW8oFqX9GmDJx61nnN/ce2FhXNB3aPMa7g3AchlVVB9RHyS8Z49HTkn3DVRi8I8EnbpWer35BjnpGOQ257O/kFpD1P5FzvxyTQ2gF50SyiwoDzibyT2VxgQqaDErr9BfFQKBZb8SEBeLACOlzjb2u0mCv7NeoZNfzl2KsqBC8tiCyfNahhauGfU9ZB7PtHMC1pJKTtPhXhNhQI8Rp39dd+Fr3kiTJl3Fe1f4bg4GDI7LbqCARVBbtCjsLEMi1BMzMS63bFPrPL9ewIDAQABAoIBAQCA261j+Oj3Pz8ad7diaGzqvz9N2dkdlpFb30HbdYNW9yI5M1t1lvTb/lwQGVcQx+5RujDs/gZKpnJhq+hQibdZaVPWyW/lRB0I5hRHyf5F/QuwZJ79M7VztXMdEcKeS6JsJHYhW6PjR97dlQEZkJM21RTS6CwmGOBX/o/fHDYICNxIqt4x7x1Hu+A9Qcs3LWvWq0qAkO48jSYBDeIFJ56BdXZacfIv9A7aCGWoVvih2vFIFEwdn+3z69FHmcW8JzVDK+WdkegtOlvuPcFGgDjS8cHq4zuKyEckur9EVm2Wer+GRdY2v7i9ypxiy/Ej4qJCqJLIa5rtWHmB9Dz7IyFBAoGBAPlIMpu9vAhAhJUeO48vsuEDdCn2ztyq2h4GwYcuNmfZUAnFdKRHHAfb48P7nR1uVCEEvnJYF9uUFkot8zljkDCoqc3J30sOd54PT2Jqn2vPhSWpjNJGW4Ku3CmZq/vfCH15z+bcr7whtlEswshE31bykbZlzCOSyW1tgfz2I+ydAoGBAPM6iEV6M74X+M4GoVCwUn9JMFRUX/JONOu4nfNT+1jDeABeXzVS3gzLSMJ/Vk/+1a/g6NFm73bt5PYHR8jG/jrT3xcTBPUiFj038w1MAM5Fsj2jSnIFRYFxwH8q0RfejWvKJRyWKUyTt7m43VRY9P01+YDfgt+VoLs94rV0PNr3AoGAahmWoL8S5xg+1hE2HG2a3zbPHIVV6oo1qA4MFPNQaMcPz/jg+oLhpV6sBOB1MO+ikyMnxBdGoEjZa90+5rA/0NYY3+QKTDHuK7IsgaEMFaEP9MXDkEQt8uNmBbbIgr2dKXrNSF+p1JMsvEQm64KU5Lb92fpd9s4lOZQgfYBuLekCgYEAwNvPg6+S6Y7edJZjQLSepVjmHmfMsDd81M/NRkx4Bvju5PPvcDul3+UsazRGvyVkUJH4aVnCVL3rB33cWIIYwZKP2R72llyR37bGXOu/088FtsQMWn59j1cf+HV91/xajHZ7mMAkPRj/3B6OOLxUfZZXoO0ZO6nMCcvXQGPLgR8CgYEA2W644EHrSwb4qsDsUmIEeKnjSejS8Vej4S5/g1YOyVzfWEr/5rtejw09Fv4U92SeYhp7Xp3C0UnRCduZKrpXIZJVPO8KgWLDtPi9KvHqDPzpQNRHMNrsXLpOLLv+bnnymWXjcyG8fRecU4sggaH4r1C/QyLPr+s/fLDyVUt7bC8=
apiServer: apiServer:
port: "8090" port: "8090"
nodes: nodes:
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz - peerId: 12D3KooWLn13hDrZ6YRGM517fHf2zS6qhPNRu18inLMpRqn1YGKu
address: 127.0.0.1:4430 address: 127.0.0.1:4430
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w== signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
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 encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y - peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431 address: 127.0.0.1:4431
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg== signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
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= encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd - peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432 address: 127.0.0.1:4432
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA== signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
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== encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
space: space:
gcTTL: 60 gcTTL: 60
syncPeriod: 10 syncPeriod: 10

View File

@ -5,24 +5,25 @@ grpcServer:
- 127.0.0.1:4631 - 127.0.0.1:4631
tls: false tls: false
account: account:
peerId: 12D3KooWEycQPaaTbsZJ2rfZ7cKNFB57o44kKukwKkb7mUCo4Agh peerId: 12D3KooWA7AHfBCyNPQaMnffj8S7Z9kZzKG6X1apLgtyP1CgpXiJ
signingKey: 2Lxt8Qy52wZHC1T/5zYvT3o4LhZY++4d0Km2gOj5R1hMqMH+Knnt+8cBGONe9r0QdtiXom/AxzWFFf0ol0bBOg== peerKey: +KIj+xVyg241tP2So4JmRNGFFIgtzK1PWUo8El0e5x0ETXCrCksPkLsA8s6Xww0DJy92dyISwoBoMQ7XhLbdOw==
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= signingKey: +UF/Do2KPeBLA0joKvnJj43jiH975JcHGjkLIkLR0p7FCFHnR1r/w4xLSa4RTjhEAQ3sDefjktShOJpalXnGvg==
encryptionKey: MIIEpQIBAAKCAQEA7NiHF065o9BfTTAWtAItg3KLqvFnRN2WVQMkjMZ/BukIj4UAd196ppexh2tnDvvqW53qVxFtXcW8oFqX9GmDJx61nnN/ce2FhXNB3aPMa7g3AchlVVB9RHyS8Z49HTkn3DVRi8I8EnbpWer35BjnpGOQ257O/kFpD1P5FzvxyTQ2gF50SyiwoDzibyT2VxgQqaDErr9BfFQKBZb8SEBeLACOlzjb2u0mCv7NeoZNfzl2KsqBC8tiCyfNahhauGfU9ZB7PtHMC1pJKTtPhXhNhQI8Rp39dd+Fr3kiTJl3Fe1f4bg4GDI7LbqCARVBbtCjsLEMi1BMzMS63bFPrPL9ewIDAQABAoIBAQCA261j+Oj3Pz8ad7diaGzqvz9N2dkdlpFb30HbdYNW9yI5M1t1lvTb/lwQGVcQx+5RujDs/gZKpnJhq+hQibdZaVPWyW/lRB0I5hRHyf5F/QuwZJ79M7VztXMdEcKeS6JsJHYhW6PjR97dlQEZkJM21RTS6CwmGOBX/o/fHDYICNxIqt4x7x1Hu+A9Qcs3LWvWq0qAkO48jSYBDeIFJ56BdXZacfIv9A7aCGWoVvih2vFIFEwdn+3z69FHmcW8JzVDK+WdkegtOlvuPcFGgDjS8cHq4zuKyEckur9EVm2Wer+GRdY2v7i9ypxiy/Ej4qJCqJLIa5rtWHmB9Dz7IyFBAoGBAPlIMpu9vAhAhJUeO48vsuEDdCn2ztyq2h4GwYcuNmfZUAnFdKRHHAfb48P7nR1uVCEEvnJYF9uUFkot8zljkDCoqc3J30sOd54PT2Jqn2vPhSWpjNJGW4Ku3CmZq/vfCH15z+bcr7whtlEswshE31bykbZlzCOSyW1tgfz2I+ydAoGBAPM6iEV6M74X+M4GoVCwUn9JMFRUX/JONOu4nfNT+1jDeABeXzVS3gzLSMJ/Vk/+1a/g6NFm73bt5PYHR8jG/jrT3xcTBPUiFj038w1MAM5Fsj2jSnIFRYFxwH8q0RfejWvKJRyWKUyTt7m43VRY9P01+YDfgt+VoLs94rV0PNr3AoGAahmWoL8S5xg+1hE2HG2a3zbPHIVV6oo1qA4MFPNQaMcPz/jg+oLhpV6sBOB1MO+ikyMnxBdGoEjZa90+5rA/0NYY3+QKTDHuK7IsgaEMFaEP9MXDkEQt8uNmBbbIgr2dKXrNSF+p1JMsvEQm64KU5Lb92fpd9s4lOZQgfYBuLekCgYEAwNvPg6+S6Y7edJZjQLSepVjmHmfMsDd81M/NRkx4Bvju5PPvcDul3+UsazRGvyVkUJH4aVnCVL3rB33cWIIYwZKP2R72llyR37bGXOu/088FtsQMWn59j1cf+HV91/xajHZ7mMAkPRj/3B6OOLxUfZZXoO0ZO6nMCcvXQGPLgR8CgYEA2W644EHrSwb4qsDsUmIEeKnjSejS8Vej4S5/g1YOyVzfWEr/5rtejw09Fv4U92SeYhp7Xp3C0UnRCduZKrpXIZJVPO8KgWLDtPi9KvHqDPzpQNRHMNrsXLpOLLv+bnnymWXjcyG8fRecU4sggaH4r1C/QyLPr+s/fLDyVUt7bC8=
apiServer: apiServer:
port: "8091" port: "8091"
nodes: nodes:
- peerId: 12D3KooWC9DkXiYK8MiQb87ffW51ggZR4FWASadh4UENXdaa16iz - peerId: 12D3KooWLn13hDrZ6YRGM517fHf2zS6qhPNRu18inLMpRqn1YGKu
address: 127.0.0.1:4430 address: 127.0.0.1:4430
signingKey: yfFJv5klknUeG8rROCNTktCk5rsBvz16aEanYBAl9oYii+Q8XwH8mVXr5hHSiP+HYxEaSSozlMAAXUjdW2vK5w== signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
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 encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
- peerId: 12D3KooWC6sZYJXFagZtRjY4Jc4dzBLpEgYsUhJRauYheSAGk26y - peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
address: 127.0.0.1:4431 address: 127.0.0.1:4431
signingKey: mLzjMshSbtOkUKZha0bNIHvW9nlqOPX6VM/mvKicx6kh8ebP2mfrkCS0qz5GwlFEqTgtuSnWsHdvGZnuan2Ahg== signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
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= encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
- peerId: 12D3KooWFWyDckUJBtHtARzRDTRpo4XzeKAo8oN23MXh3Xwbp2fd - peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
address: 127.0.0.1:4432 address: 127.0.0.1:4432
signingKey: YpCGjsSuT8O6mkYTOExkdwNRODBaJ20hYJHFO/A/RUFUsUwxIME9X9FIp69VYvKuL6er973p0iG7UVVvLgLjnA== signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
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== encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
space: space:
gcTTL: 60 gcTTL: 60
syncPeriod: 10 syncPeriod: 10

View File

@ -3,9 +3,10 @@ grpcServer:
- 127.0.0.1:4530 - 127.0.0.1:4530
tls: false tls: false
account: account:
peerId: 12D3KooWAB7hjh7KWdLz1nxkb8VQ4BU9ZfMwjAFNyBB9NnJCw7AP peerId: 12D3KooWA1MZaN1U8NHDnkvbN5wsacRGvbn7dd341S4pAzXofSng
signingKey: vE+fJjNKXf7y8hW7IXerySK+Fr8b/9WRThM5/tBxww4FUNczjvzd67XXrdvOdZtYQ+QTDfwItNbLwbzLTEMOeA== peerKey: rLHblNZKOvJxnAKrwIlxkWy70J3aXDiCYVr8iV+PyQAC0LQLKUjXGJzqOdS4tMU0UUPGNo0VQx8q4YHqqt3KLQ==
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 signingKey: rLHblNZKOvJxnAKrwIlxkWy70J3aXDiCYVr8iV+PyQAC0LQLKUjXGJzqOdS4tMU0UUPGNo0VQx8q4YHqqt3KLQ==
encryptionKey: MIIEowIBAAKCAQEAyzE3C3bWEdKCJ4HbBfP0psg34ZsdmiZcflOu55aLLnl2ctzWv17SO6dU6C8XEoVtJA4V+tvfsnQTro6sIy7DDcDpGMnA7HmLHzK9GFKQyC/9EzEFg6s9F4A6ZkW/hyQNNfE7NQBokJj+uvSXzw7wb1b535hvg+o+ZPdeQQfcKFIqZKQWMXOHHSseVV4JH2kJ7BNgvmRU1EEkZ/l9FmrdvDDSUv+SgLz0ogESQv3yR/bwwa07BVaMCAdwAMZAcD04KUjEGpEmHfsDERYRNGvOJ5bnJSHTI9QEow1P53CtOMVQ9Ak3YhqyycGtvaVmrY/CfnFJzUbb8IDmvgW6jw/rrQIDAQABAoIBAD38mJdFvI6ZUp1szv1k6/jJUcrggEpbc5ISQ2RhF7qo0Uq/NkARVD9gj9V5MCe1TpNWPLxXwUl2gd6Zpcfh5x1WAYZPXiyF87wjxW4bGhIIGcN2DAGcBroZozc6BfDbPbB8FBzaMAwUsHkmTv2ayByfQwFERpjOqBQzJqzeEfq2cxFovcQdyhHk3WmfH1+zrGENs4IVVmfmIG1LzXehaXJ7jHqlryyKyKpUmXOmymEtSB5It60pl+9RNNlaez9OzreWgE4bQaeQU09I8105YdIISmvZWGZ6PsBo3ma+Rj+si7zYGLF5CsbGxT+U9olpiO/DW+UbfrDHy0bAArlDOD0CgYEA5dI1b1GDwAifd4fR6Zv64AMFAFMo5hWW1EHsUtXVo1UD0IgheI0oxg4aqs93SkL7uMVrM5rKjfstFcpWfaSfzy38+8mneRsbsI4d17RR5g0F4D+2/uLRYRRU74m4ThQjfP6wf+eDAM1+rdmT86cyQab5y1VU9hqd159xCderu+8CgYEA4lZ77Ygdy2mHmfdzFyQ6eJJhsC5FoapJWnaw7LISEiJgnAun+qeIl1r3yFbuNK1Wx55qfdvz4v7X0KJV8HwFgpxzT7CoUybT3SncItWPwi80tq/lxklZvq6LUeOiNQrpGvECCUrPQ3Wdl0lcmOiUw1GXliAQEVdzBOT+0hGMZiMCgYEAtZ76O47f39LwszXS3hs2l/HK8gbGO460M+olKRF0VC/LY/ExAmQL5Pkgefya+UUWSV866P1bNflaF+5fi8udv81IMHOctkiGCXFGhEEst/Fyw1WW+LenYGEA/oyH6qxfn1hng60iCnBbvGhGVDe9r8SVg+tbyWIfe1e1rWGThmECgYBltGkBpn2E7wmw5OGBj5T6owRkj5ZYe9V0YgtEgQvfvDTfSdmUp32YTZc0HePyJcXt80B1B8ZCxTMjHB8z7fbn5vdl4sLwgm0HX4z81ixAHMg6IzZD8Kf0KCiQhpJX9Wwj4BKDLGuQK6TB24RRbYmTbvGH0yaFNF+J3oCm0p3dMwKBgA1TTXLpbL5lnBaAaWAHYSV9rtqvBkyVfcnB9/Ez9MNSBOQIbk82w9Pb892qjcNhTAfgRNrYTd6JZl8Sov98T0OJW0uMHFV04NSqo+RLQTaGjMfrWQ2ZWfSM4tFkoWA2mFh+R8VblzTJObdu1zDyuVYscfTv3sFnV/QX+zJWJipB
mongo: mongo:
connect: mongodb://localhost:27017/?w=majority connect: mongodb://localhost:27017/?w=majority
database: consensus database: consensus

View File

@ -3,9 +3,10 @@ grpcServer:
- 127.0.0.1:4531 - 127.0.0.1:4531
tls: false tls: false
account: account:
peerId: 12D3KooWG3ZrWs8Q3kQhQeXp8RWw8FKb2cThTFwD1nbRMMNzf2xW peerId: 12D3KooWKyYmekF5ongQGMwBgx4ZsPDQiyFjHtd5ZfKGsoXTYY7h
signingKey: P3a0z3Um1QJ2lEwqcaNkVXwMaFz/Xmb2na4RqO79Lw5ch+KZVitiA6jifmRQkPm4z8e1wIf7Eel1VnhuhRuZVw== peerKey: jRWkSxzPtg8SF3rJ7oqhby6UvS6fnWGOO2GlAePHqkWW7xWHE1XC2R8Wt0E/4sFVhpam5OKqyIm9aDsWiILHmA==
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 signingKey: jRWkSxzPtg8SF3rJ7oqhby6UvS6fnWGOO2GlAePHqkWW7xWHE1XC2R8Wt0E/4sFVhpam5OKqyIm9aDsWiILHmA==
encryptionKey: MIIEpAIBAAKCAQEAy3UBKE5OifVxeU60KbYUQ9OFob6uixxauUVn8cn24ZX9C2qPAMLQGTYBcWp0GKILqRMgcDmDV1DXF4dNzSYQE4qFDvQ0C5ltoV9vDBAxhyDEN6nftD4K2vvn+fBVYYAXJp//I/2YcdZpOzu7KFHPst74tnFZB1+7LX0oGToGzevFKgqmvoQ1LUj7OqWnINBz4jA61h2WMp11j6/BO71kEeMdeMJyhmO+w6oFlLhd3b6Vsqd/nIc4SKh0yS3jdn+OchgQEMHvNL0KrvExPwdnzQGtU9E2nrf193loeFoCZayX29x+aDgTah2V8JlcN2do40q9h3dJJ6FCgJkk5gBz8wIDAQABAoIBADy0Ym4GP0TGaN8K7pJrc0xxdjO2UxnKkf8piEQKQJE6UU/wsU5G0hRTmsaePpmC7/u4aztQzbFlu2eXxUzqiG1sLRszHbxAQQefE+EDi+OHkUQSeV6sDE0eUC6w2KjIsR+jKVsxtSRyFt/HiKYVEuWJxaeZ1jhvBcgiya4NNC6IG/wS4JYG5iPs8QZZPDT+geR2y1jVQdttchVGxKbthMxDBPfSlG05QFhb/8frCfS+jqBHla1e3UhBfdlA6elZW+IxOoxoKvLLZtMrI5+3D162ZBsfoIGXuME3YqovMBdISnRQBbQ9gsSZlYQsosWofSd2JPxVOm7YdOmOIo4sEcECgYEA3F2W2vQLdxtJ+RaLPrGICtNTXwkP3Fi5KGT/QFGCguJpGo1Z3sGgL6dvD0iKBBCTcmyDj3eBGYW80B/2J+tRiAt/0ME413Pfa6txl7LgKNDlFgAb4/ycth0TocQQE2oL1OawHBr+BiE2b5IbIOyi8wsaQNdtORYzRLS9clieWKMCgYEA7Ft1H2/HAQMBOLeyyn2LMaPkewe5TM/6K+CoDA9orcoRmZ+B3ht2iBkcJE3Efa0c2YDDbL3GENfUzzntF91auyC/aKI3A8MxBZg/6QEiTytgcvbCSeXkwZUCJeNr+BAFLiWOE26sg8P2cJPT5JfjgPkqA4dLWvqwvMFe9LcInHECgYEArVoGSToAJvNVrthYM7puva1egX1cd8dn6OoCjjNQyuuXKOcXUo/ZFoPNbyVuRSJRC4tntx2Ydl5pmQP7nY2VdsMtCihmMb8ae9XDp0V050blX/g3+JKJKQ4YmoHk75DVu+a5lXJ6cJICA6TZKH5e9Xi/b1DIwEbBkAPqoCAseKcCgYEAxSTj5HzPeMCQ3EYdE1j0KUuS4CvpG3C+MqsIgEa6AXtygrjREfnGPG71UjKrmkgysBj+6EzCUHo2P0MJx8YST9NY1GW5jaHZ2djMNgWEIJUFtd6s4Aapb+5iBEhVXmu+ZmdcwkimDKH/hJdJPnqSgJlTue23pQNFN6vzEBs7S4ECgYBhY2YJL22+btVAYR6g/pOkn+50h8S/TtEH+NUL0SKnv8N96WvoBjUJapgNNrWPzzUgmGzS+uSweSTGM5LFeidNU4tEHZ1yNt7nrlnaJP2anGgVp3JcvNQiy1Ffwvs1efo0c8Tc+fORj9V4fhdctpSAoISETDtoGcZbQjUtB/aqYQ==
mongo: mongo:
connect: mongodb://localhost:27017/?w=majority connect: mongodb://localhost:27017/?w=majority
database: consensus database: consensus

View File

@ -3,9 +3,10 @@ grpcServer:
- 127.0.0.1:4532 - 127.0.0.1:4532
tls: false tls: false
account: account:
peerId: 12D3KooWS6PKUYH6Jedkjsut9ajgWSvn53Qz1LLACoPJX6dUbtCg peerId: 12D3KooWLgWXJyeG869h3Awf9s7Jt7dw9ZnNg5ZFkMFKSHs6Bify
signingKey: 11vXVlqQr2e/XMKALUPhMgnJEtZ1HKaDerxXvhNvYfXx1ZWt16PoEMpy/+ZHA1gw3ErI9+2/6auhjGC9InHskQ== peerKey: 6DyqyTRgR35/TNWpEbqVm8NbbmOULNuQDYEk6C+ltyyhbVs1bhOkA2nigRoE6JFip83k2yVjsa2r4ST85kW0OA==
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== signingKey: 6DyqyTRgR35/TNWpEbqVm8NbbmOULNuQDYEk6C+ltyyhbVs1bhOkA2nigRoE6JFip83k2yVjsa2r4ST85kW0OA==
encryptionKey: MIIEogIBAAKCAQEAqCZtyjHrM7jUZNyZNchUAgYIZb27YRRsfC6ca2xgdbtIjq0ts9af1+JQcmHMjGyxUTvLjx4I4IPJzDF5KYRwiGSWM4avhfxKxVToW0j8UlqQH+nbN7/TmmQfW8+L4CsgaXcf34uE+CfnyoUnwPoWLe/6SI1m5n/99PcWa9X8monNoTSMoeSOCm/csyK+BBGW9BTOMgo+2Ceyu44KcERl/pdkBGmba1xz3SogEq1m7cpG2Y0Hmd9dyHVJU2jSFczVJQkWF6RuifRoGcjdtbRrY5E8LsF2CM8HeeAZ/0g/q7yoR6D/nCrWaejszXObi+GNEo51EdJW+7gD8g2U6vUqkQIDAQABAoIBAG010FbjhxRntiLwF94Th2RtEKUrznil8DPTfipTEG9GvUBVf/puqhBn38H6fQSzT5MoF/STGEbhsX4an8v0RbaARgGfN375NoLlu6gWRjMiuLrRg1y5DTEYWDmkGf/1Yq68/QmOr0URff1N8Fzo0ODzHQZkOHH6rTGeDYTqTY78ZfU17yGXoNSmXycAqbTGczBP1RvyDRd4mIuBg11E/+A4GBxe8QaSZzJsyfvtBi7jUqKgdDDDI5Gz4x90NZ90L6jRFNvlhuosGETQ80oyNN1soa6tVSq7UhGI7+wcJDyaXQF32/TnqIXArScH5gRLxHiP+FfTDCHzl5iZG5m/D3UCgYEAzHe6oorAELbpcRaUJQayOkMJIAI7KP5EVI2IbP1fhBaW+5BYtzGlxKZOXWZA057E0pjwO99rmVNs2rW6mU0mCfw9hP3oWv4EgszU2DEx1+iHhNF6cy/zGDh3lgDNXgRPoBRR05IS1Ffs8uEgVfhiVjtiv4FyrVE9fY2cTH+7YXcCgYEA0od8pJLXOhcj1ap/1Y0phaHv//ulSqLBtKEQTy36zDw9DfcIozB8LCIK/Q/3nr4RHmd1YQVRDoTB9pX8eUuoJvM3Do9CJiH5/0PXFgIOZZsDXtl/TmL/1diHw2isttDCQF6I+q5lRYlbA+oqc8Vko2c5LQchXE24oz9670gFFjcCgYApDSjVlZH2SSMZZ3Ua8fs6o1bjrE8Abfx+FWR8rWpN9NMfct28+iTUFKfLLMp7MndF6Rriinrp78v9JVtviAPJIXGgj/HkwvdY45MgTNA7Dx6WVhCFq+zcwgmQfly9MZRjCXFcTwmkxHp4USbS2+mycn3jATRrA9KasKHe4g5XBQKBgH/xPtp1Mr9m2Kw9FbseMqG3rDcRI36cMsQnLdYwxz3fTetyuZkTGiNn/O2WCpI6SAUGMttnc78zBv1oYSsFw4cIP+llPnoWI+vxuoDxdvZgoke+PhPRLlEzai5jKrNfYu3jhbNy0LDVrK5QXMRGrcZwMNsgfjGuOgtbxMYuKok5AoGAImYTQ6e0fliVoHO5CjClQRpj3oKsTmB4hwtMofSZ+tFVPOakVM6P4K8UzMa2jcgz3+KgLAD8awpHv0ISO+qdSwG9MgnfIxhz8jxatgRBXdhICHrnqCqwZqyV0hrVmuUeg0uXPN5AisvfGEiGpkAPsQCo3bhAqMD+4QooKCgpz+Y=
mongo: mongo:
connect: mongodb://localhost:27017/?w=majority connect: mongodb://localhost:27017/?w=majority
database: consensus database: consensus

View File

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

View File

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

View File

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

View File

@ -42,6 +42,14 @@ func (s *service) Init(a *app.App) (err error) {
return err return err
} }
decodedPeerKey, err := keys.DecodeKeyFromString(
acc.PeerKey,
signingkey.NewSigningEd25519PrivKeyFromBytes,
nil)
if err != nil {
return err
}
identity, err := decodedSigningKey.GetPublic().Raw() identity, err := decodedSigningKey.GetPublic().Raw()
if err != nil { if err != nil {
return err return err
@ -49,10 +57,10 @@ func (s *service) Init(a *app.App) (err error) {
s.accountData = &account.AccountData{ s.accountData = &account.AccountData{
Identity: identity, Identity: identity,
PeerKey: decodedPeerKey,
SignKey: decodedSigningKey, SignKey: decodedSigningKey,
EncKey: decodedEncryptionKey, EncKey: decodedEncryptionKey,
} }
s.peerId = acc.PeerId
return nil return nil
} }

134
node/acl/service.go Normal file
View File

@ -0,0 +1,134 @@
package acl
import (
"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/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"time"
)
const CName = "node.acl"
var log = logger.NewNamed(CName)
func New() Service {
return &service{}
}
type Service interface {
CreateLog(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (firstRecId string, err error)
AddRecord(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (id string, err error)
Watch(ctx context.Context, spaceId, aclId string, h synchandler.SyncHandler) (err error)
UnWatch(aclId string) (err error)
app.Component
}
type service struct {
consService consensusclient.Service
account account.Service
}
func (s *service) Init(a *app.App) (err error) {
s.consService = a.MustComponent(consensusclient.CName).(consensusclient.Service)
s.account = a.MustComponent(account.CName).(account.Service)
return
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) CreateLog(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (firstRecId string, err error) {
logId, err := cidToByte(aclId)
if err != nil {
return
}
recId, _, payload, err := s.signAndMarshal(rawRec)
if err != nil {
return
}
if err = s.consService.AddLog(ctx, &consensusproto.Log{
Id: logId,
Records: []*consensusproto.Record{
{
Id: recId,
Payload: payload,
CreatedUnix: uint64(time.Now().Unix()),
},
},
}); err != nil {
return
}
return cidToString(recId)
}
func (s *service) AddRecord(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (id string, err error) {
logId, err := cidToByte(aclId)
if err != nil {
return
}
recId, prevId, payload, err := s.signAndMarshal(rawRec)
if err != nil {
return
}
if err = s.consService.AddRecord(ctx, logId, &consensusproto.Record{
Id: recId,
PrevId: prevId,
Payload: payload,
CreatedUnix: uint64(time.Now().Unix()),
}); err != nil {
return
}
return cidToString(recId)
}
func (s *service) Watch(ctx context.Context, spaceId, aclId string, h synchandler.SyncHandler) (err error) {
w, err := newWatcher(spaceId, aclId, h)
if err != nil {
return
}
if err = s.consService.Watch(w.logId, w); err != nil {
return err
}
return w.Ready(ctx)
}
func (s *service) UnWatch(aclId string) (err error) {
logId, err := cidToByte(aclId)
if err != nil {
return
}
return s.consService.UnWatch(logId)
}
func (s *service) signAndMarshal(rawRec *aclrecordproto.RawACLRecord) (recId, prevId, payload []byte, err error) {
var rec = &aclrecordproto.ACLRecord{}
if err = rec.Unmarshal(rawRec.Payload); err != nil {
return
}
if rec.PrevId != "" {
if prevId, err = cidToByte(rec.PrevId); err != nil {
return
}
}
rawRec.AcceptorIdentity = s.account.Account().Identity
if rawRec.AcceptorSignature, err = s.account.Account().SignKey.Sign(rawRec.Payload); err != nil {
return
}
if payload, err = rawRec.Marshal(); err != nil {
return
}
recCid, err := cid.NewCIDFromBytes(payload)
if err != nil {
return
}
recId, err = cidToByte(recCid)
return
}

195
node/acl/service_test.go Normal file
View File

@ -0,0 +1,195 @@
package acl
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/testutil/testaccount"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient/mock_consensusclient"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
"time"
)
var ctx = context.Background()
func TestService_CreateLog(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
var clog *consensusproto.Log
fx.mockClient.EXPECT().AddLog(ctx, gomock.Any()).Do(func(ctx context.Context, l *consensusproto.Log) {
clog = l
})
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
rec := &aclrecordproto.ACLRecord{
PrevId: "",
Identity: fx.account.Account().Identity,
Data: []byte{'1', '2', '3'},
Timestamp: time.Now().Unix(),
}
pl, _ := rec.Marshal()
firstRecId, err := fx.CreateLog(ctx, aclId, &aclrecordproto.RawACLRecord{
Payload: pl,
})
require.NoError(t, err)
aclIdBytes, _ := cidToByte(aclId)
firstRecIdBytes, _ := cidToByte(firstRecId)
assert.Equal(t, aclIdBytes, clog.Id)
assert.NotEmpty(t, firstRecIdBytes)
require.Len(t, clog.Records, 1)
var resultRawAcl = &aclrecordproto.RawACLRecord{}
require.NoError(t, resultRawAcl.Unmarshal(clog.Records[0].Payload))
valid, err := fx.account.Account().SignKey.GetPublic().Verify(resultRawAcl.Payload, resultRawAcl.AcceptorSignature)
require.NoError(t, err)
require.True(t, valid)
}
func TestService_AddRecord(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
var clog *consensusproto.Log
fx.mockClient.EXPECT().AddLog(ctx, gomock.Any()).Do(func(ctx context.Context, l *consensusproto.Log) {
clog = l
})
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
rec := &aclrecordproto.ACLRecord{
PrevId: "",
Identity: fx.account.Account().Identity,
Data: []byte{'1', '2', '3'},
Timestamp: time.Now().Unix(),
}
pl, _ := rec.Marshal()
firstRecId, err := fx.CreateLog(ctx, aclId, &aclrecordproto.RawACLRecord{
Payload: pl,
})
require.NoError(t, err)
aclIdBytes, _ := cidToByte(aclId)
firstRecIdBytes, _ := cidToByte(firstRecId)
assert.Equal(t, aclIdBytes, clog.Id)
assert.NotEmpty(t, firstRecIdBytes)
var addRec *consensusproto.Record
fx.mockClient.EXPECT().AddRecord(ctx, aclIdBytes, gomock.Any()).Do(func(ctx context.Context, logId []byte, rec *consensusproto.Record) {
addRec = rec
})
rec = &aclrecordproto.ACLRecord{
PrevId: firstRecId,
Identity: fx.account.Account().Identity,
Data: []byte{'1', '2', '3', '4'},
Timestamp: time.Now().Unix(),
}
pl, _ = rec.Marshal()
newRecId, err := fx.AddRecord(ctx, aclId, &aclrecordproto.RawACLRecord{
Payload: pl,
})
require.NoError(t, err)
assert.NotEmpty(t, newRecId)
assert.Equal(t, firstRecIdBytes, addRec.PrevId)
}
func TestService_Watch(t *testing.T) {
t.Run("remote error", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
var expErr = fmt.Errorf("error")
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
aclIdBytes, _ := cidToByte(aclId)
fx.mockClient.EXPECT().Watch(aclIdBytes, gomock.Any()).Do(func(aid []byte, w consensusclient.Watcher) {
assert.Equal(t, aclIdBytes, aid)
go func() {
time.Sleep(time.Millisecond * 10)
w.AddConsensusError(expErr)
}()
})
th := &testHandler{}
err := fx.Watch(ctx, "123", aclId, th)
assert.Equal(t, expErr, err)
})
t.Run("success", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
aclIdBytes, _ := cidToByte(aclId)
fx.mockClient.EXPECT().Watch(aclIdBytes, gomock.Any()).Do(func(aid []byte, w consensusclient.Watcher) {
assert.Equal(t, aclIdBytes, aid)
go func() {
time.Sleep(time.Millisecond * 10)
r1cid, _ := cid.NewCIDFromBytes([]byte("r1"))
r2cid, _ := cid.NewCIDFromBytes([]byte("r2"))
r1cidB, _ := cidToByte(r1cid)
r2cidB, _ := cidToByte(r2cid)
w.AddConsensusRecords([]*consensusproto.Record{
{
Id: r2cidB,
PrevId: r1cidB,
Payload: []byte("p1"),
},
{
Id: r1cidB,
Payload: []byte("p1"),
},
})
}()
})
th := &testHandler{}
err := fx.Watch(ctx, "123", aclId, th)
require.NoError(t, err)
})
}
func newFixture(t *testing.T) *fixture {
fx := &fixture{
a: new(app.App),
ctrl: gomock.NewController(t),
account: &testaccount.AccountTestService{},
}
fx.mockClient = mock_consensusclient.NewMockService(fx.ctrl)
fx.mockClient.EXPECT().Name().Return(consensusclient.CName).AnyTimes()
fx.mockClient.EXPECT().Init(gomock.Any()).AnyTimes()
fx.mockClient.EXPECT().Run(gomock.Any()).AnyTimes()
fx.mockClient.EXPECT().Close(gomock.Any()).AnyTimes()
fx.Service = New()
fx.a.Register(fx.account).Register(fx.mockClient).Register(fx.Service)
require.NoError(t, fx.a.Start(ctx))
return fx
}
type fixture struct {
Service
mockClient *mock_consensusclient.MockService
ctrl *gomock.Controller
a *app.App
account *testaccount.AccountTestService
}
func (fx *fixture) Finish(t *testing.T) {
require.NoError(t, fx.a.Close(ctx))
fx.ctrl.Finish()
}
type testHandler struct {
req *spacesyncproto.ObjectSyncMessage
}
func (t *testHandler) HandleMessage(ctx context.Context, senderId string, request *spacesyncproto.ObjectSyncMessage) (err error) {
t.req = request
return
}

19
node/acl/util.go Normal file
View File

@ -0,0 +1,19 @@
package acl
import "github.com/ipfs/go-cid"
func cidToString(b []byte) (s string, err error) {
rcid, err := cid.Cast(b)
if err != nil {
return
}
return rcid.String(), nil
}
func cidToByte(s string) (b []byte, err error) {
rcid, err := cid.Decode(s)
if err != nil {
return
}
return rcid.Bytes(), nil
}

16
node/acl/util_test.go Normal file
View File

@ -0,0 +1,16 @@
package acl
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/stretchr/testify/assert"
"testing"
)
func TestCIDLen(t *testing.T) {
s, _ := cid.NewCIDFromBytes([]byte("some data"))
t.Log(s, len(s))
b, _ := cidToByte(s)
t.Log(b, len(b))
s2, _ := cidToString(b)
assert.Equal(t, s, s2)
}

93
node/acl/watcher.go Normal file
View File

@ -0,0 +1,93 @@
package acl
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/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"go.uber.org/zap"
"sync"
)
func newWatcher(spaceId, aclId string, h synchandler.SyncHandler) (w *watcher, err error) {
w = &watcher{
aclId: aclId,
spaceId: spaceId,
handler: h,
ready: make(chan struct{}),
}
if w.logId, err = cidToByte(aclId); err != nil {
return nil, err
}
return
}
type watcher struct {
spaceId string
aclId string
logId []byte
handler synchandler.SyncHandler
ready chan struct{}
isReady sync.Once
err error
}
func (w *watcher) AddConsensusRecords(recs []*consensusproto.Record) {
w.isReady.Do(func() {
close(w.ready)
})
records := make([]*aclrecordproto.RawACLRecordWithId, 0, len(recs))
for _, rec := range recs {
recId, err := cidToString(rec.Id)
if err != nil {
log.Error("received invalid id from consensus node", zap.Error(err))
continue
}
records = append(records, &aclrecordproto.RawACLRecordWithId{
Payload: rec.Payload,
Id: recId,
})
}
aclReq := &aclrecordproto.ACLSyncMessage{
Content: &aclrecordproto.ACLSyncContentValue{
Value: &aclrecordproto.ACLSyncContentValue_AddRecords{
AddRecords: &aclrecordproto.ACLAddRecords{
Records: records,
},
},
},
}
payload, err := aclReq.Marshal()
if err != nil {
log.Error("acl payload marshal error", zap.Error(err))
return
}
req := &spacesyncproto.ObjectSyncMessage{
SpaceId: w.spaceId,
Payload: payload,
ObjectId: w.aclId,
}
if err = w.handler.HandleMessage(context.TODO(), "", req); err != nil {
log.Warn("handle message error", zap.Error(err))
}
}
func (w *watcher) AddConsensusError(err error) {
w.isReady.Do(func() {
w.err = err
close(w.ready)
})
}
func (w *watcher) Ready(ctx context.Context) (err error) {
select {
case <-w.ready:
return w.err
case <-ctx.Done():
return ctx.Err()
}
}

View File

@ -2,42 +2,43 @@ package nodespace
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
"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/pkg/acl/aclrecordproto"
) )
type rpcHandler struct { type rpcHandler struct {
s *service s *service
} }
func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpaceRequest) (resp *spacesyncproto.PushSpaceResponse, err error) { func (r *rpcHandler) PullSpace(ctx context.Context, request *spacesyncproto.PullSpaceRequest) (resp *spacesyncproto.PullSpaceResponse, err error) {
_, err = r.s.GetSpace(ctx, req.SpaceHeader.Id) sp, err := r.s.GetSpace(ctx, request.Id)
if err == nil {
err = spacesyncproto.ErrSpaceExists
return
}
if err != storage.ErrSpaceStorageMissing {
err = spacesyncproto.ErrUnexpected
return
}
payload := storage.SpaceStorageCreatePayload{
RecWithId: &aclrecordproto.RawACLRecordWithId{
Payload: req.AclPayload,
Id: req.AclPayloadId,
},
SpaceHeaderWithId: req.SpaceHeader,
}
st, err := r.s.spaceStorageProvider.CreateSpaceStorage(payload)
if err != nil { if err != nil {
err = spacesyncproto.ErrUnexpected if err != spacesyncproto.ErrSpaceMissing {
if err == storage.ErrSpaceStorageExists { err = spacesyncproto.ErrUnexpected
err = spacesyncproto.ErrSpaceExists
} }
return return
} }
st.Close()
description := sp.Description()
resp = &spacesyncproto.PullSpaceResponse{
SpaceHeader: description.SpaceHeader,
AclPayload: description.AclPayload,
AclPayloadId: description.AclId,
}
return
}
func (r *rpcHandler) PushSpace(ctx context.Context, req *spacesyncproto.PushSpaceRequest) (resp *spacesyncproto.PushSpaceResponse, err error) {
description := commonspace.SpaceDescription{
SpaceHeader: req.SpaceHeader,
AclId: req.AclPayloadId,
AclPayload: req.AclPayload,
}
err = r.s.AddSpace(ctx, description)
if err != nil {
return
}
resp = &spacesyncproto.PushSpaceResponse{}
return return
} }

View File

@ -7,7 +7,7 @@ import (
"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/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"
config2 "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/net/rpc/server" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
"time" "time"
@ -22,25 +22,24 @@ func New() Service {
} }
type Service interface { type Service interface {
AddSpace(ctx context.Context, description commonspace.SpaceDescription) (err error)
GetSpace(ctx context.Context, id string) (commonspace.Space, error) GetSpace(ctx context.Context, id string) (commonspace.Space, error)
app.ComponentRunnable app.ComponentRunnable
} }
type service struct { type service struct {
conf config2.Space conf config.Space
spaceCache ocache.OCache spaceCache ocache.OCache
commonSpace commonspace.Service commonSpace commonspace.Service
spaceStorageProvider storage.SpaceStorageProvider spaceStorageProvider storage.SpaceStorageProvider
} }
func (s *service) Init(a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
s.conf = a.MustComponent(config2.CName).(*config2.Config).Space s.conf = a.MustComponent(config.CName).(*config.Config).Space
s.commonSpace = a.MustComponent(commonspace.CName).(commonspace.Service) s.commonSpace = a.MustComponent(commonspace.CName).(commonspace.Service)
s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider) s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
s.spaceCache = ocache.New( s.spaceCache = ocache.New(
func(ctx context.Context, id string) (value ocache.Object, err error) { s.loadSpace,
return s.commonSpace.GetSpace(ctx, id)
},
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),
@ -64,6 +63,25 @@ func (s *service) GetSpace(ctx context.Context, id string) (commonspace.Space, e
return v.(commonspace.Space), nil return v.(commonspace.Space), nil
} }
func (s *service) AddSpace(ctx context.Context, description commonspace.SpaceDescription) (err error) {
return s.commonSpace.AddSpace(ctx, description)
}
func (s *service) loadSpace(ctx context.Context, id string) (value ocache.Object, err error) {
cc, err := s.commonSpace.NewSpace(ctx, id)
if err != nil {
return
}
ns, err := newNodeSpace(cc)
if err != nil {
return
}
if err = ns.Init(ctx); err != nil {
return
}
return ns, nil
}
func (s *service) Close(ctx context.Context) (err error) { func (s *service) Close(ctx context.Context) (err error) {
return s.spaceCache.Close() return s.spaceCache.Close()
} }

24
node/nodespace/space.go Normal file
View File

@ -0,0 +1,24 @@
package nodespace
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
)
func newNodeSpace(cc commonspace.Space) (commonspace.Space, error) {
return &nodeSpace{cc}, nil
}
type nodeSpace struct {
commonspace.Space
}
func (s *nodeSpace) Init(ctx context.Context) (err error) {
// try to push acl to consensus node
//
return s.Space.Init(ctx)
}
func (s *nodeSpace) Close() (err error) {
return s.Space.Close()
}

View File

@ -82,7 +82,7 @@ func createListStorage(db *pogreb.DB, root *aclrecordproto.RawACLRecordWithId) (
return return
} }
func (l *listStorage) ID() string { func (l *listStorage) Id() string {
return l.id return l.id
} }

View File

@ -9,7 +9,7 @@ import (
) )
func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) { func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) {
require.Equal(t, store.ID(), root.Id) require.Equal(t, store.Id(), root.Id)
aclRoot, err := store.Root() aclRoot, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -5,7 +5,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/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" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"go.uber.org/zap" "go.uber.org/zap"
"path" "path"
"sync" "sync"
@ -22,7 +22,7 @@ type spaceStorage struct {
spaceId string spaceId string
objDb *pogreb.DB objDb *pogreb.DB
keys spaceKeys keys spaceKeys
aclStorage storage2.ListStorage aclStorage storage.ListStorage
header *spacesyncproto.RawSpaceHeaderWithId header *spacesyncproto.RawSpaceHeaderWithId
mx sync.Mutex mx sync.Mutex
} }
@ -129,15 +129,15 @@ func createSpaceStorage(rootPath string, payload spacestorage.SpaceStorageCreate
return return
} }
func (s *spaceStorage) ID() string { func (s *spaceStorage) Id() string {
return s.spaceId return s.spaceId
} }
func (s *spaceStorage) TreeStorage(id string) (storage2.TreeStorage, error) { func (s *spaceStorage) TreeStorage(id string) (storage.TreeStorage, error) {
return newTreeStorage(s.objDb, id) return newTreeStorage(s.objDb, id)
} }
func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePayload) (ts storage2.TreeStorage, err error) { func (s *spaceStorage) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
// we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation // we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation
s.mx.Lock() s.mx.Lock()
defer s.mx.Unlock() defer s.mx.Unlock()
@ -145,7 +145,7 @@ func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePaylo
return createTreeStorage(s.objDb, payload) return createTreeStorage(s.objDb, payload)
} }
func (s *spaceStorage) ACLStorage() (storage2.ListStorage, error) { func (s *spaceStorage) ACLStorage() (storage.ListStorage, error) {
return s.aclStorage, nil return s.aclStorage, nil
} }

View File

@ -3,7 +3,7 @@ package storage
import ( import (
"context" "context"
"github.com/akrylysov/pogreb" "github.com/akrylysov/pogreb"
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "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"
) )
@ -86,7 +86,7 @@ func createTreeStorage(db *pogreb.DB, payload storage.TreeStorageCreatePayload)
return return
} }
func (t *treeStorage) ID() string { func (t *treeStorage) Id() string {
return t.id return t.id
} }

View File

@ -43,7 +43,7 @@ func (fx *fixture) stop(t *testing.T) {
} }
func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) { func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) {
require.Equal(t, payload.RootRawChange.Id, store.ID()) require.Equal(t, payload.RootRawChange.Id, store.Id())
root, err := store.Root() root, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -3,7 +3,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
config2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config" config "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys"
"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"
@ -46,8 +46,8 @@ func main() {
} }
flag.Parse() flag.Parse()
var configs []config2.Config var configs []config.Config
var nodes []config2.Node var nodes []config.Node
for _, n := range nodesMap.Nodes { for _, n := range nodesMap.Nodes {
cfg, err := genNodeConfig(n.Addresses, n.APIPort) cfg, err := genNodeConfig(n.Addresses, n.APIPort)
if err != nil { if err != nil {
@ -55,7 +55,7 @@ func main() {
} }
configs = append(configs, cfg) configs = append(configs, cfg)
node := config2.Node{ node := config.Node{
PeerId: cfg.Account.PeerId, PeerId: cfg.Account.PeerId,
Address: cfg.GrpcServer.ListenAddrs[0], Address: cfg.GrpcServer.ListenAddrs[0],
SigningKey: cfg.Account.SigningKey, SigningKey: cfg.Account.SigningKey,
@ -64,7 +64,7 @@ func main() {
nodes = append(nodes, node) nodes = append(nodes, node)
} }
var clientConfigs []config2.Config var clientConfigs []config.Config
for _, c := range nodesMap.Clients { for _, c := range nodesMap.Clients {
cfg, err := genClientConfig(c.Addresses, c.APIPort) cfg, err := genClientConfig(c.Addresses, c.APIPort)
if err != nil { if err != nil {
@ -143,96 +143,108 @@ func main() {
} }
} }
func genNodeConfig(addresses []string, apiPort string) (config2.Config, error) { func genNodeConfig(addresses []string, apiPort string) (config.Config, error) {
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048) encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
signKey, _, err := signingkey.GenerateRandomEd25519KeyPair() signKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
encEncKey, err := keys.EncodeKeyToString(encKey) encEncKey, err := keys.EncodeKeyToString(encKey)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
encSignKey, err := keys.EncodeKeyToString(signKey) encSignKey, err := keys.EncodeKeyToString(signKey)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
peerID, err := peer.IDFromSigningPubKey(signKey.GetPublic()) peerID, err := peer.IDFromSigningPubKey(signKey.GetPublic())
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
return config2.Config{ return config.Config{
Anytype: config2.Anytype{SwarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"}, Anytype: config.Anytype{SwarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"},
GrpcServer: config2.GrpcServer{ GrpcServer: config.GrpcServer{
ListenAddrs: addresses, ListenAddrs: addresses,
TLS: false, TLS: false,
}, },
Storage: config2.Storage{Path: "db"}, Storage: config.Storage{Path: "db"},
Account: config2.Account{ Account: config.Account{
PeerId: peerID.String(), PeerId: peerID.String(),
PeerKey: encSignKey,
SigningKey: encSignKey, SigningKey: encSignKey,
EncryptionKey: encEncKey, EncryptionKey: encEncKey,
}, },
APIServer: config2.APIServer{ APIServer: config.APIServer{
Port: apiPort, Port: apiPort,
}, },
Space: config2.Space{ Space: config.Space{
GCTTL: 60, GCTTL: 60,
SyncPeriod: 10, SyncPeriod: 10,
}, },
}, nil }, nil
} }
func genClientConfig(addresses []string, apiPort string) (config2.Config, error) { func genClientConfig(addresses []string, apiPort string) (config.Config, error) {
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048) encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
signKey, _, err := signingkey.GenerateRandomEd25519KeyPair() signKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
}
peerKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
if err != nil {
return config.Config{}, err
} }
encEncKey, err := keys.EncodeKeyToString(encKey) encEncKey, err := keys.EncodeKeyToString(encKey)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
encSignKey, err := keys.EncodeKeyToString(signKey) encSignKey, err := keys.EncodeKeyToString(signKey)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
peerID, err := peer.IDFromSigningPubKey(signKey.GetPublic()) encPeerKey, err := keys.EncodeKeyToString(peerKey)
if err != nil { if err != nil {
return config2.Config{}, err return config.Config{}, err
} }
return config2.Config{ peerID, err := peer.IDFromSigningPubKey(peerKey.GetPublic())
Anytype: config2.Anytype{SwarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"}, if err != nil {
GrpcServer: config2.GrpcServer{ return config.Config{}, err
}
return config.Config{
Anytype: config.Anytype{SwarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"},
GrpcServer: config.GrpcServer{
ListenAddrs: addresses, ListenAddrs: addresses,
TLS: false, TLS: false,
}, },
Storage: config2.Storage{Path: "db"}, Storage: config.Storage{Path: "db"},
Account: config2.Account{ Account: config.Account{
PeerId: peerID.String(), PeerId: peerID.String(),
PeerKey: encPeerKey,
SigningKey: encSignKey, SigningKey: encSignKey,
EncryptionKey: encEncKey, EncryptionKey: encEncKey,
}, },
APIServer: config2.APIServer{ APIServer: config.APIServer{
Port: apiPort, Port: apiPort,
}, },
Space: config2.Space{ Space: config.Space{
GCTTL: 60, GCTTL: 60,
SyncPeriod: 10, SyncPeriod: 10,
}, },
@ -266,12 +278,13 @@ func genConsensusConfig(addresses []string) (cconfig.Config, error) {
} }
return cconfig.Config{ return cconfig.Config{
GrpcServer: config2.GrpcServer{ GrpcServer: config.GrpcServer{
ListenAddrs: addresses, ListenAddrs: addresses,
TLS: false, TLS: false,
}, },
Account: config2.Account{ Account: config.Account{
PeerId: peerID.String(), PeerId: peerID.String(),
PeerKey: encSignKey,
SigningKey: encSignKey, SigningKey: encSignKey,
EncryptionKey: encEncKey, EncryptionKey: encEncKey,
}, },