mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-10 13:09:24 +00:00
Have monero-wallet use Transaction<Pruned>, not Transaction
This commit is contained in:
@@ -26,7 +26,7 @@ use serde_json::{Value, json};
|
||||
|
||||
use monero_serai::{
|
||||
io::*,
|
||||
transaction::{Input, Timelock, Transaction},
|
||||
transaction::{Input, Timelock, Pruned, Transaction},
|
||||
block::Block,
|
||||
DEFAULT_LOCK_WINDOW,
|
||||
};
|
||||
@@ -361,14 +361,15 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, res)| {
|
||||
let tx = Transaction::read::<&[u8]>(
|
||||
&mut rpc_hex(if !res.as_hex.is_empty() { &res.as_hex } else { &res.pruned_as_hex })?
|
||||
.as_ref(),
|
||||
)
|
||||
.map_err(|_| match hash_hex(&res.tx_hash) {
|
||||
let buf = rpc_hex(if !res.as_hex.is_empty() { &res.as_hex } else { &res.pruned_as_hex })?;
|
||||
let mut buf = buf.as_slice();
|
||||
let tx = Transaction::read(&mut buf).map_err(|_| match hash_hex(&res.tx_hash) {
|
||||
Ok(hash) => RpcError::InvalidTransaction(hash),
|
||||
Err(err) => err,
|
||||
})?;
|
||||
if !buf.is_empty() {
|
||||
Err(RpcError::InvalidNode("transaction had extra bytes after it".to_string()))?;
|
||||
}
|
||||
|
||||
// https://github.com/monero-project/monero/issues/8311
|
||||
if res.as_hex.is_empty() {
|
||||
@@ -391,6 +392,61 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get the specified transactions in their pruned format.
|
||||
async fn get_pruned_transactions(
|
||||
&self,
|
||||
hashes: &[[u8; 32]],
|
||||
) -> Result<Vec<Transaction<Pruned>>, RpcError> {
|
||||
if hashes.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let mut hashes_hex = hashes.iter().map(hex::encode).collect::<Vec<_>>();
|
||||
let mut all_txs = Vec::with_capacity(hashes.len());
|
||||
while !hashes_hex.is_empty() {
|
||||
// Monero errors if more than 100 is requested unless using a non-restricted RPC
|
||||
// TODO: Cite
|
||||
// TODO: Deduplicate with above
|
||||
const TXS_PER_REQUEST: usize = 100;
|
||||
let this_count = TXS_PER_REQUEST.min(hashes_hex.len());
|
||||
|
||||
let txs: TransactionsResponse = self
|
||||
.rpc_call(
|
||||
"get_transactions",
|
||||
Some(json!({
|
||||
"txs_hashes": hashes_hex.drain(.. this_count).collect::<Vec<_>>(),
|
||||
"prune": true,
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
|
||||
if !txs.missed_tx.is_empty() {
|
||||
Err(RpcError::TransactionsNotFound(
|
||||
txs.missed_tx.iter().map(|hash| hash_hex(hash)).collect::<Result<_, _>>()?,
|
||||
))?;
|
||||
}
|
||||
|
||||
all_txs.extend(txs.txs);
|
||||
}
|
||||
|
||||
all_txs
|
||||
.iter()
|
||||
.map(|res| {
|
||||
let buf = rpc_hex(&res.pruned_as_hex)?;
|
||||
let mut buf = buf.as_slice();
|
||||
let tx =
|
||||
Transaction::<Pruned>::read(&mut buf).map_err(|_| match hash_hex(&res.tx_hash) {
|
||||
Ok(hash) => RpcError::InvalidTransaction(hash),
|
||||
Err(err) => err,
|
||||
})?;
|
||||
if !buf.is_empty() {
|
||||
Err(RpcError::InvalidNode("pruned transaction had extra bytes after it".to_string()))?;
|
||||
}
|
||||
Ok(tx)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get the specified transaction.
|
||||
///
|
||||
/// The received transaction will be hashed in order to verify the correct transaction was
|
||||
@@ -399,6 +455,11 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
self.get_transactions(&[tx]).await.map(|mut txs| txs.swap_remove(0))
|
||||
}
|
||||
|
||||
/// Get the specified transaction in its pruned format.
|
||||
async fn get_pruned_transaction(&self, tx: [u8; 32]) -> Result<Transaction<Pruned>, RpcError> {
|
||||
self.get_pruned_transactions(&[tx]).await.map(|mut txs| txs.swap_remove(0))
|
||||
}
|
||||
|
||||
/// Get the hash of a block from the node.
|
||||
///
|
||||
/// `number` is the block's zero-indexed position on the blockchain (`0` for the genesis block,
|
||||
@@ -469,35 +530,6 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the transactions within a block.
|
||||
///
|
||||
/// This function returns all transactions in the block, including the miner's transaction.
|
||||
///
|
||||
/// This function does not verify the returned transactions are the ones committed to by the
|
||||
/// block's header.
|
||||
async fn get_block_transactions(&self, hash: [u8; 32]) -> Result<Vec<Transaction>, RpcError> {
|
||||
let block = self.get_block(hash).await?;
|
||||
let mut res = vec![block.miner_transaction];
|
||||
res.extend(self.get_transactions(&block.transactions).await?);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Get the transactions within a block.
|
||||
///
|
||||
/// This function returns all transactions in the block, including the miner's transaction.
|
||||
///
|
||||
/// This function does not verify the returned transactions are the ones committed to by the
|
||||
/// block's header.
|
||||
async fn get_block_transactions_by_number(
|
||||
&self,
|
||||
number: usize,
|
||||
) -> Result<Vec<Transaction>, RpcError> {
|
||||
let block = self.get_block_by_number(number).await?;
|
||||
let mut res = vec![block.miner_transaction];
|
||||
res.extend(self.get_transactions(&block.transactions).await?);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Get the currently estimated fee rate from the node.
|
||||
///
|
||||
/// This may be manipulated to unsafe levels and MUST be sanity checked.
|
||||
|
||||
Reference in New Issue
Block a user