Merge branch 'main' into fix-settings-state

This commit is contained in:
mcrakhman 2023-05-23 12:12:49 +02:00
commit 6fd7a894eb
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
24 changed files with 539 additions and 114 deletions

View File

@ -8,6 +8,7 @@ import (
"go.uber.org/zap"
"os"
"runtime"
"runtime/debug"
"strings"
"sync"
"time"
@ -15,8 +16,8 @@ import (
var (
// values of this vars will be defined while compilation
GitCommit, GitBranch, GitState, GitSummary, BuildDate string
name string
AppName, GitCommit, GitBranch, GitState, GitSummary, BuildDate string
name string
)
var (
@ -54,11 +55,12 @@ type ComponentStatable interface {
// App is the central part of the application
// It contains and manages all components
type App struct {
components []Component
mu sync.RWMutex
startStat Stat
stopStat Stat
deviceState int
components []Component
mu sync.RWMutex
startStat Stat
stopStat Stat
deviceState int
anySyncVersion string
}
// Name returns app name
@ -66,6 +68,10 @@ func (app *App) Name() string {
return name
}
func (app *App) AppName() string {
return AppName
}
// Version return app version
func (app *App) Version() string {
return GitSummary
@ -257,7 +263,7 @@ func (app *App) Close(ctx context.Context) error {
case <-time.After(StopWarningAfter):
statLogger(app.stopStat, log).
With(zap.String("in_progress", currentComponentStopping)).
Warn("components close in progress")
Warn("components close in progress")
}
}()
go func() {
@ -311,3 +317,20 @@ func (app *App) SetDeviceState(state int) {
}
}
}
var onceVersion sync.Once
func (app *App) AnySyncVersion() string {
onceVersion.Do(func() {
info, ok := debug.ReadBuildInfo()
if ok {
for _, mod := range info.Deps {
if mod.Path == "github.com/anytypeio/any-sync" {
app.anySyncVersion = mod.Version
break
}
}
}
})
return app.anySyncVersion
}

View File

@ -35,6 +35,10 @@ func Identity(val string) zap.Field {
return zap.String("identity", val)
}
func App(app string) zap.Field {
return zap.String("app", app)
}
func FileId(fileId string) zap.Field {
return zap.String("fileId", fileId)
}
@ -57,5 +61,5 @@ func (m *metric) RequestLog(ctx context.Context, rpc string, fields ...zap.Field
if ak != nil {
acc = ak.Account()
}
m.rpcLog.Info("", append(fields, PeerId(peerId), Identity(acc), Method(rpc))...)
m.rpcLog.Info("", append(fields, m.appField, PeerId(peerId), Identity(acc), Method(rpc))...)
}

View File

@ -3,10 +3,11 @@ package metric
import (
"context"
"github.com/anytypeio/any-sync/app/logger"
"go.uber.org/zap"
"testing"
)
func TestLog(t *testing.T) {
m := &metric{rpcLog: logger.NewNamed("rpcLog")}
m := &metric{rpcLog: logger.NewNamed("rpcLog"), appField: zap.String("appName", "test")}
m.RequestLog(context.Background(), "rpc")
}

View File

@ -32,12 +32,16 @@ type metric struct {
registry *prometheus.Registry
rpcLog logger.CtxLogger
config Config
a *app.App
appField zap.Field
}
func (m *metric) Init(a *app.App) (err error) {
m.a = a
m.registry = prometheus.NewRegistry()
m.config = a.MustComponent("config").(configSource).GetMetric()
m.rpcLog = logger.NewNamed("rpcLog")
m.appField = App(a.Version())
return nil
}
@ -52,6 +56,9 @@ func (m *metric) Run(ctx context.Context) (err error) {
if err = m.registry.Register(collectors.NewGoCollector()); err != nil {
return err
}
if err = m.registry.Register(newVersionsCollector(m.a)); err != nil {
return
}
if m.config.Addr != "" {
var errCh = make(chan error)
http.Handle("/metrics", promhttp.HandlerFor(m.registry, promhttp.HandlerOpts{}))

30
metric/version.go Normal file
View File

@ -0,0 +1,30 @@
package metric
import (
"github.com/anytypeio/any-sync/app"
"github.com/prometheus/client_golang/prometheus"
)
func newVersionsCollector(a *app.App) prometheus.Collector {
return &versionCollector{prometheus.MustNewConstMetric(prometheus.NewDesc(
"anysync_versions",
"Build information about the main Go module.",
nil, prometheus.Labels{
"anysync_version": a.AnySyncVersion(),
"app_name": a.AppName(),
"app_version": a.Version(),
},
), prometheus.GaugeValue, 1)}
}
type versionCollector struct {
ver prometheus.Metric
}
func (v *versionCollector) Describe(descs chan<- *prometheus.Desc) {
descs <- v.ver.Desc()
}
func (v *versionCollector) Collect(metrics chan<- prometheus.Metric) {
metrics <- v.ver
}

View File

@ -1,5 +1,11 @@
package net
import "errors"
var (
ErrUnableToConnect = errors.New("unable to connect")
)
type ConfigGetter interface {
GetNet() Config
}

View File

@ -9,6 +9,7 @@ import (
net2 "github.com/anytypeio/any-sync/net"
"github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/net/secureservice"
"github.com/anytypeio/any-sync/net/secureservice/handshake"
"github.com/anytypeio/any-sync/net/timeoutconn"
"github.com/anytypeio/any-sync/nodeconf"
"github.com/libp2p/go-libp2p/core/sec"
@ -120,6 +121,9 @@ func (d *dialer) handshake(ctx context.Context, addr, peerId string) (conn drpc.
timeoutConn := timeoutconn.NewConn(tcpConn, time.Millisecond*time.Duration(d.config.Stream.TimeoutMilliseconds))
sc, err = d.transport.SecureOutbound(ctx, timeoutConn)
if err != nil {
if he, ok := err.(handshake.HandshakeError); ok {
return nil, nil, he
}
return nil, nil, fmt.Errorf("tls handshaeke error: %v; since start: %v", err, time.Since(st))
}
if peerId != sc.RemotePeer().String() {

View File

@ -2,18 +2,15 @@ package pool
import (
"context"
"errors"
"github.com/anytypeio/any-sync/app/ocache"
"github.com/anytypeio/any-sync/net"
"github.com/anytypeio/any-sync/net/dialer"
"github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/net/secureservice/handshake"
"go.uber.org/zap"
"math/rand"
)
var (
ErrUnableToConnect = errors.New("unable to connect")
)
// Pool creates and caches outgoing connection
type Pool interface {
// Get lookups to peer in existing connections or creates and cache new one
@ -76,14 +73,19 @@ func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error
peerIds[i], peerIds[j] = peerIds[j], peerIds[i]
})
// connecting
var lastErr error
for _, peerId := range peerIds {
if v, err := p.cache.Get(ctx, peerId); err == nil {
return v.(peer.Peer), nil
} else {
log.Debug("unable to connect", zap.String("peerId", peerId), zap.Error(err))
lastErr = err
}
}
return nil, ErrUnableToConnect
if _, ok := lastErr.(handshake.HandshakeError); !ok {
lastErr = net.ErrUnableToConnect
}
return nil, lastErr
}
func (p *pool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) {
@ -92,14 +94,19 @@ func (p *pool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, erro
peerIds[i], peerIds[j] = peerIds[j], peerIds[i]
})
// connecting
var lastErr error
for _, peerId := range peerIds {
if v, err := p.dialer.Dial(ctx, peerId); err == nil {
return v.(peer.Peer), nil
} else {
log.Debug("unable to connect", zap.String("peerId", peerId), zap.Error(err))
lastErr = err
}
}
return nil, ErrUnableToConnect
if _, ok := lastErr.(handshake.HandshakeError); !ok {
lastErr = net.ErrUnableToConnect
}
return nil, lastErr
}
func (p *pool) Close(ctx context.Context) (err error) {

View File

@ -5,8 +5,10 @@ import (
"errors"
"fmt"
"github.com/anytypeio/any-sync/app"
"github.com/anytypeio/any-sync/net"
"github.com/anytypeio/any-sync/net/dialer"
"github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/net/secureservice/handshake"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"storj.io/drpc"
@ -116,7 +118,17 @@ func TestPool_GetOneOf(t *testing.T) {
return nil, fmt.Errorf("persistent error")
}
p, err := fx.GetOneOf(ctx, []string{"3", "2", "1"})
assert.Equal(t, ErrUnableToConnect, err)
assert.Equal(t, net.ErrUnableToConnect, err)
assert.Nil(t, p)
})
t.Run("handshake error", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish()
fx.Dialer.dial = func(ctx context.Context, peerId string) (peer peer.Peer, err error) {
return nil, handshake.ErrIncompatibleVersion
}
p, err := fx.GetOneOf(ctx, []string{"3", "2", "1"})
assert.Equal(t, handshake.ErrIncompatibleVersion, err)
assert.Nil(t, p)
})
}

View File

@ -9,8 +9,10 @@ import (
"go.uber.org/zap"
)
func newNoVerifyChecker() handshake.CredentialChecker {
return &noVerifyChecker{cred: &handshakeproto.Credentials{Type: handshakeproto.CredentialsType_SkipVerify}}
func newNoVerifyChecker(protoVersion uint32) handshake.CredentialChecker {
return &noVerifyChecker{
cred: &handshakeproto.Credentials{Type: handshakeproto.CredentialsType_SkipVerify, Version: protoVersion},
}
}
type noVerifyChecker struct {
@ -22,15 +24,22 @@ func (n noVerifyChecker) MakeCredentials(sc sec.SecureConn) *handshakeproto.Cred
}
func (n noVerifyChecker) CheckCredential(sc sec.SecureConn, cred *handshakeproto.Credentials) (identity []byte, err error) {
if cred.Version != n.cred.Version {
return nil, handshake.ErrIncompatibleVersion
}
return nil, nil
}
func newPeerSignVerifier(account *accountdata.AccountKeys) handshake.CredentialChecker {
return &peerSignVerifier{account: account}
func newPeerSignVerifier(protoVersion uint32, account *accountdata.AccountKeys) handshake.CredentialChecker {
return &peerSignVerifier{
protoVersion: protoVersion,
account: account,
}
}
type peerSignVerifier struct {
account *accountdata.AccountKeys
protoVersion uint32
account *accountdata.AccountKeys
}
func (p *peerSignVerifier) MakeCredentials(sc sec.SecureConn) *handshakeproto.Credentials {
@ -48,10 +57,14 @@ func (p *peerSignVerifier) MakeCredentials(sc sec.SecureConn) *handshakeproto.Cr
return &handshakeproto.Credentials{
Type: handshakeproto.CredentialsType_SignedPeerIds,
Payload: payload,
Version: p.protoVersion,
}
}
func (p *peerSignVerifier) CheckCredential(sc sec.SecureConn, cred *handshakeproto.Credentials) (identity []byte, err error) {
if cred.Version != p.protoVersion {
return nil, handshake.ErrIncompatibleVersion
}
if cred.Type != handshakeproto.CredentialsType_SignedPeerIds {
return nil, handshake.ErrSkipVerifyNotAllowed
}

View File

@ -20,8 +20,8 @@ func TestPeerSignVerifier_CheckCredential(t *testing.T) {
identity1, _ := a1.SignKey.GetPublic().Marshall()
identity2, _ := a2.SignKey.GetPublic().Marshall()
cc1 := newPeerSignVerifier(a1)
cc2 := newPeerSignVerifier(a2)
cc1 := newPeerSignVerifier(0, a1)
cc2 := newPeerSignVerifier(0, a2)
c1 := newTestSC(a2.PeerId)
c2 := newTestSC(a1.PeerId)
@ -40,6 +40,29 @@ func TestPeerSignVerifier_CheckCredential(t *testing.T) {
assert.EqualError(t, err, handshake.ErrInvalidCredentials.Error())
}
func TestIncompatibleVersion(t *testing.T) {
a1 := newTestAccData(t)
a2 := newTestAccData(t)
_, _ = a1.SignKey.GetPublic().Marshall()
cc1 := newPeerSignVerifier(0, a1)
cc2 := newPeerSignVerifier(1, a2)
c1 := newTestSC(a2.PeerId)
c2 := newTestSC(a1.PeerId)
cr1 := cc1.MakeCredentials(c1)
cr2 := cc2.MakeCredentials(c2)
_, err := cc1.CheckCredential(c1, cr2)
assert.EqualError(t, err, handshake.ErrIncompatibleVersion.Error())
_, err = cc2.CheckCredential(c2, cr1)
assert.EqualError(t, err, handshake.ErrIncompatibleVersion.Error())
_, err = cc1.CheckCredential(c1, cr1)
assert.EqualError(t, err, handshake.ErrInvalidCredentials.Error())
}
func newTestAccData(t *testing.T) *accountdata.AccountKeys {
as := accounttest.AccountTestService{}
require.NoError(t, as.Init(nil))

View File

@ -18,21 +18,27 @@ const (
msgTypeAck = byte(2)
)
type handshakeError struct {
e handshakeproto.Error
type HandshakeError struct {
Err error
e handshakeproto.Error
}
func (he handshakeError) Error() string {
func (he HandshakeError) Error() string {
if he.Err != nil {
return he.Err.Error()
}
return he.e.String()
}
var (
ErrUnexpectedPayload = handshakeError{handshakeproto.Error_UnexpectedPayload}
ErrDeadlineExceeded = handshakeError{handshakeproto.Error_DeadlineExceeded}
ErrInvalidCredentials = handshakeError{handshakeproto.Error_InvalidCredentials}
ErrPeerDeclinedCredentials = errors.New("remote peer declined the credentials")
ErrSkipVerifyNotAllowed = handshakeError{handshakeproto.Error_SkipVerifyNotAllowed}
ErrUnexpected = handshakeError{handshakeproto.Error_Unexpected}
ErrUnexpectedPayload = HandshakeError{e: handshakeproto.Error_UnexpectedPayload}
ErrDeadlineExceeded = HandshakeError{e: handshakeproto.Error_DeadlineExceeded}
ErrInvalidCredentials = HandshakeError{e: handshakeproto.Error_InvalidCredentials}
ErrPeerDeclinedCredentials = HandshakeError{Err: errors.New("remote peer declined the credentials")}
ErrSkipVerifyNotAllowed = HandshakeError{e: handshakeproto.Error_SkipVerifyNotAllowed}
ErrUnexpected = HandshakeError{e: handshakeproto.Error_Unexpected}
ErrIncompatibleVersion = HandshakeError{e: handshakeproto.Error_IncompatibleVersion}
ErrGotNotAHandshakeMessage = errors.New("go not a handshake message")
)
@ -87,7 +93,7 @@ func outgoingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (i
if msg.ack.Error == handshakeproto.Error_InvalidCredentials {
return nil, ErrPeerDeclinedCredentials
}
return nil, handshakeError{e: msg.ack.Error}
return nil, HandshakeError{e: msg.ack.Error}
}
if identity, err = cc.CheckCredential(sc, msg.cred); err != nil {
@ -114,7 +120,7 @@ func outgoingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (i
return identity, nil
} else {
_ = h.conn.Close()
return nil, handshakeError{e: msg.ack.Error}
return nil, HandshakeError{e: msg.ack.Error}
}
}
@ -173,7 +179,7 @@ func incomingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (i
if msg.ack.Error == handshakeproto.Error_InvalidCredentials {
return nil, ErrPeerDeclinedCredentials
}
return nil, handshakeError{e: msg.ack.Error}
return nil, HandshakeError{e: msg.ack.Error}
}
if err = h.writeAck(handshakeproto.Error_Null); err != nil {
h.tryWriteErrAndClose(err)
@ -210,7 +216,7 @@ func (h *handshake) tryWriteErrAndClose(err error) {
return
}
var ackErr handshakeproto.Error
if he, ok := err.(handshakeError); ok {
if he, ok := err.(HandshakeError); ok {
ackErr = he.e
} else {
ackErr = handshakeproto.Error_Unexpected

View File

@ -11,16 +11,10 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net"
"net/http"
_ "net/http/pprof"
"testing"
"time"
)
func init() {
go http.ListenAndServe(":6060", nil)
}
var noVerifyChecker = &testCredChecker{
makeCred: &handshakeproto.Credentials{Type: handshakeproto.CredentialsType_SkipVerify},
checkCred: func(sc sec.SecureConn, cred *handshakeproto.Credentials) (identity []byte, err error) {
@ -324,6 +318,26 @@ func TestIncomingHandshake(t *testing.T) {
res := <-handshakeResCh
require.EqualError(t, res.err, ErrInvalidCredentials.Error())
})
t.Run("invalid cred version", func(t *testing.T) {
c1, c2 := newConnPair(t)
var handshakeResCh = make(chan handshakeRes, 1)
go func() {
identity, err := IncomingHandshake(nil, c1, &testCredChecker{makeCred: noVerifyChecker.makeCred, checkErr: ErrIncompatibleVersion})
handshakeResCh <- handshakeRes{identity: identity, err: err}
}()
h := newHandshake()
h.conn = c2
// write credentials
require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2)))
// except ack with error
msg, err := h.readMsg()
require.NoError(t, err)
require.Nil(t, msg.cred)
require.Equal(t, handshakeproto.Error_IncompatibleVersion, msg.ack.Error)
res := <-handshakeResCh
assert.Equal(t, res.err, ErrIncompatibleVersion)
})
t.Run("write cred instead ack", func(t *testing.T) {
c1, c2 := newConnPair(t)
var handshakeResCh = make(chan handshakeRes, 1)

View File

@ -58,6 +58,7 @@ const (
Error_UnexpectedPayload Error = 3
Error_SkipVerifyNotAllowed Error = 4
Error_DeadlineExceeded Error = 5
Error_IncompatibleVersion Error = 6
)
var Error_name = map[int32]string{
@ -67,6 +68,7 @@ var Error_name = map[int32]string{
3: "UnexpectedPayload",
4: "SkipVerifyNotAllowed",
5: "DeadlineExceeded",
6: "IncompatibleVersion",
}
var Error_value = map[string]int32{
@ -76,6 +78,7 @@ var Error_value = map[string]int32{
"UnexpectedPayload": 3,
"SkipVerifyNotAllowed": 4,
"DeadlineExceeded": 5,
"IncompatibleVersion": 6,
}
func (x Error) String() string {
@ -89,6 +92,7 @@ func (Error) EnumDescriptor() ([]byte, []int) {
type Credentials struct {
Type CredentialsType `protobuf:"varint,1,opt,name=type,proto3,enum=anyHandshake.CredentialsType" json:"type,omitempty"`
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"`
}
func (m *Credentials) Reset() { *m = Credentials{} }
@ -138,6 +142,13 @@ func (m *Credentials) GetPayload() []byte {
return nil
}
func (m *Credentials) GetVersion() uint32 {
if m != nil {
return m.Version
}
return 0
}
type PayloadSignedPeerIds struct {
// account identity
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
@ -249,30 +260,32 @@ func init() {
}
var fileDescriptor_60283fc75f020893 = []byte{
// 362 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x51, 0xcd, 0x8e, 0xda, 0x30,
0x18, 0x8c, 0x21, 0xb4, 0xe8, 0x2b, 0xa5, 0xc6, 0xa5, 0x55, 0x54, 0xa9, 0x11, 0xe2, 0x44, 0x39,
0x40, 0xff, 0x5e, 0x80, 0x16, 0xaa, 0x72, 0x41, 0x28, 0xb4, 0x3d, 0x70, 0x73, 0xe3, 0xaf, 0x60,
0x61, 0x39, 0x91, 0x13, 0x28, 0xb9, 0xed, 0x23, 0xec, 0x63, 0xed, 0x91, 0xe3, 0x1e, 0x57, 0xf0,
0x22, 0x2b, 0x0c, 0x2c, 0x61, 0x4f, 0x7b, 0xb1, 0xe7, 0x1b, 0x8f, 0x67, 0xc6, 0x32, 0xf4, 0x34,
0xa6, 0xdd, 0x04, 0xc3, 0xa5, 0xc1, 0x04, 0xcd, 0x4a, 0x86, 0xd8, 0x9d, 0x73, 0x2d, 0x92, 0x39,
0x5f, 0xe4, 0x50, 0x6c, 0xa2, 0x34, 0xea, 0xda, 0x35, 0x39, 0xb3, 0x1d, 0x4b, 0xb0, 0x0a, 0xd7,
0xd9, 0xcf, 0x13, 0xd7, 0x9c, 0xc2, 0x8b, 0xef, 0x06, 0x05, 0xea, 0x54, 0x72, 0x95, 0xb0, 0x4f,
0xe0, 0xa6, 0x59, 0x8c, 0x1e, 0x69, 0x90, 0x56, 0xf5, 0xf3, 0xfb, 0x4e, 0x5e, 0xdb, 0xc9, 0x09,
0x7f, 0x65, 0x31, 0x06, 0x56, 0xca, 0x3c, 0x78, 0x1e, 0xf3, 0x4c, 0x45, 0x5c, 0x78, 0x85, 0x06,
0x69, 0x55, 0x82, 0xd3, 0xd8, 0xfc, 0x01, 0xf5, 0xf1, 0x01, 0x4e, 0xe4, 0x4c, 0xa3, 0x18, 0x23,
0x9a, 0xa1, 0x48, 0xd8, 0x3b, 0x28, 0x4b, 0x6b, 0x94, 0x66, 0x36, 0xa8, 0x12, 0x3c, 0xcc, 0x8c,
0x81, 0x9b, 0xc8, 0x99, 0x3e, 0x5a, 0x59, 0xdc, 0xfc, 0x08, 0xc5, 0x5e, 0xb8, 0x60, 0x1f, 0xa0,
0x84, 0xc6, 0x44, 0xe6, 0x58, 0xee, 0xf5, 0x65, 0xb9, 0xc1, 0xfe, 0x28, 0x38, 0x28, 0xda, 0x5f,
0xe1, 0xd5, 0xa3, 0xb2, 0xac, 0x0a, 0x30, 0x59, 0xc8, 0xf8, 0x0f, 0x1a, 0xf9, 0x2f, 0xa3, 0x0e,
0xab, 0xc1, 0xcb, 0x8b, 0x56, 0x94, 0xb4, 0xaf, 0x08, 0x94, 0xac, 0x0d, 0x2b, 0x83, 0x3b, 0x5a,
0x2a, 0x45, 0x9d, 0xfd, 0xb5, 0xdf, 0x1a, 0xd7, 0x31, 0x86, 0x29, 0x0a, 0x4a, 0xd8, 0x5b, 0x60,
0x43, 0xbd, 0xe2, 0x4a, 0x8a, 0x5c, 0x00, 0x2d, 0xb0, 0x37, 0x50, 0x3b, 0xeb, 0x8e, 0xaf, 0xa6,
0x45, 0xe6, 0x41, 0xfd, 0x9c, 0x3a, 0x8a, 0xd2, 0x9e, 0x52, 0xd1, 0x7f, 0x14, 0xd4, 0x65, 0x75,
0xa0, 0x7d, 0xe4, 0x42, 0x49, 0x8d, 0x83, 0x75, 0x88, 0x28, 0x50, 0xd0, 0xd2, 0xb7, 0xfe, 0xcd,
0xd6, 0x27, 0x9b, 0xad, 0x4f, 0xee, 0xb6, 0x3e, 0xb9, 0xde, 0xf9, 0xce, 0x66, 0xe7, 0x3b, 0xb7,
0x3b, 0xdf, 0x99, 0xb6, 0x9f, 0xfe, 0xf3, 0x7f, 0x9f, 0xd9, 0xed, 0xcb, 0x7d, 0x00, 0x00, 0x00,
0xff, 0xff, 0xa0, 0x48, 0xdf, 0x7a, 0x2e, 0x02, 0x00, 0x00,
// 395 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcd, 0x6e, 0x13, 0x31,
0x10, 0xc7, 0xd7, 0x4d, 0x52, 0xaa, 0x21, 0x2d, 0xee, 0x34, 0xc0, 0x0a, 0x89, 0x55, 0x94, 0x53,
0xc8, 0x21, 0xe1, 0xeb, 0x05, 0x02, 0x2d, 0x22, 0x97, 0xaa, 0xda, 0x42, 0x0f, 0xdc, 0xdc, 0xf5,
0xd0, 0x5a, 0x31, 0xf6, 0xca, 0x76, 0x43, 0xf7, 0x2d, 0xb8, 0xf2, 0x46, 0x1c, 0x7b, 0xe4, 0x88,
0x92, 0x17, 0x41, 0x71, 0x12, 0x92, 0x70, 0xea, 0xc5, 0x9e, 0x8f, 0x9f, 0xfd, 0xff, 0x8f, 0x65,
0x18, 0x1a, 0x0a, 0x03, 0x4f, 0xc5, 0x8d, 0x23, 0x4f, 0x6e, 0xa2, 0x0a, 0x1a, 0x5c, 0x0b, 0x23,
0xfd, 0xb5, 0x18, 0x6f, 0x44, 0xa5, 0xb3, 0xc1, 0x0e, 0xe2, 0xea, 0xd7, 0xd5, 0x7e, 0x2c, 0x60,
0x53, 0x98, 0xea, 0xe3, 0xaa, 0xd6, 0x09, 0xf0, 0xf0, 0xbd, 0x23, 0x49, 0x26, 0x28, 0xa1, 0x3d,
0xbe, 0x82, 0x7a, 0xa8, 0x4a, 0x4a, 0x59, 0x9b, 0x75, 0x0f, 0x5e, 0x3f, 0xef, 0x6f, 0xb2, 0xfd,
0x0d, 0xf0, 0x53, 0x55, 0x52, 0x1e, 0x51, 0x4c, 0xe1, 0x41, 0x29, 0x2a, 0x6d, 0x85, 0x4c, 0x77,
0xda, 0xac, 0xdb, 0xcc, 0x57, 0xe9, 0xbc, 0x33, 0x21, 0xe7, 0x95, 0x35, 0x69, 0xad, 0xcd, 0xba,
0xfb, 0xf9, 0x2a, 0xed, 0x7c, 0x80, 0xd6, 0xd9, 0x02, 0x3a, 0x57, 0x57, 0x86, 0xe4, 0x19, 0x91,
0x1b, 0x49, 0x8f, 0xcf, 0x60, 0x4f, 0x45, 0x89, 0x50, 0x45, 0x0b, 0xcd, 0xfc, 0x5f, 0x8e, 0x08,
0x75, 0xaf, 0xae, 0xcc, 0x52, 0x24, 0xc6, 0x9d, 0x97, 0x50, 0x1b, 0x16, 0x63, 0x7c, 0x01, 0x0d,
0x72, 0xce, 0xba, 0xa5, 0xed, 0xa3, 0x6d, 0xdb, 0x27, 0xf3, 0x56, 0xbe, 0x20, 0x7a, 0x6f, 0xe1,
0xd1, 0x7f, 0x63, 0xe0, 0x01, 0xc0, 0xf9, 0x58, 0x95, 0x17, 0xe4, 0xd4, 0xd7, 0x8a, 0x27, 0x78,
0x08, 0xfb, 0x5b, 0xae, 0x38, 0xeb, 0xfd, 0x64, 0xd0, 0x88, 0xd7, 0xe0, 0x1e, 0xd4, 0x4f, 0x6f,
0xb4, 0xe6, 0xc9, 0xfc, 0xd8, 0x67, 0x43, 0xb7, 0x25, 0x15, 0x81, 0x24, 0x67, 0xf8, 0x04, 0x70,
0x64, 0x26, 0x42, 0x2b, 0xb9, 0x21, 0xc0, 0x77, 0xf0, 0x31, 0x1c, 0xae, 0xb9, 0xe5, 0xd4, 0xbc,
0x86, 0x29, 0xb4, 0xd6, 0xaa, 0xa7, 0x36, 0x0c, 0xb5, 0xb6, 0xdf, 0x49, 0xf2, 0x3a, 0xb6, 0x80,
0x1f, 0x93, 0x90, 0x5a, 0x19, 0x3a, 0xb9, 0x2d, 0x88, 0x24, 0x49, 0xde, 0xc0, 0xa7, 0x70, 0x34,
0x32, 0x85, 0xfd, 0x56, 0x8a, 0xa0, 0x2e, 0x35, 0x5d, 0x2c, 0x5e, 0x92, 0xef, 0xbe, 0x3b, 0xfe,
0x35, 0xcd, 0xd8, 0xdd, 0x34, 0x63, 0x7f, 0xa6, 0x19, 0xfb, 0x31, 0xcb, 0x92, 0xbb, 0x59, 0x96,
0xfc, 0x9e, 0x65, 0xc9, 0x97, 0xde, 0xfd, 0x3f, 0xcb, 0xe5, 0x6e, 0xdc, 0xde, 0xfc, 0x0d, 0x00,
0x00, 0xff, 0xff, 0xbf, 0x78, 0x2f, 0x36, 0x61, 0x02, 0x00, 0x00,
}
func (m *Credentials) Marshal() (dAtA []byte, err error) {
@ -295,6 +308,11 @@ func (m *Credentials) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if m.Version != 0 {
i = encodeVarintHandshake(dAtA, i, uint64(m.Version))
i--
dAtA[i] = 0x18
}
if len(m.Payload) > 0 {
i -= len(m.Payload)
copy(dAtA[i:], m.Payload)
@ -399,6 +417,9 @@ func (m *Credentials) Size() (n int) {
if l > 0 {
n += 1 + l + sovHandshake(uint64(l))
}
if m.Version != 0 {
n += 1 + sovHandshake(uint64(m.Version))
}
return n
}
@ -519,6 +540,25 @@ func (m *Credentials) Unmarshal(dAtA []byte) error {
m.Payload = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
}
m.Version = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Version |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipHandshake(dAtA[iNdEx:])

View File

@ -36,6 +36,7 @@ Successful handshake scheme:
message Credentials {
CredentialsType type = 1;
bytes payload = 2;
uint32 version = 3;
}
enum CredentialsType {
@ -66,4 +67,5 @@ enum Error {
UnexpectedPayload = 3;
SkipVerifyNotAllowed = 4;
DeadlineExceeded = 5;
IncompatibleVersion = 6;
}

View File

@ -16,19 +16,6 @@ import (
"net"
)
type HandshakeError struct {
remoteAddr string
err error
}
func (he HandshakeError) RemoteAddr() string {
return he.remoteAddr
}
func (he HandshakeError) Error() string {
return he.err.Error()
}
const CName = "common.net.secure"
var log = logger.NewNamed(CName)
@ -44,10 +31,11 @@ type SecureService interface {
}
type secureService struct {
p2pTr *libp2ptls.Transport
account *accountdata.AccountKeys
key crypto.PrivKey
nodeconf nodeconf.Service
p2pTr *libp2ptls.Transport
account *accountdata.AccountKeys
key crypto.PrivKey
nodeconf nodeconf.Service
protoVersion uint32
noVerifyChecker handshake.CredentialChecker
peerSignVerifier handshake.CredentialChecker
@ -63,9 +51,8 @@ func (s *secureService) Init(a *app.App) (err error) {
if s.key, err = crypto.UnmarshalEd25519PrivateKey(peerKey); err != nil {
return
}
s.noVerifyChecker = newNoVerifyChecker()
s.peerSignVerifier = newPeerSignVerifier(account.Account())
s.noVerifyChecker = newNoVerifyChecker(s.protoVersion)
s.peerSignVerifier = newPeerSignVerifier(s.protoVersion, account.Account())
s.nodeconf = a.MustComponent(nodeconf.CName).(nodeconf.Service)
@ -91,18 +78,14 @@ func (s *secureService) Name() (name string) {
func (s *secureService) SecureInbound(ctx context.Context, conn net.Conn) (cctx context.Context, sc sec.SecureConn, err error) {
sc, err = s.p2pTr.SecureInbound(ctx, conn, "")
if err != nil {
return nil, nil, HandshakeError{
remoteAddr: conn.RemoteAddr().String(),
err: err,
return nil, nil, handshake.HandshakeError{
Err: err,
}
}
identity, err := handshake.IncomingHandshake(ctx, sc, s.inboundChecker)
if err != nil {
return nil, nil, HandshakeError{
remoteAddr: conn.RemoteAddr().String(),
err: err,
}
return nil, nil, err
}
cctx = context.Background()
cctx = peer.CtxWithPeerId(cctx, sc.RemotePeer().String())
@ -113,7 +96,7 @@ func (s *secureService) SecureInbound(ctx context.Context, conn net.Conn) (cctx
func (s *secureService) SecureOutbound(ctx context.Context, conn net.Conn) (sec.SecureConn, error) {
sc, err := s.p2pTr.SecureOutbound(ctx, conn, "")
if err != nil {
return nil, HandshakeError{err: err, remoteAddr: conn.RemoteAddr().String()}
return nil, handshake.HandshakeError{Err: err}
}
peerId := sc.RemotePeer().String()
confTypes := s.nodeconf.NodeTypes(peerId)
@ -126,7 +109,7 @@ func (s *secureService) SecureOutbound(ctx context.Context, conn net.Conn) (sec.
// ignore identity for outgoing connection because we don't need it at this moment
_, err = handshake.OutgoingHandshake(ctx, sc, checker)
if err != nil {
return nil, HandshakeError{err: err, remoteAddr: conn.RemoteAddr().String()}
return nil, err
}
return sc, nil
}

View File

@ -5,6 +5,7 @@ import (
"github.com/anytypeio/any-sync/accountservice"
"github.com/anytypeio/any-sync/app"
"github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/net/secureservice/handshake"
"github.com/anytypeio/any-sync/nodeconf"
"github.com/anytypeio/any-sync/nodeconf/mock_nodeconf"
"github.com/anytypeio/any-sync/testutil/testnodeconf"
@ -19,7 +20,7 @@ var ctx = context.Background()
func TestHandshake(t *testing.T) {
nc := testnodeconf.GenNodeConfig(2)
fxS := newFixture(t, nc, nc.GetAccountService(0))
fxS := newFixture(t, nc, nc.GetAccountService(0), 0)
defer fxS.Finish(t)
sc, cc := net.Pipe()
@ -35,7 +36,7 @@ func TestHandshake(t *testing.T) {
resCh <- ar
}()
fxC := newFixture(t, nc, nc.GetAccountService(1))
fxC := newFixture(t, nc, nc.GetAccountService(1), 0)
defer fxC.Finish(t)
secConn, err := fxC.SecureOutbound(ctx, cc)
@ -52,13 +53,39 @@ func TestHandshake(t *testing.T) {
assert.Equal(t, marshalledId, accId)
}
func newFixture(t *testing.T, nc *testnodeconf.Config, acc accountservice.Service) *fixture {
func TestHandshakeIncompatibleVersion(t *testing.T) {
nc := testnodeconf.GenNodeConfig(2)
fxS := newFixture(t, nc, nc.GetAccountService(0), 0)
defer fxS.Finish(t)
sc, cc := net.Pipe()
type acceptRes struct {
ctx context.Context
conn net.Conn
err error
}
resCh := make(chan acceptRes)
go func() {
var ar acceptRes
ar.ctx, ar.conn, ar.err = fxS.SecureInbound(ctx, sc)
resCh <- ar
}()
fxC := newFixture(t, nc, nc.GetAccountService(1), 1)
defer fxC.Finish(t)
_, err := fxC.SecureOutbound(ctx, cc)
require.Equal(t, handshake.ErrIncompatibleVersion, err)
res := <-resCh
require.Equal(t, handshake.ErrIncompatibleVersion, res.err)
}
func newFixture(t *testing.T, nc *testnodeconf.Config, acc accountservice.Service, protoVersion uint32) *fixture {
fx := &fixture{
ctrl: gomock.NewController(t),
secureService: New().(*secureService),
acc: acc,
a: new(app.App),
}
fx.secureService.protoVersion = protoVersion
fx.mockNodeConf = mock_nodeconf.NewMockService(fx.ctrl)
fx.mockNodeConf.EXPECT().Init(gomock.Any())
fx.mockNodeConf.EXPECT().Name().Return(nodeconf.CName).AnyTimes()

View File

@ -2,8 +2,8 @@ package streampool
import (
"fmt"
"github.com/anytypeio/any-sync/net"
"github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/net/pool"
"github.com/anytypeio/any-sync/util/multiqueue"
"go.uber.org/zap"
"golang.org/x/exp/slices"
@ -172,7 +172,7 @@ func (s *streamPool) SendById(ctx context.Context, msg drpc.Message, peerIds ...
}
}
if len(streamsByPeer) == 0 {
return pool.ErrUnableToConnect
return net.ErrUnableToConnect
}
return
}

View File

@ -177,6 +177,20 @@ func (mr *MockServiceMockRecorder) Name() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockService)(nil).Name))
}
// NetworkCompatibilityStatus mocks base method.
func (m *MockService) NetworkCompatibilityStatus() nodeconf.NetworkCompatibilityStatus {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetworkCompatibilityStatus")
ret0, _ := ret[0].(nodeconf.NetworkCompatibilityStatus)
return ret0
}
// NetworkCompatibilityStatus indicates an expected call of NetworkCompatibilityStatus.
func (mr *MockServiceMockRecorder) NetworkCompatibilityStatus() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkCompatibilityStatus", reflect.TypeOf((*MockService)(nil).NetworkCompatibilityStatus))
}
// NodeIds mocks base method.
func (m *MockService) NodeIds(arg0 string) []string {
m.ctrl.T.Helper()

View File

@ -1,4 +1,3 @@
//go:generate mockgen -destination mock_nodeconf/mock_nodeconf.go github.com/anytypeio/any-sync/nodeconf Service
package nodeconf
import (

View File

@ -1,3 +1,4 @@
//go:generate mockgen -destination mock_nodeconf/mock_nodeconf.go github.com/anytypeio/any-sync/nodeconf Service
package nodeconf
import (
@ -5,6 +6,8 @@ import (
commonaccount "github.com/anytypeio/any-sync/accountservice"
"github.com/anytypeio/any-sync/app"
"github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/net"
"github.com/anytypeio/any-sync/net/secureservice/handshake"
"github.com/anytypeio/any-sync/util/periodicsync"
"github.com/anytypeio/go-chash"
"go.uber.org/zap"
@ -20,12 +23,22 @@ const (
var log = logger.NewNamed(CName)
type NetworkCompatibilityStatus int
const (
NetworkCompatibilityStatusUnknown NetworkCompatibilityStatus = iota
NetworkCompatibilityStatusOk
NetworkCompatibilityStatusError
NetworkCompatibilityStatusIncompatible
)
func New() Service {
return new(service)
}
type Service interface {
NodeConf
NetworkCompatibilityStatus() NetworkCompatibilityStatus
app.ComponentRunnable
}
@ -37,6 +50,8 @@ type service struct {
last NodeConf
mu sync.RWMutex
sync periodicsync.PeriodicSync
compatibilityStatus NetworkCompatibilityStatus
}
func (s *service) Init(a *app.App) (err error) {
@ -75,10 +90,19 @@ func (s *service) Run(_ context.Context) (err error) {
return
}
func (s *service) NetworkCompatibilityStatus() NetworkCompatibilityStatus {
s.mu.RLock()
defer s.mu.RUnlock()
return s.compatibilityStatus
}
func (s *service) updateConfiguration(ctx context.Context) (err error) {
last, err := s.source.GetLast(ctx, s.Configuration().Id)
if err != nil {
s.setCompatibilityStatusByErr(err)
return
} else {
s.setCompatibilityStatusByErr(nil)
}
if err = s.store.SaveLast(ctx, last); err != nil {
return
@ -139,6 +163,21 @@ func (s *service) setLastConfiguration(c Configuration) (err error) {
return
}
func (s *service) setCompatibilityStatusByErr(err error) {
s.mu.Lock()
defer s.mu.Unlock()
switch err {
case nil:
s.compatibilityStatus = NetworkCompatibilityStatusOk
case handshake.ErrIncompatibleVersion:
s.compatibilityStatus = NetworkCompatibilityStatusIncompatible
case net.ErrUnableToConnect:
s.compatibilityStatus = NetworkCompatibilityStatusUnknown
default:
s.compatibilityStatus = NetworkCompatibilityStatusError
}
}
func (s *service) Id() string {
s.mu.RLock()
defer s.mu.RUnlock()
@ -206,6 +245,8 @@ func (s *service) NodeTypes(nodeId string) []NodeType {
}
func (s *service) Close(ctx context.Context) (err error) {
s.sync.Close()
if s.sync != nil {
s.sync.Close()
}
return
}

175
nodeconf/service_test.go Normal file
View File

@ -0,0 +1,175 @@
package nodeconf
import (
"context"
"errors"
"github.com/anytypeio/any-sync/app"
"github.com/anytypeio/any-sync/net"
"github.com/anytypeio/any-sync/net/secureservice/handshake"
"github.com/anytypeio/any-sync/testutil/accounttest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sync"
"testing"
"time"
)
var ctx = context.Background()
func TestService_NetworkCompatibilityStatus(t *testing.T) {
t.Run("unknown", func(t *testing.T) {
fx := newFixture(t)
defer fx.finish(t)
fx.testSource.call = func() (c Configuration, e error) {
e = net.ErrUnableToConnect
return
}
fx.run(t)
time.Sleep(time.Millisecond * 10)
assert.Equal(t, NetworkCompatibilityStatusUnknown, fx.NetworkCompatibilityStatus())
})
t.Run("incompatible", func(t *testing.T) {
fx := newFixture(t)
defer fx.finish(t)
fx.testSource.err = handshake.ErrIncompatibleVersion
fx.run(t)
time.Sleep(time.Millisecond * 10)
assert.Equal(t, NetworkCompatibilityStatusIncompatible, fx.NetworkCompatibilityStatus())
})
t.Run("error", func(t *testing.T) {
fx := newFixture(t)
defer fx.finish(t)
fx.testSource.call = func() (c Configuration, e error) {
e = errors.New("some error")
return
}
fx.run(t)
time.Sleep(time.Millisecond * 10)
assert.Equal(t, NetworkCompatibilityStatusError, fx.NetworkCompatibilityStatus())
})
t.Run("ok", func(t *testing.T) {
fx := newFixture(t)
defer fx.finish(t)
fx.run(t)
time.Sleep(time.Millisecond * 10)
assert.Equal(t, NetworkCompatibilityStatusOk, fx.NetworkCompatibilityStatus())
})
}
func newFixture(t *testing.T) *fixture {
fx := &fixture{
Service: New(),
a: new(app.App),
testStore: &testStore{},
testSource: &testSource{},
testConf: newTestConf(),
}
fx.a.Register(fx.testConf).Register(&accounttest.AccountTestService{}).Register(fx.Service).Register(fx.testSource).Register(fx.testStore)
return fx
}
type fixture struct {
Service
a *app.App
testStore *testStore
testSource *testSource
testConf *testConf
}
func (fx *fixture) run(t *testing.T) {
require.NoError(t, fx.a.Start(ctx))
}
func (fx *fixture) finish(t *testing.T) {
require.NoError(t, fx.a.Close(ctx))
}
type testSource struct {
conf Configuration
err error
call func() (Configuration, error)
}
func (t *testSource) Init(a *app.App) error { return nil }
func (t *testSource) Name() string { return CNameSource }
func (t *testSource) GetLast(ctx context.Context, currentId string) (c Configuration, err error) {
if t.call != nil {
return t.call()
}
return t.conf, t.err
}
type testStore struct {
conf *Configuration
mu sync.Mutex
}
func (t *testStore) Init(a *app.App) error { return nil }
func (t *testStore) Name() string { return CNameStore }
func (t *testStore) GetLast(ctx context.Context, netId string) (c Configuration, err error) {
t.mu.Lock()
defer t.mu.Unlock()
if t.conf != nil {
return *t.conf, nil
} else {
err = ErrConfigurationNotFound
}
return
}
func (t *testStore) SaveLast(ctx context.Context, c Configuration) (err error) {
t.mu.Lock()
defer t.mu.Unlock()
t.conf = &c
return
}
type testConf struct {
Configuration
}
func (t *testConf) Init(a *app.App) error { return nil }
func (t *testConf) Name() string { return "config" }
func (t *testConf) GetNodeConf() Configuration {
return t.Configuration
}
func newTestConf() *testConf {
return &testConf{
Configuration{
Id: "test",
NetworkId: "testNetwork",
Nodes: []Node{
{
PeerId: "12D3KooWKLCajM89S8unbt3tgGbRLgmiWnFZT3adn9A5pQciBSLa",
Addresses: []string{"127.0.0.1:4830"},
Types: []NodeType{NodeTypeCoordinator},
},
{
PeerId: "12D3KooWKnXTtbveMDUFfeSqR5dt9a4JW66tZQXG7C7PdDh3vqGu",
Addresses: []string{"127.0.0.1:4730"},
Types: []NodeType{NodeTypeTree},
},
{
PeerId: "12D3KooWKgVN2kW8xw5Uvm2sLUnkeUNQYAvcWvF58maTzev7FjPi",
Addresses: []string{"127.0.0.1:4731"},
Types: []NodeType{NodeTypeTree},
},
{
PeerId: "12D3KooWCUPYuMnQhu9yREJgQyjcz8zWY83rZGmDLwb9YR6QkbZX",
Addresses: []string{"127.0.0.1:4732"},
Types: []NodeType{NodeTypeTree},
},
{
PeerId: "12D3KooWQxiZ5a7vcy4DTJa8Gy1eVUmwb5ojN4SrJC9Rjxzigw6C",
Addresses: []string{"127.0.0.1:4733"},
Types: []NodeType{NodeTypeFile},
},
},
CreationTime: time.Now(),
},
}
}

View File

@ -4,7 +4,6 @@ import (
accountService "github.com/anytypeio/any-sync/accountservice"
"github.com/anytypeio/any-sync/app"
"github.com/anytypeio/any-sync/commonspace/object/accountdata"
"github.com/anytypeio/any-sync/nodeconf"
"github.com/anytypeio/any-sync/util/crypto"
)
@ -46,11 +45,3 @@ func (s *AccountTestService) Name() (name string) {
func (s *AccountTestService) Account() *accountdata.AccountKeys {
return s.acc
}
func (s *AccountTestService) NodeConf(addrs []string) nodeconf.Node {
return nodeconf.Node{
PeerId: s.acc.PeerId,
Addresses: addrs,
Types: []nodeconf.NodeType{nodeconf.NodeTypeTree},
}
}

View File

@ -17,7 +17,10 @@ func GenNodeConfig(num int) (conf *Config) {
if err := ac.Init(nil); err != nil {
panic(err)
}
conf.nodes.Nodes = append(conf.nodes.Nodes, ac.NodeConf(nil))
conf.nodes.Nodes = append(conf.nodes.Nodes, nodeconf.Node{
PeerId: ac.Account().PeerId,
Types: []nodeconf.NodeType{nodeconf.NodeTypeTree},
})
conf.configs = append(conf.configs, ac)
}
return conf