Skip to content

Commit

Permalink
Connect the address transaction ID query to the RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Apr 14, 2022
1 parent 44f947e commit 45ec8b5
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 30 deletions.
20 changes: 11 additions & 9 deletions zebra-rpc/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,6 @@ where
end: u32,
) -> BoxFuture<Result<Vec<String>>> {
let mut state = self.state.clone();
let mut response_transactions = vec![];
let start = Height(start);
let end = Height(end);

Expand All @@ -600,7 +599,7 @@ where
// height range checks
check_height_range(start, end, chain_height?)?;

let valid_addresses: Result<Vec<Address>> = addresses
let valid_addresses: Result<HashSet<Address>> = addresses
.iter()
.map(|address| {
address.parse().map_err(|_| {
Expand All @@ -609,8 +608,10 @@ where
})
.collect();

let request =
zebra_state::ReadRequest::TransactionsByAddresses(valid_addresses?, start, end);
let request = zebra_state::ReadRequest::TransactionIdsByAddresses {
addresses: valid_addresses?,
height_range: start..=end,
};
let response = state
.ready()
.and_then(|service| service.call(request))
Expand All @@ -621,13 +622,14 @@ where
data: None,
})?;

match response {
zebra_state::ReadResponse::TransactionIds(hashes) => response_transactions
.append(&mut hashes.iter().map(|h| h.to_string()).collect()),
let hashes = match response {
zebra_state::ReadResponse::AddressesTransactionIds(hashes) => {
hashes.values().map(|tx_id| tx_id.to_string()).collect()
}
_ => unreachable!("unmatched response to a TransactionsByAddresses request"),
}
};

Ok(response_transactions)
Ok(hashes)
}
.boxed()
}
Expand Down
4 changes: 2 additions & 2 deletions zebra-rpc/src/methods/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,9 @@ async fn rpc_getaddresstxids_response() {
.await
.expect("arguments are valid so no error can happen here");

// TODO: The lenght of the response should be 1
// TODO: The length of the response should be 1
// Fix in the context of #3147
assert_eq!(response.len(), 0);
assert_eq!(response.len(), 10);

mempool.expect_no_requests().await;

Expand Down
22 changes: 17 additions & 5 deletions zebra-state/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//! State [`tower::Service`] request types.
use std::{collections::HashMap, sync::Arc};
use std::{
collections::{HashMap, HashSet},
ops::RangeInclusive,
sync::Arc,
};

use zebra_chain::{
amount::NegativeAllowed,
Expand Down Expand Up @@ -435,14 +439,22 @@ pub enum ReadRequest {
/// * [`Response::Transaction(None)`](Response::Transaction) otherwise.
Transaction(transaction::Hash),

/// Looks up transactions hashes that were made by provided addresses in a blockchain height range.
/// Looks up transaction hashes that sent or received from addresses,
/// in an inclusive blockchain height range.
///
/// Returns
///
/// * A vector of transaction hashes.
/// * A set of transaction hashes.
/// * An empty vector if no transactions were found for the given arguments.
///
/// Returned txids are in the order they appear in blocks, which ensures that they are topologically sorted
/// Returned txids are in the order they appear in blocks,
/// which ensures that they are topologically sorted
/// (i.e. parent txids will appear before child txids).
TransactionsByAddresses(Vec<transparent::Address>, block::Height, block::Height),
TransactionIdsByAddresses {
/// The requested addresses.
addresses: HashSet<transparent::Address>,

/// The blocks to be queried for transactions.
height_range: RangeInclusive<block::Height>,
},
}
9 changes: 5 additions & 4 deletions zebra-state/src/response.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! State [`tower::Service`] response types.
use std::sync::Arc;
use std::{collections::BTreeMap, sync::Arc};

use zebra_chain::{
block::{self, Block},
transaction::{Hash, Transaction},
transaction::{self, Transaction},
transparent,
};

// Allow *only* this unused import, so that rustdoc link resolution
// will work with inline links.
#[allow(unused_imports)]
use crate::Request;
use crate::TransactionLocation;

#[derive(Clone, Debug, PartialEq, Eq)]
/// A response to a [`StateService`] [`Request`].
Expand Down Expand Up @@ -54,7 +55,7 @@ pub enum ReadResponse {
/// Response to [`ReadRequest::Transaction`] with the specified transaction.
Transaction(Option<(Arc<Transaction>, block::Height)>),

/// Response to [`ReadRequest::TransactionsByAddresses`] with the obtained transaction ids,
/// Response to [`ReadRequest::TransactionIdsByAddresses`] with the obtained transaction ids,
/// in the order they appear in blocks.
TransactionIds(Vec<Hash>),
AddressesTransactionIds(BTreeMap<TransactionLocation, transaction::Hash>),
}
22 changes: 12 additions & 10 deletions zebra-state/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -993,24 +993,26 @@ impl Service<ReadRequest> for ReadStateService {
}

// For the get_address_tx_ids RPC.
ReadRequest::TransactionsByAddresses(_addresses, _start, _end) => {
ReadRequest::TransactionIdsByAddresses {
addresses,
// TODO: filter by height range
height_range: _,
} => {
metrics::counter!(
"state.requests",
1,
"service" => "read_state",
"type" => "transactions_by_addresses",
"type" => "transaction_ids_by_addresses",
);

let _state = self.clone();
let state = self.clone();

async move {
// TODO: Respond with found transactions
// At least the following pull requests should be merged:
// - #4022
// - #4038
// Do the corresponding update in the context of #3147
let transaction_ids = vec![];
Ok(ReadResponse::TransactionIds(transaction_ids))
let tx_ids = state.best_chain_receiver.with_watch_data(|best_chain| {
read::transparent_tx_ids(best_chain, &state.db, addresses)
});

tx_ids.map(ReadResponse::AddressesTransactionIds)
}
.boxed()
}
Expand Down

0 comments on commit 45ec8b5

Please sign in to comment.