From 2aee554d7b7b0c6e6071246a01a372fcbefa2669 Mon Sep 17 00:00:00 2001 From: natsoni Date: Mon, 26 Jan 2026 22:58:02 +0100 Subject: [PATCH] add missing liquid federation address, fix expired UTXO detection, and re-index --- backend/src/api/database-migration.ts | 20 +++++++++++++++++++- backend/src/api/liquid/elements-parser.ts | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/backend/src/api/database-migration.ts b/backend/src/api/database-migration.ts index b0e46be96..32c7616d3 100644 --- a/backend/src/api/database-migration.ts +++ b/backend/src/api/database-migration.ts @@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository'; import { RowDataPacket } from 'mysql2'; class DatabaseMigration { - private static currentVersion = 104; + private static currentVersion = 105; private queryTimeout = 3600_000; private statisticsAddedIndexed = false; private uniqueLogs: string[] = []; @@ -1178,6 +1178,24 @@ class DatabaseMigration { await this.$executeQuery('ALTER TABLE `blocks` ADD INDEX `stale` (`stale`)'); await this.updateToSchemaVersion(103); } + + // reindex liquid federation addresses and txos, and add hardcoded federation addresses + // (safe to make this conditional on the network since it doesn't change the database schema) + if (databaseSchemaVersion < 105 && config.MEMPOOL.NETWORK === 'liquid') { + await this.$executeQuery('TRUNCATE TABLE elements_pegs'); + await this.$executeQuery('TRUNCATE TABLE federation_txos'); + await this.$executeQuery('SET FOREIGN_KEY_CHECKS = 0'); + await this.$executeQuery('TRUNCATE TABLE federation_addresses'); + await this.$executeQuery('SET FOREIGN_KEY_CHECKS = 1'); + // Hardcoded federation addresses + await this.$executeQuery(`INSERT INTO federation_addresses (bitcoinaddress) VALUES ('3EiAcrzq1cELXScc98KeCswGWZaPGceT1d')`); + await this.$executeQuery(`INSERT INTO federation_addresses (bitcoinaddress) VALUES ('3G6neksSBMp51kHJ2if8SeDUrzT8iVETWT')`); + await this.$executeQuery(`INSERT INTO federation_addresses (bitcoinaddress) VALUES ('bc1qxvay4an52gcghxq5lavact7r6qe9l4laedsazz8fj2ee2cy47tlqff4aj4')`); + await this.$executeQuery(`INSERT INTO federation_addresses (bitcoinaddress) VALUES ('bc1qwnevjp8nsq7adu3hxlvdvslrf242q4vuavfg0y929jp2zntp3vgq7cq6z2')`); + await this.$executeQuery(`UPDATE state SET number = 0 WHERE name = 'last_elements_block';`); + await this.$executeQuery(`UPDATE state SET number = 0 WHERE name = 'last_bitcoin_block_audit';`); + await this.updateToSchemaVersion(105); + } } /** diff --git a/backend/src/api/liquid/elements-parser.ts b/backend/src/api/liquid/elements-parser.ts index 0e5818ab0..05717c132 100644 --- a/backend/src/api/liquid/elements-parser.ts +++ b/backend/src/api/liquid/elements-parser.ts @@ -5,7 +5,7 @@ import { Common } from '../common'; import DB from '../../database'; import logger from '../../logger'; -const federationChangeAddresses = ['bc1qxvay4an52gcghxq5lavact7r6qe9l4laedsazz8fj2ee2cy47tlqff4aj4', '3EiAcrzq1cELXScc98KeCswGWZaPGceT1d']; +const federationChangeAddresses = ['bc1qxvay4an52gcghxq5lavact7r6qe9l4laedsazz8fj2ee2cy47tlqff4aj4', '3EiAcrzq1cELXScc98KeCswGWZaPGceT1d', '3G6neksSBMp51kHJ2if8SeDUrzT8iVETWT', 'bc1qwnevjp8nsq7adu3hxlvdvslrf242q4vuavfg0y929jp2zntp3vgq7cq6z2']; const auditBlockOffsetWithTip = 1; // Wait for 1 block confirmation before processing the block in the audit process to reduce the risk of reorgs class ElementsParser { @@ -306,7 +306,7 @@ class ElementsParser { for (const utxo of unspentAsTip) { if (utxo.expiredAt === 0 && block.height >= utxo.blocknumber + utxo.timelock) { // The UTXO is expiring in this block - await DB.query(`UPDATE federation_txos SET unspent = 0, lastblockupdate = ?, expiredAt = ? WHERE txid = ? AND txindex = ?`, [confirmedTip, block.time, utxo.txid, utxo.txindex]); + await DB.query(`UPDATE federation_txos SET lastblockupdate = ?, expiredAt = ? WHERE txid = ? AND txindex = ?`, [confirmedTip, block.time, utxo.txid, utxo.txindex]); } else if (utxo.expiredAt === 0 && confirmedTip >= utxo.blocknumber + utxo.timelock) { // The UTXO is expiring before the tip: we need to keep track of it await DB.query(`UPDATE federation_txos SET lastblockupdate = ? WHERE txid = ? AND txindex = ?`, [utxo.blocknumber + utxo.timelock - 1, utxo.txid, utxo.txindex]); } else {