@node-dlc/wire
Version:
Lightning Network Wire Protocol
406 lines (396 loc) • 10.8 kB
text/typescript
import { BufferReader } from '@node-dlc/bufio';
import { shortChannelIdFromBuffer } from '@node-dlc/common';
import { expect } from 'chai';
import { readTlvs } from '../../lib/serialize/readTlvs';
describe('.readTlvs()', () => {
const n1tests: Array<{ input: string; failure?: string; output?: any }> = [
{
input: 'fd',
failure: 'type truncated',
},
{
input: 'fd01',
failure: 'type truncated',
},
{
input: 'fd000100',
failure: 'not minimally encoded',
},
{
input: 'fd0101',
failure: 'no length',
},
{
input: '0ffd',
failure: 'length truncated',
},
{
input: '0ffd26',
failure: 'length truncated',
},
{
input: '0ffd2602',
failure: 'missing value',
},
{
input: '0ffd000100',
failure: 'not minimally encoded',
},
{
input: "0ffd0201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", // prettier-ignore
failure: 'value truncated',
},
{
input: '1200',
failure: 'unknown even type',
},
{
input: 'fd010200',
failure: 'unknown even type',
},
{
input: 'fe0100000200',
failure: 'unknow even type',
},
{
input: 'ff010000000000000200',
failure: 'unknown even type',
},
{
input: '0109ffffffffffffffffff',
failure: 'greater than encoding length for n1s tlv1',
},
{
input: '010100',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '01020001',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '0103000100',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '010400010000',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '01050001000000',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '0106000100000000',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '010700010000000000',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '01080001000000000000',
failure: 'encoding for n1s tlv1s amount_msat is not minimal',
},
{
input: '020701010101010101',
failure: 'less than encoding length for n1s tlv2',
},
{
input: '0209010101010101010101',
failure: 'greater than encoding length for n1s tlv2',
},
{
input:
'0321023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb',
failure: 'less than encoding length for n1s tlv3',
},
{
input: "0329023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001", // prettier-ignore
failure: 'less than encoding length for n1s tlv3',
},
{
input:
'0330023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb000000000000000100000000000001',
failure: 'less than encoding length for n1s tlv3',
},
// {
// input: "0331043da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002", // prettier-ignore
// failure: "n1s node_id is not a valid point",
// },
{
input: "0332023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001000000000000000001", // prettier-ignore
failure: 'greater than encoding length for n1s tlv3',
},
{
input: 'fd00fe00',
failure: 'less than encoding length for n1s tlv4',
},
{
input: 'fd00fe0101',
failure: 'less than encoding length for n1s tlv4',
},
{
input: 'fd00fe03010101',
failure: 'greater than encoding length for n1s tlv4',
},
{
input: '0000',
failure: 'unknown even field for n1s namespace',
},
{
input: '',
output: {},
},
{
input: '2100',
output: {},
},
{
input: 'fd020100',
output: {},
},
{
input: 'fd00fd00',
output: {},
},
{
input: 'fd00ff00',
output: {},
},
{
input: 'fe0200000100',
output: {},
},
{
input: 'ff020000000000000100',
output: {},
},
{
input: '0100',
output: { amount_msat: '0' },
},
{
input: '010101',
output: { amount_msat: '1' },
},
{
input: '01020100',
output: { amount_msat: '256' },
},
{
input: '0103010000',
output: { amount_msat: '65536' },
},
{
input: '010401000000',
output: { amount_msat: '16777216' },
},
{
input: '01050100000000',
output: { amount_msat: '4294967296' },
},
{
input: '0106010000000000',
output: { amount_msat: '1099511627776' },
},
{
input: '010701000000000000',
output: { amount_msat: '281474976710656' },
},
{
input: '01080100000000000000',
output: { amount_msat: '72057594037927936' },
},
{
input: '02080000000000000226',
output: { scid: '0x0x550' },
},
{
input: "0331023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002", // prettier-ignore
output: {
node_id:
'023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb',
amount_msat_1: '1',
amount_msat_2: '2',
},
},
{
input: 'fd00fe020226',
output: { cltv_delta: 550 },
},
{
input: '01030100000 2080000000000000226',
output: {
amount_msat: '65536',
scid: '0x0x550',
},
},
{
input: '02 08 0000000000000226 01 01 2a',
failure: 'valid TLV records but invalid ordering',
},
{
input: '02 08 0000000000000231 02 08 0000000000000451',
failure: 'duplicate TLV type',
},
{
input: '1f 00 0f 01 2a',
failure: 'valid (ignored) TLV records but invalid ordering',
},
{
input: '1f 00 1f 01 2a',
failure: 'duplicate TLV type (ignored)',
},
];
for (const test of n1tests) {
it(`n1 ${test.input}`, () => {
const instance: any = {};
function handler(type: bigint, value: BufferReader): boolean {
switch (type) {
case BigInt(1): {
instance.amount_msat = value.readTUInt64().toString();
return true;
}
case BigInt(2): {
const scid = shortChannelIdFromBuffer(value.readBytes(8));
instance.scid = scid.toString();
return true;
}
case BigInt(3): {
const nodeId = value.readBytes(33);
const amountMsat1 = value.readUInt64BE();
const amountMsat2 = value.readUInt64BE();
instance.node_id = nodeId.toString('hex');
instance.amount_msat_1 = amountMsat1.toString();
instance.amount_msat_2 = amountMsat2.toString();
return true;
}
case BigInt(254): {
instance.cltv_delta = value.readUInt16BE();
return true;
}
}
}
const input = Buffer.from(test.input.replace(/ /g, ''), 'hex');
const reader = new BufferReader(input);
if (test.failure) {
expect(() => readTlvs(reader, handler)).to.throw();
} else {
readTlvs(reader, handler);
expect(instance).to.deep.equal(test.output);
}
});
}
const n2tests: Array<{ input: string; failure?: string; output?: any }> = [
{
input: 'fd',
failure: 'type truncated',
},
{
input: 'fd01',
failure: 'type truncated',
},
{
input: 'fd000100',
failure: 'not minimally encoded',
},
{
input: 'fd0101',
failure: 'no length',
},
{
input: '0ffd',
failure: 'length truncated',
},
{
input: '0ffd26',
failure: 'length truncated',
},
{
input: '0ffd2602',
failure: 'missing value',
},
{
input: '0ffd000100',
failure: 'not minimally encoded',
},
{
input: "0ffd0201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", // prettier-ignore
failure: 'value truncated',
},
{
input: '1200',
failure: 'unknown even type',
},
{
input: 'fd010200',
failure: 'unknown even type',
},
{
input: 'fe0100000200',
failure: 'unknow even type',
},
{
input: 'ff010000000000000200',
failure: 'unknown even type',
},
{
input: '',
output: {},
},
{
input: '2100',
output: {},
},
{
input: 'fd020100',
output: {},
},
{
input: 'fd00fd00',
output: {},
},
{
input: 'fd00ff00',
output: {},
},
{
input: 'fe0200000100',
output: {},
},
{
input: 'ff020000000000000100',
output: {},
},
{
input: 'ffffffffffffffffff 00 00 00',
failure: 'valid TLV records but invalid ordering',
},
];
for (const test of n2tests) {
it(`n2 ${test.input}`, () => {
const instance: any = {};
function handler(type: bigint, value: BufferReader): boolean {
switch (type) {
case BigInt(0): {
instance.amount_msat = value.readTUInt64().toString();
return true;
}
case BigInt(11): {
instance.cltv_delta = value.readTUInt32();
return true;
}
}
}
const input = Buffer.from(test.input.replace(/ /g, ''), 'hex');
const reader = new BufferReader(input);
if (test.failure) {
expect(() => readTlvs(reader, handler)).to.throw();
} else {
readTlvs(reader, handler);
expect(instance).to.deep.equal(test.output);
}
});
}
});