Skip to content

Commit b2f6762

Browse files
refactor(libp2p): extract p2p-forge code into separate file (#5349)
1 parent db955ee commit b2f6762

File tree

2 files changed

+149
-77
lines changed

2 files changed

+149
-77
lines changed

pkg/p2p/libp2p/libp2p.go

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ package libp2p
77
import (
88
"context"
99
"crypto/ecdsa"
10-
"crypto/tls"
1110
"errors"
1211
"fmt"
1312
"net"
1413
"net/netip"
1514
"os"
16-
"path/filepath"
1715
"runtime"
1816
"slices"
1917
"strconv"
@@ -22,7 +20,6 @@ import (
2220
"time"
2321

2422
ocprom "contrib.go.opencensus.io/exporter/prometheus"
25-
"github.com/caddyserver/certmagic"
2623
"github.com/coreos/go-semver/semver"
2724
"github.com/ethersphere/bee/v2"
2825
"github.com/ethersphere/bee/v2/pkg/addressbook"
@@ -41,6 +38,7 @@ import (
4138
"github.com/ethersphere/bee/v2/pkg/topology"
4239
"github.com/ethersphere/bee/v2/pkg/topology/lightnode"
4340
"github.com/ethersphere/bee/v2/pkg/tracing"
41+
p2pforge "github.com/ipshipyard/p2p-forge/client"
4442
"github.com/libp2p/go-libp2p"
4543
"github.com/libp2p/go-libp2p/config"
4644
"github.com/libp2p/go-libp2p/core/crypto"
@@ -65,9 +63,6 @@ import (
6563
"github.com/prometheus/client_golang/prometheus"
6664
"go.uber.org/atomic"
6765
"go.uber.org/zap"
68-
"go.uber.org/zap/zapcore"
69-
70-
p2pforge "github.com/ipshipyard/p2p-forge/client"
7166
)
7267

7368
// loggerName is the tree path name of the logger for this package.
@@ -134,14 +129,6 @@ type lightnodes interface {
134129
EachPeer(pf topology.EachPeerFunc) error
135130
}
136131

137-
// autoTLSCertManager defines the interface for managing TLS certificates.
138-
type autoTLSCertManager interface {
139-
Start() error
140-
Stop()
141-
TLSConfig() *tls.Config
142-
AddressFactory() config.AddrsFactory
143-
}
144-
145132
type Options struct {
146133
PrivateKey *ecdsa.PrivateKey
147134
NATAddr string
@@ -294,78 +281,25 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay
294281
if o.autoTLSCertManager != nil {
295282
certManager = o.autoTLSCertManager
296283
} else {
297-
// create a zap logger needed for cert manager to be as close to
298-
// swarm logger as possible
299-
l, err := zap.Config{
300-
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
301-
Development: false,
302-
Sampling: &zap.SamplingConfig{
303-
Initial: 100,
304-
Thereafter: 100,
305-
},
306-
Encoding: "json",
307-
EncoderConfig: zapcore.EncoderConfig{
308-
TimeKey: "time",
309-
LevelKey: "level",
310-
NameKey: "logger",
311-
CallerKey: "caller",
312-
FunctionKey: zapcore.OmitKey,
313-
MessageKey: "msg",
314-
StacktraceKey: "stacktrace",
315-
LineEnding: zapcore.DefaultLineEnding,
316-
EncodeLevel: zapcore.LowercaseLevelEncoder,
317-
EncodeTime: zapcore.EpochTimeEncoder,
318-
EncodeDuration: zapcore.SecondsDurationEncoder,
319-
EncodeCaller: zapcore.ShortCallerEncoder,
320-
},
321-
OutputPaths: []string{"stderr"},
322-
ErrorOutputPaths: []string{"stderr"},
323-
}.Build()
284+
forgeMgr, err := newP2PForgeCertManager(logger, P2PForgeOptions{
285+
Domain: o.AutoTLSDomain,
286+
RegistrationEndpoint: o.AutoTLSRegistrationEndpoint,
287+
CAEndpoint: o.AutoTLSCAEndpoint,
288+
StorageDir: o.AutoTLSStorageDir,
289+
})
324290
if err != nil {
325291
return nil, err
326292
}
327293

328-
// assing zap logger as it needs to be synced when the service stops
329-
zapLogger = l
330-
331-
defer func() {
332-
_ = zapLogger.Sync()
333-
}()
334-
335-
// Use AutoTLS storage dir with domain subdir for easier management
336-
// of different registers.
337-
storagePath := filepath.Join(o.AutoTLSStorageDir, o.AutoTLSDomain)
338-
339-
if err := os.MkdirAll(storagePath, 0700); err != nil {
340-
return nil, fmt.Errorf("create certificate storage directory %s: %w", storagePath, err)
341-
}
342-
343-
certManager, err = p2pforge.NewP2PForgeCertMgr(
344-
p2pforge.WithForgeDomain(o.AutoTLSDomain),
345-
p2pforge.WithForgeRegistrationEndpoint(o.AutoTLSRegistrationEndpoint),
346-
p2pforge.WithCAEndpoint(o.AutoTLSCAEndpoint),
347-
p2pforge.WithCertificateStorage(&certmagic.FileStorage{Path: storagePath}),
348-
p2pforge.WithLogger(zapLogger.Sugar()),
349-
p2pforge.WithUserAgent(userAgent()),
350-
p2pforge.WithAllowPrivateForgeAddrs(),
351-
p2pforge.WithRegistrationDelay(0),
352-
p2pforge.WithOnCertLoaded(func() {
353-
logger.Info("auto tls certificate is loaded")
354-
}),
355-
p2pforge.WithOnCertRenewed(func() {
356-
logger.Info("auto tls certificate is renewed")
357-
}),
358-
)
359-
if err != nil {
360-
return nil, fmt.Errorf("initialize AutoTLS: %w", err)
361-
}
294+
certManager = forgeMgr.CertMgr()
295+
zapLogger = forgeMgr.ZapLogger()
362296
}
363297

364298
defer func() {
365299
if returnErr != nil {
366-
// certificate manager has to be stopped if service is not
367-
// constructed
300+
// call if service is not constructed
368301
certManager.Stop()
302+
_ = zapLogger.Sync()
369303
}
370304
}()
371305

pkg/p2p/libp2p/p2pforge.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2026 The Swarm Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package libp2p
6+
7+
import (
8+
"crypto/tls"
9+
"fmt"
10+
"os"
11+
"path/filepath"
12+
13+
"github.com/caddyserver/certmagic"
14+
"github.com/ethersphere/bee/v2/pkg/log"
15+
p2pforge "github.com/ipshipyard/p2p-forge/client"
16+
"github.com/libp2p/go-libp2p/config"
17+
"go.uber.org/zap"
18+
"go.uber.org/zap/zapcore"
19+
)
20+
21+
// P2PForgeOptions contains the configuration for creating a P2P Forge certificate manager.
22+
type P2PForgeOptions struct {
23+
Domain string
24+
RegistrationEndpoint string
25+
CAEndpoint string
26+
StorageDir string
27+
}
28+
29+
// P2PForgeCertManager wraps the p2p-forge certificate manager with its associated zap logger.
30+
type P2PForgeCertManager struct {
31+
certMgr *p2pforge.P2PForgeCertMgr
32+
zapLogger *zap.Logger
33+
}
34+
35+
// newP2PForgeCertManager creates a new P2P Forge certificate manager.
36+
// It handles the creation of the storage directory and configures logging
37+
// to match bee's verbosity level.
38+
func newP2PForgeCertManager(beeLogger log.Logger, opts P2PForgeOptions) (*P2PForgeCertManager, error) {
39+
zapLogger, err := newZapLogger(beeLogger)
40+
if err != nil {
41+
return nil, fmt.Errorf("create zap logger: %w", err)
42+
}
43+
44+
// Use storage dir with domain subdir for easier management of different registries.
45+
storagePath := filepath.Join(opts.StorageDir, opts.Domain)
46+
if err := os.MkdirAll(storagePath, 0o700); err != nil {
47+
return nil, fmt.Errorf("create certificate storage directory %s: %w", storagePath, err)
48+
}
49+
50+
certMgr, err := p2pforge.NewP2PForgeCertMgr(
51+
p2pforge.WithForgeDomain(opts.Domain),
52+
p2pforge.WithForgeRegistrationEndpoint(opts.RegistrationEndpoint),
53+
p2pforge.WithCAEndpoint(opts.CAEndpoint),
54+
p2pforge.WithCertificateStorage(&certmagic.FileStorage{Path: storagePath}),
55+
p2pforge.WithLogger(zapLogger.Sugar()),
56+
p2pforge.WithUserAgent(userAgent()),
57+
p2pforge.WithAllowPrivateForgeAddrs(),
58+
p2pforge.WithRegistrationDelay(0),
59+
p2pforge.WithOnCertLoaded(func() {
60+
beeLogger.Info("auto tls certificate is loaded")
61+
}),
62+
p2pforge.WithOnCertRenewed(func() {
63+
beeLogger.Info("auto tls certificate is renewed")
64+
}),
65+
)
66+
if err != nil {
67+
return nil, fmt.Errorf("initialize P2P Forge: %w", err)
68+
}
69+
70+
return &P2PForgeCertManager{
71+
certMgr: certMgr,
72+
zapLogger: zapLogger,
73+
}, nil
74+
}
75+
76+
// CertMgr returns the underlying p2pforge.P2PForgeCertMgr.
77+
func (m *P2PForgeCertManager) CertMgr() *p2pforge.P2PForgeCertMgr {
78+
return m.certMgr
79+
}
80+
81+
// ZapLogger returns the zap logger used by the certificate manager.
82+
func (m *P2PForgeCertManager) ZapLogger() *zap.Logger {
83+
return m.zapLogger
84+
}
85+
86+
// autoTLSCertManager defines the interface for managing TLS certificates.
87+
type autoTLSCertManager interface {
88+
Start() error
89+
Stop()
90+
TLSConfig() *tls.Config
91+
AddressFactory() config.AddrsFactory
92+
}
93+
94+
// newZapLogger creates a zap logger configured to match bee's verbosity level.
95+
// This is used by third-party libraries (like p2p-forge) that require a zap logger.
96+
func newZapLogger(beeLogger log.Logger) (*zap.Logger, error) {
97+
cfg := zap.Config{
98+
Level: zap.NewAtomicLevelAt(beeVerbosityToZapLevel(beeLogger.Verbosity())),
99+
Development: false,
100+
Encoding: "json",
101+
OutputPaths: []string{"stderr"},
102+
ErrorOutputPaths: []string{"stderr"},
103+
Sampling: &zap.SamplingConfig{
104+
Initial: 100,
105+
Thereafter: 100,
106+
},
107+
EncoderConfig: zapcore.EncoderConfig{
108+
TimeKey: "time",
109+
LevelKey: "level",
110+
NameKey: "logger",
111+
CallerKey: "caller",
112+
MessageKey: "msg",
113+
StacktraceKey: "stacktrace",
114+
LineEnding: zapcore.DefaultLineEnding,
115+
EncodeLevel: zapcore.LowercaseLevelEncoder,
116+
EncodeTime: zapcore.EpochTimeEncoder,
117+
EncodeDuration: zapcore.SecondsDurationEncoder,
118+
EncodeCaller: zapcore.ShortCallerEncoder,
119+
},
120+
}
121+
return cfg.Build()
122+
}
123+
124+
// beeVerbosityToZapLevel converts bee's log verbosity level to zap's log level.
125+
func beeVerbosityToZapLevel(v log.Level) zapcore.Level {
126+
switch {
127+
case v <= log.VerbosityNone:
128+
return zap.FatalLevel // effectively silences the logger
129+
case v == log.VerbosityError:
130+
return zap.ErrorLevel
131+
case v == log.VerbosityWarning:
132+
return zap.WarnLevel
133+
case v == log.VerbosityInfo:
134+
return zap.InfoLevel
135+
default:
136+
return zap.DebugLevel // VerbosityDebug and VerbosityAll
137+
}
138+
}

0 commit comments

Comments
 (0)