Add new heads logic
This commit is contained in:
parent
0e62047498
commit
2940519b5f
@ -36,7 +36,7 @@ func (tb *ACLTreeBuilder) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tb *ACLTreeBuilder) Build() (*Tree, error) {
|
func (tb *ACLTreeBuilder) Build() (*Tree, error) {
|
||||||
heads := tb.thread.Heads()
|
heads := tb.thread.MaybeHeads()
|
||||||
aclHeads, err := tb.getACLHeads(heads)
|
aclHeads, err := tb.getACLHeads(heads)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -64,6 +64,8 @@ func (d *Document) Update(changes ...*threadmodels.RawChange) (DocumentState, Up
|
|||||||
treeChange := d.treeBuilder.changeCreator(ch.Id, aclChange)
|
treeChange := d.treeBuilder.changeCreator(ch.Id, aclChange)
|
||||||
treeChanges = append(treeChanges, treeChange)
|
treeChanges = append(treeChanges, treeChange)
|
||||||
|
|
||||||
|
// this already sets MaybeHeads to include new changes
|
||||||
|
// TODO: change this behaviour as non-obvious, because it is not evident from the interface
|
||||||
err = d.thread.AddChange(ch)
|
err = d.thread.AddChange(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, UpdateResultNoAction, fmt.Errorf("change with id %s cannot be added: %w", ch.Id, err)
|
return nil, UpdateResultNoAction, fmt.Errorf("change with id %s cannot be added: %w", ch.Id, err)
|
||||||
@ -99,6 +101,11 @@ func (d *Document) Update(changes ...*threadmodels.RawChange) (DocumentState, Up
|
|||||||
return res, UpdateResultRebuild, fmt.Errorf("could not add changes to state, rebuilded")
|
return res, UpdateResultRebuild, fmt.Errorf("could not add changes to state, rebuilded")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setting all heads
|
||||||
|
d.thread.SetHeads(d.docContext.fullTree.Heads())
|
||||||
|
// this should be the entrypoint when we build the document
|
||||||
|
d.thread.SetMaybeHeads(d.docContext.fullTree.Heads())
|
||||||
|
|
||||||
return newState, UpdateResultAppend, nil
|
return newState, UpdateResultAppend, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +158,11 @@ func (d *Document) build(fromStart bool) (DocumentState, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setting all heads
|
||||||
|
d.thread.SetHeads(d.docContext.fullTree.Heads())
|
||||||
|
// this should be the entrypoint when we build the document
|
||||||
|
d.thread.SetMaybeHeads(d.docContext.fullTree.Heads())
|
||||||
|
|
||||||
return d.docContext.docState, nil
|
return d.docContext.docState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,6 +117,6 @@ graph:
|
|||||||
baseSnapshot: A.1.2
|
baseSnapshot: A.1.2
|
||||||
aclHeads: [A.1.2]
|
aclHeads: [A.1.2]
|
||||||
treeHeads: [A.1.2]
|
treeHeads: [A.1.2]
|
||||||
heads:
|
maybeHeads:
|
||||||
- A.1.3
|
- A.1.3
|
||||||
- B.1.2
|
- B.1.2
|
||||||
|
|||||||
@ -14,11 +14,13 @@ type SymKey struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Keychain struct {
|
type Keychain struct {
|
||||||
SigningKeys map[string]threadmodels.SigningPrivKey
|
SigningKeys map[string]threadmodels.SigningPrivKey
|
||||||
EncryptionKeys map[string]threadmodels.EncryptionPrivKey
|
SigningKeysByIdentity map[string]threadmodels.SigningPrivKey
|
||||||
ReadKeys map[string]*SymKey
|
EncryptionKeys map[string]threadmodels.EncryptionPrivKey
|
||||||
GeneratedIdentities map[string]string
|
ReadKeys map[string]*SymKey
|
||||||
coder *threadmodels.Ed25519SigningPubKeyDecoder
|
ReadKeysByHash map[uint64]*SymKey
|
||||||
|
GeneratedIdentities map[string]string
|
||||||
|
coder *threadmodels.Ed25519SigningPubKeyDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKeychain() *Keychain {
|
func NewKeychain() *Keychain {
|
||||||
@ -71,6 +73,7 @@ func (k *Keychain) AddSigningKey(name string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
k.SigningKeysByIdentity[res] = newPrivKey
|
||||||
k.GeneratedIdentities[name] = res
|
k.GeneratedIdentities[name] = res
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +90,10 @@ func (k *Keychain) AddReadKey(name string) {
|
|||||||
Hash: hasher.Sum64(),
|
Hash: hasher.Sum64(),
|
||||||
Key: key,
|
Key: key,
|
||||||
}
|
}
|
||||||
|
k.ReadKeysByHash[hasher.Sum64()] = &SymKey{
|
||||||
|
Hash: hasher.Sum64(),
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Keychain) AddKey(key string) {
|
func (k *Keychain) AddKey(key string) {
|
||||||
|
|||||||
@ -20,36 +20,17 @@ type threadChange struct {
|
|||||||
readKey *SymKey
|
readKey *SymKey
|
||||||
signKey threadmodels.SigningPrivKey
|
signKey threadmodels.SigningPrivKey
|
||||||
|
|
||||||
changesData *pb.PlainTextChangeData
|
changesDataDecrypted []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type ThreadBuilder struct {
|
type ThreadBuilder struct {
|
||||||
threadId string
|
threadId string
|
||||||
allChanges map[string]*threadChange
|
allChanges map[string]*threadChange
|
||||||
heads []string
|
heads []string
|
||||||
|
maybeHeads []string
|
||||||
keychain *Keychain
|
keychain *Keychain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) AddChange(change *threadmodels.RawChange) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ThreadBuilder) MaybeHeads() []string {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ThreadBuilder) SetMaybeHeads(heads []string) {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ThreadBuilder) SetHeads(heads []string) {
|
|
||||||
//TODO implement me
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewThreadBuilder(keychain *Keychain) *ThreadBuilder {
|
func NewThreadBuilder(keychain *Keychain) *ThreadBuilder {
|
||||||
return &ThreadBuilder{
|
return &ThreadBuilder{
|
||||||
allChanges: make(map[string]*threadChange),
|
allChanges: make(map[string]*threadChange),
|
||||||
@ -92,17 +73,58 @@ func (t *ThreadBuilder) Heads() []string {
|
|||||||
return t.heads
|
return t.heads
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) AddChange(change *threadmodels.RawChange) error {
|
||||||
|
aclChange := new(pb.ACLChange)
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// TODO: think what should we do with such cases, because this can be used by attacker to break our tree
|
||||||
|
if err = proto.Unmarshal(change.Payload, aclChange); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshall changes")
|
||||||
|
}
|
||||||
|
var changesData []byte
|
||||||
|
|
||||||
|
// get correct readkey
|
||||||
|
readKey := t.keychain.ReadKeysByHash[aclChange.CurrentReadKeyHash]
|
||||||
|
if aclChange.ChangesData != nil {
|
||||||
|
changesData, err = readKey.Key.Decrypt(aclChange.ChangesData)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to decrypt changes data: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get correct signing key
|
||||||
|
signKey := t.keychain.SigningKeysByIdentity[aclChange.Identity]
|
||||||
|
t.maybeHeads = append(t.maybeHeads, change.Id)
|
||||||
|
|
||||||
|
t.allChanges[change.Id] = &threadChange{
|
||||||
|
ACLChange: aclChange,
|
||||||
|
id: change.Id,
|
||||||
|
readKey: readKey,
|
||||||
|
signKey: signKey,
|
||||||
|
changesDataDecrypted: changesData,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) MaybeHeads() []string {
|
||||||
|
return t.maybeHeads
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) SetMaybeHeads(heads []string) {
|
||||||
|
// we should copy here instead of just setting the value
|
||||||
|
t.maybeHeads = heads
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) SetHeads(heads []string) {
|
||||||
|
// we should copy here instead of just setting the value
|
||||||
|
t.heads = heads
|
||||||
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*threadmodels.RawChange, error) {
|
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*threadmodels.RawChange, error) {
|
||||||
rec := t.allChanges[recordID]
|
rec := t.allChanges[recordID]
|
||||||
|
|
||||||
var encrypted []byte
|
if rec.changesDataDecrypted != nil {
|
||||||
if rec.changesData != nil {
|
encrypted, err := rec.readKey.Key.Encrypt(rec.changesDataDecrypted)
|
||||||
m, err := proto.Marshal(rec.changesData)
|
|
||||||
if err != nil {
|
|
||||||
panic("should be able to marshal data!")
|
|
||||||
}
|
|
||||||
|
|
||||||
encrypted, err = rec.readKey.Key.Encrypt(m)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("should be able to encrypt data with read key!")
|
panic("should be able to encrypt data with read key!")
|
||||||
}
|
}
|
||||||
@ -162,9 +184,9 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(ch.Changes) > 0 || ch.Snapshot != nil {
|
if len(ch.Changes) > 0 || ch.Snapshot != nil {
|
||||||
newChange.changesData = &pb.PlainTextChangeData{}
|
changesData := &pb.PlainTextChangeData{}
|
||||||
if ch.Snapshot != nil {
|
if ch.Snapshot != nil {
|
||||||
newChange.changesData.Snapshot = t.parseChangeSnapshot(ch.Snapshot)
|
changesData.Snapshot = t.parseChangeSnapshot(ch.Snapshot)
|
||||||
}
|
}
|
||||||
if len(ch.Changes) > 0 {
|
if len(ch.Changes) > 0 {
|
||||||
var changeContents []*pb.PlainTextChangeContent
|
var changeContents []*pb.PlainTextChangeContent
|
||||||
@ -172,8 +194,13 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
|||||||
aclChangeContent := t.parseDocumentChange(ch)
|
aclChangeContent := t.parseDocumentChange(ch)
|
||||||
changeContents = append(changeContents, aclChangeContent)
|
changeContents = append(changeContents, aclChangeContent)
|
||||||
}
|
}
|
||||||
newChange.changesData.Content = changeContents
|
changesData.Content = changeContents
|
||||||
}
|
}
|
||||||
|
m, err := proto.Marshal(changesData)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newChange.changesDataDecrypted = m
|
||||||
}
|
}
|
||||||
aclChange.CurrentReadKeyHash = k.Hash
|
aclChange.CurrentReadKeyHash = k.Hash
|
||||||
newChange.ACLChange = aclChange
|
newChange.ACLChange = aclChange
|
||||||
@ -421,4 +448,5 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) {
|
|||||||
|
|
||||||
func (t *ThreadBuilder) parseHeads(thread *YMLThread) {
|
func (t *ThreadBuilder) parseHeads(thread *YMLThread) {
|
||||||
t.heads = thread.Heads
|
t.heads = thread.Heads
|
||||||
|
t.maybeHeads = thread.MaybeHeads
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,13 +36,13 @@ func (t *ThreadBuilder) Graph() (string, error) {
|
|||||||
style := "solid"
|
style := "solid"
|
||||||
if r.GetAclData() != nil {
|
if r.GetAclData() != nil {
|
||||||
style = "filled"
|
style = "filled"
|
||||||
} else if r.changesData != nil {
|
} else if r.changesDataDecrypted != nil {
|
||||||
style = "dashed"
|
style = "dashed"
|
||||||
}
|
}
|
||||||
|
|
||||||
var chSymbs []string
|
var chSymbs []string
|
||||||
if r.changesData != nil {
|
if r.changesDataDecrypted != nil {
|
||||||
for _, chc := range r.changesData.Content {
|
for _, chc := range r.changesDataDecrypted.Content {
|
||||||
tp := fmt.Sprintf("%T", chc.Value)
|
tp := fmt.Sprintf("%T", chc.Value)
|
||||||
tp = strings.Replace(tp, "ChangeContentValueOf", "", 1)
|
tp = strings.Replace(tp, "ChangeContentValueOf", "", 1)
|
||||||
res := ""
|
res := ""
|
||||||
|
|||||||
@ -99,5 +99,5 @@ graph:
|
|||||||
baseSnapshot: A.1.1
|
baseSnapshot: A.1.1
|
||||||
aclHeads: [B.1.1]
|
aclHeads: [B.1.1]
|
||||||
treeHeads: [B.1.1]
|
treeHeads: [B.1.1]
|
||||||
heads:
|
maybeHeads:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
|
|||||||
@ -101,6 +101,6 @@ graph:
|
|||||||
baseSnapshot: A.1.1
|
baseSnapshot: A.1.1
|
||||||
aclHeads: [A.1.2]
|
aclHeads: [A.1.2]
|
||||||
treeHeads: [A.1.2]
|
treeHeads: [A.1.2]
|
||||||
heads:
|
maybeHeads:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
- "B.1.2"
|
- "B.1.2"
|
||||||
|
|||||||
@ -101,6 +101,6 @@ graph:
|
|||||||
aclSnapshot: A.1.1
|
aclSnapshot: A.1.1
|
||||||
aclHeads: [A.1.3]
|
aclHeads: [A.1.3]
|
||||||
treeHeads: [A.1.3]
|
treeHeads: [A.1.3]
|
||||||
heads:
|
maybeHeads:
|
||||||
- "A.1.4"
|
- "A.1.4"
|
||||||
- "B.1.2"
|
- "B.1.2"
|
||||||
|
|||||||
@ -124,7 +124,7 @@ graph:
|
|||||||
baseSnapshot: A.1.2
|
baseSnapshot: A.1.2
|
||||||
aclHeads: [A.1.2]
|
aclHeads: [A.1.2]
|
||||||
treeHeads: [A.1.2]
|
treeHeads: [A.1.2]
|
||||||
heads:
|
maybeHeads:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
- "B.1.2"
|
- "B.1.2"
|
||||||
|
|
||||||
|
|||||||
@ -94,5 +94,6 @@ type YMLThread struct {
|
|||||||
TreeHeads []string `yaml:"treeHeads"`
|
TreeHeads []string `yaml:"treeHeads"`
|
||||||
} `yaml:"graph"`
|
} `yaml:"graph"`
|
||||||
|
|
||||||
Heads []string `yaml:"heads"`
|
Heads []string `yaml:"heads"`
|
||||||
|
MaybeHeads []string `yaml:"maybeHeads"`
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user