changes for gui wallets
This commit is contained in:
parent
e479b8e5df
commit
65ac8afa5a
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in New Issue