Skip to content
This repository has been archived by the owner on Jun 26, 2023. It is now read-only.

Commit

Permalink
fix: hide implementations behind factory methods (#167)
Browse files Browse the repository at this point in the history
To avoid leaking concrete implementation classes, hide their defintion and creation behind factory methods that are typed to return the interfaces they implement.
  • Loading branch information
achingbrain authored Feb 12, 2022
1 parent 54020ca commit 2fba080
Show file tree
Hide file tree
Showing 26 changed files with 235 additions and 216 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PeerId } from '@libp2p/peer-id'
import { peerIdFromString } from '@libp2p/peer-id'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import { pipe } from 'it-pipe'
import { duplexPair } from 'it-pair/duplex'
Expand All @@ -11,7 +11,7 @@ import { mockMuxer } from './muxer.js'
export async function mockConnection (maConn: MultiaddrConnection, direction: 'inbound' | 'outbound' = 'inbound', muxer: Muxer = mockMuxer()): Promise<Connection> {
const remoteAddr = maConn.remoteAddr
const remotePeerIdStr = remoteAddr.getPeerId()
const remotePeer = remotePeerIdStr != null ? PeerId.fromString(remotePeerIdStr) : await createEd25519PeerId()
const remotePeer = remotePeerIdStr != null ? peerIdFromString(remotePeerIdStr) : await createEd25519PeerId()
const registry = new Map()
const streams: Stream[] = []
let streamId = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'aegir/utils/chai.js'
import { pair } from 'it-pair'
import { PeerId } from '@libp2p/peer-id'
import { peerIdFromString } from '@libp2p/peer-id'
import * as PeerIdFactory from '@libp2p/peer-id-factory'
import { pushable } from 'it-pushable'
import drain from 'it-drain'
Expand Down Expand Up @@ -114,7 +114,7 @@ export function mockUpgrader (options: MockUpgraderOptions = {}) {
async function createConnection (maConn: MultiaddrConnection, direction: 'inbound' | 'outbound', muxer: Muxer): Promise<Connection> {
const remoteAddr = maConn.remoteAddr
const remotePeerIdStr = remoteAddr.getPeerId()
const remotePeer = remotePeerIdStr != null ? PeerId.fromString(remotePeerIdStr) : await PeerIdFactory.createEd25519PeerId()
const remotePeer = remotePeerIdStr != null ? peerIdFromString(remotePeerIdStr) : await PeerIdFactory.createEd25519PeerId()

const streams: Stream[] = []
let streamId = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PeerId } from '@libp2p/peer-id'
import { peerIdFromBytes } from '@libp2p/peer-id'
import { handshake } from 'it-handshake'
import { duplexPair } from 'it-pair/duplex'
import { pipe } from 'it-pipe'
Expand Down Expand Up @@ -28,7 +28,7 @@ const crypto: Crypto = {
throw new Error('Could not read remote ID')
}

const remotePeer = PeerId.fromBytes(remoteId.slice())
const remotePeer = peerIdFromBytes(remoteId.slice())
shake.rest()

if (expectedPeer != null && !expectedPeer.equals(remotePeer)) {
Expand Down Expand Up @@ -99,7 +99,7 @@ const crypto: Crypto = {
},
conn: true
},
remotePeer: PeerId.fromBytes(remoteId.slice()),
remotePeer: peerIdFromBytes(remoteId.slice()),
remoteEarlyData: new Uint8Array(0)
}
}
Expand Down
16 changes: 12 additions & 4 deletions packages/libp2p-interfaces/src/peer-id/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { CID } from 'multiformats/cid'
import type { MultihashDigest } from 'multiformats/hashes/interface'
import type { MultibaseEncoder } from 'multiformats/bases/interface'

