Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit fa578ba

Browse files
authored
fix: disallow publishing pubsub messages to zero peers (#4286)
Use the default gossipsub behaviour of not allowing publishing message to zero peers. If a user publishes a message they may be surprised to find it's not been recieved by anyone, so instead an error should be thrown when there are no peers that will receive a message.
1 parent 789ee58 commit fa578ba

File tree

4 files changed

+53
-4
lines changed

4 files changed

+53
-4
lines changed

packages/interface-ipfs-core/src/name-pubsub/pubsub.js

+16
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ export function testPubsub (factory, options) {
8888
const topic = `${namespace}${uint8ArrayToString(routingKey, 'base64url')}`
8989

9090
await nodeB.pubsub.subscribe(topic, () => {})
91+
92+
// wait for nodeA to see nodeB's subscription
93+
await waitFor(async () => {
94+
const peers = await nodeA.pubsub.peers(topic)
95+
96+
return peers.map(p => p.toString()).includes(idB.id.toString())
97+
})
98+
9199
await nodeA.name.publish(ipfsRef, { resolve: false })
92100
await delay(1000) // guarantee record is written
93101

@@ -149,6 +157,14 @@ export function testPubsub (factory, options) {
149157
const topic = `${namespace}${uint8ArrayToString(routingKey, 'base64url')}`
150158

151159
await nodeB.pubsub.subscribe(topic, checkMessage)
160+
161+
// wait for nodeA to see nodeB's subscription
162+
await waitFor(async () => {
163+
const peers = await nodeA.pubsub.peers(topic)
164+
165+
return peers.map(p => p.toString()).includes(idB.id.toString())
166+
})
167+
152168
await nodeA.name.publish(ipfsRef, { resolve: false, key: testAccountName })
153169
await waitFor(alreadySubscribed)
154170

packages/interface-ipfs-core/src/pubsub/publish.js

+37-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,30 @@ import { nanoid } from 'nanoid'
55
import { getTopic } from './utils.js'
66
import { expect } from 'aegir/chai'
77
import { getDescribe, getIt } from '../utils/mocha.js'
8+
import pWaitFor from 'p-wait-for'
89

910
/**
1011
* @typedef {import('ipfsd-ctl').Factory} Factory
12+
* @typedef {import('ipfs-core-types').IPFS} IPFS
1113
*/
1214

15+
/**
16+
* @param {string} topic
17+
* @param {IPFS} ipfs
18+
* @param {IPFS} remote
19+
*/
20+
async function waitForRemoteToBeSubscribed (topic, ipfs, remote) {
21+
await remote.pubsub.subscribe(topic, () => {})
22+
const remoteId = await remote.id()
23+
24+
// wait for remote to be subscribed to topic
25+
await pWaitFor(async () => {
26+
const peers = await ipfs.pubsub.peers(topic)
27+
28+
return peers.map(p => p.toString()).includes(remoteId.id.toString())
29+
})
30+
}
31+
1332
/**
1433
* @param {Factory} factory
1534
* @param {object} options
@@ -21,30 +40,46 @@ export function testPublish (factory, options) {
2140
describe('.pubsub.publish', function () {
2241
this.timeout(80 * 1000)
2342

24-
/** @type {import('ipfs-core-types').IPFS} */
43+
/** @type {IPFS} */
2544
let ipfs
2645

46+
/** @type {IPFS} */
47+
let remote
48+
2749
before(async () => {
2850
ipfs = (await factory.spawn()).api
51+
remote = (await factory.spawn()).api
52+
53+
// ensure we have peers to allow publishing
54+
const remoteId = await remote.id()
55+
await ipfs.swarm.connect(remoteId.addresses[0])
2956
})
3057

3158
after(() => factory.clean())
3259

3360
it('should fail with undefined msg', async () => {
3461
const topic = getTopic()
62+
63+
await waitForRemoteToBeSubscribed(topic, ipfs, remote)
64+
3565
// @ts-expect-error invalid parameter
3666
await expect(ipfs.pubsub.publish(topic)).to.eventually.be.rejected()
3767
})
3868

39-
it('should publish message from buffer', () => {
69+
it('should publish message from buffer', async () => {
4070
const topic = getTopic()
71+
72+
await waitForRemoteToBeSubscribed(topic, ipfs, remote)
73+
4174
return ipfs.pubsub.publish(topic, uint8ArrayFromString(nanoid()))
4275
})
4376

4477
it('should publish 10 times within time limit', async () => {
4578
const count = 10
4679
const topic = getTopic()
4780

81+
await waitForRemoteToBeSubscribed(topic, ipfs, remote)
82+
4883
for (let i = 0; i < count; i++) {
4984
await ipfs.pubsub.publish(topic, uint8ArrayFromString(nanoid()))
5085
}

packages/ipfs-core-config/src/libp2p-pubsub-routers.browser.js

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { gossipsub } from '@chainsafe/libp2p-gossipsub'
55
/** @type {() => Record<string, (components: any) => PubSub>}>} */
66
export const routers = () => ({
77
gossipsub: gossipsub({
8-
allowPublishToZeroPeers: true,
98
fallbackToFloodsub: true,
109
emitSelf: true,
1110
maxInboundStreams: 64,

packages/ipfs-core-config/src/libp2p-pubsub-routers.js

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { floodsub } from '@libp2p/floodsub'
66
/** @type {() => Record<string, (components: any) => PubSub>}>} */
77
export const routers = () => ({
88
gossipsub: gossipsub({
9-
allowPublishToZeroPeers: true,
109
fallbackToFloodsub: true,
1110
emitSelf: true,
1211
maxInboundStreams: 64,

0 commit comments

Comments
 (0)