From 65ac8afa5a242f1f8e0b16a8d9fe8b770845936e Mon Sep 17 00:00:00 2001 From: viraladmin <00purple@gmail.com> Date: Sat, 20 Jun 2026 18:49:22 -0600 Subject: [PATCH] changes for gui wallets --- src/rpc/command_maps.rs | 3 +- src/rpc/commands/address_history.rs | 87 +++++++++++++------ src/rpc/server/rpc_command_loop.rs | 25 +----- .../connections/sending_request.rs | 27 +----- 4 files changed, 65 insertions(+), 77 deletions(-) diff --git a/src/rpc/command_maps.rs b/src/rpc/command_maps.rs index 300c039..9a77e95 100644 --- a/src/rpc/command_maps.rs +++ b/src/rpc/command_maps.rs @@ -56,8 +56,7 @@ pub const RPC_BLOCK_HASH_AT_HEIGHT: u8 = 42; pub const RPC_WALLET_REGISTRATION_STATUS: u8 = 43; pub const RPC_ADDRESS_HISTORY: u8 = 44; pub const RPC_VANITY_OWNER_LOOKUP: u8 = 45; -pub const RPC_LATEST_ADDRESS_HISTORY: u8 = 46; -pub const RPC_LATEST_ADDRESS_TRANSACTIONS: u8 = 47; +pub const RPC_LATEST_ADDRESS_TRANSACTIONS: u8 = 46; pub const RPC_REPLY: u8 = 255; pub const MAX_RPC_REPLY_BYTES: usize = 64 * 1024 * 1024; diff --git a/src/rpc/commands/address_history.rs b/src/rpc/commands/address_history.rs index 7fee745..c1dafad 100644 --- a/src/rpc/commands/address_history.rs +++ b/src/rpc/commands/address_history.rs @@ -10,6 +10,65 @@ use std::ops::Bound; const TXID_LENGTH: usize = 32; const MAX_ADDRESS_HISTORY_TXIDS: usize = 10_000; +fn signature_count(transaction_type: u8) -> usize { + match transaction_type { + 6 | 7 => 2, + 2..=5 | 8..=12 => 1, + _ => 0, + } +} + +fn without_signature_bytes(transaction_bytes: &[u8]) -> Result, String> { + let Some((&transaction_type, _)) = transaction_bytes.split_first() else { + return Err("error: Transaction payload was empty".to_string()); + }; + let strip_bytes = signature_count(transaction_type) * Wallet::SIGNATURE_LENGTH; + if transaction_bytes.len() < strip_bytes { + return Err("error: Transaction payload was shorter than its signature bytes".to_string()); + } + Ok(transaction_bytes[..transaction_bytes.len() - strip_bytes].to_vec()) +} + +async fn transaction_records_response( + txid_bytes: &[u8], + db: &Db, + strip_signatures: bool, +) -> RpcResponse { + let mut entries = Vec::new(); + for txid in txid_bytes.chunks_exact(TXID_LENGTH) { + match transaction_bytes_with_block(db, txid).await { + Ok((block_height, transaction_bytes)) => { + let payload = if strip_signatures { + match without_signature_bytes(&transaction_bytes) { + Ok(payload) => payload, + Err(err) => return RpcResponse::Binary(err.into_bytes()), + } + } else { + transaction_bytes + }; + entries.push((txid.to_vec(), block_height, payload)); + } + Err(err) => { + return RpcResponse::Binary(err.into_bytes()); + } + } + } + + let mut response = Vec::new(); + response.extend_from_slice(&(entries.len() as u32).to_le_bytes()); + for (txid, block_height, transaction_bytes) in entries { + let Ok(tx_len) = u32::try_from(transaction_bytes.len()) else { + return RpcResponse::Binary(b"error: Transaction payload too large".to_vec()); + }; + response.extend_from_slice(&txid); + response.extend_from_slice(&block_height.to_le_bytes()); + response.extend_from_slice(&tx_len.to_le_bytes()); + response.extend_from_slice(&transaction_bytes); + } + + RpcResponse::Binary(response) +} + fn prefix_successor(prefix: &[u8]) -> Option> { let mut next = prefix.to_vec(); for index in (0..next.len()).rev() { @@ -81,7 +140,7 @@ pub async fn lookup(address_bytes: Vec, skip: u32, limit: u32, db: &Db) -> R } } - RpcResponse::Binary(txids) + transaction_records_response(&txids, db, true).await } pub async fn latest(address_bytes: Vec, limit: u32, db: &Db) -> RpcResponse { @@ -159,29 +218,5 @@ pub async fn latest_transactions(address_bytes: Vec, limit: u32, db: &Db) -> return RpcResponse::Binary(txid_bytes); } - let mut entries = Vec::new(); - for txid in txid_bytes.chunks_exact(TXID_LENGTH) { - match transaction_bytes_with_block(db, txid).await { - Ok((block_height, transaction_bytes)) => { - entries.push((txid.to_vec(), block_height, transaction_bytes)); - } - Err(err) => { - return RpcResponse::Binary(err.into_bytes()); - } - } - } - - let mut response = Vec::new(); - response.extend_from_slice(&(entries.len() as u32).to_le_bytes()); - for (txid, block_height, transaction_bytes) in entries { - let Ok(tx_len) = u32::try_from(transaction_bytes.len()) else { - return RpcResponse::Binary(b"error: Transaction payload too large".to_vec()); - }; - response.extend_from_slice(&txid); - response.extend_from_slice(&block_height.to_le_bytes()); - response.extend_from_slice(&tx_len.to_le_bytes()); - response.extend_from_slice(&transaction_bytes); - } - - RpcResponse::Binary(response) + transaction_records_response(&txid_bytes, db, false).await } diff --git a/src/rpc/server/rpc_command_loop.rs b/src/rpc/server/rpc_command_loop.rs index 082b668..f5d9aa5 100644 --- a/src/rpc/server/rpc_command_loop.rs +++ b/src/rpc/server/rpc_command_loop.rs @@ -822,7 +822,7 @@ pub async fn start_loop( .await; } 44 => { - // request confirmed transaction ids indexed to a wallet address + // request paged signature-stripped transaction records indexed to a wallet address let (uid, _) = read_bytes_from_stream::read_uid_from_stream( &connections_key, stream_locked.clone(), @@ -884,29 +884,6 @@ pub async fn start_loop( .await; } 46 => { - // request the latest confirmed transaction ids for a wallet address - let (uid, _) = read_bytes_from_stream::read_uid_from_stream( - &connections_key, - stream_locked.clone(), - ) - .await?; - let short_address = read_bytes_from_stream::read_short_address_from_stream( - &connections_key, - stream_locked.clone(), - ) - .await?; - let limit = read_bytes_from_stream::read_u32_from_stream( - &connections_key, - stream_locked.clone(), - ) - .await?; - - let result = commands::address_history::latest(short_address, limit, &db).await; - result - .send(&stream_locked, Some(&connections_key), uid) - .await; - } - 47 => { // request latest transaction records for a wallet address in one response let (uid, _) = read_bytes_from_stream::read_uid_from_stream( &connections_key, diff --git a/src/standalone_tools/connections/sending_request.rs b/src/standalone_tools/connections/sending_request.rs index a5211f7..de02fcd 100644 --- a/src/standalone_tools/connections/sending_request.rs +++ b/src/standalone_tools/connections/sending_request.rs @@ -5,7 +5,7 @@ use crate::records::memory::response_channels::Byte3; use crate::rpc::command_maps::{ MAX_RPC_REPLY_BYTES, RPC_ADDRESS_HISTORY, RPC_ADDRESS_TOTAL_BALANCE, RPC_BLOCK_BY_HASH, RPC_BLOCK_BY_HEIGHT, RPC_BLOCK_HEIGHT, RPC_BLOCK_IP, RPC_CONTRACT_BY_ADDRESS, RPC_DIFFICULTY, - RPC_LARGEST_TX_FEE, RPC_LATEST_ADDRESS_HISTORY, RPC_LATEST_ADDRESS_TRANSACTIONS, + RPC_LARGEST_TX_FEE, RPC_LATEST_ADDRESS_TRANSACTIONS, RPC_LOAN_CONTRACT, RPC_MEMPOOL_TX_BY_ADDRESS, RPC_MEMPOOL_TX_BY_SIGNATURE, RPC_MEMPOOL_TX_COUNT, RPC_NETWORK_INFO, RPC_NFT_DETAILS, RPC_NFT_LIST, RPC_REGISTER_WALLET, RPC_TIME, RPC_TOKEN_DETAILS, RPC_TOKEN_LIST, RPC_TORRENT_BY_HEIGHT, RPC_TOTAL_CONFIRMED_TX, @@ -519,31 +519,8 @@ async fn build_request_bytes( bin_msg.extend_from_slice(&hashmap_key); bin_msg.extend_from_slice(&address_bytes); } - // Lookup newest confirmed transaction ids tied to an address. + // Lookup newest transaction records tied to an address. 46 => { - let command_number: u8 = RPC_LATEST_ADDRESS_HISTORY; - let (address, limit) = command_input.split_once('|').ok_or_else(|| { - io::Error::new( - io::ErrorKind::InvalidInput, - "Latest address history input must be address|limit", - ) - })?; - let address_bytes = Wallet::normalize_to_short_address(address) - .and_then(|short| Wallet::short_address_to_bytes(&short)) - .ok_or_else(|| { - io::Error::new(io::ErrorKind::InvalidInput, "Invalid wallet address") - })?; - let limit = limit.parse::().map_err(|_| { - io::Error::new(io::ErrorKind::InvalidInput, "Invalid history limit") - })?; - - bin_msg.extend_from_slice(&command_number.to_le_bytes()); - bin_msg.extend_from_slice(&hashmap_key); - bin_msg.extend_from_slice(&address_bytes); - bin_msg.extend_from_slice(&limit.to_le_bytes()); - } - 47 => { - // NEW: latest address transaction bytes (RPC_LATEST_ADDRESS_TRANSACTIONS) let command_number: u8 = RPC_LATEST_ADDRESS_TRANSACTIONS; let (address, limit) = command_input.split_once('|').ok_or_else(|| { io::Error::new(