Skip to content

Commit

Permalink
chore!: update dependencies (#322)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
- `Message` type updated
- `PublishConfigType.Author` removed
  • Loading branch information
wemeetagain committed Aug 11, 2022
1 parent 475e968 commit 891c6fd
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 78 deletions.
54 changes: 23 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,39 +64,39 @@
},
"homepage": "https://github.com/ChainSafe/js-libp2p-gossipsub#readme",
"dependencies": {
"@libp2p/components": "^2.0.0",
"@libp2p/crypto": "^1.0.0",
"@libp2p/interface-connection": "^2.0.0",
"@libp2p/interface-keys": "^1.0.2",
"@libp2p/interface-peer-id": "^1.0.2",
"@libp2p/interface-pubsub": "1.0.4",
"@libp2p/interface-registrar": "2.0.2",
"@libp2p/interfaces": "^3.0.2",
"@libp2p/components": "^2.0.3",
"@libp2p/crypto": "^1.0.3",
"@libp2p/interface-connection": "^3.0.1",
"@libp2p/interface-keys": "^1.0.3",
"@libp2p/interface-peer-id": "^1.0.4",
"@libp2p/interface-pubsub": "^2.0.1",
"@libp2p/interface-registrar": "^2.0.3",
"@libp2p/interfaces": "^3.0.3",
"@libp2p/logger": "^2.0.0",
"@libp2p/peer-id": "^1.1.13",
"@libp2p/peer-record": "2.0.0",
"@libp2p/pubsub": "^3.0.0",
"@libp2p/peer-id": "^1.1.15",
"@libp2p/peer-record": "^4.0.1",
"@libp2p/pubsub": "^3.1.2",
"@libp2p/topology": "^3.0.0",
"abortable-iterator": "^4.0.2",
"denque": "^1.5.0",
"err-code": "^3.0.1",
"it-length-prefixed": "^8.0.2",
"it-pipe": "^2.0.3",
"it-pushable": "^3.0.0",
"it-pipe": "^2.0.4",
"it-pushable": "^3.1.0",
"multiformats": "^9.6.4",
"protobufjs": "^6.11.2",
"uint8arraylist": "^2.0.0",
"uint8arraylist": "^2.3.2",
"uint8arrays": "^3.0.0"
},
"devDependencies": {
"@chainsafe/as-sha256": "^0.2.4",
"@dapplion/benchmark": "^0.2.2",
"@libp2p/floodsub": "^3.0.0",
"@libp2p/interface-mocks": "^3.0.1",
"@libp2p/interface-pubsub-compliance-tests": "^1.0.4",
"@libp2p/peer-id-factory": "^1.0.13",
"@libp2p/peer-store": "3.1.0",
"@multiformats/multiaddr": "^10.2.0",
"@libp2p/floodsub": "^3.0.5",
"@libp2p/interface-mocks": "^4.0.1",
"@libp2p/interface-pubsub-compliance-tests": "^2.0.2",
"@libp2p/peer-id-factory": "^1.0.18",
"@libp2p/peer-store": "^3.1.2",
"@multiformats/multiaddr": "^10.3.3",
"@types/node": "^17.0.21",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
Expand All @@ -112,14 +112,14 @@
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"it-pair": "^1.0.0",
"it-pair": "^2.0.2",
"lodash": "^4.17.15",
"os": "^0.1.1",
"p-defer": "^4.0.0",
"p-event": "^5.0.1",
"p-retry": "^4.2.0",
"p-times": "^2.1.0",
"p-wait-for": "^3.2.0",
"p-times": "^4.0.0",
"p-wait-for": "^5.0.0",
"prettier": "^2.0.5",
"promisify-es6": "^1.0.3",
"sinon": "^11.1.1",
Expand All @@ -128,14 +128,6 @@
"ts-sinon": "^2.0.2",
"util": "^0.12.3"
},
"overrides": {
"@libp2p/interface-connection": "^2.0.0",
"@libp2p/interface-pubsub": "1.0.4",
"@libp2p/interface-connection-manager": "1.0.2",
"@libp2p/interface-stream-muxer": "2.0.1",
"@libp2p/interface-transport": "1.0.2",
"@libp2p/interface-peer-store": "1.2.0"
},
"engines": {
"npm": ">=8.7.0"
},
Expand Down
30 changes: 7 additions & 23 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Logger, logger } from '@libp2p/logger'
import { createTopology } from '@libp2p/topology'
import type { PeerId } from '@libp2p/interface-peer-id'
import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'

import { MessageCache } from './message-cache.js'
import { RPC, IRPC } from './message/rpc.js'
Expand Down Expand Up @@ -1076,24 +1075,18 @@ export class GossipSub extends EventEmitter<GossipsubEvents> implements Initiali
return { code: MessageStatus.invalid, reason: RejectReason.Error, error: validationResult.error }
}

const msg = validationResult.message

