Fetch funding tx for clightning channels

This commit is contained in:
nymkappa 2022-08-02 16:39:34 +02:00
parent 00cd3ee9bf
commit a25af16f7c
No known key found for this signature in database
GPG Key ID: E155910B16E8BD04
4 changed files with 29 additions and 18 deletions

View File

@ -245,7 +245,7 @@ export default class CLightningClient extends EventEmitter implements AbstractLi
async $getNetworkGraph(): Promise<ILightningApi.NetworkGraph> { async $getNetworkGraph(): Promise<ILightningApi.NetworkGraph> {
const listnodes: any[] = await this.call('listnodes'); const listnodes: any[] = await this.call('listnodes');
const listchannels: any[] = await this.call('listchannels'); const listchannels: any[] = await this.call('listchannels');
const channelsList = convertAndmergeBidirectionalChannels(listchannels['channels']); const channelsList = await convertAndmergeBidirectionalChannels(listchannels['channels']);
return { return {
nodes: listnodes['nodes'].map(node => convertNode(node)), nodes: listnodes['nodes'].map(node => convertNode(node)),

View File

@ -1,4 +1,5 @@
import { ILightningApi } from '../lightning-api.interface'; import { ILightningApi } from '../lightning-api.interface';
import FundingTxFetcher from '../../../tasks/lightning/sync-tasks/funding-tx-fetcher';
/** /**
* Convert a clightning "listnode" entry to a lnd node entry * Convert a clightning "listnode" entry to a lnd node entry
@ -22,7 +23,7 @@ export function convertNode(clNode: any): ILightningApi.Node {
/** /**
* Convert clightning "listchannels" response to lnd "describegraph.edges" format * Convert clightning "listchannels" response to lnd "describegraph.edges" format
*/ */
export function convertAndmergeBidirectionalChannels(clChannels: any[]): ILightningApi.Channel[] { export async function convertAndmergeBidirectionalChannels(clChannels: any[]): Promise<ILightningApi.Channel[]> {
const consolidatedChannelList: ILightningApi.Channel[] = []; const consolidatedChannelList: ILightningApi.Channel[] = [];
const clChannelsDict = {}; const clChannelsDict = {};
const clChannelsDictCount = {}; const clChannelsDictCount = {};
@ -33,14 +34,14 @@ export function convertNode(clNode: any): ILightningApi.Node {
clChannelsDictCount[clChannel.short_channel_id] = 1; clChannelsDictCount[clChannel.short_channel_id] = 1;
} else { } else {
consolidatedChannelList.push( consolidatedChannelList.push(
buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id]) await buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id])
); );
delete clChannelsDict[clChannel.short_channel_id]; delete clChannelsDict[clChannel.short_channel_id];
clChannelsDictCount[clChannel.short_channel_id]++; clChannelsDictCount[clChannel.short_channel_id]++;
} }
} }
for (const short_channel_id of Object.keys(clChannelsDict)) { for (const short_channel_id of Object.keys(clChannelsDict)) {
consolidatedChannelList.push(buildIncompleteChannel(clChannelsDict[short_channel_id])); consolidatedChannelList.push(await buildIncompleteChannel(clChannelsDict[short_channel_id]));
} }
return consolidatedChannelList; return consolidatedChannelList;
@ -55,16 +56,20 @@ export function convertChannelId(channelId): string {
* Convert two clightning "getchannels" entries into a full a lnd "describegraph.edges" format * Convert two clightning "getchannels" entries into a full a lnd "describegraph.edges" format
* In this case, clightning knows the channel policy for both nodes * In this case, clightning knows the channel policy for both nodes
*/ */
function buildFullChannel(clChannelA: any, clChannelB: any): ILightningApi.Channel { async function buildFullChannel(clChannelA: any, clChannelB: any): Promise<ILightningApi.Channel> {
const lastUpdate = Math.max(clChannelA.last_update ?? 0, clChannelB.last_update ?? 0); const lastUpdate = Math.max(clChannelA.last_update ?? 0, clChannelB.last_update ?? 0);
const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannelA.short_channel_id);
const parts = clChannelA.short_channel_id.split('x');
const outputIdx = parts[2];
return { return {
channel_id: clChannelA.short_channel_id, channel_id: clChannelA.short_channel_id,
capacity: clChannelA.satoshis, capacity: clChannelA.satoshis,
last_update: lastUpdate, last_update: lastUpdate,
node1_policy: convertPolicy(clChannelA), node1_policy: convertPolicy(clChannelA),
node2_policy: convertPolicy(clChannelB), node2_policy: convertPolicy(clChannelB),
chan_point: ':0', // TODO chan_point: `${tx.txid}:${outputIdx}`,
node1_pub: clChannelA.source, node1_pub: clChannelA.source,
node2_pub: clChannelB.source, node2_pub: clChannelB.source,
}; };
@ -74,14 +79,18 @@ function buildFullChannel(clChannelA: any, clChannelB: any): ILightningApi.Chann
* Convert one clightning "getchannels" entry into a full a lnd "describegraph.edges" format * Convert one clightning "getchannels" entry into a full a lnd "describegraph.edges" format
* In this case, clightning knows the channel policy of only one node * In this case, clightning knows the channel policy of only one node
*/ */
function buildIncompleteChannel(clChannel: any): ILightningApi.Channel { async function buildIncompleteChannel(clChannel: any): Promise<ILightningApi.Channel> {
const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannel.short_channel_id);
const parts = clChannel.short_channel_id.split('x');
const outputIdx = parts[2];
return { return {
channel_id: clChannel.short_channel_id, channel_id: clChannel.short_channel_id,
capacity: clChannel.satoshis, capacity: clChannel.satoshis,
last_update: clChannel.last_update ?? 0, last_update: clChannel.last_update ?? 0,
node1_policy: convertPolicy(clChannel), node1_policy: convertPolicy(clChannel),
node2_policy: null, node2_policy: null,
chan_point: ':0', // TODO chan_point: `${tx.txid}:${outputIdx}`,
node1_pub: clChannel.source, node1_pub: clChannel.source,
node2_pub: clChannel.destination, node2_pub: clChannel.destination,
}; };

View File

@ -34,6 +34,7 @@ import miningRoutes from './api/mining/mining-routes';
import bisqRoutes from './api/bisq/bisq.routes'; import bisqRoutes from './api/bisq/bisq.routes';
import liquidRoutes from './api/liquid/liquid.routes'; import liquidRoutes from './api/liquid/liquid.routes';
import bitcoinRoutes from './api/bitcoin/bitcoin.routes'; import bitcoinRoutes from './api/bitcoin/bitcoin.routes';
import fundingTxFetcher from "./tasks/lightning/sync-tasks/funding-tx-fetcher";
class Server { class Server {
private wss: WebSocket.Server | undefined; private wss: WebSocket.Server | undefined;
@ -136,7 +137,8 @@ class Server {
} }
if (config.LIGHTNING.ENABLED) { if (config.LIGHTNING.ENABLED) {
networkSyncService.$startService() fundingTxFetcher.$init()
.then(() => networkSyncService.$startService())
.then(() => lightningStatsUpdater.$startService()); .then(() => lightningStatsUpdater.$startService());
} }

View File

@ -1,8 +1,6 @@
import { existsSync, promises } from 'fs'; import { existsSync, promises } from 'fs';
import bitcoinApiFactory from '../../../api/bitcoin/bitcoin-api-factory';
import bitcoinClient from '../../../api/bitcoin/bitcoin-client'; import bitcoinClient from '../../../api/bitcoin/bitcoin-client';
import config from '../../../config'; import config from '../../../config';
import DB from '../../../database';
import logger from '../../../logger'; import logger from '../../../logger';
const fsPromises = promises; const fsPromises = promises;
@ -16,12 +14,7 @@ class FundingTxFetcher {
private channelNewlyProcessed = 0; private channelNewlyProcessed = 0;
public fundingTxCache = {}; public fundingTxCache = {};
async $fetchChannelsFundingTxs(channelIds: string[]): Promise<void> { async $init(): Promise<void> {
if (this.running) {
return;
}
this.running = true;
// Load funding tx disk cache // Load funding tx disk cache
if (Object.keys(this.fundingTxCache).length === 0 && existsSync(CACHE_FILE_NAME)) { if (Object.keys(this.fundingTxCache).length === 0 && existsSync(CACHE_FILE_NAME)) {
try { try {
@ -32,6 +25,13 @@ class FundingTxFetcher {
} }
logger.debug(`Imported ${Object.keys(this.fundingTxCache).length} funding tx amount from the disk cache`); logger.debug(`Imported ${Object.keys(this.fundingTxCache).length} funding tx amount from the disk cache`);
} }
}
async $fetchChannelsFundingTxs(channelIds: string[]): Promise<void> {
if (this.running) {
return;
}
this.running = true;
const globalTimer = new Date().getTime() / 1000; const globalTimer = new Date().getTime() / 1000;
let cacheTimer = new Date().getTime() / 1000; let cacheTimer = new Date().getTime() / 1000;