Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/backend_task/wallet/fetch_platform_address_balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl AppContext {
self.db.get_platform_sync_info(&seed_hash).unwrap_or((0, 0));

// Create provider (requires wallet to be open for address derivation)
let provider = {
let mut provider = {
let wallet = wallet_arc.read().map_err(|e| e.to_string())?;
match WalletAddressProvider::new(&wallet, self.network) {
Ok(provider) => provider.with_stored_state(&wallet, self.network, last_sync_height),
Expand All @@ -42,7 +42,6 @@ impl AppContext {
Err(e) => return Err(e),
}
};
let mut provider = provider;

// Sync using SDK's privacy-preserving method (handles both full and incremental)
let sdk = self.sdk.load().as_ref().clone();
Expand Down Expand Up @@ -148,7 +147,6 @@ impl AppContext {
funds.balance,
funds.nonce,
&self.network,
true,
) {
tracing::warn!("Failed to persist Platform address info: {}", e);
}
Expand Down
1 change: 0 additions & 1 deletion src/context/wallet_lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ impl AppContext {
info.balance,
info.nonce,
&self.network,
false, // Not a sync operation
) {
tracing::warn!("Failed to store Platform address info in database: {}", e);
}
Expand Down
89 changes: 85 additions & 4 deletions src/database/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rusqlite::{Connection, params};
use std::fs;
use std::path::Path;

pub const DEFAULT_DB_VERSION: u16 = 27;
pub const DEFAULT_DB_VERSION: u16 = 28;

pub const DEFAULT_NETWORK: &str = "dash";

Expand Down Expand Up @@ -51,6 +51,9 @@ impl Database {

fn apply_version_changes(&self, version: u16, tx: &Connection) -> rusqlite::Result<()> {
match version {
28 => {
self.drop_obsolete_sync_columns_and_rename_checkpoint(tx)?;
}
27 => {
self.add_network_indexes(tx)?;
}
Expand Down Expand Up @@ -315,8 +318,7 @@ impl Database {
unconfirmed_balance INTEGER DEFAULT 0,
total_balance INTEGER DEFAULT 0,
last_platform_full_sync INTEGER DEFAULT 0,
last_platform_sync_checkpoint INTEGER DEFAULT 0,
last_terminal_block INTEGER DEFAULT 0
last_platform_sync_height INTEGER DEFAULT 0
)",
[],
)?;
Expand Down Expand Up @@ -355,7 +357,6 @@ impl Database {
nonce INTEGER NOT NULL DEFAULT 0,
network TEXT NOT NULL,
updated_at INTEGER NOT NULL DEFAULT 0,
last_full_sync_balance INTEGER DEFAULT NULL,
PRIMARY KEY (seed_hash, address, network),
FOREIGN KEY (seed_hash) REFERENCES wallet(seed_hash) ON DELETE CASCADE
)",
Expand Down Expand Up @@ -553,6 +554,7 @@ impl Database {
/// Migration: Add platform sync columns to wallet table (version 20).
/// - last_platform_full_sync: Unix timestamp of last full platform address sync
/// - last_platform_sync_checkpoint: Block height checkpoint from last full sync
/// (renamed to `last_platform_sync_height` in version 28)
fn add_platform_sync_columns(&self, conn: &Connection) -> rusqlite::Result<()> {
conn.execute(
"ALTER TABLE wallet ADD COLUMN last_platform_full_sync INTEGER DEFAULT 0",
Expand Down Expand Up @@ -838,6 +840,85 @@ impl Database {
Ok(())
}

/// Migration: Drop obsolete sync columns and rename checkpoint column (version 28).
///
/// - Drops `last_terminal_block` from `wallet` (added in v23, no longer read/written)
/// - Drops `last_full_sync_balance` from `platform_address_balances` (added in v26, no longer read/written)
/// - Renames `last_platform_sync_checkpoint` → `last_platform_sync_height` in `wallet`
/// to reflect its new semantics (SDK sync height, not a legacy checkpoint)
///
/// Requires SQLite ≥ 3.35.0 for DROP COLUMN support.
fn drop_obsolete_sync_columns_and_rename_checkpoint(
&self,
conn: &Connection,
) -> rusqlite::Result<()> {
// Verify SQLite version supports DROP COLUMN (3.35.0+)
let version_str: String =
conn.query_row("SELECT sqlite_version()", [], |row| row.get(0))?;
let parts: Vec<u32> = version_str
.split('.')
.filter_map(|s| s.parse().ok())
.collect();
let (major, minor, _patch) = (
parts.first().copied().unwrap_or(0),
parts.get(1).copied().unwrap_or(0),
parts.get(2).copied().unwrap_or(0),
);
if major < 3 || (major == 3 && minor < 35) {
return Err(rusqlite::Error::SqliteFailure(
rusqlite::ffi::Error::new(1), // SQLITE_ERROR
Some(format!(
"SQLite {} is too old for DROP COLUMN (need ≥ 3.35.0). \
Please upgrade your system SQLite library.",
version_str
)),
));
}

// Drop obsolete columns (check existence first for idempotency)
let has_terminal_block: bool = conn
.query_row(
"SELECT COUNT(*) FROM pragma_table_info('wallet') WHERE name='last_terminal_block'",
[],
|row| row.get::<_, i32>(0).map(|count| count > 0),
)
.unwrap_or(false);
if has_terminal_block {
conn.execute("ALTER TABLE wallet DROP COLUMN last_terminal_block", [])?;
}

let has_full_sync_balance: bool = conn
.query_row(
"SELECT COUNT(*) FROM pragma_table_info('platform_address_balances') WHERE name='last_full_sync_balance'",
[],
|row| row.get::<_, i32>(0).map(|count| count > 0),
)
.unwrap_or(false);
if has_full_sync_balance {
conn.execute(
"ALTER TABLE platform_address_balances DROP COLUMN last_full_sync_balance",
[],
)?;
}

// Rename checkpoint → sync_height to match new semantics (check if rename is needed)
let has_checkpoint: bool = conn
.query_row(
"SELECT COUNT(*) FROM pragma_table_info('wallet') WHERE name='last_platform_sync_checkpoint'",
[],
|row| row.get::<_, i32>(0).map(|count| count > 0),
)
.unwrap_or(false);
if has_checkpoint {
conn.execute(
"ALTER TABLE wallet RENAME COLUMN last_platform_sync_checkpoint TO last_platform_sync_height",
[],
)?;
}

Ok(())
}

/// Migration: Add network indexes to high-traffic tables (version 27).
/// These tables are frequently queried with WHERE network = ? but lacked indexes.
fn add_network_indexes(&self, conn: &Connection) -> rusqlite::Result<()> {
Expand Down
13 changes: 6 additions & 7 deletions src/database/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,6 @@ impl Database {
balance: u64,
nonce: u32,
network: &Network,
_is_sync_operation: bool,
) -> rusqlite::Result<()> {
let network_str = network.to_string();
let canonical_address = Wallet::canonical_address(address, *network);
Expand Down Expand Up @@ -1128,7 +1127,7 @@ impl Database {
pub fn get_platform_sync_info(&self, seed_hash: &[u8; 32]) -> rusqlite::Result<(u64, u64)> {
let conn = self.conn.lock().unwrap();
conn.query_row(
"SELECT last_platform_full_sync, last_platform_sync_checkpoint FROM wallet WHERE seed_hash = ?",
"SELECT last_platform_full_sync, last_platform_sync_height FROM wallet WHERE seed_hash = ?",
params![seed_hash],
|row| {
let last_sync: i64 = row.get(0)?;
Expand All @@ -1146,7 +1145,7 @@ impl Database {
sync_height: u64,
) -> rusqlite::Result<()> {
self.execute(
"UPDATE wallet SET last_platform_full_sync = ?, last_platform_sync_checkpoint = ? WHERE seed_hash = ?",
"UPDATE wallet SET last_platform_full_sync = ?, last_platform_sync_height = ? WHERE seed_hash = ?",
params![last_sync_timestamp as i64, sync_height as i64, seed_hash],
)?;
Ok(())
Expand Down Expand Up @@ -1420,7 +1419,7 @@ mod tests {
assert!(info.is_none());

// Set platform address info
db.set_platform_address_info(&seed_hash, &address, 10_000_000, 5, &network, true)
db.set_platform_address_info(&seed_hash, &address, 10_000_000, 5, &network)
.expect("Failed to set platform address info");

// Retrieve it
Expand All @@ -1433,7 +1432,7 @@ mod tests {
assert_eq!(info.1, 5); // nonce

// Update it
db.set_platform_address_info(&seed_hash, &address, 20_000_000, 10, &network, true)
db.set_platform_address_info(&seed_hash, &address, 20_000_000, 10, &network)
.expect("Failed to update platform address info");

let info = db
Expand Down Expand Up @@ -1531,7 +1530,7 @@ mod tests {

// Add a single valid platform address using the helper function
let address = create_test_address(network);
db.set_platform_address_info(&seed_hash, &address, 5_000_000, 3, &network, true)
db.set_platform_address_info(&seed_hash, &address, 5_000_000, 3, &network)
.expect("Failed to set platform address info");

// Get all addresses
Expand Down Expand Up @@ -1569,7 +1568,7 @@ mod tests {
}

// Set platform address info
db.set_platform_address_info(&seed_hash, &address, 10_000_000, 5, &network, true)
db.set_platform_address_info(&seed_hash, &address, 10_000_000, 5, &network)
.expect("Failed to set platform address info");

// Verify it exists
Expand Down
22 changes: 4 additions & 18 deletions src/model/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1989,16 +1989,6 @@ impl Wallet {
.insert(address, PlatformAddressInfo { balance, nonce });
}

/// Set platform address info from a sync operation (same as `set_platform_address_info`).
pub fn set_platform_address_info_from_sync(
&mut self,
address: Address,
balance: Credits,
nonce: AddressNonce,
) {
self.set_platform_address_info(address, balance, nonce);
}

/// Get the private key for a Platform address
#[allow(clippy::result_large_err)]
pub fn get_platform_address_private_key(
Expand Down Expand Up @@ -2273,11 +2263,7 @@ impl WalletAddressProvider {
let canonical_address = Wallet::canonical_address(address, self.network);

// Update wallet with synced balances
wallet.set_platform_address_info_from_sync(
canonical_address.clone(),
funds.balance,
funds.nonce,
);
wallet.set_platform_address_info(canonical_address.clone(), funds.balance, funds.nonce);

// Also register in known_addresses and watched_addresses if not already present
if !wallet.known_addresses.contains_key(&canonical_address)
Expand Down Expand Up @@ -2859,11 +2845,11 @@ mod tests {
}

#[test]
fn test_set_platform_address_info_from_sync() {
fn test_set_platform_address_info() {
let mut wallet = test_wallet();
let addr = test_address(1);

wallet.set_platform_address_info_from_sync(addr.clone(), 500_000, 3);
wallet.set_platform_address_info(addr.clone(), 500_000, 3);

let info = wallet.platform_address_info.get(&addr).unwrap();
assert_eq!(info.balance, 500_000);
Expand All @@ -2875,7 +2861,7 @@ mod tests {
let mut wallet = test_wallet();
let addr = test_address(1);

wallet.set_platform_address_info_from_sync(addr.clone(), 500_000, 3);
wallet.set_platform_address_info(addr.clone(), 500_000, 3);

wallet.set_platform_address_info(addr.clone(), 600_000, 4);

Expand Down
Loading