Skip to content

Commit

Permalink
adds read::unspent_utxo fn
Browse files Browse the repository at this point in the history
  • Loading branch information
arya2 committed Nov 11, 2022
1 parent d4a4ff8 commit 5b8eadc
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 31 deletions.
8 changes: 5 additions & 3 deletions zebra-consensus/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,11 +486,13 @@ where
tracing::trace!("UXTO in known_utxos, discarding query");
output.utxo.clone()
} else if is_mempool {
let query = state.clone().oneshot(zs::Request::BestChainUtxo(*outpoint));
if let zebra_state::Response::BestChainUtxo(utxo) = query.await? {
let query = state
.clone()
.oneshot(zs::Request::UnspentBestChainUtxo(*outpoint));
if let zebra_state::Response::UnspentBestChainUtxo(utxo) = query.await? {
utxo.ok_or(TransactionError::TransparentInputNotFound)?
} else {
unreachable!("BestChainUtxo always responds with Option<Utxo>")
unreachable!("UnspentBestChainUtxo always responds with Option<Utxo>")
}
} else {
let query = state
Expand Down
4 changes: 2 additions & 2 deletions zebra-consensus/src/transaction/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ async fn mempool_request_with_missing_input_is_rejected() {
.find(|(_, tx)| !(tx.is_coinbase() || tx.inputs().is_empty()))
.expect("At least one non-coinbase transaction with transparent inputs in test vectors");

let expected_state_request = zebra_state::Request::BestChainUtxo(match tx.inputs()[0] {
let expected_state_request = zebra_state::Request::UnspentBestChainUtxo(match tx.inputs()[0] {
transparent::Input::PrevOut { outpoint, .. } => outpoint,
transparent::Input::Coinbase { .. } => panic!("requires a non-coinbase transaction"),
});
Expand All @@ -199,7 +199,7 @@ async fn mempool_request_with_missing_input_is_rejected() {
.expect_request(expected_state_request)
.await
.expect("verifier should call mock state service")
.respond(zebra_state::Response::BestChainUtxo(None));
.respond(zebra_state::Response::UnspentBestChainUtxo(None));
});

let verifier_response = verifier
Expand Down
18 changes: 7 additions & 11 deletions zebra-state/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,10 +462,7 @@ pub enum Request {
/// returning `None` immediately if it is unknown.
///
/// Checks verified blocks in the finalized chain and the _best_ non-finalized chain.
///
/// This request is purely informational, there is no guarantee that
/// the UTXO remains unspent in the best chain.
BestChainUtxo(transparent::OutPoint),
UnspentBestChainUtxo(transparent::OutPoint),

/// Looks up a block by hash or height in the current best chain.
///
Expand Down Expand Up @@ -554,7 +551,7 @@ impl Request {
Request::Tip => "tip",
Request::BlockLocator => "block_locator",
Request::Transaction(_) => "transaction",
Request::BestChainUtxo { .. } => "best_chain_utxo",
Request::UnspentBestChainUtxo { .. } => "unspent_best_chain_utxo",
Request::Block(_) => "block",
Request::FindBlockHashes { .. } => "find_block_hashes",
Request::FindBlockHeaders { .. } => "find_block_headers",
Expand Down Expand Up @@ -623,10 +620,7 @@ pub enum ReadRequest {
/// returning `None` immediately if it is unknown.
///
/// Checks verified blocks in the finalized chain and the _best_ non-finalized chain.
///
/// This request is purely informational, there is no guarantee that
/// the UTXO remains unspent in the best chain.
BestChainUtxo(transparent::OutPoint),
UnspentBestChainUtxo(transparent::OutPoint),

/// Looks up a UTXO identified by the given [`OutPoint`](transparent::OutPoint),
/// returning `None` immediately if it is unknown.
Expand Down Expand Up @@ -760,7 +754,7 @@ impl ReadRequest {
ReadRequest::Block(_) => "block",
ReadRequest::Transaction(_) => "transaction",
ReadRequest::TransactionIdsForBlock(_) => "transaction_ids_for_block",
ReadRequest::BestChainUtxo { .. } => "best_chain_utxo",
ReadRequest::UnspentBestChainUtxo { .. } => "unspent_best_chain_utxo",
ReadRequest::AnyChainUtxo { .. } => "any_chain_utxo",
ReadRequest::BlockLocator => "block_locator",
ReadRequest::FindBlockHashes { .. } => "find_block_hashes",
Expand Down Expand Up @@ -799,7 +793,9 @@ impl TryFrom<Request> for ReadRequest {

Request::Block(hash_or_height) => Ok(ReadRequest::Block(hash_or_height)),
Request::Transaction(tx_hash) => Ok(ReadRequest::Transaction(tx_hash)),
Request::BestChainUtxo(outpoint) => Ok(ReadRequest::BestChainUtxo(outpoint)),
Request::UnspentBestChainUtxo(outpoint) => {
Ok(ReadRequest::UnspentBestChainUtxo(outpoint))
}

Request::BlockLocator => Ok(ReadRequest::BlockLocator),
Request::FindBlockHashes { known_blocks, stop } => {
Expand Down
13 changes: 5 additions & 8 deletions zebra-state/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub enum Response {
/// Response to [`Request::Transaction`] with the specified transaction.
Transaction(Option<Arc<Transaction>>),

/// Response to [`Request::BestChainUtxo`] with the UTXO
BestChainUtxo(Option<transparent::Utxo>),
/// Response to [`Request::UnspentBestChainUtxo`] with the UTXO
UnspentBestChainUtxo(Option<transparent::Utxo>),

/// Response to [`Request::Block`] with the specified block.
Block(Option<Arc<Block>>),
Expand Down Expand Up @@ -84,12 +84,9 @@ pub enum ReadResponse {
/// The response to a `FindBlockHeaders` request.
BlockHeaders(Vec<block::CountedHeader>),

/// The response to a `BestChainUtxo` request, from verified blocks in the
/// The response to a `UnspentBestChainUtxo` request, from verified blocks in the
/// _best_ non-finalized chain, or the finalized chain.
///
/// This response is purely informational, there is no guarantee that
/// the UTXO remains unspent in the best chain.
BestChainUtxo(Option<transparent::Utxo>),
UnspentBestChainUtxo(Option<transparent::Utxo>),

/// The response to an `AnyChainUtxo` request, from verified blocks in
/// _any_ non-finalized chain, or the finalized chain.
Expand Down Expand Up @@ -135,7 +132,7 @@ impl TryFrom<ReadResponse> for Response {
ReadResponse::Transaction(tx_and_height) => {
Ok(Response::Transaction(tx_and_height.map(|(tx, _height)| tx)))
}
ReadResponse::BestChainUtxo(utxo) => Ok(Response::BestChainUtxo(utxo)),
ReadResponse::UnspentBestChainUtxo(utxo) => Ok(Response::UnspentBestChainUtxo(utxo)),


ReadResponse::AnyChainUtxo(_) => Err("ReadService does not track pending UTXOs. \
Expand Down
16 changes: 10 additions & 6 deletions zebra-state/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ impl Service<Request> for StateService {
| Request::Tip
| Request::BlockLocator
| Request::Transaction(_)
| Request::BestChainUtxo(_)
| Request::UnspentBestChainUtxo(_)
| Request::Block(_)
| Request::FindBlockHashes { .. }
| Request::FindBlockHeaders { .. } => {
Expand Down Expand Up @@ -1218,7 +1218,7 @@ impl Service<ReadRequest> for ReadStateService {
}

// Currently unused.
ReadRequest::BestChainUtxo(outpoint) => {
ReadRequest::UnspentBestChainUtxo(outpoint) => {
let timer = CodeTimer::start();

let state = self.clone();
Expand All @@ -1228,17 +1228,21 @@ impl Service<ReadRequest> for ReadStateService {
span.in_scope(move || {
let utxo = state.non_finalized_state_receiver.with_watch_data(
|non_finalized_state| {
read::utxo(non_finalized_state.best_chain(), &state.db, outpoint)
read::unspent_utxo(
non_finalized_state.best_chain(),
&state.db,
outpoint,
)
},
);

// The work is done in the future.
timer.finish(module_path!(), line!(), "ReadRequest::BestChainUtxo");
timer.finish(module_path!(), line!(), "ReadRequest::UnspentBestChainUtxo");

Ok(ReadResponse::BestChainUtxo(utxo))
Ok(ReadResponse::UnspentBestChainUtxo(utxo))
})
})
.map(|join_result| join_result.expect("panic in ReadRequest::BestChainUtxo"))
.map(|join_result| join_result.expect("panic in ReadRequest::UnspentBestChainUtxo"))
.boxed()
}

Expand Down
4 changes: 3 additions & 1 deletion zebra-state/src/service/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub use address::{
utxo::{address_utxos, AddressUtxos, ADDRESS_HEIGHTS_FULL_RANGE},
};

pub use block::{any_utxo, block, block_header, transaction, transaction_hashes_for_block, utxo};
pub use block::{
any_utxo, block, block_header, transaction, transaction_hashes_for_block, unspent_utxo, utxo,
};

#[cfg(feature = "getblocktemplate-rpcs")]
pub use block::hash;
Expand Down
16 changes: 16 additions & 0 deletions zebra-state/src/service/read/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ where
.or_else(|| db.utxo(&outpoint).map(|utxo| utxo.utxo))
}

/// Returns the [`Utxo`] for [`transparent::OutPoint`], if it exists and is unspent in the
/// non-finalized `chain` or finalized `db`.
pub fn unspent_utxo<C>(
chain: Option<C>,
db: &ZebraDb,
outpoint: transparent::OutPoint,
) -> Option<Utxo>
where
C: AsRef<Chain>,
{
match chain {
Some(chain) if chain.as_ref().spent_utxos.contains(&outpoint) => None,
chain => utxo(chain, db, outpoint),
}
}

/// Returns the [`Utxo`] for [`transparent::OutPoint`], if it exists in any chain
/// in the `non_finalized_state`, or in the finalized `db`.
///
Expand Down

0 comments on commit 5b8eadc

Please sign in to comment.