mirror of
https://github.com/logos-messaging/js-waku.git
synced 2026-01-05 23:33:08 +00:00
383 lines
14 KiB
TypeScript
383 lines
14 KiB
TypeScript
import { assert, expect } from 'chai';
|
|
import { Multiaddr } from 'multiaddr';
|
|
import PeerId from 'peer-id';
|
|
|
|
import { bufToHex } from '../utils';
|
|
|
|
import { ERR_INVALID_ID } from './constants';
|
|
import { ENR } from './enr';
|
|
import { createKeypairFromPeerId } from './keypair';
|
|
|
|
import { v4 } from './index';
|
|
|
|
describe('ENR', function () {
|
|
describe('decodeTxt', () => {
|
|
it('should encodeTxt and decodeTxt', async () => {
|
|
const peerId = await PeerId.create({ keyType: 'secp256k1' });
|
|
const enr = ENR.createFromPeerId(peerId);
|
|
const keypair = createKeypairFromPeerId(peerId);
|
|
enr.setLocationMultiaddr(new Multiaddr('/ip4/18.223.219.100/udp/9000'));
|
|
enr.multiaddrs = [
|
|
new Multiaddr(
|
|
'/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss'
|
|
),
|
|
new Multiaddr(
|
|
'/dns6/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss'
|
|
),
|
|
new Multiaddr(
|
|
'/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234/wss'
|
|
),
|
|
];
|
|
const txt = enr.encodeTxt(keypair.privateKey);
|
|
expect(txt.slice(0, 4)).to.be.equal('enr:');
|
|
const enr2 = ENR.decodeTxt(txt);
|
|
expect(bufToHex(enr2.signature as Buffer)).to.be.equal(
|
|
bufToHex(enr.signature as Buffer)
|
|
);
|
|
const multiaddr = enr2.getLocationMultiaddr('udp')!;
|
|
expect(multiaddr.toString()).to.be.equal('/ip4/18.223.219.100/udp/9000');
|
|
expect(enr2.multiaddrs).to.not.be.undefined;
|
|
expect(enr2.multiaddrs!.length).to.be.equal(3);
|
|
const multiaddrsAsStr = enr2.multiaddrs!.map((ma) => ma.toString());
|
|
expect(multiaddrsAsStr).to.include(
|
|
'/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss'
|
|
);
|
|
expect(multiaddrsAsStr).to.include(
|
|
'/dns6/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss'
|
|
);
|
|
expect(multiaddrsAsStr).to.include(
|
|
'/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234/wss'
|
|
);
|
|
});
|
|
|
|
it('should decode valid enr successfully', () => {
|
|
const txt =
|
|
'enr:-Ku4QMh15cIjmnq-co5S3tYaNXxDzKTgj0ufusA-QfZ66EWHNsULt2kb0eTHoo1Dkjvvf6CAHDS1Di-htjiPFZzaIPcLh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD2d10HAAABE________x8AgmlkgnY0gmlwhHZFkMSJc2VjcDI1NmsxoQIWSDEWdHwdEA3Lw2B_byeFQOINTZ0GdtF9DBjes6JqtIN1ZHCCIyg';
|
|
const enr = ENR.decodeTxt(txt);
|
|
const eth2 = enr.get('eth2') as Buffer;
|
|
expect(eth2).to.not.be.undefined;
|
|
expect(bufToHex(eth2)).to.be.equal('f6775d0700000113ffffffffffff1f00');
|
|
});
|
|
|
|
it('should decode valid ENR with multiaddrs successfully [shared test vector]', () => {
|
|
const txt =
|
|
'enr:-QEnuEBEAyErHEfhiQxAVQoWowGTCuEF9fKZtXSd7H_PymHFhGJA3rGAYDVSHKCyJDGRLBGsloNbS8AZF33IVuefjOO6BIJpZIJ2NIJpcIQS39tkim11bHRpYWRkcnO4lgAvNihub2RlLTAxLmRvLWFtczMud2FrdXYyLnRlc3Quc3RhdHVzaW0ubmV0BgG73gMAODcxbm9kZS0wMS5hYy1jbi1ob25na29uZy1jLndha3V2Mi50ZXN0LnN0YXR1c2ltLm5ldAYBu94DACm9A62t7AQL4Ef5ZYZosRpQTzFVAB8jGjf1TER2wH-0zBOe1-MDBNLeA4lzZWNwMjU2azGhAzfsxbxyCkgCqq8WwYsVWH7YkpMLnU2Bw5xJSimxKav-g3VkcIIjKA';
|
|
const enr = ENR.decodeTxt(txt);
|
|
|
|
expect(enr.multiaddrs).to.not.be.undefined;
|
|
expect(enr.multiaddrs!.length).to.be.equal(3);
|
|
const multiaddrsAsStr = enr.multiaddrs!.map((ma) => ma.toString());
|
|
expect(multiaddrsAsStr).to.include(
|
|
'/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss'
|
|
);
|
|
expect(multiaddrsAsStr).to.include(
|
|
'/dns6/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss'
|
|
);
|
|
expect(multiaddrsAsStr).to.include(
|
|
'/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234/wss'
|
|
);
|
|
});
|
|
|
|
it('should decode valid enr with tcp successfully', async () => {
|
|
const txt =
|
|
'enr:-IS4QAmC_o1PMi5DbR4Bh4oHVyQunZblg4bTaottPtBodAhJZvxVlWW-4rXITPNg4mwJ8cW__D9FBDc9N4mdhyMqB-EBgmlkgnY0gmlwhIbRi9KJc2VjcDI1NmsxoQOevTdO6jvv3fRruxguKR-3Ge4bcFsLeAIWEDjrfaigNoN0Y3CCdl8';
|
|
const enr = ENR.decodeTxt(txt);
|
|
expect(enr.tcp).to.not.be.undefined;
|
|
expect(enr.tcp).to.be.equal(30303);
|
|
expect(enr.ip).to.not.be.undefined;
|
|
expect(enr.ip).to.be.equal('134.209.139.210');
|
|
expect(enr.publicKey).to.not.be.undefined;
|
|
const peerId = await enr.peerId();
|
|
expect(peerId.toB58String()).to.be.equal(
|
|
'16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ'
|
|
);
|
|
});
|
|
|
|
it('should throw error - no id', () => {
|
|
try {
|
|
const txt = Buffer.from(
|
|
'656e723a2d435972595a62404b574342526c4179357a7a61445a584a42476b636e68344d486342465a6e75584e467264764a6a5830346a527a6a7a',
|
|
'hex'
|
|
).toString();
|
|
ENR.decodeTxt(txt);
|
|
assert.fail('Expect error here');
|
|
} catch (err) {
|
|
expect(err.message).to.be.equal(ERR_INVALID_ID);
|
|
}
|
|
});
|
|
|
|
it('should throw error - no public key', () => {
|
|
try {
|
|
const txt =
|
|
'enr:-IS4QJ2d11eu6dC7E7LoXeLMgMP3kom1u3SE8esFSWvaHoo0dP1jg8O3-nx9ht-EO3CmG7L6OkHcMmoIh00IYWB92QABgmlkgnY0gmlwhH8AAAGJc2d11eu6dCsxoQIB_c-jQMOXsbjWkbN-kj99H57gfId5pfb4wa1qxwV4CIN1ZHCCIyk';
|
|
ENR.decodeTxt(txt);
|
|
assert.fail('Expect error here');
|
|
} catch (err) {
|
|
expect(err.message).to.be.equal('Failed to verify ENR: No public key');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('verify', () => {
|
|
it('should throw error - no id', () => {
|
|
try {
|
|
const enr = new ENR({}, BigInt(0), Buffer.alloc(0));
|
|
enr.verify(Buffer.alloc(0), Buffer.alloc(0));
|
|
assert.fail('Expect error here');
|
|
} catch (err) {
|
|
expect(err.message).to.be.equal(ERR_INVALID_ID);
|
|
}
|
|
});
|
|
|
|
it('should throw error - invalid id', () => {
|
|
try {
|
|
const enr = new ENR(
|
|
{ id: Buffer.from('v3') },
|
|
BigInt(0),
|
|
Buffer.alloc(0)
|
|
);
|
|
enr.verify(Buffer.alloc(0), Buffer.alloc(0));
|
|
assert.fail('Expect error here');
|
|
} catch (err) {
|
|
expect(err.message).to.be.equal(ERR_INVALID_ID);
|
|
}
|
|
});
|
|
|
|
it('should throw error - no public key', () => {
|
|
try {
|
|
const enr = new ENR(
|
|
{ id: Buffer.from('v4') },
|
|
BigInt(0),
|
|
Buffer.alloc(0)
|
|
);
|
|
enr.verify(Buffer.alloc(0), Buffer.alloc(0));
|
|
assert.fail('Expect error here');
|
|
} catch (err) {
|
|
expect(err.message).to.be.equal('Failed to verify ENR: No public key');
|
|
}
|
|
});
|
|
|
|
it('should return false', () => {
|
|
const txt =
|
|
'enr:-Ku4QMh15cIjmnq-co5S3tYaNXxDzKTgj0ufusA-QfZ66EWHNsULt2kb0eTHoo1Dkjvvf6CAHDS1Di-htjiPFZzaIPcLh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD2d10HAAABE________x8AgmlkgnY0gmlwhHZFkMSJc2VjcDI1NmsxoQIWSDEWdHwdEA3Lw2B_byeFQOINTZ0GdtF9DBjes6JqtIN1ZHCCIyg';
|
|
const enr = ENR.decodeTxt(txt);
|
|
// should have id and public key inside ENR
|
|
expect(enr.verify(Buffer.alloc(32), Buffer.alloc(64))).to.be.false;
|
|
});
|
|
});
|
|
|
|
describe('Fuzzing testcases', () => {
|
|
it('should throw error in invalid signature', () => {
|
|
const buf = Buffer.from(
|
|
'656e723a2d4b7634514147774f54385374716d7749354c486149796d494f346f6f464b664e6b456a576130663150384f73456c67426832496a622d4772445f2d623957346b6350466377796e354845516d526371584e716470566f3168656f42683246306447356c64484f494141414141414141414143455a58526f4d704141414141414141414141505f5f5f5f5f5f5f5f5f5f676d6c6b676e5930676d6c7768424c663232534a6332566a634449314e6d73786f514a78436e4536765f7832656b67595f756f45317274777a76477934306d7139654436365866485042576749494e315a48437f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f434436410d0a',
|
|
'hex'
|
|
).toString();
|
|
try {
|
|
ENR.decodeTxt(buf);
|
|
} catch (e) {
|
|
expect(e.message).to.equal(
|
|
'Decoded ENR invalid signature: must be a byte array'
|
|
);
|
|
}
|
|
});
|
|
it('should throw error in invalid sequence number', () => {
|
|
const buf = Buffer.from(
|
|
'656e723a2d495334514b6b33ff583945717841337838334162436979416e537550444d764b353264433530486d31584744643574457951684d3356634a4c2d5062446b44673541507a5f706f76763022d48dcf992d5379716b306e616e636f4e572d656e7263713042676d6c6b676e5930676d6c77684838414141474a6332566a634449314e6d73786f514d31453579557370397638516a397476335a575843766146427672504e647a384b5049314e68576651577a494e315a4843434239410a',
|
|
'hex'
|
|
).toString();
|
|
try {
|
|
ENR.decodeTxt(buf);
|
|
} catch (e) {
|
|
expect(e.message).to.equal(
|
|
'Decoded ENR invalid sequence number: must be a byte array'
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Static tests', () => {
|
|
let privateKey: Buffer;
|
|
let record: ENR;
|
|
|
|
beforeEach(() => {
|
|
const seq = 1n;
|
|
privateKey = Buffer.from(
|
|
'b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291',
|
|
'hex'
|
|
);
|
|
record = ENR.createV4(v4.publicKey(privateKey));
|
|
record.set('ip', Buffer.from('7f000001', 'hex'));
|
|
record.set('udp', Buffer.from((30303).toString(16), 'hex'));
|
|
record.seq = seq;
|
|
});
|
|
|
|
it('should properly compute the node id', () => {
|
|
expect(record.nodeId).to.equal(
|
|
'a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7'
|
|
);
|
|
});
|
|
|
|
it('should encode/decode to RLP encoding', () => {
|
|
const decoded = ENR.decode(record.encode(privateKey));
|
|
expect(decoded).to.deep.equal(record);
|
|
});
|
|
|
|
it('should encode/decode to text encoding', () => {
|
|
// spec enr https://eips.ethereum.org/EIPS/eip-778
|
|
const testTxt =
|
|
'enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8';
|
|
const decoded = ENR.decodeTxt(testTxt);
|
|
expect(decoded.udp).to.be.equal(30303);
|
|
expect(decoded.ip).to.be.equal('127.0.0.1');
|
|
expect(decoded).to.deep.equal(record);
|
|
expect(record.encodeTxt(privateKey)).to.equal(testTxt);
|
|
});
|
|
});
|
|
|
|
describe('Multiformats support', () => {
|
|
let privateKey: Buffer;
|
|
let record: ENR;
|
|
|
|
beforeEach(() => {
|
|
privateKey = Buffer.from(
|
|
'b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291',
|
|
'hex'
|
|
);
|
|
record = ENR.createV4(v4.publicKey(privateKey));
|
|
});
|
|
|
|
it('should get / set UDP multiaddr', () => {
|
|
const multi0 = new Multiaddr('/ip4/127.0.0.1/udp/30303');
|
|
const tuples0 = multi0.tuples();
|
|
|
|
if (!tuples0[0][1] || !tuples0[1][1]) {
|
|
throw new Error('invalid multiaddr');
|
|
}
|
|
// set underlying records
|
|
record.set('ip', tuples0[0][1]);
|
|
record.set('udp', tuples0[1][1]);
|
|
// and get the multiaddr
|
|
expect(record.getLocationMultiaddr('udp')!.toString()).to.equal(
|
|
multi0.toString()
|
|
);
|
|
// set the multiaddr
|
|
const multi1 = new Multiaddr('/ip4/0.0.0.0/udp/30300');
|
|
record.setLocationMultiaddr(multi1);
|
|
// and get the multiaddr
|
|
expect(record.getLocationMultiaddr('udp')!.toString()).to.equal(
|
|
multi1.toString()
|
|
);
|
|
// and get the underlying records
|
|
const tuples1 = multi1.tuples();
|
|
expect(record.get('ip')).to.deep.equal(tuples1[0][1]);
|
|
expect(record.get('udp')).to.deep.equal(tuples1[1][1]);
|
|
});
|
|
|
|
it('should get / set TCP multiaddr', () => {
|
|
const multi0 = new Multiaddr('/ip4/127.0.0.1/tcp/30303');
|
|
const tuples0 = multi0.tuples();
|
|
|
|
if (!tuples0[0][1] || !tuples0[1][1]) {
|
|
throw new Error('invalid multiaddr');
|
|
}
|
|
|
|
// set underlying records
|
|
record.set('ip', tuples0[0][1]);
|
|
record.set('tcp', tuples0[1][1]);
|
|
// and get the multiaddr
|
|
expect(record.getLocationMultiaddr('tcp')!.toString()).to.equal(
|
|
multi0.toString()
|
|
);
|
|
// set the multiaddr
|
|
const multi1 = new Multiaddr('/ip4/0.0.0.0/tcp/30300');
|
|
record.setLocationMultiaddr(multi1);
|
|
// and get the multiaddr
|
|
expect(record.getLocationMultiaddr('tcp')!.toString()).to.equal(
|
|
multi1.toString()
|
|
);
|
|
// and get the underlying records
|
|
const tuples1 = multi1.tuples();
|
|
expect(record.get('ip')).to.deep.equal(tuples1[0][1]);
|
|
expect(record.get('tcp')).to.deep.equal(tuples1[1][1]);
|
|
});
|
|
|
|
describe('location multiaddr', async () => {
|
|
const ip4 = '127.0.0.1';
|
|
const ip6 = '::1';
|
|
const tcp = 8080;
|
|
const udp = 8080;
|
|
|
|
const peerId = await PeerId.create({ keyType: 'secp256k1' });
|
|
const enr = ENR.createFromPeerId(peerId);
|
|
enr.ip = ip4;
|
|
enr.ip6 = ip6;
|
|
enr.tcp = tcp;
|
|
enr.udp = udp;
|
|
enr.tcp6 = tcp;
|
|
enr.udp6 = udp;
|
|
|
|
it('should properly create location multiaddrs - udp4', () => {
|
|
expect(enr.getLocationMultiaddr('udp4')).to.deep.equal(
|
|
new Multiaddr(`/ip4/${ip4}/udp/${udp}`)
|
|
);
|
|
});
|
|
|
|
it('should properly create location multiaddrs - tcp4', () => {
|
|
expect(enr.getLocationMultiaddr('tcp4')).to.deep.equal(
|
|
new Multiaddr(`/ip4/${ip4}/tcp/${tcp}`)
|
|
);
|
|
});
|
|
|
|
it('should properly create location multiaddrs - udp6', () => {
|
|
expect(enr.getLocationMultiaddr('udp6')).to.deep.equal(
|
|
new Multiaddr(`/ip6/${ip6}/udp/${udp}`)
|
|
);
|
|
});
|
|
|
|
it('should properly create location multiaddrs - tcp6', () => {
|
|
expect(enr.getLocationMultiaddr('tcp6')).to.deep.equal(
|
|
new Multiaddr(`/ip6/${ip6}/tcp/${tcp}`)
|
|
);
|
|
});
|
|
|
|
it('should properly create location multiaddrs - udp', () => {
|
|
// default to ip4
|
|
expect(enr.getLocationMultiaddr('udp')).to.deep.equal(
|
|
new Multiaddr(`/ip4/${ip4}/udp/${udp}`)
|
|
);
|
|
// if ip6 is set, use it
|
|
enr.ip = undefined;
|
|
expect(enr.getLocationMultiaddr('udp')).to.deep.equal(
|
|
new Multiaddr(`/ip6/${ip6}/udp/${udp}`)
|
|
);
|
|
// if ip6 does not exist, use ip4
|
|
enr.ip6 = undefined;
|
|
enr.ip = ip4;
|
|
expect(enr.getLocationMultiaddr('udp')).to.deep.equal(
|
|
new Multiaddr(`/ip4/${ip4}/udp/${udp}`)
|
|
);
|
|
enr.ip6 = ip6;
|
|
});
|
|
|
|
it('should properly create location multiaddrs - tcp', () => {
|
|
// default to ip4
|
|
expect(enr.getLocationMultiaddr('tcp')).to.deep.equal(
|
|
new Multiaddr(`/ip4/${ip4}/tcp/${tcp}`)
|
|
);
|
|
// if ip6 is set, use it
|
|
enr.ip = undefined;
|
|
expect(enr.getLocationMultiaddr('tcp')).to.deep.equal(
|
|
new Multiaddr(`/ip6/${ip6}/tcp/${tcp}`)
|
|
);
|
|
// if ip6 does not exist, use ip4
|
|
enr.ip6 = undefined;
|
|
enr.ip = ip4;
|
|
expect(enr.getLocationMultiaddr('tcp')).to.deep.equal(
|
|
new Multiaddr(`/ip4/${ip4}/tcp/${tcp}`)
|
|
);
|
|
enr.ip6 = ip6;
|
|
});
|
|
});
|
|
});
|
|
});
|