@node-lightning/wire
Version:
Lightning Network Wire Protocol
403 lines (394 loc) • 13 kB
text/typescript
import { BufferReader } from "@node-lightning/bufio";
import { shortChannelIdFromBuffer } from "@node-lightning/core";
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);
}
});
}
});