Replacing ln-service library and wait for graph sync.

This commit is contained in:
softsimon 2022-07-06 21:43:47 +02:00
parent 1f2254681a
commit 73c4a934ce
No known key found for this signature in database
GPG Key ID: 488D7DCFB5A430D7
7 changed files with 73 additions and 35 deletions

View File

@ -37,7 +37,7 @@
"bolt07": "^1.8.1",
"crypto-js": "^4.0.0",
"express": "^4.18.0",
"ln-service": "^53.17.4",
"lightning": "^5.16.3",
"mysql2": "2.3.3",
"node-worker-threads-pool": "^1.5.1",
"socks-proxy-agent": "~7.0.0",

View File

@ -3,5 +3,5 @@ import { ILightningApi } from './lightning-api.interface';
export interface AbstractLightningApi {
$getNetworkInfo(): Promise<ILightningApi.NetworkInfo>;
$getNetworkGraph(): Promise<ILightningApi.NetworkGraph>;
$getChanInfo(id: string): Promise<ILightningApi.Channel>;
$getInfo(): Promise<ILightningApi.Info>;
}

View File

@ -21,17 +21,17 @@ export namespace ILightningApi {
policies: Policy[];
transaction_id: string;
transaction_vout: number;
updated_at: string;
updated_at?: string;
}
interface Policy {
public_key: string;
base_fee_mtokens?: number;
base_fee_mtokens?: string;
cltv_delta?: number;
fee_rate?: number;
is_disabled?: boolean;
max_htlc_mtokens?: number;
min_htlc_mtokens?: number;
max_htlc_mtokens?: string;
min_htlc_mtokens?: string;
updated_at?: string;
}
@ -41,13 +41,31 @@ export namespace ILightningApi {
features: Feature[];
public_key: string;
sockets: string[];
updated_at: string;
updated_at?: string;
}
interface Feature {
export interface Info {
chains: string[];
color: string;
active_channels_count: number;
alias: string;
current_block_hash: string;
current_block_height: number;
features: Feature[];
is_synced_to_chain: boolean;
is_synced_to_graph: boolean;
latest_block_at: string;
peers_count: number;
pending_channels_count: number;
public_key: string;
uris: any[];
version: string;
}
export interface Feature {
bit: number;
is_known: boolean;
is_required: boolean;
type: string;
type?: string;
}
}

View File

