Skip to content

Commit

Permalink
Replaces multiple service calls (per transaction) with a single call …
Browse files Browse the repository at this point in the history
…to the state service for all of a block's transactions.
  • Loading branch information
arya2 committed Dec 13, 2024
1 parent a860577 commit d2f968f
Showing 1 changed file with 36 additions and 26 deletions.
62 changes: 36 additions & 26 deletions zebra-rpc/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,6 @@ where
None
};

let self_clone = self.clone();
async move {
let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?;

Expand Down Expand Up @@ -811,6 +810,12 @@ where
next_block_hash,
} = *block_header;

let transactions_request = match verbosity {
1 => zebra_state::ReadRequest::TransactionIdsForBlock(hash_or_height),
2 => zebra_state::ReadRequest::Block(hash_or_height),
_other => panic!("get_block_header_fut should be none"),
};

// # Concurrency
//
// We look up by block hash so the hash, transaction IDs, and confirmations
Expand All @@ -824,7 +829,7 @@ where
// A block's transaction IDs are never modified, so all possible responses are
// valid. Clients that query block heights must be able to handle chain forks,
// including getting transaction IDs from any chain fork.
zebra_state::ReadRequest::TransactionIdsForBlock(hash_or_height),
transactions_request,
// Orchard trees
zebra_state::ReadRequest::OrchardTree(hash_or_height),
];
Expand All @@ -842,33 +847,24 @@ where
.iter()
.map(|tx_id| GetBlockTransaction::Hash(*tx_id))
.collect(),
zebra_state::ReadResponse::Block(block) => block
.ok_or_server_error("Block not found")?
.transactions
.iter()
.map(|tx| {
TransactionObject::new(
tx.clone(),
height,
confirmations
.try_into()
.expect("should be less than max block height, i32::MAX"),
)
})
.map(GetBlockTransaction::Object)
.collect(),
_ => unreachable!("unmatched response to a transaction_ids_for_block request"),
};

let tx = if verbosity >= 2 {
let mut tx_obj_vec = vec![];
let mut tx_futs = FuturesOrdered::new();
let tx_len = tx.len();
for txid in tx {
let GetBlockTransaction::Hash(txid) = txid else {
unreachable!("must be a Hash")
};
tx_futs
.push_back(self_clone.get_raw_transaction(txid.encode_hex(), Some(1)));
}
for _ in 0..tx_len {
let get_tx_result =
tx_futs.next().await.expect("`tx_futs` should not be empty");
let GetRawTransaction::Object(tx_obj) = get_tx_result? else {
unreachable!("must return Object");
};
tx_obj_vec.push(GetBlockTransaction::Object(tx_obj));
}
tx_obj_vec
} else {
tx
};

let orchard_tree_response = futs.next().await.expect("`futs` should not be empty");
let zebra_state::ReadResponse::OrchardTree(orchard_tree) =
orchard_tree_response.map_server_error()?
Expand Down Expand Up @@ -2045,6 +2041,20 @@ pub struct TransactionObject {
// TODO: many fields not yet supported
}

impl TransactionObject {
/// Creates a new [`TransactionObject`].
fn new(tx: Arc<Transaction>, height: block::Height, confirmations: u32) -> Self {
TransactionObject {
hex: tx.into(),
height: height
.0
.try_into()
.expect("valid block heights are limited to i32::MAX"),
confirmations,
}
}
}

impl Default for TransactionObject {
fn default() -> Self {
Self {
Expand Down

0 comments on commit d2f968f

Please sign in to comment.