// Try and perform the data transform to the message. If it fails, consider it invalid.
let data: Uint8Array
try {
const transformedData = rpcMsg.data ?? new Uint8Array(0)
data = this.dataTransform ? this.dataTransform.inboundTransform(rpcMsg.topic, transformedData) : transformedData
if (this.dataTransform) {
msg.data = this.dataTransform.inboundTransform(rpcMsg.topic, msg.data)
}
} catch (e) {
this.log('Invalid message, transform failed', e)
return { code: MessageStatus.invalid, reason: RejectReason.Error, error: ValidateError.TransformFailed }
}

const msg: Message = {
// TODO fix types upstream, see https://github.com/libp2p/js-libp2p-interfaces/pull/266
from: (rpcMsg.from == null ? undefined : peerIdFromBytes(rpcMsg.from)) as PeerId,
data: data,
sequenceNumber: rpcMsg.seqno == null ? undefined : BigInt(`0x${uint8ArrayToString(rpcMsg.seqno, 'base16')}`),
topic: rpcMsg.topic
}

// TODO: Check if message is from a blacklisted source or propagation origin
// - Reject any message from a blacklisted peer
// - Also reject any message that originated from a blacklisted peer
Expand Down Expand Up @@ -1937,18 +1930,9 @@ export class GossipSub extends EventEmitter<GossipsubEvents> implements Initiali
}

// Prepare raw message with user's publishConfig
const rawMsg = await buildRawMessage(this.publishConfig, topic, transformedData)
const { raw: rawMsg, msg } = await buildRawMessage(this.publishConfig, topic, data, transformedData)

// calculate the message id from the un-transformed data
const msg: Message = {
// TODO fix types upstream, see https://github.com/libp2p/js-libp2p-interfaces/pull/266
from: (rawMsg.from ? peerIdFromBytes(rawMsg.from) : undefined) as PeerId,
data, // the uncompressed form
sequenceNumber: rawMsg.seqno == null ? undefined : BigInt(`0x${uint8ArrayToString(rawMsg.seqno, 'base16')}`),
topic,
signature: rawMsg.signature ?? undefined,
key: rawMsg.key ?? undefined
}
const msgId = await this.msgIdFn(msg)
const msgIdStr = this.msgIdToStrFn(msgId)

Expand All @@ -1958,7 +1942,7 @@ export class GossipSub extends EventEmitter<GossipsubEvents> implements Initiali
throw Error('PublishError.Duplicate')
}

const { tosend, tosendCount } = this.selectPeersToPublish(rawMsg.topic)
const { tosend, tosendCount } = this.selectPeersToPublish(topic)
const willSendToSelf = this.opts.emitSelf === true && this.subscriptions.has(topic)