@ -1,7 +1,7 @@
import { AbstractLightningApi } from '../lightning-api-abstract-factory';
import { ILightningApi } from '../lightning-api.interface';
import * as fs from 'fs';
import * as lnService from 'ln-service';
import { authenticatedLndGrpc, getWalletInfo, getNetworkGraph, getNetworkInfo } from 'lightning';
import config from '../../../config';
import logger from '../../../logger';
@ -15,7 +15,7 @@ class LndApi implements AbstractLightningApi {
const tls = fs.readFileSync(config.LND.TLS_CERT_PATH).toString('base64');
const macaroon = fs.readFileSync(config.LND.MACAROON_PATH).toString('base64');
const { lnd } = lnService.authenticatedLndGrpc({
const { lnd } = authenticatedLndGrpc({
cert: tls,
macaroon: macaroon,
socket: config.LND.SOCKET,
@ -29,15 +29,16 @@ class LndApi implements AbstractLightningApi {
}
async $getNetworkInfo(): Promise<ILightningApi.NetworkInfo> {
return await lnService.getNetworkInfo({ lnd: this.lnd });
return await getNetworkInfo({ lnd: this.lnd });
}
async $getInfo(): Promise<ILightningApi.Info> {
// @ts-ignore
return await getWalletInfo({ lnd: this.lnd });
}
async $getNetworkGraph(): Promise<ILightningApi.NetworkGraph> {
return await lnService.getNetworkGraph({ lnd: this.lnd });
}
async $getChanInfo(id: string): Promise<ILightningApi.Channel> {
return await lnService.getChannel({ lnd: this.lnd, id });
return await getNetworkGraph({ lnd: this.lnd });
}
}

View File

@ -1,5 +1,5 @@
import express from "express";
import { Application, Request, Response, NextFunction, Express } from 'express';
import { Application, Request, Response, NextFunction } from 'express';
import * as http from 'http';
import * as WebSocket from 'ws';
import cluster from 'cluster';
@ -28,12 +28,12 @@ import { Common } from './api/common';
import poolsUpdater from './tasks/pools-updater';
import indexer from './indexer';
import priceUpdater from './tasks/price-updater';
import BlocksAuditsRepository from './repositories/BlocksAuditsRepository';
import nodeSyncService from './tasks/lightning/node-sync.service';
import lightningStatsUpdater from './tasks/lightning/stats-updater.service';
import nodesRoutes from './api/explorer/nodes.routes';
import channelsRoutes from './api/explorer/channels.routes';
import generalLightningRoutes from './api/explorer/general.routes';
import lightningStatsUpdater from './tasks/lightning/stats-updater.service';
import nodeSyncService from './tasks/lightning/node-sync.service';
import BlocksAuditsRepository from './repositories/BlocksAuditsRepository';
class Server {
private wss: WebSocket.Server | undefined;
@ -137,9 +137,7 @@ class Server {
if (config.LIGHTNING.ENABLED) {
nodeSyncService.$startService()
.then(() => {
lightningStatsUpdater.$startService();
});
.then(() => lightningStatsUpdater.$startService());
}
this.server.listen(config.MEMPOOL.HTTP_PORT, () => {

View File

@ -245,7 +245,6 @@ class NodeSyncService {
const fromChannel = chanNumber({ channel: channel.id }).number;
try {
const d = new Date(Date.parse(channel.updated_at));
const query = `INSERT INTO channels
(
id,
@ -360,7 +359,7 @@ class NodeSyncService {
private async $saveNode(node: ILightningApi.Node): Promise<void> {
try {
const updatedAt = this.utcDateToMysql(node.updated_at);
const updatedAt = node.updated_at ? this.utcDateToMysql(node.updated_at) : '0000-00-00 00:00:00';
const sockets = node.sockets.join(',');
const query = `INSERT INTO nodes(
public_key,

View File

@ -6,21 +6,43 @@ class LightningStatsUpdater {
constructor() {}
public async $startService() {
logger.info('Starting Stats service');
logger.info('Starting Lightning Stats service');
let isInSync = false;
let error: any;
try {
error = null;
isInSync = await this.$lightningIsSynced();
} catch (e) {
error = e;
}
if (!isInSync) {
if (error) {
logger.warn('Was not able to fetch Lightning Node status: ' + (error instanceof Error ? error.message : error) + '. Retrying in 1 minute...');
} else {
logger.notice('The Lightning graph is not yet in sync. Retrying in 1 minute...');
}
setTimeout(() => this.$startService(), 60 * 1000);
return;
}
const now = new Date();
const nextHourInterval = new Date(now.getFullYear(), now.getMonth(), now.getDate(), Math.floor(now.getHours() / 1) + 1, 0, 0, 0);
const difference = nextHourInterval.getTime() - now.getTime();
// setTimeout(() => {
setTimeout(() => {
setInterval(async () => {
await this.$runTasks();
}, 1000 * 60 * 60);
//}, difference);
}, difference);
await this.$runTasks();
}
private async $lightningIsSynced(): Promise<boolean> {
const nodeInfo = await lightningApi.$getInfo();
return nodeInfo.is_synced_to_chain && nodeInfo.is_synced_to_graph;
}
private async $runTasks() {
await this.$populateHistoricalData();
await this.$logLightningStatsDaily();
@ -28,8 +50,6 @@ class LightningStatsUpdater {
}
private async $logNodeStatsDaily() {
logger.info(`Running daily node stats update...`);
const currentDate = new Date().toISOString().split('T')[0];
try {
const [state]: any = await DB.query(`SELECT string FROM state WHERE name = 'last_node_stats'`);
@ -38,6 +58,8 @@ class LightningStatsUpdater {
return;
}
logger.info(`Running daily node stats update...`);
const query = `SELECT nodes.public_key, c1.channels_count_left, c2.channels_count_right, c1.channels_capacity_left, c2.channels_capacity_right FROM nodes LEFT JOIN (SELECT node1_public_key, COUNT(id) AS channels_count_left, SUM(capacity) AS channels_capacity_left FROM channels WHERE channels.status < 2 GROUP BY node1_public_key) c1 ON c1.node1_public_key = nodes.public_key LEFT JOIN (SELECT node2_public_key, COUNT(id) AS channels_count_right, SUM(capacity) AS channels_capacity_right FROM channels WHERE channels.status < 2 GROUP BY node2_public_key) c2 ON c2.node2_public_key = nodes.public_key`;
const [nodes]: any = await DB.query(query);
@ -61,8 +83,6 @@ class LightningStatsUpdater {
// We only run this on first launch
private async $populateHistoricalData() {
logger.info(`Running historical stats population...`);
const startTime = '2018-01-13';
try {
const [rows]: any = await DB.query(`SELECT COUNT(*) FROM lightning_stats`);
@ -70,6 +90,8 @@ class LightningStatsUpdater {
if (rows[0]['COUNT(*)'] > 0) {
return;
}
logger.info(`Running historical stats population...`);
const [channels]: any = await DB.query(`SELECT capacity, created, closing_date FROM channels ORDER BY created ASC`);
let date: Date = new Date(startTime);
@ -138,8 +160,6 @@ class LightningStatsUpdater {
}
private async $logLightningStatsDaily() {
logger.info(`Running lightning daily stats log...`);
const currentDate = new Date().toISOString().split('T')[0];
try {
const [state]: any = await DB.query(`SELECT string FROM state WHERE name = 'last_node_stats'`);
@ -148,6 +168,8 @@ class LightningStatsUpdater {
return;
}
logger.info(`Running lightning daily stats log...`);
const networkGraph = await lightningApi.$getNetworkGraph();
let total_capacity = 0;
for (const channel of networkGraph.channels) {