Skip to content

Commit 3d9b07c

Browse files
authored
fix: pass digest to publicKeyFromProtobuf (#3014)
This with the changes from #3013 roughly doubles the throughput of loading RSA peers from the peer store which is a massive bottleneck when restarting the amino bootstrapper. Before: ``` % node benchmarks/load-peers.js read all x 5.94 ops/sec ±1.37% (33 runs sampled) ``` After: ``` % node benchmarks/load-peers.js read all x 12.43 ops/sec ±1.18% (63 runs sampled) ```
1 parent 9acccaa commit 3d9b07c

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* eslint-disable no-console */
2+
import { generateKeyPair } from '@libp2p/crypto/keys'
3+
import { TypedEventEmitter } from '@libp2p/interface'
4+
import { defaultLogger } from '@libp2p/logger'
5+
import { peerIdFromPrivateKey } from '@libp2p/peer-id'
6+
import { multiaddr } from '@multiformats/multiaddr'
7+
import Benchmark from 'benchmark'
8+
import { MemoryDatastore } from 'datastore-core'
9+
import { persistentPeerStore } from '../dist/src/index.js'
10+
11+
const privateKey = await generateKeyPair('Ed25519')
12+
const peerId = peerIdFromPrivateKey(privateKey)
13+
14+
// simulate roughly full routing table
15+
const peers = 6_000
16+
const toAdd = await Promise.all(
17+
new Array(peers).fill(0).map(async () => {
18+
const privateKey = await generateKeyPair('RSA')
19+
return peerIdFromPrivateKey(privateKey)
20+
})
21+
)
22+
23+
const datastore = new MemoryDatastore()
24+
const peerStore = persistentPeerStore({
25+
peerId,
26+
datastore,
27+
events: new TypedEventEmitter(),
28+
logger: defaultLogger()
29+
})
30+
31+
for (const peer of toAdd) {
32+
await peerStore.save(peer, {
33+
multiaddrs: [
34+
multiaddr('/ip4/123.123.123.123/tcp/1234')
35+
]
36+
})
37+
}
38+
39+
const main = function () {
40+
const bench = new Benchmark('read all', {
41+
defer: true,
42+
fn: async function (deferred) {
43+
await peerStore.all()
44+
deferred.resolve()
45+
}
46+
})
47+
.on('complete', function (stats) {
48+
console.log(String(stats.currentTarget))
49+
})
50+
51+
bench.run()
52+
}
53+
54+
main()

packages/peer-store/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"@libp2p/logger": "^5.1.10",
7777
"@types/sinon": "^17.0.3",
7878
"aegir": "^45.1.1",
79+
"benchmark": "^2.1.4",
7980
"datastore-core": "^10.0.2",
8081
"delay": "^6.0.0",
8182
"p-defer": "^4.0.1",

packages/peer-store/src/utils/bytes-to-peer.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
import { publicKeyFromProtobuf } from '@libp2p/crypto/keys'
22
import { peerIdFromPublicKey } from '@libp2p/peer-id'
33
import { multiaddr } from '@multiformats/multiaddr'
4+
import { base58btc } from 'multiformats/bases/base58'
5+
import * as Digest from 'multiformats/hashes/digest'
46
import { Peer as PeerPB } from '../pb/peer.js'
57
import type { PeerId, Peer, Tag } from '@libp2p/interface'
68

7-
export function bytesToPeer (peerId: PeerId, buf: Uint8Array): Peer {
8-
const peer = PeerPB.decode(buf)
9+
function populatePublicKey (peerId: PeerId, protobuf: PeerPB): PeerId {
10+
if (peerId.publicKey != null || protobuf.publicKey == null) {
11+
return peerId
12+
}
13+
14+
let digest: any
915

10-
if (peer.publicKey != null && peerId.publicKey == null) {
11-
const publicKey = publicKeyFromProtobuf(peer.publicKey)
12-
peerId = peerIdFromPublicKey(publicKey)
16+
if (peerId.type === 'RSA') {
17+
// avoid hashing public key
18+
const multihash = base58btc.decode(`z${peerId}`)
19+
digest = Digest.decode(multihash)
1320
}
1421

22+
const publicKey = publicKeyFromProtobuf(protobuf.publicKey, digest)
23+
return peerIdFromPublicKey(publicKey)
24+
}
25+
26+
export function bytesToPeer (peerId: PeerId, buf: Uint8Array): Peer {
27+
const peer = PeerPB.decode(buf)
1528
const tags = new Map<string, Tag>()
1629

1730
// remove any expired tags
@@ -27,7 +40,7 @@ export function bytesToPeer (peerId: PeerId, buf: Uint8Array): Peer {
2740

2841
return {
2942
...peer,
30-
id: peerId,
43+
id: populatePublicKey(peerId, peer),
3144
addresses: peer.addresses.map(({ multiaddr: ma, isCertified }) => {
3245
return {
3346
multiaddr: multiaddr(ma),

0 commit comments

Comments
 (0)