if (tosend.size === 0 && !this.opts.allowPublishToZeroPeers && !willSendToSelf) {
Expand Down
2 changes: 0 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ export enum SignaturePolicy {

export enum PublishConfigType {
Signing,
Author,
Anonymous
}

Expand All @@ -97,7 +96,6 @@ export type PublishConfig =
key: Uint8Array
privateKey: PrivateKey
}
| { type: PublishConfigType.Author; author: PeerId }
| { type: PublishConfigType.Anonymous }

export enum MessageAcceptance {
Expand Down
70 changes: 48 additions & 22 deletions src/utils/buildRawMessage.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import { unmarshalPublicKey } from '@libp2p/crypto/keys'
import { marshalPublicKey, unmarshalPublicKey } from '@libp2p/crypto/keys'
import { randomBytes } from '@libp2p/crypto'
import { peerIdFromBytes } from '@libp2p/peer-id'
import type { PublicKey } from '@libp2p/interface-keys'
import type { PeerId } from '@libp2p/interface-peer-id'
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
import { RPC } from '../message/rpc.js'
import { PublishConfig, PublishConfigType, TopicStr, ValidateError } from '../types.js'
import { StrictSign, StrictNoSign } from '@libp2p/interface-pubsub'
import { StrictSign, StrictNoSign, Message } from '@libp2p/interface-pubsub'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'

export const SignPrefix = uint8ArrayFromString('libp2p-pubsub:')

export type RawMessageAndMessage = {
raw: RPC.IMessage
msg: Message
}

export async function buildRawMessage(
publishConfig: PublishConfig,
topic: TopicStr,
originalData: Uint8Array,
transformedData: Uint8Array
): Promise<RPC.IMessage> {
): Promise<RawMessageAndMessage> {
switch (publishConfig.type) {
case PublishConfigType.Signing: {
const rpcMsg: RPC.IMessage = {
Expand All @@ -35,34 +42,42 @@ export async function buildRawMessage(
rpcMsg.signature = await publishConfig.privateKey.sign(bytes)
rpcMsg.key = publishConfig.key

return rpcMsg
}

case PublishConfigType.Author: {
return {
from: publishConfig.author.toBytes(),
data: transformedData,
seqno: randomBytes(8),
const msg: Message = {
type: 'signed',
from: publishConfig.author,
data: originalData,
sequenceNumber: BigInt(`0x${uint8ArrayToString(rpcMsg.seqno as Uint8Array, 'base16')}`),
topic,
signature: undefined,
key: undefined
signature: rpcMsg.signature,
key: rpcMsg.key
}
return {
raw: rpcMsg,
msg: msg
}
}

case PublishConfigType.Anonymous: {
return {
from: undefined,
data: transformedData,
seqno: undefined,
topic,
signature: undefined,
key: undefined
raw: {
from: undefined,
data: transformedData,
seqno: undefined,
topic,
signature: undefined,
key: undefined
},
msg: {
type: 'unsigned',
data: originalData,
topic
}
}
}
}
}

export type ValidationResult = { valid: true; fromPeerId: PeerId | null } | { valid: false; error: ValidateError }
export type ValidationResult = { valid: true; message: Message } | { valid: false; error: ValidateError }

export async function validateToRawMessage(
signaturePolicy: typeof StrictNoSign | typeof StrictSign,
Expand All @@ -77,7 +92,7 @@ export async function validateToRawMessage(
if (msg.seqno != null) return { valid: false, error: ValidateError.SeqnoPresent }
if (msg.key != null) return { valid: false, error: ValidateError.FromPresent }

return { valid: true, fromPeerId: null }
return { valid: true, message: { type: 'unsigned', topic: msg.topic, data: msg.data ?? new Uint8Array(0) } }

case StrictSign: {
// Verify seqno
Expand Down Expand Up @@ -135,7 +150,18 @@ export async function validateToRawMessage(
return { valid: false, error: ValidateError.InvalidSignature }
}

return { valid: true, fromPeerId }
return {
valid: true,
message: {
type: 'signed',
from: fromPeerId,
data: msg.data ?? new Uint8Array(0),
sequenceNumber: BigInt(`0x${uint8ArrayToString(msg.seqno, 'base16')}`),
topic: msg.topic,
signature: msg.signature,
key: msg.key ?? marshalPublicKey(publicKey)
}
}
}
}
}
3 changes: 3 additions & 0 deletions src/utils/msgIdFn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { msgId } from '@libp2p/pubsub/utils'
* Generate a message id, based on the `key` and `seqno`
*/
export function msgIdFnStrictSign(msg: Message): Uint8Array {
if (msg.type !== 'signed') {
throw new Error('expected signed message type')
}
// Should never happen
if (msg.sequenceNumber == null) throw Error('missing seqno field')

Expand Down
10 changes: 10 additions & 0 deletions test/2-nodes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ describe('2 nodes', () => {

const evt = await promise

if (evt.detail.type !== 'signed') {
throw new Error('unexpected msg type')
}
expect(evt.detail.data).to.equalBytes(data)
expect(evt.detail.from.toString()).to.equal(nodes[0].getPeerId().toString())

Expand All @@ -193,6 +196,9 @@ describe('2 nodes', () => {

const evt = await promise

if (evt.detail.type !== 'signed') {
throw new Error('unexpected msg type')
}
expect(evt.detail.data).to.equalBytes(data)
expect(evt.detail.from.toString()).to.equal(nodes[1].getPeerId().toString())

Expand All @@ -211,6 +217,10 @@ describe('2 nodes', () => {
const msg = evt.detail

expect(uint8ArrayToString(msg.data)).to.startWith('banana')

if (msg.type !== 'signed') {
throw new Error('unexpected msg type')
}
expect(msg.from.toString()).to.equal(nodes[1].getPeerId().toString())
expect(msg.sequenceNumber).to.be.a('BigInt')
expect(msg.topic).to.equal(topic)
Expand Down
3 changes: 3 additions & 0 deletions test/e2e/go-gossipsub.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,9 @@ describe('go-libp2p-pubsub gossipsub tests', function () {

psubs.slice(1).forEach((ps) =>
ps.getPubSub().addEventListener('message', (evt) => {
if (evt.detail.type !== 'signed') {
throw new Error('unexpected message type')
}
expect(evt.detail.from.equals(psubs[0].getPeerId())).to.be.false()
})
)
Expand Down
6 changes: 6 additions & 0 deletions test/floodsub.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ describe('gossipsub fallbacks to floodsub', () => {
await nodeGs.getPubSub().publish(topic, data)

const evt = await promise
if (evt.detail.type !== 'signed') {
throw new Error('unexpected message type')
}
expect(evt.detail.data).to.equalBytes(data)
expect(evt.detail.from.toString()).to.be.eql(nodeGs.getPeerId().toString())
})
Expand All @@ -200,6 +203,9 @@ describe('gossipsub fallbacks to floodsub', () => {
await nodeFs.getPubSub().publish(topic, data)

const evt = await promise
if (evt.detail.type !== 'signed') {
throw new Error('unexpected message type')
}
expect(evt.detail.data).to.equalBytes(data)
expect(evt.detail.from.toString()).to.be.eql(nodeFs.getPeerId().toString())
})
Expand Down

0 comments on commit 891c6fd

Please sign in to comment.