diff --git a/src/records/memory/mempool/mod.rs b/src/records/memory/mempool/mod.rs index a5af7ac..9b981ab 100644 --- a/src/records/memory/mempool/mod.rs +++ b/src/records/memory/mempool/mod.rs @@ -18,7 +18,8 @@ use anyhow::{anyhow, Result}; use once_cell::sync::OnceCell; use std::fs::File; use std::io::Write; -use tokio_postgres::Client; +use tokio_postgres::types::ToSql; +use tokio_postgres::{Client, Row}; lazy_static! { pub static ref BASECOIN: String = { @@ -215,7 +216,9 @@ pub use processing::{ restore_processed_by_signatures, restore_selected_transactions_processed, spawn_processed_cleanup, }; -pub use schema::{clear_mempool, db_client, ensure_db_connection, init_db, setup_mempool}; +pub use schema::{ + clear_mempool, db_client, ensure_db_connection, init_db, pg_execute, pg_query, setup_mempool, +}; pub use selection::{ apply_selected_transaction_math, clear_selected_transaction_sql, delete_selected_transactions, select_transactions_for_block, stream_selected_transaction_originals, @@ -308,23 +311,19 @@ fn ids_for_table(batch: &SelectedMempoolBatch, table: &str) -> Vec { .collect() } -async fn mark_rows_by_ids( - client: &Client, - table: &str, - ids: &[i64], - block_number: i32, -) -> Result<()> { +async fn mark_rows_by_ids(table: &str, ids: &[i64], block_number: i32) -> Result<()> { if ids.is_empty() { return Ok(()); } let statement = format!("UPDATE {table} SET processed=true, processed_block_number=$1 WHERE id = ANY($2)"); - client.execute(&statement, &[&block_number, &ids]).await?; + let params: [&(dyn ToSql + Sync); 2] = [&block_number, &ids]; + pg_execute(&statement, ¶ms).await?; Ok(()) } -async fn unmark_rows_by_ids(client: &Client, table: &str, ids: &[i64]) -> Result<()> { +async fn unmark_rows_by_ids(table: &str, ids: &[i64]) -> Result<()> { if ids.is_empty() { return Ok(()); } @@ -332,22 +331,23 @@ async fn unmark_rows_by_ids(client: &Client, table: &str, ids: &[i64]) -> Result let statement = format!( "UPDATE {table} SET processed=false, processed_block_number=NULL WHERE id = ANY($1)" ); - client.execute(&statement, &[&ids]).await?; + let params: [&(dyn ToSql + Sync); 1] = [&ids]; + pg_execute(&statement, ¶ms).await?; Ok(()) } -async fn delete_rows(client: &Client, table: &str, ids: &[i64]) -> Result<()> { +async fn delete_rows(table: &str, ids: &[i64]) -> Result<()> { if ids.is_empty() { return Ok(()); } let statement = format!("DELETE FROM {table} WHERE id = ANY($1)"); - client.execute(&statement, &[&ids]).await?; + let params: [&(dyn ToSql + Sync); 1] = [&ids]; + pg_execute(&statement, ¶ms).await?; Ok(()) } async fn unmark_by_signatures( - client: &Client, table: &str, signature_column: &str, signatures: &[String], @@ -355,33 +355,31 @@ async fn unmark_by_signatures( let statement = format!( "UPDATE {table} SET processed=false, processed_block_number=NULL WHERE {signature_column} = ANY($1) AND processed = true" ); - Ok(client.execute(&statement, &[&signatures]).await?) + let params: [&(dyn ToSql + Sync); 1] = [&signatures]; + pg_execute(&statement, ¶ms).await } async fn delete_processed_before_or_at(block_number: u32, limit: i64) -> Result<()> { // Periodic cleanup deletes processed mempool rows in bounded batches // so long-lived nodes do not accumulate infinite processed history. - let client_handle = db_client().await?; - let client = client_handle.as_ref(); let bn = block_number as i32; - delete_processed_rows_limited(client, "transfer", bn, limit).await?; - delete_processed_rows_limited(client, "token", bn, limit).await?; - delete_processed_rows_limited(client, "issue_token", bn, limit).await?; - delete_processed_rows_limited(client, "burn", bn, limit).await?; - delete_processed_rows_limited(client, "nft", bn, limit).await?; - delete_processed_rows_limited(client, "marketing", bn, limit).await?; - delete_processed_rows_limited(client, "vanity_address", bn, limit).await?; - delete_processed_rows_limited(client, "swap", bn, limit).await?; - delete_processed_rows_limited(client, "loan_contract", bn, limit).await?; - delete_processed_rows_limited(client, "loan_payment", bn, limit).await?; - delete_processed_rows_limited(client, "collateral_claim", bn, limit).await?; + delete_processed_rows_limited("transfer", bn, limit).await?; + delete_processed_rows_limited("token", bn, limit).await?; + delete_processed_rows_limited("issue_token", bn, limit).await?; + delete_processed_rows_limited("burn", bn, limit).await?; + delete_processed_rows_limited("nft", bn, limit).await?; + delete_processed_rows_limited("marketing", bn, limit).await?; + delete_processed_rows_limited("vanity_address", bn, limit).await?; + delete_processed_rows_limited("swap", bn, limit).await?; + delete_processed_rows_limited("loan_contract", bn, limit).await?; + delete_processed_rows_limited("loan_payment", bn, limit).await?; + delete_processed_rows_limited("collateral_claim", bn, limit).await?; Ok(()) } async fn delete_processed_rows_limited( - client: &Client, table: &str, block_number: i32, limit: i64, @@ -401,5 +399,6 @@ async fn delete_processed_rows_limited( "# ); - Ok(client.execute(&statement, &[&block_number, &limit]).await?) + let params: [&(dyn ToSql + Sync); 2] = [&block_number, &limit]; + pg_execute(&statement, ¶ms).await } diff --git a/src/records/memory/mempool/processing.rs b/src/records/memory/mempool/processing.rs index 74f0af9..499907f 100644 --- a/src/records/memory/mempool/processing.rs +++ b/src/records/memory/mempool/processing.rs @@ -1,4 +1,19 @@ use super::*; +use tokio_postgres::types::ToSql; + +async fn pg_execute_block_signatures( + statement: &str, + block_number: i32, + signatures: &[String], +) -> Result { + let params: [&(dyn ToSql + Sync); 2] = [&block_number, &signatures]; + pg_execute(statement, ¶ms).await +} + +async fn pg_execute_signatures(statement: &str, signatures: &[String]) -> Result { + let params: [&(dyn ToSql + Sync); 1] = [&signatures]; + pg_execute(statement, ¶ms).await +} pub async fn mark_selected_transactions_processed( batch: &SelectedMempoolBatch, @@ -6,48 +21,26 @@ pub async fn mark_selected_transactions_processed( ) -> Result<()> { // Mark each selected mempool row as processed under the saved block // number so it can be cleaned up or restored later if needed. - let client_handle = db_client().await?; - let client = client_handle.as_ref(); let bn = block_number as i32; // Selected batches are grouped by table, then marked with one UPDATE per // table instead of touching rows one at a time. - mark_rows_by_ids(client, "transfer", &ids_for_table(batch, "transfer"), bn).await?; - mark_rows_by_ids(client, "token", &ids_for_table(batch, "token"), bn).await?; + mark_rows_by_ids("transfer", &ids_for_table(batch, "transfer"), bn).await?; + mark_rows_by_ids("token", &ids_for_table(batch, "token"), bn).await?; + mark_rows_by_ids("issue_token", &ids_for_table(batch, "issue_token"), bn).await?; + mark_rows_by_ids("burn", &ids_for_table(batch, "burn"), bn).await?; + mark_rows_by_ids("nft", &ids_for_table(batch, "nft"), bn).await?; + mark_rows_by_ids("marketing", &ids_for_table(batch, "marketing"), bn).await?; mark_rows_by_ids( - &client, - "issue_token", - &ids_for_table(batch, "issue_token"), - bn, - ) - .await?; - mark_rows_by_ids(client, "burn", &ids_for_table(batch, "burn"), bn).await?; - mark_rows_by_ids(client, "nft", &ids_for_table(batch, "nft"), bn).await?; - mark_rows_by_ids(client, "marketing", &ids_for_table(batch, "marketing"), bn).await?; - mark_rows_by_ids( - &client, "vanity_address", &ids_for_table(batch, "vanity_address"), bn, ) .await?; - mark_rows_by_ids(client, "swap", &ids_for_table(batch, "swap"), bn).await?; + mark_rows_by_ids("swap", &ids_for_table(batch, "swap"), bn).await?; + mark_rows_by_ids("loan_contract", &ids_for_table(batch, "loan_contract"), bn).await?; + mark_rows_by_ids("loan_payment", &ids_for_table(batch, "loan_payment"), bn).await?; mark_rows_by_ids( - &client, - "loan_contract", - &ids_for_table(batch, "loan_contract"), - bn, - ) - .await?; - mark_rows_by_ids( - &client, - "loan_payment", - &ids_for_table(batch, "loan_payment"), - bn, - ) - .await?; - mark_rows_by_ids( - &client, "collateral_claim", &ids_for_table(batch, "collateral_claim"), bn, @@ -60,36 +53,29 @@ pub async fn mark_selected_transactions_processed( pub async fn restore_selected_transactions_processed(batch: &SelectedMempoolBatch) -> Result<()> { // If block commit fails after selected rows were marked processed, // restore them before the chain height can acknowledge the block. - let client_handle = db_client().await?; - let client = client_handle.as_ref(); - - unmark_rows_by_ids(client, "transfer", &ids_for_table(batch, "transfer")).await?; - unmark_rows_by_ids(client, "token", &ids_for_table(batch, "token")).await?; - unmark_rows_by_ids(client, "issue_token", &ids_for_table(batch, "issue_token")).await?; - unmark_rows_by_ids(client, "burn", &ids_for_table(batch, "burn")).await?; - unmark_rows_by_ids(client, "nft", &ids_for_table(batch, "nft")).await?; - unmark_rows_by_ids(client, "marketing", &ids_for_table(batch, "marketing")).await?; + unmark_rows_by_ids("transfer", &ids_for_table(batch, "transfer")).await?; + unmark_rows_by_ids("token", &ids_for_table(batch, "token")).await?; + unmark_rows_by_ids("issue_token", &ids_for_table(batch, "issue_token")).await?; + unmark_rows_by_ids("burn", &ids_for_table(batch, "burn")).await?; + unmark_rows_by_ids("nft", &ids_for_table(batch, "nft")).await?; + unmark_rows_by_ids("marketing", &ids_for_table(batch, "marketing")).await?; unmark_rows_by_ids( - &client, "vanity_address", &ids_for_table(batch, "vanity_address"), ) .await?; - unmark_rows_by_ids(client, "swap", &ids_for_table(batch, "swap")).await?; + unmark_rows_by_ids("swap", &ids_for_table(batch, "swap")).await?; unmark_rows_by_ids( - &client, "loan_contract", &ids_for_table(batch, "loan_contract"), ) .await?; unmark_rows_by_ids( - &client, "loan_payment", &ids_for_table(batch, "loan_payment"), ) .await?; unmark_rows_by_ids( - &client, "collateral_claim", &ids_for_table(batch, "collateral_claim"), ) @@ -105,25 +91,23 @@ pub async fn restore_processed_by_signatures(signatures: &[String]) -> Result 0) } @@ -167,90 +151,88 @@ pub async fn mark_processed_by_signatures(signatures: &[String], block_number: u return Ok(()); } - let client_handle = db_client().await?; - let client = client_handle.as_ref(); let bn = block_number as i32; // Remote/synced blocks do not know local row IDs, so they mark by // transaction signatures instead. - client - .execute( - "UPDATE transfer SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE token SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE issue_token SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE burn SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE nft SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE marketing SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE vanity_address SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE swap SET processed=true, processed_block_number=$1 WHERE signature1 = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE swap SET processed=true, processed_block_number=$1 WHERE signature2 = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE loan_contract SET processed=true, processed_block_number=$1 WHERE signature1 = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE loan_contract SET processed=true, processed_block_number=$1 WHERE signature2 = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE loan_payment SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; - client - .execute( - "UPDATE collateral_claim SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", - &[&bn, &signatures], - ) - .await?; + pg_execute_block_signatures( + "UPDATE transfer SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE token SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE issue_token SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE burn SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE nft SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE marketing SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE vanity_address SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE swap SET processed=true, processed_block_number=$1 WHERE signature1 = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE swap SET processed=true, processed_block_number=$1 WHERE signature2 = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE loan_contract SET processed=true, processed_block_number=$1 WHERE signature1 = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE loan_contract SET processed=true, processed_block_number=$1 WHERE signature2 = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE loan_payment SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; + pg_execute_block_signatures( + "UPDATE collateral_claim SET processed=true, processed_block_number=$1 WHERE signature = ANY($2)", + bn, + signatures, + ) + .await?; Ok(()) } @@ -262,71 +244,47 @@ pub async fn delete_by_signatures(signatures: &[String]) -> Result<()> { return Ok(()); } - let client_handle = db_client().await?; - let client = client_handle.as_ref(); - // Failed validation removes every matching pending row no matter which // transaction table currently owns the signature. - client - .execute( - "DELETE FROM transfer WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM token WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM issue_token WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute("DELETE FROM burn WHERE signature = ANY($1)", &[&signatures]) - .await?; - client - .execute("DELETE FROM nft WHERE signature = ANY($1)", &[&signatures]) - .await?; - client - .execute( - "DELETE FROM marketing WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM vanity_address WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM swap WHERE signature1 = ANY($1) OR signature2 = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM loan_contract WHERE signature1 = ANY($1) OR signature2 = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM loan_payment WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; - client - .execute( - "DELETE FROM collateral_claim WHERE signature = ANY($1)", - &[&signatures], - ) - .await?; + pg_execute_signatures("DELETE FROM transfer WHERE signature = ANY($1)", signatures).await?; + pg_execute_signatures("DELETE FROM token WHERE signature = ANY($1)", signatures).await?; + pg_execute_signatures( + "DELETE FROM issue_token WHERE signature = ANY($1)", + signatures, + ) + .await?; + pg_execute_signatures("DELETE FROM burn WHERE signature = ANY($1)", signatures).await?; + pg_execute_signatures("DELETE FROM nft WHERE signature = ANY($1)", signatures).await?; + pg_execute_signatures( + "DELETE FROM marketing WHERE signature = ANY($1)", + signatures, + ) + .await?; + pg_execute_signatures( + "DELETE FROM vanity_address WHERE signature = ANY($1)", + signatures, + ) + .await?; + pg_execute_signatures( + "DELETE FROM swap WHERE signature1 = ANY($1) OR signature2 = ANY($1)", + signatures, + ) + .await?; + pg_execute_signatures( + "DELETE FROM loan_contract WHERE signature1 = ANY($1) OR signature2 = ANY($1)", + signatures, + ) + .await?; + pg_execute_signatures( + "DELETE FROM loan_payment WHERE signature = ANY($1)", + signatures, + ) + .await?; + pg_execute_signatures( + "DELETE FROM collateral_claim WHERE signature = ANY($1)", + signatures, + ) + .await?; Ok(()) } diff --git a/src/records/memory/mempool/schema.rs b/src/records/memory/mempool/schema.rs index ff7c009..eb20d16 100644 --- a/src/records/memory/mempool/schema.rs +++ b/src/records/memory/mempool/schema.rs @@ -31,6 +31,17 @@ pub async fn db_client() -> Result> { Ok(slot.read().await.clone()) } +fn is_closed_postgres_connection(err: &tokio_postgres::Error) -> bool { + if err.is_closed() { + return true; + } + + let message = err.to_string().to_ascii_lowercase(); + message.contains("connection closed") + || message.contains("connection reset") + || message.contains("broken pipe") +} + pub async fn reconnect_db() -> Result<()> { let client = connect_client().await?; @@ -55,6 +66,32 @@ pub async fn ensure_db_connection() -> Result<()> { reconnect_db().await } +pub async fn pg_execute(statement: &str, params: &[&(dyn ToSql + Sync)]) -> Result { + let client_handle = db_client().await?; + match client_handle.execute(statement, params).await { + Ok(count) => Ok(count), + Err(err) if is_closed_postgres_connection(&err) => { + reconnect_db().await?; + let client_handle = db_client().await?; + Ok(client_handle.execute(statement, params).await?) + } + Err(err) => Err(err.into()), + } +} + +pub async fn pg_query(statement: &str, params: &[&(dyn ToSql + Sync)]) -> Result> { + let client_handle = db_client().await?; + match client_handle.query(statement, params).await { + Ok(rows) => Ok(rows), + Err(err) if is_closed_postgres_connection(&err) => { + reconnect_db().await?; + let client_handle = db_client().await?; + Ok(client_handle.query(statement, params).await?) + } + Err(err) => Err(err.into()), + } +} + pub async fn init_db() -> Result<()> { // Initialize the shared Postgres client used by the mempool tables. if DB.get().is_some() { diff --git a/src/records/memory/mempool/selection.rs b/src/records/memory/mempool/selection.rs index 574c326..c606704 100644 --- a/src/records/memory/mempool/selection.rs +++ b/src/records/memory/mempool/selection.rs @@ -18,10 +18,8 @@ fn index_selected_wallet_transaction( pub async fn select_transactions_for_block(limit: i64) -> Result { // Pull the highest-priority unprocessed rows across all mempool // tables, keeping the original bytes for block-file streaming later. - let client_handle = db_client().await?; - let client = client_handle.as_ref(); - let rows = client - .query( + let rows = + pg_query( r#" SELECT * FROM ( SELECT @@ -1016,9 +1014,6 @@ pub async fn stream_selected_transaction_originals( } pub async fn delete_selected_transactions(batch: &SelectedMempoolBatch) -> Result<()> { - let client_handle = db_client().await?; - let client = client_handle.as_ref(); - // Each transaction kind still lives in a separate SQL table, so deletion // groups the selected IDs by table after the block has been written. let transfer_ids = ids_for_table(batch, "transfer"); @@ -1033,17 +1028,17 @@ pub async fn delete_selected_transactions(batch: &SelectedMempoolBatch) -> Resul let borrower_ids = ids_for_table(batch, "loan_payment"); let collateral_ids = ids_for_table(batch, "collateral_claim"); - delete_rows(client, "transfer", &transfer_ids).await?; - delete_rows(client, "token", &token_ids).await?; - delete_rows(client, "issue_token", &issue_token_ids).await?; - delete_rows(client, "burn", &burn_ids).await?; - delete_rows(client, "nft", &nft_ids).await?; - delete_rows(client, "marketing", &marketing_ids).await?; - delete_rows(client, "vanity_address", &vanity_ids).await?; - delete_rows(client, "swap", &swap_ids).await?; - delete_rows(client, "loan_contract", &lender_ids).await?; - delete_rows(client, "loan_payment", &borrower_ids).await?; - delete_rows(client, "collateral_claim", &collateral_ids).await?; + delete_rows("transfer", &transfer_ids).await?; + delete_rows("token", &token_ids).await?; + delete_rows("issue_token", &issue_token_ids).await?; + delete_rows("burn", &burn_ids).await?; + delete_rows("nft", &nft_ids).await?; + delete_rows("marketing", &marketing_ids).await?; + delete_rows("vanity_address", &vanity_ids).await?; + delete_rows("swap", &swap_ids).await?; + delete_rows("loan_contract", &lender_ids).await?; + delete_rows("loan_payment", &borrower_ids).await?; + delete_rows("collateral_claim", &collateral_ids).await?; Ok(()) } diff --git a/src/rpc/commands/receive_torrent.rs b/src/rpc/commands/receive_torrent.rs index be79518..d752847 100644 --- a/src/rpc/commands/receive_torrent.rs +++ b/src/rpc/commands/receive_torrent.rs @@ -256,7 +256,7 @@ pub async fn torrent_submission( } }; let torrent_hash = skein_128_hash_bytes(&torrent_bytes); - if has_recent_torrent(&torrent_hash, height).await { + if has_recent_torrent(&torrent_hash).await { // Recent-torrent cache prevents rebroadcast loops from repeatedly // staging and verifying the same metadata. let msg = "Torrent already seen.".to_string().as_bytes().to_vec(); diff --git a/src/startup/daemonize.rs b/src/startup/daemonize.rs index 2f492e4..16ceba9 100644 --- a/src/startup/daemonize.rs +++ b/src/startup/daemonize.rs @@ -232,8 +232,8 @@ pub fn handle_control_command() -> Result> { Ok(false) } -#[cfg(not(unix))] -pub fn install_shutdown_cleanup(_db: crate::sled::Db) {} +#[cfg(not(unix))] +pub fn install_shutdown_cleanup() {} #[cfg(not(unix))] pub fn remove_registered_pid_file() {} diff --git a/src/startup/node_runtime.rs b/src/startup/node_runtime.rs index 1e425ce..d3661e5 100644 --- a/src/startup/node_runtime.rs +++ b/src/startup/node_runtime.rs @@ -119,7 +119,10 @@ pub async fn run_unlocked_node(wallet: Arc, install_shutdown: bool) -> R if install_shutdown { // Console/daemon mode owns signal cleanup; Windows service shutdown is handled separately. + #[cfg(unix)] install_shutdown_cleanup(db.clone()); + #[cfg(not(unix))] + install_shutdown_cleanup(); } if let Err(e) = clear_ip_scores(&db) { diff --git a/src/startup/windows_service.rs b/src/startup/windows_service.rs index 8ecd7b3..7deb86f 100644 --- a/src/startup/windows_service.rs +++ b/src/startup/windows_service.rs @@ -419,7 +419,9 @@ fn stop_service_if_running( } #[cfg(windows)] -fn contractless_service_main(_arguments: Vec) { +fn contractless_service_main(arguments: Vec) { + drop(arguments); + // SCM enters here instead of the normal console main path. if let Err(err) = run_service() { eprintln!("Windows service error: {err}"); diff --git a/src/torrent/torrenting_system/torrent_cache.rs b/src/torrent/torrenting_system/torrent_cache.rs index 9bbfa8d..89a9dc0 100644 --- a/src/torrent/torrenting_system/torrent_cache.rs +++ b/src/torrent/torrenting_system/torrent_cache.rs @@ -8,7 +8,7 @@ lazy_static! { Mutex::new(HashMap::new()); } -pub async fn has_recent_torrent(hash: &str, _block_height: u32) -> bool { +pub async fn has_recent_torrent(hash: &str) -> bool { // The hash alone identifies duplicate torrent bytes in the recent in-memory cache. let map = RECENT_TORRENTS.lock().await; map.contains_key(hash) diff --git a/src/verifications/async_funcs/transactions.rs b/src/verifications/async_funcs/transactions.rs index 6062f28..8b64da6 100644 --- a/src/verifications/async_funcs/transactions.rs +++ b/src/verifications/async_funcs/transactions.rs @@ -73,7 +73,7 @@ async fn verify_transaction( balance_tracker: Arc>, ) -> Result { if let Transaction::Genesis(genesis_tx) = &transaction { - match genesis_tx.verify(miner, db).await { + match genesis_tx.verify().await { Ok(value) => { reserve_verified_transaction(db, &transaction, balance_tracker).await?; return Ok(value); diff --git a/src/verifications/async_funcs/verify_genesis.rs b/src/verifications/async_funcs/verify_genesis.rs index 4ab580b..297afdc 100644 --- a/src/verifications/async_funcs/verify_genesis.rs +++ b/src/verifications/async_funcs/verify_genesis.rs @@ -1,9 +1,8 @@ use crate::blocks::genesis::GenesisTransaction; use crate::common::check_genesis::genesis_checkup; -use crate::sled::Db; impl GenesisTransaction { - pub async fn verify(&self, _miner: String, db: &Db) -> Result { + pub async fn verify(&self) -> Result { // Genesis is pinned to a fixed message and only valid before the // chain already has a committed genesis block. let msg = &self.unsigned.message; @@ -11,7 +10,6 @@ impl GenesisTransaction { return Err("Not a valid Genesis block").map_err(|s| s.to_string())?; } - let _ = db; if genesis_checkup().await { return Err("Genesis block already exists.".to_string()); } diff --git a/src/wallets/create_keys.rs b/src/wallets/create_keys.rs index 2d273f8..2e0af26 100644 --- a/src/wallets/create_keys.rs +++ b/src/wallets/create_keys.rs @@ -3,7 +3,7 @@ use crate::FnDsaKeyPair; use crate::{decode, encode}; impl Wallet { - pub fn generate_keypair(_network_byte: u8) -> (Vec, String) { + pub fn generate_keypair() -> (Vec, String) { loop { // Generate a new FN-DSA key pair using the wallet security parameter. let keypair = FnDsaKeyPair::generate(Self::FN_DSA_LOGN) @@ -25,9 +25,6 @@ impl Wallet { } pub fn regenerate_public_key(private_key_hex: &str) -> Result, String> { - // Regenerated public keys always use the network selected at compile time. - let network_byte = Self::current_network_byte(); - // Decode the stored private key from its wallet hex representation. let private_key_bytes = match decode(private_key_hex) { Ok(bytes) => bytes, @@ -47,7 +44,6 @@ impl Wallet { let keypair = FnDsaKeyPair::from_private_key(&private_key_bytes) .map_err(|e| format!("Failed to decode the provided FN-DSA private key: {e}"))?; - let _ = network_byte; let public_key_bytes = keypair.public_key().to_vec(); if !Self::has_valid_public_key_bytes(&public_key_bytes) { return Err("FN-DSA public key does not satisfy this network's wallet key rule." diff --git a/src/wallets/create_wallet.rs b/src/wallets/create_wallet.rs index 1677726..2e6ee27 100644 --- a/src/wallets/create_wallet.rs +++ b/src/wallets/create_wallet.rs @@ -5,9 +5,9 @@ use crate::Path; use crate::{create_img, encrypts}; impl Wallet { - pub fn create_wallet(&self, network_byte: u8) -> Wallet { + pub fn create_wallet(&self) -> Wallet { // Generate a fresh FN-DSA key pair for the selected network. - let (public_key, private_key) = Self::generate_keypair(network_byte); + let (public_key, private_key) = Self::generate_keypair(); // Hash the public key body into the fixed 22-byte short-address format. let short_address_bytes = Self::public_key_bytes_to_short_address_bytes(&public_key) @@ -77,7 +77,7 @@ impl Wallet { }; // Generate the wallet for the active network. - let wallet = Wallet::create_wallet(&wallet, Self::current_network_byte()); + let wallet = Wallet::create_wallet(&wallet); // Save the generated wallet file before loading and decrypting it through the normal path. wallet.saved.save_the_wallet(wallet_path).await;