2021-12-11 04:27:58 +04:00
import config from '../config' ;
2022-04-13 17:38:42 +04:00
import DB from '../database' ;
2021-12-11 04:27:58 +04:00
import logger from '../logger' ;
2022-04-22 04:03:08 -04:00
import { Common } from './common' ;
2023-01-10 17:24:18 -06:00
import blocksRepository from '../repositories/BlocksRepository' ;
import cpfpRepository from '../repositories/CpfpRepository' ;
import { RowDataPacket } from 'mysql2' ;
2022-01-12 17:26:10 +09:00
2021-12-11 04:27:58 +04:00
class DatabaseMigration {
2023-07-05 11:06:51 +02:00
private static currentVersion = 64 ;
2022-11-24 19:31:10 +09:00
private queryTimeout = 3600 _000 ;
2022-01-12 14:10:16 +09:00
private statisticsAddedIndexed = false ;
2022-06-13 10:12:27 +02:00
private uniqueLogs : string [ ] = [ ] ;
2022-07-27 23:01:57 +02:00
private blocksTruncatedMessage = ` 'blocks' table has been truncated. ` ;
private hashratesTruncatedMessage = ` 'hashrates' table has been truncated. ` ;
2021-12-11 04:27:58 +04:00
2022-06-13 10:12:27 +02:00
/ * *
* Avoid printing multiple time the same message
* /
private uniqueLog ( loggerFunction : any , msg : string ) {
if ( this . uniqueLogs . includes ( msg ) ) {
return ;
}
this . uniqueLogs . push ( msg ) ;
loggerFunction ( msg ) ;
}
2022-01-11 20:43:59 +09:00
/ * *
* Entry point
* /
2021-12-11 04:27:58 +04:00
public async $initializeOrMigrateDatabase ( ) : Promise < void > {
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: Running migrations' ) ;
2022-01-11 20:43:59 +09:00
2022-01-12 16:06:45 +09:00
await this . $printDatabaseVersion ( ) ;
2022-01-11 20:43:59 +09:00
// First of all, if the `state` database does not exist, create it so we can track migration version
if ( ! await this . $checkIfTableExists ( 'state' ) ) {
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: `state` table does not exist. Creating it.' ) ;
2022-01-11 20:43:59 +09:00
try {
await this . $createMigrationStateTable ( ) ;
} catch ( e ) {
2022-01-12 17:43:32 +09:00
logger . err ( 'MIGRATIONS: Unable to create `state` table, aborting in 10 seconds. ' + e ) ;
2022-04-22 04:03:08 -04:00
await Common . sleep $ ( 10000 ) ;
2022-01-11 20:43:59 +09:00
process . exit ( - 1 ) ;
}
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: `state` table initialized.' ) ;
2022-01-11 20:43:59 +09:00
}
let databaseSchemaVersion = 0 ;
try {
databaseSchemaVersion = await this . $getSchemaVersionFromDatabase ( ) ;
} catch ( e ) {
2022-01-12 17:43:32 +09:00
logger . err ( 'MIGRATIONS: Unable to get current database migration version, aborting in 10 seconds. ' + e ) ;
2022-04-22 04:03:08 -04:00
await Common . sleep $ ( 10000 ) ;
2022-01-11 20:43:59 +09:00
process . exit ( - 1 ) ;
}
2022-06-13 10:12:27 +02:00
if ( databaseSchemaVersion === 0 ) {
logger . info ( 'Initializing database (first run, clean install)' ) ;
}
if ( databaseSchemaVersion <= 2 ) {
// Disable some spam logs when they're not relevant
2023-01-02 13:25:40 +01:00
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
this . uniqueLog ( logger . notice , this . hashratesTruncatedMessage ) ;
2022-06-13 10:12:27 +02:00
}
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: Current state.schema_version ' + databaseSchemaVersion ) ;
logger . debug ( 'MIGRATIONS: Latest DatabaseMigration.version is ' + DatabaseMigration . currentVersion ) ;
2022-01-12 14:10:16 +09:00
if ( databaseSchemaVersion >= DatabaseMigration . currentVersion ) {
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: Nothing to do.' ) ;
2022-01-11 20:43:59 +09:00
return ;
2021-12-11 04:27:58 +04:00
}
2022-01-12 16:41:27 +09:00
// Now, create missing tables. Those queries cannot be wrapped into a transaction unfortunately
try {
await this . $createMissingTablesAndIndexes ( databaseSchemaVersion ) ;
} catch ( e ) {
2022-01-12 17:43:32 +09:00
logger . err ( 'MIGRATIONS: Unable to create required tables, aborting in 10 seconds. ' + e ) ;
2022-04-22 04:03:08 -04:00
await Common . sleep $ ( 10000 ) ;
2022-01-12 16:41:27 +09:00
process . exit ( - 1 ) ;
}
2022-01-12 14:10:16 +09:00
2022-01-11 20:43:59 +09:00
if ( DatabaseMigration . currentVersion > databaseSchemaVersion ) {
try {
2021-12-11 04:27:58 +04:00
await this . $migrateTableSchemaFromVersion ( databaseSchemaVersion ) ;
2022-06-13 10:12:27 +02:00
if ( databaseSchemaVersion === 0 ) {
2023-02-24 10:41:17 +09:00
logger . notice ( ` MIGRATIONS: OK. Database schema has been properly initialized to version ${ DatabaseMigration . currentVersion } (latest version) ` ) ;
2022-06-13 10:12:27 +02:00
} else {
logger . notice ( ` MIGRATIONS: OK. Database schema have been migrated from version ${ databaseSchemaVersion } to ${ DatabaseMigration . currentVersion } (latest version) ` ) ;
}
2022-01-11 20:43:59 +09:00
} catch ( e ) {
2022-01-12 17:43:32 +09:00
logger . err ( 'MIGRATIONS: Unable to migrate database, aborting. ' + e ) ;
2021-12-11 04:27:58 +04:00
}
}
2022-01-11 20:43:59 +09:00
return ;
2021-12-11 04:27:58 +04:00
}
2022-01-12 16:41:27 +09:00
/ * *
* Create all missing tables
* /
private async $createMissingTablesAndIndexes ( databaseSchemaVersion : number ) {
await this . $setStatisticsAddedIndexedFlag ( databaseSchemaVersion ) ;
2022-02-16 15:19:16 +09:00
const isBitcoin = [ 'mainnet' , 'testnet' , 'signet' ] . includes ( config . MEMPOOL . NETWORK ) ;
2022-02-19 20:45:02 +09:00
2022-07-09 16:53:29 +02:00
await this . $executeQuery ( this . getCreateElementsTableQuery ( ) , await this . $checkIfTableExists ( 'elements_pegs' ) ) ;
await this . $executeQuery ( this . getCreateStatisticsQuery ( ) , await this . $checkIfTableExists ( 'statistics' ) ) ;
if ( databaseSchemaVersion < 2 && this . statisticsAddedIndexed === false ) {
await this . $executeQuery ( ` CREATE INDEX added ON statistics (added); ` ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 2 ) ;
2022-07-09 16:53:29 +02:00
}
if ( databaseSchemaVersion < 3 ) {
await this . $executeQuery ( this . getCreatePoolsTableQuery ( ) , await this . $checkIfTableExists ( 'pools' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 3 ) ;
2022-07-09 16:53:29 +02:00
}
if ( databaseSchemaVersion < 4 ) {
await this . $executeQuery ( 'DROP table IF EXISTS blocks;' ) ;
await this . $executeQuery ( this . getCreateBlocksTableQuery ( ) , await this . $checkIfTableExists ( 'blocks' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 4 ) ;
2022-07-09 16:53:29 +02:00
}
if ( databaseSchemaVersion < 5 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE blocks;' ) ; // Need to re-index
await this . $executeQuery ( 'ALTER TABLE blocks ADD `reward` double unsigned NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 5 ) ;
2022-07-09 16:53:29 +02:00
}
2022-02-19 20:45:02 +09:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 6 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE blocks;' ) ; // Need to re-index
// Cleanup original blocks fields type
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `height` integer unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `tx_count` smallint unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `size` integer unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `weight` integer unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `difficulty` double NOT NULL DEFAULT "0"' ) ;
// We also fix the pools.id type so we need to drop/re-create the foreign key
await this . $executeQuery ( 'ALTER TABLE blocks DROP FOREIGN KEY IF EXISTS `blocks_ibfk_1`' ) ;
await this . $executeQuery ( 'ALTER TABLE pools MODIFY `id` smallint unsigned AUTO_INCREMENT' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `pool_id` smallint unsigned NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks ADD FOREIGN KEY (`pool_id`) REFERENCES `pools` (`id`)' ) ;
// Add new block indexing fields
await this . $executeQuery ( 'ALTER TABLE blocks ADD `version` integer unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks ADD `bits` integer unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks ADD `nonce` bigint unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks ADD `merkle_root` varchar(65) NOT NULL DEFAULT ""' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks ADD `previous_block_hash` varchar(65) NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 6 ) ;
2022-07-09 16:53:29 +02:00
}
2022-02-24 16:55:18 +09:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 7 && isBitcoin === true ) {
await this . $executeQuery ( 'DROP table IF EXISTS hashrates;' ) ;
await this . $executeQuery ( this . getCreateDailyStatsTableQuery ( ) , await this . $checkIfTableExists ( 'hashrates' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 7 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-06 12:32:16 +01:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 8 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE hashrates;' ) ; // Need to re-index
await this . $executeQuery ( 'ALTER TABLE `hashrates` DROP INDEX `PRIMARY`' ) ;
await this . $executeQuery ( 'ALTER TABLE `hashrates` ADD `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST' ) ;
await this . $executeQuery ( 'ALTER TABLE `hashrates` ADD `share` float NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `hashrates` ADD `type` enum("daily", "weekly") DEFAULT "daily"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 8 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-08 17:10:29 +01:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 9 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . hashratesTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE hashrates;' ) ; // Need to re-index
await this . $executeQuery ( 'ALTER TABLE `state` CHANGE `name` `name` varchar(100)' ) ;
await this . $executeQuery ( 'ALTER TABLE `hashrates` ADD UNIQUE `hashrate_timestamp_pool_id` (`hashrate_timestamp`, `pool_id`)' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 9 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-09 19:18:51 +01:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 10 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `blocks` ADD INDEX `blockTimestamp` (`blockTimestamp`)' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 10 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-11 20:42:07 +01:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 11 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE blocks;' ) ; // Need to re-index
await this . $executeQuery ( ` ALTER TABLE blocks
ADD avg_fee INT UNSIGNED NULL ,
ADD avg_fee_rate INT UNSIGNED NULL
` );
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `reward` BIGINT UNSIGNED NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `median_fee` INT UNSIGNED NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `fees` INT UNSIGNED NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 11 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-12 11:06:37 +01:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 12 && isBitcoin === true ) {
// No need to re-index because the new data type can contain larger values
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `fees` BIGINT UNSIGNED NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 12 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-12 14:47:33 +01:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 13 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `difficulty` DOUBLE UNSIGNED NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `median_fee` BIGINT UNSIGNED NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `avg_fee` BIGINT UNSIGNED NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks MODIFY `avg_fee_rate` BIGINT UNSIGNED NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 13 ) ;
2022-07-09 16:53:29 +02:00
}
2022-03-24 07:40:03 +09:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 14 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . hashratesTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE hashrates;' ) ; // Need to re-index
await this . $executeQuery ( 'ALTER TABLE `hashrates` DROP FOREIGN KEY `hashrates_ibfk_1`' ) ;
await this . $executeQuery ( 'ALTER TABLE `hashrates` MODIFY `pool_id` SMALLINT UNSIGNED NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 14 ) ;
2022-07-09 16:53:29 +02:00
}
2022-05-19 12:13:43 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 16 && isBitcoin === true ) {
this . uniqueLog ( logger . notice , this . hashratesTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE hashrates;' ) ; // Need to re-index because we changed timestamps
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 16 ) ;
2022-07-09 16:53:29 +02:00
}
2022-05-25 10:51:35 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 17 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `pools` ADD `slug` CHAR(50) NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 17 ) ;
2022-07-09 16:53:29 +02:00
}
2022-06-18 16:48:02 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 18 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `blocks` ADD INDEX `hash` (`hash`);' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 18 ) ;
2022-07-09 16:53:29 +02:00
}
2022-06-23 15:42:42 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 19 ) {
await this . $executeQuery ( this . getCreateRatesTableQuery ( ) , await this . $checkIfTableExists ( 'rates' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 19 ) ;
2022-07-09 16:53:29 +02:00
}
2022-06-25 12:14:32 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 20 && isBitcoin === true ) {
await this . $executeQuery ( this . getCreateBlocksSummariesTableQuery ( ) , await this . $checkIfTableExists ( 'blocks_summaries' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 20 ) ;
2022-07-09 16:53:29 +02:00
}
2022-06-26 13:49:39 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 21 ) {
await this . $executeQuery ( 'DROP TABLE IF EXISTS `rates`' ) ;
await this . $executeQuery ( this . getCreatePricesTableQuery ( ) , await this . $checkIfTableExists ( 'prices' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 21 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-06 22:27:45 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 22 && isBitcoin === true ) {
await this . $executeQuery ( 'DROP TABLE IF EXISTS `difficulty_adjustments`' ) ;
await this . $executeQuery ( this . getCreateDifficultyAdjustmentsTableQuery ( ) , await this . $checkIfTableExists ( 'difficulty_adjustments' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 22 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-06 11:58:06 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 23 ) {
await this . $executeQuery ( 'TRUNCATE `prices`' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` DROP `avg_prices`' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `USD` float DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `EUR` float DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `GBP` float DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `CAD` float DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `CHF` float DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `AUD` float DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `JPY` float DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 23 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-06 11:58:06 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 24 && isBitcoin == true ) {
await this . $executeQuery ( 'DROP TABLE IF EXISTS `blocks_audits`' ) ;
await this . $executeQuery ( this . getCreateBlocksAuditsTableQuery ( ) , await this . $checkIfTableExists ( 'blocks_audits' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 24 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-06 13:20:37 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 25 && isBitcoin === true ) {
await this . $executeQuery ( this . getCreateLightningStatisticsQuery ( ) , await this . $checkIfTableExists ( 'lightning_stats' ) ) ;
await this . $executeQuery ( this . getCreateNodesQuery ( ) , await this . $checkIfTableExists ( 'nodes' ) ) ;
await this . $executeQuery ( this . getCreateChannelsQuery ( ) , await this . $checkIfTableExists ( 'channels' ) ) ;
await this . $executeQuery ( this . getCreateNodesStatsQuery ( ) , await this . $checkIfTableExists ( 'node_stats' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 25 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-06 14:56:10 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 26 && isBitcoin === true ) {
2022-07-27 22:53:09 +02:00
if ( config . LIGHTNING . ENABLED ) {
2022-07-27 23:01:57 +02:00
this . uniqueLog ( logger . notice , ` 'lightning_stats' table has been truncated. ` ) ;
2022-07-27 22:53:09 +02:00
}
2022-07-09 16:53:29 +02:00
await this . $executeQuery ( ` TRUNCATE lightning_stats ` ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD tor_nodes int(11) NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD clearnet_nodes int(11) NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD unannounced_nodes int(11) NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 26 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-10 20:01:15 +02:00
2022-07-13 07:56:17 +02:00
if ( databaseSchemaVersion < 27 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD avg_capacity bigint(20) unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD avg_fee_rate int(11) unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD avg_base_fee_mtokens bigint(20) unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD med_capacity bigint(20) unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD med_fee_rate int(11) unsigned NOT NULL DEFAULT "0"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD med_base_fee_mtokens bigint(20) unsigned NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 27 ) ;
2022-07-13 07:56:17 +02:00
}
2023-02-24 10:41:17 +09:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 28 && isBitcoin === true ) {
2022-07-27 22:53:09 +02:00
if ( config . LIGHTNING . ENABLED ) {
2022-07-27 23:01:57 +02:00
this . uniqueLog ( logger . notice , ` 'lightning_stats' and 'node_stats' tables have been truncated. ` ) ;
2022-07-27 22:53:09 +02:00
}
2022-07-09 16:53:29 +02:00
await this . $executeQuery ( ` TRUNCATE lightning_stats ` ) ;
await this . $executeQuery ( ` TRUNCATE node_stats ` ) ;
await this . $executeQuery ( ` ALTER TABLE lightning_stats MODIFY added DATE ` ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 28 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-11 17:52:38 +02:00
2022-07-09 16:53:29 +02:00
if ( databaseSchemaVersion < 29 && isBitcoin === true ) {
await this . $executeQuery ( this . getCreateGeoNamesTableQuery ( ) , await this . $checkIfTableExists ( 'geo_names' ) ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD as_number int(11) unsigned NULL DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD city_id int(11) unsigned NULL DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD country_id int(11) unsigned NULL DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD accuracy_radius int(11) unsigned NULL DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD subdivision_id int(11) unsigned NULL DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD longitude double NULL DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD latitude double NULL DEFAULT NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 29 ) ;
2022-07-09 16:53:29 +02:00
}
2022-07-11 23:16:48 +02:00
2022-07-12 14:46:54 +02:00
if ( databaseSchemaVersion < 30 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `geo_names` CHANGE `type` `type` enum("city","country","division","continent","as_organization") NOT NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 30 ) ;
2022-07-12 14:46:54 +02:00
}
if ( databaseSchemaVersion < 31 && isBitcoin == true ) { // Link blocks to prices
2022-07-09 16:53:29 +02:00
await this . $executeQuery ( 'ALTER TABLE `prices` ADD `id` int NULL AUTO_INCREMENT UNIQUE' ) ;
await this . $executeQuery ( 'DROP TABLE IF EXISTS `blocks_prices`' ) ;
await this . $executeQuery ( this . getCreateBlocksPricesTableQuery ( ) , await this . $checkIfTableExists ( 'blocks_prices' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 31 ) ;
2022-07-07 19:11:42 +02:00
}
2022-07-12 12:12:10 +02:00
2022-07-07 19:11:42 +02:00
if ( databaseSchemaVersion < 32 && isBitcoin == true ) {
await this . $executeQuery ( 'ALTER TABLE `blocks_summaries` ADD `template` JSON DEFAULT "[]"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 32 ) ;
2022-01-12 16:41:27 +09:00
}
2022-07-17 09:53:02 +02:00
if ( databaseSchemaVersion < 33 && isBitcoin == true ) {
await this . $executeQuery ( 'ALTER TABLE `geo_names` CHANGE `type` `type` enum("city","country","division","continent","as_organization", "country_iso_code") NOT NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 33 ) ;
2022-07-17 09:53:02 +02:00
}
2022-08-01 17:25:44 +02:00
if ( databaseSchemaVersion < 34 && isBitcoin == true ) {
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD clearnet_tor_nodes int(11) NOT NULL DEFAULT "0"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 34 ) ;
2022-08-01 17:25:44 +02:00
}
2022-08-05 12:32:20 +02:00
if ( databaseSchemaVersion < 35 && isBitcoin == true ) {
await this . $executeQuery ( 'DELETE from `lightning_stats` WHERE added > "2021-09-19"' ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` ADD CONSTRAINT added_unique UNIQUE (added);' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 35 ) ;
2022-08-05 12:32:20 +02:00
}
2022-08-09 11:17:37 +02:00
if ( databaseSchemaVersion < 36 && isBitcoin == true ) {
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD status TINYINT NOT NULL DEFAULT "1"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 36 ) ;
2022-08-09 11:17:37 +02:00
}
2022-08-13 10:24:11 +02:00
if ( databaseSchemaVersion < 37 && isBitcoin == true ) {
await this . $executeQuery ( this . getCreateLNNodesSocketsTableQuery ( ) , await this . $checkIfTableExists ( 'nodes_sockets' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 37 ) ;
2022-08-13 10:24:11 +02:00
}
2022-08-19 11:57:59 +02:00
if ( databaseSchemaVersion < 38 && isBitcoin == true ) {
if ( config . LIGHTNING . ENABLED ) {
this . uniqueLog ( logger . notice , ` 'lightning_stats' and 'node_stats' tables have been truncated. ` ) ;
}
await this . $executeQuery ( ` TRUNCATE lightning_stats ` ) ;
await this . $executeQuery ( ` TRUNCATE node_stats ` ) ;
await this . $executeQuery ( 'ALTER TABLE `lightning_stats` CHANGE `added` `added` timestamp NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `node_stats` CHANGE `added` `added` timestamp NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 38 ) ;
2022-08-19 11:57:59 +02:00
}
2022-08-20 22:02:54 +04:00
if ( databaseSchemaVersion < 39 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD alias_search TEXT NULL DEFAULT NULL AFTER `alias`' ) ;
await this . $executeQuery ( 'ALTER TABLE nodes ADD FULLTEXT(alias_search)' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 39 ) ;
2022-08-20 22:02:54 +04:00
}
2022-08-26 02:31:14 +04:00
if ( databaseSchemaVersion < 40 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD capacity bigint(20) unsigned DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD channels int(11) unsigned DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD INDEX `capacity` (`capacity`);' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 40 ) ;
2022-08-26 02:31:14 +04:00
}
2022-10-21 22:47:14 +04:00
if ( databaseSchemaVersion < 41 && isBitcoin === true ) {
await this . $executeQuery ( 'UPDATE channels SET closing_reason = NULL WHERE closing_reason = 1' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 41 ) ;
2022-10-21 22:47:14 +04:00
}
2022-11-02 16:45:19 -06:00
if ( databaseSchemaVersion < 42 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `channels` ADD closing_resolved tinyint(1) DEFAULT 0' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 42 ) ;
2022-11-02 16:45:19 -06:00
}
2022-11-04 18:21:08 -06:00
if ( databaseSchemaVersion < 43 && isBitcoin === true ) {
await this . $executeQuery ( this . getCreateLNNodeRecordsTableQuery ( ) , await this . $checkIfTableExists ( 'nodes_records' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 43 ) ;
2022-11-04 18:21:08 -06:00
}
2022-10-31 11:07:28 -06:00
if ( databaseSchemaVersion < 44 && isBitcoin === true ) {
await this . $executeQuery ( 'UPDATE blocks_summaries SET template = NULL' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 44 ) ;
2022-10-31 11:07:28 -06:00
}
2022-11-23 19:03:28 +09:00
if ( databaseSchemaVersion < 45 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `blocks_audits` ADD fresh_txs JSON DEFAULT "[]"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 45 ) ;
2022-11-23 19:03:28 +09:00
}
2022-11-27 13:46:23 +09:00
2022-11-28 14:35:25 +09:00
if ( databaseSchemaVersion < 46 ) {
2022-11-28 17:33:07 +09:00
await this . $executeQuery ( ` ALTER TABLE blocks MODIFY blockTimestamp timestamp NOT NULL DEFAULT 0 ` ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 46 ) ;
2022-11-28 17:33:07 +09:00
}
2022-11-29 16:41:12 +09:00
if ( databaseSchemaVersion < 47 ) {
2022-11-27 13:46:23 +09:00
await this . $executeQuery ( 'ALTER TABLE `blocks` ADD cpfp_indexed tinyint(1) DEFAULT 0' ) ;
await this . $executeQuery ( this . getCreateCPFPTableQuery ( ) , await this . $checkIfTableExists ( 'cpfp_clusters' ) ) ;
await this . $executeQuery ( this . getCreateTransactionsTableQuery ( ) , await this . $checkIfTableExists ( 'transactions' ) ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 47 ) ;
2022-11-27 13:46:23 +09:00
}
2022-11-10 12:21:19 -06:00
if ( databaseSchemaVersion < 48 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `channels` ADD source_checked tinyint(1) DEFAULT 0' ) ;
2022-11-25 15:54:44 +09:00
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 "[]"' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 48 ) ;
2022-11-24 19:31:10 +09:00
}
if ( databaseSchemaVersion < 49 && isBitcoin === true ) {
await this . $executeQuery ( 'TRUNCATE TABLE `blocks_audits`' ) ;
2022-12-01 14:41:37 +09:00
await this . updateToSchemaVersion ( 49 ) ;
2022-11-10 12:21:19 -06:00
}
2023-01-05 13:02:53 -06:00
2023-01-10 17:24:18 -06:00
if ( databaseSchemaVersion < 50 ) {
2023-01-05 13:02:53 -06:00
await this . $executeQuery ( 'ALTER TABLE `blocks` DROP COLUMN `cpfp_indexed`' ) ;
2023-01-10 17:24:18 -06:00
await this . updateToSchemaVersion ( 50 ) ;
}
if ( databaseSchemaVersion < 51 ) {
await this . $executeQuery ( 'ALTER TABLE `cpfp_clusters` ADD INDEX `height` (`height`)' ) ;
await this . updateToSchemaVersion ( 51 ) ;
}
if ( databaseSchemaVersion < 52 ) {
2023-01-09 10:24:12 -06:00
await this . $executeQuery ( this . getCreateCompactCPFPTableQuery ( ) , await this . $checkIfTableExists ( 'compact_cpfp_clusters' ) ) ;
await this . $executeQuery ( this . getCreateCompactTransactionsTableQuery ( ) , await this . $checkIfTableExists ( 'compact_transactions' ) ) ;
2023-01-10 17:24:18 -06:00
try {
await this . $convertCompactCpfpTables ( ) ;
await this . $executeQuery ( 'DROP TABLE IF EXISTS `transactions`' ) ;
2023-01-13 16:33:44 -06:00
await this . $executeQuery ( 'DROP TABLE IF EXISTS `cpfp_clusters`' ) ;
2023-01-10 17:24:18 -06:00
await this . updateToSchemaVersion ( 52 ) ;
2023-02-24 10:41:17 +09:00
} catch ( e ) {
2023-01-10 17:24:18 -06:00
logger . warn ( '' + ( e instanceof Error ? e.message : e ) ) ;
}
2023-01-05 13:02:53 -06:00
}
2023-02-23 14:50:20 +09:00
if ( databaseSchemaVersion < 53 ) {
2023-02-21 22:07:12 -06:00
await this . $executeQuery ( 'ALTER TABLE statistics MODIFY mempool_byte_weight bigint(20) UNSIGNED NOT NULL' ) ;
await this . updateToSchemaVersion ( 53 ) ;
}
2023-02-23 14:51:46 +09:00
if ( databaseSchemaVersion < 54 ) {
2023-02-23 14:50:20 +09:00
this . uniqueLog ( logger . notice , ` 'prices' table has been truncated ` ) ;
await this . $executeQuery ( ` TRUNCATE prices ` ) ;
2023-02-24 10:41:17 +09:00
if ( isBitcoin === true ) {
this . uniqueLog ( logger . notice , ` 'blocks_prices' table has been truncated ` ) ;
await this . $executeQuery ( ` TRUNCATE blocks_prices ` ) ;
}
2023-02-23 14:52:29 +09:00
await this . updateToSchemaVersion ( 54 ) ;
2023-02-23 14:50:20 +09:00
}
2023-02-17 21:21:21 +09:00
if ( databaseSchemaVersion < 55 ) {
await this . $executeQuery ( this . getAdditionalBlocksDataQuery ( ) ) ;
2023-02-25 13:59:37 +09:00
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
await this . $executeQuery ( 'TRUNCATE blocks;' ) ; // Need to re-index
2023-02-17 21:21:21 +09:00
await this . updateToSchemaVersion ( 55 ) ;
}
2023-01-02 13:25:40 +01:00
if ( databaseSchemaVersion < 56 ) {
await this . $executeQuery ( 'ALTER TABLE pools ADD unique_id int NOT NULL DEFAULT -1' ) ;
await this . $executeQuery ( 'TRUNCATE TABLE `blocks`' ) ;
this . uniqueLog ( logger . notice , this . blocksTruncatedMessage ) ;
await this . $executeQuery ( 'DELETE FROM `pools`' ) ;
await this . $executeQuery ( 'ALTER TABLE pools AUTO_INCREMENT = 1' ) ;
2023-03-27 19:39:50 +09:00
await this . $executeQuery ( ` UPDATE state SET string = NULL WHERE name = 'pools_json_sha' ` ) ;
2023-01-02 13:25:40 +01:00
this . uniqueLog ( logger . notice , '`pools` table has been truncated`' ) ;
await this . updateToSchemaVersion ( 56 ) ;
}
2023-02-13 14:23:32 +09:00
2023-03-01 17:33:37 +09:00
if ( databaseSchemaVersion < 57 && isBitcoin === true ) {
2023-02-13 14:23:32 +09:00
await this . $executeQuery ( ` ALTER TABLE nodes MODIFY updated_at datetime NULL ` ) ;
await this . updateToSchemaVersion ( 57 ) ;
}
2023-02-25 11:28:44 +09:00
if ( databaseSchemaVersion < 58 ) {
// We only run some migration queries for this version
await this . updateToSchemaVersion ( 58 ) ;
}
2023-03-14 15:39:15 +09:00
if ( databaseSchemaVersion < 59 && ( config . MEMPOOL . NETWORK === 'signet' || config . MEMPOOL . NETWORK === 'testnet' ) ) {
// https://github.com/mempool/mempool/issues/3360
await this . $executeQuery ( ` TRUNCATE prices ` ) ;
}
2023-05-17 11:46:50 -04:00
if ( databaseSchemaVersion < 60 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `blocks_audits` ADD sigop_txs JSON DEFAULT "[]"' ) ;
await this . updateToSchemaVersion ( 60 ) ;
}
2023-05-25 17:39:45 -04:00
if ( databaseSchemaVersion < 61 && isBitcoin === true ) {
// Break block templates into their own table
if ( ! await this . $checkIfTableExists ( 'blocks_templates' ) ) {
await this . $executeQuery ( 'CREATE TABLE blocks_templates AS SELECT id, template FROM blocks_summaries WHERE template != "[]"' ) ;
}
await this . $executeQuery ( 'ALTER TABLE blocks_templates MODIFY template JSON DEFAULT "[]"' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks_templates ADD PRIMARY KEY (id)' ) ;
await this . $executeQuery ( 'ALTER TABLE blocks_summaries DROP COLUMN template' ) ;
await this . updateToSchemaVersion ( 61 ) ;
}
2023-06-10 12:15:29 -04:00
if ( databaseSchemaVersion < 62 && isBitcoin === true ) {
2023-06-09 13:46:14 -04:00
await this . $executeQuery ( 'ALTER TABLE `blocks_audits` ADD expected_fees BIGINT UNSIGNED DEFAULT NULL' ) ;
await this . $executeQuery ( 'ALTER TABLE `blocks_audits` ADD expected_weight BIGINT UNSIGNED DEFAULT NULL' ) ;
2023-06-10 12:15:29 -04:00
await this . updateToSchemaVersion ( 62 ) ;
}
2023-06-19 18:14:09 -04:00
if ( databaseSchemaVersion < 63 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `blocks_audits` ADD fullrbf_txs JSON DEFAULT "[]"' ) ;
await this . updateToSchemaVersion ( 63 ) ;
}
2023-07-05 11:06:51 +02:00
if ( databaseSchemaVersion < 64 && isBitcoin === true ) {
await this . $executeQuery ( 'ALTER TABLE `nodes` ADD features text NULL' ) ;
await this . updateToSchemaVersion ( 64 ) ;
}
2022-11-10 12:21:19 -06:00
}
2022-01-12 16:41:27 +09:00
2022-01-12 14:10:16 +09:00
/ * *
* Special case here for the ` statistics ` table - It appeared that somehow some dbs already had the ` added ` field indexed
* while it does not appear in previous schemas . The mariadb command "CREATE INDEX IF NOT EXISTS" is not supported on
* older mariadb version . Therefore we set a flag here in order to know if the index needs to be created or not before
* running the migration process
* /
private async $setStatisticsAddedIndexedFlag ( databaseSchemaVersion : number ) {
if ( databaseSchemaVersion >= 2 ) {
this . statisticsAddedIndexed = true ;
return ;
}
try {
2022-01-12 16:41:27 +09:00
// We don't use "CREATE INDEX IF NOT EXISTS" because it is not supported on old mariadb version 5.X
2022-01-12 14:10:16 +09:00
const query = ` SELECT COUNT(1) hasIndex FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema = DATABASE ( ) AND table_name = 'statistics' AND index_name = 'added' ; ` ;
2022-04-12 15:15:57 +09:00
const [ rows ] = await this . $executeQuery ( query , true ) ;
2022-01-12 14:10:16 +09:00
if ( rows [ 0 ] . hasIndex === 0 ) {
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: `statistics.added` is not indexed' ) ;
2022-01-12 14:10:16 +09:00
this . statisticsAddedIndexed = false ;
} else if ( rows [ 0 ] . hasIndex === 1 ) {
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: `statistics.added` is already indexed' ) ;
2022-01-12 14:10:16 +09:00
this . statisticsAddedIndexed = true ;
}
} catch ( e ) {
// Should really never happen but just in case it fails, we just don't execute
// any query related to this indexing so it won't fail if the index actually already exists
logger . err ( 'MIGRATIONS: Unable to check if `statistics.added` INDEX exist or not.' ) ;
this . statisticsAddedIndexed = true ;
}
}
2022-01-11 20:43:59 +09:00
/ * *
* Small query execution wrapper to log all executed queries
* /
2022-07-09 16:53:29 +02:00
private async $executeQuery ( query : string , silent = false ) : Promise < any > {
2022-01-12 16:06:45 +09:00
if ( ! silent ) {
2022-02-21 23:57:44 +09:00
logger . debug ( 'MIGRATIONS: Execute query:\n' + query ) ;
2022-01-12 16:06:45 +09:00
}
2022-04-12 15:15:57 +09:00
return DB . query ( { sql : query , timeout : this.queryTimeout } ) ;
2021-12-11 04:27:58 +04:00
}
2022-01-11 20:43:59 +09:00
/ * *
* Check if 'table' exists in the database
* /
private async $checkIfTableExists ( table : string ) : Promise < boolean > {
const query = ` SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = ' ${ config . DATABASE . DATABASE } ' AND TABLE_NAME = ' ${ table } ' ` ;
2022-04-12 15:15:57 +09:00
const [ rows ] = await DB . query ( { sql : query , timeout : this.queryTimeout } ) ;
2022-01-11 20:43:59 +09:00
return rows [ 0 ] [ 'COUNT(*)' ] === 1 ;
2021-12-11 04:27:58 +04:00
}
2022-01-11 20:43:59 +09:00
/ * *
* Get current database version
* /
2021-12-11 04:27:58 +04:00
private async $getSchemaVersionFromDatabase ( ) : Promise < number > {
const query = ` SELECT number FROM state WHERE name = 'schema_version'; ` ;
2022-04-12 15:15:57 +09:00
const [ rows ] = await this . $executeQuery ( query , true ) ;
2021-12-11 04:27:58 +04:00
return rows [ 0 ] [ 'number' ] ;
}
2022-01-11 20:43:59 +09:00
/ * *
* Create the ` state ` table
* /
private async $createMigrationStateTable ( ) : Promise < void > {
2022-07-09 16:53:29 +02:00
const query = ` CREATE TABLE IF NOT EXISTS state (
name varchar ( 25 ) NOT NULL ,
number int ( 11 ) NULL ,
string varchar ( 100 ) NULL ,
CONSTRAINT name_unique UNIQUE ( name )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
await this . $executeQuery ( query ) ;
2022-01-11 20:43:59 +09:00
2022-07-09 16:53:29 +02:00
// Set initial values
await this . $executeQuery ( ` INSERT INTO state VALUES('schema_version', 0, NULL); ` ) ;
await this . $executeQuery ( ` INSERT INTO state VALUES('last_elements_block', 0, NULL); ` ) ;
2021-12-11 04:27:58 +04:00
}
2022-01-11 20:43:59 +09:00
/ * *
2022-01-12 16:41:27 +09:00
* We actually execute the migrations queries here
2022-01-11 20:43:59 +09:00
* /
private async $migrateTableSchemaFromVersion ( version : number ) : Promise < void > {
2022-01-12 14:10:16 +09:00
const transactionQueries : string [ ] = [ ] ;
2022-01-11 20:43:59 +09:00
for ( const query of this . getMigrationQueriesFromVersion ( version ) ) {
transactionQueries . push ( query ) ;
}
2022-06-13 10:12:27 +02:00
logger . notice ( ` MIGRATIONS: ${ version > 0 ? 'Upgrading' : 'Initializing' } database schema version number to ${ DatabaseMigration . currentVersion } ` ) ;
2022-01-11 20:43:59 +09:00
transactionQueries . push ( this . getUpdateToLatestSchemaVersionQuery ( ) ) ;
try {
2022-04-12 15:15:57 +09:00
await this . $executeQuery ( 'START TRANSACTION;' ) ;
2022-01-11 20:43:59 +09:00
for ( const query of transactionQueries ) {
2022-04-12 15:15:57 +09:00
await this . $executeQuery ( query ) ;
2022-01-11 20:43:59 +09:00
}
2022-04-12 15:15:57 +09:00
await this . $executeQuery ( 'COMMIT;' ) ;
2022-01-11 20:43:59 +09:00
} catch ( e ) {
2022-04-12 15:15:57 +09:00
await this . $executeQuery ( 'ROLLBACK;' ) ;
2022-01-11 20:43:59 +09:00
throw e ;
}
2021-12-11 04:27:58 +04:00
}
2022-01-11 20:43:59 +09:00
/ * *
* Generate migration queries based on schema version
* /
private getMigrationQueriesFromVersion ( version : number ) : string [ ] {
2021-12-11 04:27:58 +04:00
const queries : string [ ] = [ ] ;
2022-03-11 21:58:25 +01:00
const isBitcoin = [ 'mainnet' , 'testnet' , 'signet' ] . includes ( config . MEMPOOL . NETWORK ) ;
2021-12-11 04:27:58 +04:00
2022-01-11 20:43:59 +09:00
if ( version < 1 ) {
if ( config . MEMPOOL . NETWORK !== 'liquid' && config . MEMPOOL . NETWORK !== 'liquidtestnet' ) {
2022-06-13 10:12:27 +02:00
if ( version > 0 ) {
logger . notice ( ` MIGRATIONS: Migrating (shifting) statistics table data ` ) ;
}
2022-01-12 14:10:16 +09:00
queries . push ( this . getShiftStatisticsQuery ( ) ) ;
2022-01-11 20:43:59 +09:00
}
}
2022-03-11 21:58:25 +01:00
if ( version < 7 && isBitcoin === true ) {
2022-02-21 12:22:20 +09:00
queries . push ( ` INSERT INTO state(name, number, string) VALUES ('last_hashrates_indexing', 0, NULL) ` ) ;
}
2023-02-24 10:41:17 +09:00
if ( version < 9 && isBitcoin === true ) {
2022-03-06 12:32:16 +01:00
queries . push ( ` INSERT INTO state(name, number, string) VALUES ('last_weekly_hashrates_indexing', 0, NULL) ` ) ;
}
2023-03-04 10:55:27 +09:00
if ( version < 58 ) {
2023-02-25 11:28:44 +09:00
queries . push ( ` DELETE FROM state WHERE name = 'last_hashrates_indexing' ` ) ;
queries . push ( ` DELETE FROM state WHERE name = 'last_weekly_hashrates_indexing' ` ) ;
}
2022-01-11 20:43:59 +09:00
return queries ;
}
/ * *
* Save the schema version in the database
* /
2022-01-12 14:10:16 +09:00
private getUpdateToLatestSchemaVersionQuery ( ) : string {
2022-01-11 20:43:59 +09:00
return ` UPDATE state SET number = ${ DatabaseMigration . currentVersion } WHERE name = 'schema_version'; ` ;
}
2022-11-24 18:50:28 +09:00
private async updateToSchemaVersion ( version ) : Promise < void > {
await this . $executeQuery ( ` UPDATE state SET number = ${ version } WHERE name = 'schema_version'; ` ) ;
}
2022-01-12 16:06:45 +09:00
/ * *
* Print current database version
* /
private async $printDatabaseVersion() {
try {
2022-04-12 15:15:57 +09:00
const [ rows ] = await this . $executeQuery ( 'SELECT VERSION() as version;' , true ) ;
2022-02-21 23:57:44 +09:00
logger . debug ( ` MIGRATIONS: Database engine version ' ${ rows [ 0 ] . version } ' ` ) ;
2022-01-12 16:06:45 +09:00
} catch ( e ) {
2022-02-21 23:57:44 +09:00
logger . debug ( ` MIGRATIONS: Could not fetch database engine version. ` + e ) ;
2022-01-12 16:06:45 +09:00
}
}
2022-01-11 20:43:59 +09:00
// Couple of wrappers to clean the main logic
2022-01-12 16:41:27 +09:00
private getShiftStatisticsQuery ( ) : string {
return ` UPDATE statistics SET
vsize_1 = vsize_1 + vsize_2 , vsize_2 = vsize_3 ,
vsize_3 = vsize_4 , vsize_4 = vsize_5 ,
vsize_5 = vsize_6 , vsize_6 = vsize_8 ,
vsize_8 = vsize_10 , vsize_10 = vsize_12 ,
vsize_12 = vsize_15 , vsize_15 = vsize_20 ,
vsize_20 = vsize_30 , vsize_30 = vsize_40 ,
vsize_40 = vsize_50 , vsize_50 = vsize_60 ,
vsize_60 = vsize_70 , vsize_70 = vsize_80 ,
vsize_80 = vsize_90 , vsize_90 = vsize_100 ,
vsize_100 = vsize_125 , vsize_125 = vsize_150 ,
vsize_150 = vsize_175 , vsize_175 = vsize_200 ,
vsize_200 = vsize_250 , vsize_250 = vsize_300 ,
vsize_300 = vsize_350 , vsize_350 = vsize_400 ,
vsize_400 = vsize_500 , vsize_500 = vsize_600 ,
vsize_600 = vsize_700 , vsize_700 = vsize_800 ,
vsize_800 = vsize_900 , vsize_900 = vsize_1000 ,
vsize_1000 = vsize_1200 , vsize_1200 = vsize_1400 ,
vsize_1400 = vsize_1800 , vsize_1800 = vsize_2000 , vsize_2000 = 0 ; ` ;
}
2022-01-11 20:43:59 +09:00
private getCreateStatisticsQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS statistics (
id int ( 11 ) NOT NULL AUTO_INCREMENT ,
2021-12-11 04:27:58 +04:00
added datetime NOT NULL ,
unconfirmed_transactions int ( 11 ) UNSIGNED NOT NULL ,
tx_per_second float UNSIGNED NOT NULL ,
vbytes_per_second int ( 10 ) UNSIGNED NOT NULL ,
mempool_byte_weight int ( 10 ) UNSIGNED NOT NULL ,
fee_data longtext NOT NULL ,
total_fee double UNSIGNED NOT NULL ,
vsize_1 int ( 11 ) NOT NULL ,
vsize_2 int ( 11 ) NOT NULL ,
vsize_3 int ( 11 ) NOT NULL ,
vsize_4 int ( 11 ) NOT NULL ,
vsize_5 int ( 11 ) NOT NULL ,
vsize_6 int ( 11 ) NOT NULL ,
vsize_8 int ( 11 ) NOT NULL ,
vsize_10 int ( 11 ) NOT NULL ,
vsize_12 int ( 11 ) NOT NULL ,
vsize_15 int ( 11 ) NOT NULL ,
vsize_20 int ( 11 ) NOT NULL ,
vsize_30 int ( 11 ) NOT NULL ,
vsize_40 int ( 11 ) NOT NULL ,
vsize_50 int ( 11 ) NOT NULL ,
vsize_60 int ( 11 ) NOT NULL ,
vsize_70 int ( 11 ) NOT NULL ,
vsize_80 int ( 11 ) NOT NULL ,
vsize_90 int ( 11 ) NOT NULL ,
vsize_100 int ( 11 ) NOT NULL ,
vsize_125 int ( 11 ) NOT NULL ,
vsize_150 int ( 11 ) NOT NULL ,
vsize_175 int ( 11 ) NOT NULL ,
vsize_200 int ( 11 ) NOT NULL ,
vsize_250 int ( 11 ) NOT NULL ,
vsize_300 int ( 11 ) NOT NULL ,
vsize_350 int ( 11 ) NOT NULL ,
vsize_400 int ( 11 ) NOT NULL ,
vsize_500 int ( 11 ) NOT NULL ,
vsize_600 int ( 11 ) NOT NULL ,
vsize_700 int ( 11 ) NOT NULL ,
vsize_800 int ( 11 ) NOT NULL ,
vsize_900 int ( 11 ) NOT NULL ,
vsize_1000 int ( 11 ) NOT NULL ,
vsize_1200 int ( 11 ) NOT NULL ,
vsize_1400 int ( 11 ) NOT NULL ,
vsize_1600 int ( 11 ) NOT NULL ,
vsize_1800 int ( 11 ) NOT NULL ,
2022-01-11 20:43:59 +09:00
vsize_2000 int ( 11 ) NOT NULL ,
CONSTRAINT PRIMARY KEY ( id )
2022-01-12 16:06:45 +09:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
2021-12-11 04:27:58 +04:00
}
2022-01-12 16:41:27 +09:00
2022-01-11 20:43:59 +09:00
private getCreateElementsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS elements_pegs (
block int ( 11 ) NOT NULL ,
datetime int ( 11 ) NOT NULL ,
amount bigint ( 20 ) NOT NULL ,
txid varchar ( 65 ) NOT NULL ,
txindex int ( 11 ) NOT NULL ,
bitcoinaddress varchar ( 100 ) NOT NULL ,
bitcointxid varchar ( 65 ) NOT NULL ,
bitcoinindex int ( 11 ) NOT NULL ,
final_tx int ( 11 ) NOT NULL
2022-01-12 16:06:45 +09:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
2021-12-11 04:27:58 +04:00
}
2022-01-19 18:50:52 +09:00
2022-01-13 12:18:39 +09:00
private getCreatePoolsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS pools (
id int ( 11 ) NOT NULL AUTO_INCREMENT ,
name varchar ( 50 ) NOT NULL ,
link varchar ( 255 ) NOT NULL ,
addresses text NOT NULL ,
regexes text NOT NULL ,
PRIMARY KEY ( id )
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ; ` ;
}
private getCreateBlocksTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS blocks (
height int ( 11 ) unsigned NOT NULL ,
hash varchar ( 65 ) NOT NULL ,
blockTimestamp timestamp NOT NULL ,
size int ( 11 ) unsigned NOT NULL ,
weight int ( 11 ) unsigned NOT NULL ,
tx_count int ( 11 ) unsigned NOT NULL ,
coinbase_raw text ,
difficulty bigint ( 20 ) unsigned NOT NULL ,
pool_id int ( 11 ) DEFAULT - 1 ,
fees double unsigned NOT NULL ,
fee_span json NOT NULL ,
median_fee double unsigned NOT NULL ,
PRIMARY KEY ( height ) ,
INDEX ( pool_id ) ,
FOREIGN KEY ( pool_id ) REFERENCES pools ( id )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-02-19 20:45:02 +09:00
2023-02-17 21:21:21 +09:00
private getAdditionalBlocksDataQuery ( ) : string {
return ` ALTER TABLE blocks
ADD median_timestamp timestamp NOT NULL ,
ADD coinbase_address varchar ( 100 ) NULL ,
ADD coinbase_signature varchar ( 500 ) NULL ,
2023-02-23 08:50:30 +09:00
ADD coinbase_signature_ascii varchar ( 500 ) NULL ,
2023-02-17 21:21:21 +09:00
ADD avg_tx_size double unsigned NOT NULL ,
ADD total_inputs int unsigned NOT NULL ,
ADD total_outputs int unsigned NOT NULL ,
ADD total_output_amt bigint unsigned NOT NULL ,
ADD fee_percentiles longtext NULL ,
2023-02-18 11:26:13 +09:00
ADD median_fee_amt int unsigned NULL ,
2023-02-17 21:21:21 +09:00
ADD segwit_total_txs int unsigned NOT NULL ,
ADD segwit_total_size int unsigned NOT NULL ,
ADD segwit_total_weight int unsigned NOT NULL ,
ADD header varchar ( 160 ) NOT NULL ,
ADD utxoset_change int NOT NULL ,
ADD utxoset_size int unsigned NULL ,
ADD total_input_amt bigint unsigned NULL
` ;
}
2022-02-19 20:45:02 +09:00
private getCreateDailyStatsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS hashrates (
hashrate_timestamp timestamp NOT NULL ,
avg_hashrate double unsigned DEFAULT '0' ,
pool_id smallint unsigned NULL ,
PRIMARY KEY ( hashrate_timestamp ) ,
INDEX ( pool_id ) ,
FOREIGN KEY ( pool_id ) REFERENCES pools ( id )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-02-21 16:38:18 +09:00
2022-06-25 12:14:32 +02:00
private getCreateRatesTableQuery ( ) : string { // This table has been replaced by the prices table
2022-05-25 10:51:35 +02:00
return ` CREATE TABLE IF NOT EXISTS rates (
height int ( 10 ) unsigned NOT NULL ,
bisq_rates JSON NOT NULL ,
PRIMARY KEY ( height )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-06-18 16:48:02 +02:00
private getCreateBlocksSummariesTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS blocks_summaries (
height int ( 10 ) unsigned NOT NULL ,
id varchar ( 65 ) NOT NULL ,
transactions JSON NOT NULL ,
2022-06-20 16:35:10 +02:00
PRIMARY KEY ( id ) ,
INDEX ( height )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
2022-06-18 16:48:02 +02:00
}
2022-06-23 15:42:42 +02:00
private getCreatePricesTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS prices (
time timestamp NOT NULL ,
avg_prices JSON NOT NULL ,
PRIMARY KEY ( time )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-06-25 12:14:32 +02:00
private getCreateDifficultyAdjustmentsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS difficulty_adjustments (
time timestamp NOT NULL ,
height int ( 10 ) unsigned NOT NULL ,
difficulty double unsigned NOT NULL ,
adjustment float NOT NULL ,
PRIMARY KEY ( height ) ,
INDEX ( time )
2022-07-06 11:58:06 +02:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
private getCreateLightningStatisticsQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS lightning_stats (
id int ( 11 ) NOT NULL AUTO_INCREMENT ,
added datetime NOT NULL ,
channel_count int ( 11 ) NOT NULL ,
node_count int ( 11 ) NOT NULL ,
total_capacity double unsigned NOT NULL ,
PRIMARY KEY ( id )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
private getCreateNodesQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS nodes (
public_key varchar ( 66 ) NOT NULL ,
first_seen datetime NOT NULL ,
updated_at datetime NOT NULL ,
alias varchar ( 200 ) CHARACTER SET utf8mb4 NOT NULL ,
color varchar ( 200 ) NOT NULL ,
sockets text DEFAULT NULL ,
PRIMARY KEY ( public_key ) ,
KEY alias ( alias ( 10 ) )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
private getCreateChannelsQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS channels (
id bigint ( 11 ) unsigned NOT NULL ,
short_id varchar ( 15 ) NOT NULL DEFAULT '' ,
capacity bigint ( 20 ) unsigned NOT NULL ,
transaction_id varchar ( 64 ) NOT NULL ,
transaction_vout int ( 11 ) NOT NULL ,
updated_at datetime DEFAULT NULL ,
created datetime DEFAULT NULL ,
status int ( 11 ) NOT NULL DEFAULT 0 ,
closing_transaction_id varchar ( 64 ) DEFAULT NULL ,
closing_date datetime DEFAULT NULL ,
closing_reason int ( 11 ) DEFAULT NULL ,
node1_public_key varchar ( 66 ) NOT NULL ,
node1_base_fee_mtokens bigint ( 20 ) unsigned DEFAULT NULL ,
node1_cltv_delta int ( 11 ) DEFAULT NULL ,
node1_fee_rate bigint ( 11 ) DEFAULT NULL ,
node1_is_disabled tinyint ( 1 ) DEFAULT NULL ,
node1_max_htlc_mtokens bigint ( 20 ) unsigned DEFAULT NULL ,
node1_min_htlc_mtokens bigint ( 20 ) DEFAULT NULL ,
node1_updated_at datetime DEFAULT NULL ,
node2_public_key varchar ( 66 ) NOT NULL ,
node2_base_fee_mtokens bigint ( 20 ) unsigned DEFAULT NULL ,
node2_cltv_delta int ( 11 ) DEFAULT NULL ,
node2_fee_rate bigint ( 11 ) DEFAULT NULL ,
node2_is_disabled tinyint ( 1 ) DEFAULT NULL ,
node2_max_htlc_mtokens bigint ( 20 ) unsigned DEFAULT NULL ,
node2_min_htlc_mtokens bigint ( 20 ) unsigned DEFAULT NULL ,
node2_updated_at datetime DEFAULT NULL ,
PRIMARY KEY ( id ) ,
KEY node1_public_key ( node1_public_key ) ,
KEY node2_public_key ( node2_public_key ) ,
KEY status ( status ) ,
KEY short_id ( short_id ) ,
KEY transaction_id ( transaction_id ) ,
KEY closing_transaction_id ( closing_transaction_id )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
private getCreateNodesStatsQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS node_stats (
id int ( 11 ) unsigned NOT NULL AUTO_INCREMENT ,
public_key varchar ( 66 ) NOT NULL DEFAULT '' ,
added date NOT NULL ,
capacity bigint ( 20 ) unsigned NOT NULL DEFAULT 0 ,
channels int ( 11 ) unsigned NOT NULL DEFAULT 0 ,
PRIMARY KEY ( id ) ,
UNIQUE KEY added ( added , public_key ) ,
KEY public_key ( public_key )
2022-06-25 12:14:32 +02:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-07-06 22:27:45 +02:00
private getCreateBlocksAuditsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS blocks_audits (
time timestamp NOT NULL ,
hash varchar ( 65 ) NOT NULL ,
height int ( 10 ) unsigned NOT NULL ,
missing_txs JSON NOT NULL ,
added_txs JSON NOT NULL ,
match_rate float unsigned NOT NULL ,
PRIMARY KEY ( hash ) ,
INDEX ( height )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-07-11 17:52:38 +02:00
private getCreateGeoNamesTableQuery ( ) : string {
return ` CREATE TABLE geo_names (
id int ( 11 ) unsigned NOT NULL ,
type enum ( 'city' , 'country' , 'division' , 'continent' ) NOT NULL ,
names text DEFAULT NULL ,
UNIQUE KEY id ( id , type ) ,
KEY id_2 ( id )
2022-08-13 10:24:11 +02:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
2022-07-11 17:52:38 +02:00
}
2022-07-09 16:53:29 +02:00
private getCreateBlocksPricesTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS blocks_prices (
height int ( 10 ) unsigned NOT NULL ,
price_id int ( 10 ) unsigned NOT NULL ,
PRIMARY KEY ( height ) ,
INDEX ( price_id )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-08-13 10:24:11 +02:00
private getCreateLNNodesSocketsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS nodes_sockets (
public_key varchar ( 66 ) NOT NULL ,
socket varchar ( 100 ) NOT NULL ,
2022-08-13 11:01:18 +02:00
type enum ( 'ipv4' , 'ipv6' , 'torv2' , 'torv3' , 'i2p' , 'dns' , 'websocket' ) NULL ,
2022-08-13 10:24:11 +02:00
UNIQUE KEY public_key_socket ( public_key , socket ) ,
INDEX ( public_key )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-11-04 18:21:08 -06:00
private getCreateLNNodeRecordsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS nodes_records (
public_key varchar ( 66 ) NOT NULL ,
type int ( 10 ) unsigned NOT NULL ,
payload blob NOT NULL ,
UNIQUE KEY public_key_type ( public_key , type ) ,
INDEX ( public_key ) ,
FOREIGN KEY ( public_key )
REFERENCES nodes ( public_key )
ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2022-11-27 13:46:23 +09:00
private getCreateCPFPTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS cpfp_clusters (
root varchar ( 65 ) NOT NULL ,
height int ( 10 ) NOT NULL ,
txs JSON DEFAULT NULL ,
fee_rate double unsigned NOT NULL ,
PRIMARY KEY ( root )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
private getCreateTransactionsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS transactions (
txid varchar ( 65 ) NOT NULL ,
cluster varchar ( 65 ) DEFAULT NULL ,
PRIMARY KEY ( txid ) ,
FOREIGN KEY ( cluster ) REFERENCES cpfp_clusters ( root ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2023-01-09 10:24:12 -06:00
private getCreateCompactCPFPTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS compact_cpfp_clusters (
root binary ( 32 ) NOT NULL ,
height int ( 10 ) NOT NULL ,
txs BLOB DEFAULT NULL ,
2023-01-10 17:24:18 -06:00
fee_rate float unsigned ,
2023-01-09 10:24:12 -06:00
PRIMARY KEY ( root ) ,
INDEX ( height )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
private getCreateCompactTransactionsTableQuery ( ) : string {
return ` CREATE TABLE IF NOT EXISTS compact_transactions (
txid binary ( 32 ) NOT NULL ,
cluster binary ( 32 ) DEFAULT NULL ,
PRIMARY KEY ( txid )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ; ` ;
}
2023-02-26 15:28:50 +09:00
public async $blocksReindexingTruncate ( ) : Promise < void > {
2023-05-30 10:16:56 -07:00
logger . warn ( ` Truncating pools, blocks, hashrates and difficulty_adjustments tables for re-indexing (using '--reindex-blocks'). You can cancel this command within 5 seconds ` ) ;
2023-02-26 15:28:50 +09:00
await Common . sleep $ ( 5000 ) ;
await this . $executeQuery ( ` TRUNCATE blocks ` ) ;
await this . $executeQuery ( ` TRUNCATE hashrates ` ) ;
2023-03-03 13:59:17 +09:00
await this . $executeQuery ( ` TRUNCATE difficulty_adjustments ` ) ;
2023-02-26 15:28:50 +09:00
await this . $executeQuery ( 'DELETE FROM `pools`' ) ;
await this . $executeQuery ( 'ALTER TABLE pools AUTO_INCREMENT = 1' ) ;
await this . $executeQuery ( ` UPDATE state SET string = NULL WHERE name = 'pools_json_sha' ` ) ;
2023-02-25 11:28:44 +09:00
}
2023-01-10 17:24:18 -06:00
private async $convertCompactCpfpTables ( ) : Promise < void > {
try {
const batchSize = 250 ;
const maxHeight = await blocksRepository . $mostRecentBlockHeight ( ) || 0 ;
const [ minHeightRows ] : any = await DB . query ( ` SELECT MIN(height) AS minHeight from cpfp_clusters ` ) ;
const minHeight = ( minHeightRows . length && minHeightRows [ 0 ] . minHeight != null ) ? minHeightRows [ 0 ] . minHeight : maxHeight ;
let height = maxHeight ;
// Logging
let timer = new Date ( ) . getTime ( ) / 1000 ;
const startedAt = new Date ( ) . getTime ( ) / 1000 ;
while ( height > minHeight ) {
const [ rows ] = await DB . query (
`
SELECT * from cpfp_clusters
WHERE height <= ? AND height > ?
ORDER BY height
` ,
[ height , height - batchSize ]
) as RowDataPacket [ ] [ ] ;
if ( rows ? . length ) {
await cpfpRepository . $batchSaveClusters ( rows . map ( row = > {
return {
root : row.root ,
height : row.height ,
txs : JSON.parse ( row . txs ) ,
effectiveFeePerVsize : row.fee_rate ,
} ;
} ) ) ;
}
const elapsed = new Date ( ) . getTime ( ) / 1000 - timer ;
const runningFor = new Date ( ) . getTime ( ) / 1000 - startedAt ;
logger . debug ( ` Migrated cpfp data from block ${ height } to ${ height - batchSize } in ${ elapsed . toFixed ( 2 ) } seconds | total elapsed: ${ runningFor . toFixed ( 2 ) } seconds ` ) ;
timer = new Date ( ) . getTime ( ) / 1000 ;
height -= batchSize ;
}
} catch ( e ) {
logger . warn ( ` Failed to migrate cpfp transaction data ` ) ;
}
}
2021-12-11 04:27:58 +04:00
}
2022-01-06 02:26:07 +09:00
export default new DatabaseMigration ( ) ;