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

Merge pull request #78 from anyproto/GO-1918-any-sync-deletion-updates

GO-1918: any sync deletion updates
This commit is contained in:
Mikhail Rakhmanov 2023-08-23 17:12:36 +02:00 committed by GitHub
commit 1b903118c6
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 920 additions and 231 deletions

View file

@ -2,7 +2,6 @@ package headsync
import (
"context"
"fmt"
"time"
"github.com/anyproto/any-sync/app/ldiff"
@ -15,6 +14,7 @@ import (
"github.com/anyproto/any-sync/commonspace/spacestorage"
"github.com/anyproto/any-sync/commonspace/spacesyncproto"
"github.com/anyproto/any-sync/commonspace/syncstatus"
"github.com/anyproto/any-sync/coordinator/coordinatorproto"
"github.com/anyproto/any-sync/net/peer"
"github.com/anyproto/any-sync/net/rpc/rpcerr"
"github.com/anyproto/any-sync/util/slice"
@ -128,19 +128,11 @@ func (d *diffSyncer) syncWithPeer(ctx context.Context, p peer.Peer) (err error)
newIds, changedIds, removedIds, err := d.diff.Diff(ctx, rdiff)
err = rpcerr.Unwrap(err)
if err != nil && err != spacesyncproto.ErrSpaceMissing {
if err == spacesyncproto.ErrSpaceIsDeleted {
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.RemovedFromNetwork)
}
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.ConnectionError)
return fmt.Errorf("diff error: %v", err)
if err != nil {
return d.onDiffError(ctx, p, cl, err)
}
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.Online)
if err == spacesyncproto.ErrSpaceMissing {
return d.sendPushSpaceRequest(ctx, p.Id(), cl)
}
totalLen := len(newIds) + len(changedIds) + len(removedIds)
// not syncing ids which were removed through settings document
missingIds := d.deletionState.Filter(newIds)
@ -167,6 +159,29 @@ func (d *diffSyncer) syncWithPeer(ctx context.Context, p peer.Peer) (err error)
return
}
func (d *diffSyncer) onDiffError(ctx context.Context, p peer.Peer, cl spacesyncproto.DRPCSpaceSyncClient, err error) error {
if err != spacesyncproto.ErrSpaceMissing {
if err == spacesyncproto.ErrSpaceIsDeleted {
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.RemovedFromNetwork)
} else {
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.ConnectionError)
}
return err
}
// in case space is missing on peer, we should send push request
err = d.sendPushSpaceRequest(ctx, p.Id(), cl)
if err != nil {
if err == coordinatorproto.ErrSpaceIsDeleted {
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.RemovedFromNetwork)
} else {
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.ConnectionError)
}
return err
}
d.syncStatus.SetNodesStatus(p.Id(), syncstatus.Online)
return nil
}
func (d *diffSyncer) sendPushSpaceRequest(ctx context.Context, peerId string, cl spacesyncproto.DRPCSpaceSyncClient) (err error) {
aclStorage, err := d.storage.AclStorage()
if err != nil {

View file

@ -3,7 +3,6 @@ package headsync
import (
"context"
"sync/atomic"
"time"
"github.com/anyproto/any-sync/app"
@ -45,9 +44,8 @@ type HeadSync interface {
}
type headSync struct {
spaceId string
spaceIsDeleted *atomic.Bool
syncPeriod int
spaceId string
syncPeriod int
periodicSync periodicsync.PeriodicSync
storage spacestorage.SpaceStorage
@ -74,7 +72,6 @@ func (h *headSync) Init(a *app.App) (err error) {
cfg := a.MustComponent("config").(config.ConfigGetter)
h.syncAcl = a.MustComponent(syncacl.CName).(syncacl.SyncAcl)
h.spaceId = shared.SpaceId
h.spaceIsDeleted = shared.SpaceIsDeleted
h.syncPeriod = cfg.GetSpace().SyncPeriod
h.configuration = a.MustComponent(nodeconf.CName).(nodeconf.NodeConf)
h.log = log.With(zap.String("spaceId", h.spaceId))
@ -87,10 +84,6 @@ func (h *headSync) Init(a *app.App) (err error) {
h.deletionState = a.MustComponent(deletionstate.CName).(deletionstate.ObjectDeletionState)
h.syncer = createDiffSyncer(h)
sync := func(ctx context.Context) (err error) {
// for clients cancelling the sync process
if h.spaceIsDeleted.Load() {
return spacesyncproto.ErrSpaceIsDeleted
}
return h.syncer.Sync(ctx)
}
h.periodicSync = periodicsync.NewPeriodicSync(h.syncPeriod, time.Minute, sync, h.log)
@ -115,9 +108,6 @@ func (h *headSync) Run(ctx context.Context) (err error) {
}
func (h *headSync) HandleRangeRequest(ctx context.Context, req *spacesyncproto.HeadSyncRequest) (resp *spacesyncproto.HeadSyncResponse, err error) {
if h.spaceIsDeleted.Load() {
return nil, spacesyncproto.ErrSpaceIsDeleted
}
return HandleRangeRequest(ctx, h.diff, req)
}

View file

@ -28,7 +28,6 @@ import (
"github.com/anyproto/any-sync/nodeconf/mock_nodeconf"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"sync/atomic"
"testing"
)
@ -70,8 +69,7 @@ type headSyncFixture struct {
func newHeadSyncFixture(t *testing.T) *headSyncFixture {
spaceState := &spacestate.SpaceState{
SpaceId: "spaceId",
SpaceIsDeleted: &atomic.Bool{},
SpaceId: "spaceId",
}
ctrl := gomock.NewController(t)
configurationMock := mock_nodeconf.NewMockService(ctrl)

View file

@ -0,0 +1,274 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anyproto/any-sync/commonspace (interfaces: Space)
// Package mock_commonspace is a generated GoMock package.
package mock_commonspace
import (
context "context"
reflect "reflect"
time "time"
commonspace "github.com/anyproto/any-sync/commonspace"
headsync "github.com/anyproto/any-sync/commonspace/headsync"
syncacl "github.com/anyproto/any-sync/commonspace/object/acl/syncacl"
objectsync "github.com/anyproto/any-sync/commonspace/objectsync"
objecttreebuilder "github.com/anyproto/any-sync/commonspace/objecttreebuilder"
spacestorage "github.com/anyproto/any-sync/commonspace/spacestorage"
spacesyncproto "github.com/anyproto/any-sync/commonspace/spacesyncproto"
syncstatus "github.com/anyproto/any-sync/commonspace/syncstatus"
peer "github.com/anyproto/any-sync/net/peer"
gomock "go.uber.org/mock/gomock"
)
// MockSpace is a mock of Space interface.
type MockSpace struct {
ctrl *gomock.Controller
recorder *MockSpaceMockRecorder
}
// MockSpaceMockRecorder is the mock recorder for MockSpace.
type MockSpaceMockRecorder struct {
mock *MockSpace
}
// NewMockSpace creates a new mock instance.
func NewMockSpace(ctrl *gomock.Controller) *MockSpace {
mock := &MockSpace{ctrl: ctrl}
mock.recorder = &MockSpaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockSpace) EXPECT() *MockSpaceMockRecorder {
return m.recorder
}
// Acl mocks base method.
func (m *MockSpace) Acl() syncacl.SyncAcl {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Acl")
ret0, _ := ret[0].(syncacl.SyncAcl)
return ret0
}
// Acl indicates an expected call of Acl.
func (mr *MockSpaceMockRecorder) Acl() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Acl", reflect.TypeOf((*MockSpace)(nil).Acl))
}
// Close mocks base method.
func (m *MockSpace) Close() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close")
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close.
func (mr *MockSpaceMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSpace)(nil).Close))
}
// DebugAllHeads mocks base method.
func (m *MockSpace) DebugAllHeads() []headsync.TreeHeads {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DebugAllHeads")
ret0, _ := ret[0].([]headsync.TreeHeads)
return ret0
}
// DebugAllHeads indicates an expected call of DebugAllHeads.
func (mr *MockSpaceMockRecorder) DebugAllHeads() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DebugAllHeads", reflect.TypeOf((*MockSpace)(nil).DebugAllHeads))
}
// DeleteTree mocks base method.
func (m *MockSpace) DeleteTree(arg0 context.Context, arg1 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteTree", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// DeleteTree indicates an expected call of DeleteTree.
func (mr *MockSpaceMockRecorder) DeleteTree(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTree", reflect.TypeOf((*MockSpace)(nil).DeleteTree), arg0, arg1)
}
// Description mocks base method.
func (m *MockSpace) Description() (commonspace.SpaceDescription, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Description")
ret0, _ := ret[0].(commonspace.SpaceDescription)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Description indicates an expected call of Description.
func (mr *MockSpaceMockRecorder) Description() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Description", reflect.TypeOf((*MockSpace)(nil).Description))
}
// GetNodePeers mocks base method.
func (m *MockSpace) GetNodePeers(arg0 context.Context) ([]peer.Peer, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetNodePeers", arg0)
ret0, _ := ret[0].([]peer.Peer)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetNodePeers indicates an expected call of GetNodePeers.
func (mr *MockSpaceMockRecorder) GetNodePeers(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNodePeers", reflect.TypeOf((*MockSpace)(nil).GetNodePeers), arg0)
}
// HandleMessage mocks base method.
func (m *MockSpace) HandleMessage(arg0 context.Context, arg1 objectsync.HandleMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HandleMessage", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// HandleMessage indicates an expected call of HandleMessage.
func (mr *MockSpaceMockRecorder) HandleMessage(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleMessage", reflect.TypeOf((*MockSpace)(nil).HandleMessage), arg0, arg1)
}
// HandleRangeRequest mocks base method.
func (m *MockSpace) HandleRangeRequest(arg0 context.Context, arg1 *spacesyncproto.HeadSyncRequest) (*spacesyncproto.HeadSyncResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HandleRangeRequest", arg0, arg1)
ret0, _ := ret[0].(*spacesyncproto.HeadSyncResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// HandleRangeRequest indicates an expected call of HandleRangeRequest.
func (mr *MockSpaceMockRecorder) HandleRangeRequest(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleRangeRequest", reflect.TypeOf((*MockSpace)(nil).HandleRangeRequest), arg0, arg1)
}
// HandleSyncRequest mocks base method.
func (m *MockSpace) HandleSyncRequest(arg0 context.Context, arg1 *spacesyncproto.ObjectSyncMessage) (*spacesyncproto.ObjectSyncMessage, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HandleSyncRequest", arg0, arg1)
ret0, _ := ret[0].(*spacesyncproto.ObjectSyncMessage)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// HandleSyncRequest indicates an expected call of HandleSyncRequest.
func (mr *MockSpaceMockRecorder) HandleSyncRequest(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleSyncRequest", reflect.TypeOf((*MockSpace)(nil).HandleSyncRequest), arg0, arg1)
}
// Id mocks base method.
func (m *MockSpace) Id() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string)
return ret0
}
// Id indicates an expected call of Id.
func (mr *MockSpaceMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockSpace)(nil).Id))
}
// Init mocks base method.
func (m *MockSpace) Init(arg0 context.Context) 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 *MockSpaceMockRecorder) Init(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockSpace)(nil).Init), arg0)
}
// Storage mocks base method.
func (m *MockSpace) Storage() spacestorage.SpaceStorage {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Storage")
ret0, _ := ret[0].(spacestorage.SpaceStorage)
return ret0
}
// Storage indicates an expected call of Storage.
func (mr *MockSpaceMockRecorder) Storage() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockSpace)(nil).Storage))
}
// StoredIds mocks base method.
func (m *MockSpace) StoredIds() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StoredIds")
ret0, _ := ret[0].([]string)
return ret0
}
// StoredIds indicates an expected call of StoredIds.
func (mr *MockSpaceMockRecorder) StoredIds() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoredIds", reflect.TypeOf((*MockSpace)(nil).StoredIds))
}
// SyncStatus mocks base method.
func (m *MockSpace) SyncStatus() syncstatus.StatusUpdater {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SyncStatus")
ret0, _ := ret[0].(syncstatus.StatusUpdater)
return ret0
}
// SyncStatus indicates an expected call of SyncStatus.
func (mr *MockSpaceMockRecorder) SyncStatus() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncStatus", reflect.TypeOf((*MockSpace)(nil).SyncStatus))
}
// TreeBuilder mocks base method.
func (m *MockSpace) TreeBuilder() objecttreebuilder.TreeBuilder {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TreeBuilder")
ret0, _ := ret[0].(objecttreebuilder.TreeBuilder)
return ret0
}
// TreeBuilder indicates an expected call of TreeBuilder.
func (mr *MockSpaceMockRecorder) TreeBuilder() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TreeBuilder", reflect.TypeOf((*MockSpace)(nil).TreeBuilder))
}
// TryClose mocks base method.
func (m *MockSpace) TryClose(arg0 time.Duration) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TryClose", arg0)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// TryClose indicates an expected call of TryClose.
func (mr *MockSpaceMockRecorder) TryClose(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryClose", reflect.TypeOf((*MockSpace)(nil).TryClose), arg0)
}

