Maybe migrate db

This commit is contained in:
Jakob Notland 2026-03-31 12:08:04 +02:00
parent 8e76a62d78
commit f603baf2ef
2 changed files with 39 additions and 6 deletions

View file

@ -88,9 +88,38 @@ pub fn deserialize_ido_params(data: &[u8]) -> Option<IdoParams> {
})
}
/// Migrate the IDO schema from v1 (category, no preinit/entry tables) to v2.
/// Safe to call on a fresh DB (no-op if v2 tables already exist) or an old DB
/// (drops and recreates the IDO tables; safe because no IDOs are indexed yet).
async fn maybe_migrate(pool: &SqlitePool) {
// If ido_preinit_utxo doesn't exist we're on v1 (or fresh). Drop everything
// IDO-related and let create_tables build the v2 schema from scratch.
let needs_migration: bool = sqlx::query_scalar(
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='ido_preinit_utxo'",
)
.fetch_one(pool)
.await
.map(|n: i64| n == 0)
.unwrap_or(true);
if !needs_migration {
return;
}
// Drop in dependency order (FK constraints)
for tbl in &["ido_entry", "ido_preinit_utxo", "ido_state", "ido"] {
sqlx::query(&format!("DROP TABLE IF EXISTS {tbl}"))
.execute(pool)
.await
.unwrap_or_else(|e| panic!("failed to drop {tbl}: {e}"));
}
}
pub async fn create_tables(pool: &SqlitePool) {
maybe_migrate(pool).await;
sqlx::query(
"CREATE TABLE ido (
"CREATE TABLE IF NOT EXISTS ido (
creation_txid BLOB PRIMARY KEY,
-- Token being sold (from output[2] of publishIdoPreInit)
offered_token_category BLOB NOT NULL,
@ -106,14 +135,14 @@ pub async fn create_tables(pool: &SqlitePool) {
.expect("failed to create ido table");
sqlx::query(
"CREATE INDEX idx_ido_offered_token_category ON ido(offered_token_category)",
"CREATE INDEX IF NOT EXISTS idx_ido_offered_token_category ON ido(offered_token_category)",
)
.execute(pool)
.await
.expect("failed to create idx_ido_offered_token_category");
sqlx::query(
"CREATE TABLE ido_state (
"CREATE TABLE IF NOT EXISTS ido_state (
creation_txid BLOB PRIMARY KEY REFERENCES ido(creation_txid) ON DELETE CASCADE,
distributor_utxo_txid BLOB,
distributor_utxo_n INT,
@ -127,7 +156,7 @@ pub async fn create_tables(pool: &SqlitePool) {
// Tracks the moving pre-init contract UTXO (output[1]) through idoPreInitStep txs.
// When createIDO fires, this row is deleted and offering_category is set on the ido row.
sqlx::query(
"CREATE TABLE ido_preinit_utxo (
"CREATE TABLE IF NOT EXISTS ido_preinit_utxo (
ido_creation_txid BLOB NOT NULL REFERENCES ido(creation_txid) ON DELETE CASCADE,
utxo_txid BLOB NOT NULL,
utxo_n INTEGER NOT NULL,
@ -141,7 +170,7 @@ pub async fn create_tables(pool: &SqlitePool) {
// Unspent entry NFT UTXOs created by participants.
// Populated once offering_category is known (after createIDO fires).
sqlx::query(
"CREATE TABLE ido_entry (
"CREATE TABLE IF NOT EXISTS ido_entry (
utxo_txid BLOB NOT NULL,
utxo_n INTEGER NOT NULL,
offering_category BLOB NOT NULL,
@ -156,7 +185,7 @@ pub async fn create_tables(pool: &SqlitePool) {
.expect("failed to create ido_entry table");
sqlx::query(
"CREATE INDEX idx_ido_entry_offering ON ido_entry(offering_category, spent)",
"CREATE INDEX IF NOT EXISTS idx_ido_entry_offering ON ido_entry(offering_category, spent)",
)
.execute(pool)
.await

View file

@ -13,6 +13,7 @@ use std::time::Duration;
use super::DB;
use crate::db::bcmr::prepare_tables as bcmr_prepare_tables;
use crate::db::cauldron::config::check_db_version;
use crate::db::cauldron::ido;
use crate::db::cauldron::prepare_tables as cauldron_prepare_tables;
use crate::db::crc20::prepare_tables as crc20_prepare_tables;
use crate::db::oracle::prepare_tables as oracle_prepare_tables;
@ -100,6 +101,9 @@ pub async fn initialize_databases(network: &str, read_slots: ReadSlots) -> Resul
cauldron_prepare_tables(&cauldron_db_write).await;
} else {
check_db_version(&cauldron_db_read).await?;
// Run IDO table migration/creation separately so that schema additions
// take effect on existing databases without requiring a full DB wipe.
ido::create_tables(&cauldron_db_write).await;
}
// Initialize BCMR database