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

Commit

Permalink
deps!: update interface deps to use byte lists (#16)
Browse files Browse the repository at this point in the history
To support no-copy operations, update interfaces to use `Uint8ArrayList`s instead of `Uint8Array`s.
  • Loading branch information
achingbrain committed Aug 3, 2022
1 parent cd6bded commit 878f0ca
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 44 deletions.
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
"dependencies": {
"@libp2p/crypto": "^1.0.0",
"@libp2p/interface-peer-id": "^1.0.2",
"@libp2p/interface-record": "^1.0.1",
"@libp2p/interface-record": "^2.0.0",
"@libp2p/logger": "^2.0.0",
"@libp2p/peer-id": "^1.1.13",
"@libp2p/utils": "^3.0.0",
Expand All @@ -160,16 +160,18 @@
"it-map": "^1.0.6",
"it-pipe": "^2.0.3",
"multiformats": "^9.6.3",
"protons-runtime": "^1.0.4",
"protons-runtime": "^2.0.2",
"uint8-varint": "^1.0.2",
"uint8arraylist": "^2.1.0",
"uint8arrays": "^3.0.0",
"varint": "^6.0.0"
},
"devDependencies": {
"@libp2p/interface-record-compliance-tests": "^1.0.0",
"@libp2p/interface-record-compliance-tests": "^2.0.0",
"@libp2p/peer-id-factory": "^1.0.0",
"@types/varint": "^6.0.0",
"aegir": "^37.3.0",
"protons": "^3.0.4",
"protons": "^4.0.1",
"sinon": "^14.0.0"
}
}
5 changes: 3 additions & 2 deletions src/envelope/envelope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { encodeMessage, decodeMessage, message, bytes } from 'protons-runtime'
import type { Codec } from 'protons-runtime'
import type { Uint8ArrayList } from 'uint8arraylist'

export interface Envelope {
publicKey: Uint8Array
Expand All @@ -21,11 +22,11 @@ export namespace Envelope {
})
}

