1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-08 14:07:02 +09:00

wip: drpc access log

This commit is contained in:
Sergey Cherepanov 2023-04-24 14:59:15 +02:00 committed by Mikhail Iudin
parent 6ed21a94d3
commit ed0a751d15
No known key found for this signature in database
GPG key ID: FAAAA8BAABDFF1C0
5 changed files with 763 additions and 34 deletions

View file

@ -3,6 +3,7 @@ package commonspace
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"github.com/anytypeio/any-sync/accountservice" "github.com/anytypeio/any-sync/accountservice"
"github.com/anytypeio/any-sync/app/logger" "github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/commonspace/headsync" "github.com/anytypeio/any-sync/commonspace/headsync"
@ -20,6 +21,7 @@ import (
"github.com/anytypeio/any-sync/commonspace/spacestorage" "github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto" "github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/commonspace/syncstatus" "github.com/anytypeio/any-sync/commonspace/syncstatus"
"github.com/anytypeio/any-sync/metric"
"github.com/anytypeio/any-sync/net/peer" "github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/nodeconf" "github.com/anytypeio/any-sync/nodeconf"
"github.com/anytypeio/any-sync/util/crypto" "github.com/anytypeio/any-sync/util/crypto"
@ -29,7 +31,6 @@ import (
"github.com/zeebo/errs" "github.com/zeebo/errs"
"go.uber.org/zap" "go.uber.org/zap"
"strconv" "strconv"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -56,11 +57,22 @@ type SpaceCreatePayload struct {
type HandleMessage struct { type HandleMessage struct {
Id uint64 Id uint64
ReceiveTime time.Time
StartHandlingTime time.Time
Deadline time.Time Deadline time.Time
SenderId string SenderId string
Message *spacesyncproto.ObjectSyncMessage Message *spacesyncproto.ObjectSyncMessage
} }
func (m HandleMessage) LogFields(fields ...zap.Field) []zap.Field {
return append(fields,
metric.SpaceId(m.Message.SpaceId),
metric.ObjectId(m.Message.ObjectId),
metric.QueueDur(m.StartHandlingTime.Sub(m.ReceiveTime)),
metric.TotalDur(time.Since(m.ReceiveTime)),
)
}
type SpaceDerivePayload struct { type SpaceDerivePayload struct {
SigningKey crypto.PrivKey SigningKey crypto.PrivKey
MasterKey crypto.PrivKey MasterKey crypto.PrivKey
@ -77,7 +89,7 @@ type SpaceDescription struct {
} }
func NewSpaceId(id string, repKey uint64) string { func NewSpaceId(id string, repKey uint64) string {
return strings.Join([]string{id, strconv.FormatUint(repKey, 36)}, ".") return fmt.Sprintf("%s.%s", id, strconv.FormatUint(repKey, 36))
} }
type Space interface { type Space interface {
@ -88,6 +100,7 @@ type Space interface {
DebugAllHeads() []headsync.TreeHeads DebugAllHeads() []headsync.TreeHeads
Description() (SpaceDescription, error) Description() (SpaceDescription, error)
DeriveTree(ctx context.Context, payload objecttree.ObjectTreeCreatePayload) (res treestorage.TreeStorageCreatePayload, err error)
CreateTree(ctx context.Context, payload objecttree.ObjectTreeCreatePayload) (res treestorage.TreeStorageCreatePayload, err error) CreateTree(ctx context.Context, payload objecttree.ObjectTreeCreatePayload) (res treestorage.TreeStorageCreatePayload, err error)
PutTree(ctx context.Context, payload treestorage.TreeStorageCreatePayload, listener updatelistener.UpdateListener) (t objecttree.ObjectTree, err error) PutTree(ctx context.Context, payload treestorage.TreeStorageCreatePayload, listener updatelistener.UpdateListener) (t objecttree.ObjectTree, err error)
BuildTree(ctx context.Context, id string, opts BuildTreeOpts) (t objecttree.ObjectTree, err error) BuildTree(ctx context.Context, id string, opts BuildTreeOpts) (t objecttree.ObjectTree, err error)
@ -117,13 +130,13 @@ type space struct {
headSync headsync.HeadSync headSync headsync.HeadSync
syncStatus syncstatus.StatusUpdater syncStatus syncstatus.StatusUpdater
storage spacestorage.SpaceStorage storage spacestorage.SpaceStorage
treeManager *commonGetter cache *commonGetter
account accountservice.Service account accountservice.Service
aclList *syncacl.SyncAcl aclList *syncacl.SyncAcl
configuration nodeconf.Configuration configuration nodeconf.NodeConf
settingsObject settings.SettingsObject settingsObject settings.SettingsObject
peerManager peermanager.PeerManager peerManager peermanager.PeerManager
treeBuilder objecttree.BuildObjectTreeFunc metric metric.Metric
handleQueue multiqueue.MultiQueue[HandleMessage] handleQueue multiqueue.MultiQueue[HandleMessage]
@ -178,8 +191,8 @@ func (s *space) Init(ctx context.Context) (err error) {
if err != nil { if err != nil {
return return
} }
s.aclList = syncacl.NewSyncAcl(aclList, s.objectSync.SyncClient().MessagePool()) s.aclList = syncacl.NewSyncAcl(aclList, s.objectSync.MessagePool())
s.treeManager.AddObject(s.aclList) s.cache.AddObject(s.aclList)
deletionState := settingsstate.NewObjectDeletionState(s.storage) deletionState := settingsstate.NewObjectDeletionState(s.storage)
deps := settings.Deps{ deps := settings.Deps{
@ -187,8 +200,6 @@ func (s *space) Init(ctx context.Context) (err error) {
res, err := s.BuildTree(ctx, id, BuildTreeOpts{ res, err := s.BuildTree(ctx, id, BuildTreeOpts{
Listener: listener, Listener: listener,
WaitTreeRemoteSync: false, WaitTreeRemoteSync: false,
// space settings document should not have empty data
treeBuilder: objecttree.BuildObjectTree,
}) })
log.Debug("building settings tree", zap.String("id", id), zap.String("spaceId", s.id)) log.Debug("building settings tree", zap.String("id", id), zap.String("spaceId", s.id))
if err != nil { if err != nil {
@ -198,7 +209,7 @@ func (s *space) Init(ctx context.Context) (err error) {
return return
}, },
Account: s.account, Account: s.account,
TreeManager: s.treeManager, TreeGetter: s.cache,
Store: s.storage, Store: s.storage,
DeletionState: deletionState, DeletionState: deletionState,
Provider: s.headSync, Provider: s.headSync,
@ -206,12 +217,13 @@ func (s *space) Init(ctx context.Context) (err error) {
OnSpaceDelete: s.onSpaceDelete, OnSpaceDelete: s.onSpaceDelete,
} }
s.settingsObject = settings.NewSettingsObject(deps, s.id) s.settingsObject = settings.NewSettingsObject(deps, s.id)
s.objectSync.Init()
s.headSync.Init(initialIds, deletionState) s.headSync.Init(initialIds, deletionState)
err = s.settingsObject.Init(ctx) err = s.settingsObject.Init(ctx)
if err != nil { if err != nil {
return return
} }
s.treeManager.AddObject(s.settingsObject) s.cache.AddObject(s.settingsObject)
s.syncStatus.Run() s.syncStatus.Run()
s.handleQueue = multiqueue.New[HandleMessage](s.handleMessage, 100) s.handleQueue = multiqueue.New[HandleMessage](s.handleMessage, 100)
return nil return nil
@ -243,6 +255,23 @@ func (s *space) DebugAllHeads() []headsync.TreeHeads {
return s.headSync.DebugAllHeads() return s.headSync.DebugAllHeads()
} }
func (s *space) DeriveTree(ctx context.Context, payload objecttree.ObjectTreeCreatePayload) (res treestorage.TreeStorageCreatePayload, err error) {
if s.isClosed.Load() {
err = ErrSpaceClosed
return
}
root, err := objecttree.DeriveObjectTreeRoot(payload, s.aclList)
if err != nil {
return
}
res = treestorage.TreeStorageCreatePayload{
RootRawChange: root,
Changes: []*treechangeproto.RawTreeChangeWithId{root},
Heads: []string{root.Id},
}
return
}
func (s *space) CreateTree(ctx context.Context, payload objecttree.ObjectTreeCreatePayload) (res treestorage.TreeStorageCreatePayload, err error) { func (s *space) CreateTree(ctx context.Context, payload objecttree.ObjectTreeCreatePayload) (res treestorage.TreeStorageCreatePayload, err error) {
if s.isClosed.Load() { if s.isClosed.Load() {
err = ErrSpaceClosed err = ErrSpaceClosed
@ -268,7 +297,7 @@ func (s *space) PutTree(ctx context.Context, payload treestorage.TreeStorageCrea
} }
deps := synctree.BuildDeps{ deps := synctree.BuildDeps{
SpaceId: s.id, SpaceId: s.id,
SyncClient: s.objectSync.SyncClient(), ObjectSync: s.objectSync,
Configuration: s.configuration, Configuration: s.configuration,
HeadNotifiable: s.headSync, HeadNotifiable: s.headSync,
Listener: listener, Listener: listener,
@ -277,7 +306,6 @@ func (s *space) PutTree(ctx context.Context, payload treestorage.TreeStorageCrea
OnClose: s.onObjectClose, OnClose: s.onObjectClose,
SyncStatus: s.syncStatus, SyncStatus: s.syncStatus,
PeerGetter: s.peerManager, PeerGetter: s.peerManager,
BuildObjectTree: s.treeBuilder,
} }
t, err = synctree.PutSyncTree(ctx, payload, deps) t, err = synctree.PutSyncTree(ctx, payload, deps)
if err != nil { if err != nil {
@ -291,7 +319,6 @@ func (s *space) PutTree(ctx context.Context, payload treestorage.TreeStorageCrea
type BuildTreeOpts struct { type BuildTreeOpts struct {
Listener updatelistener.UpdateListener Listener updatelistener.UpdateListener
WaitTreeRemoteSync bool WaitTreeRemoteSync bool
treeBuilder objecttree.BuildObjectTreeFunc
} }
type HistoryTreeOpts struct { type HistoryTreeOpts struct {
@ -304,13 +331,10 @@ func (s *space) BuildTree(ctx context.Context, id string, opts BuildTreeOpts) (t
err = ErrSpaceClosed err = ErrSpaceClosed
return return
} }
treeBuilder := opts.treeBuilder
if treeBuilder == nil {
treeBuilder = s.treeBuilder
}
deps := synctree.BuildDeps{ deps := synctree.BuildDeps{
SpaceId: s.id, SpaceId: s.id,
SyncClient: s.objectSync.SyncClient(), ObjectSync: s.objectSync,
Configuration: s.configuration, Configuration: s.configuration,
HeadNotifiable: s.headSync, HeadNotifiable: s.headSync,
Listener: opts.Listener, Listener: opts.Listener,
@ -320,7 +344,6 @@ func (s *space) BuildTree(ctx context.Context, id string, opts BuildTreeOpts) (t
SyncStatus: s.syncStatus, SyncStatus: s.syncStatus,
WaitTreeRemoteSync: opts.WaitTreeRemoteSync, WaitTreeRemoteSync: opts.WaitTreeRemoteSync,
PeerGetter: s.peerManager, PeerGetter: s.peerManager,
BuildObjectTree: treeBuilder,
} }
if t, err = synctree.BuildSyncTreeOrGetRemote(ctx, id, deps); err != nil { if t, err = synctree.BuildSyncTreeOrGetRemote(ctx, id, deps); err != nil {
return nil, err return nil, err
@ -362,6 +385,7 @@ func (s *space) DeleteSpace(ctx context.Context, deleteChange *treechangeproto.R
func (s *space) HandleMessage(ctx context.Context, hm HandleMessage) (err error) { func (s *space) HandleMessage(ctx context.Context, hm HandleMessage) (err error) {
threadId := hm.Message.ObjectId threadId := hm.Message.ObjectId
hm.ReceiveTime = time.Now()
if hm.Message.ReplyId != "" { if hm.Message.ReplyId != "" {
threadId += hm.Message.ReplyId threadId += hm.Message.ReplyId
defer func() { defer func() {
@ -378,12 +402,19 @@ func (s *space) HandleMessage(ctx context.Context, hm HandleMessage) (err error)
} }
func (s *space) handleMessage(msg HandleMessage) { func (s *space) handleMessage(msg HandleMessage) {
var err error
msg.StartHandlingTime = time.Now()
ctx := peer.CtxWithPeerId(context.Background(), msg.SenderId) ctx := peer.CtxWithPeerId(context.Background(), msg.SenderId)
ctx = logger.CtxWithFields(ctx, zap.Uint64("msgId", msg.Id), zap.String("senderId", msg.SenderId)) ctx = logger.CtxWithFields(ctx, zap.Uint64("msgId", msg.Id), zap.String("senderId", msg.SenderId))
defer func() {
s.metric.RequestLog(ctx, msg.LogFields(zap.Error(err))...)
}()
if !msg.Deadline.IsZero() { if !msg.Deadline.IsZero() {
now := time.Now() now := time.Now()
if now.After(msg.Deadline) { if now.After(msg.Deadline) {
log.InfoCtx(ctx, "skip message: deadline exceed") log.InfoCtx(ctx, "skip message: deadline exceed")
err = context.DeadlineExceeded
return return
} }
var cancel context.CancelFunc var cancel context.CancelFunc
@ -391,7 +422,7 @@ func (s *space) handleMessage(msg HandleMessage) {
defer cancel() defer cancel()
} }
if err := s.objectSync.HandleMessage(ctx, msg.SenderId, msg.Message); err != nil { if err = s.objectSync.HandleMessage(ctx, msg.SenderId, msg.Message); err != nil {
if msg.Message.ObjectId != "" { if msg.Message.ObjectId != "" {
// cleanup thread on error // cleanup thread on error
_ = s.handleQueue.CloseThread(msg.Message.ObjectId) _ = s.handleQueue.CloseThread(msg.Message.ObjectId)

View file

@ -16,6 +16,7 @@ import (
"github.com/anytypeio/any-sync/commonspace/spacestorage" "github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto" "github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/commonspace/syncstatus" "github.com/anytypeio/any-sync/commonspace/syncstatus"
"github.com/anytypeio/any-sync/metric"
"github.com/anytypeio/any-sync/net/peer" "github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/net/pool" "github.com/anytypeio/any-sync/net/pool"
"github.com/anytypeio/any-sync/net/rpc/rpcerr" "github.com/anytypeio/any-sync/net/rpc/rpcerr"
@ -52,6 +53,7 @@ type spaceService struct {
credentialProvider credentialprovider.CredentialProvider credentialProvider credentialprovider.CredentialProvider
treeManager treemanager.TreeManager treeManager treemanager.TreeManager
pool pool.Pool pool pool.Pool
metric metric.Metric
} }
func (s *spaceService) Init(a *app.App) (err error) { func (s *spaceService) Init(a *app.App) (err error) {
@ -68,6 +70,7 @@ func (s *spaceService) Init(a *app.App) (err error) {
s.credentialProvider = credentialprovider.NewNoOp() s.credentialProvider = credentialprovider.NewNoOp()
} }
s.pool = a.MustComponent(pool.CName).(pool.Pool) s.pool = a.MustComponent(pool.CName).(pool.Pool)
s.metric, _ = a.Component(metric.CName).(metric.Metric)
return nil return nil
} }
@ -181,6 +184,7 @@ func (s *spaceService) NewSpace(ctx context.Context, id string) (Space, error) {
treeBuilder: builder, treeBuilder: builder,
isClosed: spaceIsClosed, isClosed: spaceIsClosed,
isDeleted: spaceIsDeleted, isDeleted: spaceIsDeleted,
metric: s.metric,
} }
return sp, nil return sp, nil
} }

View file

@ -1,2 +1,656 @@
package spacestorage package spacestorage
import (
"crypto/rand"
"fmt"
"github.com/anytypeio/any-sync/commonspace/object/accountdata"
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/util/cidutil"
"github.com/anytypeio/any-sync/util/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
rand2 "golang.org/x/exp/rand"
"strconv"
"strings"
"testing"
"time"
)
func TestSuccessHeaderPayloadForSpaceCreate(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
_, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
err = validateCreateSpaceHeaderPayload(rawHeaderWithId)
require.NoError(t, err)
}
func TestFailedHeaderPayloadForSpaceCreate_InvalidFormatSpaceId(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
spaceHeaderSeed := make([]byte, 32)
_, err = rand.Read(spaceHeaderSeed)
require.NoError(t, err)
spaceHeaderPayload := make([]byte, 32)
_, err = rand.Read(spaceHeaderPayload)
require.NoError(t, err)
replicationKey := rand2.Uint64()
header := &spacesyncproto.SpaceHeader{
Identity: identity,
Timestamp: time.Now().Unix(),
SpaceType: "SpaceType",
ReplicationKey: replicationKey,
Seed: spaceHeaderSeed,
SpaceHeaderPayload: spaceHeaderPayload,
}
marhalled, err := header.Marshal()
require.NoError(t, err)
signature, err := accountKeys.SignKey.Sign(marhalled)
require.NoError(t, err)
rawHeader := &spacesyncproto.RawSpaceHeader{
SpaceHeader: marhalled,
Signature: signature,
}
marhalledRawHeader, err := rawHeader.Marshal()
require.NoError(t, err)
id, err := cidutil.NewCidFromBytes(marhalled)
require.NoError(t, err)
spaceId := fmt.Sprintf("%s%s", id, strconv.FormatUint(replicationKey, 36))
rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marhalledRawHeader,
Id: spaceId,
}
err = validateCreateSpaceHeaderPayload(rawHeaderWithId)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestFailedHeaderPayloadForSpaceCreate_CidIsWrong(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
spaceHeaderSeed := make([]byte, 32)
_, err = rand.Read(spaceHeaderSeed)
require.NoError(t, err)
spaceHeaderPayload := make([]byte, 32)
_, err = rand.Read(spaceHeaderPayload)
require.NoError(t, err)
replicationKey := rand2.Uint64()
header := &spacesyncproto.SpaceHeader{
Identity: identity,
Timestamp: time.Now().Unix(),
SpaceType: "SpaceType",
ReplicationKey: replicationKey,
Seed: spaceHeaderSeed,
SpaceHeaderPayload: spaceHeaderPayload,
}
marhalled, err := header.Marshal()
require.NoError(t, err)
signature, err := accountKeys.SignKey.Sign(marhalled)
require.NoError(t, err)
rawHeader := &spacesyncproto.RawSpaceHeader{
SpaceHeader: marhalled,
Signature: signature,
}
marhalledRawHeader, err := rawHeader.Marshal()
require.NoError(t, err)
id := "faisdfjpiocpoakopkop34"
spaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36))
rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marhalledRawHeader,
Id: spaceId,
}
err = validateCreateSpaceHeaderPayload(rawHeaderWithId)
assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err)
}
func TestFailedHeaderPayloadForSpaceCreate_SignedWithAnotherIdentity(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
spaceHeaderSeed := make([]byte, 32)
_, err = rand.Read(spaceHeaderSeed)
require.NoError(t, err)
spaceHeaderPayload := make([]byte, 32)
_, err = rand.Read(spaceHeaderPayload)
require.NoError(t, err)
replicationKey := rand2.Uint64()
header := &spacesyncproto.SpaceHeader{
Identity: identity,
Timestamp: time.Now().Unix(),
SpaceType: "SpaceType",
ReplicationKey: replicationKey,
Seed: spaceHeaderSeed,
SpaceHeaderPayload: spaceHeaderPayload,
}
marhalled, err := header.Marshal()
require.NoError(t, err)
anotherAccountKeys, err := accountdata.NewRandom()
signature, err := anotherAccountKeys.SignKey.Sign(marhalled)
require.NoError(t, err)
rawHeader := &spacesyncproto.RawSpaceHeader{
SpaceHeader: marhalled,
Signature: signature,
}
marhalledRawHeader, err := rawHeader.Marshal()
require.NoError(t, err)
id := "faisdfjpiocpoakopkop34"
spaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36))
rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marhalledRawHeader,
Id: spaceId,
}
err = validateCreateSpaceHeaderPayload(rawHeaderWithId)
assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err)
}
func TestSuccessAclPayloadSpace(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
spaceId := "AnySpaceId"
_, rawWithId, err := rawAclWithId(accountKeys, spaceId)
require.NoError(t, err)
validationSpaceId, err := validateCreateSpaceAclPayload(rawWithId)
require.Equal(t, validationSpaceId, spaceId)
require.NoError(t, err)
}
func TestFailAclPayloadSpace_IncorrectCid(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
readKeyBytes := make([]byte, 32)
_, err = rand.Read(readKeyBytes)
require.NoError(t, err)
readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes)
require.NoError(t, err)
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
require.NoError(t, err)
rawIdentity, err := accountKeys.SignKey.GetPublic().Raw()
require.NoError(t, err)
identitySignature, err := masterKey.Sign(rawIdentity)
require.NoError(t, err)
rawMasterKey, err := masterKey.GetPublic().Marshall()
require.NoError(t, err)
aclRoot := aclrecordproto.AclRoot{
Identity: identity,
MasterKey: rawMasterKey,
SpaceId: "SpaceId",
EncryptedReadKey: readKey,
Timestamp: time.Now().Unix(),
IdentitySignature: identitySignature,
}
marshalled, err := aclRoot.Marshal()
require.NoError(t, err)
signature, err := accountKeys.SignKey.Sign(marshalled)
rawAclRecord := &aclrecordproto.RawAclRecord{
Payload: marshalled,
Signature: signature,
}
marshalledRaw, err := rawAclRecord.Marshal()
require.NoError(t, err)
aclHeadId := "rand"
rawWithId := &aclrecordproto.RawAclRecordWithId{
Payload: marshalledRaw,
Id: aclHeadId,
}
_, err = validateCreateSpaceAclPayload(rawWithId)
assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err)
}
func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
readKeyBytes := make([]byte, 32)
_, err = rand.Read(readKeyBytes)
require.NoError(t, err)
readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes)
require.NoError(t, err)
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
require.NoError(t, err)
rawIdentity, err := accountKeys.SignKey.GetPublic().Raw()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
identitySignature, err := masterKey.Sign(rawIdentity)
require.NoError(t, err)
rawMasterKey, err := masterKey.GetPublic().Raw()
require.NoError(t, err)
aclRoot := aclrecordproto.AclRoot{
Identity: identity,
MasterKey: rawMasterKey,
SpaceId: "SpaceId",
EncryptedReadKey: readKey,
Timestamp: time.Now().Unix(),
IdentitySignature: identitySignature,
}
marshalled, err := aclRoot.Marshal()
require.NoError(t, err)
rawAclRecord := &aclrecordproto.RawAclRecord{
Payload: marshalled,
Signature: marshalled,
}
marshalledRaw, err := rawAclRecord.Marshal()
require.NoError(t, err)
aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw)
require.NoError(t, err)
rawWithId := &aclrecordproto.RawAclRecordWithId{
Payload: marshalledRaw,
Id: aclHeadId,
}
_, err = validateCreateSpaceAclPayload(rawWithId)
assert.NotNil(t, err)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) {
spaceId := "AnySpaceId"
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
readKeyBytes := make([]byte, 32)
_, err = rand.Read(readKeyBytes)
if err != nil {
return
}
readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes)
if err != nil {
return
}
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
if err != nil {
return
}
masterPubKey := masterKey.GetPublic()
identity, err := accountKeys.SignKey.GetPublic().Marshall()
if err != nil {
return
}
rawMasterKey, err := masterPubKey.Marshall()
if err != nil {
return
}
aclRoot := aclrecordproto.AclRoot{
Identity: identity,
MasterKey: rawMasterKey,
SpaceId: spaceId,
EncryptedReadKey: readKey,
Timestamp: time.Now().Unix(),
IdentitySignature: identity,
}
marshalled, err := aclRoot.Marshal()
if err != nil {
return
}
signature, err := accountKeys.SignKey.Sign(marshalled)
rawAclRecord := &aclrecordproto.RawAclRecord{
Payload: marshalled,
Signature: signature,
}
marshalledRaw, err := rawAclRecord.Marshal()
if err != nil {
return
}
aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw)
if err != nil {
return
}
rawWithId := &aclrecordproto.RawAclRecordWithId{
Payload: marshalledRaw,
Id: aclHeadId,
}
_, err = validateCreateSpaceAclPayload(rawWithId)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestSuccessSettingsPayloadSpace(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
spaceSettingsSeed := make([]byte, 32)
_, err = rand.Read(spaceSettingsSeed)
require.NoError(t, err)
changePayload := make([]byte, 32)
_, err = rand.Read(changePayload)
require.NoError(t, err)
spaceId := "SpaceId"
rootChange := &treechangeproto.RootChange{
AclHeadId: "AclHeadId",
SpaceId: spaceId,
ChangeType: "ChangeType",
Timestamp: time.Now().Unix(),
Seed: spaceSettingsSeed,
Identity: identity,
ChangePayload: changePayload,
}
marshalledChange, err := rootChange.Marshal()
require.NoError(t, err)
signature, err := accountKeys.SignKey.Sign(marshalledChange)
require.NoError(t, err)
raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange,
Signature: signature,
}
marshalledRawChange, err := raw.Marshal()
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
require.NoError(t, err)
rawIdChange := &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: id,
}
_, validationSpaceId, err := validateCreateSpaceSettingsPayload(rawIdChange)
require.Equal(t, validationSpaceId, spaceId)
require.NoError(t, err)
}
func TestFailSettingsPayloadSpace_InvalidSignature(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
spaceSettingsSeed := make([]byte, 32)
_, err = rand.Read(spaceSettingsSeed)
require.NoError(t, err)
changePayload := make([]byte, 32)
_, err = rand.Read(changePayload)
require.NoError(t, err)
rootChange := &treechangeproto.RootChange{
AclHeadId: "AclHeadId",
SpaceId: "SpaceId",
ChangeType: "ChangeType",
Timestamp: time.Now().Unix(),
Seed: spaceSettingsSeed,
Identity: identity,
ChangePayload: changePayload,
}
marshalledChange, err := rootChange.Marshal()
require.NoError(t, err)
raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange,
Signature: marshalledChange,
}
marshalledRawChange, err := raw.Marshal()
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
require.NoError(t, err)
rawIdChange := &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: id,
}
_, _, err = validateCreateSpaceSettingsPayload(rawIdChange)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestFailSettingsPayloadSpace_InvalidCid(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
identity, err := accountKeys.SignKey.GetPublic().Marshall()
require.NoError(t, err)
spaceSettingsSeed := make([]byte, 32)
_, err = rand.Read(spaceSettingsSeed)
require.NoError(t, err)
changePayload := make([]byte, 32)
_, err = rand.Read(changePayload)
require.NoError(t, err)
rootChange := &treechangeproto.RootChange{
AclHeadId: "AclHeadId",
SpaceId: "SpaceId",
ChangeType: "ChangeType",
Timestamp: time.Now().Unix(),
Seed: spaceSettingsSeed,
Identity: identity,
ChangePayload: changePayload,
}
marshalledChange, err := rootChange.Marshal()
require.NoError(t, err)
signature, err := accountKeys.SignKey.Sign(marshalledChange)
require.NoError(t, err)
raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange,
Signature: signature,
}
marshalledRawChange, err := raw.Marshal()
id := "id"
require.NoError(t, err)
rawIdChange := &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: id,
}
_, _, err = validateCreateSpaceSettingsPayload(rawIdChange)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestSuccessSameIds(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
aclHeadId, rawAclWithId, err := rawAclWithId(accountKeys, spaceId)
require.NoError(t, err)
rawSettingsPayload, err := rawSettingsPayload(accountKeys, spaceId, aclHeadId)
spacePayload := SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = ValidateSpaceStorageCreatePayload(spacePayload)
require.NoError(t, err)
}
func TestFailWithAclWrongSpaceId(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
aclHeadId, rawAclWithId, err := rawAclWithId(accountKeys, "spaceId")
require.NoError(t, err)
rawSettingsPayload, err := rawSettingsPayload(accountKeys, spaceId, aclHeadId)
spacePayload := SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = ValidateSpaceStorageCreatePayload(spacePayload)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestFailWithSettingsWrongSpaceId(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
aclHeadId, rawAclWithId, err := rawAclWithId(accountKeys, spaceId)
require.NoError(t, err)
rawSettingsPayload, err := rawSettingsPayload(accountKeys, "spaceId", aclHeadId)
spacePayload := SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = ValidateSpaceStorageCreatePayload(spacePayload)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func TestFailWithWrongAclHeadIdInSettingsPayload(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
_, rawAclWithId, err := rawAclWithId(accountKeys, spaceId)
require.NoError(t, err)
rawSettingsPayload, err := rawSettingsPayload(accountKeys, spaceId, "aclHeadId")
spacePayload := SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = ValidateSpaceStorageCreatePayload(spacePayload)
assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err)
}
func rawSettingsPayload(accountKeys *accountdata.AccountKeys, spaceId, aclHeadId string) (rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
identity, err := accountKeys.SignKey.GetPublic().Marshall()
if err != nil {
return
}
spaceSettingsSeed := make([]byte, 32)
_, err = rand.Read(spaceSettingsSeed)
if err != nil {
return
}
changePayload := make([]byte, 32)
_, err = rand.Read(changePayload)
if err != nil {
return
}
rootChange := &treechangeproto.RootChange{
AclHeadId: aclHeadId,
SpaceId: spaceId,
ChangeType: "ChangeType",
Timestamp: time.Now().Unix(),
Seed: spaceSettingsSeed,
Identity: identity,
ChangePayload: changePayload,
}
marshalledChange, err := rootChange.Marshal()
if err != nil {
return
}
signature, err := accountKeys.SignKey.Sign(marshalledChange)
if err != nil {
return
}
raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange,
Signature: signature,
}
marshalledRawChange, err := raw.Marshal()
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
if err != nil {
return
}
rawIdChange = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange,
Id: id,
}
return
}
func rawAclWithId(accountKeys *accountdata.AccountKeys, spaceId string) (aclHeadId string, rawWithId *aclrecordproto.RawAclRecordWithId, err error) {
readKeyBytes := make([]byte, 32)
_, err = rand.Read(readKeyBytes)
if err != nil {
return
}
readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes)
if err != nil {
return
}
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
identity, err := accountKeys.SignKey.GetPublic().Marshall()
if err != nil {
return
}
masterPubKey := masterKey.GetPublic()
rawIdentity, err := accountKeys.SignKey.GetPublic().Raw()
if err != nil {
return
}
identitySignature, err := masterKey.Sign(rawIdentity)
if err != nil {
return
}
rawMasterKey, err := masterPubKey.Marshall()
if err != nil {
return
}
aclRoot := aclrecordproto.AclRoot{
Identity: identity,
MasterKey: rawMasterKey,
SpaceId: spaceId,
EncryptedReadKey: readKey,
Timestamp: time.Now().Unix(),
IdentitySignature: identitySignature,
}
marshalled, err := aclRoot.Marshal()
if err != nil {
return
}
signature, err := accountKeys.SignKey.Sign(marshalled)
rawAclRecord := &aclrecordproto.RawAclRecord{
Payload: marshalled,
Signature: signature,
}
marshalledRaw, err := rawAclRecord.Marshal()
if err != nil {
return
}
aclHeadId, err = cidutil.NewCidFromBytes(marshalledRaw)
if err != nil {
return
}
rawWithId = &aclrecordproto.RawAclRecordWithId{
Payload: marshalledRaw,
Id: aclHeadId,
}
return
}
func rawHeaderWithId(accountKeys *accountdata.AccountKeys) (spaceId string, rawWithId *spacesyncproto.RawSpaceHeaderWithId, err error) {
identity, err := accountKeys.SignKey.GetPublic().Marshall()
if err != nil {
return
}
spaceHeaderSeed := make([]byte, 32)
_, err = rand.Read(spaceHeaderSeed)
if err != nil {
return
}
spaceHeaderPayload := make([]byte, 32)
_, err = rand.Read(spaceHeaderPayload)
if err != nil {
return
}
replicationKey := rand2.Uint64()
header := &spacesyncproto.SpaceHeader{
Identity: identity,
Timestamp: time.Now().Unix(),
SpaceType: "SpaceType",
ReplicationKey: replicationKey,
Seed: spaceHeaderSeed,
SpaceHeaderPayload: spaceHeaderPayload,
}
marhalled, err := header.Marshal()
if err != nil {
return
}
signature, err := accountKeys.SignKey.Sign(marhalled)
if err != nil {
return
}
rawHeader := &spacesyncproto.RawSpaceHeader{
SpaceHeader: marhalled,
Signature: signature,
}
marhalledRawHeader, err := rawHeader.Marshal()
if err != nil {
return
}
id, err := cidutil.NewCidFromBytes(marhalledRawHeader)
if err != nil {
return
}
spaceId = fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36))
rawWithId = &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marhalledRawHeader,
Id: spaceId,
}
return
}

39
metric/log.go Normal file
View file

@ -0,0 +1,39 @@
package metric
import (
"go.uber.org/zap"
"golang.org/x/net/context"
"time"
)
func Method(val string) zap.Field {
return zap.String("rpc", val)
}
func QueueDur(val time.Duration) zap.Field {
return zap.Int64("queueMs", val.Milliseconds())
}
func TotalDur(val time.Duration) zap.Field {
return zap.Int64("totalMs", val.Milliseconds())
}
func SpaceId(val string) zap.Field {
return zap.String("spaceId", val)
}
func ObjectId(val string) zap.Field {
return zap.String("objectId", val)
}
func Identity(val string) zap.Field {
return zap.String("identity", val)
}
func IP(val string) zap.Field {
return zap.String("ip", val)
}
func (m *metric) RequestLog(ctx context.Context, fields ...zap.Field) {
m.rpcLog.InfoCtx(ctx, "", fields...)
}

View file

@ -24,6 +24,7 @@ func New() Metric {
type Metric interface { type Metric interface {
Registry() *prometheus.Registry Registry() *prometheus.Registry
WrapDRPCHandler(h drpc.Handler) drpc.Handler WrapDRPCHandler(h drpc.Handler) drpc.Handler
RequestLog(ctx context.Context, fields ...zap.Field)
app.ComponentRunnable app.ComponentRunnable
} }