diff --git a/commonspace/object/tree/objecttree/historytree.go b/commonspace/object/tree/objecttree/historytree.go index e8de9520..c5b78a95 100644 --- a/commonspace/object/tree/objecttree/historytree.go +++ b/commonspace/object/tree/objecttree/historytree.go @@ -43,14 +43,5 @@ func (h *historyTree) rebuildFromStorage(beforeId string, include bool) (err err defer ot.aclList.RUnlock() state := ot.aclList.AclState() - if len(ot.keys) != len(state.UserReadKeys()) { - for key, value := range state.UserReadKeys() { - treeKey, err := deriveTreeKey(value, h.id) - if err != nil { - return err - } - ot.keys[key] = treeKey - } - } - return + return ot.readKeysFromAclState(state) } diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index 7ba9c2e5..f455b150 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -27,6 +27,7 @@ var ( ErrHasInvalidChanges = errors.New("the change is invalid") ErrNoCommonSnapshot = errors.New("trees doesn't have a common snapshot") ErrNoChangeInTree = errors.New("no such change in tree") + ErrMissingKey = errors.New("missing current read key") ) type AddResultSummary int @@ -99,7 +100,8 @@ type objectTree struct { root *Change tree *Tree - keys map[string]crypto.SymKey + keys map[string]crypto.SymKey + currentReadKey crypto.SymKey // buffers difSnapshotBuf []*treechangeproto.RawTreeChangeWithId @@ -238,10 +240,11 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt if content.IsEncrypted { readKeyId = state.CurrentReadKeyId() - readKey, err = state.CurrentReadKey() - if err != nil { + if ot.currentReadKey == nil { + err = ErrMissingKey return } + readKey = ot.currentReadKey } cnt = BuilderContent{ TreeHeadIds: ot.tree.Heads(), @@ -637,15 +640,9 @@ func (ot *objectTree) validateTree(newChanges []*Change) error { defer ot.aclList.RUnlock() state := ot.aclList.AclState() - // just not to take lock many times, updating the key map from aclList - if len(ot.keys) != len(state.UserReadKeys()) { - for key, value := range state.UserReadKeys() { - treeKey, err := deriveTreeKey(value, ot.id) - if err != nil { - return err - } - ot.keys[key] = treeKey - } + err := ot.readKeysFromAclState(state) + if err != nil { + return err } if len(newChanges) == 0 { return ot.validator.ValidateFullTree(ot.tree, ot.aclList) @@ -654,6 +651,26 @@ func (ot *objectTree) validateTree(newChanges []*Change) error { return ot.validator.ValidateNewChanges(ot.tree, ot.aclList, newChanges) } +func (ot *objectTree) readKeysFromAclState(state *list.AclState) (err error) { + // just not to take lock many times, updating the key map from aclList + if len(ot.keys) == len(state.UserReadKeys()) { + return nil + } + for key, value := range state.UserReadKeys() { + treeKey, err := deriveTreeKey(value, ot.id) + if err != nil { + return err + } + ot.keys[key] = treeKey + } + curKey, err := state.CurrentReadKey() + if err != nil { + return err + } + ot.currentReadKey, err = deriveTreeKey(curKey, ot.id) + return err +} + func (ot *objectTree) Debug(parser DescriptionParser) (DebugInfo, error) { return objectTreeDebug{}.debugInfo(ot, parser) }