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)
# TODO: folders were changed, so we should update Makefile and protos generation
proto:
@echo 'Generating protobuf packages (Go)...'
# Uncomment if needed
@$(eval ROOT_PKG := pkg)
@$(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_TEST_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges)
@$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types)
@$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types)
@$(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))
@$(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_TREE_CHANGES := M$(P_TREE_CHANGES_PATH_PB)/protos/treechange.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_TREE_CHANGES_PATH_PB))
# use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT))
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_RECORDS_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
$(eval PKGMAP := $$(P_ACL_CHANGES))
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/proto/*.proto
$(eval PKGMAP := $$(P_TREE_CHANGES))
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. common/commonspace/spacesyncproto/protos/*.proto
build:
@$(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

View File

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

View File

@ -5,7 +5,7 @@ package spacesyncproto
import (
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"
io "io"
math "math"
@ -322,7 +322,7 @@ func (m *HeadSyncResponse) GetResults() []*HeadSyncResult {
type ObjectSyncMessage struct {
SpaceId string `protobuf:"bytes,1,opt,name=spaceId,proto3" json:"spaceId,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"`
TrackingId string `protobuf:"bytes,5,opt,name=trackingId,proto3" json:"trackingId,omitempty"`
}
@ -374,7 +374,7 @@ func (m *ObjectSyncMessage) GetContent() *ObjectSyncContentValue {
return nil
}
func (m *ObjectSyncMessage) GetTreeHeader() *aclpb.TreeHeader {
func (m *ObjectSyncMessage) GetTreeHeader() *treechangeproto.RootChange {
if m != nil {
return m.TreeHeader
}
@ -510,7 +510,7 @@ func (*ObjectSyncContentValue) XXX_OneofWrappers() []interface{} {
// ObjectHeadUpdate is a message sent on document head update
type ObjectHeadUpdate struct {
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"`
}
@ -554,7 +554,7 @@ func (m *ObjectHeadUpdate) GetHeads() []string {
return nil
}
func (m *ObjectHeadUpdate) GetChanges() []*aclpb.RawTreeChangeWithId {
func (m *ObjectHeadUpdate) GetChanges() []*treechangeproto.RawTreeChangeWithId {
if m != nil {
return m.Changes
}
@ -571,7 +571,7 @@ func (m *ObjectHeadUpdate) GetSnapshotPath() []string {
// ObjectHeadUpdate is a message sent when document needs full sync
type ObjectFullSyncRequest struct {
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"`
}
@ -615,7 +615,7 @@ func (m *ObjectFullSyncRequest) GetHeads() []string {
return nil
}
func (m *ObjectFullSyncRequest) GetChanges() []*aclpb.RawTreeChangeWithId {
func (m *ObjectFullSyncRequest) GetChanges() []*treechangeproto.RawTreeChangeWithId {
if m != nil {
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
type ObjectFullSyncResponse struct {
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"`
}
@ -676,7 +676,7 @@ func (m *ObjectFullSyncResponse) GetHeads() []string {
return nil
}
func (m *ObjectFullSyncResponse) GetChanges() []*aclpb.RawTreeChangeWithId {
func (m *ObjectFullSyncResponse) GetChanges() []*treechangeproto.RawTreeChangeWithId {
if m != nil {
return m.Changes
}
@ -734,6 +734,82 @@ func (m *ObjectErrorResponse) GetError() string {
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() {
proto.RegisterEnum("anySpace.ErrCodes", ErrCodes_name, ErrCodes_value)
proto.RegisterType((*HeadSyncRange)(nil), "anySpace.HeadSyncRange")
@ -747,6 +823,7 @@ func init() {
proto.RegisterType((*ObjectFullSyncRequest)(nil), "anySpace.ObjectFullSyncRequest")
proto.RegisterType((*ObjectFullSyncResponse)(nil), "anySpace.ObjectFullSyncResponse")
proto.RegisterType((*ObjectErrorResponse)(nil), "anySpace.ObjectErrorResponse")
proto.RegisterType((*SpaceHeader)(nil), "anySpace.SpaceHeader")
}
func init() {
@ -754,52 +831,57 @@ func init() {
}
var fileDescriptor_5855f4ef9cf24cdb = []byte{
// 712 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4b, 0x6f, 0xd3, 0x40,
0x10, 0xf6, 0xa6, 0x79, 0x75, 0xd2, 0x47, 0x58, 0x68, 0x31, 0x41, 0xa4, 0xc1, 0xa7, 0x08, 0xa4,
0xa4, 0x0a, 0x17, 0x44, 0xb9, 0xd0, 0x2a, 0x55, 0x22, 0xc4, 0x43, 0x5b, 0x0a, 0x12, 0xe2, 0xb2,
0xb5, 0xb7, 0x49, 0xa8, 0x63, 0x1b, 0xef, 0x86, 0xd2, 0x1b, 0x17, 0x38, 0x23, 0xfe, 0x12, 0x17,
0x8e, 0x15, 0x27, 0x8e, 0xa8, 0xfd, 0x23, 0x68, 0xc7, 0x76, 0x5e, 0xb8, 0xe5, 0xd6, 0x43, 0xec,
0x9d, 0xd9, 0xf9, 0xbe, 0xfd, 0xf6, 0x9b, 0xf5, 0x06, 0x1e, 0xda, 0xfe, 0x70, 0xe8, 0x7b, 0xcd,
0xe8, 0x25, 0x03, 0x6e, 0x8b, 0x26, 0x3e, 0xe5, 0x89, 0x67, 0x07, 0xa1, 0xaf, 0xfc, 0x26, 0x3e,
0xe5, 0x24, 0xdb, 0xc0, 0x04, 0x2d, 0x72, 0xef, 0x64, 0x4f, 0xe7, 0x2a, 0x9b, 0xc1, 0x51, 0xaf,
0xc9, 0x6d, 0x57, 0xff, 0xec, 0x3e, 0xf7, 0x7a, 0x42, 0xea, 0x61, 0x70, 0x90, 0x40, 0x27, 0xf9,
0x08, 0x6b, 0x75, 0x61, 0xb9, 0x23, 0xb8, 0xb3, 0x77, 0xe2, 0xd9, 0x4c, 0xe7, 0x29, 0x85, 0xec,
0x61, 0xe8, 0x0f, 0x4d, 0x52, 0x23, 0xf5, 0x2c, 0xc3, 0x31, 0x5d, 0x81, 0x8c, 0xf2, 0xcd, 0x0c,
0x66, 0x32, 0xca, 0xa7, 0x37, 0x20, 0xe7, 0x0e, 0x86, 0x03, 0x65, 0x2e, 0xd4, 0x48, 0x7d, 0x99,
0x45, 0x81, 0x75, 0x0c, 0x2b, 0x63, 0x2a, 0x21, 0x47, 0xae, 0xd2, 0x5c, 0x7d, 0x2e, 0xfb, 0xc8,
0xb5, 0xc4, 0x70, 0x4c, 0xb7, 0xa0, 0x28, 0x5c, 0x31, 0x14, 0x9e, 0x92, 0x66, 0xa6, 0xb6, 0x50,
0x2f, 0xb5, 0x36, 0x1a, 0x89, 0xfe, 0xc6, 0x2c, 0xbe, 0x1d, 0xd5, 0xb1, 0x31, 0x40, 0x2f, 0x6c,
0xfb, 0x23, 0x6f, 0xbc, 0x30, 0x06, 0xd6, 0x16, 0xac, 0xa5, 0x02, 0xb5, 0xee, 0x81, 0x83, 0xab,
0x2f, 0xb2, 0xcc, 0xc0, 0x41, 0x3d, 0x82, 0x3b, 0xb8, 0x93, 0x45, 0x86, 0x63, 0xeb, 0x1d, 0xac,
0x4e, 0xc0, 0x1f, 0x46, 0x42, 0x2a, 0x6a, 0x42, 0x01, 0x2d, 0xee, 0x26, 0xd8, 0x24, 0xa4, 0x4d,
0xc8, 0x87, 0xe8, 0x5e, 0x2c, 0xfd, 0x66, 0x8a, 0x74, 0x3d, 0xcf, 0xe2, 0x32, 0x6b, 0x17, 0xca,
0x53, 0xd2, 0x02, 0xdf, 0x93, 0x82, 0xb6, 0xa0, 0x10, 0xa2, 0x4c, 0x69, 0x12, 0x64, 0x31, 0x2f,
0x32, 0x80, 0x25, 0x85, 0xd6, 0x2f, 0x02, 0xd7, 0x5e, 0x1c, 0xbc, 0x17, 0xb6, 0xd2, 0xb3, 0xcf,
0x84, 0x94, 0xbc, 0x27, 0x2e, 0x11, 0xfa, 0x08, 0x0a, 0xb6, 0xef, 0x29, 0xe1, 0x29, 0xdc, 0x6c,
0xa9, 0x55, 0x9b, 0xac, 0x31, 0xe1, 0xd9, 0x89, 0x4a, 0x5e, 0x73, 0x77, 0x24, 0x58, 0x02, 0xa0,
0x4d, 0x00, 0x15, 0x0a, 0xa1, 0xa5, 0x88, 0x10, 0x9d, 0x2e, 0xb5, 0x56, 0x1b, 0xdc, 0x76, 0x1b,
0xaf, 0xc6, 0x69, 0x36, 0x55, 0x42, 0xd7, 0x21, 0xaf, 0xa3, 0xae, 0x63, 0x66, 0x51, 0x45, 0x1c,
0xd1, 0xaa, 0x26, 0xe2, 0xf6, 0xd1, 0xc0, 0xeb, 0x75, 0x1d, 0x33, 0x87, 0x73, 0x53, 0x19, 0xeb,
0x47, 0x06, 0xd6, 0xd3, 0xc5, 0xd0, 0xc7, 0x00, 0xba, 0x3b, 0xfb, 0x81, 0xc3, 0x95, 0xc0, 0xcd,
0x95, 0x5a, 0x95, 0xf9, 0x2d, 0x74, 0xc6, 0x15, 0x1d, 0x83, 0x4d, 0xd5, 0xd3, 0xa7, 0xb0, 0x7a,
0x38, 0x72, 0xdd, 0xa9, 0x9e, 0xc6, 0x2e, 0x6c, 0xcc, 0x53, 0xec, 0xce, 0x96, 0x75, 0x0c, 0x36,
0x8f, 0xa4, 0xcf, 0xa1, 0x3c, 0x49, 0x45, 0x2d, 0x8c, 0x4d, 0xa9, 0x5d, 0xcc, 0x16, 0xd5, 0x75,
0x0c, 0xf6, 0x0f, 0x96, 0xb6, 0x61, 0x59, 0x84, 0xa1, 0x1f, 0x8e, 0xc9, 0xb2, 0x48, 0x76, 0x67,
0x9e, 0xac, 0x3d, 0x5d, 0xd4, 0x31, 0xd8, 0x2c, 0x6a, 0xbb, 0x00, 0xb9, 0x8f, 0xda, 0x2a, 0xeb,
0x33, 0x81, 0xf2, 0xbc, 0x1f, 0xfa, 0x43, 0xd1, 0x7e, 0x44, 0x27, 0x6c, 0x91, 0x45, 0x81, 0x3e,
0x79, 0xf1, 0xd7, 0x1f, 0x9f, 0x5f, 0x13, 0xdb, 0xca, 0xf8, 0xb1, 0xee, 0xec, 0x0e, 0x4e, 0xbd,
0x19, 0xa8, 0x7e, 0xd7, 0x61, 0x49, 0x21, 0xb5, 0x60, 0x49, 0x7a, 0x3c, 0x90, 0x7d, 0x5f, 0xbd,
0xe4, 0xaa, 0x6f, 0x2e, 0x20, 0xe1, 0x4c, 0xce, 0xfa, 0x42, 0x60, 0x2d, 0xd5, 0xcf, 0x2b, 0xd6,
0xf1, 0x95, 0x24, 0x07, 0x6a, 0xbe, 0x13, 0x57, 0x2c, 0xe4, 0x3e, 0x5c, 0x4f, 0x69, 0xa2, 0x16,
0x81, 0x4d, 0x8c, 0xbf, 0xd6, 0x28, 0xb8, 0x57, 0x81, 0x62, 0x3b, 0x0c, 0x77, 0x7c, 0x47, 0x48,
0xba, 0x02, 0xb0, 0xef, 0x89, 0x4f, 0x81, 0xb0, 0x95, 0x70, 0xca, 0x46, 0xeb, 0x3b, 0x81, 0x1c,
0x1e, 0x0a, 0xfa, 0x04, 0x8a, 0xc9, 0xe5, 0x40, 0x6f, 0xa5, 0x5d, 0x18, 0x68, 0x78, 0xa5, 0x92,
0x7a, 0x97, 0x44, 0xcb, 0xef, 0x42, 0x7e, 0x4f, 0x85, 0x82, 0x0f, 0xe9, 0xed, 0xb4, 0xdb, 0x20,
0xbe, 0x55, 0x2a, 0x97, 0x4d, 0xd6, 0xc9, 0x26, 0xd9, 0xde, 0xfa, 0x79, 0x56, 0x25, 0xa7, 0x67,
0x55, 0xf2, 0xe7, 0xac, 0x4a, 0xbe, 0x9d, 0x57, 0x8d, 0xd3, 0xf3, 0xaa, 0xf1, 0xfb, 0xbc, 0x6a,
0xbc, 0xbd, 0xfb, 0xdf, 0xff, 0xb0, 0x83, 0x3c, 0xbe, 0x1e, 0xfc, 0x0d, 0x00, 0x00, 0xff, 0xff,
0x93, 0x27, 0x56, 0x41, 0xef, 0x06, 0x00, 0x00,
// 797 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xcd, 0x8e, 0xe3, 0x44,
0x10, 0xb6, 0x33, 0x99, 0x49, 0x52, 0x99, 0x99, 0x0d, 0x0d, 0x3b, 0x98, 0x00, 0xd9, 0xe0, 0x03,
0x8a, 0x40, 0x4a, 0x50, 0x90, 0x10, 0x30, 0x5c, 0xd8, 0x51, 0x46, 0x89, 0x56, 0xfc, 0xa8, 0x67,
0x17, 0x24, 0xc4, 0xa5, 0xd7, 0xae, 0x4d, 0xcc, 0xda, 0x6e, 0xe3, 0xee, 0xb0, 0xe4, 0x09, 0xb8,
0x80, 0x84, 0x78, 0x03, 0x9e, 0x85, 0x0b, 0xc7, 0x3d, 0xc2, 0x0d, 0xcd, 0xbc, 0x08, 0xea, 0xb2,
0x1d, 0x3b, 0xc1, 0xbb, 0x1c, 0xf7, 0x12, 0x77, 0x7d, 0x5d, 0xf5, 0xf5, 0xd7, 0x55, 0xd5, 0x15,
0xf8, 0xd0, 0x93, 0x51, 0x24, 0xe3, 0x49, 0xf6, 0x51, 0x89, 0xf0, 0x70, 0x42, 0xbf, 0x6a, 0x13,
0x7b, 0x49, 0x2a, 0xb5, 0x9c, 0xd0, 0xaf, 0x2a, 0xd1, 0x31, 0x01, 0xac, 0x2d, 0xe2, 0xcd, 0x95,
0xc1, 0xfa, 0x93, 0xe4, 0xf1, 0x72, 0x22, 0xbc, 0x70, 0xa2, 0x53, 0x44, 0x6f, 0x25, 0xe2, 0x25,
0xee, 0x44, 0x96, 0x70, 0x16, 0xea, 0x2e, 0xe0, 0x64, 0x8e, 0xc2, 0xbf, 0xda, 0xc4, 0x1e, 0x37,
0x30, 0x63, 0xd0, 0x7c, 0x94, 0xca, 0xc8, 0xb1, 0x87, 0xf6, 0xa8, 0xc9, 0x69, 0xcd, 0x4e, 0xa1,
0xa1, 0xa5, 0xd3, 0x20, 0xa4, 0xa1, 0x25, 0x7b, 0x05, 0x0e, 0xc3, 0x20, 0x0a, 0xb4, 0x73, 0x30,
0xb4, 0x47, 0x27, 0x3c, 0x33, 0xdc, 0x27, 0x70, 0xba, 0xa5, 0x42, 0xb5, 0x0e, 0xb5, 0xe1, 0x5a,
0x09, 0xb5, 0x22, 0xae, 0x63, 0x4e, 0x6b, 0x76, 0x0e, 0x6d, 0x0c, 0x31, 0xc2, 0x58, 0x2b, 0xa7,
0x31, 0x3c, 0x18, 0x75, 0xa7, 0x77, 0xc6, 0x85, 0xfc, 0xf1, 0x6e, 0xfc, 0x2c, 0xf3, 0xe3, 0xdb,
0x00, 0x73, 0xb0, 0x27, 0xd7, 0xf1, 0xf6, 0x60, 0x32, 0xdc, 0x73, 0xb8, 0x5d, 0x1b, 0x68, 0x74,
0x07, 0x3e, 0x9d, 0xde, 0xe1, 0x8d, 0xc0, 0x27, 0x3d, 0x28, 0x7c, 0xba, 0x49, 0x87, 0xd3, 0xda,
0xfd, 0x16, 0x6e, 0x95, 0xc1, 0xdf, 0xaf, 0x51, 0x69, 0xe6, 0x40, 0x8b, 0x32, 0xbc, 0x28, 0x62,
0x0b, 0x93, 0x4d, 0xe0, 0x28, 0x35, 0x59, 0x2a, 0xa4, 0xbf, 0x5a, 0x23, 0xdd, 0xec, 0xf3, 0xdc,
0xcd, 0xbd, 0x84, 0x5e, 0x45, 0x5a, 0x22, 0x63, 0x85, 0x6c, 0x0a, 0xad, 0x94, 0x64, 0x2a, 0xc7,
0x26, 0x16, 0xe7, 0x59, 0x09, 0xe0, 0x85, 0xa3, 0xfb, 0xb7, 0x0d, 0x2f, 0x7d, 0xf1, 0xf0, 0x3b,
0xf4, 0xb4, 0xd9, 0xfd, 0x0c, 0x95, 0x12, 0x4b, 0x7c, 0x8e, 0xd0, 0x8f, 0xa1, 0xe5, 0xc9, 0x58,
0x63, 0xac, 0xe9, 0xb2, 0xdd, 0xe9, 0xb0, 0x3c, 0xa3, 0xe4, 0xb9, 0xc8, 0x5c, 0xbe, 0x12, 0xe1,
0x1a, 0x79, 0x11, 0xc0, 0x3e, 0x00, 0x30, 0x6d, 0x62, 0xa4, 0x60, 0x4a, 0x99, 0xee, 0x4e, 0xcf,
0xc6, 0x95, 0xce, 0xe1, 0x52, 0xea, 0x0b, 0x5a, 0xf2, 0x8a, 0x27, 0x3b, 0x83, 0x23, 0x63, 0x2d,
0x7c, 0xa7, 0x49, 0x62, 0x72, 0x8b, 0x0d, 0x0c, 0x9f, 0xf0, 0x1e, 0x07, 0xf1, 0x72, 0xe1, 0x3b,
0x87, 0xb4, 0x57, 0x41, 0xdc, 0x3f, 0x1a, 0x70, 0x56, 0xaf, 0x89, 0x7d, 0x02, 0x60, 0x8a, 0xf4,
0x20, 0xf1, 0x85, 0x46, 0xba, 0x63, 0x77, 0xda, 0xdf, 0xbf, 0xc9, 0x7c, 0xeb, 0x31, 0xb7, 0x78,
0xc5, 0x9f, 0xdd, 0x83, 0x5b, 0x8f, 0xd6, 0x61, 0x58, 0x29, 0x6d, 0x9e, 0x8c, 0x3b, 0xfb, 0x14,
0x97, 0xbb, 0x6e, 0x73, 0x8b, 0xef, 0x47, 0xb2, 0xcf, 0xa1, 0x57, 0x42, 0x59, 0x25, 0xf3, 0xdc,
0x0c, 0x9f, 0xcd, 0x96, 0xf9, 0xcd, 0x2d, 0xfe, 0x9f, 0x58, 0x36, 0x83, 0x13, 0x4c, 0x53, 0x99,
0x6e, 0xc9, 0x9a, 0x44, 0xf6, 0xe6, 0x3e, 0xd9, 0xac, 0xea, 0x34, 0xb7, 0xf8, 0x6e, 0xd4, 0xdd,
0x16, 0x1c, 0xfe, 0x60, 0x52, 0xe5, 0xfe, 0x64, 0x43, 0x6f, 0x3f, 0x1f, 0xe6, 0xbd, 0x98, 0x7c,
0x64, 0x8d, 0xd6, 0xe1, 0x99, 0xc1, 0x3e, 0x82, 0x56, 0x56, 0xc9, 0xf2, 0x05, 0x56, 0xab, 0x2b,
0x9e, 0xdc, 0x4f, 0x11, 0xb3, 0x02, 0x7f, 0x1d, 0xe8, 0xd5, 0xc2, 0xe7, 0x85, 0x3f, 0x73, 0xe1,
0x58, 0xc5, 0x22, 0x51, 0x2b, 0xa9, 0xbf, 0x14, 0x7a, 0xe5, 0x1c, 0x10, 0xef, 0x0e, 0xe6, 0xfe,
0x6c, 0xc3, 0xed, 0xda, 0xb4, 0xbe, 0x18, 0x39, 0xbf, 0xd8, 0x45, 0x7b, 0xed, 0xd7, 0xe5, 0xc5,
0xe8, 0x79, 0x17, 0x5e, 0xae, 0xa9, 0xac, 0xd1, 0x42, 0x95, 0xcd, 0x5f, 0x72, 0x66, 0xb8, 0xbf,
0xdb, 0xd0, 0xa5, 0x6e, 0xc8, 0xdf, 0x58, 0x1f, 0xda, 0x81, 0x8f, 0xb1, 0x0e, 0xf4, 0x26, 0x9f,
0xaa, 0x5b, 0x9b, 0xbd, 0x01, 0x1d, 0x1d, 0x44, 0xa8, 0xb4, 0x88, 0x12, 0x6a, 0xf4, 0x03, 0x5e,
0x02, 0x66, 0x97, 0x86, 0xc3, 0xfd, 0x4d, 0x92, 0x35, 0x6e, 0x87, 0x97, 0x00, 0x7b, 0x1b, 0x4e,
0x53, 0x4c, 0xc2, 0xc0, 0x13, 0x3a, 0x90, 0xf1, 0x3d, 0xdc, 0x50, 0x3b, 0x36, 0xf9, 0x1e, 0x6a,
0x26, 0xa8, 0x42, 0xcc, 0x5e, 0xf1, 0x31, 0xa7, 0xf5, 0x3b, 0x7d, 0x68, 0xcf, 0xd2, 0xf4, 0x42,
0xfa, 0xa8, 0xd8, 0x29, 0xc0, 0x83, 0x18, 0x7f, 0x4c, 0xd0, 0xd3, 0xe8, 0xf7, 0xac, 0xe9, 0x6f,
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) {
@ -1386,6 +1468,60 @@ func (m *ObjectErrorResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
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 {
offset -= sovSpacesync(v)
base := offset
@ -1671,6 +1807,33 @@ func (m *ObjectErrorResponse) Size() (n int) {
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) {
return (math_bits.Len64(x|1) + 6) / 7
}
@ -2362,7 +2525,7 @@ func (m *ObjectSyncMessage) Unmarshal(dAtA []byte) error {
return io.ErrUnexpectedEOF
}
if m.TreeHeader == nil {
m.TreeHeader = &aclpb.TreeHeader{}
m.TreeHeader = &treechangeproto.RootChange{}
}
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
@ -2733,7 +2896,7 @@ func (m *ObjectHeadUpdate) Unmarshal(dAtA []byte) error {
if postIndex > l {
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 {
return err
}
@ -2881,7 +3044,7 @@ func (m *ObjectFullSyncRequest) Unmarshal(dAtA []byte) error {
if postIndex > l {
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 {
return err
}
@ -3029,7 +3192,7 @@ func (m *ObjectFullSyncResponse) Unmarshal(dAtA []byte) error {
if postIndex > l {
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 {
return err
}
@ -3169,6 +3332,194 @@ func (m *ObjectErrorResponse) Unmarshal(dAtA []byte) error {
}
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) {
l := len(dAtA)
iNdEx := 0

View File

@ -4,7 +4,7 @@ import (
"context"
"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/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/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/spacesyncproto"
"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"
)

View File

@ -4,7 +4,7 @@ import (
"context"
"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/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/storage"
"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
require (
github.com/anytypeio/go-chash v0.0.0-20220629194632-4ad1154fe232
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab
github.com/cespare/xxhash v1.1.0
github.com/goccy/go-graphviz v0.0.9
@ -16,6 +17,7 @@ require (
github.com/multiformats/go-multihash v0.1.0
github.com/stretchr/testify v1.8.0
github.com/zeebo/blake3 v0.2.3
github.com/zeebo/errs v1.3.0
go.uber.org/zap v1.21.0
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/yaml.v3 v3.0.1
@ -24,7 +26,6 @@ require (
require (
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/btcec/v2 v2.1.3 // 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/fogleman/gg v1.3.0 // 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/libp2p/go-buffer-pool v0.0.2 // 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/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // 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/multierr v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // 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/yaml.v2 v2.4.0 // 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/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/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/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
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/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
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/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
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-20191204190536-9bdfabe68543/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 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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"
"fmt"
"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/util/keys"
"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 {
Identity string
Permission aclpb.ACLUserPermissions
Permission aclrecordproto.ACLUserPermissions
}
type ACLState struct {
currentReadKeyHash uint64
userReadKeys map[uint64]*symmetric.Key
userStates map[string]*aclpb.ACLUserState
userInvites map[string]*aclpb.ACLUserInvite
userStates map[string]*aclrecordproto.ACLUserState
userInvites map[string]*aclrecordproto.ACLUserInvite
signingPubKeyDecoder keys.Decoder
encryptionKey encryptionkey.PrivKey
@ -56,8 +56,8 @@ func newACLStateWithIdentity(
identity: identity,
encryptionKey: encryptionKey,
userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclpb.ACLUserState),
userInvites: make(map[string]*aclpb.ACLUserInvite),
userStates: make(map[string]*aclrecordproto.ACLUserState),
userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
signingPubKeyDecoder: decoder,
permissionsAtRecord: make(map[string][]UserPermissionPair),
keychain: common.NewKeychain(),
@ -68,8 +68,8 @@ func newACLState(decoder keys.Decoder) *ACLState {
return &ACLState{
signingPubKeyDecoder: decoder,
userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclpb.ACLUserState),
userInvites: make(map[string]*aclpb.ACLUserInvite),
userStates: make(map[string]*aclrecordproto.ACLUserState),
userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
permissionsAtRecord: make(map[string][]UserPermissionPair),
keychain: common.NewKeychain(),
}
@ -106,8 +106,8 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
return UserPermissionPair{}, ErrNoSuchUser
}
func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
aclData := &aclpb.ACLData{}
func (st *ACLState) applyRecord(record *aclrecordproto.ACLRecord) (err error) {
aclData := &aclrecordproto.ACLData{}
err = proto.Unmarshal(record.Data, aclData)
if err != nil {
@ -126,11 +126,11 @@ func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
var (
change = recordWrapper.Content
aclData = &aclpb.ACLData{}
aclData = &aclrecordproto.ACLData{}
)
if recordWrapper.Model != nil {
aclData = recordWrapper.Model.(*aclpb.ACLData)
aclData = recordWrapper.Model.(*aclrecordproto.ACLData)
} else {
err = proto.Unmarshal(change.Data, aclData)
if err != nil {
@ -158,7 +158,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
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() {
if err != nil {
return
@ -176,7 +176,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, iden
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)
return
}
@ -192,7 +192,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, iden
return nil
}
func (st *ACLState) applyChangeContent(ch *aclpb.ACLContentValue) error {
func (st *ACLState) applyChangeContent(ch *aclrecordproto.ACLContentValue) error {
switch {
case ch.GetUserPermissionChange() != nil:
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)
state, exists := st.userStates[chIdentity]
if !exists {
@ -222,12 +222,12 @@ func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLUserPermissionChange)
return nil
}
func (st *ACLState) applyUserInvite(ch *aclpb.ACLUserInvite) error {
func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error {
st.userInvites[ch.InviteId] = ch
return nil
}
func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
invite, exists := st.userInvites[ch.UserInviteId]
if !exists {
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
userState := &aclpb.ACLUserState{
userState := &aclrecordproto.ACLUserState{
Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey,
EncryptedReadKeys: ch.EncryptedReadKeys,
@ -277,13 +277,13 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
return nil
}
func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
func (st *ACLState) applyUserAdd(ch *aclrecordproto.ACLUserAdd) error {
chIdentity := string(ch.Identity)
if _, exists := st.userStates[chIdentity]; exists {
return ErrUserAlreadyExists
}
st.userStates[chIdentity] = &aclpb.ACLUserState{
st.userStates[chIdentity] = &aclrecordproto.ACLUserState{
Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey,
Permissions: ch.Permissions,
@ -304,7 +304,7 @@ func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
return nil
}
func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error {
chIdentity := string(ch.Identity)
if chIdentity == st.identity {
return ErrDocumentForbidden
@ -338,7 +338,7 @@ func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
return nil
}
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLUserConfirm) error {
func (st *ACLState) applyUserConfirm(ch *aclrecordproto.ACLUserConfirm) error {
chIdentity := string(ch.Identity)
state, exists := st.userStates[chIdentity]
if !exists {
@ -365,7 +365,7 @@ func (st *ACLState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e
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)]
if !exists {
return false
@ -374,17 +374,17 @@ func (st *ACLState) hasPermission(identity []byte, permission aclpb.ACLUserPermi
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
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
userAdd := data.GetAclContent()[0].GetUserAdd()
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
}

View File

@ -2,7 +2,7 @@ package list
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/aclrecordproto/aclpb"
"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/symmetric"

View File

@ -5,7 +5,7 @@ import (
"errors"
"fmt"
"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/storage"
"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) {
header, err := storage.Header()
header, err := storage.Root()
if err != nil {
return
}

View File

@ -1,7 +1,7 @@
package list
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/util/keys/asymmetric/signingkey"
"github.com/stretchr/testify/assert"

View File

@ -1,19 +1,19 @@
package list
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"
)
type ACLRecord struct {
Id string
Content *aclpb.ACLRecord
Content *aclrecordproto.ACLRecord
Identity string
Model interface{}
Sign []byte
}
func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
func NewRecord(id string, aclRecord *aclrecordproto.ACLRecord) *ACLRecord {
return &ACLRecord{
Id: id,
Content: aclRecord,
@ -21,17 +21,45 @@ func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
}
}
func NewFromRawRecord(rawRec *aclpb.RawACLRecord) (*ACLRecord, error) {
aclRec := &aclpb.ACLRecord{}
err := proto.Unmarshal(rawRec.Payload, aclRec)
func NewFromRawRecord(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) {
rawRec := &aclrecordproto.RawACLRecord{}
err = proto.Unmarshal(rawRecWithId.Payload, rawRec)
if err != nil {
return nil, err
return
}
protoAclRec := &aclrecordproto.ACLRecord{}
err = proto.Unmarshal(rawRec.Payload, protoAclRec)
if err != nil {
return
}
return &ACLRecord{
Id: rawRec.Id,
Content: aclRec,
Id: rawRecWithId.Id,
Content: protoAclRec,
Sign: rawRec.Signature,
Identity: string(aclRec.Identity),
Identity: string(protoAclRec.Identity),
}, 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 (
"context"
"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"
)
type inMemoryACLListStorage struct {
header *aclpb.ACLHeader
records []*aclpb.RawACLRecord
records []*aclrecordproto.RawACLRecordWithId
id string
sync.RWMutex
@ -18,29 +17,27 @@ type inMemoryACLListStorage struct {
func NewInMemoryACLListStorage(
id string,
header *aclpb.ACLHeader,
records []*aclpb.RawACLRecord) (ListStorage, error) {
records []*aclrecordproto.RawACLRecordWithId) (ListStorage, error) {
return &inMemoryACLListStorage{
id: id,
header: header,
records: records,
RWMutex: sync.RWMutex{},
}, nil
}
func (i *inMemoryACLListStorage) Header() (*aclpb.ACLHeader, error) {
func (i *inMemoryACLListStorage) Root() (*aclrecordproto.RawACLRecordWithId, error) {
i.RLock()
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()
defer i.RUnlock()
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()
defer i.RUnlock()
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")
}
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")
}
@ -63,26 +60,27 @@ func (i *inMemoryACLListStorage) ID() (string, error) {
type inMemoryTreeStorage struct {
id string
header *aclpb.TreeHeader
root *treechangeproto.RawTreeChangeWithId
heads []string
changes map[string]*aclpb.RawTreeChangeWithId
changes map[string]*treechangeproto.RawTreeChangeWithId
sync.RWMutex
}
func NewInMemoryTreeStorage(
treeId string,
header *aclpb.TreeHeader,
root *treechangeproto.RawTreeChangeWithId,
heads []string,
changes []*aclpb.RawTreeChangeWithId) (TreeStorage, error) {
allChanges := make(map[string]*aclpb.RawTreeChangeWithId)
changes []*treechangeproto.RawTreeChangeWithId) (TreeStorage, error) {
allChanges := make(map[string]*treechangeproto.RawTreeChangeWithId)
for _, ch := range changes {
allChanges[ch.Id] = ch
}
allChanges[treeId] = root
return &inMemoryTreeStorage{
id: treeId,
header: header,
root: root,
heads: heads,
changes: allChanges,
RWMutex: sync.RWMutex{},
@ -95,10 +93,10 @@ func (t *inMemoryTreeStorage) ID() (string, error) {
return t.id, nil
}
func (t *inMemoryTreeStorage) Header() (*aclpb.TreeHeader, error) {
func (t *inMemoryTreeStorage) Root() (*treechangeproto.RawTreeChangeWithId, error) {
t.RLock()
defer t.RUnlock()
return t.header, nil
return t.root, nil
}
func (t *inMemoryTreeStorage) Heads() ([]string, error) {
@ -118,7 +116,7 @@ func (t *inMemoryTreeStorage) SetHeads(heads []string) error {
return nil
}
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) error {
func (t *inMemoryTreeStorage) AddRawChange(change *treechangeproto.RawTreeChangeWithId) error {
t.Lock()
defer t.Unlock()
// TODO: better to do deep copy
@ -126,7 +124,7 @@ func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) er
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()
defer t.RUnlock()
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) {
i.Lock()
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 {
return nil, err
}
@ -175,7 +173,7 @@ func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePay
func (i *inMemoryStorageProvider) CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error) {
i.Lock()
defer i.Unlock()
res, err := NewInMemoryACLListStorage(payload.ListId, payload.Header, payload.Records)
res, err := NewInMemoryACLListStorage(payload.ListId, payload.Records)
if err != nil {
return nil, err
}

View File

@ -2,14 +2,14 @@ package storage
import (
"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 {
Storage
Header() (*aclpb.ACLHeader, error)
Head() (*aclpb.RawACLRecord, error)
Root() (*aclrecordproto.RawACLRecordWithId, error)
Head() (*aclrecordproto.RawACLRecordWithId, error)
GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error)
AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error
GetRawRecord(ctx context.Context, id string) (*aclrecordproto.RawACLRecordWithId, error)
AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error
}

View File

@ -2,27 +2,26 @@ package storage
import (
"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")
type TreeStorageCreatePayload struct {
TreeId string
Header *aclpb.TreeHeader
Changes []*aclpb.RawTreeChangeWithId
RootRawChange *treechangeproto.RawTreeChangeWithId
Changes []*treechangeproto.RawTreeChangeWithId
Heads []string
}
type ACLListStorageCreatePayload struct {
ListId string
Header *aclpb.ACLHeader
Records []*aclpb.RawACLRecord
Records []*aclrecordproto.RawACLRecordWithId
}
type Provider interface {
Storage(id string) (Storage, error)
AddStorage(id string, st Storage) error
CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error)
CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error)
}

View File

@ -2,17 +2,17 @@ package storage
import (
"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 {
Storage
Header() (*aclpb.TreeHeader, error)
Root() (*treechangeproto.RawTreeChangeWithId, error)
Heads() ([]string, error)
SetHeads(heads []string) error
AddRawChange(change *aclpb.RawTreeChangeWithId) error
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawTreeChangeWithId, error)
AddRawChange(change *treechangeproto.RawTreeChangeWithId) error
GetRawChange(ctx context.Context, id string) (*treechangeproto.RawTreeChangeWithId, error)
}
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)

View File

@ -2,11 +2,7 @@ package tree
import (
"errors"
"fmt"
"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"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
)
var (
@ -14,68 +10,52 @@ var (
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
type Change struct {
Next []*Change
PreviousIds []string
AclHeadId string
Id string
SnapshotId string
IsSnapshot bool
DecryptedChange []byte // TODO: check if we need it
ParsedModel interface{} // TODO: check if we need it
Timestamp int64
ReadKeyHash uint64
Identity string
Data []byte
Model interface{}
// iterator helpers
visited bool
branchesFinished bool
Content *aclpb.TreeChange
Identity string
Sign []byte
Signature []byte
}
func (ch *Change) ProtoChange() proto.Marshaler {
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 {
func NewChange(id string, ch *treechangeproto.TreeChange, signature []byte) *Change {
return &Change{
Next: nil,
PreviousIds: ch.TreeHeadIds,
AclHeadId: ch.AclHeadId,
Timestamp: ch.Timestamp,
ReadKeyHash: ch.CurrentReadKeyHash,
Id: id,
Content: ch,
Data: ch.ChangesData,
SnapshotId: ch.SnapshotBaseId,
IsSnapshot: ch.IsSnapshot,
Identity: string(ch.Identity),
Sign: signature,
Signature: signature,
}
}
func (ch *Change) DecryptedChangeContent() []byte {
return ch.DecryptedChange
}
func (ch *Change) Signature() []byte {
return ch.Sign
func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change {
return &Change{
Next: nil,
AclHeadId: ch.AclHeadId,
Id: id,
IsSnapshot: true,
Identity: string(ch.Identity),
Signature: signature,
}
}
func (ch *Change) CID() string {

View File

@ -2,8 +2,8 @@ package tree
import (
"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/treechangeproto"
"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/symmetric"
@ -14,32 +14,44 @@ import (
var ErrEmptyChange = errors.New("change payload should not be empty")
type BuilderContent struct {
treeHeadIds []string
aclHeadId string
snapshotBaseId string
currentReadKeyHash uint64
identity []byte
isSnapshot bool
signingKey signingkey.PrivKey
readKey *symmetric.Key
content []byte
TreeHeadIds []string
AclHeadId string
SnapshotBaseId string
CurrentReadKeyHash uint64
Identity []byte
IsSnapshot bool
SigningKey signingkey.PrivKey
ReadKey *symmetric.Key
Content []byte
}
type InitialContent struct {
AclHeadId string
Identity []byte
SigningKey signingkey.PrivKey
SpaceId string
Seed []byte
ChangeType string
}
type ChangeBuilder interface {
ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error)
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error)
BuildRaw(ch *Change) (*aclpb.RawTreeChangeWithId, error)
ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error)
BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
BuildRaw(ch *Change) (*treechangeproto.RawTreeChangeWithId, error)
SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId)
}
type changeBuilder struct {
rootChange *treechangeproto.RawTreeChangeWithId
keys *common.Keychain
}
func newChangeBuilder(keys *common.Keychain) ChangeBuilder {
return &changeBuilder{keys: keys}
func newChangeBuilder(keys *common.Keychain, rootChange *treechangeproto.RawTreeChangeWithId) ChangeBuilder {
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 {
err = ErrEmptyChange
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)
if err != nil {
return
@ -78,28 +90,69 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, v
}
}
unmarshalled := &aclpb.TreeChange{}
err = proto.Unmarshal(raw.Payload, unmarshalled)
return c.unmarshallRawChange(raw, rawIdChange.Id)
}
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 {
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
}
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *aclpb.RawTreeChangeWithId, err error) {
change := &aclpb.TreeChange{
TreeHeadIds: payload.treeHeadIds,
AclHeadId: payload.aclHeadId,
SnapshotBaseId: payload.snapshotBaseId,
CurrentReadKeyHash: payload.currentReadKeyHash,
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
change := &treechangeproto.TreeChange{
TreeHeadIds: payload.TreeHeadIds,
AclHeadId: payload.AclHeadId,
SnapshotBaseId: payload.SnapshotBaseId,
CurrentReadKeyHash: payload.CurrentReadKeyHash,
Timestamp: int64(time.Now().Nanosecond()),
Identity: payload.identity,
IsSnapshot: payload.isSnapshot,
Identity: payload.Identity,
IsSnapshot: payload.IsSnapshot,
}
encrypted, err := payload.readKey.Encrypt(payload.content)
encrypted, err := payload.ReadKey.Encrypt(payload.Content)
if err != nil {
return
}
@ -110,12 +163,12 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
return
}
signature, err := payload.signingKey.Sign(marshalledChange)
signature, err := payload.SigningKey.Sign(marshalledChange)
if err != nil {
return
}
raw := &aclpb.RawTreeChange{
raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange,
Signature: signature,
}
@ -131,33 +184,67 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
}
ch = NewChange(id, change, signature)
ch.ParsedModel = payload.content
ch.Model = payload.Content
rawIdChange = &aclpb.RawTreeChangeWithId{
rawIdChange = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: id,
}
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
marshalled, err = ch.Content.Marshal()
marshalled, err = treeChange.Marshal()
if err != nil {
return
}
marshalledRawChange, err := proto.Marshal(&aclpb.RawTreeChange{
marshalledRawChange, err := proto.Marshal(&treechangeproto.RawTreeChange{
Payload: marshalled,
Signature: ch.Sign,
Signature: ch.Signature,
})
if err != nil {
return
}
raw = &aclpb.RawTreeChangeWithId{
raw = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: ch.Id,
}
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 (
"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"
)
@ -43,12 +43,12 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
state = aclList.ACLState()
)
// 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 {
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
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
for _, id := range c.PreviousIds {
prevChange := tree.attached[id]
if prevChange.Content.AclHeadId == c.Content.AclHeadId {
if prevChange.AclHeadId == c.AclHeadId {
continue
}
var after bool
after, err = aclList.IsAfter(c.Content.AclHeadId, prevChange.Content.AclHeadId)
after, err = aclList.IsAfter(c.AclHeadId, prevChange.AclHeadId)
if err != nil {
return
}
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
}
}

View File

@ -3,10 +3,10 @@ package tree
import (
"context"
"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/list"
"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"
"sync"
)
@ -27,7 +27,7 @@ type AddResultSummary int
type AddResult struct {
OldHeads []string
Heads []string
Added []*aclpb.RawTreeChangeWithId
Added []*treechangeproto.RawTreeChangeWithId
Mode Mode
}
@ -39,7 +39,7 @@ type ObjectTree interface {
RWLocker
ID() string
Header() *aclpb.TreeHeader
Header() *treechangeproto.RootChange
Heads() []string
Root() *Change
HasChange(string) bool
@ -49,12 +49,12 @@ type ObjectTree interface {
IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error
SnapshotPath() []string
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*aclpb.RawTreeChangeWithId, error)
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*treechangeproto.RawTreeChangeWithId, error)
Storage() storage.TreeStorage
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
}
@ -68,13 +68,13 @@ type objectTree struct {
aclList list.ACLList
id string
header *aclpb.TreeHeader
root *treechangeproto.RootChange
tree *Tree
keys map[uint64]*symmetric.Key
// buffers
difSnapshotBuf []*aclpb.RawTreeChangeWithId
difSnapshotBuf []*treechangeproto.RawTreeChangeWithId
tmpChangesBuf []*Change
newSnapshotsBuf []*Change
notSeenIdxBuf []int
@ -94,11 +94,12 @@ type objectTreeDeps struct {
}
func defaultObjectTreeDeps(
rootChange *treechangeproto.RawTreeChangeWithId,
treeStorage storage.TreeStorage,
aclList list.ACLList) objectTreeDeps {
keychain := common.NewKeychain()
changeBuilder := newChangeBuilder(keychain)
changeBuilder := newChangeBuilder(keychain, rootChange)
treeBuilder := newTreeBuilder(treeStorage, changeBuilder)
return objectTreeDeps{
changeBuilder: changeBuilder,
@ -131,8 +132,8 @@ func (ot *objectTree) ID() string {
return ot.id
}
func (ot *objectTree) Header() *aclpb.TreeHeader {
return ot.header
func (ot *objectTree) Header() *treechangeproto.RootChange {
return ot.root
}
func (ot *objectTree) Storage() storage.TreeStorage {
@ -172,7 +173,7 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont
res = AddResult{
OldHeads: oldHeads,
Heads: []string{objChange.Id},
Added: []*aclpb.RawTreeChangeWithId{rawChange},
Added: []*treechangeproto.RawTreeChangeWithId{rawChange},
Mode: Append,
}
return
@ -188,20 +189,20 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt
return
}
cnt = BuilderContent{
treeHeadIds: ot.tree.Heads(),
aclHeadId: ot.aclList.Head().Id,
snapshotBaseId: ot.tree.RootId(),
currentReadKeyHash: state.CurrentReadKeyHash(),
identity: content.Identity,
isSnapshot: content.IsSnapshot,
signingKey: content.Key,
readKey: readKey,
content: content.Data,
TreeHeadIds: ot.tree.Heads(),
AclHeadId: ot.aclList.Head().Id,
SnapshotBaseId: ot.tree.RootId(),
CurrentReadKeyHash: state.CurrentReadKeyHash(),
Identity: content.Identity,
IsSnapshot: content.IsSnapshot,
SigningKey: content.Key,
ReadKey: readKey,
Content: content.Data,
}
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...)
if err != nil {
return
@ -223,7 +224,7 @@ func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
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
ot.tmpChangesBuf = ot.tmpChangesBuf[: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
// they can include not only the changes that were added now,
// 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{})
// 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 {
// if we got some changes that we need to convert to raw
if _, exists := alreadyConverted[ch]; !exists {
var raw *aclpb.RawTreeChangeWithId
var raw *treechangeproto.RawTreeChangeWithId
raw, err = ot.changeBuilder.BuildRaw(ch)
if err != nil {
return
@ -342,7 +343,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
ot.rebuildFromStorage(nil)
return
}
var added []*aclpb.RawTreeChangeWithId
var added []*treechangeproto.RawTreeChangeWithId
added, err = getAddedChanges(nil)
// we shouldn't get any error in this case
if err != nil {
@ -378,7 +379,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
err = ErrHasInvalidChanges
return
}
var added []*aclpb.RawTreeChangeWithId
var added []*treechangeproto.RawTreeChangeWithId
added, err = getAddedChanges(treeChangesAdded)
if err != nil {
// 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) {
var model any
if c.ParsedModel != nil {
if c.Model != nil {
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 {
err = list.ErrNoReadKey
return false
}
var decrypted []byte
decrypted, err = readKey.Decrypt(c.Content.GetChangesData())
decrypted, err = readKey.Decrypt(c.Data)
if err != nil {
return false
}
@ -429,7 +434,7 @@ func (ot *objectTree) IterateFrom(id string, convert ChangeConvertFunc, iterate
return false
}
c.ParsedModel = model
c.Model = model
return iterate(c)
})
return
@ -474,7 +479,7 @@ func (ot *objectTree) SnapshotPath() []string {
return path
}
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawTreeChangeWithId, error) {
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
var (
needFullDocument = len(theirPath) == 0
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)
}
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)
}

View File

@ -2,10 +2,12 @@ package tree
import (
"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/storage"
"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/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -14,8 +16,26 @@ import (
type mockChangeCreator struct{}
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *aclpb.RawTreeChangeWithId {
aclChange := &aclpb.TreeChange{
func (c *mockChangeCreator) createRoot(id, aclId string) *treechangeproto.RawTreeChangeWithId {
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,
AclHeadId: aclId,
SnapshotBaseId: snapshotId,
@ -24,26 +44,21 @@ func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot b
}
res, _ := aclChange.Marshal()
raw := &aclpb.RawTreeChange{
raw := &treechangeproto.RawTreeChange{
Payload: res,
Signature: nil,
}
rawMarshalled, _ := raw.Marshal()
return &aclpb.RawTreeChangeWithId{
return &treechangeproto.RawTreeChangeWithId{
RawChange: rawMarshalled,
Id: id,
}
}
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclListId, aclHeadId, firstChangeId string) storage.TreeStorage {
firstChange := c.createRaw(firstChangeId, aclHeadId, "", true)
header := &aclpb.TreeHeader{
FirstId: firstChangeId,
AclId: aclListId,
TreeHeaderType: aclpb.TreeHeaderType_Object,
}
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawTreeChangeWithId{firstChange})
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclHeadId string) storage.TreeStorage {
root := c.createRoot(treeId, aclHeadId)
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root})
return treeStorage
}
@ -51,15 +66,23 @@ type mockChangeBuilder struct {
originalBuilder ChangeBuilder
}
func (c *mockChangeBuilder) ConvertFromRaw(rawChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
return c.originalBuilder.ConvertFromRaw(rawChange, false)
}
func (c *mockChangeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error) {
func (c *mockChangeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) {
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)
}
@ -93,15 +116,15 @@ func prepareACLList(t *testing.T) list.ACLList {
func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext {
changeCreator := &mockChangeCreator{}
treeStorage := changeCreator.createNewTreeStorage("treeId", aclList.ID(), aclList.Head().Id, "0")
treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id)
root, _ := treeStorage.Root()
changeBuilder := &mockChangeBuilder{
originalBuilder: newChangeBuilder(nil),
originalBuilder: newChangeBuilder(nil, root),
}
deps := objectTreeDeps{
changeBuilder: changeBuilder,
treeBuilder: newTreeBuilder(treeStorage, changeBuilder),
treeStorage: treeStorage,
updateListener: nil,
rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder),
validator: &mockChangeValidator{},
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) {
aclList := prepareACLList(t)
@ -137,7 +172,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
}
@ -178,7 +213,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("0", aclList.Head().Id, "", true, ""),
}
res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
@ -198,7 +233,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
}
res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
@ -220,7 +255,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -264,7 +299,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -283,7 +318,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -357,7 +392,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
@ -433,7 +468,7 @@ func TestObjectTree(t *testing.T) {
changeCreator := ctx.changeCreator
objTree := ctx.objTree
rawChanges := []*aclpb.RawTreeChangeWithId{
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
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.Equal(t, "3", objTree.Root().Id)
rawChanges = []*aclpb.RawTreeChangeWithId{
rawChanges = []*treechangeproto.RawTreeChangeWithId{
changeCreator.createRaw("4", aclList.Head().Id, "0", false, "2"),
changeCreator.createRaw("5", aclList.Head().Id, "0", false, "1"),
changeCreator.createRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"),

View File

@ -1,11 +1,10 @@
package tree
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/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/slice"
"github.com/gogo/protobuf/proto"
@ -13,14 +12,19 @@ import (
)
type ObjectTreeCreatePayload struct {
AccountData *account.AccountData
HeaderData []byte
ChangeData []byte
TreeType aclpb.TreeHeaderType
SignKey signingkey.PrivKey
ChangeType string
Seed []byte
SpaceId string
Identity []byte
}
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)
}
@ -30,53 +34,34 @@ func CreateObjectTree(
createStorage storage.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
aclList.RLock()
var (
deps = defaultObjectTreeDeps(nil, aclList)
state = aclList.ACLState()
aclId = aclList.ID()
deps = defaultObjectTreeDeps(nil, nil, aclList)
aclHeadId = aclList.Head().Id
readKeyHash = state.CurrentReadKeyHash()
)
readKey, err := state.CurrentReadKey()
aclList.RUnlock()
if err != nil {
return
}
// create first change
cnt := BuilderContent{
treeHeadIds: nil,
aclHeadId: aclHeadId,
snapshotBaseId: "",
currentReadKeyHash: readKeyHash,
isSnapshot: true,
readKey: readKey,
identity: payload.AccountData.Identity,
signingKey: payload.AccountData.SignKey,
content: payload.ChangeData,
cnt := InitialContent{
AclHeadId: aclHeadId,
Identity: payload.Identity,
SigningKey: payload.SignKey,
SpaceId: payload.SpaceId,
Seed: payload.Seed,
ChangeType: payload.ChangeType,
}
_, raw, err := deps.changeBuilder.BuildContent(cnt)
if err != nil {
return
}
// create header
header, id, err := createTreeHeaderAndId(
raw,
payload.TreeType,
aclId,
payload.AccountData.Identity,
payload.HeaderData)
_, raw, err := deps.changeBuilder.BuildInitialContent(cnt)
if err != nil {
return
}
deps.changeBuilder.SetRootRawChange(raw)
// create storage
st, err := createStorage(storage.TreeStorageCreatePayload{
TreeId: id,
Header: header,
Changes: []*aclpb.RawTreeChangeWithId{raw},
TreeId: raw.Id,
RootRawChange: raw,
Changes: []*treechangeproto.RawTreeChangeWithId{raw},
Heads: []string{raw.Id},
})
if err != nil {
@ -98,7 +83,7 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
tree: nil,
keys: make(map[uint64]*symmetric.Key),
tmpChangesBuf: make([]*Change, 0, 10),
difSnapshotBuf: make([]*aclpb.RawTreeChangeWithId, 0, 10),
difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
notSeenIdxBuf: make([]int, 0, 10),
newSnapshotsBuf: make([]*Change, 0, 10),
}
@ -128,32 +113,23 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
if err != nil {
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 {
return nil, err
}
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 (
"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/treechangeproto"
"time"
)
@ -18,7 +18,7 @@ type rawChangeLoader struct {
type rawCacheEntry struct {
change *Change
rawChange *aclpb.RawTreeChangeWithId
rawChange *treechangeproto.RawTreeChangeWithId
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
for _, h := range t.headIds {
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 {
var raw *aclpb.RawTreeChangeWithId
var raw *treechangeproto.RawTreeChangeWithId
raw, err = r.changeBuilder.BuildRaw(ch)
if err != nil {
return
@ -95,7 +95,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.
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
r.cache = make(map[string]rawCacheEntry)
defer func() {
@ -162,7 +162,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
// preparing first pass
r.idStack = append(r.idStack, heads...)
var buffer []*aclpb.RawTreeChangeWithId
var buffer []*treechangeproto.RawTreeChangeWithId
rootVisited := dfs(commonSnapshot, heads, 0,
func(counter int, mapExists bool) bool {
@ -203,7 +203,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
})
// discarding visited
buffer = discardFromSlice(buffer, func(change *aclpb.RawTreeChangeWithId) bool {
buffer = discardFromSlice(buffer, func(change *treechangeproto.RawTreeChangeWithId) bool {
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",
shortId,
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, ","),
)
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 (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"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/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/testchangepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
testchanges "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/proto"
"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/storage"
"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/syncproto"
@ -25,13 +27,14 @@ type service struct {
messageService message.Service
treeCache treecache.Service
account account.Service
storage storage.Service
// to create new documents we need to know all nodes
nodes []*node.Node
}
type Service interface {
UpdateDocument(ctx context.Context, id, text string) error
CreateDocument(ctx context.Context, text string) (string, error)
UpdateDocumentTree(ctx context.Context, id, text string) error
CreateDocumentTree(ctx context.Context, aclTreeId string, text string) (id string, err error)
}
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.messageService = a.MustComponent(message.CName).(message.Service)
s.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
s.storage = a.MustComponent(storage.CName).(storage.Service)
nodesService := a.MustComponent(node.CName).(node.Service)
s.nodes = nodesService.Nodes()
@ -54,41 +58,65 @@ func (s *service) Name() (name string) {
}
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) {
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 (
ch *aclpb.RawChange
header *treepb.TreeHeader
header *aclpb.Header
snapshotPath []string
heads []string
)
log.With(zap.String("id", id), zap.String("text", text)).
Debug("updating document")
err = s.treeCache.Do(ctx, id, func(tree acltree.ACLTree) error {
ch, err = tree.AddContent(ctx, func(builder acltree.ChangeBuilder) error {
builder.AddChangeContent(
&testchangepb.PlainTextChange_Data{
Content: []*testchangepb.PlainTextChange_Content{
createAppendTextChangeContent(text),
},
})
err = s.treeCache.Do(ctx, id, func(obj interface{}) error {
docTree, ok := obj.(tree.ObjectTree)
if !ok {
return fmt.Errorf("can't update acl trees with 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
})
if err != nil {
return err
}
id = tree.ID()
heads = tree.Heads()
header = tree.Header()
snapshotPath = tree.SnapshotPath()
id = docTree.ID()
heads = docTree.Heads()
header = docTree.Header()
snapshotPath = docTree.SnapshotPath()
return 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())).
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,
Changes: []*aclpb.RawChange{ch},
TreeId: id,
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()
var (
ch *aclpb.RawChange
header *treepb.TreeHeader
header *aclpb.Header
snapshotPath []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 {
err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin)
content := createInitialTextChange(text)
doc, err := tree.CreateNewTreeStorage(acc, t, content, s.storage.CreateTreeStorage)
if err != nil {
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))
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])
id, err = doc.ID()
if err != nil {
return err
}
log.With(
zap.String("id", id),
zap.Strings("heads", heads),
zap.String("header", header.String())).
Debug("document created in the database")
header, err = doc.Header()
if err != nil {
return err
}
heads = []string{header.FirstId}
snapshotPath = []string{header.FirstId}
ch, err = doc.GetRawChange(ctx, header.FirstId)
if err != nil {
return err
}
return nil
})
if err != nil {
return "", err
}
log.With(zap.String("id", id), zap.String("text", text)).
Debug("creating document")
err = s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.Sync_HeadUpdate{
err = s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
Heads: heads,
Changes: []*aclpb.RawChange{ch},
TreeId: id,
SnapshotPath: snapshotPath,
TreeHeader: header,
}))
}, header, id))
if err != nil {
return "", err
}
return id, err
}
func createInitialChangeContent(text string) proto.Marshaler {
return &testchangepb.PlainTextChange_Data{
Content: []*testchangepb.PlainTextChange_Content{
func createInitialTextChange(text string) proto.Marshaler {
return &testchanges.PlainTextChangeData{
Content: []*testchanges.PlainTextChangeContent{
createAppendTextChangeContent(text),
},
Snapshot: &testchangepb.PlainTextChange_Snapshot{Text: text},
Snapshot: &testchanges.PlainTextChangeSnapshot{Text: text},
}
}
func createAppendTextChangeContent(text string) *testchangepb.PlainTextChange_Content {
return &testchangepb.PlainTextChange_Content{
Value: &testchangepb.PlainTextChange_Content_TextAppend{
TextAppend: &testchangepb.PlainTextChange_TextAppend{
func createAppendTextChange(text string) proto.Marshaler {
return &testchanges.PlainTextChangeData{
Content: []*testchanges.PlainTextChangeContent{
createAppendTextChangeContent(text),
},
}
}
func createAppendTextChangeContent(text string) *testchanges.PlainTextChangeContent {
return &testchanges.PlainTextChangeContent{
Value: &testchanges.PlainTextChangeContentValueOfTextAppend{
TextAppend: &testchanges.PlainTextChangeTextAppend{
Text: text,
},
},

View File

@ -2,16 +2,10 @@ package storage
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"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/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"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"
@ -38,10 +32,10 @@ type service struct {
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()
// 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) {
@ -52,12 +46,12 @@ func (s *service) AddStorage(id string, st storage.Storage) error {
return s.storageProvider.AddStorage(id, st)
}
func (s *service) CreateTreeStorage(treeId string, header *aclpb.Header, changes []*aclpb.RawChange) (storage.TreeStorage, error) {
return s.storageProvider.CreateTreeStorage(treeId, header, changes)
func (s *service) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (storage.TreeStorage, error) {
return s.storageProvider.CreateTreeStorage(payload)
}
func (s *service) CreateACLListStorage(id string, header *aclpb.Header, records []*aclpb.RawRecord) (storage.ListStorage, error) {
return s.storageProvider.CreateACLListStorage(id, header, records)
func (s *service) CreateACLListStorage(payload storage.ACLListStorageCreatePayload) (storage.ListStorage, error) {
return s.storageProvider.CreateACLListStorage(payload)
}
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) {
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 (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"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/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
aclstorage "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/ocache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/storage"
"go.uber.org/zap"
)
const CName = "treecache"
// TODO: add context
type ACLTreeFunc = func(tree acltree.ACLTree) error
type ChangeBuildFunc = func(builder acltree.ChangeBuilder) error
type ObjFunc = func(obj interface{}) error
var log = logger.NewNamed("treecache")
type Service interface {
Do(ctx context.Context, treeId string, f ACLTreeFunc) error
Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error
Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error
Do(ctx context.Context, id string, f ObjFunc) error
Add(ctx context.Context, id string, payload any) error
}
type service struct {
treeProvider treestorage.Provider
storage storage.Service
account account.Service
cache ocache.OCache
}
@ -37,53 +36,48 @@ func New() app.ComponentRunnable {
return &service{}
}
func (s *service) Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) 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 {
func (s *service) Do(ctx context.Context, treeId string, f ObjFunc) error {
log.
With(zap.String("treeId", treeId)).
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)
if err != nil {
return err
}
aclTree := tree.(acltree.ACLTree)
aclTree.Lock()
defer aclTree.Unlock()
return f(tree.(acltree.ACLTree))
return f(t)
}
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.
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(changes))).
Debug("adding tree with changes")
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Changes))).
Debug("adding Tree with changes")
_, err := s.treeProvider.CreateTreeStorage(treeId, header, changes)
_, err := s.storage.CreateTreeStorage(payload.(aclstorage.TreeStorageCreatePayload))
if err != nil {
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) {
s.cache = ocache.New(s.loadTree)
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
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) {
tree, err := s.treeProvider.TreeStorage(id)
t, err := s.storage.Storage(id)
if err != nil {
return nil, err
}
// TODO: should probably accept nil listeners
aclTree, err := acltree.BuildACLTree(tree, s.account.Account(), acltree.NoOpListener{})
return aclTree, err
header, err := t.Header()
if err != nil {
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;
option go_package = "/syncproto";
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto";
import "pkg/acl/aclrecordproto/aclpb/protos/aclrecordproto.proto";
message Message {
Header header = 1;