@node-dlc/wire
Version:
Lightning Network Wire Protocol
162 lines (135 loc) • 5.1 kB
text/typescript
/* eslint-disable @typescript-eslint/require-await */
import { OutPoint } from '@node-dlc/bitcoin';
import { ShortChannelId, shortChannelIdFromNumber } from '@node-dlc/common';
import { ChannelAnnouncementMessage } from '../messages/ChannelAnnouncementMessage';
import { ChannelUpdateMessage } from '../messages/ChannelUpdateMessage';
import { ExtendedChannelAnnouncementMessage } from '../messages/ExtendedChannelAnnouncementMessage';
import { NodeAnnouncementMessage } from '../messages/NodeAnnouncementMessage';
import { IGossipStore } from './GossipStore';
/**
* In-memory implementation of the IGossipStore.
*/
export class GossipMemoryStore implements IGossipStore {
private _channelAnn = new Map<bigint, ChannelAnnouncementMessage>();
private _channelByOutPoint = new Map<string, bigint>();
private _channelUpd = new Map<bigint, ChannelUpdateMessage>();
private _nodeAnn = new Map<string, NodeAnnouncementMessage>();
private _nodeChannels = new Map<string, Set<bigint>>();
public get channelAnnouncementCount(): number {
return this._channelAnn.size;
}
public get channelUpdateCount(): number {
return this._channelUpd.size;
}
public get nodeAnnouncementCount(): number {
return this._nodeAnn.size;
}
public async saveChannelAnnouncement(
msg: ChannelAnnouncementMessage,
): Promise<void> {
const chanKey = getChanKey(msg.shortChannelId);
this._channelAnn.set(chanKey, msg);
if (msg instanceof ExtendedChannelAnnouncementMessage) {
this._channelByOutPoint.set(
msg.outpoint.toString(),
msg.shortChannelId.toNumber(),
);
}
await this._saveNodeChannel(msg.nodeId1, chanKey);
await this._saveNodeChannel(msg.nodeId2, chanKey);
}
public async saveChannelUpdate(msg: ChannelUpdateMessage): Promise<void> {
this._channelUpd.set(
getChanUpdKey(getChanKey(msg.shortChannelId), msg.direction),
msg,
);
}
public async saveNodeAnnouncement(
msg: NodeAnnouncementMessage,
): Promise<void> {
this._nodeAnn.set(getNodeKey(msg.nodeId), msg);
}
public async findChannelsForNode(nodeId: Buffer): Promise<ShortChannelId[]> {
const scidInts = this._nodeChannels.get(getNodeKey(nodeId));
const results: ShortChannelId[] = [];
if (!scidInts) return results;
for (const scidInt of scidInts) {
results.push(shortChannelIdFromNumber(scidInt));
}
return results;
}
public async findNodeAnnouncement(
nodeId: Buffer,
): Promise<NodeAnnouncementMessage> {
return this._nodeAnn.get(getNodeKey(nodeId));
}
public async findNodeAnnouncements(): Promise<NodeAnnouncementMessage[]> {
return Array.from(this._nodeAnn.values());
}
public async findChannelAnnouncemnts(): Promise<
ChannelAnnouncementMessage[]
> {
return Array.from(this._channelAnn.values());
}
public async findChannelAnnouncement(
scid: ShortChannelId,
): Promise<ChannelAnnouncementMessage> {
return this._channelAnn.get(getChanKey(scid));
}
public async findChannelAnnouncementByOutpoint(
outpoint: OutPoint,
): Promise<ChannelAnnouncementMessage> {
const scidNum = this._channelByOutPoint.get(outpoint.toString());
return this._channelAnn.get(scidNum);
}
public async findChannelUpdate(
scid: ShortChannelId,
dir: number,
): Promise<ChannelUpdateMessage> {
return this._channelUpd.get(getChanUpdKey(getChanKey(scid), dir));
}
public async deleteChannelAnnouncement(scid: ShortChannelId): Promise<void> {
const msg = await this.findChannelAnnouncement(scid);
if (!msg) return;
const chanKey = getChanKey(scid);
// delete channel
this._channelAnn.delete(getChanKey(scid));
// delete outpoint link
if (msg instanceof ExtendedChannelAnnouncementMessage) {
this._channelByOutPoint.delete(msg.outpoint.toString());
}
// delete channel_updates
this._channelUpd.delete(getChanUpdKey(scid.toNumber(), 0));
this._channelUpd.delete(getChanUpdKey(scid.toNumber(), 0));
// delete node links
this._nodeChannels.get(getNodeKey(msg.nodeId1)).delete(chanKey);
this._nodeChannels.get(getNodeKey(msg.nodeId2)).delete(chanKey);
}
public async deleteChannelUpdate(
scid: ShortChannelId,
dir: number,
): Promise<void> {
this._channelUpd.delete(getChanUpdKey(getChanKey(scid), dir));
}
public async deleteNodeAnnouncement(nodeId: Buffer): Promise<void> {
this._nodeAnn.delete(getNodeKey(nodeId));
this._nodeChannels.get(getNodeKey(nodeId));
}
private async _saveNodeChannel(nodeId: Buffer, chanKey: bigint) {
const nodeKey = getNodeKey(nodeId);
this._nodeChannels.set(
nodeKey,
this._nodeChannels.get(nodeKey) || new Set<bigint>(),
);
this._nodeChannels.get(nodeKey).add(chanKey);
}
}
function getNodeKey(nodeId: Buffer): string {
return nodeId.toString('hex');
}
function getChanKey(scid: ShortChannelId): bigint {
return scid.toNumber();
}
function getChanUpdKey(chanKey: bigint, direction: number): bigint {
return (chanKey << BigInt(8)) | BigInt(direction);
}