From 8d0007eb1adcedce8ea87b877694f1f8c497d71a Mon Sep 17 00:00:00 2001 From: viraladmin <00purple@gmail.com> Date: Tue, 21 Jul 2026 10:47:28 -0600 Subject: [PATCH] fixed bug in prevalidation mempool lookup --- README.md | 4 +- src/blocks/block.rs | 4 + src/common/types.rs | 36 +++++ src/miner/genesis.rs | 1 + src/miner/mining.rs | 1 + src/records/memory/mempool/lookups.rs | 39 +++--- src/records/memory/mempool/mod.rs | 7 +- .../unpack_block/load_by_binary_data.rs | 4 + .../unpack_block/load_by_block_number.rs | 4 + src/rpc/commands/tx_submit.rs | 24 ++++ .../async_funcs/checks/block_balance.rs | 23 +--- src/verifications/async_funcs/checks/mod.rs | 1 - src/verifications/async_funcs/transactions.rs | 126 +++++++++++++----- src/verifications/async_funcs/verify_block.rs | 17 ++- .../async_funcs/verify_borrower.rs | 7 - src/verifications/async_funcs/verify_burn.rs | 7 - .../async_funcs/verify_collateral.rs | 22 ++- .../async_funcs/verify_create_nft.rs | 7 - .../async_funcs/verify_create_token.rs | 8 -- .../async_funcs/verify_delete_key.rs | 5 - .../async_funcs/verify_issue_token.rs | 8 -- .../async_funcs/verify_lender.rs | 8 -- .../async_funcs/verify_marketing.rs | 7 - .../async_funcs/verify_storage_key.rs | 7 - .../async_funcs/verify_storage_values.rs | 16 --- src/verifications/async_funcs/verify_swap.rs | 7 - .../async_funcs/verify_transfer.rs | 7 - .../async_funcs/verify_vanity.rs | 7 - src/verifications/verification_service.rs | 5 +- src/verifications/verification_types.rs | 10 +- 30 files changed, 230 insertions(+), 199 deletions(-) diff --git a/README.md b/README.md index 1ea1528..c845653 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ GPT-5.6 SOL assisted with: - Hardening network-map monitoring and connection-state handling. - Implementing and reviewing on-chain data-storage transaction support. - Integrating data storage, address data, NFTs, loans, assets, and transaction history into the GUI wallet. -- Improving GUI wallet cache synchronization, cache deletion safety, and Windows file-access coordination. +- Improving [GUI wallet](https://contractless.dev/contractless/Contractless-GUI-Wallet) cache synchronization, cache deletion safety, and Windows file-access coordination. - Reviewing Rust transaction validation, mempool handling, block saving, and chain-reorganization paths. - Identifying behavioral inconsistencies between local wallet caches and RPC responses. - Expanding and reorganizing user documentation for installation, wallets, transactions, validation tools, loans, swaps, NFTs, fees, and data storage. @@ -90,5 +90,3 @@ Use the release package that matches your operating system and follow the matchi ## Current Status Contractless is still under active testnet development. Interfaces, transaction tools, docs, and node behavior may continue to change while the chain is tested. - -If you are interested in running a testnet node, start with the installation guide for your operating system, then review the configuration and wallet tools documentation. diff --git a/src/blocks/block.rs b/src/blocks/block.rs index 3513bbc..6d4ba6f 100644 --- a/src/blocks/block.rs +++ b/src/blocks/block.rs @@ -50,6 +50,10 @@ pub struct VrfBlock { pub struct Block { pub vrf_block: VrfBlock, pub transactions: Vec, + // Exact transaction slices are retained for downloaded/stored blocks so + // mempool reuse can compare bytes without serializing or hashing again. + #[serde(skip)] + pub original_transactions: Vec>, } impl UnminedBlock { diff --git a/src/common/types.rs b/src/common/types.rs index 8e09f83..753deab 100644 --- a/src/common/types.rs +++ b/src/common/types.rs @@ -131,3 +131,39 @@ pub enum Transaction { StorageI128(StorageI128), DeleteKey(DeleteKey), } + +impl Transaction { + // Return the signature used by the indexed mempool lookup. Two-party + // transactions use the final signer because valid submitted swaps and + // loan contracts must already contain both signatures. + pub fn mempool_signature(&self) -> Option<&str> { + match self { + Transaction::Genesis(_) | Transaction::Rewards(_) => None, + Transaction::Transfer(tx) => Some(&tx.signature), + Transaction::Burn(tx) => Some(&tx.signature), + Transaction::Token(tx) => Some(&tx.signature), + Transaction::IssueToken(tx) => Some(&tx.signature), + Transaction::Nft(tx) => Some(&tx.signature), + Transaction::Marketing(tx) => Some(&tx.signature), + Transaction::Swap(tx) => Some(&tx.signature2), + Transaction::Lender(tx) => Some(&tx.signature2), + Transaction::Borrower(tx) => Some(&tx.signature), + Transaction::Collateral(tx) => Some(&tx.signature), + Transaction::Vanity(tx) => Some(&tx.signature), + Transaction::StorageKey(tx) => Some(&tx.signature), + Transaction::StorageBool(tx) => Some(&tx.signature), + Transaction::StorageU8(tx) => Some(&tx.signature), + Transaction::StorageU16(tx) => Some(&tx.signature), + Transaction::StorageU32(tx) => Some(&tx.signature), + Transaction::StorageU64(tx) => Some(&tx.signature), + Transaction::StorageU128(tx) => Some(&tx.signature), + Transaction::StorageString(tx) => Some(&tx.signature), + Transaction::StorageI8(tx) => Some(&tx.signature), + Transaction::StorageI16(tx) => Some(&tx.signature), + Transaction::StorageI32(tx) => Some(&tx.signature), + Transaction::StorageI64(tx) => Some(&tx.signature), + Transaction::StorageI128(tx) => Some(&tx.signature), + Transaction::DeleteKey(tx) => Some(&tx.signature), + } + } +} diff --git a/src/miner/genesis.rs b/src/miner/genesis.rs index 3d493f2..46b23d8 100644 --- a/src/miner/genesis.rs +++ b/src/miner/genesis.rs @@ -133,6 +133,7 @@ async fn create_genesis_block( let block = Block { vrf_block, transactions: vec![Transaction::Genesis(signed_genesis_transaction.clone())], + original_transactions: Vec::new(), }; // Reuse normal block verification before saving so genesis diff --git a/src/miner/mining.rs b/src/miner/mining.rs index dd8e258..63ff9fe 100644 --- a/src/miner/mining.rs +++ b/src/miner/mining.rs @@ -285,6 +285,7 @@ pub async fn mine_block_internal( let new_block = Block { vrf_block, transactions: vec![Transaction::Rewards(rewards_transaction)], + original_transactions: Vec::new(), }; // Return only candidates that pass local verification. diff --git a/src/records/memory/mempool/lookups.rs b/src/records/memory/mempool/lookups.rs index f35496a..782aa4e 100644 --- a/src/records/memory/mempool/lookups.rs +++ b/src/records/memory/mempool/lookups.rs @@ -1,36 +1,37 @@ use super::*; -pub async fn signature_exists(signature: &str, hash: &str) -> Result { +pub async fn exact_transaction_exists(signature: &str, original: &[u8]) -> Result { let client_handle = db_client().await?; let client = client_handle.as_ref(); - // Check every mempool table because the signature column names differ by - // transaction type, especially for two-party swaps and loans. + // Use the indexed signature to locate a candidate row, then compare the + // complete serialized transaction so every byte must match what was + // previously validated and admitted to the mempool. let row = client .query_one( r#" SELECT CASE - WHEN EXISTS (SELECT 1 FROM transfer a WHERE a.signature = $1 AND a.hash = $2 AND a.processed = false) - OR EXISTS (SELECT 1 FROM token b WHERE b.signature = $1 AND b.hash = $2 AND b.processed = false) - OR EXISTS (SELECT 1 FROM issue_token c WHERE c.signature = $1 AND c.hash = $2 AND c.processed = false) - OR EXISTS (SELECT 1 FROM burn d WHERE d.signature = $1 AND d.hash = $2 AND d.processed = false) - OR EXISTS (SELECT 1 FROM nft e WHERE e.signature = $1 AND e.hash = $2 AND e.processed = false) - OR EXISTS (SELECT 1 FROM marketing f WHERE f.signature = $1 AND f.hash = $2 AND f.processed = false) - OR EXISTS (SELECT 1 FROM vanity_address va WHERE va.signature = $1 AND va.hash = $2 AND va.processed = false) - OR EXISTS (SELECT 1 FROM swap g WHERE g.signature1 = $1 AND g.hash = $2 AND g.processed = false) - OR EXISTS (SELECT 1 FROM swap h WHERE h.signature2 = $1 AND h.hash = $2 AND h.processed = false) - OR EXISTS (SELECT 1 FROM loan_contract i WHERE i.signature1 = $1 AND i.hash = $2 AND i.processed = false) - OR EXISTS (SELECT 1 FROM loan_contract j WHERE j.signature2 = $1 AND j.hash = $2 AND j.processed = false) - OR EXISTS (SELECT 1 FROM loan_payment k WHERE k.signature = $1 AND k.hash = $2 AND k.processed = false) - OR EXISTS (SELECT 1 FROM collateral_claim l WHERE l.signature = $1 AND l.hash = $2 AND l.processed = false) - OR EXISTS (SELECT 1 FROM storage_key sk WHERE sk.signature = $1 AND sk.hash = $2 AND sk.processed = false) - OR EXISTS (SELECT 1 FROM storage_value sv WHERE sv.signature = $1 AND sv.hash = $2 AND sv.processed = false) + WHEN EXISTS (SELECT 1 FROM transfer a WHERE a.signature = $1 AND a.original = $2 AND a.processed = false) + OR EXISTS (SELECT 1 FROM token b WHERE b.signature = $1 AND b.original = $2 AND b.processed = false) + OR EXISTS (SELECT 1 FROM issue_token c WHERE c.signature = $1 AND c.original = $2 AND c.processed = false) + OR EXISTS (SELECT 1 FROM burn d WHERE d.signature = $1 AND d.original = $2 AND d.processed = false) + OR EXISTS (SELECT 1 FROM nft e WHERE e.signature = $1 AND e.original = $2 AND e.processed = false) + OR EXISTS (SELECT 1 FROM marketing f WHERE f.signature = $1 AND f.original = $2 AND f.processed = false) + OR EXISTS (SELECT 1 FROM vanity_address va WHERE va.signature = $1 AND va.original = $2 AND va.processed = false) + OR EXISTS (SELECT 1 FROM swap g WHERE g.signature1 = $1 AND g.original = $2 AND g.processed = false) + OR EXISTS (SELECT 1 FROM swap h WHERE h.signature2 = $1 AND h.original = $2 AND h.processed = false) + OR EXISTS (SELECT 1 FROM loan_contract i WHERE i.signature1 = $1 AND i.original = $2 AND i.processed = false) + OR EXISTS (SELECT 1 FROM loan_contract j WHERE j.signature2 = $1 AND j.original = $2 AND j.processed = false) + OR EXISTS (SELECT 1 FROM loan_payment k WHERE k.signature = $1 AND k.original = $2 AND k.processed = false) + OR EXISTS (SELECT 1 FROM collateral_claim l WHERE l.signature = $1 AND l.original = $2 AND l.processed = false) + OR EXISTS (SELECT 1 FROM storage_key sk WHERE sk.signature = $1 AND sk.original = $2 AND sk.processed = false) + OR EXISTS (SELECT 1 FROM storage_value sv WHERE sv.signature = $1 AND sv.original = $2 AND sv.processed = false) THEN 1 ELSE 0 END AS signature_found; "#, - &[&signature, &hash], + &[&signature, &original], ) .await?; diff --git a/src/records/memory/mempool/mod.rs b/src/records/memory/mempool/mod.rs index 905fa5c..f609c09 100644 --- a/src/records/memory/mempool/mod.rs +++ b/src/records/memory/mempool/mod.rs @@ -225,9 +225,10 @@ mod schema; mod selection; pub use lookups::{ - get_basecoin_balance, get_coin_balance, get_pending_payments_for_contract, largest_fee, - latest_pending_txids_by_address, pending_transaction_by_txid, signature_exists, - total_transactions, transaction_by_signature, transactions_by_address, + exact_transaction_exists, get_basecoin_balance, get_coin_balance, + get_pending_payments_for_contract, largest_fee, latest_pending_txids_by_address, + pending_transaction_by_txid, total_transactions, transaction_by_signature, + transactions_by_address, }; pub use processing::{ delete_by_signatures, delete_unprocessed_by_address, mark_processed_by_signatures, diff --git a/src/records/unpack_block/load_by_binary_data.rs b/src/records/unpack_block/load_by_binary_data.rs index 8c8ce21..78b8c3b 100644 --- a/src/records/unpack_block/load_by_binary_data.rs +++ b/src/records/unpack_block/load_by_binary_data.rs @@ -64,10 +64,12 @@ pub async fn load_block_from_binary(binary_data: &[u8]) -> Result .map_err(|e| e.to_string())?; let mut i = VRF_BLOCK_BYTES; let mut transactions: Vec = Vec::new(); + let mut original_transactions = Vec::new(); while i < binary_data.len() { // Each transaction starts with its type byte, followed by the fixed-length body // defined for that transaction family. + let transaction_start = i; let txtype = binary_data[i]; i += 1; let body_len = transaction_body_len(txtype)?; @@ -332,11 +334,13 @@ pub async fn load_block_from_binary(binary_data: &[u8]) -> Result } }; transactions.push(transaction); + original_transactions.push(binary_data[transaction_start..i].to_vec()); } let block = Block { vrf_block, transactions, + original_transactions, }; Ok(block) diff --git a/src/records/unpack_block/load_by_block_number.rs b/src/records/unpack_block/load_by_block_number.rs index 745a724..ce310d1 100644 --- a/src/records/unpack_block/load_by_block_number.rs +++ b/src/records/unpack_block/load_by_block_number.rs @@ -92,10 +92,12 @@ pub async fn load_block(block_number: u32) -> Result { .map_err(|e| e.to_string())?; let mut i = VRF_BLOCK_BYTES; let mut transactions: Vec = Vec::new(); + let mut original_transactions = Vec::new(); while i < binary_data.len() { // Each stored transaction begins with its type byte, followed by the fixed-size // body for that transaction family. + let transaction_start = i; let txtype = binary_data[i]; i += 1; let body_len = transaction_body_len(txtype)?; @@ -349,11 +351,13 @@ pub async fn load_block(block_number: u32) -> Result { } }; transactions.push(transaction); + original_transactions.push(binary_data[transaction_start..i].to_vec()); } let block = Block { vrf_block, transactions, + original_transactions, }; Ok(block) diff --git a/src/rpc/commands/tx_submit.rs b/src/rpc/commands/tx_submit.rs index 302b627..c96ad02 100644 --- a/src/rpc/commands/tx_submit.rs +++ b/src/rpc/commands/tx_submit.rs @@ -22,13 +22,16 @@ use crate::common::types::{ STORAGE_STRING_TYPE, STORAGE_U128_TYPE, STORAGE_U16_TYPE, STORAGE_U32_TYPE, STORAGE_U64_TYPE, STORAGE_U8_TYPE, SWAP_TYPE, TRANSFER_TYPE, VANITY_ADDRESS_TYPE, }; +use crate::encode; use crate::records::memory::connections::get_client_type_from_memory; use crate::records::memory::enums::ClientType; +use crate::records::memory::mempool::exact_transaction_exists; use crate::records::memory::response_channels::{reserve_transient_entry_with_context, Command}; use crate::rpc::command_maps::RPC_SUBMIT_TRANSACTION; use crate::rpc::responses::RpcResponse; use crate::sled::Db; use crate::torrent::torrenting_system::get_nodes::get_live_node_broadcast_peers; +use crate::wallets::structures::Wallet; use crate::Arc; use crate::Mutex; use crate::OnceLock; @@ -124,6 +127,27 @@ pub async fn save_and_submit( // the declared transaction type. // In each branch, a non-empty verifier response means the transaction // already exists in the mempool and should not be rebroadcast. + // All submitted transaction families end with their final signature. + // Use that indexed signature to locate a candidate mempool row, then + // require the complete original bytes to match before reporting a duplicate. + if tx.len() >= Wallet::SIGNATURE_LENGTH { + let signature = encode(&tx[tx.len() - Wallet::SIGNATURE_LENGTH..]); + let mut original = Vec::with_capacity(1 + tx.len()); + original.push(txtype); + original.extend_from_slice(&tx); + match exact_transaction_exists(&signature, &original).await { + Ok(true) => { + return RpcResponse::Binary( + b"successful_broadcast: false already_in_mempool".to_vec(), + ); + } + Ok(false) => {} + Err(err) => { + return RpcResponse::Binary(format!("error: {err}").into_bytes()); + } + } + } + match txtype { TRANSFER_TYPE => match TransferTransaction::from_bytes(txtype, &tx).await { Ok(transfer) => match transfer.verify(db).await { diff --git a/src/verifications/async_funcs/checks/block_balance.rs b/src/verifications/async_funcs/checks/block_balance.rs index 6fe1daf..563b2a6 100644 --- a/src/verifications/async_funcs/checks/block_balance.rs +++ b/src/verifications/async_funcs/checks/block_balance.rs @@ -4,9 +4,7 @@ use crate::common::nft_assets::nft_asset_name; use crate::common::types::Transaction; use crate::decode; use crate::records::balance_sheet::get_wallet_balance::get_balance_with_db; -use crate::records::memory::mempool::{ - get_basecoin_balance, get_coin_balance, signature_exists, BASECOIN, -}; +use crate::records::memory::mempool::{get_basecoin_balance, get_coin_balance, BASECOIN}; use crate::rpc::commands::transaction_by_txid::request_transaction_by_txid; use crate::rpc::responses::RpcResponse; use crate::sled::Db; @@ -172,23 +170,6 @@ fn add_amount_to_total( Ok(()) } -async fn transaction_is_pending(view: &TransactionBalanceView) -> Result { - for signature in &view.signatures { - if signature.is_empty() { - continue; - } - - if signature_exists(signature, &view.hash) - .await - .map_err(|err| err.to_string())? - { - return Ok(true); - } - } - - Ok(false) -} - async fn loan_contract_for_hash( db: &Db, contract_hash: &str, @@ -678,13 +659,13 @@ async fn pending_reserved_amount(db: &Db, address: &str, coin: &str) -> Result Result { let view = transaction_balance_view(db, transaction).await?; if view.check_saved_txid && saved_txid_exists(db, &view.hash)? { return Err("This transaction already exists.".to_string()); } - let already_reserved_in_mempool = transaction_is_pending(&view).await?; let loan_payment = if let Transaction::Borrower(tx) = transaction { let payment = &tx.unsigned_contract_payment; let contract = loan_contract_for_hash(db, &payment.contract_hash).await?; diff --git a/src/verifications/async_funcs/checks/mod.rs b/src/verifications/async_funcs/checks/mod.rs index 0fa89be..ea64c0b 100644 --- a/src/verifications/async_funcs/checks/mod.rs +++ b/src/verifications/async_funcs/checks/mod.rs @@ -1,6 +1,5 @@ // These lower-level checks are reused by the higher-level async verification routines. pub mod balance_check; pub mod block_balance; -pub mod mempool_check; pub mod time_checks; pub mod verify_db; diff --git a/src/verifications/async_funcs/transactions.rs b/src/verifications/async_funcs/transactions.rs index dbec3dc..99b8c1b 100644 --- a/src/verifications/async_funcs/transactions.rs +++ b/src/verifications/async_funcs/transactions.rs @@ -1,9 +1,11 @@ use crate::common::types::Transaction; +use crate::records::memory::mempool::exact_transaction_exists; use crate::sled::Db; use crate::verifications::async_funcs::checks::block_balance::{ prepare_transaction_balance_reservation, BlockBalanceTracker, }; use crate::verifications::sync_funcs::transaction_verify_loop::COUNTER; +use crate::verifications::verification_types::VerifiableTransaction; use crate::Arc; use crate::AtomicBool; use crate::AtomicOrdering; @@ -11,7 +13,7 @@ use crate::Mutex; pub async fn verify_transactions( miner: String, - transactions: Vec, + transactions: Vec, db: &Db, stop_flag: Arc, balance_tracker: Arc>, @@ -78,15 +80,41 @@ pub async fn verify_transactions( // normalize failures into a consistent error string. async fn verify_transaction( miner: String, - transaction: Transaction, + verifiable: VerifiableTransaction, db: &Db, balance_tracker: Arc>, block_timestamp: u32, ) -> Result { + let transaction = verifiable.transaction; + let already_in_mempool = match ( + transaction.mempool_signature(), + verifiable.original.as_deref(), + ) { + (Some(signature), Some(original)) if !signature.is_empty() => { + exact_transaction_exists(signature, original) + .await + .map_err(|err| err.to_string())? + } + _ => false, + }; + + // Exact mempool bytes prove ordinary transactions already passed their + // complete type-specific validation. Collateral claims remain time-aware + // and must recheck their schedule against the containing block timestamp. + if already_in_mempool && !matches!(&transaction, Transaction::Collateral(_)) { + let signature = transaction + .mempool_signature() + .unwrap_or_default() + .to_string(); + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool).await?; + return Ok(signature); + } + if let Transaction::Genesis(genesis_tx) = &transaction { match genesis_tx.verify().await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -105,7 +133,13 @@ async fn verify_transaction( "You cannot include more than 1 reward in a mined block.".to_string() ); } else { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction( + db, + &transaction, + balance_tracker, + already_in_mempool, + ) + .await?; return Ok(value); } } @@ -117,7 +151,8 @@ async fn verify_transaction( if let Transaction::Transfer(transfer_tx) = &transaction { match transfer_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -128,7 +163,8 @@ async fn verify_transaction( if let Transaction::Burn(burn_tx) = &transaction { match burn_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -139,7 +175,8 @@ async fn verify_transaction( if let Transaction::Token(create_token_tx) = &transaction { match create_token_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -152,7 +189,8 @@ async fn verify_transaction( if let Transaction::IssueToken(issue_token_tx) = &transaction { match issue_token_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -165,7 +203,8 @@ async fn verify_transaction( if let Transaction::Nft(create_nft_tx) = &transaction { match create_nft_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -178,7 +217,8 @@ async fn verify_transaction( if let Transaction::Marketing(marketing_tx) = &transaction { match marketing_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -191,7 +231,8 @@ async fn verify_transaction( if let Transaction::Swap(swap_tx) = &transaction { match swap_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -202,7 +243,8 @@ async fn verify_transaction( if let Transaction::Lender(loan_creation_tx) = &transaction { match loan_creation_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -215,7 +257,8 @@ async fn verify_transaction( if let Transaction::Borrower(loan_payment_tx) = &transaction { match loan_payment_tx.verify_for_block(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -226,9 +269,13 @@ async fn verify_transaction( } } if let Transaction::Collateral(collateral_claim_tx) = &transaction { - match collateral_claim_tx.verify_at(db, block_timestamp).await { + match collateral_claim_tx + .verify_at(db, block_timestamp, already_in_mempool) + .await + { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -241,7 +288,8 @@ async fn verify_transaction( if let Transaction::Vanity(vanity_tx) = &transaction { match vanity_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -254,7 +302,8 @@ async fn verify_transaction( if let Transaction::StorageKey(storage_key_tx) = &transaction { match storage_key_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -267,7 +316,8 @@ async fn verify_transaction( if let Transaction::StorageBool(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -280,7 +330,8 @@ async fn verify_transaction( if let Transaction::StorageU8(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -293,7 +344,8 @@ async fn verify_transaction( if let Transaction::StorageU16(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -306,7 +358,8 @@ async fn verify_transaction( if let Transaction::StorageU32(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -319,7 +372,8 @@ async fn verify_transaction( if let Transaction::StorageU64(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -332,7 +386,8 @@ async fn verify_transaction( if let Transaction::StorageU128(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -345,7 +400,8 @@ async fn verify_transaction( if let Transaction::StorageString(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -358,7 +414,8 @@ async fn verify_transaction( if let Transaction::StorageI8(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -371,7 +428,8 @@ async fn verify_transaction( if let Transaction::StorageI16(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -384,7 +442,8 @@ async fn verify_transaction( if let Transaction::StorageI32(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -397,7 +456,8 @@ async fn verify_transaction( if let Transaction::StorageI64(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -410,7 +470,8 @@ async fn verify_transaction( if let Transaction::StorageI128(storage_tx) = &transaction { match storage_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -423,7 +484,8 @@ async fn verify_transaction( if let Transaction::DeleteKey(delete_key_tx) = &transaction { match delete_key_tx.verify(db).await { Ok(value) => { - reserve_verified_transaction(db, &transaction, balance_tracker).await?; + reserve_verified_transaction(db, &transaction, balance_tracker, already_in_mempool) + .await?; return Ok(value); } Err(err) => { @@ -443,10 +505,12 @@ async fn reserve_verified_transaction( db: &Db, transaction: &Transaction, balance_tracker: Arc>, + already_in_mempool: bool, ) -> Result<(), String> { // Build the balance reservation while this worker still has the // transaction in hand, then lock only the shared in-block totals. - let reservation = prepare_transaction_balance_reservation(db, transaction).await?; + let reservation = + prepare_transaction_balance_reservation(db, transaction, already_in_mempool).await?; let mut tracker = balance_tracker.lock().await; tracker.reserve(reservation) } diff --git a/src/verifications/async_funcs/verify_block.rs b/src/verifications/async_funcs/verify_block.rs index 74fa2ad..acb3c63 100644 --- a/src/verifications/async_funcs/verify_block.rs +++ b/src/verifications/async_funcs/verify_block.rs @@ -1,7 +1,6 @@ use crate::blocks::block::{Block, UnminedBlock}; use crate::common::binary_conversions::hex_to_u64; use crate::common::check_genesis::genesis_checkup; -use crate::common::types::Transaction; use crate::encode; use crate::miner::fairness::fairness_difficulty; use crate::records::block_height::get_block_height::get_height; @@ -13,6 +12,7 @@ use crate::records::unpack_block::unpack_header::load_block_header; use crate::records::wallet_registry::resolve_pubkey_from_short_address; use crate::sled::Db; use crate::verifications::verification_service::VerificationService; +use crate::verifications::verification_types::VerifiableTransaction; use crate::wallets::structures::Wallet; use crate::Arc; use crate::Utc; @@ -97,9 +97,20 @@ impl Block { .await?; } + let transactions = self + .transactions + .iter() + .cloned() + .enumerate() + .map(|(index, transaction)| VerifiableTransaction { + transaction, + original: self.original_transactions.get(index).cloned(), + }) + .collect(); + let results = Self::send_transactions_to_validate( miner.to_string(), - self.transactions.clone(), + transactions, db.clone(), verification_service, timestamp, @@ -181,7 +192,7 @@ impl Block { async fn send_transactions_to_validate( miner: String, - transactions: Vec, + transactions: Vec, db: crate::sled::Db, verification_service: Arc, block_timestamp: u32, diff --git a/src/verifications/async_funcs/verify_borrower.rs b/src/verifications/async_funcs/verify_borrower.rs index 492e38c..2ee3086 100644 --- a/src/verifications/async_funcs/verify_borrower.rs +++ b/src/verifications/async_funcs/verify_borrower.rs @@ -9,7 +9,6 @@ use crate::rpc::commands::transaction_by_txid::request_transaction_by_txid; use crate::rpc::responses::RpcResponse; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::verifications::async_funcs::total_payments::get_total_payments; use crate::wallets::structures::Wallet; @@ -32,12 +31,6 @@ impl ContractPaymentTransaction { let hash = self.unsigned_contract_payment.hash().await; let signature = &self.signature; - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. - if memcheck(signature, &hash).await { - return Ok(signature.to_string()); - } - // Loan payments must come from a valid wallet address and carry a // valid signature from the payer. let address = &self.unsigned_contract_payment.address; diff --git a/src/verifications/async_funcs/verify_burn.rs b/src/verifications/async_funcs/verify_burn.rs index 62a46e9..53834f8 100644 --- a/src/verifications/async_funcs/verify_burn.rs +++ b/src/verifications/async_funcs/verify_burn.rs @@ -9,7 +9,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::{ db_bytes_verification, db_hex_verification, }; @@ -21,12 +20,6 @@ impl BurnTransaction { pub async fn verify(&self, db: &Db) -> Result { let hash = self.unsigned_burn.hash().await; - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. - if memcheck(&self.signature, &hash).await { - return Ok(self.signature.clone()); - } - // Burn transactions are anchored to the sender wallet and the // signed burn payload before any asset-specific rules apply. if !Wallet::short_address_validation(&self.unsigned_burn.address) { diff --git a/src/verifications/async_funcs/verify_collateral.rs b/src/verifications/async_funcs/verify_collateral.rs index 265e8f2..acec5bc 100644 --- a/src/verifications/async_funcs/verify_collateral.rs +++ b/src/verifications/async_funcs/verify_collateral.rs @@ -10,7 +10,6 @@ use crate::rpc::commands::transaction_by_txid::request_transaction_by_txid; use crate::rpc::responses::RpcResponse; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::verifications::async_funcs::total_payments::get_total_payments; use crate::wallets::structures::Wallet; @@ -19,19 +18,25 @@ use crate::{decode, encode}; impl CollateralClaimTransaction { pub async fn verify(&self, db: &Db) -> Result { - self.verify_internal(db, Utc::now().timestamp() as u32, true) + self.verify_internal(db, Utc::now().timestamp() as u32, false) .await } - pub async fn verify_at(&self, db: &Db, as_of_timestamp: u32) -> Result { - self.verify_internal(db, as_of_timestamp, false).await + pub async fn verify_at( + &self, + db: &Db, + as_of_timestamp: u32, + already_in_mempool: bool, + ) -> Result { + self.verify_internal(db, as_of_timestamp, already_in_mempool) + .await } async fn verify_internal( &self, db: &Db, as_of_timestamp: u32, - allow_mempool_short_circuit: bool, + already_in_mempool: bool, ) -> Result { let hash = self.unsigned_collateral_claim.hash().await; let signature = &self.signature; @@ -42,13 +47,6 @@ impl CollateralClaimTransaction { ); } - let already_in_mempool = memcheck(signature, &hash).await; - // Submission can reuse an already verified mempool entry. Block - // validation still checks the schedule against the block timestamp. - if allow_mempool_short_circuit && already_in_mempool { - return Ok(signature.to_string()); - } - // Collateral claims are valid only when the claimant signs the // claim transaction with the same wallet in the payload. if !Wallet::short_address_validation(&self.unsigned_collateral_claim.address) { diff --git a/src/verifications/async_funcs/verify_create_nft.rs b/src/verifications/async_funcs/verify_create_nft.rs index 81ac209..d2501f9 100644 --- a/src/verifications/async_funcs/verify_create_nft.rs +++ b/src/verifications/async_funcs/verify_create_nft.rs @@ -10,7 +10,6 @@ use crate::records::wallet_registry::{ use crate::sled::Db; use crate::verifications::async_funcs::asset_rules::is_reserved_base_coin_ticker; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::wallets::structures::Wallet; use crate::Cid; @@ -38,12 +37,6 @@ impl CreateNftTransaction { return Err("NFT name is reserved for the base coin.".to_string()); } - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. - if memcheck(signature, hash).await { - return Ok(signature.to_string()); - } - // NFT creation is anchored to a valid creator wallet and a valid // signature over the unsigned NFT payload. let creator = &self.unsigned_create_nft.creator; diff --git a/src/verifications/async_funcs/verify_create_token.rs b/src/verifications/async_funcs/verify_create_token.rs index f3e359b..b5c2212 100644 --- a/src/verifications/async_funcs/verify_create_token.rs +++ b/src/verifications/async_funcs/verify_create_token.rs @@ -9,7 +9,6 @@ use crate::records::wallet_registry::{ use crate::sled::Db; use crate::verifications::async_funcs::asset_rules::is_reserved_base_coin_ticker; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::{ db_bytes_verification, db_hex_verification, }; @@ -17,10 +16,7 @@ use crate::wallets::structures::Wallet; impl CreateTokenTransaction { pub async fn verify(&self, db: &Db) -> Result { - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. let hash = self.unsigned_create_token.hash().await; - let signature = &self.signature; // Token tickers use the fixed padded coin-length format. let ticker_length = self.unsigned_create_token.ticker.len(); @@ -38,10 +34,6 @@ impl CreateTokenTransaction { return Err("Ticker is reserved for the base coin.".to_string()); } - if memcheck(signature, &hash).await { - return Ok(self.signature.clone()); - } - // Token creation is anchored to the creator's wallet signature. if !Wallet::short_address_validation(&self.unsigned_create_token.creator) { return Err("Sender Wallet Address is Invalid.".to_string()); diff --git a/src/verifications/async_funcs/verify_delete_key.rs b/src/verifications/async_funcs/verify_delete_key.rs index 2609174..cd52b41 100644 --- a/src/verifications/async_funcs/verify_delete_key.rs +++ b/src/verifications/async_funcs/verify_delete_key.rs @@ -6,7 +6,6 @@ use crate::records::wallet_registry::{ require_canonical_registered_short_address, resolve_pubkey_from_short_address, }; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::wallets::structures::Wallet; use crate::{decode, encode, sled::Db}; @@ -16,10 +15,6 @@ impl DeleteKey { let delete = &self.unsigned_deletekey; let hash = delete.hash().await; - // Existing mempool entries short-circuit before the storage-state checks. - if memcheck(&self.signature, &hash).await { - return Ok(self.signature.clone()); - } if delete.txtype != DELETE_KEY_TYPE { return Err("Delete-key transaction type is invalid.".to_string()); } diff --git a/src/verifications/async_funcs/verify_issue_token.rs b/src/verifications/async_funcs/verify_issue_token.rs index 163c3f3..87ffe11 100644 --- a/src/verifications/async_funcs/verify_issue_token.rs +++ b/src/verifications/async_funcs/verify_issue_token.rs @@ -12,7 +12,6 @@ use crate::rpc::responses::RpcResponse; use crate::sled::Db; use crate::verifications::async_funcs::asset_rules::reserved_base_coins; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::{ db_bytes_verification, db_hex_verification, }; @@ -50,13 +49,6 @@ fn token_hard_limit(db: &Db, ticker: &str) -> Option { impl IssueTokenTransaction { pub async fn verify(&self, db: &Db) -> Result { let hash = self.unsigned_issue_token.hash().await; - let signature = &self.signature; - - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. - if memcheck(signature, &hash).await { - return Ok(self.signature.clone()); - } // Issuance is anchored to the creator's wallet signature. if !Wallet::short_address_validation(&self.unsigned_issue_token.creator) { diff --git a/src/verifications/async_funcs/verify_lender.rs b/src/verifications/async_funcs/verify_lender.rs index 8d7bb70..bd0ad9b 100644 --- a/src/verifications/async_funcs/verify_lender.rs +++ b/src/verifications/async_funcs/verify_lender.rs @@ -11,7 +11,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::time_checks::is_within_30_days; use crate::verifications::async_funcs::checks::verify_db::{ db_bytes_verification, db_hex_verification, @@ -21,13 +20,6 @@ use crate::wallets::structures::Wallet; impl LoanContractTransaction { pub async fn verify(&self, db: &Db) -> Result { let calculated_hash = &self.unsigned_loan_contract.hash().await; - let signature2 = &self.signature2; - - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. - if memcheck(signature2, calculated_hash).await { - return Ok(signature2.to_string()); - }; // Loan contracts require valid lender and borrower wallet addresses. let lender = &self.unsigned_loan_contract.lender; diff --git a/src/verifications/async_funcs/verify_marketing.rs b/src/verifications/async_funcs/verify_marketing.rs index 90818e7..6dec744 100644 --- a/src/verifications/async_funcs/verify_marketing.rs +++ b/src/verifications/async_funcs/verify_marketing.rs @@ -7,20 +7,13 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::wallets::structures::Wallet; impl MarketingTransaction { pub async fn verify(&self, db: &Db) -> Result { - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. let hash = &self.unsigned_marketing.hash().await; let signature = &self.signature; - if memcheck(signature, hash).await { - return Ok(signature.to_string()); - } - // Marketing transactions must come from a valid advertiser wallet // and carry a valid signature from that same wallet. let advertiser = &self.unsigned_marketing.advertiser; diff --git a/src/verifications/async_funcs/verify_storage_key.rs b/src/verifications/async_funcs/verify_storage_key.rs index 4ada8ee..bcb2791 100644 --- a/src/verifications/async_funcs/verify_storage_key.rs +++ b/src/verifications/async_funcs/verify_storage_key.rs @@ -7,7 +7,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::wallets::structures::Wallet; @@ -21,13 +20,7 @@ impl StorageKey { return Err("Storage key transaction type is invalid.".to_string()); } - // Transactions already present in the mempool can short-circuit - // deeper verification and return their stored signature. let hash = storage_key.hash().await; - if memcheck(&self.signature, &hash).await { - return Ok(self.signature.clone()); - } - // Only canonical registered short addresses can create storage // keys. Vanity aliases are resolved by callers before they reach // this fixed transaction format. diff --git a/src/verifications/async_funcs/verify_storage_values.rs b/src/verifications/async_funcs/verify_storage_values.rs index 757ce0c..eee4034 100644 --- a/src/verifications/async_funcs/verify_storage_values.rs +++ b/src/verifications/async_funcs/verify_storage_values.rs @@ -17,7 +17,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::wallets::structures::Wallet; @@ -32,13 +31,6 @@ async fn verify_storage_value( // fee, hash, and signature. let parts = tx.storage_parts(); - // Match the rest of transaction verification: if this exact signed - // transaction is already in the mempool, return before doing deeper - // database checks. - if memcheck(parts.signature, &parts.hash).await { - return Ok(parts.signature.to_string()); - } - // The shared verifier is called by each concrete storage type, so // confirm the embedded transaction type matches that caller. if parts.txtype != expected_type { @@ -187,14 +179,6 @@ impl StorageString { pub async fn verify(&self, db: &Db) -> Result { // String storage has extra chain-linking rules before it can use // the common storage-value verifier. - let parts = self.storage_parts(); - - // Existing mempool entries can still short-circuit before walking - // the previous-hash string chain. - if memcheck(parts.signature, &parts.hash).await { - return Ok(parts.signature.to_string()); - } - // The on-chain string chunk is fixed at 180 bytes. Shorter text is // padded by the creator and trimmed only when saved into sled. if self.unsigned_storage.value.as_bytes().len() != STORAGE_STRING_VALUE_BYTES { diff --git a/src/verifications/async_funcs/verify_swap.rs b/src/verifications/async_funcs/verify_swap.rs index fb72cf9..baeb21b 100644 --- a/src/verifications/async_funcs/verify_swap.rs +++ b/src/verifications/async_funcs/verify_swap.rs @@ -9,7 +9,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::time_checks::is_within_30_days; use crate::verifications::async_funcs::checks::verify_db::{ db_bytes_verification, db_hex_verification, @@ -36,13 +35,7 @@ fn validate_swap_tip(value: u64, tip: u64, is_nft: bool, sender: &str) -> Result impl SwapTransaction { pub async fn verify(&self, db: &Db) -> Result { - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. let hash = self.unsigned_swap.hash().await; - if memcheck(&self.signature2, &hash).await { - return Ok(self.signature2.clone()); - } - // Both swap participants must provide valid wallet addresses and // matching signatures over the shared unsigned swap payload. if !(Wallet::short_address_validation(&self.unsigned_swap.sender1) diff --git a/src/verifications/async_funcs/verify_transfer.rs b/src/verifications/async_funcs/verify_transfer.rs index 8985beb..9381de0 100644 --- a/src/verifications/async_funcs/verify_transfer.rs +++ b/src/verifications/async_funcs/verify_transfer.rs @@ -10,7 +10,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::{ db_bytes_verification, db_hex_verification, }; @@ -35,12 +34,6 @@ fn is_zero_burn_address(address: &str) -> bool { impl TransferTransaction { pub async fn verify(&self, db: &Db) -> Result { let hash = self.unsigned_transfer.hash().await; - // Transactions that are already sitting in the mempool can skip - // the deeper verification work and return their stored signature. - if memcheck(&self.signature, &hash).await { - return Ok(self.signature.clone()); - } - // Validate both wallet addresses and the signed transfer payload // before checking balances and asset-specific rules. if !(Wallet::short_address_validation(&self.unsigned_transfer.sender) diff --git a/src/verifications/async_funcs/verify_vanity.rs b/src/verifications/async_funcs/verify_vanity.rs index 5a11f0e..e5c4d9a 100644 --- a/src/verifications/async_funcs/verify_vanity.rs +++ b/src/verifications/async_funcs/verify_vanity.rs @@ -7,7 +7,6 @@ use crate::records::wallet_registry::{ }; use crate::sled::Db; use crate::verifications::async_funcs::checks::balance_check::balance_checkup; -use crate::verifications::async_funcs::checks::mempool_check::memcheck; use crate::verifications::async_funcs::checks::verify_db::db_hex_verification; use crate::wallets::structures::Wallet; @@ -17,12 +16,6 @@ impl VanityAddressTransaction { // address-registration payload, so recompute that hash first. let hash = self.unsigned_vanity_address.hash().await; - // Transactions already present in the mempool can short-circuit - // the deeper verification path and reuse their stored signature. - if memcheck(&self.signature, &hash).await { - return Ok(self.signature.clone()); - } - // The paying wallet must already be a valid short address for the // current network before registry ownership is checked. let address = &self.unsigned_vanity_address.address; diff --git a/src/verifications/verification_service.rs b/src/verifications/verification_service.rs index 2667ebc..2b80a17 100644 --- a/src/verifications/verification_service.rs +++ b/src/verifications/verification_service.rs @@ -1,11 +1,10 @@ -use crate::common::types::Transaction; use crate::rayon::ThreadPool; use crate::rayon::ThreadPoolBuilder; use crate::verifications::async_funcs::checks::block_balance::BlockBalanceTracker; use crate::verifications::async_funcs::transactions::verify_transactions; use crate::verifications::sync_funcs::transaction_verify_loop::COUNTER; use crate::verifications::verification_types::{ - VerificationChunkJob, VerificationChunkResult, VerificationJob, + VerifiableTransaction, VerificationChunkJob, VerificationChunkResult, VerificationJob, }; use crate::Arc; use crate::AtomicBool; @@ -75,7 +74,7 @@ impl VerificationService { pub async fn verify_block_transactions( &self, miner: String, - transactions: Vec, + transactions: Vec, db: crate::sled::Db, block_timestamp: u32, ) -> Result, String> { diff --git a/src/verifications/verification_types.rs b/src/verifications/verification_types.rs index 536b934..1deaf13 100644 --- a/src/verifications/verification_types.rs +++ b/src/verifications/verification_types.rs @@ -1,10 +1,16 @@ use crate::common::types::Transaction; use crate::sled::Db; +#[derive(Clone)] +pub struct VerifiableTransaction { + pub transaction: Transaction, + pub original: Option>, +} + // VerificationJob represents one full transaction batch submitted to the verification service. pub struct VerificationJob { pub miner: String, - pub transactions: Vec, + pub transactions: Vec, pub db: Db, pub block_timestamp: u32, } @@ -12,7 +18,7 @@ pub struct VerificationJob { // VerificationChunkJob is the per-worker slice created from a larger verification job. pub struct VerificationChunkJob { pub miner: String, - pub transactions: Vec, + pub transactions: Vec, pub db: Db, pub block_timestamp: u32, }