merge forensics columns into main channels table
This commit is contained in:
parent
609f68eb24
commit
ded11892f5
@ -382,7 +382,15 @@ class DatabaseMigration {
|
|||||||
|
|
||||||
if (databaseSchemaVersion < 48 && isBitcoin === true) {
|
if (databaseSchemaVersion < 48 && isBitcoin === true) {
|
||||||
await this.$executeQuery('ALTER TABLE `channels` ADD source_checked tinyint(1) DEFAULT 0');
|
await this.$executeQuery('ALTER TABLE `channels` ADD source_checked tinyint(1) DEFAULT 0');
|
||||||
await this.$executeQuery(this.getCreateChannelsForensicsTableQuery(), await this.$checkIfTableExists('channels_forensics'));
|
await this.$executeQuery('ALTER TABLE `channels` ADD closing_fee bigint(20) unsigned DEFAULT 0');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD node1_funding_balance bigint(20) unsigned DEFAULT 0');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD node2_funding_balance bigint(20) unsigned DEFAULT 0');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD node1_closing_balance bigint(20) unsigned DEFAULT 0');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD node2_closing_balance bigint(20) unsigned DEFAULT 0');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD funding_ratio float unsigned DEFAULT NULL');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD closed_by varchar(66) DEFAULT NULL');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD single_funded tinyint(1) DEFAULT 0');
|
||||||
|
await this.$executeQuery('ALTER TABLE `channels` ADD outputs JSON DEFAULT "[]"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,25 +772,6 @@ class DatabaseMigration {
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCreateChannelsForensicsTableQuery(): string {
|
|
||||||
return `CREATE TABLE IF NOT EXISTS channels_forensics (
|
|
||||||
channel_id bigint(11) unsigned NOT NULL,
|
|
||||||
closing_fee bigint(20) unsigned DEFAULT 0,
|
|
||||||
node1_funding_balance bigint(20) unsigned DEFAULT 0,
|
|
||||||
node2_funding_balance bigint(20) unsigned DEFAULT 0,
|
|
||||||
node1_closing_balance bigint(20) unsigned DEFAULT 0,
|
|
||||||
node2_closing_balance bigint(20) unsigned DEFAULT 0,
|
|
||||||
funding_ratio float unsigned DEFAULT NULL,
|
|
||||||
closed_by varchar(66) DEFAULT NULL,
|
|
||||||
single_funded tinyint(1) default 0,
|
|
||||||
outputs JSON NOT NULL,
|
|
||||||
PRIMARY KEY (channel_id),
|
|
||||||
FOREIGN KEY (channel_id)
|
|
||||||
REFERENCES channels (id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getCreateNodesStatsQuery(): string {
|
private getCreateNodesStatsQuery(): string {
|
||||||
return `CREATE TABLE IF NOT EXISTS node_stats (
|
return `CREATE TABLE IF NOT EXISTS node_stats (
|
||||||
id int(11) unsigned NOT NULL AUTO_INCREMENT,
|
id int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
@ -131,9 +131,8 @@ class ChannelsApi {
|
|||||||
public async $getChannelsWithoutSourceChecked(): Promise<any[]> {
|
public async $getChannelsWithoutSourceChecked(): Promise<any[]> {
|
||||||
try {
|
try {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT channels.*, forensics.*
|
SELECT channels.*
|
||||||
FROM channels
|
FROM channels
|
||||||
LEFT JOIN channels_forensics AS forensics ON forensics.channel_id = channels.id
|
|
||||||
WHERE channels.source_checked != 1
|
WHERE channels.source_checked != 1
|
||||||
`;
|
`;
|
||||||
const [rows]: any = await DB.query(query);
|
const [rows]: any = await DB.query(query);
|
||||||
@ -161,16 +160,12 @@ class ChannelsApi {
|
|||||||
SELECT n1.alias AS alias_left, n1.longitude as node1_longitude, n1.latitude as node1_latitude,
|
SELECT n1.alias AS alias_left, n1.longitude as node1_longitude, n1.latitude as node1_latitude,
|
||||||
n2.alias AS alias_right, n2.longitude as node2_longitude, n2.latitude as node2_latitude,
|
n2.alias AS alias_right, n2.longitude as node2_longitude, n2.latitude as node2_latitude,
|
||||||
channels.*,
|
channels.*,
|
||||||
ns1.channels AS channels_left, ns1.capacity AS capacity_left, ns2.channels AS channels_right, ns2.capacity AS capacity_right,
|
ns1.channels AS channels_left, ns1.capacity AS capacity_left, ns2.channels AS channels_right, ns2.capacity AS capacity_right
|
||||||
forensics.closing_fee as closing_fee, forensics.node1_funding_balance as node1_funding_balance, forensics.node2_funding_balance as node2_funding_balance,
|
|
||||||
forensics.funding_ratio as funding_ratio, forensics.node1_closing_balance as node1_closing_balance, forensics.node2_closing_balance as node2_closing_balance,
|
|
||||||
forensics.closed_by as closed_by, forensics.single_funded as single_funded
|
|
||||||
FROM channels
|
FROM channels
|
||||||
LEFT JOIN nodes AS n1 ON n1.public_key = channels.node1_public_key
|
LEFT JOIN nodes AS n1 ON n1.public_key = channels.node1_public_key
|
||||||
LEFT JOIN nodes AS n2 ON n2.public_key = channels.node2_public_key
|
LEFT JOIN nodes AS n2 ON n2.public_key = channels.node2_public_key
|
||||||
LEFT JOIN node_stats AS ns1 ON ns1.public_key = channels.node1_public_key
|
LEFT JOIN node_stats AS ns1 ON ns1.public_key = channels.node1_public_key
|
||||||
LEFT JOIN node_stats AS ns2 ON ns2.public_key = channels.node2_public_key
|
LEFT JOIN node_stats AS ns2 ON ns2.public_key = channels.node2_public_key
|
||||||
LEFT JOIN channels_forensics AS forensics ON forensics.channel_id = channels.id
|
|
||||||
WHERE (
|
WHERE (
|
||||||
ns1.id = (
|
ns1.id = (
|
||||||
SELECT MAX(id)
|
SELECT MAX(id)
|
||||||
@ -277,15 +272,12 @@ class ChannelsApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async $getChannelForensicsByClosingId(transactionId: string): Promise<any> {
|
public async $getChannelByClosingId(transactionId: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
channels.id, channels.node1_public_key, channels.node2_public_key,
|
channels.*
|
||||||
channels.closing_reason, channels.closing_transaction_id, channels.capacity,
|
|
||||||
forensics.*
|
|
||||||
FROM channels
|
FROM channels
|
||||||
LEFT JOIN channels_forensics as forensics ON forensics.channel_id = channels.id
|
|
||||||
WHERE channels.closing_transaction_id = ?
|
WHERE channels.closing_transaction_id = ?
|
||||||
`;
|
`;
|
||||||
const [rows]: any = await DB.query(query, [transactionId]);
|
const [rows]: any = await DB.query(query, [transactionId]);
|
||||||
@ -294,20 +286,17 @@ class ChannelsApi {
|
|||||||
return rows[0];
|
return rows[0];
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.err('$getChannelForensicsByClosingId error: ' + (e instanceof Error ? e.message : e));
|
logger.err('$getChannelByClosingId error: ' + (e instanceof Error ? e.message : e));
|
||||||
// don't throw - this data isn't essential
|
// don't throw - this data isn't essential
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async $getChannelForensicsByOpeningId(transactionId: string): Promise<any> {
|
public async $getChannelsByOpeningId(transactionId: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
channels.id, channels.node1_public_key, channels.node2_public_key,
|
channels.*
|
||||||
channels.status, channels.transaction_id, channels.capacity,
|
|
||||||
forensics.*
|
|
||||||
FROM channels
|
FROM channels
|
||||||
LEFT JOIN channels_forensics as forensics ON forensics.channel_id = channels.id
|
|
||||||
WHERE channels.transaction_id = ?
|
WHERE channels.transaction_id = ?
|
||||||
`;
|
`;
|
||||||
const [rows]: any = await DB.query(query, [transactionId]);
|
const [rows]: any = await DB.query(query, [transactionId]);
|
||||||
@ -318,7 +307,7 @@ class ChannelsApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.err('$getChannelForensicsByOpeningId error: ' + (e instanceof Error ? e.message : e));
|
logger.err('$getChannelsByOpeningId error: ' + (e instanceof Error ? e.message : e));
|
||||||
// don't throw - this data isn't essential
|
// don't throw - this data isn't essential
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,36 +315,21 @@ class ChannelsApi {
|
|||||||
public async $updateClosingInfo(channelInfo: { id: string, node1_closing_balance: number, node2_closing_balance: number, closed_by: string | null, closing_fee: number, outputs: ILightningApi.ForensicOutput[]}): Promise<void> {
|
public async $updateClosingInfo(channelInfo: { id: string, node1_closing_balance: number, node2_closing_balance: number, closed_by: string | null, closing_fee: number, outputs: ILightningApi.ForensicOutput[]}): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO channels_forensics
|
UPDATE channels SET
|
||||||
(
|
|
||||||
channel_id,
|
|
||||||
node1_closing_balance,
|
|
||||||
node2_closing_balance,
|
|
||||||
closed_by,
|
|
||||||
closing_fee,
|
|
||||||
outputs
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
node1_closing_balance = ?,
|
node1_closing_balance = ?,
|
||||||
node2_closing_balance = ?,
|
node2_closing_balance = ?,
|
||||||
closed_by = ?,
|
closed_by = ?,
|
||||||
closing_fee = ?,
|
closing_fee = ?,
|
||||||
outputs = ?
|
outputs = ?
|
||||||
|
WHERE channels.id = ?
|
||||||
`;
|
`;
|
||||||
const jsonOutputs = JSON.stringify(channelInfo.outputs);
|
|
||||||
await DB.query<ResultSetHeader>(query, [
|
await DB.query<ResultSetHeader>(query, [
|
||||||
|
channelInfo.node1_closing_balance || 0,
|
||||||
|
channelInfo.node2_closing_balance || 0,
|
||||||
|
channelInfo.closed_by,
|
||||||
|
channelInfo.closing_fee || 0,
|
||||||
|
JSON.stringify(channelInfo.outputs),
|
||||||
channelInfo.id,
|
channelInfo.id,
|
||||||
channelInfo.node1_closing_balance || 0,
|
|
||||||
channelInfo.node2_closing_balance || 0,
|
|
||||||
channelInfo.closed_by,
|
|
||||||
channelInfo.closing_fee || 0,
|
|
||||||
jsonOutputs,
|
|
||||||
channelInfo.node1_closing_balance || 0,
|
|
||||||
channelInfo.node2_closing_balance || 0,
|
|
||||||
channelInfo.closed_by,
|
|
||||||
channelInfo.closing_fee || 0,
|
|
||||||
jsonOutputs
|
|
||||||
]);
|
]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.err('$updateClosingInfo error: ' + (e instanceof Error ? e.message : e));
|
logger.err('$updateClosingInfo error: ' + (e instanceof Error ? e.message : e));
|
||||||
@ -366,32 +340,19 @@ class ChannelsApi {
|
|||||||
public async $updateOpeningInfo(channelInfo: { id: string, node1_funding_balance: number, node2_funding_balance: number, funding_ratio: number, single_funded: boolean | void }): Promise<void> {
|
public async $updateOpeningInfo(channelInfo: { id: string, node1_funding_balance: number, node2_funding_balance: number, funding_ratio: number, single_funded: boolean | void }): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO channels_forensics
|
UPDATE channels SET
|
||||||
(
|
node1_funding_balance = ?,
|
||||||
channel_id,
|
node2_funding_balance = ?,
|
||||||
node1_funding_balance,
|
funding_ratio = ?,
|
||||||
node2_funding_balance,
|
single_funded = ?
|
||||||
funding_ratio,
|
WHERE channels.id = ?
|
||||||
single_funded,
|
|
||||||
outputs
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?, ?, ?, 'null')
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
node1_funding_balance = ?,
|
|
||||||
node2_funding_balance = ?,
|
|
||||||
funding_ratio = ?,
|
|
||||||
single_funded = ?
|
|
||||||
`;
|
`;
|
||||||
await DB.query<ResultSetHeader>(query, [
|
await DB.query<ResultSetHeader>(query, [
|
||||||
|
channelInfo.node1_funding_balance || 0,
|
||||||
|
channelInfo.node2_funding_balance || 0,
|
||||||
|
channelInfo.funding_ratio,
|
||||||
|
channelInfo.single_funded ? 1 : 0,
|
||||||
channelInfo.id,
|
channelInfo.id,
|
||||||
channelInfo.node1_funding_balance || 0,
|
|
||||||
channelInfo.node2_funding_balance || 0,
|
|
||||||
channelInfo.funding_ratio,
|
|
||||||
channelInfo.single_funded ? 1 : 0,
|
|
||||||
channelInfo.node1_funding_balance || 0,
|
|
||||||
channelInfo.node2_funding_balance || 0,
|
|
||||||
channelInfo.funding_ratio,
|
|
||||||
channelInfo.single_funded ? 1 : 0,
|
|
||||||
]);
|
]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.err('$updateOpeningInfo error: ' + (e instanceof Error ? e.message : e));
|
logger.err('$updateOpeningInfo error: ' + (e instanceof Error ? e.message : e));
|
||||||
|
@ -227,12 +227,12 @@ class ForensicsService {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const input of openTx.vin) {
|
for (const input of openTx.vin) {
|
||||||
const closeChannel = await channelsApi.$getChannelForensicsByClosingId(input.txid);
|
const closeChannel = await channelsApi.$getChannelByClosingId(input.txid);
|
||||||
if (closeChannel) {
|
if (closeChannel) {
|
||||||
// this input directly spends a channel close output
|
// this input directly spends a channel close output
|
||||||
await this.$attributeChannelBalances(closeChannel, openChannel, input);
|
await this.$attributeChannelBalances(closeChannel, openChannel, input);
|
||||||
} else {
|
} else {
|
||||||
const prevOpenChannels = await channelsApi.$getChannelForensicsByOpeningId(input.txid);
|
const prevOpenChannels = await channelsApi.$getChannelsByOpeningId(input.txid);
|
||||||
if (prevOpenChannels?.length) {
|
if (prevOpenChannels?.length) {
|
||||||
// this input spends a channel open change output
|
// this input spends a channel open change output
|
||||||
for (const prevOpenChannel of prevOpenChannels) {
|
for (const prevOpenChannel of prevOpenChannels) {
|
||||||
@ -286,7 +286,7 @@ class ForensicsService {
|
|||||||
for (const sweepInput of sweepTx.vin) {
|
for (const sweepInput of sweepTx.vin) {
|
||||||
const lnScriptType = this.findLightningScript(sweepInput);
|
const lnScriptType = this.findLightningScript(sweepInput);
|
||||||
if (lnScriptType > 1) {
|
if (lnScriptType > 1) {
|
||||||
const closeChannel = await channelsApi.$getChannelForensicsByClosingId(sweepInput.txid);
|
const closeChannel = await channelsApi.$getChannelByClosingId(sweepInput.txid);
|
||||||
if (closeChannel) {
|
if (closeChannel) {
|
||||||
const initiator = (lnScriptType === 2 || lnScriptType === 4) ? 'remote' : (lnScriptType === 3 ? 'local' : null);
|
const initiator = (lnScriptType === 2 || lnScriptType === 4) ? 'remote' : (lnScriptType === 3 ? 'local' : null);
|
||||||
await this.$attributeChannelBalances(closeChannel, openChannel, sweepInput, openContribution, initiator);
|
await this.$attributeChannelBalances(closeChannel, openChannel, sweepInput, openContribution, initiator);
|
||||||
@ -348,8 +348,8 @@ class ForensicsService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!linkedOpenings) {
|
if (!linkedOpenings) {
|
||||||
if (!prevChannel.outputs) {
|
if (!prevChannel.outputs || !prevChannel.outputs.length) {
|
||||||
prevChannel.outputs = prevChannel.outputs || prevChannelTx.vout.map(vout => {
|
prevChannel.outputs = prevChannelTx.vout.map(vout => {
|
||||||
return {
|
return {
|
||||||
type: 0,
|
type: 0,
|
||||||
value: vout.value,
|
value: vout.value,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user