mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-08 05:57:03 +09:00
Add record verifier and encoding
This commit is contained in:
parent
3ab01e7d96
commit
79d0352d6d
10 changed files with 358 additions and 113 deletions
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/anyproto/any-sync/commonspace/object/accountdata"
|
"github.com/anyproto/any-sync/commonspace/object/accountdata"
|
||||||
|
"github.com/anyproto/any-sync/commonspace/object/acl/recordverifier"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||||
"github.com/anyproto/any-sync/commonspace/spacepayloads"
|
"github.com/anyproto/any-sync/commonspace/spacepayloads"
|
||||||
"github.com/anyproto/any-sync/commonspace/spacestorage"
|
"github.com/anyproto/any-sync/commonspace/spacestorage"
|
||||||
|
@ -17,6 +18,14 @@ import (
|
||||||
"github.com/anyproto/any-sync/util/crypto"
|
"github.com/anyproto/any-sync/util/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func mockDeps() Deps {
|
||||||
|
return Deps{
|
||||||
|
TreeSyncer: mockTreeSyncer{},
|
||||||
|
SyncStatus: syncstatus.NewNoOpSyncStatus(),
|
||||||
|
recordVerifier: recordverifier.NewAlwaysAccept(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createTree(t *testing.T, ctx context.Context, spc Space, acc *accountdata.AccountKeys) string {
|
func createTree(t *testing.T, ctx context.Context, spc Space, acc *accountdata.AccountKeys) string {
|
||||||
bytes := make([]byte, 32)
|
bytes := make([]byte, 32)
|
||||||
rand.Read(bytes)
|
rand.Read(bytes)
|
||||||
|
@ -60,7 +69,7 @@ func TestSpaceDeleteIdsMarkDeleted(t *testing.T) {
|
||||||
require.NotNil(t, sp)
|
require.NotNil(t, sp)
|
||||||
|
|
||||||
// initializing space
|
// initializing space
|
||||||
spc, err := fx.spaceService.NewSpace(ctx, sp, Deps{TreeSyncer: mockTreeSyncer{}, SyncStatus: syncstatus.NewNoOpSyncStatus()})
|
spc, err := fx.spaceService.NewSpace(ctx, sp, mockDeps())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, spc)
|
require.NotNil(t, spc)
|
||||||
// adding space to tree manager
|
// adding space to tree manager
|
||||||
|
@ -109,7 +118,7 @@ func TestSpaceDeleteIdsMarkDeleted(t *testing.T) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
storeSetter := fx.storageProvider.(storeSetter)
|
storeSetter := fx.storageProvider.(storeSetter)
|
||||||
storeSetter.SetStore(sp, newStore)
|
storeSetter.SetStore(sp, newStore)
|
||||||
spc, err = fx.spaceService.NewSpace(ctx, sp, Deps{TreeSyncer: mockTreeSyncer{}, SyncStatus: syncstatus.NewNoOpSyncStatus()})
|
spc, err = fx.spaceService.NewSpace(ctx, sp, mockDeps())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, spc)
|
require.NotNil(t, spc)
|
||||||
waitTest := make(chan struct{})
|
waitTest := make(chan struct{})
|
||||||
|
@ -153,7 +162,7 @@ func TestSpaceDeleteIds(t *testing.T) {
|
||||||
require.NotNil(t, sp)
|
require.NotNil(t, sp)
|
||||||
|
|
||||||
// initializing space
|
// initializing space
|
||||||
spc, err := fx.spaceService.NewSpace(ctx, sp, Deps{TreeSyncer: mockTreeSyncer{}, SyncStatus: syncstatus.NewNoOpSyncStatus()})
|
spc, err := fx.spaceService.NewSpace(ctx, sp, mockDeps())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, spc)
|
require.NotNil(t, spc)
|
||||||
// adding space to tree manager
|
// adding space to tree manager
|
||||||
|
@ -202,7 +211,7 @@ func TestSpaceDeleteIds(t *testing.T) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
storeSetter := fx.storageProvider.(storeSetter)
|
storeSetter := fx.storageProvider.(storeSetter)
|
||||||
storeSetter.SetStore(sp, newStore)
|
storeSetter.SetStore(sp, newStore)
|
||||||
spc, err = fx.spaceService.NewSpace(ctx, sp, Deps{TreeSyncer: mockTreeSyncer{}, SyncStatus: syncstatus.NewNoOpSyncStatus()})
|
spc, err = fx.spaceService.NewSpace(ctx, sp, mockDeps())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, spc)
|
require.NotNil(t, spc)
|
||||||
waitTest := make(chan struct{})
|
waitTest := make(chan struct{})
|
||||||
|
|
24
commonspace/object/acl/recordverifier/alwaysaccept.go
Normal file
24
commonspace/object/acl/recordverifier/alwaysaccept.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package recordverifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anyproto/any-sync/app"
|
||||||
|
"github.com/anyproto/any-sync/consensus/consensusproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AlwaysAccept struct{}
|
||||||
|
|
||||||
|
func NewAlwaysAccept() RecordVerifier {
|
||||||
|
return &AlwaysAccept{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlwaysAccept) Init(_ *app.App) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlwaysAccept) Name() string {
|
||||||
|
return CName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlwaysAccept) VerifyAcceptor(_ *consensusproto.RawRecord) error {
|
||||||
|
return nil
|
||||||
|
}
|
55
commonspace/object/acl/recordverifier/recordverifier.go
Normal file
55
commonspace/object/acl/recordverifier/recordverifier.go
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package recordverifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/anyproto/any-sync/app"
|
||||||
|
"github.com/anyproto/any-sync/commonspace/object/acl/list"
|
||||||
|
"github.com/anyproto/any-sync/consensus/consensusproto"
|
||||||
|
"github.com/anyproto/any-sync/nodeconf"
|
||||||
|
"github.com/anyproto/any-sync/util/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CName = "common.acl.recordverifier"
|
||||||
|
|
||||||
|
type RecordVerifier interface {
|
||||||
|
app.Component
|
||||||
|
list.AcceptorVerifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() RecordVerifier {
|
||||||
|
return &recordVerifier{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type recordVerifier struct {
|
||||||
|
configuration nodeconf.NodeConf
|
||||||
|
networkKey crypto.PubKey
|
||||||
|
store crypto.KeyStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *recordVerifier) Init(a *app.App) (err error) {
|
||||||
|
r.configuration = a.MustComponent(nodeconf.CName).(nodeconf.NodeConf)
|
||||||
|
r.store = crypto.NewKeyStorage()
|
||||||
|
networkId := r.configuration.Configuration().NetworkId
|
||||||
|
r.networkKey, err = crypto.DecodeNetworkId(networkId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *recordVerifier) Name() (name string) {
|
||||||
|
return CName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *recordVerifier) VerifyAcceptor(rec *consensusproto.RawRecord) (err error) {
|
||||||
|
identity, err := r.store.PubKeyFromProto(rec.AcceptorIdentity)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get acceptor identity: %w", err)
|
||||||
|
}
|
||||||
|
if !identity.Equals(r.networkKey) {
|
||||||
|
return fmt.Errorf("acceptor identity does not match network key")
|
||||||
|
}
|
||||||
|
verified, err := r.networkKey.Verify(rec.Payload, rec.AcceptorSignature)
|
||||||
|
if !verified || err != nil {
|
||||||
|
return fmt.Errorf("failed to verify acceptor: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
108
commonspace/object/acl/recordverifier/recordverifier_test.go
Normal file
108
commonspace/object/acl/recordverifier/recordverifier_test.go
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
package recordverifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anyproto/any-sync/app"
|
||||||
|
"github.com/anyproto/any-sync/consensus/consensusproto"
|
||||||
|
"github.com/anyproto/any-sync/nodeconf/testconf"
|
||||||
|
"github.com/anyproto/any-sync/testutil/accounttest"
|
||||||
|
"github.com/anyproto/any-sync/util/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fixture struct {
|
||||||
|
*recordVerifier
|
||||||
|
app *app.App
|
||||||
|
networkPrivKey crypto.PrivKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFixture(t *testing.T) *fixture {
|
||||||
|
accService := &accounttest.AccountTestService{}
|
||||||
|
a := &app.App{}
|
||||||
|
verifier := &recordVerifier{}
|
||||||
|
a.Register(accService).
|
||||||
|
Register(&testconf.StubConf{}).
|
||||||
|
Register(verifier)
|
||||||
|
require.NoError(t, a.Start(context.Background()))
|
||||||
|
return &fixture{
|
||||||
|
recordVerifier: verifier,
|
||||||
|
app: a,
|
||||||
|
networkPrivKey: accService.Account().SignKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecordVerifier_VerifyAcceptor(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
identity, err := fx.networkPrivKey.GetPublic().Marshall()
|
||||||
|
require.NoError(t, err)
|
||||||
|
testPayload := []byte("test payload")
|
||||||
|
acceptorSignature, err := fx.networkPrivKey.Sign(testPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
rawRecord := &consensusproto.RawRecord{
|
||||||
|
AcceptorIdentity: identity,
|
||||||
|
Payload: testPayload,
|
||||||
|
AcceptorSignature: acceptorSignature,
|
||||||
|
}
|
||||||
|
err = fx.VerifyAcceptor(rawRecord)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecordVerifier_VerifyAcceptor_InvalidSignature(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
identity, err := fx.networkPrivKey.GetPublic().Marshall()
|
||||||
|
require.NoError(t, err)
|
||||||
|
testPayload := []byte("test payload")
|
||||||
|
rawRecord := &consensusproto.RawRecord{
|
||||||
|
AcceptorIdentity: identity,
|
||||||
|
Payload: testPayload,
|
||||||
|
AcceptorSignature: []byte("invalid signature"),
|
||||||
|
}
|
||||||
|
err = fx.VerifyAcceptor(rawRecord)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecordVerifier_VerifyAcceptor_ModifiedPayload(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
identity, err := fx.networkPrivKey.GetPublic().Marshall()
|
||||||
|
require.NoError(t, err)
|
||||||
|
testPayload := []byte("test payload")
|
||||||
|
acceptorSignature, err := fx.networkPrivKey.Sign(testPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
rawRecord := &consensusproto.RawRecord{
|
||||||
|
AcceptorIdentity: identity,
|
||||||
|
Payload: []byte("modified payload"),
|
||||||
|
AcceptorSignature: acceptorSignature,
|
||||||
|
}
|
||||||
|
err = fx.VerifyAcceptor(rawRecord)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecordVerifier_VerifyAcceptor_InvalidIdentity(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
testPayload := []byte("test payload")
|
||||||
|
acceptorSignature, err := fx.networkPrivKey.Sign(testPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
rawRecord := &consensusproto.RawRecord{
|
||||||
|
AcceptorIdentity: []byte("invalid identity"),
|
||||||
|
Payload: testPayload,
|
||||||
|
AcceptorSignature: acceptorSignature,
|
||||||
|
}
|
||||||
|
err = fx.VerifyAcceptor(rawRecord)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecordVerifier_VerifyAcceptor_EmptySignature(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
identity, err := fx.networkPrivKey.GetPublic().Marshall()
|
||||||
|
require.NoError(t, err)
|
||||||
|
rawRecord := &consensusproto.RawRecord{
|
||||||
|
AcceptorIdentity: identity,
|
||||||
|
Payload: []byte("test payload"),
|
||||||
|
AcceptorSignature: nil,
|
||||||
|
}
|
||||||
|
err = fx.VerifyAcceptor(rawRecord)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/anyproto/any-sync/accountservice"
|
"github.com/anyproto/any-sync/accountservice"
|
||||||
"github.com/anyproto/any-sync/app"
|
"github.com/anyproto/any-sync/app"
|
||||||
|
"github.com/anyproto/any-sync/commonspace/object/acl/recordverifier"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/tree/synctree"
|
"github.com/anyproto/any-sync/commonspace/object/tree/synctree"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/treemanager"
|
"github.com/anyproto/any-sync/commonspace/object/treemanager"
|
||||||
|
@ -129,6 +130,7 @@ func (r *RpcServer) getSpace(ctx context.Context, spaceId string) (sp Space, err
|
||||||
sp, err = r.spaceService.NewSpace(ctx, spaceId, Deps{
|
sp, err = r.spaceService.NewSpace(ctx, spaceId, Deps{
|
||||||
TreeSyncer: NewTreeSyncer(spaceId),
|
TreeSyncer: NewTreeSyncer(spaceId),
|
||||||
SyncStatus: syncstatus.NewNoOpSyncStatus(),
|
SyncStatus: syncstatus.NewNoOpSyncStatus(),
|
||||||
|
recordVerifier: recordverifier.NewAlwaysAccept(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/anyproto/any-sync/commonspace/acl/aclclient"
|
"github.com/anyproto/any-sync/commonspace/acl/aclclient"
|
||||||
"github.com/anyproto/any-sync/commonspace/deletionmanager"
|
"github.com/anyproto/any-sync/commonspace/deletionmanager"
|
||||||
|
"github.com/anyproto/any-sync/commonspace/object/acl/recordverifier"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/keyvalue"
|
"github.com/anyproto/any-sync/commonspace/object/keyvalue"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/keyvalue/keyvaluestorage"
|
"github.com/anyproto/any-sync/commonspace/object/keyvalue/keyvaluestorage"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/treesyncer"
|
"github.com/anyproto/any-sync/commonspace/object/treesyncer"
|
||||||
|
@ -72,6 +73,7 @@ type Deps struct {
|
||||||
SyncStatus syncstatus.StatusUpdater
|
SyncStatus syncstatus.StatusUpdater
|
||||||
TreeSyncer treesyncer.TreeSyncer
|
TreeSyncer treesyncer.TreeSyncer
|
||||||
AccountService accountservice.Service
|
AccountService accountservice.Service
|
||||||
|
recordVerifier recordverifier.RecordVerifier
|
||||||
Indexer keyvaluestorage.Indexer
|
Indexer keyvaluestorage.Indexer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +190,13 @@ func (s *spaceService) NewSpace(ctx context.Context, id string, deps Deps) (Spac
|
||||||
if deps.Indexer != nil {
|
if deps.Indexer != nil {
|
||||||
keyValueIndexer = deps.Indexer
|
keyValueIndexer = deps.Indexer
|
||||||
}
|
}
|
||||||
|
recordVerifier := recordverifier.New()
|
||||||
|
if deps.recordVerifier != nil {
|
||||||
|
recordVerifier = deps.recordVerifier
|
||||||
|
}
|
||||||
spaceApp.Register(state).
|
spaceApp.Register(state).
|
||||||
Register(deps.SyncStatus).
|
Register(deps.SyncStatus).
|
||||||
|
Register(recordVerifier).
|
||||||
Register(peerManager).
|
Register(peerManager).
|
||||||
Register(st).
|
Register(st).
|
||||||
Register(keyValueIndexer).
|
Register(keyValueIndexer).
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
anystore "github.com/anyproto/any-store"
|
anystore "github.com/anyproto/any-store"
|
||||||
"github.com/anyproto/go-chash"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"storj.io/drpc"
|
"storj.io/drpc"
|
||||||
|
@ -44,114 +43,12 @@ import (
|
||||||
"github.com/anyproto/any-sync/net/streampool/streamhandler"
|
"github.com/anyproto/any-sync/net/streampool/streamhandler"
|
||||||
"github.com/anyproto/any-sync/node/nodeclient"
|
"github.com/anyproto/any-sync/node/nodeclient"
|
||||||
"github.com/anyproto/any-sync/nodeconf"
|
"github.com/anyproto/any-sync/nodeconf"
|
||||||
|
"github.com/anyproto/any-sync/nodeconf/testconf"
|
||||||
"github.com/anyproto/any-sync/testutil/accounttest"
|
"github.com/anyproto/any-sync/testutil/accounttest"
|
||||||
"github.com/anyproto/any-sync/util/crypto"
|
"github.com/anyproto/any-sync/util/crypto"
|
||||||
"github.com/anyproto/any-sync/util/syncqueues"
|
"github.com/anyproto/any-sync/util/syncqueues"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockConf struct {
|
|
||||||
id string
|
|
||||||
networkId string
|
|
||||||
configuration nodeconf.Configuration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) NetworkCompatibilityStatus() nodeconf.NetworkCompatibilityStatus {
|
|
||||||
return nodeconf.NetworkCompatibilityStatusOk
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Init(a *app.App) (err error) {
|
|
||||||
accountKeys := a.MustComponent(accountService.CName).(accountService.Service).Account()
|
|
||||||
networkId := accountKeys.SignKey.GetPublic().Network()
|
|
||||||
node := nodeconf.Node{
|
|
||||||
PeerId: accountKeys.PeerId,
|
|
||||||
Addresses: []string{"127.0.0.1:4430"},
|
|
||||||
Types: []nodeconf.NodeType{nodeconf.NodeTypeTree},
|
|
||||||
}
|
|
||||||
m.id = networkId
|
|
||||||
m.networkId = networkId
|
|
||||||
m.configuration = nodeconf.Configuration{
|
|
||||||
Id: networkId,
|
|
||||||
NetworkId: networkId,
|
|
||||||
Nodes: []nodeconf.Node{node},
|
|
||||||
CreationTime: time.Now(),
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Name() (name string) {
|
|
||||||
return nodeconf.CName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Run(ctx context.Context) (err error) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Close(ctx context.Context) (err error) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Id() string {
|
|
||||||
return m.id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Configuration() nodeconf.Configuration {
|
|
||||||
return m.configuration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) NodeIds(spaceId string) []string {
|
|
||||||
var nodeIds []string
|
|
||||||
for _, node := range m.configuration.Nodes {
|
|
||||||
nodeIds = append(nodeIds, node.PeerId)
|
|
||||||
}
|
|
||||||
return nodeIds
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) IsResponsible(spaceId string) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) FilePeers() []string {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) ConsensusPeers() []string {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) CoordinatorPeers() []string {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) NamingNodePeers() []string {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) PaymentProcessingNodePeers() []string {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) PeerAddresses(peerId string) (addrs []string, ok bool) {
|
|
||||||
if peerId == m.configuration.Nodes[0].PeerId {
|
|
||||||
return m.configuration.Nodes[0].Addresses, true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) CHash() chash.CHash {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) Partition(spaceId string) (part int) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockConf) NodeTypes(nodeId string) []nodeconf.NodeType {
|
|
||||||
if nodeId == m.configuration.Nodes[0].PeerId {
|
|
||||||
return m.configuration.Nodes[0].Types
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ nodeclient.NodeClient = (*mockNodeClient)(nil)
|
var _ nodeclient.NodeClient = (*mockNodeClient)(nil)
|
||||||
|
|
||||||
type mockNodeClient struct {
|
type mockNodeClient struct {
|
||||||
|
@ -654,7 +551,7 @@ func newFixture(t *testing.T) *spaceFixture {
|
||||||
app: &app.App{},
|
app: &app.App{},
|
||||||
config: &mockConfig{},
|
config: &mockConfig{},
|
||||||
account: &accounttest.AccountTestService{},
|
account: &accounttest.AccountTestService{},
|
||||||
configurationService: &mockConf{},
|
configurationService: &testconf.StubConf{},
|
||||||
streamOpener: newStreamOpener("spaceId"),
|
streamOpener: newStreamOpener("spaceId"),
|
||||||
peerManagerProvider: &testPeerManagerProvider{},
|
peerManagerProvider: &testPeerManagerProvider{},
|
||||||
storageProvider: &spaceStorageProvider{rootPath: t.TempDir()},
|
storageProvider: &spaceStorageProvider{rootPath: t.TempDir()},
|
||||||
|
@ -699,7 +596,7 @@ func newPeerFixture(t *testing.T, spaceId string, keys *accountdata.AccountKeys,
|
||||||
app: &app.App{},
|
app: &app.App{},
|
||||||
config: &mockConfig{},
|
config: &mockConfig{},
|
||||||
account: accounttest.NewWithAcc(keys),
|
account: accounttest.NewWithAcc(keys),
|
||||||
configurationService: &mockConf{},
|
configurationService: &testconf.StubConf{},
|
||||||
storageProvider: provider,
|
storageProvider: provider,
|
||||||
streamOpener: newStreamOpener(spaceId),
|
streamOpener: newStreamOpener(spaceId),
|
||||||
peerManagerProvider: &testPeerManagerProvider{},
|
peerManagerProvider: &testPeerManagerProvider{},
|
||||||
|
|
115
nodeconf/testconf/nodeconf.go
Normal file
115
nodeconf/testconf/nodeconf.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package testconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/anyproto/go-chash"
|
||||||
|
|
||||||
|
accountService "github.com/anyproto/any-sync/accountservice"
|
||||||
|
"github.com/anyproto/any-sync/app"
|
||||||
|
"github.com/anyproto/any-sync/nodeconf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StubConf struct {
|
||||||
|
id string
|
||||||
|
networkId string
|
||||||
|
configuration nodeconf.Configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) NetworkCompatibilityStatus() nodeconf.NetworkCompatibilityStatus {
|
||||||
|
return nodeconf.NetworkCompatibilityStatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Init(a *app.App) (err error) {
|
||||||
|
accountKeys := a.MustComponent(accountService.CName).(accountService.Service).Account()
|
||||||
|
networkId := accountKeys.SignKey.GetPublic().Network()
|
||||||
|
node := nodeconf.Node{
|
||||||
|
PeerId: accountKeys.PeerId,
|
||||||
|
Addresses: []string{"127.0.0.1:4430"},
|
||||||
|
Types: []nodeconf.NodeType{nodeconf.NodeTypeTree},
|
||||||
|
}
|
||||||
|
m.id = networkId
|
||||||
|
m.networkId = networkId
|
||||||
|
m.configuration = nodeconf.Configuration{
|
||||||
|
Id: networkId,
|
||||||
|
NetworkId: networkId,
|
||||||
|
Nodes: []nodeconf.Node{node},
|
||||||
|
CreationTime: time.Now(),
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Name() (name string) {
|
||||||
|
return nodeconf.CName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Run(ctx context.Context) (err error) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Close(ctx context.Context) (err error) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Id() string {
|
||||||
|
return m.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Configuration() nodeconf.Configuration {
|
||||||
|
return m.configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) NodeIds(spaceId string) []string {
|
||||||
|
var nodeIds []string
|
||||||
|
for _, node := range m.configuration.Nodes {
|
||||||
|
nodeIds = append(nodeIds, node.PeerId)
|
||||||
|
}
|
||||||
|
return nodeIds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) IsResponsible(spaceId string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) FilePeers() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) ConsensusPeers() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) CoordinatorPeers() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) NamingNodePeers() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) PaymentProcessingNodePeers() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) PeerAddresses(peerId string) (addrs []string, ok bool) {
|
||||||
|
if peerId == m.configuration.Nodes[0].PeerId {
|
||||||
|
return m.configuration.Nodes[0].Addresses, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) CHash() chash.CHash {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) Partition(spaceId string) (part int) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StubConf) NodeTypes(nodeId string) []nodeconf.NodeType {
|
||||||
|
if nodeId == m.configuration.Nodes[0].PeerId {
|
||||||
|
return m.configuration.Nodes[0].Types
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -2,8 +2,10 @@ package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"github.com/anyproto/any-sync/util/strkey"
|
|
||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
|
||||||
|
"github.com/anyproto/any-sync/util/strkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EncodeKeyToString[T Key](key T) (str string, err error) {
|
func EncodeKeyToString[T Key](key T) (str string, err error) {
|
||||||
|
@ -55,3 +57,11 @@ func DecodePeerId(peerId string) (PubKey, error) {
|
||||||
}
|
}
|
||||||
return UnmarshalEd25519PublicKey(raw)
|
return UnmarshalEd25519PublicKey(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DecodeNetworkId(networkId string) (PubKey, error) {
|
||||||
|
pubKeyRaw, err := strkey.Decode(strkey.NetworkAddressVersionByte, networkId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return UnmarshalEd25519PublicKey(pubKeyRaw)
|
||||||
|
}
|
||||||
|
|
18
util/crypto/decode_test.go
Normal file
18
util/crypto/decode_test.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeNetworkId(t *testing.T) {
|
||||||
|
_, pubKey, err := GenerateRandomEd25519KeyPair()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
networkId := pubKey.Network()
|
||||||
|
require.Equal(t, uint8('N'), networkId[0])
|
||||||
|
decodedKey, err := DecodeNetworkId(networkId)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, pubKey, decodedKey)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue