WIP root change refactoring

This commit is contained in:
mcrakhman 2022-09-25 13:50:35 +02:00 committed by Mikhail Iudin
parent 41709d7dd3
commit d41045aa63
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
36 changed files with 5094 additions and 4442 deletions

View File

@ -12,26 +12,25 @@ endif
export PATH=$(GOPATH)/bin:$(shell echo $$PATH) export PATH=$(GOPATH)/bin:$(shell echo $$PATH)
# TODO: folders were changed, so we should update Makefile and protos generation
proto: proto:
@echo 'Generating protobuf packages (Go)...' @echo 'Generating protobuf packages (Go)...'
# Uncomment if needed # Uncomment if needed
@$(eval ROOT_PKG := pkg) @$(eval ROOT_PKG := pkg)
@$(eval GOGO_START := GOGO_NO_UNDERSCORE=1 GOGO_EXPORT_ONEOF_INTERFACE=1) @$(eval GOGO_START := GOGO_NO_UNDERSCORE=1 GOGO_EXPORT_ONEOF_INTERFACE=1)
@$(eval P_ACL_CHANGES_PATH_PB := $(ROOT_PKG)/acl/aclchanges/aclpb) @$(eval P_ACL_RECORDS_PATH_PB := $(ROOT_PKG)/acl/aclrecordproto)
@$(eval P_TREE_CHANGES_PATH_PB := $(ROOT_PKG)/acl/treechangeproto)
@$(eval P_SYNC_CHANGES_PATH_PB := syncproto) @$(eval P_SYNC_CHANGES_PATH_PB := syncproto)
@$(eval P_TEST_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges) @$(eval P_TEST_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges)
@$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types) @$(eval P_ACL_RECORDS := M$(P_ACL_RECORDS_PATH_PB)/protos/aclrecord.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_RECORDS_PATH_PB))
@$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types) @$(eval P_TREE_CHANGES := M$(P_TREE_CHANGES_PATH_PB)/protos/treechange.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_TREE_CHANGES_PATH_PB))
@$(eval P_ACL_CHANGES := M$(P_ACL_CHANGES_PATH_PB)/protos/aclchanges.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_CHANGES_PATH_PB))
# use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT)) $(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_RECORDS_PATH_PB)/protos/*.proto
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto $(GOGO_START) protoc --gogofaster_out=:. $(P_TREE_CHANGES_PATH_PB)/protos/*.proto
$(GOGO_START) protoc --gogofaster_out=:. $(P_TEST_CHANGES_PATH_PB)/proto/*.proto $(GOGO_START) protoc --gogofaster_out=:. $(P_TEST_CHANGES_PATH_PB)/proto/*.proto
$(eval PKGMAP := $$(P_ACL_CHANGES)) $(eval PKGMAP := $$(P_TREE_CHANGES))
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/proto/*.proto
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. common/commonspace/spacesyncproto/protos/*.proto $(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. common/commonspace/spacesyncproto/protos/*.proto
build: build:
@$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app)) @$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app))
go build -v -o bin/anytype-node -ldflags "$(FLAGS)" cmd/node/node.go go build -v -o bin/anytype-node -ldflags "$(FLAGS)" cmd/node/node.go

View File

@ -2,7 +2,7 @@ syntax = "proto3";
package anySpace; package anySpace;
option go_package = "common/commonspace/spacesyncproto"; option go_package = "common/commonspace/spacesyncproto";
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto"; import "pkg/acl/treechangeproto/protos/treechange.proto";
enum ErrCodes { enum ErrCodes {
Unexpected = 0; Unexpected = 0;
@ -49,7 +49,7 @@ message HeadSyncResponse {
message ObjectSyncMessage { message ObjectSyncMessage {
string spaceId = 1; string spaceId = 1;
ObjectSyncContentValue content = 2; ObjectSyncContentValue content = 2;
acl.TreeHeader treeHeader = 3; treechange.RootChange treeHeader = 3;
string treeId = 4; string treeId = 4;
string trackingId = 5; string trackingId = 5;
// //
@ -70,24 +70,32 @@ message ObjectSyncContentValue {
// ObjectHeadUpdate is a message sent on document head update // ObjectHeadUpdate is a message sent on document head update
message ObjectHeadUpdate { message ObjectHeadUpdate {
repeated string heads = 1; repeated string heads = 1;
repeated acl.RawTreeChangeWithId changes = 2; repeated treechange.RawTreeChangeWithId changes = 2;
repeated string snapshotPath = 3; repeated string snapshotPath = 3;
} }
// ObjectHeadUpdate is a message sent when document needs full sync // ObjectHeadUpdate is a message sent when document needs full sync
message ObjectFullSyncRequest { message ObjectFullSyncRequest {
repeated string heads = 1; repeated string heads = 1;
repeated acl.RawTreeChangeWithId changes = 2; repeated treechange.RawTreeChangeWithId changes = 2;
repeated string snapshotPath = 3; repeated string snapshotPath = 3;
} }
// ObjectFullSyncResponse is a message sent as a response for a specific full sync // ObjectFullSyncResponse is a message sent as a response for a specific full sync
message ObjectFullSyncResponse { message ObjectFullSyncResponse {
repeated string heads = 1; repeated string heads = 1;
repeated acl.RawTreeChangeWithId changes = 2; repeated treechange.RawTreeChangeWithId changes = 2;
repeated string snapshotPath = 3; repeated string snapshotPath = 3;
} }
message ObjectErrorResponse { message ObjectErrorResponse {
string error = 1; string error = 1;
} }
message SpaceHeader {
bytes identity = 1;
int64 timestamp = 2;
string spaceType = 3;
uint64 replicationKey = 4;
bytes seed = 5;
}

View File

@ -1,6 +1,6 @@
package spacesyncproto package spacesyncproto
import "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" import "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
type SpaceStream = DRPCSpace_StreamStream type SpaceStream = DRPCSpace_StreamStream

View File

@ -5,7 +5,7 @@ package spacesyncproto
import ( import (
fmt "fmt" fmt "fmt"
aclpb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" treechangeproto "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
io "io" io "io"
math "math" math "math"
@ -322,7 +322,7 @@ func (m *HeadSyncResponse) GetResults() []*HeadSyncResult {
type ObjectSyncMessage struct { type ObjectSyncMessage struct {
SpaceId string `protobuf:"bytes,1,opt,name=spaceId,proto3" json:"spaceId,omitempty"` SpaceId string `protobuf:"bytes,1,opt,name=spaceId,proto3" json:"spaceId,omitempty"`
Content *ObjectSyncContentValue `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` Content *ObjectSyncContentValue `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"`
TreeHeader *aclpb.TreeHeader `protobuf:"bytes,3,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"` TreeHeader *treechangeproto.RootChange `protobuf:"bytes,3,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"`
TreeId string `protobuf:"bytes,4,opt,name=treeId,proto3" json:"treeId,omitempty"` TreeId string `protobuf:"bytes,4,opt,name=treeId,proto3" json:"treeId,omitempty"`
TrackingId string `protobuf:"bytes,5,opt,name=trackingId,proto3" json:"trackingId,omitempty"` TrackingId string `protobuf:"bytes,5,opt,name=trackingId,proto3" json:"trackingId,omitempty"`
} }
@ -374,7 +374,7 @@ func (m *ObjectSyncMessage) GetContent() *ObjectSyncContentValue {
return nil return nil
} }
func (m *ObjectSyncMessage) GetTreeHeader() *aclpb.TreeHeader { func (m *ObjectSyncMessage) GetTreeHeader() *treechangeproto.RootChange {
if m != nil { if m != nil {
return m.TreeHeader return m.TreeHeader
} }
@ -510,7 +510,7 @@ func (*ObjectSyncContentValue) XXX_OneofWrappers() []interface{} {
// ObjectHeadUpdate is a message sent on document head update // ObjectHeadUpdate is a message sent on document head update
type ObjectHeadUpdate struct { type ObjectHeadUpdate struct {
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"` Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
Changes []*aclpb.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"` Changes []*treechangeproto.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"` SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
} }
@ -554,7 +554,7 @@ func (m *ObjectHeadUpdate) GetHeads() []string {
return nil return nil
} }
func (m *ObjectHeadUpdate) GetChanges() []*aclpb.RawTreeChangeWithId { func (m *ObjectHeadUpdate) GetChanges() []*treechangeproto.RawTreeChangeWithId {
if m != nil { if m != nil {
return m.Changes return m.Changes
} }
@ -571,7 +571,7 @@ func (m *ObjectHeadUpdate) GetSnapshotPath() []string {
// ObjectHeadUpdate is a message sent when document needs full sync // ObjectHeadUpdate is a message sent when document needs full sync
type ObjectFullSyncRequest struct { type ObjectFullSyncRequest struct {
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"` Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
Changes []*aclpb.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"` Changes []*treechangeproto.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"` SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
} }
@ -615,7 +615,7 @@ func (m *ObjectFullSyncRequest) GetHeads() []string {
return nil return nil
} }
func (m *ObjectFullSyncRequest) GetChanges() []*aclpb.RawTreeChangeWithId { func (m *ObjectFullSyncRequest) GetChanges() []*treechangeproto.RawTreeChangeWithId {
if m != nil { if m != nil {
return m.Changes return m.Changes
} }
@ -632,7 +632,7 @@ func (m *ObjectFullSyncRequest) GetSnapshotPath() []string {
// ObjectFullSyncResponse is a message sent as a response for a specific full sync // ObjectFullSyncResponse is a message sent as a response for a specific full sync
type ObjectFullSyncResponse struct { type ObjectFullSyncResponse struct {
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"` Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
Changes []*aclpb.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"` Changes []*treechangeproto.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"` SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
} }
@ -676,7 +676,7 @@ func (m *ObjectFullSyncResponse) GetHeads() []string {
return nil return nil
} }
func (m *ObjectFullSyncResponse) GetChanges() []*aclpb.RawTreeChangeWithId { func (m *ObjectFullSyncResponse) GetChanges() []*treechangeproto.RawTreeChangeWithId {
if m != nil { if m != nil {
return m.Changes return m.Changes
} }
@ -734,6 +734,82 @@ func (m *ObjectErrorResponse) GetError() string {
return "" return ""
} }
type SpaceHeader struct {
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
SpaceType string `protobuf:"bytes,3,opt,name=spaceType,proto3" json:"spaceType,omitempty"`
ReplicationKey uint64 `protobuf:"varint,4,opt,name=replicationKey,proto3" json:"replicationKey,omitempty"`
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
}
func (m *SpaceHeader) Reset() { *m = SpaceHeader{} }
func (m *SpaceHeader) String() string { return proto.CompactTextString(m) }
func (*SpaceHeader) ProtoMessage() {}
func (*SpaceHeader) Descriptor() ([]byte, []int) {
return fileDescriptor_5855f4ef9cf24cdb, []int{11}
}
func (m *SpaceHeader) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *SpaceHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_SpaceHeader.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *SpaceHeader) XXX_Merge(src proto.Message) {
xxx_messageInfo_SpaceHeader.Merge(m, src)
}
func (m *SpaceHeader) XXX_Size() int {
return m.Size()
}
func (m *SpaceHeader) XXX_DiscardUnknown() {
xxx_messageInfo_SpaceHeader.DiscardUnknown(m)
}
var xxx_messageInfo_SpaceHeader proto.InternalMessageInfo
func (m *SpaceHeader) GetIdentity() []byte {
if m != nil {
return m.Identity
}
return nil
}
func (m *SpaceHeader) GetTimestamp() int64 {
if m != nil {
return m.Timestamp
}
return 0
}
func (m *SpaceHeader) GetSpaceType() string {
if m != nil {
return m.SpaceType
}
return ""
}
func (m *SpaceHeader) GetReplicationKey() uint64 {
if m != nil {
return m.ReplicationKey
}
return 0
}
func (m *SpaceHeader) GetSeed() []byte {
if m != nil {
return m.Seed
}
return nil
}
func init() { func init() {
proto.RegisterEnum("anySpace.ErrCodes", ErrCodes_name, ErrCodes_value) proto.RegisterEnum("anySpace.ErrCodes", ErrCodes_name, ErrCodes_value)
proto.RegisterType((*HeadSyncRange)(nil), "anySpace.HeadSyncRange") proto.RegisterType((*HeadSyncRange)(nil), "anySpace.HeadSyncRange")
@ -747,6 +823,7 @@ func init() {
proto.RegisterType((*ObjectFullSyncRequest)(nil), "anySpace.ObjectFullSyncRequest") proto.RegisterType((*ObjectFullSyncRequest)(nil), "anySpace.ObjectFullSyncRequest")
proto.RegisterType((*ObjectFullSyncResponse)(nil), "anySpace.ObjectFullSyncResponse") proto.RegisterType((*ObjectFullSyncResponse)(nil), "anySpace.ObjectFullSyncResponse")
proto.RegisterType((*ObjectErrorResponse)(nil), "anySpace.ObjectErrorResponse") proto.RegisterType((*ObjectErrorResponse)(nil), "anySpace.ObjectErrorResponse")
proto.RegisterType((*SpaceHeader)(nil), "anySpace.SpaceHeader")
} }
func init() { func init() {
@ -754,52 +831,57 @@ func init() {
} }
var fileDescriptor_5855f4ef9cf24cdb = []byte{ var fileDescriptor_5855f4ef9cf24cdb = []byte{
// 712 bytes of a gzipped FileDescriptorProto // 797 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4b, 0x6f, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xcd, 0x8e, 0xe3, 0x44,
0x10, 0xf6, 0xa6, 0x79, 0x75, 0xd2, 0x47, 0x58, 0x68, 0x31, 0x41, 0xa4, 0xc1, 0xa7, 0x08, 0xa4, 0x10, 0xb6, 0x33, 0x99, 0x49, 0x52, 0x99, 0x99, 0x0d, 0x0d, 0x3b, 0x98, 0x00, 0xd9, 0xe0, 0x03,
0xa4, 0x0a, 0x17, 0x44, 0xb9, 0xd0, 0x2a, 0x55, 0x22, 0xc4, 0x43, 0x5b, 0x0a, 0x12, 0xe2, 0xb2, 0x8a, 0x40, 0x4a, 0x50, 0x90, 0x10, 0x30, 0x5c, 0xd8, 0x51, 0x46, 0x89, 0x56, 0xfc, 0xa8, 0x67,
0xb5, 0xb7, 0x49, 0xa8, 0x63, 0x1b, 0xef, 0x86, 0xd2, 0x1b, 0x17, 0x38, 0x23, 0xfe, 0x12, 0x17, 0x17, 0x24, 0xc4, 0xa5, 0xd7, 0xae, 0x4d, 0xcc, 0xda, 0x6e, 0xe3, 0xee, 0xb0, 0xe4, 0x09, 0xb8,
0x8e, 0x15, 0x27, 0x8e, 0xa8, 0xfd, 0x23, 0x68, 0xc7, 0x76, 0x5e, 0xb8, 0xe5, 0xd6, 0x43, 0xec, 0x80, 0x84, 0x78, 0x03, 0x9e, 0x85, 0x0b, 0xc7, 0x3d, 0xc2, 0x0d, 0xcd, 0xbc, 0x08, 0xea, 0xb2,
0x9d, 0xd9, 0xf9, 0xbe, 0xfd, 0xf6, 0x9b, 0xf5, 0x06, 0x1e, 0xda, 0xfe, 0x70, 0xe8, 0x7b, 0xcd, 0x1d, 0x3b, 0xc1, 0xbb, 0x1c, 0xf7, 0x12, 0x77, 0x7d, 0x5d, 0xf5, 0xf5, 0xd7, 0x55, 0xd5, 0x15,
0xe8, 0x25, 0x03, 0x6e, 0x8b, 0x26, 0x3e, 0xe5, 0x89, 0x67, 0x07, 0xa1, 0xaf, 0xfc, 0x26, 0x3e, 0xf8, 0xd0, 0x93, 0x51, 0x24, 0xe3, 0x49, 0xf6, 0x51, 0x89, 0xf0, 0x70, 0x42, 0xbf, 0x6a, 0x13,
0xe5, 0x24, 0xdb, 0xc0, 0x04, 0x2d, 0x72, 0xef, 0x64, 0x4f, 0xe7, 0x2a, 0x9b, 0xc1, 0x51, 0xaf, 0x7b, 0x49, 0x2a, 0xb5, 0x9c, 0xd0, 0xaf, 0x2a, 0xd1, 0x31, 0x01, 0xac, 0x2d, 0xe2, 0xcd, 0x95,
0xc9, 0x6d, 0x57, 0xff, 0xec, 0x3e, 0xf7, 0x7a, 0x42, 0xea, 0x61, 0x70, 0x90, 0x40, 0x27, 0xf9, 0xc1, 0xfa, 0x93, 0xe4, 0xf1, 0x72, 0x22, 0xbc, 0x70, 0xa2, 0x53, 0x44, 0x6f, 0x25, 0xe2, 0x25,
0x08, 0x6b, 0x75, 0x61, 0xb9, 0x23, 0xb8, 0xb3, 0x77, 0xe2, 0xd9, 0x4c, 0xe7, 0x29, 0x85, 0xec, 0xee, 0x44, 0x96, 0x70, 0x16, 0xea, 0x2e, 0xe0, 0x64, 0x8e, 0xc2, 0xbf, 0xda, 0xc4, 0x1e, 0x37,
0x61, 0xe8, 0x0f, 0x4d, 0x52, 0x23, 0xf5, 0x2c, 0xc3, 0x31, 0x5d, 0x81, 0x8c, 0xf2, 0xcd, 0x0c, 0x30, 0x63, 0xd0, 0x7c, 0x94, 0xca, 0xc8, 0xb1, 0x87, 0xf6, 0xa8, 0xc9, 0x69, 0xcd, 0x4e, 0xa1,
0x66, 0x32, 0xca, 0xa7, 0x37, 0x20, 0xe7, 0x0e, 0x86, 0x03, 0x65, 0x2e, 0xd4, 0x48, 0x7d, 0x99, 0xa1, 0xa5, 0xd3, 0x20, 0xa4, 0xa1, 0x25, 0x7b, 0x05, 0x0e, 0xc3, 0x20, 0x0a, 0xb4, 0x73, 0x30,
0x45, 0x81, 0x75, 0x0c, 0x2b, 0x63, 0x2a, 0x21, 0x47, 0xae, 0xd2, 0x5c, 0x7d, 0x2e, 0xfb, 0xc8, 0xb4, 0x47, 0x27, 0x3c, 0x33, 0xdc, 0x27, 0x70, 0xba, 0xa5, 0x42, 0xb5, 0x0e, 0xb5, 0xe1, 0x5a,
0xb5, 0xc4, 0x70, 0x4c, 0xb7, 0xa0, 0x28, 0x5c, 0x31, 0x14, 0x9e, 0x92, 0x66, 0xa6, 0xb6, 0x50, 0x09, 0xb5, 0x22, 0xae, 0x63, 0x4e, 0x6b, 0x76, 0x0e, 0x6d, 0x0c, 0x31, 0xc2, 0x58, 0x2b, 0xa7,
0x2f, 0xb5, 0x36, 0x1a, 0x89, 0xfe, 0xc6, 0x2c, 0xbe, 0x1d, 0xd5, 0xb1, 0x31, 0x40, 0x2f, 0x6c, 0x31, 0x3c, 0x18, 0x75, 0xa7, 0x77, 0xc6, 0x85, 0xfc, 0xf1, 0x6e, 0xfc, 0x2c, 0xf3, 0xe3, 0xdb,
0xfb, 0x23, 0x6f, 0xbc, 0x30, 0x06, 0xd6, 0x16, 0xac, 0xa5, 0x02, 0xb5, 0xee, 0x81, 0x83, 0xab, 0x00, 0x73, 0xb0, 0x27, 0xd7, 0xf1, 0xf6, 0x60, 0x32, 0xdc, 0x73, 0xb8, 0x5d, 0x1b, 0x68, 0x74,
0x2f, 0xb2, 0xcc, 0xc0, 0x41, 0x3d, 0x82, 0x3b, 0xb8, 0x93, 0x45, 0x86, 0x63, 0xeb, 0x1d, 0xac, 0x07, 0x3e, 0x9d, 0xde, 0xe1, 0x8d, 0xc0, 0x27, 0x3d, 0x28, 0x7c, 0xba, 0x49, 0x87, 0xd3, 0xda,
0x4e, 0xc0, 0x1f, 0x46, 0x42, 0x2a, 0x6a, 0x42, 0x01, 0x2d, 0xee, 0x26, 0xd8, 0x24, 0xa4, 0x4d, 0xfd, 0x16, 0x6e, 0x95, 0xc1, 0xdf, 0xaf, 0x51, 0x69, 0xe6, 0x40, 0x8b, 0x32, 0xbc, 0x28, 0x62,
0xc8, 0x87, 0xe8, 0x5e, 0x2c, 0xfd, 0x66, 0x8a, 0x74, 0x3d, 0xcf, 0xe2, 0x32, 0x6b, 0x17, 0xca, 0x0b, 0x93, 0x4d, 0xe0, 0x28, 0x35, 0x59, 0x2a, 0xa4, 0xbf, 0x5a, 0x23, 0xdd, 0xec, 0xf3, 0xdc,
0x53, 0xd2, 0x02, 0xdf, 0x93, 0x82, 0xb6, 0xa0, 0x10, 0xa2, 0x4c, 0x69, 0x12, 0x64, 0x31, 0x2f, 0xcd, 0xbd, 0x84, 0x5e, 0x45, 0x5a, 0x22, 0x63, 0x85, 0x6c, 0x0a, 0xad, 0x94, 0x64, 0x2a, 0xc7,
0x32, 0x80, 0x25, 0x85, 0xd6, 0x2f, 0x02, 0xd7, 0x5e, 0x1c, 0xbc, 0x17, 0xb6, 0xd2, 0xb3, 0xcf, 0x26, 0x16, 0xe7, 0x59, 0x09, 0xe0, 0x85, 0xa3, 0xfb, 0xb7, 0x0d, 0x2f, 0x7d, 0xf1, 0xf0, 0x3b,
0x84, 0x94, 0xbc, 0x27, 0x2e, 0x11, 0xfa, 0x08, 0x0a, 0xb6, 0xef, 0x29, 0xe1, 0x29, 0xdc, 0x6c, 0xf4, 0xb4, 0xd9, 0xfd, 0x0c, 0x95, 0x12, 0x4b, 0x7c, 0x8e, 0xd0, 0x8f, 0xa1, 0xe5, 0xc9, 0x58,
0xa9, 0x55, 0x9b, 0xac, 0x31, 0xe1, 0xd9, 0x89, 0x4a, 0x5e, 0x73, 0x77, 0x24, 0x58, 0x02, 0xa0, 0x63, 0xac, 0xe9, 0xb2, 0xdd, 0xe9, 0xb0, 0x3c, 0xa3, 0xe4, 0xb9, 0xc8, 0x5c, 0xbe, 0x12, 0xe1,
0x4d, 0x00, 0x15, 0x0a, 0xa1, 0xa5, 0x88, 0x10, 0x9d, 0x2e, 0xb5, 0x56, 0x1b, 0xdc, 0x76, 0x1b, 0x1a, 0x79, 0x11, 0xc0, 0x3e, 0x00, 0x30, 0x6d, 0x62, 0xa4, 0x60, 0x4a, 0x99, 0xee, 0x4e, 0xcf,
0xaf, 0xc6, 0x69, 0x36, 0x55, 0x42, 0xd7, 0x21, 0xaf, 0xa3, 0xae, 0x63, 0x66, 0x51, 0x45, 0x1c, 0xc6, 0x95, 0xce, 0xe1, 0x52, 0xea, 0x0b, 0x5a, 0xf2, 0x8a, 0x27, 0x3b, 0x83, 0x23, 0x63, 0x2d,
0xd1, 0xaa, 0x26, 0xe2, 0xf6, 0xd1, 0xc0, 0xeb, 0x75, 0x1d, 0x33, 0x87, 0x73, 0x53, 0x19, 0xeb, 0x7c, 0xa7, 0x49, 0x62, 0x72, 0x8b, 0x0d, 0x0c, 0x9f, 0xf0, 0x1e, 0x07, 0xf1, 0x72, 0xe1, 0x3b,
0x47, 0x06, 0xd6, 0xd3, 0xc5, 0xd0, 0xc7, 0x00, 0xba, 0x3b, 0xfb, 0x81, 0xc3, 0x95, 0xc0, 0xcd, 0x87, 0xb4, 0x57, 0x41, 0xdc, 0x3f, 0x1a, 0x70, 0x56, 0xaf, 0x89, 0x7d, 0x02, 0x60, 0x8a, 0xf4,
0x95, 0x5a, 0x95, 0xf9, 0x2d, 0x74, 0xc6, 0x15, 0x1d, 0x83, 0x4d, 0xd5, 0xd3, 0xa7, 0xb0, 0x7a, 0x20, 0xf1, 0x85, 0x46, 0xba, 0x63, 0x77, 0xda, 0xdf, 0xbf, 0xc9, 0x7c, 0xeb, 0x31, 0xb7, 0x78,
0x38, 0x72, 0xdd, 0xa9, 0x9e, 0xc6, 0x2e, 0x6c, 0xcc, 0x53, 0xec, 0xce, 0x96, 0x75, 0x0c, 0x36, 0xc5, 0x9f, 0xdd, 0x83, 0x5b, 0x8f, 0xd6, 0x61, 0x58, 0x29, 0x6d, 0x9e, 0x8c, 0x3b, 0xfb, 0x14,
0x8f, 0xa4, 0xcf, 0xa1, 0x3c, 0x49, 0x45, 0x2d, 0x8c, 0x4d, 0xa9, 0x5d, 0xcc, 0x16, 0xd5, 0x75, 0x97, 0xbb, 0x6e, 0x73, 0x8b, 0xef, 0x47, 0xb2, 0xcf, 0xa1, 0x57, 0x42, 0x59, 0x25, 0xf3, 0xdc,
0x0c, 0xf6, 0x0f, 0x96, 0xb6, 0x61, 0x59, 0x84, 0xa1, 0x1f, 0x8e, 0xc9, 0xb2, 0x48, 0x76, 0x67, 0x0c, 0x9f, 0xcd, 0x96, 0xf9, 0xcd, 0x2d, 0xfe, 0x9f, 0x58, 0x36, 0x83, 0x13, 0x4c, 0x53, 0x99,
0x9e, 0xac, 0x3d, 0x5d, 0xd4, 0x31, 0xd8, 0x2c, 0x6a, 0xbb, 0x00, 0xb9, 0x8f, 0xda, 0x2a, 0xeb, 0x6e, 0xc9, 0x9a, 0x44, 0xf6, 0xe6, 0x3e, 0xd9, 0xac, 0xea, 0x34, 0xb7, 0xf8, 0x6e, 0xd4, 0xdd,
0x33, 0x81, 0xf2, 0xbc, 0x1f, 0xfa, 0x43, 0xd1, 0x7e, 0x44, 0x27, 0x6c, 0x91, 0x45, 0x81, 0x3e, 0x16, 0x1c, 0xfe, 0x60, 0x52, 0xe5, 0xfe, 0x64, 0x43, 0x6f, 0x3f, 0x1f, 0xe6, 0xbd, 0x98, 0x7c,
0x79, 0xf1, 0xd7, 0x1f, 0x9f, 0x5f, 0x13, 0xdb, 0xca, 0xf8, 0xb1, 0xee, 0xec, 0x0e, 0x4e, 0xbd, 0x64, 0x8d, 0xd6, 0xe1, 0x99, 0xc1, 0x3e, 0x82, 0x56, 0x56, 0xc9, 0xf2, 0x05, 0x56, 0xab, 0x2b,
0x19, 0xa8, 0x7e, 0xd7, 0x61, 0x49, 0x21, 0xb5, 0x60, 0x49, 0x7a, 0x3c, 0x90, 0x7d, 0x5f, 0xbd, 0x9e, 0xdc, 0x4f, 0x11, 0xb3, 0x02, 0x7f, 0x1d, 0xe8, 0xd5, 0xc2, 0xe7, 0x85, 0x3f, 0x73, 0xe1,
0xe4, 0xaa, 0x6f, 0x2e, 0x20, 0xe1, 0x4c, 0xce, 0xfa, 0x42, 0x60, 0x2d, 0xd5, 0xcf, 0x2b, 0xd6, 0x58, 0xc5, 0x22, 0x51, 0x2b, 0xa9, 0xbf, 0x14, 0x7a, 0xe5, 0x1c, 0x10, 0xef, 0x0e, 0xe6, 0xfe,
0xf1, 0x95, 0x24, 0x07, 0x6a, 0xbe, 0x13, 0x57, 0x2c, 0xe4, 0x3e, 0x5c, 0x4f, 0x69, 0xa2, 0x16, 0x6c, 0xc3, 0xed, 0xda, 0xb4, 0xbe, 0x18, 0x39, 0xbf, 0xd8, 0x45, 0x7b, 0xed, 0xd7, 0xe5, 0xc5,
0x81, 0x4d, 0x8c, 0xbf, 0xd6, 0x28, 0xb8, 0x57, 0x81, 0x62, 0x3b, 0x0c, 0x77, 0x7c, 0x47, 0x48, 0xe8, 0x79, 0x17, 0x5e, 0xae, 0xa9, 0xac, 0xd1, 0x42, 0x95, 0xcd, 0x5f, 0x72, 0x66, 0xb8, 0xbf,
0xba, 0x02, 0xb0, 0xef, 0x89, 0x4f, 0x81, 0xb0, 0x95, 0x70, 0xca, 0x46, 0xeb, 0x3b, 0x81, 0x1c, 0xdb, 0xd0, 0xa5, 0x6e, 0xc8, 0xdf, 0x58, 0x1f, 0xda, 0x81, 0x8f, 0xb1, 0x0e, 0xf4, 0x26, 0x9f,
0x1e, 0x0a, 0xfa, 0x04, 0x8a, 0xc9, 0xe5, 0x40, 0x6f, 0xa5, 0x5d, 0x18, 0x68, 0x78, 0xa5, 0x92, 0xaa, 0x5b, 0x9b, 0xbd, 0x01, 0x1d, 0x1d, 0x44, 0xa8, 0xb4, 0x88, 0x12, 0x6a, 0xf4, 0x03, 0x5e,
0x7a, 0x97, 0x44, 0xcb, 0xef, 0x42, 0x7e, 0x4f, 0x85, 0x82, 0x0f, 0xe9, 0xed, 0xb4, 0xdb, 0x20, 0x02, 0x66, 0x97, 0x86, 0xc3, 0xfd, 0x4d, 0x92, 0x35, 0x6e, 0x87, 0x97, 0x00, 0x7b, 0x1b, 0x4e,
0xbe, 0x55, 0x2a, 0x97, 0x4d, 0xd6, 0xc9, 0x26, 0xd9, 0xde, 0xfa, 0x79, 0x56, 0x25, 0xa7, 0x67, 0x53, 0x4c, 0xc2, 0xc0, 0x13, 0x3a, 0x90, 0xf1, 0x3d, 0xdc, 0x50, 0x3b, 0x36, 0xf9, 0x1e, 0x6a,
0x55, 0xf2, 0xe7, 0xac, 0x4a, 0xbe, 0x9d, 0x57, 0x8d, 0xd3, 0xf3, 0xaa, 0xf1, 0xfb, 0xbc, 0x6a, 0x26, 0xa8, 0x42, 0xcc, 0x5e, 0xf1, 0x31, 0xa7, 0xf5, 0x3b, 0x7d, 0x68, 0xcf, 0xd2, 0xf4, 0x42,
0xbc, 0xbd, 0xfb, 0xdf, 0xff, 0xb0, 0x83, 0x3c, 0xbe, 0x1e, 0xfc, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xa8, 0xd8, 0x29, 0xc0, 0x83, 0x18, 0x7f, 0x4c, 0xd0, 0xd3, 0xe8, 0xf7, 0xac, 0xe9, 0x6f,
0x93, 0x27, 0x56, 0x41, 0xef, 0x06, 0x00, 0x00, 0x36, 0x1c, 0x92, 0x7e, 0xf6, 0x29, 0xb4, 0x8b, 0xe1, 0xc6, 0x5e, 0xab, 0x1b, 0x78, 0xd4, 0x22,
0xfd, 0x7e, 0xed, 0x2c, 0xcc, 0x52, 0x74, 0x09, 0x47, 0x57, 0x3a, 0x45, 0x11, 0xb1, 0xd7, 0xeb,
0xa6, 0x59, 0x3e, 0x15, 0xfb, 0xcf, 0xdb, 0x1c, 0xd9, 0xef, 0xd9, 0x77, 0xcf, 0xff, 0xbc, 0x1e,
0xd8, 0x4f, 0xaf, 0x07, 0xf6, 0x3f, 0xd7, 0x03, 0xfb, 0xd7, 0x9b, 0x81, 0xf5, 0xf4, 0x66, 0x60,
0xfd, 0x75, 0x33, 0xb0, 0xbe, 0x79, 0xeb, 0x7f, 0xff, 0x82, 0x1f, 0x1e, 0xd1, 0xe7, 0xfd, 0x7f,
0x03, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x1f, 0x02, 0x55, 0xae, 0x07, 0x00, 0x00,
} }
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) { func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
@ -1386,6 +1468,60 @@ func (m *ObjectErrorResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *SpaceHeader) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *SpaceHeader) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *SpaceHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Seed) > 0 {
i -= len(m.Seed)
copy(dAtA[i:], m.Seed)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.Seed)))
i--
dAtA[i] = 0x2a
}
if m.ReplicationKey != 0 {
i = encodeVarintSpacesync(dAtA, i, uint64(m.ReplicationKey))
i--
dAtA[i] = 0x20
}
if len(m.SpaceType) > 0 {
i -= len(m.SpaceType)
copy(dAtA[i:], m.SpaceType)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.SpaceType)))
i--
dAtA[i] = 0x1a
}
if m.Timestamp != 0 {
i = encodeVarintSpacesync(dAtA, i, uint64(m.Timestamp))
i--
dAtA[i] = 0x10
}
if len(m.Identity) > 0 {
i -= len(m.Identity)
copy(dAtA[i:], m.Identity)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.Identity)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintSpacesync(dAtA []byte, offset int, v uint64) int { func encodeVarintSpacesync(dAtA []byte, offset int, v uint64) int {
offset -= sovSpacesync(v) offset -= sovSpacesync(v)
base := offset base := offset
@ -1671,6 +1807,33 @@ func (m *ObjectErrorResponse) Size() (n int) {
return n return n
} }
func (m *SpaceHeader) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Identity)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
if m.Timestamp != 0 {
n += 1 + sovSpacesync(uint64(m.Timestamp))
}
l = len(m.SpaceType)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
if m.ReplicationKey != 0 {
n += 1 + sovSpacesync(uint64(m.ReplicationKey))
}
l = len(m.Seed)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
return n
}
func sovSpacesync(x uint64) (n int) { func sovSpacesync(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7 return (math_bits.Len64(x|1) + 6) / 7
} }
@ -2362,7 +2525,7 @@ func (m *ObjectSyncMessage) Unmarshal(dAtA []byte) error {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if m.TreeHeader == nil { if m.TreeHeader == nil {
m.TreeHeader = &aclpb.TreeHeader{} m.TreeHeader = &treechangeproto.RootChange{}
} }
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
@ -2733,7 +2896,7 @@ func (m *ObjectHeadUpdate) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Changes = append(m.Changes, &aclpb.RawTreeChangeWithId{}) m.Changes = append(m.Changes, &treechangeproto.RawTreeChangeWithId{})
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -2881,7 +3044,7 @@ func (m *ObjectFullSyncRequest) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Changes = append(m.Changes, &aclpb.RawTreeChangeWithId{}) m.Changes = append(m.Changes, &treechangeproto.RawTreeChangeWithId{})
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -3029,7 +3192,7 @@ func (m *ObjectFullSyncResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Changes = append(m.Changes, &aclpb.RawTreeChangeWithId{}) m.Changes = append(m.Changes, &treechangeproto.RawTreeChangeWithId{})
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -3169,6 +3332,194 @@ func (m *ObjectErrorResponse) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *SpaceHeader) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: SpaceHeader: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: SpaceHeader: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Identity = append(m.Identity[:0], dAtA[iNdEx:postIndex]...)
if m.Identity == nil {
m.Identity = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
}
m.Timestamp = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Timestamp |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SpaceType", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SpaceType = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ReplicationKey", wireType)
}
m.ReplicationKey = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ReplicationKey |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Seed", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Seed = append(m.Seed[:0], dAtA[iNdEx:postIndex]...)
if m.Seed == nil {
m.Seed = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthSpacesync
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipSpacesync(dAtA []byte) (n int, err error) { func skipSpacesync(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -4,7 +4,7 @@ import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
"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/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
) )

View File

@ -5,7 +5,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
"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/nodeconf" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"time" "time"
) )

View File

@ -4,7 +4,7 @@ import (
"context" "context"
"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/syncservice" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"

6
go.mod
View File

@ -3,6 +3,7 @@ module github.com/anytypeio/go-anytype-infrastructure-experiments
go 1.18 go 1.18
require ( require (
github.com/anytypeio/go-chash v0.0.0-20220629194632-4ad1154fe232
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab
github.com/cespare/xxhash v1.1.0 github.com/cespare/xxhash v1.1.0
github.com/goccy/go-graphviz v0.0.9 github.com/goccy/go-graphviz v0.0.9
@ -16,6 +17,7 @@ require (
github.com/multiformats/go-multihash v0.1.0 github.com/multiformats/go-multihash v0.1.0
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
github.com/zeebo/blake3 v0.2.3 github.com/zeebo/blake3 v0.2.3
github.com/zeebo/errs v1.3.0
go.uber.org/zap v1.21.0 go.uber.org/zap v1.21.0
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@ -24,7 +26,6 @@ require (
require ( require (
github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/anytypeio/go-chash v0.0.0-20220629194632-4ad1154fe232 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
@ -32,7 +33,6 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/fogleman/gg v1.3.0 // indirect github.com/fogleman/gg v1.3.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect
github.com/libp2p/go-buffer-pool v0.0.2 // indirect github.com/libp2p/go-buffer-pool v0.0.2 // indirect
github.com/libp2p/go-openssl v0.0.7 // indirect github.com/libp2p/go-openssl v0.0.7 // indirect
@ -47,13 +47,11 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/zeebo/errs v1.3.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
lukechampine.com/blake3 v1.1.6 // indirect lukechampine.com/blake3 v1.1.6 // indirect

10
go.sum
View File

@ -32,10 +32,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c=
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw=
@ -117,8 +113,6 @@ github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
@ -184,10 +178,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=

View File

@ -1,143 +0,0 @@
syntax = "proto3";
package acl;
option go_package = "pkg/acl/aclchanges/aclpb";
// ACL protos
message RawACLRecord {
bytes payload = 1;
bytes signature = 2;
string id = 3; // this field is only used on user side for convenience, it should be empty when saving to db
}
message ACLContentValue {
oneof value {
ACLUserAdd userAdd = 1;
ACLUserRemove userRemove = 2;
ACLUserPermissionChange userPermissionChange = 3;
ACLUserInvite userInvite = 4;
ACLUserJoin userJoin = 5;
ACLUserConfirm userConfirm = 6;
}
}
message ACLData {
repeated ACLContentValue aclContent = 1;
}
message ACLState {
repeated uint64 readKeyHashes = 1;
repeated ACLUserState userStates = 2;
map<string, ACLUserInvite> invites = 3; // TODO: later
// repeated string unconfirmedUsers = 4; // TODO: later
}
message ACLUserState {
bytes identity = 1;
bytes encryptionKey = 2;
repeated bytes encryptedReadKeys = 3; // all read keys that we know
ACLUserPermissions permissions = 4;
bool isConfirmed = 5;
}
// we already know identity and encryptionKey
message ACLUserAdd {
bytes identity = 1; // public signing key
bytes encryptionKey = 2; // public encryption key
repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
ACLUserPermissions permissions = 4;
}
// TODO: this is not used as of now
message ACLUserConfirm { // not needed for read permissions
bytes identity = 1; // not needed
string userAddId = 2;
}
message ACLUserInvite {
bytes acceptPublicKey = 1;
bytes encryptPublicKey = 2;
repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
ACLUserPermissions permissions = 4;
string inviteId = 5;
}
message ACLUserJoin {
bytes identity = 1;
bytes encryptionKey = 2;
bytes acceptSignature = 3; // sign acceptPublicKey
string userInviteId = 4;
repeated bytes encryptedReadKeys = 5; // the idea is that user should itself reencrypt the keys with the pub key
}
message ACLUserRemove {
bytes identity = 1;
repeated ACLReadKeyReplace readKeyReplaces = 3; // new read key encrypted for all users
}
message ACLReadKeyReplace {
bytes identity = 1;
bytes encryptionKey = 2;
bytes encryptedReadKey = 3;
}
message ACLUserPermissionChange {
bytes identity = 1;
ACLUserPermissions permissions = 2;
}
enum ACLUserPermissions {
Admin = 0;
Writer = 1;
Reader = 2;
Removed = 3;
}
message ACLRecord {
string prevId = 1;
bytes identity = 2;
bytes data = 3;
uint64 currentReadKeyHash = 4;
int64 timestamp = 5;
}
message ACLHeader {
string firstId = 1;
bytes identity = 2; // the identity of the creator
}
// Tree protos
message RawTreeChange {
bytes payload = 1;
bytes signature = 2;
}
message RawTreeChangeWithId {
bytes rawChange = 1;
string id = 2;
}
message TreeChange {
repeated string treeHeadIds = 1;
string aclHeadId = 2;
string snapshotBaseId = 3;
bytes changesData = 4;
uint64 currentReadKeyHash = 5;
int64 timestamp = 6;
bytes identity = 7;
bool isSnapshot = 8;
}
enum TreeHeaderType {
Object = 0;
Space = 1;
}
message TreeHeader {
string firstId = 1;
string aclId = 2;
TreeHeaderType treeHeaderType = 3;
bytes identity = 4;
bytes data = 5; // this should be reserved for the client to add the data it needs
}

View File

@ -1,12 +0,0 @@
package aclchanges
import (
"github.com/gogo/protobuf/proto"
)
type Change interface {
ProtoChange() proto.Marshaler
DecryptedChangeContent() []byte
Signature() []byte
CID() string
}

View File

@ -0,0 +1,102 @@
syntax = "proto3";
package aclrecord;
option go_package = "pkg/acl/aclrecordproto";
message RawACLRecord {
bytes payload = 1;
bytes signature = 2;
}
message RawACLRecordWithId {
bytes payload = 1;
string id = 2;
}
message ACLRecord {
string prevId = 1;
bytes identity = 2;
bytes data = 3;
uint64 currentReadKeyHash = 4;
int64 timestamp = 5;
}
message ACLRoot {
bytes identity = 1;
bytes encryptionKey = 2;
string spaceId = 3;
bytes encryptedReadKey = 4;
string derivationScheme = 5;
}
message ACLContentValue {
oneof value {
ACLUserAdd userAdd = 1;
ACLUserRemove userRemove = 2;
ACLUserPermissionChange userPermissionChange = 3;
ACLUserInvite userInvite = 4;
ACLUserJoin userJoin = 5;
}
}
message ACLData {
repeated ACLContentValue aclContent = 1;
}
message ACLState {
repeated uint64 readKeyHashes = 1;
repeated ACLUserState userStates = 2;
map<string, ACLUserInvite> invites = 3;
}
message ACLUserState {
bytes identity = 1;
bytes encryptionKey = 2;
repeated bytes encryptedReadKeys = 3;
ACLUserPermissions permissions = 4;
bool isConfirmed = 5;
}
message ACLUserAdd {
bytes identity = 1;
bytes encryptionKey = 2;
repeated bytes encryptedReadKeys = 3;
ACLUserPermissions permissions = 4;
}
message ACLUserInvite {
bytes acceptPublicKey = 1;
bytes encryptPublicKey = 2;
repeated bytes encryptedReadKeys = 3;
ACLUserPermissions permissions = 4;
string inviteId = 5;
}
message ACLUserJoin {
bytes identity = 1;
bytes encryptionKey = 2;
bytes acceptSignature = 3;
string inviteId = 4;
repeated bytes encryptedReadKeys = 5;
}
message ACLUserRemove {
bytes identity = 1;
repeated ACLReadKeyReplace readKeyReplaces = 3;
}
message ACLReadKeyReplace {
bytes identity = 1;
bytes encryptionKey = 2;
bytes encryptedReadKey = 3;
}
message ACLUserPermissionChange {
bytes identity = 1;
ACLUserPermissions permissions = 2;
}
enum ACLUserPermissions {
Admin = 0;
Writer = 1;
Reader = 2;
}

View File

@ -5,7 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
@ -30,14 +30,14 @@ var ErrInvalidSignature = errors.New("signature is invalid")
type UserPermissionPair struct { type UserPermissionPair struct {
Identity string Identity string
Permission aclpb.ACLUserPermissions Permission aclrecordproto.ACLUserPermissions
} }
type ACLState struct { type ACLState struct {
currentReadKeyHash uint64 currentReadKeyHash uint64
userReadKeys map[uint64]*symmetric.Key userReadKeys map[uint64]*symmetric.Key
userStates map[string]*aclpb.ACLUserState userStates map[string]*aclrecordproto.ACLUserState
userInvites map[string]*aclpb.ACLUserInvite userInvites map[string]*aclrecordproto.ACLUserInvite
signingPubKeyDecoder keys.Decoder signingPubKeyDecoder keys.Decoder
encryptionKey encryptionkey.PrivKey encryptionKey encryptionkey.PrivKey
@ -56,8 +56,8 @@ func newACLStateWithIdentity(
identity: identity, identity: identity,
encryptionKey: encryptionKey, encryptionKey: encryptionKey,
userReadKeys: make(map[uint64]*symmetric.Key), userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclpb.ACLUserState), userStates: make(map[string]*aclrecordproto.ACLUserState),
userInvites: make(map[string]*aclpb.ACLUserInvite), userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
signingPubKeyDecoder: decoder, signingPubKeyDecoder: decoder,
permissionsAtRecord: make(map[string][]UserPermissionPair), permissionsAtRecord: make(map[string][]UserPermissionPair),
keychain: common.NewKeychain(), keychain: common.NewKeychain(),
@ -68,8 +68,8 @@ func newACLState(decoder keys.Decoder) *ACLState {
return &ACLState{ return &ACLState{
signingPubKeyDecoder: decoder, signingPubKeyDecoder: decoder,
userReadKeys: make(map[uint64]*symmetric.Key), userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclpb.ACLUserState), userStates: make(map[string]*aclrecordproto.ACLUserState),
userInvites: make(map[string]*aclpb.ACLUserInvite), userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
permissionsAtRecord: make(map[string][]UserPermissionPair), permissionsAtRecord: make(map[string][]UserPermissionPair),
keychain: common.NewKeychain(), keychain: common.NewKeychain(),
} }
@ -106,8 +106,8 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
return UserPermissionPair{}, ErrNoSuchUser return UserPermissionPair{}, ErrNoSuchUser
} }
func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) { func (st *ACLState) applyRecord(record *aclrecordproto.ACLRecord) (err error) {
aclData := &aclpb.ACLData{} aclData := &aclrecordproto.ACLData{}
err = proto.Unmarshal(record.Data, aclData) err = proto.Unmarshal(record.Data, aclData)
if err != nil { if err != nil {
@ -126,11 +126,11 @@ func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) { func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
var ( var (
change = recordWrapper.Content change = recordWrapper.Content
aclData = &aclpb.ACLData{} aclData = &aclrecordproto.ACLData{}
) )
if recordWrapper.Model != nil { if recordWrapper.Model != nil {
aclData = recordWrapper.Model.(*aclpb.ACLData) aclData = recordWrapper.Model.(*aclrecordproto.ACLData)
} else { } else {
err = proto.Unmarshal(change.Data, aclData) err = proto.Unmarshal(change.Data, aclData)
if err != nil { if err != nil {
@ -158,7 +158,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
return nil return nil
} }
func (st *ACLState) applyChangeData(changeData *aclpb.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
@ -176,7 +176,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, iden
return return
} }
if !st.hasPermission(identity, aclpb.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
} }
@ -192,7 +192,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, iden
return nil return nil
} }
func (st *ACLState) applyChangeContent(ch *aclpb.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())
@ -211,7 +211,7 @@ func (st *ACLState) applyChangeContent(ch *aclpb.ACLContentValue) error {
} }
} }
func (st *ACLState) applyUserPermissionChange(ch *aclpb.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 {
@ -222,12 +222,12 @@ func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLUserPermissionChange)
return nil return nil
} }
func (st *ACLState) applyUserInvite(ch *aclpb.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 *aclpb.ACLUserJoin) error { func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
invite, exists := st.userInvites[ch.UserInviteId] invite, exists := st.userInvites[ch.UserInviteId]
if !exists { if !exists {
return fmt.Errorf("no such invite with id %s", ch.UserInviteId) return fmt.Errorf("no such invite with id %s", ch.UserInviteId)
@ -266,7 +266,7 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
} }
// adding user to the list // adding user to the list
userState := &aclpb.ACLUserState{ userState := &aclrecordproto.ACLUserState{
Identity: ch.Identity, Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey, EncryptionKey: ch.EncryptionKey,
EncryptedReadKeys: ch.EncryptedReadKeys, EncryptedReadKeys: ch.EncryptedReadKeys,
@ -277,13 +277,13 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
return nil return nil
} }
func (st *ACLState) applyUserAdd(ch *aclpb.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] = &aclpb.ACLUserState{ st.userStates[chIdentity] = &aclrecordproto.ACLUserState{
Identity: ch.Identity, Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey, EncryptionKey: ch.EncryptionKey,
Permissions: ch.Permissions, Permissions: ch.Permissions,
@ -304,7 +304,7 @@ func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
return nil return nil
} }
func (st *ACLState) applyUserRemove(ch *aclpb.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
@ -338,7 +338,7 @@ func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
return nil return nil
} }
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLUserConfirm) error { func (st *ACLState) applyUserConfirm(ch *aclrecordproto.ACLUserConfirm) error {
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
state, exists := st.userStates[chIdentity] state, exists := st.userStates[chIdentity]
if !exists { if !exists {
@ -365,7 +365,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 aclpb.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
@ -374,17 +374,17 @@ func (st *ACLState) hasPermission(identity []byte, permission aclpb.ACLUserPermi
return state.Permissions == permission return state.Permissions == permission
} }
func (st *ACLState) isUserJoin(data *aclpb.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 *aclpb.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]*aclpb.ACLUserState { func (st *ACLState) GetUserStates() map[string]*aclrecordproto.ACLUserState {
return st.userStates return st.userStates
} }

View File

@ -2,7 +2,7 @@ package list
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"

View File

@ -5,7 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
@ -60,7 +60,7 @@ func BuildACLList(decoder keys.Decoder, storage storage.ListStorage) (ACLList, e
} }
func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStorage) (list ACLList, err error) { func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStorage) (list ACLList, err error) {
header, err := storage.Header() header, err := storage.Root()
if err != nil { if err != nil {
return return
} }

View File

@ -1,7 +1,7 @@
package list package list
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"

View File

@ -1,19 +1,19 @@
package list package list
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
) )
type ACLRecord struct { type ACLRecord struct {
Id string Id string
Content *aclpb.ACLRecord Content *aclrecordproto.ACLRecord
Identity string Identity string
Model interface{} Model interface{}
Sign []byte Sign []byte
} }
func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord { func NewRecord(id string, aclRecord *aclrecordproto.ACLRecord) *ACLRecord {
return &ACLRecord{ return &ACLRecord{
Id: id, Id: id,
Content: aclRecord, Content: aclRecord,
@ -21,17 +21,45 @@ func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
} }
} }
func NewFromRawRecord(rawRec *aclpb.RawACLRecord) (*ACLRecord, error) { func NewFromRawRecord(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) {
aclRec := &aclpb.ACLRecord{} rawRec := &aclrecordproto.RawACLRecord{}
err := proto.Unmarshal(rawRec.Payload, aclRec) err = proto.Unmarshal(rawRecWithId.Payload, rawRec)
if err != nil { if err != nil {
return nil, err return
}
protoAclRec := &aclrecordproto.ACLRecord{}
err = proto.Unmarshal(rawRec.Payload, protoAclRec)
if err != nil {
return
} }
return &ACLRecord{ return &ACLRecord{
Id: rawRec.Id, Id: rawRecWithId.Id,
Content: aclRec, Content: protoAclRec,
Sign: rawRec.Signature, Sign: rawRec.Signature,
Identity: string(aclRec.Identity), Identity: string(protoAclRec.Identity),
}, nil }, nil
} }
func NewFromRawRoot(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) {
rawRec := &aclrecordproto.RawACLRecord{}
err = proto.Unmarshal(rawRecWithId.Payload, rawRec)
if err != nil {
return
}
protoAclRec := &aclrecordproto.ACLRecord{}
err = proto.Unmarshal(rawRec.Payload, protoAclRec)
if err != nil {
return
}
return &ACLRecord{
Id: rawRecWithId.Id,
Content: protoAclRec,
Sign: rawRec.Signature,
Identity: string(protoAclRec.Identity),
}, nil
}

View File

@ -3,14 +3,13 @@ package storage
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"sync" "sync"
) )
type inMemoryACLListStorage struct { type inMemoryACLListStorage struct {
header *aclpb.ACLHeader records []*aclrecordproto.RawACLRecordWithId
records []*aclpb.RawACLRecord
id string id string
sync.RWMutex sync.RWMutex
@ -18,29 +17,27 @@ type inMemoryACLListStorage struct {
func NewInMemoryACLListStorage( func NewInMemoryACLListStorage(
id string, id string,
header *aclpb.ACLHeader, records []*aclrecordproto.RawACLRecordWithId) (ListStorage, error) {
records []*aclpb.RawACLRecord) (ListStorage, error) {
return &inMemoryACLListStorage{ return &inMemoryACLListStorage{
id: id, id: id,
header: header,
records: records, records: records,
RWMutex: sync.RWMutex{}, RWMutex: sync.RWMutex{},
}, nil }, nil
} }
func (i *inMemoryACLListStorage) Header() (*aclpb.ACLHeader, error) { func (i *inMemoryACLListStorage) Root() (*aclrecordproto.RawACLRecordWithId, error) {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.header, nil return i.records[0], nil
} }
func (i *inMemoryACLListStorage) Head() (*aclpb.RawACLRecord, error) { func (i *inMemoryACLListStorage) Head() (*aclrecordproto.RawACLRecordWithId, error) {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.records[len(i.records)-1], nil return i.records[len(i.records)-1], nil
} }
func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error) { func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*aclrecordproto.RawACLRecordWithId, error) {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
for _, rec := range i.records { for _, rec := range i.records {
@ -51,7 +48,7 @@ func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*
return nil, fmt.Errorf("no such record") return nil, fmt.Errorf("no such record")
} }
func (i *inMemoryACLListStorage) AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error { func (i *inMemoryACLListStorage) AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error {
panic("implement me") panic("implement me")
} }
@ -63,26 +60,27 @@ func (i *inMemoryACLListStorage) ID() (string, error) {
type inMemoryTreeStorage struct { type inMemoryTreeStorage struct {
id string id string
header *aclpb.TreeHeader root *treechangeproto.RawTreeChangeWithId
heads []string heads []string
changes map[string]*aclpb.RawTreeChangeWithId changes map[string]*treechangeproto.RawTreeChangeWithId
sync.RWMutex sync.RWMutex
} }
func NewInMemoryTreeStorage( func NewInMemoryTreeStorage(
treeId string, treeId string,
header *aclpb.TreeHeader, root *treechangeproto.RawTreeChangeWithId,
heads []string, heads []string,
changes []*aclpb.RawTreeChangeWithId) (TreeStorage, error) { changes []*treechangeproto.RawTreeChangeWithId) (TreeStorage, error) {
allChanges := make(map[string]*aclpb.RawTreeChangeWithId) allChanges := make(map[string]*treechangeproto.RawTreeChangeWithId)
for _, ch := range changes { for _, ch := range changes {
allChanges[ch.Id] = ch allChanges[ch.Id] = ch
} }
allChanges[treeId] = root
return &inMemoryTreeStorage{ return &inMemoryTreeStorage{
id: treeId, id: treeId,
header: header, root: root,
heads: heads, heads: heads,
changes: allChanges, changes: allChanges,
RWMutex: sync.RWMutex{}, RWMutex: sync.RWMutex{},
@ -95,10 +93,10 @@ func (t *inMemoryTreeStorage) ID() (string, error) {
return t.id, nil return t.id, nil
} }
func (t *inMemoryTreeStorage) Header() (*aclpb.TreeHeader, error) { func (t *inMemoryTreeStorage) Root() (*treechangeproto.RawTreeChangeWithId, error) {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.header, nil return t.root, nil
} }
func (t *inMemoryTreeStorage) Heads() ([]string, error) { func (t *inMemoryTreeStorage) Heads() ([]string, error) {
@ -118,7 +116,7 @@ func (t *inMemoryTreeStorage) SetHeads(heads []string) error {
return nil return nil
} }
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) error { func (t *inMemoryTreeStorage) AddRawChange(change *treechangeproto.RawTreeChangeWithId) error {
t.Lock() t.Lock()
defer t.Unlock() defer t.Unlock()
// TODO: better to do deep copy // TODO: better to do deep copy
@ -126,7 +124,7 @@ func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) er
return nil return nil
} }
func (t *inMemoryTreeStorage) GetRawChange(ctx context.Context, changeId string) (*aclpb.RawTreeChangeWithId, error) { func (t *inMemoryTreeStorage) GetRawChange(ctx context.Context, changeId string) (*treechangeproto.RawTreeChangeWithId, error) {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
if res, exists := t.changes[changeId]; exists { if res, exists := t.changes[changeId]; exists {
@ -163,7 +161,7 @@ func (i *inMemoryStorageProvider) Storage(id string) (Storage, error) {
func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error) { func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error) {
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
res, err := NewInMemoryTreeStorage(payload.TreeId, payload.Header, payload.Heads, payload.Changes) res, err := NewInMemoryTreeStorage(payload.TreeId, payload.RootRawChange, payload.Heads, payload.Changes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -175,7 +173,7 @@ func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePay
func (i *inMemoryStorageProvider) CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error) { func (i *inMemoryStorageProvider) CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error) {
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
res, err := NewInMemoryACLListStorage(payload.ListId, payload.Header, payload.Records) res, err := NewInMemoryACLListStorage(payload.ListId, payload.Records)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,14 +2,14 @@ package storage
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
) )
type ListStorage interface { type ListStorage interface {
Storage Storage
Header() (*aclpb.ACLHeader, error) Root() (*aclrecordproto.RawACLRecordWithId, error)
Head() (*aclpb.RawACLRecord, error) Head() (*aclrecordproto.RawACLRecordWithId, error)
GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error) GetRawRecord(ctx context.Context, id string) (*aclrecordproto.RawACLRecordWithId, error)
AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error
} }

View File

@ -2,27 +2,26 @@ package storage
import ( import (
"errors" "errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
) )
var ErrUnknownTreeId = errors.New("tree does not exist") var ErrUnknownTreeId = errors.New("tree does not exist")
type TreeStorageCreatePayload struct { type TreeStorageCreatePayload struct {
TreeId string TreeId string
Header *aclpb.TreeHeader RootRawChange *treechangeproto.RawTreeChangeWithId
Changes []*aclpb.RawTreeChangeWithId Changes []*treechangeproto.RawTreeChangeWithId
Heads []string Heads []string
} }
type ACLListStorageCreatePayload struct { type ACLListStorageCreatePayload struct {
ListId string ListId string
Header *aclpb.ACLHeader Records []*aclrecordproto.RawACLRecordWithId
Records []*aclpb.RawACLRecord
} }
type Provider interface { type Provider interface {
Storage(id string) (Storage, error) Storage(id string) (Storage, error)
AddStorage(id string, st Storage) error
CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error) CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error)
CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error) CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error)
} }

View File

@ -2,17 +2,17 @@ package storage
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
) )
type TreeStorage interface { type TreeStorage interface {
Storage Storage
Header() (*aclpb.TreeHeader, error) Root() (*treechangeproto.RawTreeChangeWithId, error)
Heads() ([]string, error) Heads() ([]string, error)
SetHeads(heads []string) error SetHeads(heads []string) error
AddRawChange(change *aclpb.RawTreeChangeWithId) error AddRawChange(change *treechangeproto.RawTreeChangeWithId) error
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawTreeChangeWithId, error) GetRawChange(ctx context.Context, id string) (*treechangeproto.RawTreeChangeWithId, error)
} }
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error) type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)

View File

@ -2,11 +2,7 @@ package tree
import ( import (
"errors" "errors"
"fmt" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/gogo/protobuf/proto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
) )
var ( var (
@ -14,68 +10,52 @@ var (
ErrIncorrectCID = errors.New("change has incorrect CID") ErrIncorrectCID = errors.New("change has incorrect CID")
) )
type ChangeContent struct {
ChangesData proto.Marshaler
ACLData *aclpb.ACLData
Id string // TODO: this is just for testing, because id should be created automatically from content
}
// Change is an abstract type for all types of changes // Change is an abstract type for all types of changes
type Change struct { type Change struct {
Next []*Change Next []*Change
PreviousIds []string PreviousIds []string
AclHeadId string
Id string Id string
SnapshotId string SnapshotId string
IsSnapshot bool IsSnapshot bool
DecryptedChange []byte // TODO: check if we need it Timestamp int64
ParsedModel interface{} // TODO: check if we need it ReadKeyHash uint64
Identity string
Data []byte
Model interface{}
// iterator helpers // iterator helpers
visited bool visited bool
branchesFinished bool branchesFinished bool
Content *aclpb.TreeChange Signature []byte
Identity string
Sign []byte
} }
func (ch *Change) ProtoChange() proto.Marshaler { func NewChange(id string, ch *treechangeproto.TreeChange, signature []byte) *Change {
return ch.Content
}
func (ch *Change) DecryptContents(key *symmetric.Key) error {
// if the document is already decrypted
if ch.Content.CurrentReadKeyHash == 0 {
return nil
}
decrypted, err := key.Decrypt(ch.Content.ChangesData)
if err != nil {
return fmt.Errorf("failed to decrypt changes data: %w", err)
}
ch.DecryptedChange = decrypted
return nil
}
func NewChange(id string, ch *aclpb.TreeChange, signature []byte) *Change {
return &Change{ return &Change{
Next: nil, Next: nil,
PreviousIds: ch.TreeHeadIds, PreviousIds: ch.TreeHeadIds,
AclHeadId: ch.AclHeadId,
Timestamp: ch.Timestamp,
ReadKeyHash: ch.CurrentReadKeyHash,
Id: id, Id: id,
Content: ch, Data: ch.ChangesData,
SnapshotId: ch.SnapshotBaseId, SnapshotId: ch.SnapshotBaseId,
IsSnapshot: ch.IsSnapshot, IsSnapshot: ch.IsSnapshot,
Identity: string(ch.Identity), Identity: string(ch.Identity),
Sign: signature, Signature: signature,
} }
} }
func (ch *Change) DecryptedChangeContent() []byte { func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change {
return ch.DecryptedChange return &Change{
} Next: nil,
AclHeadId: ch.AclHeadId,
func (ch *Change) Signature() []byte { Id: id,
return ch.Sign IsSnapshot: true,
Identity: string(ch.Identity),
Signature: signature,
}
} }
func (ch *Change) CID() string { func (ch *Change) CID() string {

View File

@ -2,8 +2,8 @@ package tree
import ( import (
"errors" "errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
@ -14,32 +14,44 @@ import (
var ErrEmptyChange = errors.New("change payload should not be empty") var ErrEmptyChange = errors.New("change payload should not be empty")
type BuilderContent struct { type BuilderContent struct {
treeHeadIds []string TreeHeadIds []string
aclHeadId string AclHeadId string
snapshotBaseId string SnapshotBaseId string
currentReadKeyHash uint64 CurrentReadKeyHash uint64
identity []byte Identity []byte
isSnapshot bool IsSnapshot bool
signingKey signingkey.PrivKey SigningKey signingkey.PrivKey
readKey *symmetric.Key ReadKey *symmetric.Key
content []byte Content []byte
}
type InitialContent struct {
AclHeadId string
Identity []byte
SigningKey signingkey.PrivKey
SpaceId string
Seed []byte
ChangeType string
} }
type ChangeBuilder interface { type ChangeBuilder interface {
ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error)
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error) BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
BuildRaw(ch *Change) (*aclpb.RawTreeChangeWithId, error) BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
BuildRaw(ch *Change) (*treechangeproto.RawTreeChangeWithId, error)
SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId)
} }
type changeBuilder struct { type changeBuilder struct {
rootChange *treechangeproto.RawTreeChangeWithId
keys *common.Keychain keys *common.Keychain
} }
func newChangeBuilder(keys *common.Keychain) ChangeBuilder { func newChangeBuilder(keys *common.Keychain, rootChange *treechangeproto.RawTreeChangeWithId) ChangeBuilder {
return &changeBuilder{keys: keys} return &changeBuilder{keys: keys, rootChange: rootChange}
} }
func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) { func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
if rawIdChange.GetRawChange() == nil { if rawIdChange.GetRawChange() == nil {
err = ErrEmptyChange err = ErrEmptyChange
return return
@ -53,7 +65,7 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, v
} }
} }
raw := &aclpb.RawTreeChange{} // TODO: sync pool raw := &treechangeproto.RawTreeChange{} // TODO: sync pool
err = proto.Unmarshal(rawIdChange.GetRawChange(), raw) err = proto.Unmarshal(rawIdChange.GetRawChange(), raw)
if err != nil { if err != nil {
return return
@ -78,28 +90,69 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, v
} }
} }
unmarshalled := &aclpb.TreeChange{} return c.unmarshallRawChange(raw, rawIdChange.Id)
err = proto.Unmarshal(raw.Payload, unmarshalled) }
func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {
c.rootChange = rawIdChange
}
func (c *changeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
change := &treechangeproto.RootChange{
AclHeadId: payload.AclHeadId,
Timestamp: int64(time.Now().Nanosecond()),
Identity: payload.Identity,
ChangeType: payload.ChangeType,
SpaceId: payload.SpaceId,
Seed: payload.Seed,
}
marshalledChange, err := proto.Marshal(change)
if err != nil { if err != nil {
return return
} }
ch = NewChange(rawIdChange.Id, unmarshalled, raw.Signature) signature, err := payload.SigningKey.Sign(marshalledChange)
if err != nil {
return
}
raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange,
Signature: signature,
}
marshalledRawChange, err := proto.Marshal(raw)
if err != nil {
return
}
id, err := cid.NewCIDFromBytes(marshalledRawChange)
if err != nil {
return
}
ch = NewChangeFromRoot(id, change, signature)
rawIdChange = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: id,
}
return return
} }
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *aclpb.RawTreeChangeWithId, err error) { func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
change := &aclpb.TreeChange{ change := &treechangeproto.TreeChange{
TreeHeadIds: payload.treeHeadIds, TreeHeadIds: payload.TreeHeadIds,
AclHeadId: payload.aclHeadId, AclHeadId: payload.AclHeadId,
SnapshotBaseId: payload.snapshotBaseId, SnapshotBaseId: payload.SnapshotBaseId,
CurrentReadKeyHash: payload.currentReadKeyHash, CurrentReadKeyHash: payload.CurrentReadKeyHash,
Timestamp: int64(time.Now().Nanosecond()), Timestamp: int64(time.Now().Nanosecond()),
Identity: payload.identity, Identity: payload.Identity,
IsSnapshot: payload.isSnapshot, IsSnapshot: payload.IsSnapshot,
} }
encrypted, err := payload.readKey.Encrypt(payload.content) encrypted, err := payload.ReadKey.Encrypt(payload.Content)
if err != nil { if err != nil {
return return
} }
@ -110,12 +163,12 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
return return
} }
signature, err := payload.signingKey.Sign(marshalledChange) signature, err := payload.SigningKey.Sign(marshalledChange)
if err != nil { if err != nil {
return return
} }
raw := &aclpb.RawTreeChange{ raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange, Payload: marshalledChange,
Signature: signature, Signature: signature,
} }
@ -131,33 +184,67 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
} }
ch = NewChange(id, change, signature) ch = NewChange(id, change, signature)
ch.ParsedModel = payload.content ch.Model = payload.Content
rawIdChange = &aclpb.RawTreeChangeWithId{ rawIdChange = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange, RawChange: marshalledRawChange,
Id: id, Id: id,
} }
return return
} }
func (c *changeBuilder) BuildRaw(ch *Change) (raw *aclpb.RawTreeChangeWithId, err error) { func (c *changeBuilder) BuildRaw(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) {
if ch.Id == c.rootChange.Id {
return c.rootChange, nil
}
treeChange := &treechangeproto.TreeChange{
TreeHeadIds: ch.PreviousIds,
AclHeadId: ch.AclHeadId,
SnapshotBaseId: ch.SnapshotId,
ChangesData: ch.Data,
CurrentReadKeyHash: ch.ReadKeyHash,
Timestamp: ch.Timestamp,
Identity: []byte(ch.Identity),
IsSnapshot: ch.IsSnapshot,
}
var marshalled []byte var marshalled []byte
marshalled, err = ch.Content.Marshal() marshalled, err = treeChange.Marshal()
if err != nil { if err != nil {
return return
} }
marshalledRawChange, err := proto.Marshal(&aclpb.RawTreeChange{ marshalledRawChange, err := proto.Marshal(&treechangeproto.RawTreeChange{
Payload: marshalled, Payload: marshalled,
Signature: ch.Sign, Signature: ch.Signature,
}) })
if err != nil { if err != nil {
return return
} }
raw = &aclpb.RawTreeChangeWithId{ raw = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange, RawChange: marshalledRawChange,
Id: ch.Id, Id: ch.Id,
} }
return return
} }
func (c *changeBuilder) unmarshallRawChange(raw *treechangeproto.RawTreeChange, id string) (ch *Change, err error) {
if c.rootChange.Id == id {
unmarshalled := &treechangeproto.RootChange{}
err = proto.Unmarshal(raw.Payload, unmarshalled)
if err != nil {
return
}
ch = NewChangeFromRoot(id, unmarshalled, raw.Signature)
return
}
unmarshalled := &treechangeproto.TreeChange{}
err = proto.Unmarshal(raw.Payload, unmarshalled)
if err != nil {
return
}
ch = NewChange(id, unmarshalled, raw.Signature)
return
}

View File

@ -2,7 +2,7 @@ package tree
import ( import (
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
) )
@ -43,12 +43,12 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
state = aclList.ACLState() state = aclList.ACLState()
) )
// checking if the user could write // checking if the user could write
perm, err = state.PermissionsAtRecord(c.Content.AclHeadId, c.Identity) perm, err = state.PermissionsAtRecord(c.AclHeadId, c.Identity)
if err != nil { if err != nil {
return return
} }
if perm.Permission != aclpb.ACLUserPermissions_Writer && perm.Permission != aclpb.ACLUserPermissions_Admin { if perm.Permission != aclrecordproto.ACLUserPermissions_Writer && perm.Permission != aclrecordproto.ACLUserPermissions_Admin {
err = list.ErrInsufficientPermissions err = list.ErrInsufficientPermissions
return return
} }
@ -56,16 +56,16 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
// 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]
if prevChange.Content.AclHeadId == c.Content.AclHeadId { if prevChange.AclHeadId == c.AclHeadId {
continue continue
} }
var after bool var after bool
after, err = aclList.IsAfter(c.Content.AclHeadId, prevChange.Content.AclHeadId) after, err = aclList.IsAfter(c.AclHeadId, prevChange.AclHeadId)
if err != nil { if err != nil {
return return
} }
if !after { if !after {
err = fmt.Errorf("current acl head id (%s) should be after each of the previous ones (%s)", c.Content.AclHeadId, prevChange.Content.AclHeadId) err = fmt.Errorf("current acl head id (%s) should be after each of the previous ones (%s)", c.AclHeadId, prevChange.AclHeadId)
return return
} }
} }

View File

@ -3,10 +3,10 @@ package tree
import ( import (
"context" "context"
"errors" "errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
"sync" "sync"
) )
@ -27,7 +27,7 @@ type AddResultSummary int
type AddResult struct { type AddResult struct {
OldHeads []string OldHeads []string
Heads []string Heads []string
Added []*aclpb.RawTreeChangeWithId Added []*treechangeproto.RawTreeChangeWithId
Mode Mode Mode Mode
} }
@ -39,7 +39,7 @@ type ObjectTree interface {
RWLocker RWLocker
ID() string ID() string
Header() *aclpb.TreeHeader Header() *treechangeproto.RootChange
Heads() []string Heads() []string
Root() *Change Root() *Change
HasChange(string) bool HasChange(string) bool
@ -49,12 +49,12 @@ type ObjectTree interface {
IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error
SnapshotPath() []string SnapshotPath() []string
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*aclpb.RawTreeChangeWithId, error) ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*treechangeproto.RawTreeChangeWithId, error)
Storage() storage.TreeStorage Storage() storage.TreeStorage
AddContent(ctx context.Context, content SignableChangeContent) (AddResult, error) AddContent(ctx context.Context, content SignableChangeContent) (AddResult, error)
AddRawChanges(ctx context.Context, changes ...*aclpb.RawTreeChangeWithId) (AddResult, error) AddRawChanges(ctx context.Context, changes ...*treechangeproto.RawTreeChangeWithId) (AddResult, error)
Close() error Close() error
} }
@ -68,13 +68,13 @@ type objectTree struct {
aclList list.ACLList aclList list.ACLList
id string id string
header *aclpb.TreeHeader root *treechangeproto.RootChange
tree *Tree tree *Tree
keys map[uint64]*symmetric.Key keys map[uint64]*symmetric.Key
// buffers // buffers
difSnapshotBuf []*aclpb.RawTreeChangeWithId difSnapshotBuf []*treechangeproto.RawTreeChangeWithId
tmpChangesBuf []*Change tmpChangesBuf []*Change
newSnapshotsBuf []*Change newSnapshotsBuf []*Change
notSeenIdxBuf []int notSeenIdxBuf []int
@ -94,11 +94,12 @@ type objectTreeDeps struct {
} }
func defaultObjectTreeDeps( func defaultObjectTreeDeps(
rootChange *treechangeproto.RawTreeChangeWithId,
treeStorage storage.TreeStorage, treeStorage storage.TreeStorage,
aclList list.ACLList) objectTreeDeps { aclList list.ACLList) objectTreeDeps {
keychain := common.NewKeychain() keychain := common.NewKeychain()
changeBuilder := newChangeBuilder(keychain) changeBuilder := newChangeBuilder(keychain, rootChange)
treeBuilder := newTreeBuilder(treeStorage, changeBuilder) treeBuilder := newTreeBuilder(treeStorage, changeBuilder)
return objectTreeDeps{ return objectTreeDeps{
changeBuilder: changeBuilder, changeBuilder: changeBuilder,
@ -131,8 +132,8 @@ func (ot *objectTree) ID() string {
return ot.id return ot.id
} }
func (ot *objectTree) Header() *aclpb.TreeHeader { func (ot *objectTree) Header() *treechangeproto.RootChange {
return ot.header return ot.root
} }
func (ot *objectTree) Storage() storage.TreeStorage { func (ot *objectTree) Storage() storage.TreeStorage {
@ -172,7 +173,7 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont
res = AddResult{ res = AddResult{
OldHeads: oldHeads, OldHeads: oldHeads,
Heads: []string{objChange.Id}, Heads: []string{objChange.Id},
Added: []*aclpb.RawTreeChangeWithId{rawChange}, Added: []*treechangeproto.RawTreeChangeWithId{rawChange},
Mode: Append, Mode: Append,
} }
return return
@ -188,20 +189,20 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt
return return
} }
cnt = BuilderContent{ cnt = BuilderContent{
treeHeadIds: ot.tree.Heads(), TreeHeadIds: ot.tree.Heads(),
aclHeadId: ot.aclList.Head().Id, AclHeadId: ot.aclList.Head().Id,
snapshotBaseId: ot.tree.RootId(), SnapshotBaseId: ot.tree.RootId(),
currentReadKeyHash: state.CurrentReadKeyHash(), CurrentReadKeyHash: state.CurrentReadKeyHash(),
identity: content.Identity, Identity: content.Identity,
isSnapshot: content.IsSnapshot, IsSnapshot: content.IsSnapshot,
signingKey: content.Key, SigningKey: content.Key,
readKey: readKey, ReadKey: readKey,
content: content.Data, Content: content.Data,
} }
return return
} }
func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawTreeChangeWithId) (addResult AddResult, err error) { func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*treechangeproto.RawTreeChangeWithId) (addResult AddResult, err error) {
addResult, err = ot.addRawChanges(ctx, rawChanges...) addResult, err = ot.addRawChanges(ctx, rawChanges...)
if err != nil { if err != nil {
return return
@ -223,7 +224,7 @@ func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
return return
} }
func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.RawTreeChangeWithId) (addResult AddResult, err error) { func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*treechangeproto.RawTreeChangeWithId) (addResult AddResult, err error) {
// resetting buffers // resetting buffers
ot.tmpChangesBuf = ot.tmpChangesBuf[:0] ot.tmpChangesBuf = ot.tmpChangesBuf[:0]
ot.notSeenIdxBuf = ot.notSeenIdxBuf[:0] ot.notSeenIdxBuf = ot.notSeenIdxBuf[:0]
@ -275,7 +276,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
// returns changes that we added to the tree as attached this round // returns changes that we added to the tree as attached this round
// they can include not only the changes that were added now, // they can include not only the changes that were added now,
// but also the changes that were previously in the tree // but also the changes that were previously in the tree
getAddedChanges := func(toConvert []*Change) (added []*aclpb.RawTreeChangeWithId, err error) { getAddedChanges := func(toConvert []*Change) (added []*treechangeproto.RawTreeChangeWithId, err error) {
alreadyConverted := make(map[*Change]struct{}) alreadyConverted := make(map[*Change]struct{})
// first we see if we have already unmarshalled those changes // first we see if we have already unmarshalled those changes
@ -300,7 +301,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
for _, ch := range toConvert { for _, ch := range toConvert {
// if we got some changes that we need to convert to raw // if we got some changes that we need to convert to raw
if _, exists := alreadyConverted[ch]; !exists { if _, exists := alreadyConverted[ch]; !exists {
var raw *aclpb.RawTreeChangeWithId var raw *treechangeproto.RawTreeChangeWithId
raw, err = ot.changeBuilder.BuildRaw(ch) raw, err = ot.changeBuilder.BuildRaw(ch)
if err != nil { if err != nil {
return return
@ -342,7 +343,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
ot.rebuildFromStorage(nil) ot.rebuildFromStorage(nil)
return return
} }
var added []*aclpb.RawTreeChangeWithId var added []*treechangeproto.RawTreeChangeWithId
added, err = getAddedChanges(nil) added, err = getAddedChanges(nil)
// we shouldn't get any error in this case // we shouldn't get any error in this case
if err != nil { if err != nil {
@ -378,7 +379,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
err = ErrHasInvalidChanges err = ErrHasInvalidChanges
return return
} }
var added []*aclpb.RawTreeChangeWithId var added []*treechangeproto.RawTreeChangeWithId
added, err = getAddedChanges(treeChangesAdded) added, err = getAddedChanges(treeChangesAdded)
if err != nil { if err != nil {
// that means that some unattached changes were somehow corrupted in memory // that means that some unattached changes were somehow corrupted in memory
@ -409,17 +410,21 @@ func (ot *objectTree) IterateFrom(id string, convert ChangeConvertFunc, iterate
ot.tree.Iterate(ot.tree.RootId(), func(c *Change) (isContinue bool) { ot.tree.Iterate(ot.tree.RootId(), func(c *Change) (isContinue bool) {
var model any var model any
if c.ParsedModel != nil { if c.Model != nil {
return iterate(c) return iterate(c)
} }
readKey, exists := ot.keys[c.Content.CurrentReadKeyHash] // if this is a root change
if c.Id == ot.id {
return iterate(c)
}
readKey, exists := ot.keys[c.ReadKeyHash]
if !exists { if !exists {
err = list.ErrNoReadKey err = list.ErrNoReadKey
return false return false
} }
var decrypted []byte var decrypted []byte
decrypted, err = readKey.Decrypt(c.Content.GetChangesData()) decrypted, err = readKey.Decrypt(c.Data)
if err != nil { if err != nil {
return false return false
} }
@ -429,7 +434,7 @@ func (ot *objectTree) IterateFrom(id string, convert ChangeConvertFunc, iterate
return false return false
} }
c.ParsedModel = model c.Model = model
return iterate(c) return iterate(c)
}) })
return return
@ -474,7 +479,7 @@ func (ot *objectTree) SnapshotPath() []string {
return path return path
} }
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawTreeChangeWithId, error) { func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
var ( var (
needFullDocument = len(theirPath) == 0 needFullDocument = len(theirPath) == 0
ourPath = ot.SnapshotPath() ourPath = ot.SnapshotPath()
@ -498,11 +503,11 @@ func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string)
} }
} }
func (ot *objectTree) getChangesFromTree(theirHeads []string) (rawChanges []*aclpb.RawTreeChangeWithId, err error) { func (ot *objectTree) getChangesFromTree(theirHeads []string) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
return ot.rawChangeLoader.LoadFromTree(ot.tree, theirHeads) return ot.rawChangeLoader.LoadFromTree(ot.tree, theirHeads)
} }
func (ot *objectTree) getChangesFromDB(commonSnapshot string, theirHeads []string) (rawChanges []*aclpb.RawTreeChangeWithId, err error) { func (ot *objectTree) getChangesFromDB(commonSnapshot string, theirHeads []string) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
return ot.rawChangeLoader.LoadFromStorage(commonSnapshot, ot.tree.headIds, theirHeads) return ot.rawChangeLoader.LoadFromStorage(commonSnapshot, ot.tree.headIds, theirHeads)
} }

View File

@ -2,10 +2,12 @@ package tree
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "crypto/rand"
"encoding/hex"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -14,8 +16,26 @@ import (
type mockChangeCreator struct{} type mockChangeCreator struct{}
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *aclpb.RawTreeChangeWithId { func (c *mockChangeCreator) createRoot(id, aclId string) *treechangeproto.RawTreeChangeWithId {
aclChange := &aclpb.TreeChange{ aclChange := &treechangeproto.RootChange{
AclHeadId: aclId,
}
res, _ := aclChange.Marshal()
raw := &treechangeproto.RawTreeChange{
Payload: res,
Signature: nil,
}
rawMarshalled, _ := raw.Marshal()
return &treechangeproto.RawTreeChangeWithId{
RawChange: rawMarshalled,
Id: id,
}
}
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *treechangeproto.RawTreeChangeWithId {
aclChange := &treechangeproto.TreeChange{
TreeHeadIds: prevIds, TreeHeadIds: prevIds,
AclHeadId: aclId, AclHeadId: aclId,
SnapshotBaseId: snapshotId, SnapshotBaseId: snapshotId,
@ -24,26 +44,21 @@ func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot b
} }
res, _ := aclChange.Marshal() res, _ := aclChange.Marshal()
raw := &aclpb.RawTreeChange{ raw := &treechangeproto.RawTreeChange{
Payload: res, Payload: res,
Signature: nil, Signature: nil,
} }
rawMarshalled, _ := raw.Marshal() rawMarshalled, _ := raw.Marshal()
return &aclpb.RawTreeChangeWithId{ return &treechangeproto.RawTreeChangeWithId{
RawChange: rawMarshalled, RawChange: rawMarshalled,
Id: id, Id: id,
} }
} }
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclListId, aclHeadId, firstChangeId string) storage.TreeStorage { func (c *mockChangeCreator) createNewTreeStorage(treeId, aclHeadId string) storage.TreeStorage {
firstChange := c.createRaw(firstChangeId, aclHeadId, "", true) root := c.createRoot(treeId, aclHeadId)
header := &aclpb.TreeHeader{ treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root})
FirstId: firstChangeId,
AclId: aclListId,
TreeHeaderType: aclpb.TreeHeaderType_Object,
}
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawTreeChangeWithId{firstChange})
return treeStorage return treeStorage
} }
@ -51,15 +66,23 @@ type mockChangeBuilder struct {
originalBuilder ChangeBuilder originalBuilder ChangeBuilder
} }
func (c *mockChangeBuilder) ConvertFromRaw(rawChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) { func (c *mockChangeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) {
return c.originalBuilder.ConvertFromRaw(rawChange, false)
}
func (c *mockChangeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error) {
panic("implement me") panic("implement me")
} }
func (c *mockChangeBuilder) BuildRaw(ch *Change) (raw *aclpb.RawTreeChangeWithId, err error) { func (c *mockChangeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {
c.originalBuilder.SetRootRawChange(rawIdChange)
}
func (c *mockChangeBuilder) ConvertFromRaw(rawChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
return c.originalBuilder.ConvertFromRaw(rawChange, false)
}
func (c *mockChangeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) {
panic("implement me")
}
func (c *mockChangeBuilder) BuildRaw(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) {
return c.originalBuilder.BuildRaw(ch) return c.originalBuilder.BuildRaw(ch)
} }
@ -93,15 +116,15 @@ func prepareACLList(t *testing.T) list.ACLList {
func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext { func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext {
changeCreator := &mockChangeCreator{} changeCreator := &mockChangeCreator{}
treeStorage := changeCreator.createNewTreeStorage("treeId", aclList.ID(), aclList.Head().Id, "0") treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id)
root, _ := treeStorage.Root()
changeBuilder := &mockChangeBuilder{ changeBuilder := &mockChangeBuilder{
originalBuilder: newChangeBuilder(nil), originalBuilder: newChangeBuilder(nil, root),
} }
deps := objectTreeDeps{ deps := objectTreeDeps{
changeBuilder: changeBuilder, changeBuilder: changeBuilder,
treeBuilder: newTreeBuilder(treeStorage, changeBuilder), treeBuilder: newTreeBuilder(treeStorage, changeBuilder),
treeStorage: treeStorage, treeStorage: treeStorage,
updateListener: nil,
rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder),
validator: &mockChangeValidator{}, validator: &mockChangeValidator{},
aclList: aclList, aclList: aclList,
@ -128,6 +151,18 @@ func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext {
} }
} }
func TestSameSignature(t *testing.T) {
privKey, _, err := signingkey.GenerateEd25519Key(rand.Reader)
require.NoError(t, err)
bytes := []byte("asefhiosahjfoiesjgioesajgihs")
for i := 0; i < 5; i++ {
signed, err := privKey.Sign(bytes)
require.NoError(t, err)
t.Log(hex.EncodeToString(signed))
}
// kitten step voyage hand cover funny timber auction differ mushroom update pulp
}
func TestObjectTree(t *testing.T) { func TestObjectTree(t *testing.T) {
aclList := prepareACLList(t) aclList := prepareACLList(t)
@ -137,7 +172,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
} }
@ -178,7 +213,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("0", aclList.Head().Id, "", true, ""), changeCreator.createRaw("0", aclList.Head().Id, "", true, ""),
} }
res, err := objTree.AddRawChanges(context.Background(), rawChanges...) res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
@ -198,7 +233,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
} }
res, err := objTree.AddRawChanges(context.Background(), rawChanges...) res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
@ -220,7 +255,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"), changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -264,7 +299,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"), changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -283,7 +318,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"), changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -357,7 +392,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"), changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -433,7 +468,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"), changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -442,7 +477,7 @@ func TestObjectTree(t *testing.T) {
require.NoError(t, err, "adding changes should be without error") require.NoError(t, err, "adding changes should be without error")
require.Equal(t, "3", objTree.Root().Id) require.Equal(t, "3", objTree.Root().Id)
rawChanges = []*aclpb.RawTreeChangeWithId{ rawChanges = []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("4", aclList.Head().Id, "0", false, "2"), changeCreator.createRaw("4", aclList.Head().Id, "0", false, "2"),
changeCreator.createRaw("5", aclList.Head().Id, "0", false, "1"), changeCreator.createRaw("5", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"), changeCreator.createRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"),

View File

@ -1,11 +1,10 @@
package tree package tree
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
@ -13,14 +12,19 @@ import (
) )
type ObjectTreeCreatePayload struct { type ObjectTreeCreatePayload struct {
AccountData *account.AccountData SignKey signingkey.PrivKey
HeaderData []byte ChangeType string
ChangeData []byte Seed []byte
TreeType aclpb.TreeHeaderType SpaceId string
Identity []byte
} }
func BuildObjectTree(treeStorage storage.TreeStorage, aclList list.ACLList) (ObjectTree, error) { func BuildObjectTree(treeStorage storage.TreeStorage, aclList list.ACLList) (ObjectTree, error) {
deps := defaultObjectTreeDeps(treeStorage, aclList) rootChange, err := treeStorage.Root()
if err != nil {
return nil, err
}
deps := defaultObjectTreeDeps(rootChange, treeStorage, aclList)
return buildObjectTree(deps) return buildObjectTree(deps)
} }
@ -30,53 +34,34 @@ func CreateObjectTree(
createStorage storage.TreeStorageCreatorFunc) (objTree ObjectTree, err error) { createStorage storage.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
aclList.RLock() aclList.RLock()
var ( var (
deps = defaultObjectTreeDeps(nil, aclList) deps = defaultObjectTreeDeps(nil, nil, aclList)
state = aclList.ACLState()
aclId = aclList.ID()
aclHeadId = aclList.Head().Id aclHeadId = aclList.Head().Id
readKeyHash = state.CurrentReadKeyHash()
) )
readKey, err := state.CurrentReadKey()
aclList.RUnlock() aclList.RUnlock()
if err != nil { if err != nil {
return return
} }
cnt := InitialContent{
// create first change AclHeadId: aclHeadId,
cnt := BuilderContent{ Identity: payload.Identity,
treeHeadIds: nil, SigningKey: payload.SignKey,
aclHeadId: aclHeadId, SpaceId: payload.SpaceId,
snapshotBaseId: "", Seed: payload.Seed,
currentReadKeyHash: readKeyHash, ChangeType: payload.ChangeType,
isSnapshot: true,
readKey: readKey,
identity: payload.AccountData.Identity,
signingKey: payload.AccountData.SignKey,
content: payload.ChangeData,
} }
_, raw, err := deps.changeBuilder.BuildContent(cnt) _, raw, err := deps.changeBuilder.BuildInitialContent(cnt)
if err != nil {
return
}
// create header
header, id, err := createTreeHeaderAndId(
raw,
payload.TreeType,
aclId,
payload.AccountData.Identity,
payload.HeaderData)
if err != nil { if err != nil {
return return
} }
deps.changeBuilder.SetRootRawChange(raw)
// create storage // create storage
st, err := createStorage(storage.TreeStorageCreatePayload{ st, err := createStorage(storage.TreeStorageCreatePayload{
TreeId: id, TreeId: raw.Id,
Header: header, RootRawChange: raw,
Changes: []*aclpb.RawTreeChangeWithId{raw}, Changes: []*treechangeproto.RawTreeChangeWithId{raw},
Heads: []string{raw.Id}, Heads: []string{raw.Id},
}) })
if err != nil { if err != nil {
@ -98,7 +83,7 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
tree: nil, tree: nil,
keys: make(map[uint64]*symmetric.Key), keys: make(map[uint64]*symmetric.Key),
tmpChangesBuf: make([]*Change, 0, 10), tmpChangesBuf: make([]*Change, 0, 10),
difSnapshotBuf: make([]*aclpb.RawTreeChangeWithId, 0, 10), difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
notSeenIdxBuf: make([]int, 0, 10), notSeenIdxBuf: make([]int, 0, 10),
newSnapshotsBuf: make([]*Change, 0, 10), newSnapshotsBuf: make([]*Change, 0, 10),
} }
@ -128,32 +113,23 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
objTree.header, err = objTree.treeStorage.Header()
rawRootWithId, err := objTree.treeStorage.Root()
if err != nil {
return nil, err
}
rawRoot := &treechangeproto.RawTreeChange{}
err = proto.Unmarshal(rawRootWithId.RawChange, rawRoot)
if err != nil {
return nil, err
}
objTree.root = &treechangeproto.RootChange{}
err = proto.Unmarshal(rawRoot.Payload, objTree.root)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return objTree, nil return objTree, nil
} }
func createTreeHeaderAndId(
raw *aclpb.RawTreeChangeWithId,
treeType aclpb.TreeHeaderType,
aclId string,
identity []byte,
headerData []byte) (header *aclpb.TreeHeader, treeId string, err error) {
header = &aclpb.TreeHeader{
FirstId: raw.Id,
TreeHeaderType: treeType,
AclId: aclId,
Identity: identity,
Data: headerData,
}
marshalledHeader, err := proto.Marshal(header)
if err != nil {
return
}
treeId, err = cid.NewCIDFromBytes(marshalledHeader)
return
}

View File

@ -2,8 +2,8 @@ package tree
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
"time" "time"
) )
@ -18,7 +18,7 @@ type rawChangeLoader struct {
type rawCacheEntry struct { type rawCacheEntry struct {
change *Change change *Change
rawChange *aclpb.RawTreeChangeWithId rawChange *treechangeproto.RawTreeChangeWithId
position int position int
} }
@ -29,15 +29,15 @@ func newRawChangeLoader(treeStorage storage.TreeStorage, changeBuilder ChangeBui
} }
} }
func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.RawTreeChangeWithId, error) { func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
var stack []*Change var stack []*Change
for _, h := range t.headIds { for _, h := range t.headIds {
stack = append(stack, t.attached[h]) stack = append(stack, t.attached[h])
} }
convert := func(chs []*Change) (rawChanges []*aclpb.RawTreeChangeWithId, err error) { convert := func(chs []*Change) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
for _, ch := range chs { for _, ch := range chs {
var raw *aclpb.RawTreeChangeWithId var raw *treechangeproto.RawTreeChangeWithId
raw, err = r.changeBuilder.BuildRaw(ch) raw, err = r.changeBuilder.BuildRaw(ch)
if err != nil { if err != nil {
return return
@ -95,7 +95,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.
return convert(results) return convert(results)
} }
func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoints []string) ([]*aclpb.RawTreeChangeWithId, error) { func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoints []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
// resetting cache // resetting cache
r.cache = make(map[string]rawCacheEntry) r.cache = make(map[string]rawCacheEntry)
defer func() { defer func() {
@ -162,7 +162,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
// preparing first pass // preparing first pass
r.idStack = append(r.idStack, heads...) r.idStack = append(r.idStack, heads...)
var buffer []*aclpb.RawTreeChangeWithId var buffer []*treechangeproto.RawTreeChangeWithId
rootVisited := dfs(commonSnapshot, heads, 0, rootVisited := dfs(commonSnapshot, heads, 0,
func(counter int, mapExists bool) bool { func(counter int, mapExists bool) bool {
@ -203,7 +203,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
}) })
// discarding visited // discarding visited
buffer = discardFromSlice(buffer, func(change *aclpb.RawTreeChangeWithId) bool { buffer = discardFromSlice(buffer, func(change *treechangeproto.RawTreeChangeWithId) bool {
return change == nil return change == nil
}) })

View File

@ -90,7 +90,7 @@ func (t *Tree) Graph() (data string, err error) {
label := fmt.Sprintf("Id: %s\nOrd: %s\nTime: %s\nChanges: %s\n", label := fmt.Sprintf("Id: %s\nOrd: %s\nTime: %s\nChanges: %s\n",
shortId, shortId,
ord, ord,
time.Unix(c.Content.Timestamp, 0).Format("02.01.06 15:04:05"), time.Unix(c.Timestamp, 0).Format("02.01.06 15:04:05"),
strings.Join(chSymbs, ","), strings.Join(chSymbs, ","),
) )
n.SetLabel(label) n.SetLabel(label)

View File

@ -0,0 +1,55 @@
syntax = "proto3";
package treechange;
option go_package = "pkg/acl/treechangeproto";
// RootChange is a root of a tree
message RootChange {
// AclHeadId is a cid of latest acl record at the time of tree creation
string aclHeadId = 1;
// SpaceId is an id of space where the document is placed
string spaceId = 2;
// ChangeType is a type of tree which this RootChange is a root of
string changeType = 3;
// Timestamp is this change creation timestamp
int64 timestamp = 4;
// Seed is a random bytes to make root change unique
bytes seed = 5;
// Identity is a public key of the tree's creator
bytes identity = 6;
}
// TreeChange is a change of a tree
message TreeChange {
// TreeHeadIds are previous ids for this TreeChange
repeated string treeHeadIds = 1;
// AclHeadId is a cid of latest acl record at the time of this change
string aclHeadId = 2;
// SnapshotBaseId is a snapshot (root) of the tree where this change is added
string snapshotBaseId = 3;
// ChangesData is an arbitrary payload to be read by the client
bytes changesData = 4;
// CurrentReadKeyHash is the hash of the read key which is used to encrypt this change
uint64 currentReadKeyHash = 5;
// Timestamp is this change creation timestamp
int64 timestamp = 6;
// Identity is a public key with which the raw payload of this change is signed
bytes identity = 7;
// IsSnapshot indicates whether this change contains a snapshot of state
bool isSnapshot = 8;
}
// RawTreeChange is a marshalled TreeChange (or RootChange) payload and a signature of this payload
message RawTreeChange {
// Payload is a byte payload containing TreeChange
bytes payload = 1;
// Signature is a signature made by identity indicated in the TreeChange payload
bytes signature = 2;
}
// RawTreeChangeWithId is a marshalled RawTreeChange with CID
message RawTreeChangeWithId {
// RawChange is a byte payload of RawTreeChange
bytes rawChange = 1;
// Id is a cid made from rawChange payload
string id = 2;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,14 +2,16 @@ package document
import ( import (
"context" "context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/testchangepb" testchanges "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/proto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/message" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/message"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
@ -25,13 +27,14 @@ type service struct {
messageService message.Service messageService message.Service
treeCache treecache.Service treeCache treecache.Service
account account.Service account account.Service
storage storage.Service
// to create new documents we need to know all nodes // to create new documents we need to know all nodes
nodes []*node.Node nodes []*node.Node
} }
type Service interface { type Service interface {
UpdateDocument(ctx context.Context, id, text string) error UpdateDocumentTree(ctx context.Context, id, text string) error
CreateDocument(ctx context.Context, text string) (string, error) CreateDocumentTree(ctx context.Context, aclTreeId string, text string) (id string, err error)
} }
func New() app.Component { func New() app.Component {
@ -42,6 +45,7 @@ func (s *service) Init(a *app.App) (err error) {
s.account = a.MustComponent(account.CName).(account.Service) s.account = a.MustComponent(account.CName).(account.Service)
s.messageService = a.MustComponent(message.CName).(message.Service) s.messageService = a.MustComponent(message.CName).(message.Service)
s.treeCache = a.MustComponent(treecache.CName).(treecache.Service) s.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
s.storage = a.MustComponent(storage.CName).(storage.Service)
nodesService := a.MustComponent(node.CName).(node.Service) nodesService := a.MustComponent(node.CName).(node.Service)
s.nodes = nodesService.Nodes() s.nodes = nodesService.Nodes()
@ -54,41 +58,65 @@ func (s *service) Name() (name string) {
} }
func (s *service) Run(ctx context.Context) (err error) { func (s *service) Run(ctx context.Context) (err error) {
return nil syncData := s.storage.ImportedACLSyncData()
// we could have added a timeout or some additional logic,
// but let's just use the ACL id of the latest started node :-)
return s.messageService.SendToSpaceAsync("", syncproto.WrapACLList(
&syncproto.SyncACLList{Records: syncData.Records},
syncData.Header,
syncData.Id,
))
} }
func (s *service) Close(ctx context.Context) (err error) { func (s *service) Close(ctx context.Context) (err error) {
return nil return nil
} }
func (s *service) UpdateDocument(ctx context.Context, id, text string) (err error) { func (s *service) UpdateDocumentTree(ctx context.Context, id, text string) (err error) {
var ( var (
ch *aclpb.RawChange ch *aclpb.RawChange
header *treepb.TreeHeader header *aclpb.Header
snapshotPath []string snapshotPath []string
heads []string heads []string
) )
log.With(zap.String("id", id), zap.String("text", text)). log.With(zap.String("id", id), zap.String("text", text)).
Debug("updating document") Debug("updating document")
err = s.treeCache.Do(ctx, id, func(tree acltree.ACLTree) error { err = s.treeCache.Do(ctx, id, func(obj interface{}) error {
ch, err = tree.AddContent(ctx, func(builder acltree.ChangeBuilder) error { docTree, ok := obj.(tree.ObjectTree)
builder.AddChangeContent( if !ok {
&testchangepb.PlainTextChange_Data{ return fmt.Errorf("can't update acl trees with text")
Content: []*testchangepb.PlainTextChange_Content{ }
createAppendTextChangeContent(text),
}, docTree.Lock()
}) defer docTree.Unlock()
err = s.treeCache.Do(ctx, docTree.Header().AclListId, func(obj interface{}) error {
aclTree := obj.(list.ACLList)
aclTree.RLock()
defer aclTree.RUnlock()
content := createAppendTextChange(text)
signable := tree.SignableChangeContent{
Proto: content,
Key: s.account.Account().SignKey,
Identity: s.account.Account().Identity,
IsSnapshot: false,
}
ch, err = docTree.AddContent(ctx, signable)
if err != nil {
return err
}
return nil return nil
}) })
if err != nil { if err != nil {
return err return err
} }
id = tree.ID() id = docTree.ID()
heads = tree.Heads() heads = docTree.Heads()
header = tree.Header() header = docTree.Header()
snapshotPath = tree.SnapshotPath() snapshotPath = docTree.SnapshotPath()
return nil return nil
}) })
if err != nil { if err != nil {
@ -100,87 +128,90 @@ func (s *service) UpdateDocument(ctx context.Context, id, text string) (err erro
zap.String("header", header.String())). zap.String("header", header.String())).
Debug("document updated in the database") Debug("document updated in the database")
return s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.Sync_HeadUpdate{ return s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
Heads: heads, Heads: heads,
Changes: []*aclpb.RawChange{ch}, Changes: []*aclpb.RawChange{ch},
TreeId: id,
SnapshotPath: snapshotPath, SnapshotPath: snapshotPath,
TreeHeader: header, }, header, id))
}))
} }
func (s *service) CreateDocument(ctx context.Context, text string) (id string, err error) { func (s *service) CreateDocumentTree(ctx context.Context, aclListId string, text string) (id string, err error) {
acc := s.account.Account() acc := s.account.Account()
var ( var (
ch *aclpb.RawChange ch *aclpb.RawChange
header *treepb.TreeHeader header *aclpb.Header
snapshotPath []string snapshotPath []string
heads []string heads []string
) )
err = s.treeCache.Do(ctx, aclListId, func(obj interface{}) error {
t := obj.(list.ACLList)
t.RLock()
defer t.RUnlock()
err = s.treeCache.Create(ctx, func(builder acltree.ChangeBuilder) error { content := createInitialTextChange(text)
err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin) doc, err := tree.CreateNewTreeStorage(acc, t, content, s.storage.CreateTreeStorage)
if err != nil { if err != nil {
return err return err
} }
// adding all predefined nodes to the document as admins
for _, n := range s.nodes {
err = builder.UserAdd(n.SigningKeyString, n.EncryptionKey, aclpb.ACLChange_Admin)
if err != nil {
return err
}
}
builder.AddChangeContent(createInitialChangeContent(text)) id, err = doc.ID()
return nil
}, func(tree acltree.ACLTree) error {
id = tree.ID()
heads = tree.Heads()
header = tree.Header()
snapshotPath = tree.SnapshotPath()
ch, err = tree.Storage().GetChange(ctx, heads[0])
if err != nil { if err != nil {
return err return err
} }
log.With(
zap.String("id", id), header, err = doc.Header()
zap.Strings("heads", heads), if err != nil {
zap.String("header", header.String())). return err
Debug("document created in the database") }
heads = []string{header.FirstId}
snapshotPath = []string{header.FirstId}
ch, err = doc.GetRawChange(ctx, header.FirstId)
if err != nil {
return err
}
return nil return nil
}) })
if err != nil { if err != nil {
return "", err return "", err
} }
log.With(zap.String("id", id), zap.String("text", text)). log.With(zap.String("id", id), zap.String("text", text)).
Debug("creating document") Debug("creating document")
err = s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.Sync_HeadUpdate{ err = s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
Heads: heads, Heads: heads,
Changes: []*aclpb.RawChange{ch}, Changes: []*aclpb.RawChange{ch},
TreeId: id,
SnapshotPath: snapshotPath, SnapshotPath: snapshotPath,
TreeHeader: header, }, header, id))
}))
if err != nil { if err != nil {
return "", err return "", err
} }
return id, err return id, err
} }
func createInitialChangeContent(text string) proto.Marshaler { func createInitialTextChange(text string) proto.Marshaler {
return &testchangepb.PlainTextChange_Data{ return &testchanges.PlainTextChangeData{
Content: []*testchangepb.PlainTextChange_Content{ Content: []*testchanges.PlainTextChangeContent{
createAppendTextChangeContent(text), createAppendTextChangeContent(text),
}, },
Snapshot: &testchangepb.PlainTextChange_Snapshot{Text: text}, Snapshot: &testchanges.PlainTextChangeSnapshot{Text: text},
} }
} }
func createAppendTextChangeContent(text string) *testchangepb.PlainTextChange_Content { func createAppendTextChange(text string) proto.Marshaler {
return &testchangepb.PlainTextChange_Content{ return &testchanges.PlainTextChangeData{
Value: &testchangepb.PlainTextChange_Content_TextAppend{ Content: []*testchanges.PlainTextChangeContent{
TextAppend: &testchangepb.PlainTextChange_TextAppend{ createAppendTextChangeContent(text),
},
}
}
func createAppendTextChangeContent(text string) *testchanges.PlainTextChangeContent {
return &testchanges.PlainTextChangeContent{
Value: &testchanges.PlainTextChangeContentValueOfTextAppend{
TextAppend: &testchanges.PlainTextChangeTextAppend{
Text: text, Text: text,
}, },
}, },

View File

@ -2,16 +2,10 @@ package storage
import ( import (
"context" "context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/etc" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
) )
var CName = "storage" var CName = "storage"
@ -38,10 +32,10 @@ type service struct {
importedACLSyncData ImportedACLSyncData importedACLSyncData ImportedACLSyncData
} }
func (s *service) Init(ctx context.Context, a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
s.storageProvider = storage.NewInMemoryTreeStorageProvider() s.storageProvider = storage.NewInMemoryTreeStorageProvider()
// importing hardcoded acl list, check that the keys there are correct // importing hardcoded acl list, check that the keys there are correct
return s.importACLList(a) return nil
} }
func (s *service) Storage(treeId string) (storage.Storage, error) { func (s *service) Storage(treeId string) (storage.Storage, error) {
@ -52,12 +46,12 @@ func (s *service) AddStorage(id string, st storage.Storage) error {
return s.storageProvider.AddStorage(id, st) return s.storageProvider.AddStorage(id, st)
} }
func (s *service) CreateTreeStorage(treeId string, header *aclpb.Header, changes []*aclpb.RawChange) (storage.TreeStorage, error) { func (s *service) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (storage.TreeStorage, error) {
return s.storageProvider.CreateTreeStorage(treeId, header, changes) return s.storageProvider.CreateTreeStorage(payload)
} }
func (s *service) CreateACLListStorage(id string, header *aclpb.Header, records []*aclpb.RawRecord) (storage.ListStorage, error) { func (s *service) CreateACLListStorage(payload storage.ACLListStorageCreatePayload) (storage.ListStorage, error) {
return s.storageProvider.CreateACLListStorage(id, header, records) return s.storageProvider.CreateACLListStorage(payload)
} }
func (s *service) Name() (name string) { func (s *service) Name() (name string) {
@ -75,62 +69,3 @@ func (s *service) Run(ctx context.Context) (err error) {
func (s service) Close(ctx context.Context) (err error) { func (s service) Close(ctx context.Context) (err error) {
return nil return nil
} }
func (s *service) importACLList(a *app.App) (err error) {
path := fmt.Sprintf("%s/%s", etc.Path(), "acl.yml")
st, err := acllistbuilder.NewACLListStorageBuilderFromFile(path)
if err != nil {
return err
}
id, err := st.ID()
if err != nil {
return err
}
header, err := st.Header()
if err != nil {
return err
}
// checking that acl list contains all the needed permissions for all our nodes
err = s.checkActualNodesPermissions(st, a)
if err != nil {
return err
}
s.importedACLSyncData = ImportedACLSyncData{
Id: id,
Header: header,
Records: st.GetRawRecords(),
}
log.Infof("imported ACLList with id %s", id)
return s.storageProvider.AddStorage(id, st)
}
func (s *service) checkActualNodesPermissions(st *acllistbuilder.ACLListStorageBuilder, a *app.App) error {
nodes := a.MustComponent(node.CName).(node.Service)
acc := a.MustComponent(account.CName).(account.Service)
aclList, err := list.BuildACLListWithIdentity(acc.Account(), st)
if err != nil {
return err
}
state := aclList.ACLState()
// checking own state
if state.GetUserStates()[acc.Account().Identity].Permissions != aclpb.ACLChange_Admin {
return fmt.Errorf("own node with signing key %s should be admin", acc.Account().Identity)
}
// checking other nodes' states
for _, n := range nodes.Nodes() {
if state.GetUserStates()[n.SigningKeyString].Permissions != aclpb.ACLChange_Admin {
return fmt.Errorf("other node with signing key %s should be admin", n.SigningKeyString)
}
}
return nil
}

View File

@ -2,33 +2,32 @@ package treecache
import ( import (
"context" "context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage" aclstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/storage"
"go.uber.org/zap" "go.uber.org/zap"
) )
const CName = "treecache" const CName = "treecache"
// TODO: add context type ObjFunc = func(obj interface{}) error
type ACLTreeFunc = func(tree acltree.ACLTree) error
type ChangeBuildFunc = func(builder acltree.ChangeBuilder) error
var log = logger.NewNamed("treecache") var log = logger.NewNamed("treecache")
type Service interface { type Service interface {
Do(ctx context.Context, treeId string, f ACLTreeFunc) error Do(ctx context.Context, id string, f ObjFunc) error
Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error Add(ctx context.Context, id string, payload any) error
Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error
} }
type service struct { type service struct {
treeProvider treestorage.Provider storage storage.Service
account account.Service account account.Service
cache ocache.OCache cache ocache.OCache
} }
@ -37,53 +36,48 @@ func New() app.ComponentRunnable {
return &service{} return &service{}
} }
func (s *service) Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error { func (s *service) Do(ctx context.Context, treeId string, f ObjFunc) error {
acc := s.account.Account()
st, err := acltree.CreateNewTreeStorageWithACL(acc, build, s.treeProvider.CreateTreeStorage)
if err != nil {
return err
}
id, err := st.TreeID()
if err != nil {
return err
}
return s.Do(ctx, id, f)
}
func (s *service) Do(ctx context.Context, treeId string, f ACLTreeFunc) error {
log. log.
With(zap.String("treeId", treeId)). With(zap.String("treeId", treeId)).
Debug("requesting tree from cache to perform operation") Debug("requesting tree from cache to perform operation")
tree, err := s.cache.Get(ctx, treeId) t, err := s.cache.Get(ctx, treeId)
defer s.cache.Release(treeId) defer s.cache.Release(treeId)
if err != nil { if err != nil {
return err return err
} }
aclTree := tree.(acltree.ACLTree) return f(t)
aclTree.Lock()
defer aclTree.Unlock()
return f(tree.(acltree.ACLTree))
} }
func (s *service) Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error { func (s *service) Add(ctx context.Context, treeId string, payload any) error {
switch pl := payload.(type) {
case aclstorage.TreeStorageCreatePayload:
log. log.
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(changes))). With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Changes))).
Debug("adding tree with changes") Debug("adding Tree with changes")
_, err := s.treeProvider.CreateTreeStorage(treeId, header, changes) _, err := s.storage.CreateTreeStorage(payload.(aclstorage.TreeStorageCreatePayload))
if err != nil { if err != nil {
return err return err
} }
return s.Do(ctx, treeId, f) case aclstorage.ACLListStorageCreatePayload:
log.
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Records))).
Debug("adding ACLList with records")
_, err := s.storage.CreateACLListStorage(payload.(aclstorage.ACLListStorageCreatePayload))
if err != nil {
return err
}
}
return nil
} }
func (s *service) Init(a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
s.cache = ocache.New(s.loadTree) s.cache = ocache.New(s.loadTree)
s.account = a.MustComponent(account.CName).(account.Service) s.account = a.MustComponent(account.CName).(account.Service)
s.treeProvider = treestorage.NewInMemoryTreeStorageProvider() s.storage = a.MustComponent(storage.CName).(storage.Service)
// TODO: for test we should load some predefined keys // TODO: for test we should load some predefined keys
return nil return nil
} }
@ -101,11 +95,33 @@ func (s *service) Close(ctx context.Context) (err error) {
} }
func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error) { func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error) {
tree, err := s.treeProvider.TreeStorage(id) t, err := s.storage.Storage(id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TODO: should probably accept nil listeners header, err := t.Header()
aclTree, err := acltree.BuildACLTree(tree, s.account.Account(), acltree.NoOpListener{}) if err != nil {
return aclTree, err return nil, err
}
switch header.DocType { // handler
case aclpb.Header_ACL:
return list.BuildACLListWithIdentity(s.account.Account(), t.(aclstorage.ListStorage))
case aclpb.Header_DocTree:
break
default:
return nil, fmt.Errorf("incorrect type")
}
log.Info("got header", zap.String("header", header.String()))
var objTree tree.ObjectTree
err = s.Do(ctx, header.AclListId, func(obj interface{}) error {
aclList := obj.(list.ACLList)
objTree, err = tree.BuildObjectTree(t.(aclstorage.TreeStorage), nil, aclList)
if err != nil {
return err
}
return nil
})
return objTree, err
} }

View File

@ -2,7 +2,7 @@ syntax = "proto3";
package anytype; package anytype;
option go_package = "/syncproto"; option go_package = "/syncproto";
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto"; import "pkg/acl/aclrecordproto/aclpb/protos/aclrecordproto.proto";
message Message { message Message {
Header header = 1; Header header = 1;