changes for gui wallets

This commit is contained in:
viraladmin 2026-06-20 18:49:22 -06:00
parent e479b8e5df
commit 65ac8afa5a
4 changed files with 65 additions and 77 deletions

View File

@ -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;

View File

@ -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<Vec<u8>, 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<Vec<u8>> {
let mut next = prefix.to_vec();
for index in (0..next.len()).rev() {
@ -81,7 +140,7 @@ pub async fn lookup(address_bytes: Vec<u8>, skip: u32, limit: u32, db: &Db) -> R
}
}
RpcResponse::Binary(txids)
transaction_records_response(&txids, db, true).await
}
pub async fn latest(address_bytes: Vec<u8>, limit: u32, db: &Db) -> RpcResponse {
@ -159,29 +218,5 @@ pub async fn latest_transactions(address_bytes: Vec<u8>, 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
}

View File

@ -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,

View File

@ -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::<u32>().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(