Skip to content

Commit 612f4ee

Browse files
authored
Ed25519 identity instead of RSA + pubsub benchmarks (#44)
Implements #43.
1 parent 3438fa7 commit 612f4ee

File tree

2 files changed

+254
-2
lines changed

2 files changed

+254
-2
lines changed

internal/runtime/network.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package runtime
22

33
import (
44
"context"
5+
"crypto/rand"
56
"fmt"
67
"io"
78
"strings"
89
"time"
910

1011
ds "github.com/ipfs/go-datastore"
1112
"github.com/libp2p/go-libp2p"
13+
"github.com/libp2p/go-libp2p-core/crypto"
1214
"github.com/libp2p/go-libp2p-core/discovery"
1315
"github.com/libp2p/go-libp2p-core/host"
1416
"github.com/libp2p/go-libp2p-core/metrics"
@@ -39,14 +41,17 @@ var network = fx.Provide(
3941
overlay,
4042
bootstrap,
4143
peercache,
42-
dhtRouting)
44+
dhtRouting,
45+
randomIdentityEd25519,
46+
)
4347

4448
type routingConfig struct {
4549
fx.In
4650

4751
CLI *cli.Context
4852
Metrics *metrics.BandwidthCounter
4953
Lifecycle fx.Lifecycle
54+
Priv crypto.PrivKey
5055
}
5156

5257
func dhtRouting(config routingConfig) (*dual.DHT, error) {
@@ -67,7 +72,8 @@ func (config routingConfig) NewHost() (h host.Host, err error) {
6772
libp2p.NoTransports,
6873
libp2p.Transport(quic.NewTransport),
6974
libp2p.ListenAddrStrings(config.ListenAddrs()...),
70-
libp2p.BandwidthReporter(config.Metrics))
75+
libp2p.BandwidthReporter(config.Metrics),
76+
libp2p.Identity(config.Priv))
7177
if err == nil {
7278
config.Lifecycle.Append(closer(h))
7379
}
@@ -335,3 +341,8 @@ func (config overlayConfig) Features() func(pubsub.GossipSubFeature, protocol.ID
335341
func (config overlayConfig) Subprotocols() ([]protocol.ID, func(pubsub.GossipSubFeature, protocol.ID) bool) {
336342
return []protocol.ID{config.Proto()}, config.Features()
337343
}
344+
345+
func randomIdentityEd25519() (crypto.PrivKey, error) {
346+
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, rand.Reader)
347+
return priv, err
348+
}
+241
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
package pubsub_test
2+
3+
import (
4+
"context"
5+
"crypto/rand"
6+
"fmt"
7+
"testing"
8+
9+
"capnproto.org/go/capnp/v3/rpc"
10+
"capnproto.org/go/capnp/v3/rpc/transport"
11+
"github.com/libp2p/go-libp2p"
12+
"github.com/libp2p/go-libp2p-core/crypto"
13+
"github.com/libp2p/go-libp2p-core/protocol"
14+
pubsub "github.com/libp2p/go-libp2p-pubsub"
15+
inproc "github.com/lthibault/go-libp2p-inproc-transport"
16+
"github.com/stretchr/testify/require"
17+
protoutil "github.com/wetware/casm/pkg/util/proto"
18+
ww "github.com/wetware/ww/pkg"
19+
pscap "github.com/wetware/ww/pkg/vat/cap/pubsub"
20+
"golang.org/x/sync/errgroup"
21+
)
22+
23+
const (
24+
ns = "ns"
25+
topic = "benchmark"
26+
payload = "benchmark payload"
27+
)
28+
29+
var (
30+
h, _ = libp2p.New(
31+
libp2p.NoTransports,
32+
libp2p.Transport(inproc.New()),
33+
)
34+
)
35+
36+
func BenchmarkPubSub(b *testing.B) {
37+
ctx, cancel := context.WithCancel(context.Background())
38+
defer cancel()
39+
40+
ps, err := pubsub.NewGossipSub(ctx, h,
41+
pubsub.WithPeerExchange(true),
42+
pubsub.WithProtocolMatchFn(ProtoMatchFunc()),
43+
pubsub.WithGossipSubProtocols(Subprotocols()))
44+
require.NoError(b, err)
45+
46+
topic, err := ps.Join(topic)
47+
require.NoError(b, err)
48+
49+
group, ctx := errgroup.WithContext(ctx)
50+
51+
b.ResetTimer()
52+
for i := 0; i < b.N; i++ {
53+
group.Go(func() error { return topic.Publish(ctx, []byte(payload)) })
54+
}
55+
56+
require.NoError(b, group.Wait())
57+
}
58+
59+
func BenchmarkPubSubNosign(b *testing.B) {
60+
ctx, cancel := context.WithCancel(context.Background())
61+
defer cancel()
62+
63+
ps, err := pubsub.NewGossipSub(ctx, h,
64+
pubsub.WithPeerExchange(true),
65+
pubsub.WithProtocolMatchFn(ProtoMatchFunc()),
66+
pubsub.WithGossipSubProtocols(Subprotocols()),
67+
pubsub.WithMessageSignaturePolicy(pubsub.LaxNoSign))
68+
require.NoError(b, err)
69+
70+
topic, err := ps.Join(topic)
71+
require.NoError(b, err)
72+
73+
group, ctx := errgroup.WithContext(ctx)
74+
75+
b.ResetTimer()
76+
for i := 0; i < b.N; i++ {
77+
group.Go(func() error { return topic.Publish(ctx, []byte(payload)) })
78+
}
79+
80+
require.NoError(b, group.Wait())
81+
}
82+
83+
func BenchmarkPubSubEd25519(b *testing.B) {
84+
ctx, cancel := context.WithCancel(context.Background())
85+
defer cancel()
86+
87+
priv, err := randomIdentity()
88+
require.NoError(b, err)
89+
90+
h, err := libp2p.New(
91+
libp2p.NoTransports,
92+
libp2p.Transport(inproc.New()),
93+
libp2p.Identity(priv),
94+
)
95+
require.NoError(b, err)
96+
defer h.Close()
97+
98+
ps, err := pubsub.NewGossipSub(ctx, h,
99+
pubsub.WithPeerExchange(true),
100+
pubsub.WithProtocolMatchFn(ProtoMatchFunc()),
101+
pubsub.WithGossipSubProtocols(Subprotocols()))
102+
require.NoError(b, err)
103+
104+
topic, err := ps.Join(topic)
105+
require.NoError(b, err)
106+
107+
group, ctx := errgroup.WithContext(ctx)
108+
109+
b.ResetTimer()
110+
for i := 0; i < b.N; i++ {
111+
group.Go(func() error { return topic.Publish(ctx, []byte(payload)) })
112+
}
113+
114+
require.NoError(b, group.Wait())
115+
}
116+
117+
func BenchmarkPubSubCap(b *testing.B) {
118+
ctx, cancel := context.WithCancel(context.Background())
119+
defer cancel()
120+
121+
ps, err := pubsub.NewGossipSub(ctx, h,
122+
pubsub.WithPeerExchange(true),
123+
pubsub.WithProtocolMatchFn(ProtoMatchFunc()),
124+
pubsub.WithGossipSubProtocols(Subprotocols()))
125+
126+
require.NoError(b, err)
127+
server := pscap.New(ns, ps)
128+
defer server.Close()
129+
130+
client := pscap.PubSub{Client: server.Client()}
131+
defer client.Release()
132+
133+
futTopic, release := client.Join(ctx, payload)
134+
defer release()
135+
topic, _ := futTopic.Struct()
136+
group, ctx := errgroup.WithContext(ctx)
137+
138+
b.ResetTimer()
139+
for i := 0; i < b.N; i++ {
140+
group.Go(func() error { return topic.Publish(ctx, []byte(payload)) })
141+
}
142+
143+
require.NoError(b, group.Wait())
144+
}
145+
146+
func BenchmarkPubSubCapNetwork(b *testing.B) {
147+
ctx, cancel := context.WithCancel(context.Background())
148+
defer cancel()
149+
150+
ps, err := pubsub.NewGossipSub(ctx, h,
151+
pubsub.WithPeerExchange(true),
152+
pubsub.WithProtocolMatchFn(ProtoMatchFunc()),
153+
pubsub.WithGossipSubProtocols(Subprotocols()))
154+
155+
require.NoError(b, err)
156+
server := pscap.New(ns, ps)
157+
defer server.Close()
158+
159+
left, right := transport.NewPipe(1)
160+
p1, p2 := rpc.NewTransport(left), rpc.NewTransport(right)
161+
162+
conn1 := rpc.NewConn(p1, &rpc.Options{
163+
BootstrapClient: server.Client(),
164+
})
165+
defer conn1.Close()
166+
167+
conn2 := rpc.NewConn(p2, &rpc.Options{})
168+
defer conn2.Close()
169+
170+
client := pscap.PubSub{Client: conn2.Bootstrap(ctx)}
171+
defer client.Release()
172+
173+
futTopic, release := client.Join(ctx, payload)
174+
defer release()
175+
topic, _ := futTopic.Struct()
176+
177+
group, ctx := errgroup.WithContext(ctx)
178+
179+
b.ResetTimer()
180+
for i := 0; i < b.N; i++ {
181+
group.Go(func() error {
182+
return topic.Publish(ctx, []byte(payload))
183+
})
184+
}
185+
186+
require.NoError(b, group.Wait())
187+
}
188+
189+
func Proto() protocol.ID {
190+
return protoutil.Join(
191+
ww.Subprotocol(ns),
192+
pubsub.GossipSubID_v11)
193+
}
194+
195+
func Features() func(pubsub.GossipSubFeature, protocol.ID) bool {
196+
supportGossip := Matcher()
197+
198+
_, version := protoutil.Split(Proto())
199+
supportsPX := protoutil.Suffix(version)
200+
201+
return func(feat pubsub.GossipSubFeature, proto protocol.ID) bool {
202+
switch feat {
203+
case pubsub.GossipSubFeatureMesh:
204+
return supportGossip.MatchProto(proto)
205+
206+
case pubsub.GossipSubFeaturePX:
207+
return supportsPX.MatchProto(proto)
208+
209+
default:
210+
return false
211+
}
212+
}
213+
}
214+
215+
func Subprotocols() ([]protocol.ID, func(pubsub.GossipSubFeature, protocol.ID) bool) {
216+
return []protocol.ID{Proto()}, Features()
217+
}
218+
219+
func Matcher() protoutil.MatchFunc {
220+
proto, version := protoutil.Split(pubsub.GossipSubID_v11)
221+
return protoutil.Match(
222+
ww.NewMatcher(ns),
223+
protoutil.Exactly(string(proto)),
224+
protoutil.SemVer(string(version)))
225+
}
226+
227+
func ProtoMatchFunc() pubsub.ProtocolMatchFn {
228+
match := Matcher()
229+
230+
return func(local string) func(string) bool {
231+
if match.Match(local) {
232+
return match.Match
233+
}
234+
panic(fmt.Sprintf("match failed for local protocol %s", local))
235+
}
236+
}
237+
238+
func randomIdentity() (crypto.PrivKey, error) {
239+
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, rand.Reader)
240+
return priv, err
241+
}

0 commit comments

Comments
 (0)