export const encode = (obj: Envelope): Uint8Array => {
export const encode = (obj: Envelope): Uint8ArrayList => {
return encodeMessage(obj, Envelope.codec())
}

export const decode = (buf: Uint8Array): Envelope => {
export const decode = (buf: Uint8Array | Uint8ArrayList): Envelope => {
return decodeMessage(buf, Envelope.codec())
}
}
53 changes: 25 additions & 28 deletions src/envelope/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import errCode from 'err-code'
import { concat as uint8arraysConcat } from 'uint8arrays/concat'
import { fromString as uint8arraysFromString } from 'uint8arrays/from-string'
import { unmarshalPrivateKey, unmarshalPublicKey } from '@libp2p/crypto/keys'
import varint from 'varint'
import { equals as uint8arraysEquals } from 'uint8arrays/equals'
import { codes } from '../errors.js'
import { Envelope as Protobuf } from './envelope.js'
import { peerIdFromKeys } from '@libp2p/peer-id'
import type { PeerId } from '@libp2p/interface-peer-id'
import type { Record, Envelope } from '@libp2p/interface-record'
import { Uint8ArrayList } from 'uint8arraylist'
import { unsigned } from 'uint8-varint'

export interface EnvelopeInit {
peerId: PeerId
payloadType: Uint8Array
payload: Uint8Array
payload: Uint8Array | Uint8ArrayList
signature: Uint8Array
}

export class RecordEnvelope implements Envelope {
/**
* Unmarshal a serialized Envelope protobuf message
*/
static createFromProtobuf = async (data: Uint8Array) => {
static createFromProtobuf = async (data: Uint8Array | Uint8ArrayList) => {
const envelopeData = Protobuf.decode(data)
const peerId = await peerIdFromKeys(envelopeData.publicKey)

Expand All @@ -38,18 +37,16 @@ export class RecordEnvelope implements Envelope {
* and signs it with the given peerId's private key
*/
static seal = async (record: Record, peerId: PeerId) => {
const domain = record.domain
const payloadType = record.codec
const payload = record.marshal()

const signData = formatSignaturePayload(domain, payloadType, payload)

if (peerId.privateKey == null) {
throw new Error('Missing private key')
}

const domain = record.domain
const payloadType = record.codec
const payload = record.marshal()
const signData = formatSignaturePayload(domain, payloadType, payload)
const key = await unmarshalPrivateKey(peerId.privateKey)
const signature = await key.sign(signData)
const signature = await key.sign(signData.subarray())

return new RecordEnvelope({
peerId,
Expand All @@ -63,7 +60,7 @@ export class RecordEnvelope implements Envelope {
* Open and certify a given marshalled envelope.
* Data is unmarshalled and the signature validated for the given domain.
*/
static openAndCertify = async (data: Uint8Array, domain: string) => {
static openAndCertify = async (data: Uint8Array | Uint8ArrayList, domain: string) => {
const envelope = await RecordEnvelope.createFromProtobuf(data)
const valid = await envelope.validate(domain)

Expand All @@ -76,9 +73,9 @@ export class RecordEnvelope implements Envelope {

public peerId: PeerId
public payloadType: Uint8Array
public payload: Uint8Array
public payload: Uint8Array | Uint8ArrayList
public signature: Uint8Array
public marshaled?: Uint8Array
public marshaled?: Uint8ArrayList

/**
* The Envelope is responsible for keeping an arbitrary signed record
Expand All @@ -96,7 +93,7 @@ export class RecordEnvelope implements Envelope {
/**
* Marshal the envelope content
*/
marshal () {
marshal (): Uint8ArrayList {
if (this.peerId.publicKey == null) {
throw new Error('Missing public key')
}
Expand All @@ -105,7 +102,7 @@ export class RecordEnvelope implements Envelope {
this.marshaled = Protobuf.encode({
publicKey: this.peerId.publicKey,
payloadType: this.payloadType,
payload: this.payload,
payload: this.payload.subarray(),
signature: this.signature
})
}
Expand All @@ -117,7 +114,7 @@ export class RecordEnvelope implements Envelope {
* Verifies if the other Envelope is identical to this one
*/
equals (other: Envelope) {
return uint8arraysEquals(this.marshal(), other.marshal())
return this.marshal().equals(other.marshal())
}

/**
Expand All @@ -132,14 +129,14 @@ export class RecordEnvelope implements Envelope {

const key = unmarshalPublicKey(this.peerId.publicKey)

return await key.verify(signData, this.signature)
return await key.verify(signData.subarray(), this.signature)
}
}

/**
* Helper function that prepares a Uint8Array to sign or verify a signature
*/
const formatSignaturePayload = (domain: string, payloadType: Uint8Array, payload: Uint8Array) => {
const formatSignaturePayload = (domain: string, payloadType: Uint8Array, payload: Uint8Array | Uint8ArrayList): Uint8ArrayList => {
// When signing, a peer will prepare a Uint8Array by concatenating the following:
// - The length of the domain separation string string in bytes
// - The domain separation string, encoded as UTF-8
Expand All @@ -149,16 +146,16 @@ const formatSignaturePayload = (domain: string, payloadType: Uint8Array, payload
// - The value of the payload field

const domainUint8Array = uint8arraysFromString(domain)
const domainLength = varint.encode(domainUint8Array.byteLength)
const payloadTypeLength = varint.encode(payloadType.length)
const payloadLength = varint.encode(payload.length)
const domainLength = unsigned.encode(domainUint8Array.byteLength)
const payloadTypeLength = unsigned.encode(payloadType.length)
const payloadLength = unsigned.encode(payload.length)

return uint8arraysConcat([
new Uint8Array(domainLength),
return new Uint8ArrayList(
domainLength,
domainUint8Array,
new Uint8Array(payloadTypeLength),
payloadTypeLength,
payloadType,
new Uint8Array(payloadLength),
payloadLength,
payload
])
)
}
5 changes: 3 additions & 2 deletions src/peer-record/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ENVELOPE_DOMAIN_PEER_RECORD,
ENVELOPE_PAYLOAD_TYPE_PEER_RECORD
} from './consts.js'
import type { Uint8ArrayList } from 'uint8arraylist'

export interface PeerRecordInit {
peerId: PeerId
Expand All @@ -30,7 +31,7 @@ export class PeerRecord {
/**
* Unmarshal Peer Record Protobuf
*/
static createFromProtobuf = (buf: Uint8Array): PeerRecord => {
static createFromProtobuf = (buf: Uint8Array | Uint8ArrayList): PeerRecord => {
const peerRecord = Protobuf.decode(buf)
const peerId = peerIdFromBytes(peerRecord.peerId)
const multiaddrs = (peerRecord.addresses ?? []).map((a) => new Multiaddr(a.multiaddr))
Expand All @@ -47,7 +48,7 @@ export class PeerRecord {
public seqNumber: bigint
public domain = PeerRecord.DOMAIN
public codec = PeerRecord.CODEC
private marshaled?: Uint8Array
private marshaled?: Uint8ArrayList

constructor (init: PeerRecordInit) {
const { peerId, multiaddrs, seqNumber } = init
Expand Down
9 changes: 5 additions & 4 deletions src/peer-record/peer-record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { encodeMessage, decodeMessage, message, bytes, uint64 } from 'protons-runtime'
import type { Codec } from 'protons-runtime'
import type { Uint8ArrayList } from 'uint8arraylist'

export interface PeerRecord {
peerId: Uint8Array
Expand All @@ -22,11 +23,11 @@ export namespace PeerRecord {
})
}

export const encode = (obj: AddressInfo): Uint8Array => {
export const encode = (obj: AddressInfo): Uint8ArrayList => {
return encodeMessage(obj, AddressInfo.codec())
}

export const decode = (buf: Uint8Array): AddressInfo => {
export const decode = (buf: Uint8Array | Uint8ArrayList): AddressInfo => {
return decodeMessage(buf, AddressInfo.codec())
}
}
Expand All @@ -39,11 +40,11 @@ export namespace PeerRecord {
})
}

export const encode = (obj: PeerRecord): Uint8Array => {
export const encode = (obj: PeerRecord): Uint8ArrayList => {
return encodeMessage(obj, PeerRecord.codec())
}

export const decode = (buf: Uint8Array): PeerRecord => {
export const decode = (buf: Uint8Array | Uint8ArrayList): PeerRecord => {
return decodeMessage(buf, PeerRecord.codec())
}
}
8 changes: 4 additions & 4 deletions test/envelope.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { expect } from 'aegir/chai'
import { fromString as uint8arrayFromString } from 'uint8arrays/from-string'
import { equals as uint8arrayEquals } from 'uint8arrays/equals'
import { RecordEnvelope } from '../src/envelope/index.js'
import { codes as ErrorCodes } from '../src/errors.js'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import type { Record } from '@libp2p/interface-record'
import type { PeerId } from '@libp2p/interface-peer-id'
import { Uint8ArrayList } from 'uint8arraylist'

const domain = 'libp2p-testing'
const codec = uint8arrayFromString('/libp2p/testdata')
Expand All @@ -22,11 +22,11 @@ class TestRecord implements Record {
}

marshal () {
return uint8arrayFromString(this.data)
return new Uint8ArrayList(uint8arrayFromString(this.data))
}

equals (other: Record) {
return uint8arrayEquals(this.marshal(), other.marshal())
return this.marshal().equals(other.marshal())
}
}

Expand Down Expand Up @@ -54,7 +54,7 @@ describe('Envelope', () => {
expect(envelope).to.exist()
expect(envelope.peerId.equals(peerId)).to.eql(true)
expect(envelope.payloadType).to.equalBytes(payloadType)
expect(envelope.payload).to.equalBytes(payload)
expect(envelope.payload.subarray()).to.equalBytes(payload.subarray())
expect(envelope.signature).to.equalBytes(signature)
})

Expand Down

0 comments on commit 878f0ca

Please sign in to comment.