View file

@ -4,7 +4,6 @@ package objectsync
import (
"context"
"fmt"
"sync/atomic"
"time"
"github.com/anyproto/any-sync/app"
@ -64,8 +63,7 @@ type objectSync struct {
spaceStorage spacestorage.SpaceStorage
metric metric.Metric
spaceIsDeleted *atomic.Bool
handleQueue multiqueue.MultiQueue[HandleMessage]
handleQueue multiqueue.MultiQueue[HandleMessage]
}
func (s *objectSync) Init(a *app.App) (err error) {
@ -77,7 +75,6 @@ func (s *objectSync) Init(a *app.App) (err error) {
if mc != nil {
s.metric = mc.(metric.Metric)
}
s.spaceIsDeleted = sharedData.SpaceIsDeleted
s.spaceId = sharedData.SpaceId
s.handleQueue = multiqueue.New[HandleMessage](s.processHandleMessage, 30)
return nil
@ -160,9 +157,6 @@ func (s *objectSync) processHandleMessage(msg HandleMessage) {
func (s *objectSync) handleRequest(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) (response *spacesyncproto.ObjectSyncMessage, err error) {
log := log.With(zap.String("objectId", msg.ObjectId))
if s.spaceIsDeleted.Load() {
return nil, spacesyncproto.ErrSpaceIsDeleted
}
err = s.checkEmptyFullSync(log, msg)
if err != nil {
return nil, err
@ -176,9 +170,6 @@ func (s *objectSync) handleRequest(ctx context.Context, senderId string, msg *sp
func (s *objectSync) handleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) (err error) {
log := log.With(zap.String("objectId", msg.ObjectId))
if s.spaceIsDeleted.Load() {
return spacesyncproto.ErrSpaceIsDeleted
}
err = s.checkEmptyFullSync(log, msg)
if err != nil {
return err

View file

@ -2,11 +2,9 @@ package settings
import (
"context"
"github.com/anyproto/any-sync/commonspace/deletionmanager"
"sync/atomic"
"github.com/anyproto/any-sync/accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/deletionmanager"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/updatelistener"
@ -30,11 +28,10 @@ func New() Settings {
}
type settings struct {
account accountservice.Service
storage spacestorage.SpaceStorage
configuration nodeconf.NodeConf
treeBuilder objecttreebuilder.TreeBuilderComponent
spaceIsDeleted *atomic.Bool
account accountservice.Service
storage spacestorage.SpaceStorage
configuration nodeconf.NodeConf
treeBuilder objecttreebuilder.TreeBuilderComponent
settingsObject SettingsObject
}
@ -45,7 +42,6 @@ func (s *settings) Init(a *app.App) (err error) {
s.treeBuilder = a.MustComponent(objecttreebuilder.CName).(objecttreebuilder.TreeBuilderComponent)
sharedState := a.MustComponent(spacestate.CName).(*spacestate.SpaceState)
s.storage = a.MustComponent(spacestorage.CName).(spacestorage.SpaceStorage)
s.spaceIsDeleted = sharedState.SpaceIsDeleted
deps := Deps{
BuildFunc: func(ctx context.Context, id string, listener updatelistener.UpdateListener) (t synctree.SyncTree, err error) {

View file

@ -74,7 +74,6 @@ type Space interface {
DeleteTree(ctx context.Context, id string) (err error)
GetNodePeers(ctx context.Context) (peer []peer.Peer, err error)
SetDeleted(isDeleted bool)
HandleMessage(ctx context.Context, msg objectsync.HandleMessage) (err error)
HandleSyncRequest(ctx context.Context, req *spacesyncproto.ObjectSyncMessage) (resp *spacesyncproto.ObjectSyncMessage, err error)
@ -154,10 +153,6 @@ func (s *space) GetNodePeers(ctx context.Context) (peer []peer.Peer, err error)
return s.peerManager.GetNodePeers(ctx)
}
func (s *space) SetDeleted(isDeleted bool) {
s.state.SpaceIsDeleted.Swap(isDeleted)
}
func (s *space) Acl() syncacl.SyncAcl {
return s.aclList.(syncacl.SyncAcl)
}

View file

@ -1,3 +1,4 @@
//go:generate mockgen -destination mock_commonspace/mock_commonspace.go github.com/anyproto/any-sync/commonspace Space
package commonspace
import (
@ -147,20 +148,11 @@ func (s *spaceService) NewSpace(ctx context.Context, id string) (Space, error) {
}
}
}
var (
spaceIsClosed = &atomic.Bool{}
spaceIsDeleted = &atomic.Bool{}
)
isDeleted, err := st.IsSpaceDeleted()
if err != nil {
return nil, err
}
spaceIsDeleted.Swap(isDeleted)
spaceIsClosed := &atomic.Bool{}
state := &spacestate.SpaceState{
SpaceId: st.Id(),
SpaceIsDeleted: spaceIsDeleted,
SpaceIsClosed: spaceIsClosed,
TreesUsed: &atomic.Int32{},
SpaceId: st.Id(),
SpaceIsClosed: spaceIsClosed,
TreesUsed: &atomic.Int32{},
}
if s.config.KeepTreeDataInMemory {
state.TreeBuilderFunc = objecttree.BuildObjectTree
@ -188,8 +180,9 @@ func (s *spaceService) NewSpace(ctx context.Context, id string) (Space, error) {
Register(headsync.New())
sp := &space{
state: state,
app: spaceApp,
state: state,
app: spaceApp,
storage: st,
}
return sp, nil
}

View file

@ -10,7 +10,6 @@ const CName = "common.commonspace.spacestate"
type SpaceState struct {
SpaceId string
SpaceIsDeleted *atomic.Bool
SpaceIsClosed *atomic.Bool
TreesUsed *atomic.Int32
TreeBuilderFunc objecttree.BuildObjectTreeFunc

View file

@ -37,6 +37,8 @@ type Watcher interface {
type Service interface {
// AddLog adds new log to consensus servers
AddLog(ctx context.Context, rec *consensusproto.RawRecordWithId) (err error)
// DeleteLog deletes the log from the consensus node
DeleteLog(ctx context.Context, logId string) (err error)
// AddRecord adds new record to consensus servers
AddRecord(ctx context.Context, logId string, rec *consensusproto.RawRecord) (record *consensusproto.RawRecordWithId, err error)
// Watch starts watching to given logId and calls watcher when any relative event received
@ -97,6 +99,17 @@ func (s *service) AddLog(ctx context.Context, rec *consensusproto.RawRecordWithI
})
}
func (s *service) DeleteLog(ctx context.Context, logId string) (err error) {
return s.doClient(ctx, func(cl consensusproto.DRPCConsensusClient) error {
if _, err = cl.LogDelete(ctx, &consensusproto.LogDeleteRequest{
LogId: logId,
}); err != nil {
return rpcerr.Unwrap(err)
}
return nil
})
}
func (s *service) AddRecord(ctx context.Context, logId string, rec *consensusproto.RawRecord) (record *consensusproto.RawRecordWithId, err error) {
err = s.doClient(ctx, func(cl consensusproto.DRPCConsensusClient) error {
if record, err = cl.RecordAdd(ctx, &consensusproto.RecordAddRequest{

View file

@ -180,6 +180,10 @@ type testServer struct {
watchErrOnce bool
}
func (t *testServer) LogDelete(ctx context.Context, req *consensusproto.LogDeleteRequest) (*consensusproto.Ok, error) {
return &consensusproto.Ok{}, nil
}
func (t *testServer) LogAdd(ctx context.Context, req *consensusproto.LogAddRequest) (*consensusproto.Ok, error) {
if t.addLog != nil {
if err := t.addLog(ctx, req); err != nil {

View file

@ -80,6 +80,20 @@ func (mr *MockServiceMockRecorder) Close(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockService)(nil).Close), arg0)
}
// DeleteLog mocks base method.
func (m *MockService) DeleteLog(arg0 context.Context, arg1 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteLog", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// DeleteLog indicates an expected call of DeleteLog.
func (mr *MockServiceMockRecorder) DeleteLog(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLog", reflect.TypeOf((*MockService)(nil).DeleteLog), arg0, arg1)
}
// Init mocks base method.
func (m *MockService) Init(arg0 *app.App) error {
m.ctrl.T.Helper()

View file

@ -558,6 +558,50 @@ func (m *LogWatchEvent) GetError() *Err {
return nil
}
type LogDeleteRequest struct {
LogId string `protobuf:"bytes,1,opt,name=logId,proto3" json:"logId,omitempty"`
}
func (m *LogDeleteRequest) Reset() { *m = LogDeleteRequest{} }
func (m *LogDeleteRequest) String() string { return proto.CompactTextString(m) }
func (*LogDeleteRequest) ProtoMessage() {}
func (*LogDeleteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{9}
}
func (m *LogDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *LogDeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_LogDeleteRequest.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 *LogDeleteRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_LogDeleteRequest.Merge(m, src)
}
func (m *LogDeleteRequest) XXX_Size() int {
return m.Size()
}
func (m *LogDeleteRequest) XXX_DiscardUnknown() {
xxx_messageInfo_LogDeleteRequest.DiscardUnknown(m)
}
var xxx_messageInfo_LogDeleteRequest proto.InternalMessageInfo
func (m *LogDeleteRequest) GetLogId() string {
if m != nil {
return m.LogId
}
return ""
}
type Err struct {
Error ErrCodes `protobuf:"varint,1,opt,name=error,proto3,enum=consensusProto.ErrCodes" json:"error,omitempty"`
}
@ -566,7 +610,7 @@ func (m *Err) Reset() { *m = Err{} }
func (m *Err) String() string { return proto.CompactTextString(m) }
func (*Err) ProtoMessage() {}
func (*Err) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{9}
return fileDescriptor_b8d7f1c16b400059, []int{10}
}
func (m *Err) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -616,7 +660,7 @@ func (m *LogSyncContentValue) Reset() { *m = LogSyncContentValue{} }
func (m *LogSyncContentValue) String() string { return proto.CompactTextString(m) }
func (*LogSyncContentValue) ProtoMessage() {}
func (*LogSyncContentValue) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{10}
return fileDescriptor_b8d7f1c16b400059, []int{11}
}
func (m *LogSyncContentValue) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -713,7 +757,7 @@ func (m *LogSyncMessage) Reset() { *m = LogSyncMessage{} }
func (m *LogSyncMessage) String() string { return proto.CompactTextString(m) }
func (*LogSyncMessage) ProtoMessage() {}
func (*LogSyncMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{11}
return fileDescriptor_b8d7f1c16b400059, []int{12}
}
func (m *LogSyncMessage) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -773,7 +817,7 @@ func (m *LogHeadUpdate) Reset() { *m = LogHeadUpdate{} }
func (m *LogHeadUpdate) String() string { return proto.CompactTextString(m) }
func (*LogHeadUpdate) ProtoMessage() {}
func (*LogHeadUpdate) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{12}
return fileDescriptor_b8d7f1c16b400059, []int{13}
}
func (m *LogHeadUpdate) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -826,7 +870,7 @@ func (m *LogFullSyncRequest) Reset() { *m = LogFullSyncRequest{} }
func (m *LogFullSyncRequest) String() string { return proto.CompactTextString(m) }
func (*LogFullSyncRequest) ProtoMessage() {}
func (*LogFullSyncRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{13}
return fileDescriptor_b8d7f1c16b400059, []int{14}
}
func (m *LogFullSyncRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -879,7 +923,7 @@ func (m *LogFullSyncResponse) Reset() { *m = LogFullSyncResponse{} }
func (m *LogFullSyncResponse) String() string { return proto.CompactTextString(m) }
func (*LogFullSyncResponse) ProtoMessage() {}
func (*LogFullSyncResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_b8d7f1c16b400059, []int{14}
return fileDescriptor_b8d7f1c16b400059, []int{15}
}
func (m *LogFullSyncResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -933,6 +977,7 @@ func init() {
proto.RegisterType((*RecordAddRequest)(nil), "consensusProto.RecordAddRequest")
proto.RegisterType((*LogWatchRequest)(nil), "consensusProto.LogWatchRequest")
proto.RegisterType((*LogWatchEvent)(nil), "consensusProto.LogWatchEvent")
proto.RegisterType((*LogDeleteRequest)(nil), "consensusProto.LogDeleteRequest")
proto.RegisterType((*Err)(nil), "consensusProto.Err")
proto.RegisterType((*LogSyncContentValue)(nil), "consensusProto.LogSyncContentValue")
proto.RegisterType((*LogSyncMessage)(nil), "consensusProto.LogSyncMessage")
@ -946,58 +991,60 @@ func init() {
}
var fileDescriptor_b8d7f1c16b400059 = []byte{
// 806 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0xeb, 0x44,
0x10, 0x8f, 0xed, 0xfc, 0x9d, 0xf0, 0x12, 0x33, 0x0f, 0x21, 0x13, 0xf1, 0xf2, 0x22, 0x73, 0x09,
0x4f, 0x28, 0x0f, 0x82, 0x10, 0x42, 0x15, 0x42, 0x34, 0x4a, 0x95, 0x48, 0x69, 0x5a, 0x5c, 0x4a,
0x25, 0x90, 0x90, 0x5c, 0xef, 0xc6, 0xb5, 0x9a, 0x7a, 0x8d, 0xbd, 0x49, 0x9b, 0x2b, 0x1c, 0xb9,
0xf0, 0xb1, 0x90, 0xb8, 0xf4, 0xc8, 0x11, 0xb5, 0x17, 0x3e, 0x00, 0x1f, 0x00, 0x79, 0xfd, 0x27,
0xae, 0x93, 0x14, 0x10, 0xbd, 0xb4, 0x9e, 0x99, 0xdf, 0xfc, 0x66, 0xe6, 0xb7, 0xbb, 0xa3, 0xc0,
0x6b, 0x8b, 0xb9, 0x01, 0x75, 0x83, 0x45, 0xb0, 0xfe, 0xf2, 0x7c, 0xc6, 0xd9, 0x6b, 0xf1, 0x37,
0xe3, 0xed, 0x09, 0x07, 0x36, 0x52, 0xc7, 0x71, 0x68, 0xeb, 0xc7, 0xa0, 0x4c, 0x98, 0x8d, 0x0d,
0x90, 0x1d, 0xa2, 0x49, 0x1d, 0xa9, 0x5b, 0x33, 0x64, 0x87, 0xe0, 0x67, 0x50, 0xf1, 0xa9, 0xc5,
0x7c, 0x12, 0x68, 0x4a, 0x47, 0xe9, 0xd6, 0xfb, 0x2f, 0x7b, 0x0f, 0x13, 0x7b, 0x86, 0x79, 0x6d,
0x08, 0xc4, 0x99, 0xc3, 0x2f, 0xc6, 0xc4, 0x48, 0xf0, 0xfa, 0x6f, 0x12, 0xd4, 0xd2, 0x20, 0x6a,
0x50, 0xf1, 0xcc, 0xd5, 0x9c, 0x99, 0x11, 0xfb, 0x1b, 0x46, 0x62, 0xe2, 0xbb, 0x50, 0x0b, 0x1c,
0xdb, 0x35, 0xf9, 0xc2, 0xa7, 0x9a, 0x2c, 0x62, 0x6b, 0x07, 0xbe, 0x02, 0xd5, 0xb4, 0x2c, 0xea,
0x71, 0xe6, 0x8f, 0x09, 0x75, 0xb9, 0xc3, 0x57, 0x9a, 0x22, 0x40, 0x1b, 0x7e, 0xfc, 0x00, 0xde,
0x4c, 0x7c, 0x27, 0x29, 0x63, 0x51, 0x80, 0x37, 0x03, 0x59, 0xf4, 0xd7, 0xce, 0x15, 0x0d, 0xb8,
0x79, 0xe5, 0x69, 0xa5, 0x8e, 0xd4, 0x55, 0x8c, 0xcd, 0x80, 0xbe, 0x07, 0xcd, 0xdc, 0xa4, 0x8f,
0x8c, 0x14, 0xa9, 0x28, 0x27, 0x2a, 0xea, 0x2e, 0x94, 0x63, 0x19, 0xde, 0x86, 0xb2, 0xe7, 0xd3,
0xe5, 0x38, 0xd1, 0x38, 0xb6, 0xb0, 0x05, 0x55, 0x27, 0x19, 0x2f, 0xd2, 0x20, 0xb5, 0x11, 0xa1,
0x48, 0x4c, 0x6e, 0xc6, 0x63, 0x8b, 0xef, 0x50, 0x34, 0x9e, 0x36, 0x5d, 0x14, 0x4d, 0xaf, 0x1d,
0x7a, 0x11, 0xe4, 0xa3, 0x4b, 0x7d, 0x04, 0xcf, 0x26, 0xcc, 0xfe, 0x92, 0x10, 0x83, 0xfe, 0xb0,
0xa0, 0x01, 0xc7, 0x4f, 0xa1, 0x1c, 0x1d, 0x8e, 0x28, 0xfe, 0x2f, 0xce, 0x32, 0x86, 0xeb, 0xdf,
0x81, 0x1a, 0xf9, 0x33, 0x64, 0x6f, 0x41, 0x69, 0xce, 0xec, 0x74, 0x90, 0xc8, 0xc0, 0x8f, 0xd2,
0x12, 0xb2, 0x28, 0xf1, 0xce, 0xce, 0x12, 0x29, 0xf9, 0x21, 0x34, 0x27, 0xcc, 0x3e, 0x33, 0xb9,
0x75, 0x91, 0x70, 0xb7, 0xa0, 0x7a, 0x1d, 0xda, 0x63, 0x12, 0x68, 0x52, 0x47, 0xe9, 0xd6, 0x8c,
0xd4, 0xc6, 0x36, 0xc0, 0xc2, 0x4d, 0xa3, 0xb2, 0x88, 0x66, 0x3c, 0xfa, 0xcf, 0x92, 0x18, 0x5b,
0xf0, 0x0d, 0x97, 0xd4, 0xdd, 0xd5, 0x69, 0xe6, 0x66, 0xcb, 0xff, 0xed, 0x66, 0xe3, 0xfb, 0x50,
0xa2, 0xbe, 0xcf, 0x7c, 0x71, 0x22, 0xf5, 0xfe, 0xf3, 0x7c, 0xe2, 0xd0, 0xf7, 0x8d, 0x08, 0xa1,
0x7f, 0x02, 0xca, 0xd0, 0xf7, 0xb1, 0x97, 0x64, 0x84, 0x2d, 0x34, 0xfa, 0xda, 0x96, 0x8c, 0x01,
0x23, 0x34, 0x48, 0xd2, 0x7e, 0x94, 0xe1, 0xf9, 0x84, 0xd9, 0x27, 0x2b, 0xd7, 0x1a, 0x30, 0x97,
0x53, 0x97, 0x7f, 0x63, 0xce, 0x17, 0x14, 0xbf, 0x00, 0xb8, 0xa0, 0x26, 0x39, 0xf5, 0x88, 0xc9,
0x69, 0x7c, 0x8a, 0x2f, 0xf2, 0x64, 0x13, 0x66, 0x8f, 0x52, 0xd0, 0xa8, 0x60, 0x64, 0x52, 0x70,
0x0a, 0xcd, 0xd9, 0x62, 0x3e, 0x0f, 0x89, 0x63, 0xb1, 0xe3, 0x83, 0xd2, 0xb7, 0xb0, 0x1c, 0x3c,
0x44, 0x8e, 0x0a, 0x46, 0x3e, 0x19, 0xbf, 0x02, 0x75, 0xed, 0x0a, 0xbc, 0x90, 0x22, 0x56, 0xe5,
0xbd, 0x47, 0x09, 0x23, 0xe8, 0xa8, 0x60, 0x6c, 0xa4, 0xef, 0x57, 0xa0, 0xb4, 0x0c, 0x87, 0xd5,
0x57, 0xd0, 0x88, 0x35, 0x38, 0xa4, 0x41, 0x60, 0xda, 0x74, 0x63, 0x3b, 0x65, 0x5e, 0xa0, 0xfc,
0xf0, 0x05, 0x7e, 0x0e, 0x15, 0x2b, 0x12, 0xee, 0x91, 0x76, 0xf2, 0xf2, 0x1a, 0x49, 0x8e, 0xfe,
0xbd, 0xb8, 0x43, 0x6b, 0x15, 0xc3, 0x37, 0x18, 0xaa, 0x18, 0xd7, 0x16, 0xdf, 0xff, 0xe3, 0x06,
0xe9, 0x16, 0xe0, 0xa6, 0xbe, 0x4f, 0x5d, 0x84, 0x88, 0x3b, 0x94, 0xd7, 0xfc, 0x89, 0xab, 0xbc,
0xfa, 0x49, 0x82, 0x6a, 0x72, 0x7d, 0xb1, 0x01, 0x70, 0xea, 0xd2, 0x1b, 0x8f, 0x5a, 0x9c, 0x12,
0xb5, 0x80, 0xcf, 0xa0, 0x36, 0x61, 0xf6, 0xf0, 0xc6, 0x09, 0x78, 0xa0, 0x4a, 0xd8, 0x84, 0xfa,
0x84, 0xd9, 0x53, 0xc6, 0x0f, 0xd8, 0xc2, 0x25, 0xaa, 0x8c, 0x08, 0x8d, 0x88, 0x75, 0xc0, 0xdc,
0xd9, 0xdc, 0xb1, 0xb8, 0xaa, 0x84, 0x39, 0x07, 0xcc, 0x3f, 0x77, 0x08, 0xa1, 0xae, 0x5a, 0x0c,
0x21, 0x63, 0x77, 0x69, 0xce, 0x1d, 0x72, 0x1c, 0x9d, 0xad, 0x5a, 0x42, 0x15, 0xea, 0xc3, 0xf0,
0x9d, 0x1c, 0xcd, 0x66, 0x01, 0xe5, 0xea, 0x5f, 0x4a, 0xff, 0x4f, 0x09, 0x6a, 0x83, 0xa4, 0x63,
0xdc, 0x83, 0x72, 0xb4, 0xf9, 0x70, 0xdb, 0xe3, 0x58, 0x2f, 0xb1, 0x16, 0xe6, 0xc3, 0x47, 0x97,
0x38, 0x85, 0x5a, 0xba, 0xec, 0xb0, 0xb3, 0xa1, 0x43, 0x6e, 0x0f, 0xb6, 0xfe, 0x49, 0x29, 0x9c,
0x42, 0x35, 0xd9, 0x47, 0xf8, 0x72, 0x4b, 0x3b, 0xd9, 0xcd, 0xd7, 0x7a, 0xb1, 0x0b, 0x20, 0x56,
0x59, 0x57, 0xfa, 0x50, 0xda, 0xef, 0xff, 0x7a, 0xd7, 0x96, 0x6e, 0xef, 0xda, 0xd2, 0x1f, 0x77,
0x6d, 0xe9, 0x97, 0xfb, 0x76, 0xe1, 0xf6, 0xbe, 0x5d, 0xf8, 0xfd, 0xbe, 0x5d, 0xf8, 0x56, 0xdb,
0xf5, 0x23, 0xe0, 0xbc, 0x2c, 0xfe, 0x7d, 0xfc, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x98, 0x49,
0x74, 0x26, 0x27, 0x08, 0x00, 0x00,
// 833 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x8f, 0xdb, 0x54,
0x10, 0x8f, 0xed, 0x24, 0x9b, 0x4c, 0x68, 0x62, 0xa6, 0x08, 0x99, 0x88, 0xa6, 0x91, 0xb9, 0x84,
0x0a, 0xa5, 0x10, 0x84, 0x10, 0xaa, 0x10, 0x6a, 0x43, 0x56, 0x89, 0xe4, 0x66, 0x17, 0x97, 0x52,
0x09, 0x24, 0x24, 0xd7, 0xef, 0xc5, 0x6b, 0xd5, 0xf5, 0x33, 0xf6, 0x4b, 0xda, 0x5c, 0xe1, 0xc8,
0x85, 0xef, 0xc1, 0x17, 0x41, 0xe2, 0xd2, 0x23, 0x47, 0xb4, 0xfb, 0x15, 0xf8, 0x00, 0xc8, 0xcf,
0x7f, 0xe2, 0xb5, 0x93, 0x00, 0xa2, 0x97, 0x5d, 0xcf, 0xcc, 0x6f, 0x7e, 0x33, 0xf3, 0x7b, 0xef,
0x8d, 0x02, 0x77, 0x6d, 0xe6, 0x47, 0xd4, 0x8f, 0xd6, 0xd1, 0xee, 0x2b, 0x08, 0x19, 0x67, 0x77,
0xc5, 0xdf, 0x82, 0x77, 0x2c, 0x1c, 0xd8, 0xcd, 0x1d, 0xe7, 0xb1, 0xad, 0x9f, 0x83, 0x62, 0x30,
0x07, 0xbb, 0x20, 0xbb, 0x44, 0x93, 0x86, 0xd2, 0xa8, 0x6d, 0xca, 0x2e, 0xc1, 0xcf, 0xe0, 0x24,
0xa4, 0x36, 0x0b, 0x49, 0xa4, 0x29, 0x43, 0x65, 0xd4, 0x99, 0xdc, 0x1e, 0x5f, 0x4f, 0x1c, 0x9b,
0xd6, 0x0b, 0x53, 0x20, 0x9e, 0xb8, 0xfc, 0x62, 0x41, 0xcc, 0x0c, 0xaf, 0xff, 0x2e, 0x41, 0x3b,
0x0f, 0xa2, 0x06, 0x27, 0x81, 0xb5, 0xf5, 0x98, 0x95, 0xb0, 0xbf, 0x61, 0x66, 0x26, 0xbe, 0x0b,
0xed, 0xc8, 0x75, 0x7c, 0x8b, 0xaf, 0x43, 0xaa, 0xc9, 0x22, 0xb6, 0x73, 0xe0, 0x1d, 0x50, 0x2d,
0xdb, 0xa6, 0x01, 0x67, 0xe1, 0x82, 0x50, 0x9f, 0xbb, 0x7c, 0xab, 0x29, 0x02, 0x54, 0xf1, 0xe3,
0x07, 0xf0, 0x66, 0xe6, 0x7b, 0x94, 0x33, 0xd6, 0x05, 0xb8, 0x1a, 0x28, 0xa2, 0xbf, 0x76, 0x9f,
0xd3, 0x88, 0x5b, 0xcf, 0x03, 0xad, 0x31, 0x94, 0x46, 0x8a, 0x59, 0x0d, 0xe8, 0xf7, 0xa0, 0x57,
0x9a, 0xf4, 0xc8, 0x48, 0x89, 0x8a, 0x72, 0xa6, 0xa2, 0xee, 0x43, 0x33, 0x95, 0xe1, 0x6d, 0x68,
0x06, 0x21, 0xdd, 0x2c, 0x32, 0x8d, 0x53, 0x0b, 0xfb, 0xd0, 0x72, 0xb3, 0xf1, 0x12, 0x0d, 0x72,
0x1b, 0x11, 0xea, 0xc4, 0xe2, 0x56, 0x3a, 0xb6, 0xf8, 0x8e, 0x45, 0xe3, 0x79, 0xd3, 0x75, 0xd1,
0xf4, 0xce, 0xa1, 0xd7, 0x41, 0x3e, 0x7b, 0xa6, 0xcf, 0xe1, 0x86, 0xc1, 0x9c, 0xfb, 0x84, 0x98,
0xf4, 0x87, 0x35, 0x8d, 0x38, 0x7e, 0x0a, 0xcd, 0xe4, 0x70, 0x44, 0xf1, 0x7f, 0x71, 0x96, 0x29,
0x5c, 0xff, 0x0e, 0xd4, 0xc4, 0x5f, 0x20, 0x7b, 0x0b, 0x1a, 0x1e, 0x73, 0xf2, 0x41, 0x12, 0x03,
0x3f, 0xca, 0x4b, 0xc8, 0xa2, 0xc4, 0x3b, 0x07, 0x4b, 0xe4, 0xe4, 0x0f, 0xa1, 0x67, 0x30, 0xe7,
0x89, 0xc5, 0xed, 0x8b, 0x8c, 0xbb, 0x0f, 0xad, 0x17, 0xb1, 0xbd, 0x20, 0x91, 0x26, 0x0d, 0x95,
0x51, 0xdb, 0xcc, 0x6d, 0x1c, 0x00, 0xac, 0xfd, 0x3c, 0x2a, 0x8b, 0x68, 0xc1, 0xa3, 0xff, 0x2c,
0x89, 0xb1, 0x05, 0xdf, 0x6c, 0x43, 0xfd, 0x43, 0x9d, 0x16, 0x6e, 0xb6, 0xfc, 0xdf, 0x6e, 0x36,
0xbe, 0x0f, 0x0d, 0x1a, 0x86, 0x2c, 0x14, 0x27, 0xd2, 0x99, 0xdc, 0x2c, 0x27, 0xce, 0xc2, 0xd0,
0x4c, 0x10, 0xfa, 0x08, 0x54, 0x83, 0x39, 0x5f, 0x52, 0x8f, 0x72, 0x7a, 0x54, 0x39, 0xfd, 0x13,
0x50, 0x66, 0x61, 0x88, 0xe3, 0x8c, 0x3b, 0x0e, 0x76, 0x27, 0xda, 0x1e, 0xee, 0x29, 0x23, 0x34,
0xca, 0x0a, 0xfc, 0x28, 0xc3, 0x4d, 0x83, 0x39, 0x8f, 0xb6, 0xbe, 0x3d, 0x65, 0x3e, 0xa7, 0x3e,
0xff, 0xc6, 0xf2, 0xd6, 0x14, 0xbf, 0x00, 0xb8, 0xa0, 0x16, 0x79, 0x1c, 0x10, 0x8b, 0xd3, 0xf4,
0xbc, 0x6f, 0x95, 0xc9, 0x0c, 0xe6, 0xcc, 0x73, 0xd0, 0xbc, 0x66, 0x16, 0x52, 0x70, 0x09, 0xbd,
0xd5, 0xda, 0xf3, 0x62, 0xe2, 0xb4, 0xf1, 0xf4, 0x48, 0xf5, 0x3d, 0x2c, 0xa7, 0xd7, 0x91, 0xf3,
0x9a, 0x59, 0x4e, 0xc6, 0xaf, 0x40, 0xdd, 0xb9, 0xa2, 0x20, 0xa6, 0x48, 0xf5, 0x7b, 0xef, 0x28,
0x61, 0x02, 0x9d, 0xd7, 0xcc, 0x4a, 0xfa, 0x83, 0x13, 0x68, 0x6c, 0xe2, 0x61, 0xf5, 0x2d, 0x74,
0x53, 0x0d, 0x1e, 0xd2, 0x28, 0xb2, 0x1c, 0x5a, 0xd9, 0x63, 0x85, 0xb7, 0x2a, 0x5f, 0x7f, 0xab,
0x9f, 0xc3, 0x89, 0x9d, 0x08, 0x77, 0xa4, 0x9d, 0xb2, 0xbc, 0x66, 0x96, 0xa3, 0x7f, 0x2f, 0x6e,
0xdb, 0x4e, 0xc5, 0xf8, 0xb5, 0xc6, 0x2a, 0xa6, 0xb5, 0xc5, 0xf7, 0xff, 0xb8, 0x6b, 0xba, 0x0d,
0x58, 0xd5, 0xf7, 0x75, 0x17, 0x21, 0xe2, 0x0e, 0x95, 0x35, 0x7f, 0xcd, 0x55, 0xee, 0xfc, 0x24,
0x41, 0x2b, 0xbb, 0xbe, 0xd8, 0x05, 0x78, 0xec, 0xd3, 0x97, 0x01, 0xb5, 0x39, 0x25, 0x6a, 0x0d,
0x6f, 0x40, 0xdb, 0x60, 0xce, 0xec, 0xa5, 0x1b, 0xf1, 0x48, 0x95, 0xb0, 0x07, 0x1d, 0x83, 0x39,
0x4b, 0xc6, 0x4f, 0xd9, 0xda, 0x27, 0xaa, 0x8c, 0x08, 0xdd, 0x84, 0x75, 0xca, 0xfc, 0x95, 0xe7,
0xda, 0x5c, 0x55, 0xe2, 0x9c, 0x53, 0x16, 0x3e, 0x75, 0x09, 0xa1, 0xbe, 0x5a, 0x8f, 0x21, 0x0b,
0x7f, 0x63, 0x79, 0x2e, 0x39, 0x4f, 0xce, 0x56, 0x6d, 0xa0, 0x0a, 0x9d, 0x59, 0xfc, 0x4e, 0xce,
0x56, 0xab, 0x88, 0x72, 0xf5, 0x2f, 0x65, 0xf2, 0xab, 0x0c, 0xed, 0x69, 0xd6, 0x31, 0xde, 0x83,
0x66, 0xb2, 0x23, 0x71, 0xdf, 0xe3, 0xd8, 0xad, 0xbb, 0x3e, 0x96, 0xc3, 0x67, 0xcf, 0x70, 0x09,
0xed, 0x7c, 0x2d, 0xe2, 0xb0, 0xa2, 0x43, 0x69, 0x63, 0xf6, 0xff, 0x49, 0x29, 0x5c, 0x42, 0x2b,
0xdb, 0x5c, 0x78, 0x7b, 0x4f, 0x3b, 0xc5, 0x1d, 0xd9, 0xbf, 0x75, 0x08, 0x20, 0x96, 0xde, 0x48,
0xfa, 0x50, 0xc2, 0xfb, 0x42, 0xd3, 0x64, 0xf9, 0x54, 0xfb, 0x2b, 0xef, 0xa5, 0x7d, 0x23, 0x3e,
0x98, 0xfc, 0x76, 0x39, 0x90, 0x5e, 0x5d, 0x0e, 0xa4, 0x3f, 0x2f, 0x07, 0xd2, 0x2f, 0x57, 0x83,
0xda, 0xab, 0xab, 0x41, 0xed, 0x8f, 0xab, 0x41, 0xed, 0x5b, 0xed, 0xd0, 0x2f, 0x8e, 0xa7, 0x4d,
0xf1, 0xef, 0xe3, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x75, 0xd4, 0x24, 0x0c, 0x94, 0x08, 0x00,
0x00,
}
func (m *Log) Marshal() (dAtA []byte, err error) {
@ -1383,6 +1430,36 @@ func (m *LogWatchEvent) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *LogDeleteRequest) 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 *LogDeleteRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *LogDeleteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.LogId) > 0 {
i -= len(m.LogId)
copy(dAtA[i:], m.LogId)
i = encodeVarintConsensus(dAtA, i, uint64(len(m.LogId)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *Err) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -1869,6 +1946,19 @@ func (m *LogWatchEvent) Size() (n int) {
return n
}
func (m *LogDeleteRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.LogId)
if l > 0 {
n += 1 + l + sovConsensus(uint64(l))
}
return n
}
func (m *Err) Size() (n int) {
if m == nil {
return 0
@ -3139,6 +3229,88 @@ func (m *LogWatchEvent) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *LogDeleteRequest) 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 ErrIntOverflowConsensus
}
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: LogDeleteRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: LogDeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field LogId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConsensus
}
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 ErrInvalidLengthConsensus
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthConsensus
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.LogId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipConsensus(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthConsensus
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Err) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View file

@ -43,6 +43,7 @@ type DRPCConsensusClient interface {
LogAdd(ctx context.Context, in *LogAddRequest) (*Ok, error)
RecordAdd(ctx context.Context, in *RecordAddRequest) (*RawRecordWithId, error)
LogWatch(ctx context.Context) (DRPCConsensus_LogWatchClient, error)
LogDelete(ctx context.Context, in *LogDeleteRequest) (*Ok, error)
}
type drpcConsensusClient struct {
@ -112,10 +113,20 @@ func (x *drpcConsensus_LogWatchClient) RecvMsg(m *LogWatchEvent) error {
return x.MsgRecv(m, drpcEncoding_File_consensus_consensusproto_protos_consensus_proto{})
}
func (c *drpcConsensusClient) LogDelete(ctx context.Context, in *LogDeleteRequest) (*Ok, error) {
out := new(Ok)
err := c.cc.Invoke(ctx, "/consensusProto.Consensus/LogDelete", drpcEncoding_File_consensus_consensusproto_protos_consensus_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
type DRPCConsensusServer interface {
LogAdd(context.Context, *LogAddRequest) (*Ok, error)
RecordAdd(context.Context, *RecordAddRequest) (*RawRecordWithId, error)
LogWatch(DRPCConsensus_LogWatchStream) error
LogDelete(context.Context, *LogDeleteRequest) (*Ok, error)
}
type DRPCConsensusUnimplementedServer struct{}
@ -132,9 +143,13 @@ func (s *DRPCConsensusUnimplementedServer) LogWatch(DRPCConsensus_LogWatchStream
return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
func (s *DRPCConsensusUnimplementedServer) LogDelete(context.Context, *LogDeleteRequest) (*Ok, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
}
type DRPCConsensusDescription struct{}
func (DRPCConsensusDescription) NumMethods() int { return 3 }
func (DRPCConsensusDescription) NumMethods() int { return 4 }
func (DRPCConsensusDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
@ -164,6 +179,15 @@ func (DRPCConsensusDescription) Method(n int) (string, drpc.Encoding, drpc.Recei
&drpcConsensus_LogWatchStream{in1.(drpc.Stream)},
)
}, DRPCConsensusServer.LogWatch, true
case 3:
return "/consensusProto.Consensus/LogDelete", drpcEncoding_File_consensus_consensusproto_protos_consensus_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCConsensusServer).
LogDelete(
ctx,
in1.(*LogDeleteRequest),
)
}, DRPCConsensusServer.LogDelete, true
default:
return "", nil, nil, nil, false
}
@ -230,3 +254,19 @@ func (x *drpcConsensus_LogWatchStream) Recv() (*LogWatchRequest, error) {
func (x *drpcConsensus_LogWatchStream) RecvMsg(m *LogWatchRequest) error {
return x.MsgRecv(m, drpcEncoding_File_consensus_consensusproto_protos_consensus_proto{})
}
type DRPCConsensus_LogDeleteStream interface {
drpc.Stream
SendAndClose(*Ok) error
}
type drpcConsensus_LogDeleteStream struct {
drpc.Stream
}
func (x *drpcConsensus_LogDeleteStream) SendAndClose(m *Ok) error {
if err := x.MsgSend(m, drpcEncoding_File_consensus_consensusproto_protos_consensus_proto{}); err != nil {
return err
}
return x.CloseSend()
}

View file

@ -44,12 +44,14 @@ message Record {
service Consensus {
// AddLog adds new log to consensus
// LogAdd adds new log to consensus
rpc LogAdd(LogAddRequest) returns (Ok);
// AddRecord adds new record to log
// RecordAdd adds new record to log
rpc RecordAdd(RecordAddRequest) returns (RawRecordWithId);
// WatchLog fetches log and subscribes for a changes
// LogWatch fetches log and subscribes for a changes
rpc LogWatch(stream LogWatchRequest) returns (stream LogWatchEvent);
// LogDelete deletes the log from the consensus
rpc LogDelete(LogDeleteRequest) returns (Ok);
}
message Ok {}
@ -75,6 +77,10 @@ message LogWatchEvent {
Err error = 3;
}
message LogDeleteRequest {
string logId = 1;
}
message Err {
ErrCodes error = 1;
}

View file

@ -5,7 +5,6 @@ import (
"context"
"errors"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anyproto/any-sync/coordinator/coordinatorproto"
"github.com/anyproto/any-sync/net/peer"
"github.com/anyproto/any-sync/net/pool"
@ -27,11 +26,13 @@ func New() CoordinatorClient {
}
type CoordinatorClient interface {
ChangeStatus(ctx context.Context, spaceId string, deleteRaw *treechangeproto.RawTreeChangeWithId) (status *coordinatorproto.SpaceStatusPayload, err error)
ChangeStatus(ctx context.Context, spaceId string, conf *coordinatorproto.DeletionConfirmPayloadWithSignature) (status *coordinatorproto.SpaceStatusPayload, err error)
StatusCheckMany(ctx context.Context, spaceIds []string) (statuses []*coordinatorproto.SpaceStatusPayload, err error)
StatusCheck(ctx context.Context, spaceId string) (status *coordinatorproto.SpaceStatusPayload, err error)
SpaceSign(ctx context.Context, payload SpaceSignPayload) (receipt *coordinatorproto.SpaceReceiptWithSignature, err error)
FileLimitCheck(ctx context.Context, spaceId string, identity []byte) (limit uint64, err error)
NetworkConfiguration(ctx context.Context, currentId string) (*coordinatorproto.NetworkConfigurationResponse, error)
DeletionLog(ctx context.Context, lastRecordId string, limit int) (records []*coordinatorproto.DeletionLogRecord, err error)
app.Component
}
@ -57,13 +58,16 @@ func (c *coordinatorClient) Name() (name string) {
return CName
}
func (c *coordinatorClient) ChangeStatus(ctx context.Context, spaceId string, deleteRaw *treechangeproto.RawTreeChangeWithId) (status *coordinatorproto.SpaceStatusPayload, err error) {
func (c *coordinatorClient) ChangeStatus(ctx context.Context, spaceId string, conf *coordinatorproto.DeletionConfirmPayloadWithSignature) (status *coordinatorproto.SpaceStatusPayload, err error) {
confMarshalled, err := conf.Marshal()
if err != nil {
return nil, err
}
err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error {
resp, err := cl.SpaceStatusChange(ctx, &coordinatorproto.SpaceStatusChangeRequest{
SpaceId: spaceId,
DeletionPayloadId: deleteRaw.GetId(),
DeletionPayload: deleteRaw.GetRawChange(),
DeletionPayloadType: coordinatorproto.DeletionPayloadType_Tree,
DeletionPayload: confMarshalled,
DeletionPayloadType: coordinatorproto.DeletionPayloadType_Confirm,
})
if err != nil {
return rpcerr.Unwrap(err)
@ -74,6 +78,35 @@ func (c *coordinatorClient) ChangeStatus(ctx context.Context, spaceId string, de
return
}
func (c *coordinatorClient) DeletionLog(ctx context.Context, lastRecordId string, limit int) (records []*coordinatorproto.DeletionLogRecord, err error) {
err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error {
resp, err := cl.DeletionLog(ctx, &coordinatorproto.DeletionLogRequest{
AfterId: lastRecordId,
Limit: uint32(limit),
})
if err != nil {
return rpcerr.Unwrap(err)
}
records = resp.Records
return nil
})
return
}
func (c *coordinatorClient) StatusCheckMany(ctx context.Context, spaceIds []string) (statuses []*coordinatorproto.SpaceStatusPayload, err error) {
err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error {
resp, err := cl.SpaceStatusCheckMany(ctx, &coordinatorproto.SpaceStatusCheckManyRequest{
SpaceIds: spaceIds,
})
if err != nil {
return rpcerr.Unwrap(err)
}
statuses = resp.Payloads
return nil
})
return
}
func (c *coordinatorClient) StatusCheck(ctx context.Context, spaceId string) (status *coordinatorproto.SpaceStatusPayload, err error) {
err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error {
resp, err := cl.SpaceStatusCheck(ctx, &coordinatorproto.SpaceStatusCheckRequest{

View file

@ -9,7 +9,6 @@ import (
reflect "reflect"
app "github.com/anyproto/any-sync/app"
treechangeproto "github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
coordinatorclient "github.com/anyproto/any-sync/coordinator/coordinatorclient"
coordinatorproto "github.com/anyproto/any-sync/coordinator/coordinatorproto"
gomock "go.uber.org/mock/gomock"
@ -39,7 +38,7 @@ func (m *MockCoordinatorClient) EXPECT() *MockCoordinatorClientMockRecorder {
}
// ChangeStatus mocks base method.
func (m *MockCoordinatorClient) ChangeStatus(arg0 context.Context, arg1 string, arg2 *treechangeproto.RawTreeChangeWithId) (*coordinatorproto.SpaceStatusPayload, error) {
func (m *MockCoordinatorClient) ChangeStatus(arg0 context.Context, arg1 string, arg2 *coordinatorproto.DeletionConfirmPayloadWithSignature) (*coordinatorproto.SpaceStatusPayload, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChangeStatus", arg0, arg1, arg2)
ret0, _ := ret[0].(*coordinatorproto.SpaceStatusPayload)
@ -53,6 +52,21 @@ func (mr *MockCoordinatorClientMockRecorder) ChangeStatus(arg0, arg1, arg2 inter
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeStatus", reflect.TypeOf((*MockCoordinatorClient)(nil).ChangeStatus), arg0, arg1, arg2)
}
// DeletionLog mocks base method.
func (m *MockCoordinatorClient) DeletionLog(arg0 context.Context, arg1 string, arg2 int) ([]*coordinatorproto.DeletionLogRecord, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeletionLog", arg0, arg1, arg2)
ret0, _ := ret[0].([]*coordinatorproto.DeletionLogRecord)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// DeletionLog indicates an expected call of DeletionLog.
func (mr *MockCoordinatorClientMockRecorder) DeletionLog(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletionLog", reflect.TypeOf((*MockCoordinatorClient)(nil).DeletionLog), arg0, arg1, arg2)
}
// FileLimitCheck mocks base method.
func (m *MockCoordinatorClient) FileLimitCheck(arg0 context.Context, arg1 string, arg2 []byte) (uint64, error) {
m.ctrl.T.Helper()
@ -140,3 +154,18 @@ func (mr *MockCoordinatorClientMockRecorder) StatusCheck(arg0, arg1 interface{})
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatusCheck", reflect.TypeOf((*MockCoordinatorClient)(nil).StatusCheck), arg0, arg1)
}
// StatusCheckMany mocks base method.
func (m *MockCoordinatorClient) StatusCheckMany(arg0 context.Context, arg1 []string) ([]*coordinatorproto.SpaceStatusPayload, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StatusCheckMany", arg0, arg1)
ret0, _ := ret[0].([]*coordinatorproto.SpaceStatusPayload)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StatusCheckMany indicates an expected call of StatusCheckMany.
func (mr *MockCoordinatorClientMockRecorder) StatusCheckMany(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatusCheckMany", reflect.TypeOf((*MockCoordinatorClient)(nil).StatusCheckMany), arg0, arg1)
}

View file

@ -192,6 +192,8 @@ type SpaceSignRequest struct {
OldIdentity []byte `protobuf:"bytes,3,opt,name=oldIdentity,proto3" json:"oldIdentity,omitempty"`
// NewIdentitySignature is the new identity signed by the old one
NewIdentitySignature []byte `protobuf:"bytes,4,opt,name=newIdentitySignature,proto3" json:"newIdentitySignature,omitempty"`
// ForceRequest if true, forces the creating space receipt even if the space is deleted before
ForceRequest bool `protobuf:"varint,5,opt,name=forceRequest,proto3" json:"forceRequest,omitempty"`
}
func (m *SpaceSignRequest) Reset() { *m = SpaceSignRequest{} }
@ -255,6 +257,13 @@ func (m *SpaceSignRequest) GetNewIdentitySignature() []byte {
return nil
}
func (m *SpaceSignRequest) GetForceRequest() bool {
if m != nil {
return m.ForceRequest
}
return false
}
type SpaceStatusPayload struct {
Status SpaceStatus `protobuf:"varint,1,opt,name=status,proto3,enum=coordinator.SpaceStatus" json:"status,omitempty"`
DeletionTimestamp int64 `protobuf:"varint,2,opt,name=deletionTimestamp,proto3" json:"deletionTimestamp,omitempty"`
@ -1412,82 +1421,83 @@ func init() {
}
var fileDescriptor_d94f6f99586adae2 = []byte{
// 1194 bytes of a gzipped FileDescriptorProto
// 1208 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0x4d, 0x6f, 0x1b, 0x45,
0x18, 0xf6, 0xf8, 0x23, 0x89, 0x5f, 0xb7, 0xee, 0x66, 0x9a, 0xa6, 0x8b, 0x6b, 0x5c, 0x6b, 0x5b,
0x8a, 0x31, 0x55, 0x5a, 0xb9, 0x02, 0x51, 0x95, 0x43, 0xc1, 0x2d, 0x52, 0xaa, 0x36, 0x8d, 0x36,
0x09, 0x08, 0x7a, 0x40, 0x5b, 0xef, 0x24, 0x59, 0xc5, 0xde, 0x5d, 0x66, 0xc7, 0x6d, 0x72, 0x40,
0xe2, 0x27, 0x70, 0x85, 0x3b, 0x12, 0x07, 0x0e, 0xdc, 0xf9, 0x03, 0x1c, 0x7b, 0xe4, 0x58, 0x25,
0x7f, 0x04, 0xcd, 0xec, 0xcc, 0xee, 0xec, 0x7a, 0xed, 0x54, 0xe2, 0xc0, 0xc5, 0xf6, 0x3c, 0xf3,
0x7e, 0xce, 0xfb, 0x69, 0xf8, 0x64, 0x14, 0x04, 0xd4, 0xf5, 0x7c, 0x87, 0x05, 0xf4, 0x8e, 0xf6,
0x3b, 0xa4, 0x01, 0x0b, 0xee, 0x88, 0xcf, 0x48, 0xc7, 0x37, 0x04, 0x84, 0x1b, 0x1a, 0x64, 0xfd,
0x8a, 0xc0, 0xd8, 0x09, 0x9d, 0x11, 0xd9, 0xf1, 0x0e, 0x7c, 0x9b, 0xfc, 0x30, 0x25, 0x11, 0xc3,
0x26, 0x2c, 0x47, 0x1c, 0xdb, 0x74, 0x4d, 0xd4, 0x45, 0xbd, 0xba, 0xad, 0x8e, 0x78, 0x1d, 0x96,
0x0e, 0x89, 0xe3, 0x12, 0x6a, 0x96, 0xbb, 0xa8, 0x77, 0xc1, 0x96, 0x27, 0xdc, 0x85, 0x46, 0x30,
0x76, 0x37, 0x5d, 0xe2, 0x33, 0x8f, 0x9d, 0x98, 0x15, 0x71, 0xa9, 0x43, 0x78, 0x00, 0x6b, 0x3e,
0x79, 0xad, 0x8e, 0x5c, 0x9b, 0xc3, 0xa6, 0x94, 0x98, 0x55, 0x41, 0x5a, 0x78, 0x67, 0x31, 0xc0,
0xb1, 0x6d, 0xcc, 0x61, 0xd3, 0x68, 0xdb, 0x39, 0x19, 0x07, 0x8e, 0x8b, 0xef, 0xc2, 0x52, 0x24,
0x00, 0x61, 0x5c, 0x73, 0x60, 0x6e, 0xe8, 0x3e, 0x6a, 0x0c, 0xb6, 0xa4, 0xc3, 0xb7, 0x61, 0xd5,
0x25, 0x63, 0xc2, 0xbc, 0xc0, 0xdf, 0xf5, 0x26, 0x24, 0x62, 0xce, 0x24, 0x14, 0x0e, 0x54, 0xec,
0xd9, 0x0b, 0x6b, 0x0f, 0x56, 0xb5, 0x17, 0x89, 0xc2, 0xc0, 0x8f, 0x08, 0x7e, 0x08, 0xcb, 0x94,
0x8c, 0x88, 0x17, 0x32, 0xa1, 0xb5, 0x31, 0xb8, 0x35, 0xab, 0xd5, 0x8e, 0x09, 0xbe, 0xf1, 0xd8,
0x61, 0xe2, 0x83, 0xad, 0xd8, 0xac, 0x23, 0x78, 0x6f, 0x2e, 0x15, 0xbe, 0x0b, 0x97, 0x23, 0xed,
0x52, 0xba, 0x2a, 0x54, 0x5d, 0xb0, 0x8b, 0xae, 0x70, 0x1b, 0xea, 0x51, 0xf2, 0x88, 0x71, 0x30,
0x52, 0xc0, 0xfa, 0x1d, 0xc1, 0x05, 0x5d, 0xdb, 0xe2, 0x90, 0x86, 0x84, 0xd0, 0x4d, 0x57, 0x48,
0xa9, 0xdb, 0xf2, 0x84, 0x7b, 0x70, 0xc9, 0x19, 0x8d, 0x82, 0xa9, 0xcf, 0x72, 0x61, 0xcd, 0xc3,
0xdc, 0x14, 0x9f, 0xb0, 0xd7, 0x01, 0x3d, 0xda, 0x74, 0x45, 0x3c, 0xeb, 0x76, 0x0a, 0xe0, 0x0e,
0xc0, 0x2b, 0x67, 0xec, 0xb9, 0x7b, 0x3e, 0xf3, 0xc6, 0x66, 0xad, 0x8b, 0x7a, 0x55, 0x5b, 0x43,
0xac, 0x17, 0x70, 0xe5, 0x2b, 0x6f, 0x4c, 0x9e, 0x7a, 0x13, 0x8f, 0x0d, 0x0f, 0xc9, 0xe8, 0x48,
0x65, 0x61, 0x81, 0x01, 0xa8, 0xd8, 0x00, 0xcd, 0xb9, 0x72, 0xc6, 0x39, 0x6b, 0x03, 0xd6, 0xf3,
0xc2, 0x65, 0x40, 0xd7, 0xa0, 0x36, 0xe6, 0xa8, 0x90, 0x59, 0xb5, 0xe3, 0x83, 0x75, 0x0f, 0xae,
0x6a, 0x09, 0x94, 0x31, 0x67, 0xee, 0x0b, 0x5a, 0x7b, 0x60, 0xce, 0x32, 0x49, 0x35, 0xf7, 0x61,
0x39, 0xd4, 0x82, 0xd9, 0x18, 0x5c, 0x9f, 0x97, 0xad, 0x32, 0xb0, 0xb6, 0xa2, 0xb7, 0xee, 0xc3,
0xb5, 0xbc, 0xd8, 0x67, 0x8e, 0x7f, 0xa2, 0xec, 0x69, 0xc1, 0x8a, 0x34, 0x80, 0x17, 0x42, 0xa5,
0x57, 0xb7, 0x93, 0xb3, 0xf5, 0x02, 0xda, 0xc5, 0xac, 0xd2, 0xaa, 0x07, 0xb0, 0x22, 0xb5, 0xc4,
0xbc, 0xef, 0x60, 0x56, 0xc2, 0x60, 0xbd, 0x45, 0x39, 0x7f, 0x1d, 0xff, 0x80, 0x9c, 0xdf, 0x3a,
0xb4, 0x22, 0x94, 0x32, 0x93, 0x70, 0xcd, 0x5e, 0xf0, 0xe0, 0xe7, 0x40, 0x95, 0x7d, 0x39, 0x18,
0xdb, 0x70, 0x39, 0x07, 0xed, 0x9e, 0x84, 0x71, 0x5f, 0x69, 0x0e, 0xba, 0x19, 0xb7, 0x1e, 0xcd,
0xd2, 0xd9, 0x45, 0xcc, 0xd6, 0xd7, 0xb2, 0x56, 0xb3, 0x1e, 0xfe, 0xf7, 0x90, 0x3e, 0x80, 0x6b,
0x5b, 0x71, 0x61, 0x0c, 0x03, 0x7f, 0xdf, 0x3b, 0x98, 0x52, 0x87, 0xab, 0x56, 0x8f, 0xd7, 0x86,
0xfa, 0x68, 0x4a, 0x29, 0xe1, 0xa9, 0x2d, 0x9f, 0x2f, 0x05, 0xac, 0xbf, 0x10, 0xb4, 0x8b, 0xb9,
0xa5, 0x61, 0x3d, 0xb8, 0x34, 0xd2, 0x2f, 0x12, 0x21, 0x79, 0x38, 0x5b, 0xb1, 0xe5, 0x7c, 0xc5,
0x7e, 0x08, 0x35, 0x3f, 0x70, 0x49, 0x64, 0x56, 0x44, 0x6a, 0xac, 0x66, 0xdc, 0xdb, 0x0a, 0x5c,
0x62, 0xc7, 0xf7, 0xb8, 0x0f, 0xc6, 0x88, 0x12, 0x47, 0xb5, 0xcf, 0x3d, 0xdf, 0x3b, 0x16, 0xef,
0x5e, 0xb5, 0x67, 0x70, 0xcb, 0x83, 0x2a, 0x67, 0xd5, 0xda, 0x0d, 0xca, 0xb4, 0x9b, 0x36, 0xd4,
0x1d, 0xd7, 0xa5, 0x24, 0x8a, 0x48, 0x64, 0x96, 0x45, 0x3e, 0xa7, 0x00, 0xfe, 0x18, 0x6a, 0xec,
0x24, 0x94, 0x26, 0x35, 0x07, 0x57, 0x66, 0x4c, 0x12, 0xb1, 0x8c, 0x69, 0xac, 0x09, 0xdc, 0x50,
0x91, 0x16, 0x0f, 0x45, 0x27, 0x32, 0x10, 0xd9, 0x9e, 0x5b, 0x90, 0x62, 0xa8, 0x38, 0xc5, 0x16,
0xf7, 0xda, 0x3f, 0x11, 0xac, 0x17, 0xeb, 0xfb, 0x1f, 0xbb, 0x6e, 0x1b, 0xea, 0x2c, 0x19, 0x75,
0x35, 0x31, 0xea, 0x52, 0xc0, 0x7a, 0x04, 0x58, 0x59, 0xfc, 0x34, 0x38, 0xd0, 0x6a, 0xd7, 0xd9,
0x67, 0x5a, 0x6c, 0xd4, 0x31, 0x6d, 0x96, 0xdc, 0xd8, 0x8b, 0xaa, 0x59, 0x7a, 0x70, 0x39, 0x23,
0x45, 0xa6, 0xe1, 0x67, 0x62, 0x54, 0x06, 0x34, 0xe9, 0x2d, 0x9d, 0xc2, 0x22, 0x14, 0x2c, 0x9c,
0xcc, 0x56, 0xe4, 0xdc, 0x80, 0x43, 0x27, 0x7a, 0x16, 0xc8, 0x57, 0x5e, 0xb1, 0xd5, 0xd1, 0xfa,
0x05, 0xc1, 0xea, 0x0c, 0x23, 0x6e, 0x42, 0xd9, 0x53, 0xb6, 0x96, 0x3d, 0x77, 0xfe, 0x1c, 0xc0,
0x9f, 0x27, 0x3b, 0x43, 0x45, 0xf4, 0x85, 0x9b, 0x8b, 0x4d, 0xca, 0xed, 0x0f, 0x99, 0xc7, 0xac,
0xe6, 0x1e, 0xb3, 0xff, 0x13, 0x02, 0x78, 0x4c, 0x69, 0x40, 0x87, 0xa2, 0x28, 0x9a, 0x00, 0x7b,
0x3e, 0x39, 0x0e, 0xc9, 0x88, 0x11, 0xd7, 0x28, 0x61, 0x43, 0x4e, 0x62, 0xa1, 0x84, 0xb8, 0x06,
0xc2, 0x26, 0xac, 0xa5, 0x08, 0x4f, 0x33, 0xe2, 0xbb, 0x9e, 0x7f, 0x60, 0x94, 0x13, 0xda, 0x21,
0xaf, 0x1e, 0xe2, 0x1a, 0x15, 0x8c, 0xa1, 0x29, 0x90, 0xad, 0x80, 0x3d, 0x3e, 0xf6, 0x22, 0x16,
0x19, 0x55, 0x6c, 0x40, 0x43, 0xe8, 0x7b, 0xbe, 0xbf, 0x1f, 0x11, 0x66, 0xfc, 0x51, 0xee, 0xff,
0x08, 0x0d, 0xad, 0xed, 0xe0, 0xf5, 0xcc, 0xde, 0xa4, 0x84, 0x95, 0x70, 0x07, 0x5a, 0x7a, 0x77,
0x8a, 0xd5, 0x2a, 0x2b, 0x0c, 0x94, 0xbb, 0x57, 0x17, 0x3b, 0xcc, 0xa1, 0x9c, 0xbf, 0x9c, 0x93,
0xab, 0x1c, 0xaa, 0xf4, 0x9f, 0xc0, 0x8a, 0xaa, 0x41, 0xdc, 0x80, 0xe5, 0x5d, 0x4a, 0xc8, 0x17,
0xdb, 0x9b, 0x46, 0x89, 0x1f, 0xf8, 0xf8, 0xe5, 0x07, 0xc4, 0x5d, 0x19, 0xa6, 0x8f, 0xce, 0x31,
0xe1, 0xf0, 0x90, 0x27, 0x8d, 0x1f, 0x4d, 0x23, 0x8e, 0x54, 0xfa, 0xb7, 0xd3, 0xa4, 0xd2, 0x3a,
0x32, 0x5e, 0x81, 0x2a, 0x17, 0x1b, 0xcb, 0x94, 0x55, 0x66, 0xa0, 0xfe, 0x43, 0xb8, 0x3a, 0x27,
0x78, 0x78, 0x09, 0xca, 0xcf, 0x8f, 0x8c, 0x12, 0x5e, 0x85, 0x8b, 0x36, 0x99, 0x04, 0xaf, 0xc8,
0x36, 0x25, 0xa1, 0x43, 0x89, 0x81, 0x30, 0xc0, 0x52, 0x0c, 0x19, 0xe5, 0xc1, 0x6f, 0x35, 0x68,
0x68, 0x66, 0xe1, 0x27, 0x50, 0x4f, 0xb6, 0x3f, 0xfc, 0x7e, 0x41, 0x67, 0x4f, 0xf7, 0xe4, 0x56,
0x67, 0xde, 0xb5, 0xac, 0x84, 0x6f, 0xa1, 0x99, 0xdd, 0x3e, 0xb0, 0x95, 0xe1, 0x28, 0xdc, 0x7b,
0x5a, 0x37, 0x16, 0xd2, 0x48, 0xd1, 0xdf, 0xab, 0xb5, 0x3d, 0x9d, 0xf0, 0xf8, 0xe6, 0xbc, 0x39,
0x94, 0x11, 0xff, 0xc1, 0x39, 0x54, 0x52, 0xc1, 0x91, 0x4c, 0xd2, 0xdc, 0x0a, 0x81, 0x7b, 0x0b,
0xd9, 0xb5, 0x05, 0xa5, 0xf5, 0xd1, 0x3b, 0x50, 0x4a, 0x65, 0x2f, 0xd5, 0xca, 0xad, 0xcd, 0x5b,
0xbc, 0xc0, 0x50, 0x6d, 0xe3, 0x68, 0xdd, 0x3a, 0x8f, 0x2c, 0x75, 0xa8, 0x68, 0x7a, 0xe6, 0x1c,
0x5a, 0x30, 0x9e, 0x73, 0x0e, 0x2d, 0x1c, 0xc5, 0xdb, 0xd0, 0xd0, 0xf2, 0x12, 0x5f, 0x9f, 0xdf,
0x6e, 0x62, 0xd1, 0xdd, 0xf9, 0x04, 0xb1, 0xc4, 0x2f, 0x3f, 0xfd, 0xfb, 0xb4, 0x83, 0xde, 0x9c,
0x76, 0xd0, 0xdb, 0xd3, 0x0e, 0xfa, 0xf9, 0xac, 0x53, 0x7a, 0x73, 0xd6, 0x29, 0xfd, 0x73, 0xd6,
0x29, 0x7d, 0xd7, 0x5e, 0xf4, 0x37, 0xf0, 0xe5, 0x92, 0xf8, 0xba, 0xf7, 0x6f, 0x00, 0x00, 0x00,
0xff, 0xff, 0x82, 0x8b, 0x4c, 0x0c, 0x2d, 0x0e, 0x00, 0x00,
0x18, 0xf6, 0xf8, 0x23, 0xb1, 0x5f, 0xa7, 0xee, 0x66, 0x92, 0xa6, 0xc6, 0x35, 0xae, 0xb5, 0x2d,
0xc5, 0x98, 0x2a, 0xad, 0x5c, 0x81, 0xa8, 0xca, 0xa1, 0xe0, 0x16, 0x29, 0x55, 0x9b, 0x46, 0x93,
0x04, 0x04, 0x3d, 0xa0, 0xad, 0x77, 0x92, 0xac, 0x62, 0xef, 0x9a, 0xd9, 0x71, 0x9b, 0x1c, 0x90,
0xf8, 0x09, 0x5c, 0xf9, 0x01, 0x48, 0x1c, 0x38, 0x70, 0x47, 0xe2, 0xcc, 0xb1, 0x47, 0x8e, 0x55,
0xf2, 0x47, 0xd0, 0xcc, 0xce, 0x78, 0x67, 0xd7, 0x6b, 0xa7, 0x12, 0x07, 0x2e, 0xb6, 0xe7, 0x99,
0xf7, 0x73, 0xde, 0x4f, 0xc3, 0x27, 0x83, 0x20, 0x60, 0xae, 0xe7, 0x3b, 0x3c, 0x60, 0x77, 0x8c,
0xdf, 0x63, 0x16, 0xf0, 0xe0, 0x8e, 0xfc, 0x0c, 0x4d, 0x7c, 0x53, 0x42, 0xb8, 0x6a, 0x40, 0xf6,
0x5f, 0x08, 0xac, 0xdd, 0xb1, 0x33, 0xa0, 0xbb, 0xde, 0xa1, 0x4f, 0xe8, 0x0f, 0x13, 0x1a, 0x72,
0x5c, 0x87, 0xe5, 0x50, 0x60, 0x5b, 0x6e, 0x1d, 0xb5, 0x51, 0xa7, 0x42, 0xf4, 0x11, 0x6f, 0xc0,
0xd2, 0x11, 0x75, 0x5c, 0xca, 0xea, 0xf9, 0x36, 0xea, 0xac, 0x10, 0x75, 0xc2, 0x6d, 0xa8, 0x06,
0x43, 0x77, 0xcb, 0xa5, 0x3e, 0xf7, 0xf8, 0x69, 0xbd, 0x20, 0x2f, 0x4d, 0x08, 0xf7, 0x60, 0xdd,
0xa7, 0xaf, 0xf5, 0x51, 0x68, 0x73, 0xf8, 0x84, 0xd1, 0x7a, 0x51, 0x92, 0x66, 0xde, 0x61, 0x1b,
0x56, 0x0e, 0x02, 0x36, 0xa0, 0xca, 0xae, 0x7a, 0xa9, 0x8d, 0x3a, 0x65, 0x92, 0xc0, 0x6c, 0x0e,
0x38, 0xb2, 0x9f, 0x3b, 0x7c, 0x12, 0xee, 0x38, 0xa7, 0xc3, 0xc0, 0x71, 0xf1, 0x5d, 0x58, 0x0a,
0x25, 0x20, 0x1d, 0xa8, 0xf5, 0xea, 0x9b, 0xe6, 0x3b, 0x18, 0x0c, 0x44, 0xd1, 0xe1, 0xdb, 0xb0,
0xea, 0xd2, 0x21, 0xe5, 0x5e, 0xe0, 0xef, 0x79, 0x23, 0x1a, 0x72, 0x67, 0x34, 0x96, 0x4e, 0x16,
0xc8, 0xec, 0x85, 0xbd, 0x0f, 0xab, 0xc6, 0xab, 0x85, 0xe3, 0xc0, 0x0f, 0x29, 0x7e, 0x08, 0xcb,
0x8c, 0x0e, 0xa8, 0x37, 0xe6, 0x52, 0x6b, 0xb5, 0x77, 0x6b, 0x56, 0x2b, 0x89, 0x08, 0xbe, 0xf1,
0xf8, 0xd1, 0xd4, 0x4f, 0xa2, 0xd9, 0xec, 0x63, 0x78, 0x6f, 0x2e, 0x15, 0xbe, 0x0b, 0x6b, 0xa1,
0x71, 0xa9, 0x5c, 0x95, 0xaa, 0x56, 0x48, 0xd6, 0x15, 0x6e, 0x42, 0x25, 0x9c, 0x3e, 0x74, 0x14,
0xb0, 0x18, 0xb0, 0x7f, 0x43, 0xb0, 0x62, 0x6a, 0x5b, 0x1c, 0xf6, 0x31, 0xa5, 0x6c, 0xcb, 0x95,
0x52, 0x2a, 0x44, 0x9d, 0x70, 0x07, 0x2e, 0x3b, 0x83, 0x41, 0x30, 0xf1, 0x79, 0x2a, 0xf4, 0x69,
0x58, 0x98, 0xe2, 0x53, 0xfe, 0x3a, 0x60, 0xc7, 0x5b, 0xae, 0x8c, 0x79, 0x85, 0xc4, 0x00, 0x6e,
0x01, 0xbc, 0x72, 0x86, 0x9e, 0xbb, 0xef, 0x73, 0x6f, 0x28, 0xc3, 0x5c, 0x24, 0x06, 0x62, 0xbf,
0x80, 0x2b, 0x5f, 0x79, 0x43, 0xfa, 0xd4, 0x1b, 0x79, 0xbc, 0x7f, 0x44, 0x07, 0xc7, 0x3a, 0x53,
0x33, 0x0c, 0x40, 0xd9, 0x06, 0x18, 0xce, 0xe5, 0x13, 0xce, 0xd9, 0x9b, 0xb0, 0x91, 0x16, 0xae,
0x02, 0xba, 0x0e, 0xa5, 0xa1, 0x40, 0xa5, 0xcc, 0x22, 0x89, 0x0e, 0xf6, 0x3d, 0xb8, 0x6a, 0x24,
0x50, 0xc2, 0x9c, 0xb9, 0x2f, 0x68, 0xef, 0x43, 0x7d, 0x96, 0x49, 0xa9, 0xb9, 0x0f, 0xcb, 0x63,
0x23, 0x98, 0xd5, 0xde, 0xf5, 0x79, 0xd9, 0xaa, 0x02, 0x4b, 0x34, 0xbd, 0x7d, 0x1f, 0xae, 0xa5,
0xc5, 0x3e, 0x73, 0xfc, 0x53, 0x6d, 0x4f, 0x03, 0xca, 0xca, 0x00, 0x51, 0x08, 0x85, 0x4e, 0x85,
0x4c, 0xcf, 0xf6, 0x0b, 0x68, 0x66, 0xb3, 0x2a, 0xab, 0x1e, 0x40, 0x59, 0x69, 0x89, 0x78, 0xdf,
0xc1, 0xac, 0x29, 0x83, 0xfd, 0x16, 0xa5, 0xfc, 0x75, 0xfc, 0x43, 0x7a, 0x71, 0x7b, 0x31, 0x8a,
0x50, 0xc9, 0x9c, 0x86, 0x6b, 0xf6, 0x42, 0x04, 0x3f, 0x05, 0xea, 0xec, 0x4b, 0xc1, 0x98, 0xc0,
0x5a, 0x0a, 0xda, 0x3b, 0x1d, 0x47, 0xbd, 0xa7, 0xd6, 0x6b, 0x27, 0xdc, 0x7a, 0x34, 0x4b, 0x47,
0xb2, 0x98, 0xed, 0xaf, 0x55, 0xad, 0x26, 0x3d, 0xfc, 0xef, 0x21, 0x7d, 0x00, 0xd7, 0xb6, 0xa3,
0xc2, 0xe8, 0x07, 0xfe, 0x81, 0x77, 0x38, 0x61, 0x8e, 0x50, 0xad, 0x1f, 0xaf, 0x09, 0x95, 0xc1,
0x84, 0x31, 0x2a, 0x52, 0x5b, 0x3d, 0x5f, 0x0c, 0xd8, 0x7f, 0x22, 0x68, 0x66, 0x73, 0x2b, 0xc3,
0x3a, 0x70, 0x79, 0x60, 0x5e, 0x4c, 0x85, 0xa4, 0xe1, 0x64, 0xc5, 0xe6, 0xd3, 0x15, 0xfb, 0x21,
0x94, 0xfc, 0xc0, 0xa5, 0x61, 0xbd, 0x20, 0x53, 0x63, 0x35, 0xe1, 0xde, 0x76, 0xe0, 0x52, 0x12,
0xdd, 0xe3, 0x2e, 0x58, 0x03, 0x46, 0x1d, 0xdd, 0x3e, 0xf7, 0x7d, 0xef, 0x44, 0xbe, 0x7b, 0x91,
0xcc, 0xe0, 0xb6, 0x07, 0x45, 0xc1, 0x6a, 0xb4, 0x1b, 0x94, 0x68, 0x37, 0x4d, 0xa8, 0x38, 0xae,
0xcb, 0x68, 0x18, 0xd2, 0xb0, 0x9e, 0x97, 0xf9, 0x1c, 0x03, 0xf8, 0x63, 0x28, 0xf1, 0xd3, 0xb1,
0x32, 0xa9, 0xd6, 0xbb, 0x32, 0x63, 0x92, 0x8c, 0x65, 0x44, 0x63, 0x8f, 0xe0, 0x86, 0x8e, 0xb4,
0x7c, 0x28, 0x36, 0x52, 0x81, 0x48, 0xf6, 0xdc, 0x8c, 0x14, 0x43, 0xd9, 0x29, 0xb6, 0xb8, 0xd7,
0xfe, 0x81, 0x60, 0x23, 0x5b, 0xdf, 0xff, 0xd8, 0x75, 0x9b, 0x50, 0xe1, 0xd3, 0x51, 0x57, 0x92,
0xa3, 0x2e, 0x06, 0xec, 0x47, 0x80, 0xb5, 0xc5, 0x4f, 0x83, 0x43, 0xa3, 0x76, 0x9d, 0x03, 0x6e,
0xc4, 0x46, 0x1f, 0xe3, 0x66, 0x29, 0x8c, 0xbd, 0xa4, 0x9b, 0xa5, 0x07, 0x6b, 0x09, 0x29, 0x2a,
0x0d, 0x3f, 0x93, 0xa3, 0x32, 0x60, 0xd3, 0xde, 0xd2, 0xca, 0x2c, 0x42, 0xc9, 0x22, 0xc8, 0x88,
0x26, 0x17, 0x06, 0x1c, 0x39, 0xe1, 0xb3, 0x40, 0xbd, 0x72, 0x99, 0xe8, 0xa3, 0xfd, 0x0b, 0x82,
0xd5, 0x19, 0x46, 0x5c, 0x83, 0xbc, 0xa7, 0x6d, 0xcd, 0x7b, 0xee, 0xfc, 0x39, 0x80, 0x3f, 0x9f,
0xee, 0x0c, 0x05, 0xd9, 0x17, 0x6e, 0x2e, 0x36, 0x29, 0xb5, 0x3f, 0x24, 0x1e, 0xb3, 0x98, 0x7a,
0xcc, 0xee, 0x4f, 0x08, 0xe0, 0x31, 0x63, 0x01, 0xeb, 0xcb, 0xa2, 0xa8, 0x01, 0xec, 0xfb, 0xf4,
0x64, 0x4c, 0x07, 0x9c, 0xba, 0x56, 0x0e, 0x5b, 0x6a, 0x12, 0x4b, 0x25, 0xd4, 0xb5, 0x10, 0xae,
0xc3, 0x7a, 0x8c, 0x88, 0x34, 0xa3, 0xbe, 0xeb, 0xf9, 0x87, 0x56, 0x7e, 0x4a, 0xdb, 0x17, 0xd5,
0x43, 0x5d, 0xab, 0x80, 0x31, 0xd4, 0x24, 0xb2, 0x1d, 0xf0, 0xc7, 0x27, 0x5e, 0xc8, 0x43, 0xab,
0x88, 0x2d, 0xa8, 0x4a, 0x7d, 0xcf, 0x0f, 0x0e, 0x42, 0xca, 0xad, 0xdf, 0xf3, 0xdd, 0x1f, 0xa1,
0x6a, 0xb4, 0x1d, 0xbc, 0x91, 0xd8, 0x9b, 0xb4, 0xb0, 0x1c, 0x6e, 0x41, 0xc3, 0xec, 0x4e, 0x91,
0x5a, 0x6d, 0x85, 0x85, 0x52, 0xf7, 0xfa, 0x62, 0x97, 0x3b, 0x4c, 0xf0, 0xe7, 0x53, 0x72, 0xb5,
0x43, 0x85, 0xee, 0x13, 0x28, 0xeb, 0x1a, 0xc4, 0x55, 0x58, 0xde, 0x63, 0x94, 0x7e, 0xb1, 0xb3,
0x65, 0xe5, 0xc4, 0x41, 0x8c, 0x5f, 0x71, 0x40, 0xc2, 0x95, 0x7e, 0xfc, 0xe8, 0x02, 0x93, 0x0e,
0xf7, 0x45, 0xd2, 0xf8, 0xe1, 0x24, 0x14, 0x48, 0xa1, 0x7b, 0x3b, 0x4e, 0x2a, 0xa3, 0x23, 0xe3,
0x32, 0x14, 0x85, 0xd8, 0x48, 0xa6, 0xaa, 0x32, 0x0b, 0x75, 0x1f, 0xc2, 0xd5, 0x39, 0xc1, 0xc3,
0x4b, 0x90, 0x7f, 0x7e, 0x6c, 0xe5, 0xf0, 0x2a, 0x5c, 0x22, 0x74, 0x14, 0xbc, 0xa2, 0x3b, 0x8c,
0x8e, 0x1d, 0x46, 0x2d, 0x84, 0x01, 0x96, 0x22, 0xc8, 0xca, 0xf7, 0x7e, 0x2d, 0x41, 0xd5, 0x30,
0x0b, 0x3f, 0x81, 0xca, 0x74, 0xfb, 0xc3, 0xef, 0x67, 0x74, 0xf6, 0x78, 0x97, 0x6e, 0xb4, 0xe6,
0x5d, 0xab, 0x4a, 0xf8, 0x16, 0x6a, 0xc9, 0xed, 0x03, 0xdb, 0x09, 0x8e, 0xcc, 0xbd, 0xa7, 0x71,
0x63, 0x21, 0x8d, 0x12, 0xfd, 0xbd, 0x5e, 0xed, 0xe3, 0x09, 0x8f, 0x6f, 0xce, 0x9b, 0x43, 0x09,
0xf1, 0x1f, 0x5c, 0x40, 0xa5, 0x14, 0x1c, 0xab, 0x24, 0x4d, 0xad, 0x10, 0xb8, 0xb3, 0x90, 0xdd,
0x58, 0x50, 0x1a, 0x1f, 0xbd, 0x03, 0xa5, 0x52, 0xf6, 0x52, 0xaf, 0xdc, 0xc6, 0xbc, 0xc5, 0x0b,
0x0c, 0x35, 0x36, 0x8e, 0xc6, 0xad, 0x8b, 0xc8, 0x62, 0x87, 0xb2, 0xa6, 0x67, 0xca, 0xa1, 0x05,
0xe3, 0x39, 0xe5, 0xd0, 0xc2, 0x51, 0xbc, 0x03, 0x55, 0x23, 0x2f, 0xf1, 0xf5, 0xf9, 0xed, 0x26,
0x12, 0xdd, 0x9e, 0x4f, 0x10, 0x49, 0xfc, 0xf2, 0xd3, 0xbf, 0xcf, 0x5a, 0xe8, 0xcd, 0x59, 0x0b,
0xbd, 0x3d, 0x6b, 0xa1, 0x9f, 0xcf, 0x5b, 0xb9, 0x37, 0xe7, 0xad, 0xdc, 0x3f, 0xe7, 0xad, 0xdc,
0x77, 0xcd, 0x45, 0x7f, 0x15, 0x5f, 0x2e, 0xc9, 0xaf, 0x7b, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff,
0x06, 0x2a, 0x53, 0x54, 0x51, 0x0e, 0x00, 0x00,
}
func (m *SpaceSignRequest) Marshal() (dAtA []byte, err error) {
@ -1510,6 +1520,16 @@ func (m *SpaceSignRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if m.ForceRequest {
i--
if m.ForceRequest {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x28
}
if len(m.NewIdentitySignature) > 0 {
i -= len(m.NewIdentitySignature)
copy(dAtA[i:], m.NewIdentitySignature)
@ -2383,6 +2403,9 @@ func (m *SpaceSignRequest) Size() (n int) {
if l > 0 {
n += 1 + l + sovCoordinator(uint64(l))
}
if m.ForceRequest {
n += 2
}
return n
}
@ -2917,6 +2940,26 @@ func (m *SpaceSignRequest) Unmarshal(dAtA []byte) error {
m.NewIdentitySignature = []byte{}
}
iNdEx = postIndex
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ForceRequest", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCoordinator
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.ForceRequest = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipCoordinator(dAtA[iNdEx:])

View file

@ -0,0 +1,63 @@
package coordinatorproto
import (
"bytes"
"github.com/anyproto/any-sync/util/crypto"
"time"
)
func PrepareDeleteConfirmation(privKey crypto.PrivKey, spaceId, peerId, networkId string) (signed *DeletionConfirmPayloadWithSignature, err error) {
marshalledIdentity, err := privKey.GetPublic().Marshall()
if err != nil {
return
}
deleteConfirm := &DeletionConfirmPayload{
SpaceId: spaceId,
PeerId: peerId,
AccountIdentity: marshalledIdentity,
NetworkId: networkId,
Timestamp: time.Now().Unix(),
}
marshalledDeleteConfirm, err := deleteConfirm.Marshal()
if err != nil {
return
}
signature, err := privKey.Sign(marshalledDeleteConfirm)
if err != nil {
return
}
signed = &DeletionConfirmPayloadWithSignature{
DeletionPayload: marshalledDeleteConfirm,
Signature: signature,
}
return
}
func ValidateDeleteConfirmation(pubKey crypto.PubKey, spaceId, networkId string, deleteConfirm *DeletionConfirmPayloadWithSignature) (err error) {
res, err := pubKey.Verify(deleteConfirm.GetDeletionPayload(), deleteConfirm.GetSignature())
if err != nil {
return
}
if !res {
return errSignatureIncorrect
}
payload := &DeletionConfirmPayload{}
err = payload.Unmarshal(deleteConfirm.GetDeletionPayload())
if err != nil {
return
}
if payload.SpaceId != spaceId {
return errSpaceIdIncorrect
}
if payload.NetworkId != networkId {
return errNetworkIsIncorrect
}
accountRaw, err := crypto.UnmarshalEd25519PublicKeyProto(payload.AccountIdentity)
if err != nil {
return
}
if !bytes.Equal(pubKey.Storage(), accountRaw.Storage()) {
return errAccountIncorrect
}
return
}

View file

@ -0,0 +1,14 @@
package coordinatorproto
import (
"github.com/stretchr/testify/require"
"testing"
)
func TestValidateDeleteConfirmation(t *testing.T) {
fx := newFixture(t)
delConfirm, err := PrepareDeleteConfirmation(fx.accountPrivKey, fx.spaceId, fx.peerId, fx.networkKey.GetPublic().Network())
require.NoError(t, err)
err = ValidateDeleteConfirmation(fx.accountKey, fx.spaceId, fx.networkKey.GetPublic().Network(), delConfirm)
require.NoError(t, err)
}

View file

@ -38,6 +38,8 @@ message SpaceSignRequest {
bytes oldIdentity = 3;
// NewIdentitySignature is the new identity signed by the old one
bytes newIdentitySignature = 4;
// ForceRequest if true, forces the creating space receipt even if the space is deleted before
bool forceRequest = 5;
}
enum ErrorCodes {

View file

@ -10,12 +10,12 @@ import (
)
var (
errReceiptSignatureIncorrect = errors.New("receipt signature is incorrect")
errNetworkIsIncorrect = errors.New("network is incorrect")
errReceiptSpaceIdIncorrect = errors.New("receipt space id is incorrect")
errReceiptPeerIdIncorrect = errors.New("receipt peer id is incorrect")
errReceiptAccountIncorrect = errors.New("receipt account is incorrect")
errReceiptExpired = errors.New("receipt is expired")
errSignatureIncorrect = errors.New("receipt signature is incorrect")
errNetworkIsIncorrect = errors.New("network is incorrect")
errSpaceIdIncorrect = errors.New("receipt space id is incorrect")
errPeerIdIncorrect = errors.New("receipt peer id is incorrect")
errAccountIncorrect = errors.New("receipt account is incorrect")
errReceiptExpired = errors.New("receipt is expired")
)
func PrepareSpaceReceipt(spaceId, peerId string, validPeriod time.Duration, accountPubKey crypto.PubKey, networkKey crypto.PrivKey) (signedReceipt *SpaceReceiptWithSignature, err error) {
@ -51,10 +51,10 @@ func CheckReceipt(peerId, spaceId string, accountIdentity []byte, networkId stri
return
}
if payload.SpaceId != spaceId {
return errReceiptSpaceIdIncorrect
return errSpaceIdIncorrect
}
if payload.PeerId != peerId {
return errReceiptPeerIdIncorrect
return errPeerIdIncorrect
}
protoRaw, err := crypto.UnmarshalEd25519PublicKeyProto(payload.AccountIdentity)
if err != nil {
@ -65,7 +65,7 @@ func CheckReceipt(peerId, spaceId string, accountIdentity []byte, networkId stri
return
}
if !bytes.Equal(protoRaw.Storage(), accountRaw.Storage()) {
return errReceiptAccountIncorrect
return errAccountIncorrect
}
err = checkNetwork(
networkId,
@ -98,7 +98,7 @@ func checkNetwork(networkId, payloadNetworkId string, payload, signature []byte)
return
}
if !res {
return errReceiptSignatureIncorrect
return errSignatureIncorrect
}
return
}

View file

@ -13,12 +13,14 @@ import (
type fixture struct {
networkKey crypto.PrivKey
accountKey crypto.PubKey
accountPrivKey crypto.PrivKey
accountIdentity []byte
ctx context.Context
originalReceipt *SpaceReceipt
signedReceipt *SpaceReceiptWithSignature
spaceId string
peerId string
spaceId string
peerId string
}
func newFixture(t *testing.T) *fixture {
@ -34,6 +36,7 @@ func newFixture(t *testing.T) *fixture {
accountIdentity: accountKeyProto,
networkKey: networkKey,
accountKey: accountKey.GetPublic(),
accountPrivKey: accountKey,
}
}
@ -70,21 +73,21 @@ func TestReceiptIncorrectSpaceId(t *testing.T) {
fx := newFixture(t)
fx.prepareReceipt(t, time.Second)
err := CheckReceipt(fx.peerId, "otherId", fx.accountIdentity, fx.networkKey.GetPublic().Network(), fx.signedReceipt)
require.Error(t, errReceiptSpaceIdIncorrect, err)
require.Error(t, errSpaceIdIncorrect, err)
}
func TestReceiptIncorrectPeerId(t *testing.T) {
fx := newFixture(t)
fx.prepareReceipt(t, time.Second)
err := CheckReceipt("otherId", fx.spaceId, fx.accountIdentity, fx.networkKey.GetPublic().Network(), fx.signedReceipt)
require.Error(t, errReceiptPeerIdIncorrect, err)
require.Error(t, errPeerIdIncorrect, err)
}
func TestReceiptIncorrectAccountIdentity(t *testing.T) {
fx := newFixture(t)
fx.prepareReceipt(t, time.Second)
err := CheckReceipt(fx.peerId, fx.spaceId, []byte("some identity"), fx.networkKey.GetPublic().Network(), fx.signedReceipt)
require.Error(t, errReceiptAccountIncorrect, err)
require.Error(t, errAccountIncorrect, err)
}
func TestReceiptIncorrectNetworkId(t *testing.T) {
@ -114,7 +117,7 @@ func TestReceiptIncorrectSignature(t *testing.T) {
fx.prepareReceipt(t, time.Second)
fx.signedReceipt.Signature = []byte("random sig")
err := CheckReceipt(fx.peerId, fx.spaceId, fx.accountIdentity, fx.networkKey.GetPublic().Network(), fx.signedReceipt)
require.Error(t, errReceiptSignatureIncorrect, err)
require.Error(t, errSignatureIncorrect, err)
}
func TestReceiptExpired(t *testing.T) {

View file

@ -27,7 +27,7 @@ func New() Quic {
}
type Quic interface {
ListenAddrs(ctx context.Context, addrs ...string) (err error)
ListenAddrs(ctx context.Context, addrs ...string) (listenAddrs []net.Addr, err error)
transport.Transport
app.ComponentRunnable
}
@ -74,10 +74,11 @@ func (q *quicTransport) Run(ctx context.Context) (err error) {
}
q.listCtx, q.listCtxCancel = context.WithCancel(context.Background())
return q.ListenAddrs(ctx, q.conf.ListenAddrs...)
_, err = q.ListenAddrs(ctx, q.conf.ListenAddrs...)
return
}
func (q *quicTransport) ListenAddrs(ctx context.Context, addrs ...string) (err error) {
func (q *quicTransport) ListenAddrs(ctx context.Context, addrs ...string) (listenAddrs []net.Addr, err error) {
q.mu.Lock()
defer q.mu.Unlock()
var tlsConf tls.Config
@ -93,8 +94,9 @@ func (q *quicTransport) ListenAddrs(ctx context.Context, addrs ...string) (err e
for _, listAddr := range addrs {
list, err := quic.ListenAddr(listAddr, &tlsConf, q.quicConf)
if err != nil {
return err
return nil, err
}
listenAddrs = append(listenAddrs, list.Addr())
q.listeners = append(q.listeners, list)
go q.acceptLoop(q.listCtx, list)
}