Find inactive channels with dead nodes.
This commit is contained in:
parent
65c731e1ad
commit
7e1c2f4f40
@ -52,7 +52,7 @@
|
|||||||
<div class="row row-cols-1 row-cols-md-2">
|
<div class="row row-cols-1 row-cols-md-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<h2 class="mb-0">{{ channel.alias_left }}</h2>
|
<h2 class="mb-0">{{ channel.alias_left || '?' }}</h2>
|
||||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]" >
|
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]" >
|
||||||
{{ channel.node1_public_key | shortenString : 18 }}
|
{{ channel.node1_public_key | shortenString : 18 }}
|
||||||
</a>
|
</a>
|
||||||
@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<h2 class="mb-0">{{ channel.alias_right }}</h2>
|
<h2 class="mb-0">{{ channel.alias_right || '?' }}</h2>
|
||||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]" >
|
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]" >
|
||||||
{{ channel.node2_public_key | shortenString : 18 }}
|
{{ channel.node2_public_key | shortenString : 18 }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -3,17 +3,23 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<thead>
|
<thead>
|
||||||
<th class="alias text-left" i18n="nodes.alias">Node Alias</th>
|
<th class="alias text-left" i18n="nodes.alias">Node Alias</th>
|
||||||
|
<th class="alias text-left" i18n="channels.transaction">Node ID</th>
|
||||||
<th class="alias text-left" i18n="nodes.alias">Status</th>
|
<th class="alias text-left" i18n="nodes.alias">Status</th>
|
||||||
<th class="channels text-right" i18n="channels.rate">Fee Rate</th>
|
<th class="channels text-right" i18n="channels.rate">Fee Rate</th>
|
||||||
<th class="capacity text-right" i18n="channels.id">Channel ID</th>
|
|
||||||
<th class="capacity text-right" i18n="nodes.capacity">Capacity</th>
|
<th class="capacity text-right" i18n="nodes.capacity">Capacity</th>
|
||||||
<th class="alias text-right" i18n="channels.transaction">Transaction ID</th>
|
<th class="capacity text-right" i18n="channels.id">Channel ID</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody *ngIf="channels$ | async as channels; else skeleton">
|
<tbody *ngIf="channels$ | async as channels; else skeleton">
|
||||||
<tr *ngFor="let channel of channels; let i = index;">
|
<tr *ngFor="let channel of channels; let i = index;">
|
||||||
<ng-template [ngIf]="channel.node2_public_key === publicKey" [ngIfElse]="right">
|
<ng-template [ngIf]="channel.node2_public_key === publicKey" [ngIfElse]="right">
|
||||||
<td class="alias text-left">
|
<td class="alias text-left">
|
||||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]">{{ channel.alias_left }}</a>
|
{{ channel.alias_left || '?' }}
|
||||||
|
</td>
|
||||||
|
<td class="text-left">
|
||||||
|
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]">
|
||||||
|
<span>{{ channel.node1_public_key | shortenString : 10 }}</span>
|
||||||
|
</a>
|
||||||
|
<app-clipboard [text]="channel.node1_public_key"></app-clipboard>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
||||||
@ -25,8 +31,14 @@
|
|||||||
</td>
|
</td>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #right>
|
<ng-template #right>
|
||||||
<td class="alias text-left" *ngIf="channel.node1_public_key === publicKey">
|
<td class="alias text-left">
|
||||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]">{{ channel.alias_right }}</a>
|
{{ channel.alias_right || '?' }}
|
||||||
|
</td>
|
||||||
|
<td class="text-left">
|
||||||
|
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]">
|
||||||
|
<span>{{ channel.node2_public_key | shortenString : 10 }}</span>
|
||||||
|
</a>
|
||||||
|
<app-clipboard [text]="channel.node2_public_key"></app-clipboard>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
||||||
@ -37,23 +49,20 @@
|
|||||||
{{ channel.node2_fee_rate / 10000 | number }}%
|
{{ channel.node2_fee_rate / 10000 | number }}%
|
||||||
</td>
|
</td>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<td class="capacity text-right">
|
|
||||||
<a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]">{{ channel.id }}</a>
|
|
||||||
</td>
|
|
||||||
<td class="capacity text-right">
|
<td class="capacity text-right">
|
||||||
<app-amount [satoshis]="channel.capacity" digitsInfo="1.2-2"></app-amount>
|
<app-amount [satoshis]="channel.capacity" digitsInfo="1.2-2"></app-amount>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="capacity text-right">
|
||||||
<a [routerLink]="['/tx' | relativeUrl, channel.transaction_id + ':' + channel.transaction_vout]" >
|
<a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]">{{ channel.id }}</a>
|
||||||
<span>{{ channel.transaction_id | shortenString : 10 }}</span>
|
</td>
|
||||||
</a>
|
|
||||||
<app-clipboard [text]="channel.transaction_id"></app-clipboard>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<ng-template #skeleton>
|
<ng-template #skeleton>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
<tr *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
||||||
|
<td class="alias text-left" style="width: 370px;">
|
||||||
|
<span class="skeleton-loader"></span>
|
||||||
|
</td>
|
||||||
<td class="alias text-left">
|
<td class="alias text-left">
|
||||||
<span class="skeleton-loader"></span>
|
<span class="skeleton-loader"></span>
|
||||||
</td>
|
</td>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<h5 class="card-title" i18n="mining.average-fee">Capacity</h5>
|
<h5 class="card-title" i18n="mining.average-fee">Capacity</h5>
|
||||||
<div class="card-text" i18n-ngbTooltip="mining.average-fee"
|
<div class="card-text" i18n-ngbTooltip="mining.average-fee"
|
||||||
ngbTooltip="Fee paid on average for each transaction in the past 144 blocks" placement="bottom">
|
ngbTooltip="Percentage change past week" placement="bottom">
|
||||||
<app-amount [satoshis]="statistics.latest.total_capacity" digitsInfo="1.2-2"></app-amount>
|
<app-amount [satoshis]="statistics.latest.total_capacity" digitsInfo="1.2-2"></app-amount>
|
||||||
<span class="fiat">
|
<span class="fiat">
|
||||||
<app-change [current]="statistics.latest.total_capacity" [previous]="statistics.previous.total_capacity"></app-change>
|
<app-change [current]="statistics.latest.total_capacity" [previous]="statistics.previous.total_capacity"></app-change>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<h5 class="card-title" i18n="mining.rewards">Nodes</h5>
|
<h5 class="card-title" i18n="mining.rewards">Nodes</h5>
|
||||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-desc"
|
<div class="card-text" i18n-ngbTooltip="mining.rewards-desc"
|
||||||
ngbTooltip="Amount being paid to miners in the past 144 blocks" placement="bottom">
|
ngbTooltip="Percentage change past week" placement="bottom">
|
||||||
<div class="fee-text">
|
<div class="fee-text">
|
||||||
{{ statistics.latest.node_count | number }}
|
{{ statistics.latest.node_count | number }}
|
||||||
</div>
|
</div>
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<h5 class="card-title" i18n="mining.rewards-per-tx">Channels</h5>
|
<h5 class="card-title" i18n="mining.rewards-per-tx">Channels</h5>
|
||||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-per-tx-desc"
|
<div class="card-text" i18n-ngbTooltip="mining.rewards-per-tx-desc"
|
||||||
ngbTooltip="Average miners' reward per transaction in the past 144 blocks" placement="bottom">
|
ngbTooltip="Percentage change past week" placement="bottom">
|
||||||
<div class="fee-text">
|
<div class="fee-text">
|
||||||
{{ statistics.latest.channel_count | number }}
|
{{ statistics.latest.channel_count | number }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@ class NodesApi {
|
|||||||
public async $getLatestStatistics(): Promise<any> {
|
public async $getLatestStatistics(): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const [rows]: any = await DB.query(`SELECT * FROM statistics ORDER BY id DESC LIMIT 1`);
|
const [rows]: any = await DB.query(`SELECT * FROM statistics ORDER BY id DESC LIMIT 1`);
|
||||||
const [rows2]: any = await DB.query(`SELECT * FROM statistics ORDER BY id DESC LIMIT 1 OFFSET 71`);
|
const [rows2]: any = await DB.query(`SELECT * FROM statistics ORDER BY id DESC LIMIT 1 OFFSET 72`);
|
||||||
return {
|
return {
|
||||||
latest: rows[0],
|
latest: rows[0],
|
||||||
previous: rows2[0],
|
previous: rows2[0],
|
@ -3,8 +3,8 @@ import * as express from 'express';
|
|||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import nodesRoutes from './api/nodes/nodes.routes';
|
import nodesRoutes from './api/explorer/nodes.routes';
|
||||||
import channelsRoutes from './api/nodes/channels.routes';
|
import channelsRoutes from './api/explorer/channels.routes';
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
private server: http.Server | undefined;
|
private server: http.Server | undefined;
|
||||||
|
@ -3,7 +3,7 @@ import DB from '../database';
|
|||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
import lightningApi from '../api/lightning/lightning-api-factory';
|
import lightningApi from '../api/lightning/lightning-api-factory';
|
||||||
import { ILightningApi } from '../api/lightning/lightning-api.interface';
|
import { ILightningApi } from '../api/lightning/lightning-api.interface';
|
||||||
import channelsApi from '../api/nodes/channels.api';
|
import channelsApi from '../api/explorer/channels.api';
|
||||||
import bitcoinClient from '../api/bitcoin/bitcoin-client';
|
import bitcoinClient from '../api/bitcoin/bitcoin-client';
|
||||||
|
|
||||||
class NodeSyncService {
|
class NodeSyncService {
|
||||||
@ -33,6 +33,7 @@ class NodeSyncService {
|
|||||||
await this.$saveChannel(channel);
|
await this.$saveChannel(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.$findInactiveNodesAndChannels();
|
||||||
await this.$scanForClosedChannels();
|
await this.$scanForClosedChannels();
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -40,7 +41,21 @@ class NodeSyncService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async $scanForClosedChannels() {
|
// Looking for channels whos nodes are inactive
|
||||||
|
private async $findInactiveNodesAndChannels(): Promise<void> {
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
const [channels]: [ILightningApi.Channel[]] = await DB.query(`SELECT channels.id FROM channels WHERE channels.status = 1 AND ((SELECT COUNT(*) FROM nodes WHERE nodes.public_key = channels.node1_public_key) = 0 OR (SELECT COUNT(*) FROM nodes WHERE nodes.public_key = channels.node2_public_key) = 0)`);
|
||||||
|
|
||||||
|
for (const channel of channels) {
|
||||||
|
await this.$updateChannelStatus(channel.id, 0);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.err('$findInactiveNodesAndChannels() error: ' + (e instanceof Error ? e.message : e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async $scanForClosedChannels(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const channels = await channelsApi.$getChannelsByStatus(0);
|
const channels = await channelsApi.$getChannelsByStatus(0);
|
||||||
for (const channel of channels) {
|
for (const channel of channels) {
|
||||||
@ -152,6 +167,14 @@ class NodeSyncService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async $updateChannelStatus(channelShortId: string, status: number): Promise<void> {
|
||||||
|
try {
|
||||||
|
await DB.query(`UPDATE channels SET status = ? WHERE id = ?`, [status, channelShortId]);
|
||||||
|
} catch (e) {
|
||||||
|
logger.err('$updateChannelStatus() error: ' + (e instanceof Error ? e.message : e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async $setChannelsInactive(): Promise<void> {
|
private async $setChannelsInactive(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await DB.query(`UPDATE channels SET status = 0 WHERE status = 1`);
|
await DB.query(`UPDATE channels SET status = 0 WHERE status = 1`);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user