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

feat!: change connection encryption interface to uint8arraylist #278

Merged
merged 2 commits into from
Aug 5, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -13,4 +13,5 @@ docs
node_modules
# Lock files
package-lock.json
yarn.lock
yarn.lock
.vscode
Original file line number Diff line number Diff line change
@@ -143,6 +143,7 @@
"it-pair": "^2.0.2",
"it-pipe": "^2.0.3",
"it-stream-types": "^1.0.4",
"uint8arraylist": "^2.1.1",
"uint8arrays": "^3.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import { createMaConnPair } from './utils/index.js'
import type { TestSetup } from '@libp2p/interface-compliance-tests'
import type { ConnectionEncrypter } from '@libp2p/interface-connection-encrypter'
import type { PeerId } from '@libp2p/interface-peer-id'
import type { Source } from 'it-stream-types'
import { Uint8ArrayList } from 'uint8arraylist'

export default (common: TestSetup<ConnectionEncrypter>) => {
describe('interface-connection-encrypter compliance tests', () => {
@@ -56,16 +56,10 @@ export default (common: TestSetup<ConnectionEncrypter>) => {
void pipe(inboundResult.conn, inboundResult.conn)

// Send some data and collect the result
const input = uint8ArrayFromString('data to encrypt')
const input = new Uint8ArrayList(uint8ArrayFromString('data to encrypt'))
const result = await pipe(
[input],
outboundResult.conn,
// Convert BufferList to Buffer via slice
(source: Source<Uint8Array>) => (async function * toBuffer () {
for await (const chunk of source) {
yield chunk.slice()
}
})(),
async (source) => await all(source)
)

Original file line number Diff line number Diff line change
@@ -2,12 +2,13 @@ import { duplexPair } from 'it-pair/duplex'
import { Multiaddr } from '@multiformats/multiaddr'
import type { MultiaddrConnection } from '@libp2p/interface-connection'
import type { Duplex } from 'it-stream-types'
import type { Uint8ArrayList } from 'uint8arraylist'

export function createMaConnPair (): [MultiaddrConnection, MultiaddrConnection] {
const [local, remote] = duplexPair<Uint8Array>()
export function createMaConnPair (): [MultiaddrConnection<Uint8ArrayList>, MultiaddrConnection<Uint8ArrayList>] {
const [local, remote] = duplexPair<Uint8ArrayList>()

function duplexToMaConn (duplex: Duplex<Uint8Array>): MultiaddrConnection {
const output: MultiaddrConnection = {
function duplexToMaConn (duplex: Duplex<Uint8ArrayList>): MultiaddrConnection<Uint8ArrayList> {
const output: MultiaddrConnection<Uint8ArrayList> = {
...duplex,
close: async () => {},
remoteAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4001'),
3 changes: 2 additions & 1 deletion packages/interface-connection-encrypter/package.json
Original file line number Diff line number Diff line change
@@ -153,7 +153,8 @@
},
"dependencies": {
"@libp2p/interface-peer-id": "^1.0.0",
"it-stream-types": "^1.0.4"
"it-stream-types": "^1.0.4",
"uint8arraylist": "^2.1.1"
},
"devDependencies": {
"aegir": "^37.4.0"
7 changes: 4 additions & 3 deletions packages/interface-connection-encrypter/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { PeerId } from '@libp2p/interface-peer-id'
import type { Duplex } from 'it-stream-types'
import type { Uint8ArrayList } from 'uint8arraylist'

/**
* A libp2p connection encrypter module must be compliant to this interface
@@ -11,15 +12,15 @@ export interface ConnectionEncrypter {
/**
* Encrypt outgoing data to the remote party.
*/
secureOutbound: (localPeer: PeerId, connection: Duplex<Uint8Array>, remotePeer: PeerId) => Promise<SecuredConnection>
secureOutbound: (localPeer: PeerId, connection: Duplex<Uint8ArrayList>, remotePeer: PeerId) => Promise<SecuredConnection>
/**
* Decrypt incoming data.
*/
secureInbound: (localPeer: PeerId, connection: Duplex<Uint8Array>, remotePeer?: PeerId) => Promise<SecuredConnection>
secureInbound: (localPeer: PeerId, connection: Duplex<Uint8ArrayList>, remotePeer?: PeerId) => Promise<SecuredConnection>
}

export interface SecuredConnection {
conn: Duplex<Uint8Array>
conn: Duplex<Uint8ArrayList>
remoteEarlyData: Uint8Array
remotePeer: PeerId
}
3 changes: 2 additions & 1 deletion packages/interface-connection/package.json
Original file line number Diff line number Diff line change
@@ -155,7 +155,8 @@
"@libp2p/interface-peer-id": "^1.0.0",
"@libp2p/interfaces": "^3.0.0",
"@multiformats/multiaddr": "^10.2.0",
"it-stream-types": "^1.0.4"
"it-stream-types": "^1.0.4",
"uint8arraylist": "^2.1.1"
},
"devDependencies": {
"aegir": "^37.4.0"
13 changes: 7 additions & 6 deletions packages/interface-connection/src/index.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ import type { PeerId } from '@libp2p/interface-peer-id'
import type * as Status from './status.js'
import type { Duplex } from 'it-stream-types'
import type { AbortOptions } from '@libp2p/interfaces'
import type { Uint8ArrayList } from 'uint8arraylist'

export interface ConnectionTimeline {
open: number
@@ -71,7 +72,7 @@ export interface StreamStat {
* It may be encrypted and multiplexed depending on the
* configuration of the nodes.
*/
export interface Stream extends Duplex<Uint8Array> {
export interface Stream<T extends Uint8Array | Uint8ArrayList = Uint8Array> extends Duplex<T> {
/**
* Close a stream for reading and writing
*/
@@ -119,23 +120,23 @@ export interface Stream extends Duplex<Uint8Array> {
* multiplexed, depending on the configuration of the nodes
* between which the connection is made.
*/
export interface Connection {
export interface Connection<T extends Uint8Array | Uint8ArrayList = Uint8Array> {
id: string
stat: ConnectionStat
remoteAddr: Multiaddr
remotePeer: PeerId
tags: string[]
streams: Stream[]
streams: Array<Stream<T>>

newStream: (multicodecs: string | string[], options?: AbortOptions) => Promise<Stream>
addStream: (stream: Stream) => void
addStream: (stream: Stream<T>) => void
removeStream: (id: string) => void
close: () => Promise<void>
}

export const symbol = Symbol.for('@libp2p/connection')

export function isConnection (other: any): other is Connection {
export function isConnection (other: any): other is Connection<Uint8Array | Uint8ArrayList> {
return other != null && Boolean(other[symbol])
}

@@ -255,7 +256,7 @@ export interface MultiaddrConnectionTimeline {
* a peer. It is a low-level primitive and is the raw connection
* without encryption or stream multiplexing.
*/
export interface MultiaddrConnection extends Duplex<Uint8Array> {
export interface MultiaddrConnection<T extends Uint8Array | Uint8ArrayList = Uint8Array> extends Duplex<T> {
close: (err?: Error) => Promise<void>
remoteAddr: Multiaddr
timeline: MultiaddrConnectionTimeline
25 changes: 13 additions & 12 deletions packages/interface-mocks/src/connection-encrypter.ts
Original file line number Diff line number Diff line change
@@ -6,10 +6,11 @@ import { UnexpectedPeerError } from '@libp2p/interface-connection-encrypter/erro
import { Multiaddr } from '@multiformats/multiaddr'
import type { ConnectionEncrypter } from '@libp2p/interface-connection-encrypter'
import type { Transform, Source } from 'it-stream-types'
import { Uint8ArrayList } from 'uint8arraylist'

// A basic transform that does nothing to the data
const transform = (): Transform<Uint8Array, Uint8Array> => {
return (source: Source<Uint8Array>) => (async function * () {
const transform = <T>(): Transform<T, T> => {
return (source: Source<T>) => (async function * () {
for await (const chunk of source) {
yield chunk
}
@@ -21,8 +22,8 @@ export function mockConnectionEncrypter () {
protocol: 'insecure',
secureInbound: async (localPeer, duplex, expectedPeer) => {
// 1. Perform a basic handshake.
const shake = handshake(duplex)
shake.write(localPeer.toBytes())
const shake = handshake<Uint8ArrayList>(duplex)
shake.write(new Uint8ArrayList(localPeer.toBytes()))
const remoteId = await shake.read()

if (remoteId == null) {
@@ -37,9 +38,9 @@ export function mockConnectionEncrypter () {
}

// 2. Create your encryption box/unbox wrapper
const wrapper = duplexPair<Uint8Array>()
const encrypt = transform() // Use transform iterables to modify data
const decrypt = transform()
const wrapper = duplexPair<Uint8ArrayList>()
const encrypt = transform<Uint8ArrayList>() // Use transform iterables to modify data
const decrypt = transform<Uint8ArrayList>()

void pipe(
wrapper[0], // We write to wrapper
@@ -66,8 +67,8 @@ export function mockConnectionEncrypter () {
},
secureOutbound: async (localPeer, duplex, remotePeer) => {
// 1. Perform a basic handshake.
const shake = handshake(duplex)
shake.write(localPeer.toBytes())
const shake = handshake<Uint8ArrayList>(duplex)
shake.write(new Uint8ArrayList(localPeer.toBytes()))
const remoteId = await shake.read()

if (remoteId == null) {
@@ -77,9 +78,9 @@ export function mockConnectionEncrypter () {
shake.rest()

// 2. Create your encryption box/unbox wrapper
const wrapper = duplexPair<Uint8Array>()
const encrypt = transform()
const decrypt = transform()
const wrapper = duplexPair<Uint8ArrayList>()
const encrypt = transform<Uint8ArrayList>()
const decrypt = transform<Uint8ArrayList>()

void pipe(
wrapper[0], // We write to wrapper