diff --git a/commonspace/acl/aclclient/acjoiningclient.go b/commonspace/acl/aclclient/acjoiningclient.go index 567ea6ce..7ec26f21 100644 --- a/commonspace/acl/aclclient/acjoiningclient.go +++ b/commonspace/acl/aclclient/acjoiningclient.go @@ -23,6 +23,7 @@ type AclJoiningClient interface { app.Component AclGetRecords(ctx context.Context, spaceId, aclHead string) ([]*consensusproto.RawRecordWithId, error) RequestJoin(ctx context.Context, spaceId string, payload list.RequestJoinPayload) error + SendRecord(ctx context.Context, spaceId string, rec *consensusproto.RawRecord) (res *spacesyncproto.AclAddRecordResponse, err error) } type aclJoiningClient struct { @@ -113,6 +114,24 @@ func (c *aclJoiningClient) RequestJoin(ctx context.Context, spaceId string, payl }) } +func (c *aclJoiningClient) SendRecord(ctx context.Context, spaceId string, rec *consensusproto.RawRecord) (res *spacesyncproto.AclAddRecordResponse, err error) { + marshalled, err := rec.Marshal() + if err != nil { + return + } + err = c.doClient(ctx, spaceId, func(cl spacesyncproto.DRPCSpaceSyncClient) error { + res, err = cl.AclAddRecord(ctx, &spacesyncproto.AclAddRecordRequest{ + SpaceId: spaceId, + Payload: marshalled, + }) + if err != nil { + return err + } + return nil + }) + return +} + func (c *aclJoiningClient) doClient(ctx context.Context, spaceId string, f func(cl spacesyncproto.DRPCSpaceSyncClient) error) error { p, err := c.pool.GetOneOf(ctx, c.nodeConf.NodeIds(spaceId)) if err != nil { diff --git a/commonspace/headsync/diffsyncer.go b/commonspace/headsync/diffsyncer.go index 50228bee..cab177ae 100644 --- a/commonspace/headsync/diffsyncer.go +++ b/commonspace/headsync/diffsyncer.go @@ -113,6 +113,9 @@ func (d *diffSyncer) Sync(ctx context.Context) error { } func (d *diffSyncer) syncWithPeer(ctx context.Context, p peer.Peer) (err error) { + if !d.treeSyncer.ShouldSync(p.Id()) { + return + } ctx = logger.CtxWithFields(ctx, zap.String("peerId", p.Id())) conn, err := p.AcquireDrpcConn(ctx) if err != nil { diff --git a/commonspace/headsync/diffsyncer_test.go b/commonspace/headsync/diffsyncer_test.go index 54bef04a..f7e290ac 100644 --- a/commonspace/headsync/diffsyncer_test.go +++ b/commonspace/headsync/diffsyncer_test.go @@ -119,6 +119,7 @@ func TestDiffSyncer(t *testing.T) { mPeer := mockPeer{} remDiff := NewRemoteDiff(fx.spaceState.SpaceId, fx.clientMock) fx.aclMock.EXPECT().Id().AnyTimes().Return("aclId") + fx.treeSyncerMock.EXPECT().ShouldSync(gomock.Any()).Return(true) fx.peerManagerMock.EXPECT(). GetResponsiblePeers(gomock.Any()). Return([]peer.Peer{mPeer}, nil) @@ -140,6 +141,7 @@ func TestDiffSyncer(t *testing.T) { defer fx.stop() mPeer := mockPeer{} remDiff := NewRemoteDiff(fx.spaceState.SpaceId, fx.clientMock) + fx.treeSyncerMock.EXPECT().ShouldSync(gomock.Any()).Return(true) fx.aclMock.EXPECT().Id().AnyTimes().Return("aclId") fx.peerManagerMock.EXPECT(). GetResponsiblePeers(gomock.Any()). @@ -205,6 +207,7 @@ func TestDiffSyncer(t *testing.T) { fx.initDiffSyncer(t) defer fx.stop() fx.aclMock.EXPECT().Id().AnyTimes().Return("aclId") + fx.treeSyncerMock.EXPECT().ShouldSync(gomock.Any()).Return(true) aclStorageMock := mock_liststorage.NewMockListStorage(fx.ctrl) settingsStorage := mock_treestorage.NewMockTreeStorage(fx.ctrl) settingsId := "settingsId" @@ -255,6 +258,7 @@ func TestDiffSyncer(t *testing.T) { defer fx.stop() remDiff := NewRemoteDiff(fx.spaceState.SpaceId, fx.clientMock) fx.aclMock.EXPECT().Id().AnyTimes().Return("aclId") + fx.treeSyncerMock.EXPECT().ShouldSync(gomock.Any()).Return(true) fx.peerManagerMock.EXPECT(). GetResponsiblePeers(gomock.Any()). Return([]peer.Peer{mockPeer{}}, nil) @@ -273,6 +277,7 @@ func TestDiffSyncer(t *testing.T) { defer fx.stop() mPeer := mockPeer{} remDiff := NewRemoteDiff(fx.spaceState.SpaceId, fx.clientMock) + fx.treeSyncerMock.EXPECT().ShouldSync(gomock.Any()).Return(true) fx.aclMock.EXPECT().Id().AnyTimes().Return("aclId") fx.peerManagerMock.EXPECT(). GetResponsiblePeers(gomock.Any()). diff --git a/commonspace/object/acl/list/aclrecordbuilder.go b/commonspace/object/acl/list/aclrecordbuilder.go index b045a0f4..6305fd20 100644 --- a/commonspace/object/acl/list/aclrecordbuilder.go +++ b/commonspace/object/acl/list/aclrecordbuilder.go @@ -1,6 +1,7 @@ package list import ( + "errors" "time" "github.com/gogo/protobuf/proto" @@ -509,6 +510,10 @@ func (a *aclRecordBuilder) BuildRequestRemove() (rawRecord *consensusproto.RawRe err = ErrIsOwner return } + _, err = a.state.Record(a.state.pubKey) + if !errors.Is(err, ErrNoSuchRecord) { + return nil, ErrPendingRequest + } removeRec := &aclrecordproto.AclAccountRequestRemove{} content := &aclrecordproto.AclContentValue{Value: &aclrecordproto.AclContentValue_AccountRequestRemove{AccountRequestRemove: removeRec}} return a.buildRecord(content) diff --git a/commonspace/object/acl/list/aclstate.go b/commonspace/object/acl/list/aclstate.go index 928a2083..74152e9d 100644 --- a/commonspace/object/acl/list/aclstate.go +++ b/commonspace/object/acl/list/aclstate.go @@ -163,7 +163,7 @@ func (st *AclState) PermissionsAtRecord(id string, pubKey crypto.PubKey) (AclPer return perms, nil } -func (st *AclState) CurrentStates() []AccountState { +func (st *AclState) CurrentAccounts() []AccountState { var res []AccountState for _, state := range st.accountStates { res = append(res, state) @@ -171,6 +171,19 @@ func (st *AclState) CurrentStates() []AccountState { return res } +func (st *AclState) HadReadPermissions(identity crypto.PubKey) (had bool) { + state, exists := st.accountStates[mapKeyFromPubKey(identity)] + if !exists { + return false + } + for _, perm := range state.PermissionChanges { + if !perm.Permission.NoPermissions() { + return true + } + } + return false +} + func (st *AclState) Invites() []crypto.PubKey { var invites []crypto.PubKey for _, inv := range st.inviteKeys { diff --git a/commonspace/object/acl/list/acltestsuite_test.go b/commonspace/object/acl/list/acltestsuite_test.go index 9921e5eb..026cded0 100644 --- a/commonspace/object/acl/list/acltestsuite_test.go +++ b/commonspace/object/acl/list/acltestsuite_test.go @@ -101,6 +101,7 @@ func TestAclExecutor(t *testing.T) { // g can cancel request to remove {"g.cancel:g", nil}, {"g.request_remove:g", nil}, + {"g.request_remove:g", ErrPendingRequest}, {"a.remove:g", nil}, // g cannot cancel not existing request to remove {"g.cancel:g", ErrNoSuchRecord}, diff --git a/commonspace/object/acl/list/validator.go b/commonspace/object/acl/list/validator.go index 0f756052..61dd18cb 100644 --- a/commonspace/object/acl/list/validator.go +++ b/commonspace/object/acl/list/validator.go @@ -247,6 +247,9 @@ func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRe if c.aclState.Permissions(authorIdentity).NoPermissions() { return ErrInsufficientPermissions } + if c.aclState.Permissions(authorIdentity).IsOwner() { + return ErrIsOwner + } if _, exists := c.aclState.pendingRequests[mapKeyFromPubKey(authorIdentity)]; exists { return ErrPendingRequest } diff --git a/commonspace/object/tree/objecttree/derivedtree.go b/commonspace/object/tree/objecttree/derivedtree.go index 2af33e10..5d369780 100644 --- a/commonspace/object/tree/objecttree/derivedtree.go +++ b/commonspace/object/tree/objecttree/derivedtree.go @@ -1,12 +1,17 @@ package objecttree import ( - "github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto" "github.com/gogo/protobuf/proto" + + "github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto" ) func IsEmptyDerivedTree(tree ObjectTree) bool { - return tree.IsDerived() && tree.Len() == 1 && tree.Root().Id == tree.Header().Id + return tree.IsDerived() && IsEmptyTree(tree) +} + +func IsEmptyTree(tree ObjectTree) bool { + return tree.Len() == 1 && tree.Root().Id == tree.Header().Id } func IsDerivedRoot(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) { diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index 576832ed..238636d6 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -366,6 +366,16 @@ func (ot *objectTree) addRawChanges(ctx context.Context, changesPayload RawChang return } + var ( + filteredHeads = false + headsToUse = changesPayload.NewHeads + ) + // if our validator provides filtering mechanism then we use it + filteredHeads, ot.newChangesBuf, ot.newSnapshotsBuf, ot.notSeenIdxBuf = ot.validator.FilterChanges(ot.aclList, changesPayload.NewHeads, ot.newChangesBuf, ot.newSnapshotsBuf, ot.notSeenIdxBuf) + if filteredHeads { + // if we filtered some of the heads, then we don't know which heads to use + headsToUse = []string{} + } rollback := func(changes []*Change) { for _, ch := range changes { if _, exists := ot.tree.attached[ch.Id]; exists { @@ -400,7 +410,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, changesPayload RawChang } if shouldRebuildFromStorage { - err = ot.rebuildFromStorage(changesPayload.NewHeads, ot.newChangesBuf) + err = ot.rebuildFromStorage(headsToUse, ot.newChangesBuf) if err != nil { // rebuilding without new changes ot.rebuildFromStorage(nil, nil) @@ -662,12 +672,15 @@ func (ot *objectTree) readKeysFromAclState(state *list.AclState) (err error) { return nil } // if we can't read the keys anyway - if state.AccountKey() == nil || state.Permissions(state.AccountKey().GetPublic()).NoPermissions() { + if state.AccountKey() == nil || !state.HadReadPermissions(state.AccountKey().GetPublic()) { return nil } for key, value := range state.Keys() { + if _, exists := ot.keys[key]; exists { + continue + } if value.ReadKey == nil { - return list.ErrNoReadKey + continue } treeKey, err := deriveTreeKey(value.ReadKey, ot.id) if err != nil { @@ -679,6 +692,9 @@ func (ot *objectTree) readKeysFromAclState(state *list.AclState) (err error) { if err != nil { return err } + if curKey == nil { + return nil + } ot.currentReadKey, err = deriveTreeKey(curKey, ot.id) return err } diff --git a/commonspace/object/tree/objecttree/objecttree_test.go b/commonspace/object/tree/objecttree/objecttree_test.go index 3cc2059b..d65d15fc 100644 --- a/commonspace/object/tree/objecttree/objecttree_test.go +++ b/commonspace/object/tree/objecttree/objecttree_test.go @@ -25,6 +25,25 @@ type testTreeContext struct { objTree ObjectTree } +func genBuildFilterableTestableTree(filterFunc func(ch *Change) bool) func(treeStorage treestorage.TreeStorage, aclList list.AclList) (ObjectTree, error) { + return func(treeStorage treestorage.TreeStorage, aclList list.AclList) (ObjectTree, error) { + root, _ := treeStorage.Root() + changeBuilder := &nonVerifiableChangeBuilder{ + ChangeBuilder: NewChangeBuilder(newMockKeyStorage(), root), + } + deps := objectTreeDeps{ + changeBuilder: changeBuilder, + treeBuilder: newTreeBuilder(true, treeStorage, changeBuilder), + treeStorage: treeStorage, + rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), + validator: &noOpTreeValidator{filterFunc: filterFunc}, + aclList: aclList, + } + + return buildObjectTree(deps) + } +} + func prepareAclList(t *testing.T) (list.AclList, *accountdata.AccountKeys) { randKeys, err := accountdata.NewRandom() require.NoError(t, err) @@ -129,7 +148,7 @@ func TestObjectTree(t *testing.T) { }, aAccount.Acl) require.NoError(t, err) aStore, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root}) - aTree, err := BuildKeyVerifiableObjectTree(aStore, aAccount.Acl) + aTree, err := BuildKeyFilterableObjectTree(aStore, aAccount.Acl) require.NoError(t, err) _, err = aTree.AddContent(ctx, SignableChangeContent{ Data: []byte("some"), @@ -140,7 +159,7 @@ func TestObjectTree(t *testing.T) { }) require.NoError(t, err) bStore := aTree.Storage().(*treestorage.InMemoryTreeStorage).Copy() - bTree, err := BuildKeyVerifiableObjectTree(bStore, bAccount.Acl) + bTree, err := BuildKeyFilterableObjectTree(bStore, bAccount.Acl) require.NoError(t, err) err = exec.Execute("a.remove:b") require.NoError(t, err) @@ -157,17 +176,17 @@ func TestObjectTree(t *testing.T) { NewHeads: aTree.Heads(), RawChanges: res.Added, }) - require.Equal(t, ErrHasInvalidChanges, err) require.Equal(t, oldHeads, bTree.Heads()) bStore = aTree.Storage().(*treestorage.InMemoryTreeStorage).Copy() root, _ = bStore.Root() heads, _ := bStore.Heads() - err = ValidateRawTreeBuildFunc(treestorage.TreeStorageCreatePayload{ + filteredPayload, err := ValidateFilterRawTree(treestorage.TreeStorageCreatePayload{ RootRawChange: root, Changes: bStore.AllChanges(), Heads: heads, - }, BuildKeyVerifiableObjectTree, bAccount.Acl) - require.Equal(t, ErrHasInvalidChanges, err) + }, bAccount.Acl) + require.NoError(t, err) + require.Equal(t, 2, len(filteredPayload.Changes)) err = aTree.IterateRoot(func(change *Change, decrypted []byte) (any, error) { return nil, nil }, func(change *Change) bool { @@ -667,6 +686,35 @@ func TestObjectTree(t *testing.T) { }) }) + t.Run("test tree filter", func(t *testing.T) { + filterFunc := func(change *Change) bool { + return slices.Contains([]string{"0", "1", "2", "3", "4", "7", "8"}, change.Id) + } + ctx := prepareContext(t, aclList, genBuildFilterableTestableTree(filterFunc), false, nil) + rawChanges := []*treechangeproto.RawTreeChangeWithId{ + ctx.changeCreator.CreateRawWithData("1", aclList.Head().Id, "0", false, []byte("1"), "0"), + ctx.changeCreator.CreateRawWithData("2", aclList.Head().Id, "0", false, []byte("2"), "1"), + ctx.changeCreator.CreateRawWithData("3", aclList.Head().Id, "0", false, []byte("3"), "2"), + ctx.changeCreator.CreateRawWithData("4", aclList.Head().Id, "0", false, []byte("4"), "2"), + ctx.changeCreator.CreateRawWithData("5", aclList.Head().Id, "0", false, []byte("5"), "1"), + ctx.changeCreator.CreateRawWithData("6", aclList.Head().Id, "0", true, []byte("6"), "3", "4", "5"), + ctx.changeCreator.CreateRawWithData("7", aclList.Head().Id, "6", false, []byte("7"), "6"), + ctx.changeCreator.CreateRawWithData("8", aclList.Head().Id, "6", false, []byte("8"), "6"), + } + _, err := ctx.objTree.AddRawChanges(context.Background(), RawChangesPayload{ + NewHeads: []string{"7", "8"}, + RawChanges: rawChanges, + }) + require.NoError(t, err) + var ids []string + ctx.objTree.IterateRoot(nil, func(change *Change) bool { + ids = append(ids, change.Id) + return true + }) + slices.Sort(ids) + require.Equal(t, []string{"0", "1", "2", "3", "4"}, ids) + }) + t.Run("rollback when add to storage returns error", func(t *testing.T) { ctx := prepareTreeContext(t, aclList) changeCreator := ctx.changeCreator diff --git a/commonspace/object/tree/objecttree/objecttreefactory.go b/commonspace/object/tree/objecttree/objecttreefactory.go index cbd30c99..a96992ba 100644 --- a/commonspace/object/tree/objecttree/objecttreefactory.go +++ b/commonspace/object/tree/objecttree/objecttreefactory.go @@ -55,7 +55,7 @@ func verifiableTreeDeps( changeBuilder: changeBuilder, treeBuilder: treeBuilder, treeStorage: treeStorage, - validator: newTreeValidator(false), + validator: newTreeValidator(false, false), rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), aclList: aclList, } @@ -71,7 +71,7 @@ func emptyDataTreeDeps( changeBuilder: changeBuilder, treeBuilder: treeBuilder, treeStorage: treeStorage, - validator: newTreeValidator(false), + validator: newTreeValidator(false, false), rawChangeLoader: newStorageLoader(treeStorage, changeBuilder), aclList: aclList, } @@ -136,13 +136,13 @@ func BuildEmptyDataTestableTree(treeStorage treestorage.TreeStorage, aclList lis return buildObjectTree(deps) } -func BuildKeyVerifiableObjectTree(treeStorage treestorage.TreeStorage, aclList list.AclList) (ObjectTree, error) { +func BuildKeyFilterableObjectTree(treeStorage treestorage.TreeStorage, aclList list.AclList) (ObjectTree, error) { rootChange, err := treeStorage.Root() if err != nil { return nil, err } deps := defaultObjectTreeDeps(rootChange, treeStorage, aclList) - deps.validator = newTreeValidator(true) + deps.validator = newTreeValidator(true, true) return buildObjectTree(deps) } diff --git a/commonspace/object/tree/objecttree/objecttreevalidator.go b/commonspace/object/tree/objecttree/objecttreevalidator.go index 0aa7848b..bb971ad7 100644 --- a/commonspace/object/tree/objecttree/objecttreevalidator.go +++ b/commonspace/object/tree/objecttree/objecttreevalidator.go @@ -9,14 +9,19 @@ import ( "github.com/anyproto/any-sync/util/slice" ) +type ValidatorFunc func(payload treestorage.TreeStorageCreatePayload, buildFunc BuildObjectTreeFunc, aclList list.AclList) (retPayload treestorage.TreeStorageCreatePayload, err error) + type ObjectTreeValidator interface { // ValidateFullTree should always be entered while holding a read lock on AclList ValidateFullTree(tree *Tree, aclList list.AclList) error // ValidateNewChanges should always be entered while holding a read lock on AclList ValidateNewChanges(tree *Tree, aclList list.AclList, newChanges []*Change) error + FilterChanges(aclList list.AclList, heads []string, changes []*Change, snapshots []*Change, indexes []int) (filteredHeads bool, filtered, filteredSnapshots []*Change, newIndexes []int) } -type noOpTreeValidator struct{} +type noOpTreeValidator struct { + filterFunc func(ch *Change) bool +} func (n *noOpTreeValidator) ValidateFullTree(tree *Tree, aclList list.AclList) error { return nil @@ -26,13 +31,34 @@ func (n *noOpTreeValidator) ValidateNewChanges(tree *Tree, aclList list.AclList, return nil } -type objectTreeValidator struct { - validateKeys bool +func (n *noOpTreeValidator) FilterChanges(aclList list.AclList, heads []string, changes []*Change, snapshots []*Change, indexes []int) (filteredHeads bool, filtered, filteredSnapshots []*Change, newIndexes []int) { + if n.filterFunc == nil { + return false, changes, snapshots, indexes + } + for idx, c := range changes { + // only taking changes which we can read + if n.filterFunc(c) { + newIndexes = append(newIndexes, indexes[idx]) + filtered = append(filtered, c) + if c.IsSnapshot { + filteredSnapshots = append(filteredSnapshots, c) + } + } else { + filteredHeads = true + } + } + return } -func newTreeValidator(validateKeys bool) ObjectTreeValidator { +type objectTreeValidator struct { + validateKeys bool + shouldFilter bool +} + +func newTreeValidator(validateKeys bool, filterChanges bool) ObjectTreeValidator { return &objectTreeValidator{ validateKeys: validateKeys, + shouldFilter: filterChanges, } } @@ -54,6 +80,30 @@ func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list.AclLis return } +func (v *objectTreeValidator) FilterChanges(aclList list.AclList, heads []string, changes []*Change, snapshots []*Change, indexes []int) (filteredHeads bool, filtered, filteredSnapshots []*Change, newIndexes []int) { + if !v.shouldFilter { + return false, changes, snapshots, indexes + } + aclList.RLock() + defer aclList.RUnlock() + state := aclList.AclState() + for idx, c := range changes { + // only taking changes which we can read + if keys, exists := state.Keys()[c.ReadKeyId]; exists && keys.ReadKey != nil { + newIndexes = append(newIndexes, indexes[idx]) + filtered = append(filtered, c) + if c.IsSnapshot { + filteredSnapshots = append(filteredSnapshots, c) + } + } else { + // if we filtered at least one change this can be the change between heads and other changes + // thus we cannot use heads + filteredHeads = true + } + } + return +} + func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.AclList, c *Change) (err error) { var ( perms list.AclPermissions @@ -103,7 +153,7 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.AclList, c return } -func ValidateRawTreeBuildFunc(payload treestorage.TreeStorageCreatePayload, buildFunc BuildObjectTreeFunc, aclList list.AclList) (err error) { +func ValidateRawTreeBuildFunc(payload treestorage.TreeStorageCreatePayload, buildFunc BuildObjectTreeFunc, aclList list.AclList) (newPayload treestorage.TreeStorageCreatePayload, err error) { treeStorage, err := treestorage.NewInMemoryTreeStorage(payload.RootRawChange, []string{payload.RootRawChange.Id}, nil) if err != nil { return @@ -120,15 +170,48 @@ func ValidateRawTreeBuildFunc(payload treestorage.TreeStorageCreatePayload, buil return } if !slice.UnsortedEquals(res.Heads, payload.Heads) { - return ErrHasInvalidChanges + return payload, ErrHasInvalidChanges } // if tree has only one change we still should check if the snapshot id is same as root if IsEmptyDerivedTree(tree) { - return ErrDerived + return payload, ErrDerived } - return + return payload, nil +} + +func ValidateFilterRawTree(payload treestorage.TreeStorageCreatePayload, aclList list.AclList) (retPayload treestorage.TreeStorageCreatePayload, err error) { + aclList.RLock() + if !aclList.AclState().HadReadPermissions(aclList.AclState().Identity()) { + aclList.RUnlock() + return payload, list.ErrNoReadKey + } + aclList.RUnlock() + treeStorage, err := treestorage.NewInMemoryTreeStorage(payload.RootRawChange, []string{payload.RootRawChange.Id}, nil) + if err != nil { + return + } + tree, err := BuildKeyFilterableObjectTree(treeStorage, aclList) + if err != nil { + return + } + res, err := tree.AddRawChanges(context.Background(), RawChangesPayload{ + NewHeads: payload.Heads, + RawChanges: payload.Changes, + }) + if err != nil { + return + } + if IsEmptyTree(tree) { + return payload, ErrNoChangeInTree + } + return treestorage.TreeStorageCreatePayload{ + RootRawChange: payload.RootRawChange, + Heads: res.Heads, + Changes: treeStorage.(*treestorage.InMemoryTreeStorage).AllChanges(), + }, nil } func ValidateRawTree(payload treestorage.TreeStorageCreatePayload, aclList list.AclList) (err error) { - return ValidateRawTreeBuildFunc(payload, BuildObjectTree, aclList) + _, err = ValidateRawTreeBuildFunc(payload, BuildObjectTree, aclList) + return } diff --git a/commonspace/object/tree/synctree/synctree.go b/commonspace/object/tree/synctree/synctree.go index e4fc2310..ca3f2cc3 100644 --- a/commonspace/object/tree/synctree/synctree.go +++ b/commonspace/object/tree/synctree/synctree.go @@ -6,6 +6,8 @@ import ( "errors" "time" + "go.uber.org/zap" + "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/commonspace/object/acl/list" "github.com/anyproto/any-sync/commonspace/object/tree/objecttree" @@ -16,7 +18,6 @@ import ( "github.com/anyproto/any-sync/commonspace/syncstatus" "github.com/anyproto/any-sync/net/peer" "github.com/anyproto/any-sync/nodeconf" - "go.uber.org/zap" ) var ( @@ -59,18 +60,19 @@ type ResponsiblePeersGetter interface { } type BuildDeps struct { - SpaceId string - SyncClient SyncClient - Configuration nodeconf.NodeConf - HeadNotifiable HeadNotifiable - Listener updatelistener.UpdateListener - AclList list.AclList - SpaceStorage spacestorage.SpaceStorage - TreeStorage treestorage.TreeStorage - OnClose func(id string) - SyncStatus syncstatus.StatusUpdater - PeerGetter ResponsiblePeersGetter - BuildObjectTree objecttree.BuildObjectTreeFunc + SpaceId string + SyncClient SyncClient + Configuration nodeconf.NodeConf + HeadNotifiable HeadNotifiable + Listener updatelistener.UpdateListener + AclList list.AclList + SpaceStorage spacestorage.SpaceStorage + TreeStorage treestorage.TreeStorage + OnClose func(id string) + SyncStatus syncstatus.StatusUpdater + PeerGetter ResponsiblePeersGetter + BuildObjectTree objecttree.BuildObjectTreeFunc + ValidateObjectTree objecttree.ValidatorFunc } func BuildSyncTreeOrGetRemote(ctx context.Context, id string, deps BuildDeps) (t SyncTree, err error) { diff --git a/commonspace/object/tree/synctree/treeremotegetter.go b/commonspace/object/tree/synctree/treeremotegetter.go index 6f9720e0..0c1be341 100644 --- a/commonspace/object/tree/synctree/treeremotegetter.go +++ b/commonspace/object/tree/synctree/treeremotegetter.go @@ -104,13 +104,17 @@ func (t treeRemoteGetter) getTree(ctx context.Context) (treeStorage treestorage. Heads: fullSyncResp.Heads, } + validatorFunc := t.deps.ValidateObjectTree + if validatorFunc == nil { + validatorFunc = objecttree.ValidateRawTreeBuildFunc + } // basically building tree with in-memory storage and validating that it was without errors log.With(zap.String("id", t.treeId)).DebugCtx(ctx, "validating tree") - err = objecttree.ValidateRawTreeBuildFunc(payload, t.deps.BuildObjectTree, t.deps.AclList) + newPayload, err := validatorFunc(payload, t.deps.BuildObjectTree, t.deps.AclList) if err != nil { return } // now we are sure that we can save it to the storage - treeStorage, err = t.deps.SpaceStorage.CreateTreeStorage(payload) + treeStorage, err = t.deps.SpaceStorage.CreateTreeStorage(newPayload) return } diff --git a/commonspace/object/treesyncer/mock_treesyncer/mock_treesyncer.go b/commonspace/object/treesyncer/mock_treesyncer/mock_treesyncer.go index 1c61db09..257afd19 100644 --- a/commonspace/object/treesyncer/mock_treesyncer/mock_treesyncer.go +++ b/commonspace/object/treesyncer/mock_treesyncer/mock_treesyncer.go @@ -5,7 +5,6 @@ // // mockgen -destination mock_treesyncer/mock_treesyncer.go github.com/anyproto/any-sync/commonspace/object/treesyncer TreeSyncer // - // Package mock_treesyncer is a generated GoMock package. package mock_treesyncer @@ -96,6 +95,20 @@ func (mr *MockTreeSyncerMockRecorder) Run(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockTreeSyncer)(nil).Run), arg0) } +// ShouldSync mocks base method. +func (m *MockTreeSyncer) ShouldSync(arg0 string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ShouldSync", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// ShouldSync indicates an expected call of ShouldSync. +func (mr *MockTreeSyncerMockRecorder) ShouldSync(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldSync", reflect.TypeOf((*MockTreeSyncer)(nil).ShouldSync), arg0) +} + // StartSync mocks base method. func (m *MockTreeSyncer) StartSync() { m.ctrl.T.Helper() @@ -108,6 +121,18 @@ func (mr *MockTreeSyncerMockRecorder) StartSync() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartSync", reflect.TypeOf((*MockTreeSyncer)(nil).StartSync)) } +// StopSync mocks base method. +func (m *MockTreeSyncer) StopSync() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "StopSync") +} + +// StopSync indicates an expected call of StopSync. +func (mr *MockTreeSyncerMockRecorder) StopSync() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopSync", reflect.TypeOf((*MockTreeSyncer)(nil).StopSync)) +} + // SyncAll mocks base method. func (m *MockTreeSyncer) SyncAll(arg0 context.Context, arg1 string, arg2, arg3 []string) error { m.ctrl.T.Helper() diff --git a/commonspace/object/treesyncer/treesyncer.go b/commonspace/object/treesyncer/treesyncer.go index 76cbdae3..5f8819fd 100644 --- a/commonspace/object/treesyncer/treesyncer.go +++ b/commonspace/object/treesyncer/treesyncer.go @@ -12,5 +12,7 @@ const CName = "common.object.treesyncer" type TreeSyncer interface { app.ComponentRunnable StartSync() + StopSync() + ShouldSync(peerId string) bool SyncAll(ctx context.Context, peerId string, existing, missing []string) error } diff --git a/commonspace/objecttreebuilder/treebuilder.go b/commonspace/objecttreebuilder/treebuilder.go index afbbdc30..09836725 100644 --- a/commonspace/objecttreebuilder/treebuilder.go +++ b/commonspace/objecttreebuilder/treebuilder.go @@ -6,6 +6,8 @@ import ( "errors" "sync/atomic" + "go.uber.org/zap" + "github.com/anyproto/any-sync/app" "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/commonspace/headsync" @@ -23,12 +25,12 @@ import ( "github.com/anyproto/any-sync/commonspace/spacestorage" "github.com/anyproto/any-sync/commonspace/syncstatus" "github.com/anyproto/any-sync/nodeconf" - "go.uber.org/zap" ) type BuildTreeOpts struct { - Listener updatelistener.UpdateListener - TreeBuilder objecttree.BuildObjectTreeFunc + Listener updatelistener.UpdateListener + TreeBuilder objecttree.BuildObjectTreeFunc + TreeValidator objecttree.ValidatorFunc } const CName = "common.commonspace.objecttreebuilder" @@ -111,17 +113,18 @@ func (t *treeBuilder) BuildTree(ctx context.Context, id string, opts BuildTreeOp treeBuilder = t.builder } deps := synctree.BuildDeps{ - SpaceId: t.spaceId, - SyncClient: t.syncClient, - Configuration: t.configuration, - HeadNotifiable: t.headsNotifiable, - Listener: opts.Listener, - AclList: t.aclList, - SpaceStorage: t.spaceStorage, - OnClose: t.onClose, - SyncStatus: t.syncStatus, - PeerGetter: t.peerManager, - BuildObjectTree: treeBuilder, + SpaceId: t.spaceId, + SyncClient: t.syncClient, + Configuration: t.configuration, + HeadNotifiable: t.headsNotifiable, + Listener: opts.Listener, + AclList: t.aclList, + SpaceStorage: t.spaceStorage, + OnClose: t.onClose, + SyncStatus: t.syncStatus, + PeerGetter: t.peerManager, + BuildObjectTree: treeBuilder, + ValidateObjectTree: opts.TreeValidator, } t.treesUsed.Add(1) t.log.Debug("incrementing counter", zap.String("id", id), zap.Int32("trees", t.treesUsed.Load())) diff --git a/commonspace/settings/settingsobject.go b/commonspace/settings/settingsobject.go index 7edce869..c3f5b182 100644 --- a/commonspace/settings/settingsobject.go +++ b/commonspace/settings/settingsobject.go @@ -4,9 +4,13 @@ import ( "context" "errors" "fmt" + "github.com/anyproto/any-sync/commonspace/deletionmanager" "github.com/anyproto/any-sync/util/crypto" + "github.com/gogo/protobuf/proto" + "go.uber.org/zap" + "github.com/anyproto/any-sync/accountservice" "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/commonspace/object/tree/objecttree" @@ -18,8 +22,6 @@ import ( "github.com/anyproto/any-sync/commonspace/spacestorage" "github.com/anyproto/any-sync/commonspace/spacesyncproto" "github.com/anyproto/any-sync/nodeconf" - "github.com/gogo/protobuf/proto" - "go.uber.org/zap" ) var log = logger.NewNamed("common.commonspace.settings") @@ -166,7 +168,10 @@ func (s *settingsObject) checkHistoryState(ctx context.Context) (err error) { } func (s *settingsObject) Close() error { - return s.SyncTree.Close() + if s.SyncTree != nil { + return s.SyncTree.Close() + } + return nil } var isDerivedRoot = objecttree.IsDerivedRoot diff --git a/commonspace/spaceutils_test.go b/commonspace/spaceutils_test.go index 56e1f2f0..12cec096 100644 --- a/commonspace/spaceutils_test.go +++ b/commonspace/spaceutils_test.go @@ -6,6 +6,9 @@ import ( "testing" "time" + "github.com/anyproto/go-chash" + "github.com/stretchr/testify/require" + accountService "github.com/anyproto/any-sync/accountservice" "github.com/anyproto/any-sync/app" "github.com/anyproto/any-sync/app/ocache" @@ -23,8 +26,6 @@ import ( "github.com/anyproto/any-sync/net/pool" "github.com/anyproto/any-sync/nodeconf" "github.com/anyproto/any-sync/testutil/accounttest" - "github.com/anyproto/go-chash" - "github.com/stretchr/testify/require" ) // @@ -282,6 +283,10 @@ func (n noOpSyncer) Close() error { type mockTreeSyncer struct { } +func (m mockTreeSyncer) ShouldSync(peerId string) bool { + return false +} + func (m mockTreeSyncer) Init(a *app.App) (err error) { return nil } @@ -301,6 +306,9 @@ func (m mockTreeSyncer) Close(ctx context.Context) (err error) { func (m mockTreeSyncer) StartSync() { } +func (m mockTreeSyncer) StopSync() { +} + func (m mockTreeSyncer) SyncAll(ctx context.Context, peerId string, existing, missing []string) error { return nil } diff --git a/coordinator/coordinatorproto/coordinator.pb.go b/coordinator/coordinatorproto/coordinator.pb.go index 9660af40..747d1293 100644 --- a/coordinator/coordinatorproto/coordinator.pb.go +++ b/coordinator/coordinatorproto/coordinator.pb.go @@ -99,6 +99,31 @@ func (SpaceStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor_d94f6f99586adae2, []int{1} } +type SpacePermissions int32 + +const ( + SpacePermissions_SpacePermissionsUnknown SpacePermissions = 0 + SpacePermissions_SpacePermissionsOwner SpacePermissions = 1 +) + +var SpacePermissions_name = map[int32]string{ + 0: "SpacePermissionsUnknown", + 1: "SpacePermissionsOwner", +} + +var SpacePermissions_value = map[string]int32{ + "SpacePermissionsUnknown": 0, + "SpacePermissionsOwner": 1, +} + +func (x SpacePermissions) String() string { + return proto.EnumName(SpacePermissions_name, int32(x)) +} + +func (SpacePermissions) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_d94f6f99586adae2, []int{2} +} + // NodeType determines the type of API that a node supports type NodeType int32 @@ -142,7 +167,7 @@ func (x NodeType) String() string { } func (NodeType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d94f6f99586adae2, []int{2} + return fileDescriptor_d94f6f99586adae2, []int{3} } // DeletionChangeType determines the type of deletion payload @@ -171,7 +196,7 @@ func (x DeletionPayloadType) String() string { } func (DeletionPayloadType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d94f6f99586adae2, []int{3} + return fileDescriptor_d94f6f99586adae2, []int{4} } type DeletionLogRecordStatus int32 @@ -202,7 +227,7 @@ func (x DeletionLogRecordStatus) String() string { } func (DeletionLogRecordStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d94f6f99586adae2, []int{4} + return fileDescriptor_d94f6f99586adae2, []int{5} } type SpaceSignRequest struct { @@ -287,8 +312,9 @@ func (m *SpaceSignRequest) GetForceRequest() bool { } 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"` + 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"` + Permissions SpacePermissions `protobuf:"varint,3,opt,name=permissions,proto3,enum=coordinator.SpacePermissions" json:"permissions,omitempty"` } func (m *SpaceStatusPayload) Reset() { *m = SpaceStatusPayload{} } @@ -338,6 +364,13 @@ func (m *SpaceStatusPayload) GetDeletionTimestamp() int64 { return 0 } +func (m *SpaceStatusPayload) GetPermissions() SpacePermissions { + if m != nil { + return m.Permissions + } + return SpacePermissions_SpacePermissionsUnknown +} + type SpaceSignResponse struct { Receipt *SpaceReceiptWithSignature `protobuf:"bytes,1,opt,name=receipt,proto3" json:"receipt,omitempty"` } @@ -1995,6 +2028,7 @@ func (m *AclGetRecordsResponse) GetRecords() [][]byte { func init() { proto.RegisterEnum("coordinator.ErrorCodes", ErrorCodes_name, ErrorCodes_value) proto.RegisterEnum("coordinator.SpaceStatus", SpaceStatus_name, SpaceStatus_value) + proto.RegisterEnum("coordinator.SpacePermissions", SpacePermissions_name, SpacePermissions_value) proto.RegisterEnum("coordinator.NodeType", NodeType_name, NodeType_value) proto.RegisterEnum("coordinator.DeletionPayloadType", DeletionPayloadType_name, DeletionPayloadType_value) proto.RegisterEnum("coordinator.DeletionLogRecordStatus", DeletionLogRecordStatus_name, DeletionLogRecordStatus_value) @@ -2037,105 +2071,109 @@ func init() { } var fileDescriptor_d94f6f99586adae2 = []byte{ - // 1567 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xcf, 0x73, 0xd3, 0xc6, - 0x17, 0xb7, 0x64, 0x3b, 0xb1, 0x9f, 0x83, 0x51, 0x36, 0x3f, 0xf0, 0xd7, 0x18, 0x63, 0x16, 0xbe, - 0xd4, 0xb8, 0x1d, 0xa0, 0x66, 0xda, 0x29, 0x43, 0x0f, 0x84, 0x40, 0x69, 0xf8, 0x11, 0x32, 0x0a, - 0xa1, 0xd3, 0x72, 0xe8, 0x08, 0x69, 0xe3, 0x68, 0x62, 0x4b, 0xae, 0xb4, 0x06, 0xfc, 0x5f, 0xf4, - 0xd6, 0x53, 0xef, 0x9d, 0x69, 0x0f, 0x9d, 0x5e, 0x7a, 0xe8, 0x4c, 0xcf, 0x3d, 0x72, 0xec, 0x91, - 0x81, 0x6b, 0xff, 0x88, 0xce, 0xae, 0x56, 0xd2, 0xea, 0x87, 0x9d, 0x74, 0x38, 0x70, 0x49, 0xbc, - 0x9f, 0x7d, 0xef, 0xed, 0xfb, 0xb5, 0xef, 0xbd, 0x15, 0x7c, 0x62, 0xba, 0xae, 0x67, 0xd9, 0x8e, - 0x41, 0x5d, 0xef, 0x8a, 0xf4, 0x7b, 0xec, 0xb9, 0xd4, 0xbd, 0xc2, 0xff, 0xfa, 0x32, 0x7e, 0x99, - 0x43, 0xa8, 0x26, 0x41, 0xf8, 0x4f, 0x05, 0xb4, 0xdd, 0xb1, 0x61, 0x92, 0x5d, 0x7b, 0xe0, 0xe8, - 0xe4, 0xbb, 0x09, 0xf1, 0x29, 0x6a, 0xc0, 0xa2, 0xcf, 0xb0, 0x2d, 0xab, 0xa1, 0x74, 0x94, 0x6e, - 0x55, 0x0f, 0x97, 0x68, 0x1d, 0x16, 0x0e, 0x88, 0x61, 0x11, 0xaf, 0xa1, 0x76, 0x94, 0xee, 0x92, - 0x2e, 0x56, 0xa8, 0x03, 0x35, 0x77, 0x68, 0x6d, 0x59, 0xc4, 0xa1, 0x36, 0x9d, 0x36, 0x8a, 0x7c, - 0x53, 0x86, 0x50, 0x1f, 0x56, 0x1d, 0xf2, 0x22, 0x5c, 0xb2, 0xd3, 0x0c, 0x3a, 0xf1, 0x48, 0xa3, - 0xc4, 0x49, 0x73, 0xf7, 0x10, 0x86, 0xa5, 0x7d, 0xd7, 0x33, 0x89, 0xd0, 0xab, 0x51, 0xee, 0x28, - 0xdd, 0x8a, 0x9e, 0xc0, 0x30, 0x05, 0x14, 0xe8, 0x4f, 0x0d, 0x3a, 0xf1, 0x77, 0x8c, 0xe9, 0xd0, - 0x35, 0x2c, 0x74, 0x15, 0x16, 0x7c, 0x0e, 0x70, 0x03, 0xea, 0xfd, 0xc6, 0x65, 0xd9, 0x0f, 0x12, - 0x83, 0x2e, 0xe8, 0xd0, 0x47, 0xb0, 0x6c, 0x91, 0x21, 0xa1, 0xb6, 0xeb, 0x3c, 0xb6, 0x47, 0xc4, - 0xa7, 0xc6, 0x68, 0xcc, 0x8d, 0x2c, 0xea, 0xd9, 0x0d, 0xbc, 0x07, 0xcb, 0x92, 0xd7, 0xfc, 0xb1, - 0xeb, 0xf8, 0x04, 0xdd, 0x84, 0x45, 0x8f, 0x98, 0xc4, 0x1e, 0x53, 0x7e, 0x6a, 0xad, 0x7f, 0x31, - 0x7b, 0xaa, 0x1e, 0x10, 0x7c, 0x65, 0xd3, 0x83, 0xc8, 0x4e, 0x3d, 0x64, 0xc3, 0x87, 0xf0, 0xbf, - 0x99, 0x54, 0xe8, 0x2a, 0xac, 0xf8, 0xd2, 0xa6, 0x30, 0x95, 0x1f, 0xb5, 0xa4, 0xe7, 0x6d, 0xa1, - 0x16, 0x54, 0xfd, 0xc8, 0xd1, 0x41, 0xc0, 0x62, 0x00, 0xff, 0xa4, 0xc0, 0x92, 0x7c, 0xda, 0xfc, - 0xb0, 0x8f, 0x09, 0xf1, 0xb6, 0x2c, 0x2e, 0xa5, 0xaa, 0x8b, 0x15, 0xea, 0xc2, 0x49, 0xc3, 0x34, - 0xdd, 0x89, 0x43, 0x53, 0xa1, 0x4f, 0xc3, 0x4c, 0x15, 0x87, 0xd0, 0x17, 0xae, 0x77, 0xb8, 0x65, - 0xf1, 0x98, 0x57, 0xf5, 0x18, 0x40, 0x6d, 0x80, 0xe7, 0xc6, 0xd0, 0xb6, 0xf6, 0x1c, 0x6a, 0x0f, - 0x79, 0x98, 0x4b, 0xba, 0x84, 0xe0, 0xa7, 0xb0, 0xf6, 0x85, 0x3d, 0x24, 0x0f, 0xec, 0x91, 0x4d, - 0x37, 0x0f, 0x88, 0x79, 0x18, 0x66, 0x6a, 0x8e, 0x02, 0x4a, 0xbe, 0x02, 0x92, 0x71, 0x6a, 0xc2, - 0x38, 0xbc, 0x0d, 0xeb, 0x69, 0xe1, 0x22, 0xa0, 0xab, 0x50, 0x1e, 0x32, 0x94, 0xcb, 0x2c, 0xe9, - 0xc1, 0x82, 0x29, 0xeb, 0x53, 0xd7, 0x33, 0x06, 0xe4, 0x3e, 0x99, 0x0a, 0x61, 0x12, 0x82, 0xaf, - 0xc1, 0x29, 0x29, 0xc1, 0x12, 0xea, 0xce, 0xf4, 0x30, 0xde, 0x83, 0x46, 0x96, 0x49, 0xa8, 0x71, - 0x1d, 0x16, 0xc7, 0x52, 0xb0, 0x6b, 0xfd, 0xb3, 0xb3, 0xb2, 0x59, 0x04, 0x5e, 0x0f, 0xe9, 0xf1, - 0x75, 0x38, 0x9d, 0x16, 0xfb, 0xd0, 0x70, 0xa6, 0xa1, 0x3e, 0x4d, 0xa8, 0x08, 0x05, 0xd8, 0x45, - 0x29, 0x76, 0xab, 0x7a, 0xb4, 0xc6, 0x4f, 0xa1, 0x95, 0xcf, 0x2a, 0xb4, 0xba, 0x01, 0x15, 0x71, - 0x4a, 0xc0, 0x7b, 0x0c, 0xb5, 0x22, 0x06, 0xfc, 0x5a, 0x49, 0xd9, 0x6b, 0x38, 0x03, 0x72, 0x74, - 0xf9, 0x91, 0x2e, 0xa9, 0x90, 0x19, 0x85, 0x33, 0xbb, 0xc1, 0x92, 0x23, 0x05, 0x86, 0xd9, 0x99, - 0x82, 0x91, 0x0e, 0x2b, 0x29, 0xe8, 0xf1, 0x74, 0x1c, 0xd4, 0xa6, 0x7a, 0xbf, 0x93, 0x30, 0xeb, - 0x76, 0x96, 0x4e, 0xcf, 0x63, 0xc6, 0x4f, 0xc4, 0x5d, 0x4e, 0x5a, 0xf8, 0xee, 0x21, 0xbd, 0x01, - 0xa7, 0xb7, 0x83, 0x8b, 0xb3, 0xe9, 0x3a, 0xfb, 0xf6, 0x60, 0xe2, 0x19, 0xec, 0xe8, 0xd0, 0x79, - 0x2d, 0xa8, 0x9a, 0x13, 0xcf, 0x23, 0x2c, 0xf5, 0x85, 0xfb, 0x62, 0x00, 0xff, 0xa1, 0x40, 0x2b, - 0x9f, 0x5b, 0x28, 0xd6, 0x85, 0x93, 0xa6, 0xbc, 0x11, 0x09, 0x49, 0xc3, 0xc9, 0x1b, 0xad, 0xa6, - 0x6f, 0xf4, 0x07, 0x50, 0x76, 0x5c, 0x8b, 0xf8, 0x8d, 0x22, 0x4f, 0x8d, 0xe5, 0x84, 0x79, 0xdb, - 0xae, 0x45, 0xf4, 0x60, 0x1f, 0xf5, 0x40, 0x33, 0x3d, 0x62, 0x84, 0xe5, 0x75, 0xcf, 0xb1, 0x5f, - 0x72, 0xbf, 0x97, 0xf4, 0x0c, 0x8e, 0x6d, 0x28, 0x31, 0x56, 0xa9, 0x1c, 0x29, 0x89, 0x72, 0xd4, - 0x82, 0xaa, 0x61, 0x59, 0x1e, 0xf1, 0x7d, 0xe2, 0x37, 0x54, 0x9e, 0xcf, 0x31, 0x80, 0x3e, 0x84, - 0x32, 0x9d, 0x8e, 0x85, 0x4a, 0xf5, 0xfe, 0x5a, 0x46, 0x25, 0x1e, 0xcb, 0x80, 0x06, 0x8f, 0xe0, - 0x7c, 0x18, 0x69, 0xee, 0x28, 0x6f, 0x24, 0x02, 0x91, 0xac, 0xc9, 0x39, 0x29, 0xa6, 0xe4, 0xa7, - 0xd8, 0xfc, 0x5a, 0xfc, 0xab, 0x02, 0xeb, 0xf9, 0xe7, 0xbd, 0xc7, 0xaa, 0xdc, 0x82, 0x2a, 0x8d, - 0x5a, 0x61, 0x99, 0xb7, 0xc2, 0x18, 0xc0, 0xb7, 0x01, 0x85, 0x1a, 0x3f, 0x70, 0x07, 0xd2, 0xdd, - 0x35, 0xf6, 0xa9, 0x14, 0x9b, 0x70, 0x19, 0x17, 0x53, 0xa6, 0xec, 0x09, 0x51, 0x4c, 0xb1, 0x0d, - 0x2b, 0x09, 0x29, 0x22, 0x0d, 0x3f, 0xe3, 0xad, 0xd4, 0xf5, 0xa2, 0xda, 0xd2, 0xce, 0xbd, 0x84, - 0x9c, 0x85, 0x91, 0xe9, 0x21, 0x39, 0x53, 0xe0, 0xc0, 0xf0, 0x1f, 0xba, 0xc2, 0xcb, 0x15, 0x3d, - 0x5c, 0xe2, 0xdf, 0x15, 0x58, 0xce, 0x30, 0xa2, 0x3a, 0xa8, 0x76, 0xa8, 0xab, 0x6a, 0x5b, 0xb3, - 0xfb, 0x04, 0xfa, 0x3c, 0x9a, 0x29, 0x8a, 0xbc, 0x2e, 0x5c, 0x98, 0xaf, 0x52, 0x6a, 0xbe, 0x48, - 0x38, 0xb3, 0x94, 0x72, 0x26, 0xdb, 0xdd, 0xb7, 0x87, 0xe4, 0xae, 0xe7, 0x4e, 0x02, 0x57, 0x57, - 0xf5, 0x18, 0xc0, 0xbf, 0x29, 0x62, 0xc8, 0xe1, 0x87, 0xbc, 0xc7, 0x3a, 0xd9, 0x03, 0x2d, 0x84, - 0x6e, 0x8b, 0x4a, 0x20, 0x6c, 0xc9, 0xe0, 0x78, 0x0b, 0x56, 0x12, 0x3a, 0x8b, 0xc8, 0xf6, 0x61, - 0x95, 0xba, 0xb7, 0x04, 0x6a, 0xc5, 0xa3, 0x96, 0xc2, 0xc5, 0xe4, 0xee, 0x61, 0x07, 0x56, 0x37, - 0x82, 0xcc, 0x4d, 0x3a, 0x20, 0xd7, 0x4c, 0xe5, 0x3f, 0x98, 0xa9, 0xe6, 0x9a, 0x89, 0x7f, 0x54, - 0xe0, 0x8c, 0x7c, 0x60, 0xf6, 0x52, 0xce, 0xaa, 0x40, 0x39, 0x57, 0x4f, 0x3d, 0xc6, 0xd5, 0x2b, - 0xce, 0xbd, 0x7a, 0xe9, 0x6c, 0xc1, 0xf7, 0x61, 0x2d, 0xe5, 0x8f, 0x77, 0x70, 0x6e, 0x1b, 0x5a, - 0x42, 0x98, 0x4e, 0x9e, 0x13, 0x2f, 0xb2, 0x38, 0x1c, 0xb0, 0xcf, 0x46, 0xbe, 0x48, 0xef, 0x07, - 0x87, 0xb2, 0x40, 0x6f, 0x98, 0xc3, 0x0d, 0xcb, 0x12, 0x57, 0xf1, 0xc8, 0xec, 0x6c, 0xc4, 0xcd, - 0x2f, 0x70, 0x4e, 0xd4, 0xdb, 0x1e, 0xb0, 0x40, 0xcb, 0xa2, 0x84, 0x5d, 0x4d, 0xa8, 0x04, 0xf7, - 0x3b, 0x12, 0x16, 0xad, 0xe7, 0x48, 0xbb, 0xc7, 0xa5, 0xdd, 0x25, 0x34, 0x90, 0xe6, 0x1f, 0x4b, - 0x33, 0xc3, 0x1c, 0x7e, 0x49, 0x8c, 0xe8, 0xf2, 0x8b, 0x25, 0xfe, 0x98, 0xb9, 0x3c, 0x21, 0x4b, - 0xa8, 0xd6, 0x48, 0x56, 0xaa, 0xa5, 0xa8, 0x12, 0xf5, 0x7e, 0x56, 0x00, 0xee, 0x78, 0x9e, 0xeb, - 0x6d, 0xf2, 0x46, 0x57, 0x07, 0xd8, 0x73, 0xc8, 0xcb, 0x31, 0x31, 0x29, 0xb1, 0xb4, 0x02, 0xd2, - 0xc4, 0xf4, 0x2d, 0x02, 0xa2, 0x29, 0xa8, 0x01, 0xab, 0x31, 0xc2, 0xd2, 0x91, 0x38, 0x96, 0xed, - 0x0c, 0x34, 0x35, 0xa2, 0xdd, 0x64, 0x1d, 0x91, 0x58, 0x5a, 0x11, 0x21, 0xa8, 0x73, 0x64, 0xdb, - 0xa5, 0x77, 0x5e, 0xda, 0x3e, 0xf5, 0xb5, 0x12, 0x5a, 0x13, 0x8f, 0x12, 0x3e, 0xc9, 0xea, 0xc4, - 0x30, 0x0f, 0x88, 0xa5, 0x95, 0x19, 0x69, 0x22, 0x5b, 0x2c, 0x6d, 0x01, 0x69, 0x50, 0xe3, 0xaa, - 0x3d, 0xda, 0xdf, 0xf7, 0x09, 0xd5, 0x7e, 0x51, 0x7b, 0x3f, 0x28, 0x50, 0x93, 0xc6, 0x0e, 0xb4, - 0x9e, 0x78, 0x57, 0x85, 0x07, 0x17, 0x50, 0x1b, 0x9a, 0xf2, 0x74, 0x12, 0xa8, 0x18, 0x6a, 0xac, - 0x29, 0xa9, 0xfd, 0x70, 0x63, 0x97, 0x1a, 0x1e, 0xe3, 0x57, 0x53, 0x72, 0x43, 0x8d, 0x8a, 0x91, - 0xf1, 0x01, 0x2e, 0x99, 0xd5, 0x7b, 0x01, 0x95, 0xb0, 0x3b, 0xa3, 0x1a, 0x2c, 0x3e, 0xf6, 0x08, - 0xd9, 0xd8, 0xd9, 0xd2, 0x0a, 0x6c, 0xc1, 0x06, 0x77, 0xb6, 0x50, 0x98, 0x95, 0x9b, 0x71, 0x39, - 0x66, 0x18, 0x77, 0xdb, 0x26, 0x0b, 0x92, 0xe3, 0x4f, 0x7c, 0x86, 0x14, 0xd1, 0x32, 0x9c, 0xd8, - 0x36, 0x46, 0xb6, 0x33, 0x60, 0x12, 0x19, 0x54, 0x62, 0x07, 0xef, 0x18, 0xd3, 0x11, 0x71, 0xe8, - 0x8e, 0xe7, 0x9a, 0xc4, 0xf7, 0x6d, 0x67, 0xc0, 0x76, 0xca, 0xbd, 0xeb, 0x71, 0x6f, 0x92, 0x06, - 0x3b, 0x54, 0x81, 0x12, 0xd3, 0x21, 0x50, 0x40, 0xd4, 0x05, 0x4d, 0x61, 0x0b, 0xe1, 0x66, 0x4d, - 0xed, 0xdd, 0x84, 0x53, 0x33, 0x1a, 0x02, 0x5a, 0x00, 0xf5, 0xd1, 0xa1, 0x56, 0x60, 0xaa, 0xe8, - 0x64, 0xe4, 0x3e, 0x27, 0x3b, 0x1e, 0x19, 0x1b, 0x1e, 0xd1, 0x14, 0x04, 0xb0, 0x10, 0x40, 0x9a, - 0xda, 0xff, 0xa7, 0x02, 0x35, 0xc9, 0x20, 0x74, 0x0f, 0xaa, 0xd1, 0x8b, 0x13, 0x9d, 0xc9, 0x99, - 0x16, 0xe3, 0xf7, 0x7b, 0xb3, 0x3d, 0x6b, 0x5b, 0xe4, 0xec, 0xd7, 0x50, 0x4f, 0xbe, 0x78, 0x10, - 0x4e, 0x70, 0xe4, 0xbe, 0xb5, 0x9a, 0xe7, 0xe7, 0xd2, 0x08, 0xd1, 0xdf, 0x86, 0x9f, 0x13, 0xe2, - 0x57, 0x03, 0xba, 0x30, 0x6b, 0xb6, 0x4d, 0x88, 0xff, 0xff, 0x11, 0x54, 0xe2, 0x80, 0xc3, 0x44, - 0x9e, 0x44, 0xcf, 0x12, 0xd4, 0x9d, 0xcb, 0x2e, 0x3d, 0x7a, 0x9a, 0x97, 0x8e, 0x41, 0x29, 0x0e, - 0x7b, 0x16, 0x3e, 0xf3, 0xa5, 0x19, 0x1e, 0xcd, 0x51, 0x54, 0x7a, 0xc5, 0x34, 0x2f, 0x1e, 0x45, - 0x16, 0x1b, 0x94, 0x37, 0x91, 0xa7, 0x0c, 0x9a, 0x33, 0xf2, 0xa7, 0x0c, 0x9a, 0x3b, 0xde, 0xef, - 0x40, 0x4d, 0xca, 0x4b, 0x74, 0x76, 0xf6, 0x08, 0x13, 0x88, 0xee, 0xcc, 0x26, 0x88, 0x25, 0x4a, - 0x65, 0x0c, 0xe5, 0xbc, 0x63, 0x12, 0x3d, 0x3b, 0x25, 0x31, 0x6f, 0x42, 0x78, 0x02, 0x27, 0x12, - 0xf5, 0x0a, 0x9d, 0x4b, 0xb0, 0xe4, 0x4d, 0x02, 0x4d, 0x3c, 0x8f, 0x44, 0xc8, 0x75, 0xa2, 0xae, - 0x99, 0x6c, 0x64, 0xe8, 0x52, 0x1e, 0x73, 0x6e, 0x33, 0x6c, 0xf6, 0x8e, 0x43, 0x2a, 0xce, 0xdb, - 0x85, 0x25, 0xb9, 0x99, 0xa1, 0x4e, 0x8a, 0x37, 0xd3, 0x32, 0x9b, 0xe7, 0xe6, 0x50, 0xc8, 0xce, - 0x91, 0xfa, 0x50, 0xc6, 0x39, 0xd9, 0x7e, 0x97, 0x71, 0x4e, 0x4e, 0x1b, 0xbb, 0xf5, 0xe9, 0x5f, - 0x6f, 0xda, 0xca, 0xab, 0x37, 0x6d, 0xe5, 0xf5, 0x9b, 0xb6, 0xf2, 0xfd, 0xdb, 0x76, 0xe1, 0xd5, - 0xdb, 0x76, 0xe1, 0xef, 0xb7, 0xed, 0xc2, 0x37, 0xad, 0x79, 0x5f, 0x19, 0x9f, 0x2d, 0xf0, 0x7f, - 0xd7, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xe6, 0x06, 0x8a, 0x8c, 0x14, 0x00, 0x00, + // 1626 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xcf, 0x6f, 0x13, 0xc7, + 0x17, 0xf7, 0x6e, 0x9c, 0xc4, 0x7e, 0x0e, 0x66, 0x33, 0xf9, 0x81, 0x31, 0xc6, 0x84, 0x85, 0x2f, + 0xdf, 0xe0, 0xef, 0x57, 0x40, 0x8d, 0x5a, 0x15, 0x51, 0xa9, 0x84, 0x40, 0x69, 0xf8, 0x11, 0xa2, + 0x0d, 0xa1, 0x6a, 0x39, 0x54, 0xcb, 0xee, 0xc4, 0x59, 0xc5, 0x9e, 0x75, 0x67, 0xc7, 0x84, 0xfc, + 0x17, 0xbd, 0xf5, 0xd4, 0x7b, 0xa5, 0xf6, 0x50, 0x55, 0xaa, 0x7a, 0xa8, 0xd4, 0x73, 0x8f, 0x1c, + 0x7b, 0x44, 0x70, 0xed, 0x1f, 0x51, 0xcd, 0xec, 0xec, 0xee, 0xec, 0x0f, 0x3b, 0xa9, 0x38, 0x70, + 0x49, 0x3c, 0x9f, 0x79, 0xef, 0xcd, 0xfb, 0x35, 0xef, 0xcd, 0x5b, 0xf8, 0xd0, 0xf1, 0x7d, 0xea, + 0x7a, 0xc4, 0x66, 0x3e, 0xbd, 0xaa, 0xfc, 0x1e, 0x52, 0x9f, 0xf9, 0x57, 0xc5, 0xdf, 0x40, 0xc5, + 0xaf, 0x08, 0x08, 0xd5, 0x14, 0xc8, 0xfc, 0x43, 0x03, 0x63, 0x7b, 0x68, 0x3b, 0x78, 0xdb, 0xeb, + 0x11, 0x0b, 0x7f, 0x33, 0xc2, 0x01, 0x43, 0x0d, 0x98, 0x0d, 0x38, 0xb6, 0xe1, 0x36, 0xb4, 0x15, + 0x6d, 0xb5, 0x6a, 0x45, 0x4b, 0xb4, 0x0c, 0x33, 0x7b, 0xd8, 0x76, 0x31, 0x6d, 0xe8, 0x2b, 0xda, + 0xea, 0x9c, 0x25, 0x57, 0x68, 0x05, 0x6a, 0x7e, 0xdf, 0xdd, 0x70, 0x31, 0x61, 0x1e, 0x3b, 0x6c, + 0x4c, 0x89, 0x4d, 0x15, 0x42, 0x5d, 0x58, 0x24, 0xf8, 0x20, 0x5a, 0xf2, 0xd3, 0x6c, 0x36, 0xa2, + 0xb8, 0x51, 0x16, 0xa4, 0x85, 0x7b, 0xc8, 0x84, 0xb9, 0x5d, 0x9f, 0x3a, 0x58, 0xea, 0xd5, 0x98, + 0x5e, 0xd1, 0x56, 0x2b, 0x56, 0x0a, 0x33, 0x7f, 0xd5, 0x00, 0x85, 0x06, 0x30, 0x9b, 0x8d, 0x82, + 0x2d, 0xfb, 0xb0, 0xef, 0xdb, 0x2e, 0xba, 0x06, 0x33, 0x81, 0x00, 0x84, 0x05, 0xf5, 0x6e, 0xe3, + 0x8a, 0xea, 0x08, 0x85, 0xc1, 0x92, 0x74, 0xe8, 0xff, 0x30, 0xef, 0xe2, 0x3e, 0x66, 0x9e, 0x4f, + 0x9e, 0x78, 0x03, 0x1c, 0x30, 0x7b, 0x30, 0x14, 0x56, 0x4e, 0x59, 0xf9, 0x0d, 0xf4, 0x29, 0xd4, + 0x86, 0x98, 0x0e, 0xbc, 0x20, 0xf0, 0x7c, 0x12, 0x08, 0x83, 0xeb, 0xdd, 0xb3, 0xf9, 0x43, 0xb6, + 0x12, 0x22, 0x4b, 0xe5, 0x30, 0x77, 0x60, 0x5e, 0xf1, 0x7b, 0x30, 0xf4, 0x49, 0x80, 0xd1, 0x2d, + 0x98, 0xa5, 0xd8, 0xc1, 0xde, 0x90, 0x09, 0xb5, 0x6b, 0xdd, 0x4b, 0x79, 0x89, 0x56, 0x48, 0xf0, + 0x85, 0xc7, 0xf6, 0x62, 0x4f, 0x59, 0x11, 0x9b, 0xb9, 0x0f, 0xa7, 0xc7, 0x52, 0xa1, 0x6b, 0xb0, + 0x10, 0x28, 0x9b, 0xd2, 0x57, 0xe2, 0xa8, 0x39, 0xab, 0x68, 0x0b, 0xb5, 0xa0, 0x1a, 0xc4, 0xa1, + 0x0a, 0x43, 0x9e, 0x00, 0xe6, 0x0f, 0x1a, 0xcc, 0xa9, 0xa7, 0x4d, 0x4e, 0x9c, 0x21, 0xc6, 0x74, + 0xc3, 0x15, 0x52, 0xaa, 0x96, 0x5c, 0xa1, 0x55, 0x38, 0x69, 0x3b, 0x8e, 0x3f, 0x22, 0x2c, 0x93, + 0x3c, 0x59, 0x98, 0xab, 0x42, 0x30, 0x3b, 0xf0, 0xe9, 0xfe, 0x86, 0x2b, 0xb2, 0xa6, 0x6a, 0x25, + 0x00, 0x6a, 0x03, 0xbc, 0xb0, 0xfb, 0x9e, 0xbb, 0x43, 0x98, 0xd7, 0x17, 0x89, 0x52, 0xb6, 0x14, + 0xc4, 0x7c, 0x06, 0x4b, 0x9f, 0x79, 0x7d, 0xfc, 0xd0, 0x1b, 0x78, 0x6c, 0x7d, 0x0f, 0x3b, 0xfb, + 0x51, 0xae, 0x17, 0x28, 0xa0, 0x15, 0x2b, 0xa0, 0x18, 0xa7, 0xa7, 0x8c, 0x33, 0x37, 0x61, 0x39, + 0x2b, 0x5c, 0x06, 0x74, 0x11, 0xa6, 0xfb, 0x1c, 0x15, 0x32, 0xcb, 0x56, 0xb8, 0xe0, 0xca, 0x06, + 0xcc, 0xa7, 0x76, 0x0f, 0x3f, 0xc0, 0x87, 0x52, 0x98, 0x82, 0x98, 0xd7, 0xe1, 0x94, 0x92, 0xa1, + 0x29, 0x75, 0xc7, 0x7a, 0xd8, 0xdc, 0x81, 0x46, 0x9e, 0x49, 0xaa, 0x71, 0x03, 0x66, 0x87, 0x4a, + 0xb0, 0x6b, 0xdd, 0x73, 0xe3, 0xae, 0x83, 0x0c, 0xbc, 0x15, 0xd1, 0x9b, 0x37, 0xe0, 0x4c, 0x56, + 0xec, 0x23, 0x9b, 0x1c, 0x46, 0xfa, 0x34, 0xa1, 0x22, 0x15, 0xe0, 0x37, 0x6d, 0x6a, 0xb5, 0x6a, + 0xc5, 0x6b, 0xf3, 0x19, 0xb4, 0x8a, 0x59, 0xa5, 0x56, 0x37, 0xa1, 0x22, 0x4f, 0x09, 0x79, 0x8f, + 0xa1, 0x56, 0xcc, 0x60, 0xbe, 0xd6, 0x32, 0xf6, 0xda, 0xa4, 0x87, 0x8f, 0x2e, 0x60, 0xca, 0x2d, + 0x97, 0x32, 0xe3, 0x70, 0xe6, 0x37, 0x78, 0x72, 0x64, 0xc0, 0x28, 0x3b, 0x33, 0x30, 0xb2, 0x60, + 0x21, 0x03, 0x3d, 0x39, 0x1c, 0x86, 0xd5, 0xad, 0xde, 0x5d, 0x49, 0x99, 0x75, 0x27, 0x4f, 0x67, + 0x15, 0x31, 0x9b, 0x4f, 0xe5, 0x5d, 0x4e, 0x5b, 0xf8, 0xee, 0x21, 0xbd, 0x09, 0x67, 0x36, 0xc3, + 0x8b, 0xb3, 0xee, 0x93, 0x5d, 0xaf, 0x37, 0xa2, 0x36, 0x3f, 0x3a, 0x72, 0x5e, 0x0b, 0xaa, 0xce, + 0x88, 0x52, 0xcc, 0x53, 0x5f, 0xba, 0x2f, 0x01, 0xcc, 0xdf, 0x35, 0x68, 0x15, 0x73, 0x4b, 0xc5, + 0x56, 0xe1, 0xa4, 0xa3, 0x6e, 0xc4, 0x42, 0xb2, 0x70, 0xfa, 0x46, 0xeb, 0xd9, 0x1b, 0xfd, 0x5f, + 0x98, 0x26, 0xbe, 0x8b, 0x79, 0x6d, 0xe5, 0xa9, 0x31, 0x9f, 0x32, 0x6f, 0xd3, 0x77, 0xb1, 0x15, + 0xee, 0xa3, 0x0e, 0x18, 0x0e, 0xc5, 0x76, 0x54, 0x9f, 0x77, 0x88, 0xf7, 0x52, 0xf8, 0xbd, 0x6c, + 0xe5, 0x70, 0xd3, 0x83, 0x32, 0x67, 0x55, 0xca, 0x91, 0x96, 0x2a, 0x47, 0x2d, 0xa8, 0xda, 0xae, + 0x4b, 0x71, 0x10, 0xe0, 0xa0, 0xa1, 0x8b, 0x7c, 0x4e, 0x00, 0xf4, 0x3f, 0x98, 0x66, 0x87, 0x43, + 0xa9, 0x52, 0xbd, 0xbb, 0x94, 0x53, 0x49, 0xc4, 0x32, 0xa4, 0x31, 0x07, 0x70, 0x21, 0x8a, 0xb4, + 0x70, 0x14, 0x1d, 0xc8, 0x40, 0xa4, 0x6b, 0x72, 0x41, 0x8a, 0x69, 0xc5, 0x29, 0x36, 0xb9, 0x16, + 0xff, 0xac, 0xc1, 0x72, 0xf1, 0x79, 0xef, 0xb1, 0x2a, 0xb7, 0xa0, 0xca, 0xe2, 0x5e, 0x3a, 0x2d, + 0x7a, 0x69, 0x02, 0x98, 0x77, 0x00, 0x45, 0x1a, 0x3f, 0xf4, 0x7b, 0xca, 0xdd, 0xb5, 0x77, 0x99, + 0x12, 0x9b, 0x68, 0x99, 0x14, 0x53, 0xae, 0xec, 0x09, 0x59, 0x4c, 0x4d, 0x0f, 0x16, 0x52, 0x52, + 0x64, 0x1a, 0x7e, 0x2c, 0x5a, 0xa9, 0x4f, 0xe3, 0xda, 0xd2, 0x2e, 0xbc, 0x84, 0x82, 0x85, 0x93, + 0x59, 0x11, 0x39, 0x57, 0x60, 0xcf, 0x0e, 0x1e, 0xf9, 0xd2, 0xcb, 0x15, 0x2b, 0x5a, 0x9a, 0xbf, + 0x69, 0x30, 0x9f, 0x63, 0x44, 0x75, 0xd0, 0xbd, 0x48, 0x57, 0xdd, 0x73, 0xc7, 0xf7, 0x09, 0xf4, + 0x49, 0xfc, 0x28, 0x09, 0xdf, 0x0b, 0x17, 0x27, 0xab, 0x94, 0x79, 0xa0, 0xa4, 0x9c, 0x59, 0xce, + 0x38, 0x93, 0xef, 0xee, 0x7a, 0x7d, 0x7c, 0x8f, 0xfa, 0xa3, 0xd0, 0xd5, 0x55, 0x2b, 0x01, 0xcc, + 0x5f, 0xa2, 0x57, 0x92, 0x38, 0xe4, 0x3d, 0xd6, 0xc9, 0x0e, 0x18, 0x11, 0x74, 0x47, 0x56, 0x02, + 0x69, 0x4b, 0x0e, 0x37, 0x37, 0x60, 0x21, 0xa5, 0xb3, 0x8c, 0x6c, 0x17, 0x16, 0x99, 0x7f, 0x5b, + 0xa2, 0x6e, 0xf2, 0x56, 0xd3, 0x84, 0x98, 0xc2, 0x3d, 0x93, 0xc0, 0xe2, 0x5a, 0x98, 0xb9, 0x69, + 0x07, 0x14, 0x9a, 0xa9, 0xfd, 0x0b, 0x33, 0xf5, 0x42, 0x33, 0xcd, 0xef, 0x35, 0x38, 0xab, 0x1e, + 0x98, 0xbf, 0x94, 0xe3, 0x2a, 0x50, 0xc1, 0xd5, 0xd3, 0x8f, 0x71, 0xf5, 0xa6, 0x26, 0x5e, 0xbd, + 0x6c, 0xb6, 0x98, 0x0f, 0x60, 0x29, 0xe3, 0x8f, 0x77, 0x70, 0x6e, 0x1b, 0x5a, 0x52, 0x98, 0x85, + 0x5f, 0x60, 0x1a, 0x5b, 0x1c, 0x3d, 0xd1, 0xcf, 0xc5, 0xbe, 0xc8, 0xee, 0x87, 0x87, 0xf2, 0x40, + 0xaf, 0x39, 0xfd, 0x35, 0xd7, 0x95, 0x57, 0xf1, 0xc8, 0xec, 0x6c, 0x24, 0xcd, 0x2f, 0x74, 0x4e, + 0xdc, 0xdb, 0x1e, 0xf2, 0x40, 0xab, 0xa2, 0xa4, 0x5d, 0x4d, 0xa8, 0x84, 0xf7, 0x3b, 0x16, 0x16, + 0xaf, 0x27, 0x48, 0xbb, 0x2f, 0xa4, 0xdd, 0xc3, 0x2c, 0x94, 0x16, 0x1c, 0x4b, 0x33, 0xdb, 0xe9, + 0x7f, 0x8e, 0xed, 0xf8, 0xf2, 0xcb, 0xa5, 0xf9, 0x01, 0x77, 0x79, 0x4a, 0x96, 0x54, 0xad, 0x91, + 0xae, 0x54, 0x73, 0x71, 0x25, 0xea, 0xfc, 0xa8, 0x01, 0xdc, 0xa5, 0xd4, 0xa7, 0xeb, 0xa2, 0xd1, + 0xd5, 0x01, 0x76, 0x08, 0x7e, 0x39, 0xc4, 0x0e, 0xc3, 0xae, 0x51, 0x42, 0x86, 0x7c, 0x7d, 0xcb, + 0x80, 0x18, 0x1a, 0x6a, 0xc0, 0x62, 0x82, 0xf0, 0x74, 0xc4, 0xc4, 0xf5, 0x48, 0xcf, 0xd0, 0x63, + 0xda, 0x75, 0xde, 0x11, 0xb1, 0x6b, 0x4c, 0x21, 0x04, 0x75, 0x81, 0x6c, 0xfa, 0xec, 0xee, 0x4b, + 0x2f, 0x60, 0x81, 0x51, 0x46, 0x4b, 0x72, 0x28, 0x11, 0x2f, 0x59, 0x0b, 0xdb, 0xce, 0x1e, 0x76, + 0x8d, 0x69, 0x4e, 0x9a, 0xca, 0x16, 0xd7, 0x98, 0x41, 0x06, 0xd4, 0x84, 0x6a, 0x8f, 0x77, 0x77, + 0x03, 0xcc, 0x8c, 0x9f, 0xf4, 0xce, 0x77, 0x1a, 0xd4, 0x94, 0x67, 0x07, 0x5a, 0x4e, 0x0d, 0x66, + 0xd1, 0xc1, 0x25, 0xd4, 0x86, 0xa6, 0xfa, 0x3a, 0x09, 0x55, 0x8c, 0x34, 0x36, 0xb4, 0xcc, 0x7e, + 0xb4, 0xb1, 0xcd, 0x6c, 0xca, 0xf9, 0xf5, 0x8c, 0xdc, 0x48, 0xa3, 0xa9, 0xd8, 0xf8, 0x10, 0x57, + 0xcc, 0xea, 0xdc, 0x97, 0x33, 0xae, 0x32, 0x8c, 0xa1, 0x33, 0xf2, 0x8d, 0xad, 0x60, 0x3b, 0x64, + 0x9f, 0xf8, 0x07, 0xc4, 0x28, 0xa1, 0xd3, 0xb0, 0x94, 0xdd, 0x7c, 0x7c, 0x40, 0x30, 0x35, 0xb4, + 0xce, 0x01, 0x54, 0xa2, 0x4e, 0x8f, 0x6a, 0x30, 0xfb, 0x84, 0x62, 0xbc, 0xb6, 0xb5, 0x61, 0x94, + 0xf8, 0x82, 0x0f, 0x01, 0x7c, 0xa1, 0x71, 0x8f, 0xad, 0x27, 0xa5, 0x9d, 0x63, 0x22, 0x04, 0xeb, + 0x3c, 0xe0, 0x24, 0x18, 0x05, 0x1c, 0x99, 0x42, 0xf3, 0x70, 0x62, 0xd3, 0x1e, 0x78, 0xa4, 0xc7, + 0x25, 0x72, 0xa8, 0xcc, 0x8d, 0xd8, 0xb2, 0x0f, 0x07, 0x98, 0xb0, 0x2d, 0xea, 0x3b, 0x38, 0x08, + 0x3c, 0xd2, 0xe3, 0x3b, 0xd3, 0x9d, 0x1b, 0x49, 0x9f, 0x53, 0x1e, 0x89, 0xa8, 0x02, 0x65, 0xae, + 0x43, 0xa8, 0x80, 0xac, 0x31, 0x86, 0xc6, 0x17, 0x32, 0x64, 0x86, 0xde, 0xb9, 0x05, 0xa7, 0xc6, + 0x34, 0x17, 0x34, 0x03, 0xfa, 0xe3, 0x7d, 0xa3, 0xc4, 0x55, 0xb1, 0xf0, 0xc0, 0x7f, 0x81, 0xb7, + 0x28, 0x1e, 0xda, 0x14, 0x1b, 0x1a, 0x02, 0x98, 0x09, 0x21, 0x43, 0xef, 0xfe, 0x5d, 0x81, 0x9a, + 0x62, 0x10, 0xba, 0x0f, 0xd5, 0x78, 0x7a, 0x45, 0x05, 0x63, 0xaf, 0xf2, 0x35, 0xa1, 0xd9, 0x1e, + 0xb7, 0x2d, 0xf3, 0xff, 0x4b, 0xa8, 0xa7, 0xa7, 0x27, 0x64, 0xa6, 0x38, 0x0a, 0xe7, 0xb6, 0xe6, + 0x85, 0x89, 0x34, 0x52, 0xf4, 0xd7, 0xd1, 0xc7, 0x8d, 0x64, 0x02, 0x41, 0x17, 0xc7, 0xbd, 0x93, + 0x53, 0xe2, 0xff, 0x73, 0x04, 0x95, 0x3c, 0x60, 0x3f, 0x95, 0x73, 0xf1, 0x88, 0x83, 0x56, 0x27, + 0xb2, 0x2b, 0x03, 0x54, 0xf3, 0xf2, 0x31, 0x28, 0xe5, 0x61, 0xcf, 0xa3, 0x4f, 0x06, 0xca, 0x3c, + 0x80, 0x26, 0x28, 0xaa, 0x4c, 0x44, 0xcd, 0x4b, 0x47, 0x91, 0x25, 0x06, 0x15, 0xbd, 0xee, 0x33, + 0x06, 0x4d, 0x18, 0x1f, 0x32, 0x06, 0x4d, 0x1c, 0x15, 0xb6, 0xa0, 0xa6, 0xe4, 0x25, 0x3a, 0x37, + 0xfe, 0x39, 0x14, 0x8a, 0x5e, 0x19, 0x4f, 0x90, 0x48, 0x54, 0x4a, 0x22, 0x2a, 0x98, 0x89, 0x52, + 0xfd, 0x3f, 0x23, 0xb1, 0xe8, 0xb5, 0xf1, 0x14, 0x4e, 0xa4, 0x6a, 0x1f, 0x3a, 0x9f, 0x62, 0x29, + 0x7a, 0x55, 0x34, 0xcd, 0x49, 0x24, 0x52, 0x2e, 0x89, 0x3b, 0x70, 0xba, 0x29, 0xa2, 0xcb, 0x45, + 0xcc, 0x85, 0x8d, 0xb5, 0xd9, 0x39, 0x0e, 0xa9, 0x3c, 0x6f, 0x1b, 0xe6, 0xd4, 0xc6, 0x88, 0x56, + 0x32, 0xbc, 0xb9, 0xf6, 0xdb, 0x3c, 0x3f, 0x81, 0x42, 0x75, 0x8e, 0xd2, 0xd3, 0x72, 0xce, 0xc9, + 0xf7, 0xce, 0x9c, 0x73, 0x0a, 0x5a, 0xe2, 0xed, 0x8f, 0xfe, 0x7c, 0xd3, 0xd6, 0x5e, 0xbd, 0x69, + 0x6b, 0xaf, 0xdf, 0xb4, 0xb5, 0x6f, 0xdf, 0xb6, 0x4b, 0xaf, 0xde, 0xb6, 0x4b, 0x7f, 0xbd, 0x6d, + 0x97, 0xbe, 0x6a, 0x4d, 0xfa, 0xe6, 0xf9, 0x7c, 0x46, 0xfc, 0xbb, 0xfe, 0x4f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x83, 0x2d, 0x56, 0x38, 0x1a, 0x15, 0x00, 0x00, } func (m *SpaceSignRequest) Marshal() (dAtA []byte, err error) { @@ -2219,6 +2257,11 @@ func (m *SpaceStatusPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Permissions != 0 { + i = encodeVarintCoordinator(dAtA, i, uint64(m.Permissions)) + i-- + dAtA[i] = 0x18 + } if m.DeletionTimestamp != 0 { i = encodeVarintCoordinator(dAtA, i, uint64(m.DeletionTimestamp)) i-- @@ -3453,6 +3496,9 @@ func (m *SpaceStatusPayload) Size() (n int) { if m.DeletionTimestamp != 0 { n += 1 + sovCoordinator(uint64(m.DeletionTimestamp)) } + if m.Permissions != 0 { + n += 1 + sovCoordinator(uint64(m.Permissions)) + } return n } @@ -4261,6 +4307,25 @@ func (m *SpaceStatusPayload) Unmarshal(dAtA []byte) error { break } } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + m.Permissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCoordinator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permissions |= SpacePermissions(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipCoordinator(dAtA[iNdEx:]) diff --git a/coordinator/coordinatorproto/protos/coordinator.proto b/coordinator/coordinatorproto/protos/coordinator.proto index 9f7a6909..ac8d9528 100644 --- a/coordinator/coordinatorproto/protos/coordinator.proto +++ b/coordinator/coordinatorproto/protos/coordinator.proto @@ -75,9 +75,15 @@ enum SpaceStatus { SpaceStatusNotExists = 4; } +enum SpacePermissions { + SpacePermissionsUnknown = 0; + SpacePermissionsOwner = 1; +} + message SpaceStatusPayload { SpaceStatus status = 1; int64 deletionTimestamp = 2; + SpacePermissions permissions = 3; } message SpaceSignResponse {