@node-lightning/wire
Version:
Lightning Network Wire Protocol
149 lines (130 loc) • 8.67 kB
text/typescript
/* eslint-disable no-constant-condition */
// tslint:disable: max-classes-per-file
// tslint:disable: no-unused-expression
import { BitField } from "@node-lightning/core";
import { ILogger } from "@node-lightning/logger";
import { expect } from "chai";
import sinon from "sinon";
import { Duplex } from "stream";
import { GossipFilter, GossipMemoryStore, GossipPeer, WireError, WireErrorCode } from "../../lib";
import { IWireMessage } from "../../lib";
import { InitFeatureFlags } from "../../lib/flags/InitFeatureFlags";
import { Peer } from "../../lib/Peer";
import { PeerState } from "../../lib/PeerState";
import { PingPongState } from "../../lib/PingPongState";
import { createFakeLogger } from "../_test-utils";
class FakeSocket extends Duplex {
[x: string]: any;
public outgoing: Buffer[] = [];
constructor() {
super({ objectMode: true });
this.pipe = sinon.spy(this.pipe.bind(this));
this.end = sinon.spy(this.end.bind(this));
this.rpk = Buffer.alloc(33);
}
public _write(data: any, encoding: BufferEncoding, cb: (err?: Error) => void) {
this.outgoing.push(data);
cb();
}
public _read() {
// nada
}
public simReceive(data: Buffer) {
this.push(data);
}
}
describe("GossipPeer", () => {
let sut: GossipPeer;
let chainHashes: Buffer[];
let peer: Peer;
let ls: Buffer;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const rpk: Buffer = Buffer.alloc(32, 1);
let logger: ILogger;
let sandbox: sinon.SinonSandbox;
let socket: FakeSocket;
let localFeatures: BitField<InitFeatureFlags>;
let remoteFeatures: BitField<InitFeatureFlags>;
let filter: GossipFilter;
beforeEach(() => {
chainHashes = [Buffer.alloc(32, 0xff)];
localFeatures = new BitField<InitFeatureFlags>();
localFeatures.set(InitFeatureFlags.optionDataLossProtectOptional);
remoteFeatures = new BitField<InitFeatureFlags>();
remoteFeatures.set(InitFeatureFlags.optionDataLossProtectOptional);
remoteFeatures.set(InitFeatureFlags.gossipQueriesOptional);
ls = Buffer.alloc(32, 0);
logger = createFakeLogger();
peer = new Peer(ls, localFeatures, chainHashes, logger, 1);
socket = new FakeSocket();
peer.attach(socket as any);
peer.pingPongState = sinon.createStubInstance(PingPongState) as any;
peer.state = PeerState.Ready;
peer.remoteFeatures = remoteFeatures;
sandbox = sinon.createSandbox();
const gossipStore = new GossipMemoryStore();
const pendingStore = new GossipMemoryStore();
filter = new GossipFilter(gossipStore, pendingStore);
sut = new GossipPeer(peer, filter, logger);
});
afterEach(() => {
sandbox.restore();
});
describe("integation - wire messages", () => {
it("it should process all valid messages", done => {
const hexMsgs = [
"0100ce1d69dbb62e86ad28157f4c24705e325f069d5158b91b28bdf55e508afcc1b554a498f4bda8a3d34a206ddb617ad0e945ecadc9a61086bac5afae3e19976242d464e8d305772f29021a4d07617c4159e7e0634bd53991c0e0577c0e9c3d3ee61d7311e6773275335c12f17e573e2813391a71050ab58c03c17d06c0d841db2ec6c6514c2156713651dfbee13d491559764c95343386218ab904173742dde6ca3118d303967e073a44e94f16eef4d878d4d74f1ff1f6924109421cf9c41e8e5c961cf1c7e2316e61a952c7caad056fea1d13d2f4bf855bd3f06d019a33814bc70ea99fa79f026c791b87040e781e8493f5165dafbfc23fabe2912c3ed0ab7e0f000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000013a9090000030000036b96e4713c5f84dcb8030592e1bd42a2d9a43d91fa2e535b9bfd05f2c5def9b9039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad303ca63b9acbadf5b644c11d0a9dd65b82b14e0d26fc5e0bcf071a90879f603d46203a0ee0a716f4a436864fe53bb788a003321aee63150bf63fd5529e4e1da93481d",
"01024e6eac97124742ba6a033612c8009945c0d52568756a885692b4adbf202666503b56ecb6f5758ea450dda940b2a6853b8e1706c3bd4f38a347be91b08c5e5c4743497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000013a90900000300005cdd9d780002009000000000000003e8000003e800000001",
"01015254ffbc21374af9d998355151515933de1d998e9cb124aa4d65a7aa6b473e75201420c58f2414f4fb7461f3f133ab529cbbf9a57365ed6bcf775172826fdc7500005ae86dba039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3f8e71c79616c6c732e6f7267000000000000000000000000000000000000000000000000070122c8fc922607",
"0102fcd0d7af22e815879e2ba0c2422bc812d04f8b286fd53e631fe18bb6ed5aecc06a0b96fceb352509656f2b121b76cc808fe02e62ff42edc600bd6e196fe2af9b43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000013a90900000300005ae7cc490001009000000000000003e8000003e800000001",
"010105d3b12aacb824409ce8724609fe453fdcd33a498ecca170784985c4a6a2765657c4ef9e1170d3a5795ec86021c3a081c84a9f3a02e2ca66d17b683baacae08000005cddd5e5036b96e4713c5f84dcb8030592e1bd42a2d9a43d91fa2e535b9bfd05f2c5def9b9b6d43364656d6f312e6c6e646578706c6f7265722e636f6d0000000000000000000000000701265736a32611",
];
const msgs = [];
sut.on("readable", () => {
while (true) {
const msg = sut.read() as IWireMessage;
if (!msg) break;
msgs.push(msg);
}
if (msgs.length === hexMsgs.length) done();
});
for (const hexMsg of hexMsgs) {
const buffer = Buffer.from(hexMsg, "hex");
socket.simReceive(buffer);
}
});
it("it should continue processing after errors", done => {
const hexMsgs = [
"0100ce1d69dbb62e86ad28157f4c24705e325f069d5158b91b28bdf55e508afcc1b554a498f4bda8a3d34a206ddb617ad0e945ecadc9a61086bac5afae3e19976242d464e8d305772f29021a4d07617c4159e7e0634bd53991c0e0577c0e9c3d3ee61d7311e6773275335c12f17e573e2813391a71050ab58c03c17d06c0d841db2ec6c6514c2156713651dfbee13d491559764c95343386218ab904173742dde6ca3118d303967e073a44e94f16eef4d878d4d74f1ff1f6924109421cf9c41e8e5c961cf1c7e2316e61a952c7caad056fea1d13d2f4bf855bd3f06d019a33814bc70ea99fa79f026c791b87040e781e8493f5165dafbfc23fabe2912c3ed0ab7e0f000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000013a9090000030000036b96e4713c5f84dcb8030592e1bd42a2d9a43d91fa2e535b9bfd05f2c5def9b9039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad303ca63b9acbadf5b644c11d0a9dd65b82b14e0d26fc5e0bcf071a90879f603d46203a0ee0a716f4a436864fe53bb788a003321aee63150bf63fd5529e4e1da93481d",
"01024e6eac97124742ba6a033612c8009945c0d52568756a885692b4adbf202666503b56ecb6f5758ea450dda940b2a6853b8e1706c3bd4f38a347be91b08c5e5c4743497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000013a90900000300005cdd9d780002009000000000000003e8000003e800000001",
"01010254ffbc21374af9d998355151515933de1d998e9cb124aa4d65a7aa6b473e75201420c58f2414f4fb7461f3f133ab529cbbf9a57365ed6bcf775172826fdc7500005ae86dba039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3f8e71c79616c6c732e6f7267000000000000000000000000000000000000000000000000070122c8fc922607",
"0102fcd0d7af22e815879e2ba0c2422bc812d04f8b286fd53e631fe18bb6ed5aecc06a0b96fceb352509656f2b121b76cc808fe02e62ff42edc600bd6e196fe2af9b43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000013a90900000300005ae7cc490001009000000000000003e8000003e800000001",
"010105d3b12aacb824409ce8724609fe453fdcd33a498ecca170784985c4a6a2765657c4ef9e1170d3a5795ec86021c3a081c84a9f3a02e2ca66d17b683baacae08000005cddd5e5036b96e4713c5f84dcb8030592e1bd42a2d9a43d91fa2e535b9bfd05f2c5def9b9b6d43364656d6f312e6c6e646578706c6f7265722e636f6d0000000000000000000000000701265736a32611",
];
const msgs = [];
const errors: WireError[] = [];
function validate() {
if (msgs.length + errors.length === hexMsgs.length) {
expect(errors[0].code == WireErrorCode.nodeAnnSigFailed);
done();
}
}
sut.on("readable", () => {
while (true) {
const msg = sut.read() as IWireMessage;
if (!msg) break;
msgs.push(msg);
}
validate();
});
sut.on("gossip_error", error => {
errors.push(error);
validate();
});
for (const hexMsg of hexMsgs) {
const buffer = Buffer.from(hexMsg, "hex");
socket.simReceive(buffer);
}
});
});
});