export interface PeerId {
interface BasePeerId {
readonly type: 'RSA' | 'Ed25519' | 'secp256k1'
readonly multihash: MultihashDigest
readonly privateKey?: Uint8Array
Expand All @@ -14,17 +14,25 @@ export interface PeerId {
equals: (other: any) => boolean
}

export interface RSAPeerId extends PeerId {
export interface RSAPeerId extends BasePeerId {
readonly type: 'RSA'
readonly publicKey?: Uint8Array
}

export interface Ed25519PeerId extends PeerId {
export interface Ed25519PeerId extends BasePeerId {
readonly type: 'Ed25519'
readonly publicKey: Uint8Array
}

export interface Secp256k1PeerId extends PeerId {
export interface Secp256k1PeerId extends BasePeerId {
readonly type: 'secp256k1'
readonly publicKey: Uint8Array
}

export type PeerId = RSAPeerId | Ed25519PeerId | Secp256k1PeerId

export const symbol = Symbol.for('@libp2p/peer-id')

export function isPeerId (other: any): other is PeerId {
return symbol in other
}
10 changes: 5 additions & 5 deletions packages/libp2p-peer-id-factory/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { keys } from '@libp2p/crypto'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import { PeerId } from '@libp2p/peer-id'
import { peerIdFromKeys, peerIdFromBytes } from '@libp2p/peer-id'
import { PeerIdProto } from './proto.js'
import type { PublicKey, PrivateKey } from '@libp2p/interfaces/keys'
import type { RSAPeerId, Ed25519PeerId, Secp256k1PeerId } from '@libp2p/peer-id'
import type { RSAPeerId, Ed25519PeerId, Secp256k1PeerId } from '@libp2p/interfaces/peer-id'

export const createEd25519PeerId = async (): Promise<Ed25519PeerId> => {
const key = await keys.generateKeyPair('Ed25519')
Expand Down Expand Up @@ -39,11 +39,11 @@ export const createRSAPeerId = async (opts?: { bits: number }): Promise<RSAPeerI
}

export async function createFromPubKey (publicKey: PublicKey) {
return await PeerId.fromKeys(keys.marshalPublicKey(publicKey))
return await peerIdFromKeys(keys.marshalPublicKey(publicKey))
}

export async function createFromPrivKey (privateKey: PrivateKey) {
return await PeerId.fromKeys(keys.marshalPublicKey(privateKey.public), keys.marshalPrivateKey(privateKey))
return await peerIdFromKeys(keys.marshalPublicKey(privateKey.public), keys.marshalPrivateKey(privateKey))
}

export function exportToProtobuf (peerId: RSAPeerId | Ed25519PeerId | Secp256k1PeerId, excludePrivateKey?: boolean) {
Expand Down Expand Up @@ -87,5 +87,5 @@ async function createFromParts (multihash: Uint8Array, privKey?: Uint8Array, pub
return await createFromPubKey(key)
}

return PeerId.fromBytes(multihash)
return peerIdFromBytes(multihash)
}
39 changes: 20 additions & 19 deletions packages/libp2p-peer-id-factory/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { base58btc } from 'multiformats/bases/base58'
import { identity } from 'multiformats/hashes/identity'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import { PeerId } from '@libp2p/peer-id'
import { peerIdFromString, peerIdFromBytes, peerIdFromCID, createPeerId } from '@libp2p/peer-id'
import * as PeerIdFactory from '../src/index.js'
import util from 'util'
import testId from './fixtures/sample-id.js'
Expand All @@ -29,7 +29,8 @@ const testIdCIDString = testIdCID.toString()

describe('PeerId', () => {
it('create an id without \'new\'', () => {
expect(PeerId).to.throw(Error)
// @ts-expect-error missing args
expect(() => createPeerId()).to.throw(Error)
})

it('create a new id', async () => {
Expand All @@ -45,49 +46,49 @@ describe('PeerId', () => {

it('can get the public key from a Secp256k1 key', async () => {
const original = await PeerIdFactory.createSecp256k1PeerId()
const newId = PeerId.fromString(original.toString(base58btc))
const newId = peerIdFromString(original.toString(base58btc))
expect(original.publicKey).to.equalBytes(newId.publicKey)
})

it('recreate from a Uint8Array', () => {
const id = PeerId.fromBytes(testIdBytes)
const id = peerIdFromBytes(testIdBytes)
expect(testId.id).to.equal(uint8ArrayToString(id.multihash.bytes, 'base16'))
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})

it('recreate from a B58 String', () => {
const id = PeerId.fromString(testIdB58String)
const id = peerIdFromString(testIdB58String)
expect(testIdB58String).to.equal(id.toString())
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})

it('recreate from CID object', () => {
const id = PeerId.fromCID(testIdCID)
const id = peerIdFromCID(testIdCID)
expect(testIdCIDString).to.equal(id.toCID().toString())
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})

it('recreate from Base58 String (CIDv0)', () => {
const id = PeerId.fromCID(CID.parse(testIdB58String))
const id = peerIdFromCID(CID.parse(testIdB58String))
expect(testIdCIDString).to.equal(id.toCID().toString())
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})

it('recreate from Base36 String', () => {
const id = PeerId.fromString(testIdB36String)
const id = peerIdFromString(testIdB36String)
expect(testIdCIDString).to.equal(id.toCID().toString())
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})

it('recreate from CIDv1 Base32 (libp2p-key multicodec)', () => {
const cid = CID.createV1(LIBP2P_KEY_CODE, testIdDigest)
const id = PeerId.fromCID(cid)
const id = peerIdFromCID(cid)
expect(cid.toString()).to.equal(id.toCID().toString())
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})

it('recreate from CID Uint8Array', () => {
const id = PeerId.fromBytes(testIdCID.bytes)
const id = peerIdFromBytes(testIdCID.bytes)
expect(testIdCIDString).to.equal(id.toCID().toString())
expect(testIdBytes).to.equalBytes(id.multihash.bytes)
})
Expand All @@ -96,7 +97,7 @@ describe('PeerId', () => {
// only libp2p and dag-pb are supported
const invalidCID = CID.createV1(RAW_CODE, testIdDigest)
expect(() => {
PeerId.fromCID(invalidCID)
peerIdFromCID(invalidCID)
}).to.throw(/invalid/i)
})

Expand All @@ -105,15 +106,15 @@ describe('PeerId', () => {
// https://github.com/multiformats/js-multihash/blob/b85999d5768bf06f1b0f16b926ef2cb6d9c14265/src/constants.js#L345
const invalidMultihash = uint8ArrayToString(Uint8Array.from([0x50, 0x1, 0x0]), 'base58btc')
expect(() => {
PeerId.fromString(invalidMultihash)
peerIdFromString(invalidMultihash)
}).to.throw(/Non-base32hexpadupper character/i)
})

it('throws on invalid CID object', () => {
const invalidCID = {}
expect(() => {
// @ts-expect-error invalid cid is invalid type
PeerId.fromCID(invalidCID)
peerIdFromCID(invalidCID)
}).to.throw(/invalid/i)
})

Expand Down Expand Up @@ -153,7 +154,7 @@ describe('PeerId', () => {

it('recreate from embedded ed25519 key', async () => {
const key = '12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD'
const id = await PeerId.fromString(key)
const id = await peerIdFromString(key)
expect(id.toString()).to.equal(key)

if (id.publicKey == null) {
Expand All @@ -166,7 +167,7 @@ describe('PeerId', () => {

it('recreate from embedded secp256k1 key', async () => {
const key = '16Uiu2HAm5qw8UyXP2RLxQUx5KvtSN8DsTKz8quRGqGNC3SYiaB8E'
const id = await PeerId.fromString(key)
const id = await peerIdFromString(key)
expect(id.toString()).to.equal(key)

if (id.publicKey == null) {
Expand All @@ -179,7 +180,7 @@ describe('PeerId', () => {

it('recreate from string key', async () => {
const key = 'QmRsooYQasV5f5r834NSpdUtmejdQcpxXkK6qsozZWEihC'
const id = await PeerId.fromString(key)
const id = await peerIdFromString(key)
expect(id.toString()).to.equal(key)
})

Expand Down Expand Up @@ -258,7 +259,7 @@ describe('PeerId', () => {
it('only id', async () => {
const key = await keys.generateKeyPair('RSA', 1024)
const digest = await key.public.hash()
const id = PeerId.fromBytes(digest)
const id = peerIdFromBytes(digest)
expect(id.privateKey).to.not.exist()
expect(id.publicKey).to.not.exist()
const other = await PeerIdFactory.createFromJSON({
Expand All @@ -277,8 +278,8 @@ describe('PeerId', () => {

it('keys are equal after one is stringified', async () => {
const peerId = await PeerIdFactory.createEd25519PeerId()
const peerId1 = PeerId.fromString(peerId.toString(base58btc))
const peerId2 = PeerId.fromString(peerId.toString(base58btc))
const peerId1 = peerIdFromString(peerId.toString(base58btc))
const peerId2 = peerIdFromString(peerId.toString(base58btc))

expect(peerId1).to.deep.equal(peerId2)

Expand Down
Loading

0 comments on commit 2fba080

Please sign in to comment.