Fix bugs appearing while creating tree

This commit is contained in:
mcrakhman 2022-10-19 20:21:58 +02:00
parent 6cb6b91bd4
commit c9ded8956c
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
7 changed files with 61 additions and 49 deletions

View File

@ -2,6 +2,7 @@ package commonspace
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
@ -30,6 +31,7 @@ type Service interface {
type service struct { type service struct {
config config2.Space config config2.Space
account account.Service
configurationService nodeconf.Service configurationService nodeconf.Service
storageProvider storage.SpaceStorageProvider storageProvider storage.SpaceStorageProvider
cache treegetter.TreeGetter cache treegetter.TreeGetter
@ -38,6 +40,7 @@ type service struct {
func (s *service) Init(a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
s.config = a.MustComponent(config2.CName).(*config2.Config).Space s.config = a.MustComponent(config2.CName).(*config2.Config).Space
s.account = a.MustComponent(account.CName).(account.Service)
s.storageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider) s.storageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
s.configurationService = a.MustComponent(nodeconf.CName).(nodeconf.Service) s.configurationService = a.MustComponent(nodeconf.CName).(nodeconf.Service)
s.cache = a.MustComponent(treegetter.CName).(treegetter.TreeGetter) s.cache = a.MustComponent(treegetter.CName).(treegetter.TreeGetter)
@ -93,6 +96,7 @@ func (s *service) GetSpace(ctx context.Context, id string) (Space, error) {
syncService: syncService, syncService: syncService,
diffService: diffService, diffService: diffService,
cache: s.cache, cache: s.cache,
account: s.account,
storage: st, storage: st,
} }
if err := sp.Init(ctx); err != nil { if err := sp.Init(ctx); err != nil {

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
@ -70,6 +71,7 @@ type space struct {
diffService diffservice.DiffService diffService diffservice.DiffService
storage storage.SpaceStorage storage storage.SpaceStorage
cache treegetter.TreeGetter cache treegetter.TreeGetter
account account.Service
aclList list.ACLList aclList list.ACLList
isClosed atomic.Bool isClosed atomic.Bool
@ -93,7 +95,7 @@ func (s *space) Init(ctx context.Context) (err error) {
if err != nil { if err != nil {
return return
} }
s.aclList, err = list.BuildACLList(aclStorage) s.aclList, err = list.BuildACLListWithIdentity(s.account.Account(), aclStorage)
if err != nil { if err != nil {
return return
} }

View File

@ -38,7 +38,7 @@ func (s *syncClient) LastUsage() time.Time {
func (s *syncClient) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) { func (s *syncClient) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
s.notifyIfNeeded(message) s.notifyIfNeeded(message)
return s.BroadcastAsync(message) return s.StreamPool.BroadcastAsync(message)
} }
func (s *syncClient) BroadcastAsyncOrSendResponsible(message *spacesyncproto.ObjectSyncMessage) (err error) { func (s *syncClient) BroadcastAsyncOrSendResponsible(message *spacesyncproto.ObjectSyncMessage) (err error) {

View File

@ -5,10 +5,10 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
aclrecordproto2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
signingkey2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"go.uber.org/zap" "go.uber.org/zap"
@ -30,17 +30,17 @@ var ErrIncorrectRoot = errors.New("incorrect root")
type UserPermissionPair struct { type UserPermissionPair struct {
Identity string Identity string
Permission aclrecordproto2.ACLUserPermissions Permission aclrecordproto.ACLUserPermissions
} }
type ACLState struct { type ACLState struct {
id string id string
currentReadKeyHash uint64 currentReadKeyHash uint64
userReadKeys map[uint64]*symmetric.Key userReadKeys map[uint64]*symmetric.Key
userStates map[string]*aclrecordproto2.ACLUserState userStates map[string]*aclrecordproto.ACLUserState
userInvites map[string]*aclrecordproto2.ACLUserInvite userInvites map[string]*aclrecordproto.ACLUserInvite
encryptionKey encryptionkey.PrivKey encryptionKey encryptionkey.PrivKey
signingKey signingkey2.PrivKey signingKey signingkey.PrivKey
identity string identity string
permissionsAtRecord map[string][]UserPermissionPair permissionsAtRecord map[string][]UserPermissionPair
@ -50,9 +50,9 @@ type ACLState struct {
func newACLStateWithKeys( func newACLStateWithKeys(
id string, id string,
signingKey signingkey2.PrivKey, signingKey signingkey.PrivKey,
encryptionKey encryptionkey.PrivKey) (*ACLState, error) { encryptionKey encryptionkey.PrivKey) (*ACLState, error) {
identity, err := signingKey.Raw() identity, err := signingKey.GetPublic().Raw()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -62,8 +62,8 @@ func newACLStateWithKeys(
signingKey: signingKey, signingKey: signingKey,
encryptionKey: encryptionKey, encryptionKey: encryptionKey,
userReadKeys: make(map[uint64]*symmetric.Key), userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclrecordproto2.ACLUserState), userStates: make(map[string]*aclrecordproto.ACLUserState),
userInvites: make(map[string]*aclrecordproto2.ACLUserInvite), userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
permissionsAtRecord: make(map[string][]UserPermissionPair), permissionsAtRecord: make(map[string][]UserPermissionPair),
}, nil }, nil
} }
@ -72,8 +72,8 @@ func newACLState(id string) *ACLState {
return &ACLState{ return &ACLState{
id: id, id: id,
userReadKeys: make(map[uint64]*symmetric.Key), userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclrecordproto2.ACLUserState), userStates: make(map[string]*aclrecordproto.ACLUserState),
userInvites: make(map[string]*aclrecordproto2.ACLUserInvite), userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
permissionsAtRecord: make(map[string][]UserPermissionPair), permissionsAtRecord: make(map[string][]UserPermissionPair),
} }
} }
@ -111,16 +111,19 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
func (st *ACLState) applyRecord(record *ACLRecord) (err error) { func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
if record.Id == st.id { if record.Id == st.id {
root, ok := record.Model.(*aclrecordproto2.ACLRoot) root, ok := record.Model.(*aclrecordproto.ACLRoot)
if !ok { if !ok {
return ErrIncorrectRoot return ErrIncorrectRoot
} }
st.permissionsAtRecord[record.Id] = []UserPermissionPair{
{Identity: string(root.Identity), Permission: aclrecordproto.ACLUserPermissions_Admin},
}
return st.applyRoot(root) return st.applyRoot(root)
} }
aclData := &aclrecordproto2.ACLData{} aclData := &aclrecordproto.ACLData{}
if record.Model != nil { if record.Model != nil {
aclData = record.Model.(*aclrecordproto2.ACLData) aclData = record.Model.(*aclrecordproto.ACLData)
} else { } else {
err = proto.Unmarshal(record.Data, aclData) err = proto.Unmarshal(record.Data, aclData)
if err != nil { if err != nil {
@ -148,8 +151,8 @@ func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
return nil return nil
} }
func (st *ACLState) applyRoot(root *aclrecordproto2.ACLRoot) (err error) { func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
if st.signingKey != nil && st.encryptionKey != nil { if st.signingKey != nil && st.encryptionKey != nil && st.identity == string(root.Identity) {
err = st.saveReadKeyFromRoot(root) err = st.saveReadKeyFromRoot(root)
if err != nil { if err != nil {
return return
@ -157,16 +160,16 @@ func (st *ACLState) applyRoot(root *aclrecordproto2.ACLRoot) (err error) {
} }
// adding user to the list // adding user to the list
userState := &aclrecordproto2.ACLUserState{ userState := &aclrecordproto.ACLUserState{
Identity: root.Identity, Identity: root.Identity,
EncryptionKey: root.EncryptionKey, EncryptionKey: root.EncryptionKey,
Permissions: aclrecordproto2.ACLUserPermissions_Admin, Permissions: aclrecordproto.ACLUserPermissions_Admin,
} }
st.userStates[string(root.Identity)] = userState st.userStates[string(root.Identity)] = userState
return return
} }
func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto2.ACLRoot) (err error) { func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.ACLRoot) (err error) {
var readKey *symmetric.Key var readKey *symmetric.Key
if len(root.GetDerivationScheme()) != 0 { if len(root.GetDerivationScheme()) != 0 {
var encPubKey []byte var encPubKey []byte
@ -175,7 +178,7 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto2.ACLRoot) (err erro
return return
} }
readKey, err = aclrecordproto2.ACLReadKeyDerive([]byte(st.identity), encPubKey) readKey, err = aclrecordproto.ACLReadKeyDerive([]byte(st.identity), encPubKey)
if err != nil { if err != nil {
return return
} }
@ -199,7 +202,7 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto2.ACLRoot) (err erro
return return
} }
func (st *ACLState) applyChangeData(changeData *aclrecordproto2.ACLData, hash uint64, identity []byte) (err error) { func (st *ACLState) applyChangeData(changeData *aclrecordproto.ACLData, hash uint64, identity []byte) (err error) {
defer func() { defer func() {
if err != nil { if err != nil {
return return
@ -214,7 +217,7 @@ func (st *ACLState) applyChangeData(changeData *aclrecordproto2.ACLData, hash ui
return return
} }
if !st.hasPermission(identity, aclrecordproto2.ACLUserPermissions_Admin) { if !st.hasPermission(identity, aclrecordproto.ACLUserPermissions_Admin) {
err = fmt.Errorf("user %s must have admin permissions", identity) err = fmt.Errorf("user %s must have admin permissions", identity)
return return
} }
@ -230,7 +233,7 @@ func (st *ACLState) applyChangeData(changeData *aclrecordproto2.ACLData, hash ui
return nil return nil
} }
func (st *ACLState) applyChangeContent(ch *aclrecordproto2.ACLContentValue) error { func (st *ACLState) applyChangeContent(ch *aclrecordproto.ACLContentValue) error {
switch { switch {
case ch.GetUserPermissionChange() != nil: case ch.GetUserPermissionChange() != nil:
return st.applyUserPermissionChange(ch.GetUserPermissionChange()) return st.applyUserPermissionChange(ch.GetUserPermissionChange())
@ -247,7 +250,7 @@ func (st *ACLState) applyChangeContent(ch *aclrecordproto2.ACLContentValue) erro
} }
} }
func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto2.ACLUserPermissionChange) error { func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto.ACLUserPermissionChange) error {
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
state, exists := st.userStates[chIdentity] state, exists := st.userStates[chIdentity]
if !exists { if !exists {
@ -258,12 +261,12 @@ func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto2.ACLUserPermiss
return nil return nil
} }
func (st *ACLState) applyUserInvite(ch *aclrecordproto2.ACLUserInvite) error { func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error {
st.userInvites[ch.InviteId] = ch st.userInvites[ch.InviteId] = ch
return nil return nil
} }
func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error { func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
invite, exists := st.userInvites[ch.InviteId] invite, exists := st.userInvites[ch.InviteId]
if !exists { if !exists {
return fmt.Errorf("no such invite with id %s", ch.InviteId) return fmt.Errorf("no such invite with id %s", ch.InviteId)
@ -276,12 +279,12 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
// validating signature // validating signature
signature := ch.GetAcceptSignature() signature := ch.GetAcceptSignature()
verificationKey, err := signingkey2.NewSigningEd25519PubKeyFromBytes(invite.AcceptPublicKey) verificationKey, err := signingkey.NewSigningEd25519PubKeyFromBytes(invite.AcceptPublicKey)
if err != nil { if err != nil {
return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err) return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err)
} }
res, err := verificationKey.(signingkey2.PubKey).Verify(ch.Identity, signature) res, err := verificationKey.(signingkey.PubKey).Verify(ch.Identity, signature)
if err != nil { if err != nil {
return fmt.Errorf("verification returned error: %w", err) return fmt.Errorf("verification returned error: %w", err)
} }
@ -302,7 +305,7 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
} }
// adding user to the list // adding user to the list
userState := &aclrecordproto2.ACLUserState{ userState := &aclrecordproto.ACLUserState{
Identity: ch.Identity, Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey, EncryptionKey: ch.EncryptionKey,
Permissions: invite.Permissions, Permissions: invite.Permissions,
@ -311,13 +314,13 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto2.ACLUserJoin) error {
return nil return nil
} }
func (st *ACLState) applyUserAdd(ch *aclrecordproto2.ACLUserAdd) error { func (st *ACLState) applyUserAdd(ch *aclrecordproto.ACLUserAdd) error {
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
if _, exists := st.userStates[chIdentity]; exists { if _, exists := st.userStates[chIdentity]; exists {
return ErrUserAlreadyExists return ErrUserAlreadyExists
} }
st.userStates[chIdentity] = &aclrecordproto2.ACLUserState{ st.userStates[chIdentity] = &aclrecordproto.ACLUserState{
Identity: ch.Identity, Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey, EncryptionKey: ch.EncryptionKey,
Permissions: ch.Permissions, Permissions: ch.Permissions,
@ -337,7 +340,7 @@ func (st *ACLState) applyUserAdd(ch *aclrecordproto2.ACLUserAdd) error {
return nil return nil
} }
func (st *ACLState) applyUserRemove(ch *aclrecordproto2.ACLUserRemove) error { func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error {
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
if chIdentity == st.identity { if chIdentity == st.identity {
return ErrDocumentForbidden return ErrDocumentForbidden
@ -381,7 +384,7 @@ func (st *ACLState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e
return key, hasher.Sum64(), nil return key, hasher.Sum64(), nil
} }
func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto2.ACLUserPermissions) bool { func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto.ACLUserPermissions) bool {
state, exists := st.userStates[string(identity)] state, exists := st.userStates[string(identity)]
if !exists { if !exists {
return false return false
@ -390,17 +393,17 @@ func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto2.AC
return state.Permissions == permission return state.Permissions == permission
} }
func (st *ACLState) isUserJoin(data *aclrecordproto2.ACLData) bool { func (st *ACLState) isUserJoin(data *aclrecordproto.ACLData) bool {
// if we have a UserJoin, then it should always be the first one applied // if we have a UserJoin, then it should always be the first one applied
return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil
} }
func (st *ACLState) isUserAdd(data *aclrecordproto2.ACLData, identity []byte) bool { func (st *ACLState) isUserAdd(data *aclrecordproto.ACLData, identity []byte) bool {
// if we have a UserAdd, then it should always be the first one applied // if we have a UserAdd, then it should always be the first one applied
userAdd := data.GetAclContent()[0].GetUserAdd() userAdd := data.GetAclContent()[0].GetUserAdd()
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0 return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0
} }
func (st *ACLState) GetUserStates() map[string]*aclrecordproto2.ACLUserState { func (st *ACLState) GetUserStates() map[string]*aclrecordproto.ACLUserState {
return st.userStates return st.userStates
} }

View File

@ -71,6 +71,10 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChang
if err != nil { if err != nil {
return return
} }
ch, err = c.unmarshallRawChange(raw, rawIdChange.Id)
if err != nil {
return
}
if verify { if verify {
var identityKey signingkey.PubKey var identityKey signingkey.PubKey
@ -90,8 +94,7 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChang
return return
} }
} }
return
return c.unmarshallRawChange(raw, rawIdChange.Id)
} }
func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) { func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {

View File

@ -53,6 +53,10 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list2.ACLList,
return return
} }
if c.Id == tree.RootId() {
return
}
// checking if the change refers to later acl heads than its previous ids // checking if the change refers to later acl heads than its previous ids
for _, id := range c.PreviousIds { for _, id := range c.PreviousIds {
prevChange := tree.attached[id] prevChange := tree.attached[id]

View File

@ -1,6 +1,7 @@
package tree package tree
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
@ -54,10 +55,7 @@ func createObjectTree(
aclList list.ACLList, aclList list.ACLList,
createStorage storage2.TreeStorageCreatorFunc) (objTree ObjectTree, err error) { createStorage storage2.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
aclList.RLock() aclList.RLock()
var ( aclHeadId := aclList.Head().Id
deps = defaultObjectTreeDeps(nil, nil, aclList)
aclHeadId = aclList.Head().Id
)
aclList.RUnlock() aclList.RUnlock()
if err != nil { if err != nil {
@ -73,11 +71,10 @@ func createObjectTree(
Seed: seed, Seed: seed,
} }
_, raw, err := deps.changeBuilder.BuildInitialContent(cnt) _, raw, err := newChangeBuilder(common.NewKeychain(), nil).BuildInitialContent(cnt)
if err != nil { if err != nil {
return return
} }
deps.changeBuilder.SetRootRawChange(raw)
// create storage // create storage
st, err := createStorage(storage2.TreeStorageCreatePayload{ st, err := createStorage(storage2.TreeStorageCreatePayload{
@ -90,8 +87,7 @@ func createObjectTree(
return return
} }
deps.treeStorage = st return BuildObjectTree(st, aclList)
return buildObjectTree(deps)
} }
func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {