any-sync/commonspace/payloads.go
2023-04-02 18:13:10 +02:00

183 lines
4.6 KiB
Go

package commonspace
import (
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/util/cidutil"
"github.com/anytypeio/any-sync/util/crypto"
"hash/fnv"
"math/rand"
"time"
)
const (
SpaceReserved = "any-sync.space"
)
func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload spacestorage.SpaceStorageCreatePayload, err error) {
// marshalling keys
identity, err := payload.SigningKey.GetPublic().Marshall()
if err != nil {
return
}
// preparing header and space id
spaceHeaderSeed := make([]byte, 32)
_, err = rand.Read(spaceHeaderSeed)
if err != nil {
return
}
header := &spacesyncproto.SpaceHeader{
Identity: identity,
Timestamp: time.Now().Unix(),
SpaceType: payload.SpaceType,
SpaceHeaderPayload: payload.SpacePayload,
ReplicationKey: payload.ReplicationKey,
Seed: spaceHeaderSeed,
}
marshalled, err := header.Marshal()
if err != nil {
return
}
signature, err := payload.SigningKey.Sign(marshalled)
if err != nil {
return
}
rawHeader := &spacesyncproto.RawSpaceHeader{SpaceHeader: marshalled, Signature: signature}
marshalled, err = rawHeader.Marshal()
if err != nil {
return
}
id, err := cidutil.NewCidFromBytes(marshalled)
spaceId := NewSpaceId(id, payload.ReplicationKey)
rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marshalled,
Id: spaceId,
}
readKey, err := payload.SigningKey.GetPublic().Encrypt(payload.ReadKey)
if err != nil {
return
}
// building acl root
keyStorage := crypto.NewKeyStorage()
aclBuilder := list.NewAclRecordBuilder("", keyStorage)
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
PrivKey: payload.SigningKey,
MasterKey: payload.MasterKey,
SpaceId: spaceId,
EncryptedReadKey: readKey,
})
if err != nil {
return
}
// building settings
builder := objecttree.NewChangeBuilder(keyStorage, nil)
spaceSettingsSeed := make([]byte, 32)
_, err = rand.Read(spaceSettingsSeed)
if err != nil {
return
}
_, settingsRoot, err := builder.BuildRoot(objecttree.InitialContent{
AclHeadId: aclRoot.Id,
PrivKey: payload.SigningKey,
SpaceId: spaceId,
Seed: spaceSettingsSeed,
ChangeType: SpaceReserved,
Timestamp: time.Now().Unix(),
})
if err != nil {
return
}
// creating storage
storagePayload = spacestorage.SpaceStorageCreatePayload{
AclWithId: aclRoot,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: settingsRoot,
}
return
}
func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload spacestorage.SpaceStorageCreatePayload, err error) {
// marshalling keys
identity, err := payload.SigningKey.GetPublic().Marshall()
if err != nil {
return
}
pubKey, err := payload.SigningKey.GetPublic().Raw()
if err != nil {
return
}
// preparing replication key
hasher := fnv.New64()
_, err = hasher.Write(pubKey)
if err != nil {
return
}
repKey := hasher.Sum64()
// preparing header and space id
header := &spacesyncproto.SpaceHeader{
Identity: identity,
SpaceType: payload.SpaceType,
SpaceHeaderPayload: payload.SpacePayload,
ReplicationKey: repKey,
}
marshalled, err := header.Marshal()
if err != nil {
return
}
signature, err := payload.SigningKey.Sign(marshalled)
if err != nil {
return
}
rawHeader := &spacesyncproto.RawSpaceHeader{SpaceHeader: marshalled, Signature: signature}
marshalled, err = rawHeader.Marshal()
if err != nil {
return
}
id, err := cidutil.NewCidFromBytes(marshalled)
spaceId := NewSpaceId(id, repKey)
rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marshalled,
Id: spaceId,
}
// building acl root
keyStorage := crypto.NewKeyStorage()
aclBuilder := list.NewAclRecordBuilder("", keyStorage)
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
PrivKey: payload.SigningKey,
MasterKey: payload.MasterKey,
SpaceId: spaceId,
})
if err != nil {
return
}
// building settings
builder := objecttree.NewChangeBuilder(keyStorage, nil)
_, settingsRoot, err := builder.BuildRoot(objecttree.InitialContent{
AclHeadId: aclRoot.Id,
PrivKey: payload.SigningKey,
SpaceId: spaceId,
ChangeType: SpaceReserved,
})
if err != nil {
return
}
// creating storage
storagePayload = spacestorage.SpaceStorageCreatePayload{
AclWithId: aclRoot,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: settingsRoot,
}
return
}