Skip to content

Commit

Permalink
Move and rename height_from_signed_int()
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Dec 9, 2022
1 parent 23b6db9 commit f08a54f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 47 deletions.
58 changes: 56 additions & 2 deletions zebra-rpc/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,11 @@ where
.boxed()
}

// TODO: use a generic error constructor (#5548)
// TODO:
// - use a generic error constructor (#5548)
// - use `height_from_signed_int()` to handle negative heights
// (this might be better in the state request, because it needs the state height)
// - create a function that handles block hashes or heights, and use it in `z_get_treestate()`
fn get_block(&self, height: String, verbosity: u8) -> BoxFuture<Result<GetBlock>> {
let mut state = self.state.clone();

Expand Down Expand Up @@ -759,7 +763,11 @@ where
.boxed()
}

// TODO: use a generic error constructor (#5548)
// TODO:
// - use a generic error constructor (#5548)
// - use `height_from_signed_int()` to handle negative heights
// (this might be better in the state request, because it needs the state height)
// - create a function that handles block hashes or heights, and use it in `get_block()`
fn z_get_treestate(&self, hash_or_height: String) -> BoxFuture<Result<GetTreestate>> {
let mut state = self.state.clone();

Expand Down Expand Up @@ -1348,3 +1356,49 @@ fn check_height_range(start: Height, end: Height, chain_height: Height) -> Resul

Ok(())
}

/// Given a potentially negative index, find the corresponding `Height`.
///
/// This function is used to parse the integer index argument of `get_block_hash`.
/// This is based on zcashd's implementation:
/// <https://github.com/zcash/zcash/blob/c267c3ee26510a974554f227d40a89e3ceb5bb4d/src/rpc/blockchain.cpp#L589-L618>
//
// TODO: also use this function in `get_block` and `z_get_treestate`
#[allow(dead_code)]
pub fn height_from_signed_int(index: i32, tip_height: Height) -> Result<Height> {
if index >= 0 {
let height = index.try_into().expect("Positive i32 always fits in u32");
if height > tip_height.0 {
return Err(Error::invalid_params(
"Provided index is greater than the current tip",
));
}
Ok(Height(height))
} else {
// `index + 1` can't overflow, because `index` is always negative here.
let height = i32::try_from(tip_height.0)
.expect("tip height fits in i32, because Height::MAX fits in i32")
.checked_add(index + 1);

let sanitized_height = match height {
None => return Err(Error::invalid_params("Provided index is not valid")),
Some(h) => {
if h < 0 {
return Err(Error::invalid_params(
"Provided negative index ends up with a negative height",
));
}
let h: u32 = h.try_into().expect("Positive i32 always fits in u32");
if h > tip_height.0 {
return Err(Error::invalid_params(
"Provided index is greater than the current tip",
));
}

h
}
};

Ok(Height(sanitized_height))
}
}
48 changes: 3 additions & 45 deletions zebra-rpc/src/methods/get_block_template_rpcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use crate::methods::{
long_poll::LongPollInput, submit_block, transaction::TransactionTemplate,
},
},
GetBlockHash, MISSING_BLOCK_ERROR_CODE,
height_from_signed_int, GetBlockHash, MISSING_BLOCK_ERROR_CODE,
};

pub mod config;
Expand Down Expand Up @@ -294,9 +294,10 @@ where
let latest_chain_tip = self.latest_chain_tip.clone();

async move {
// TODO: look up this height as part of the state request?
let tip_height = best_chain_tip_height(&latest_chain_tip)?;

let height = get_height_from_int(index, tip_height)?;
let height = height_from_signed_int(index, tip_height)?;

let request = zebra_state::ReadRequest::BestChainBlockHash(height);
let response = state
Expand Down Expand Up @@ -711,46 +712,3 @@ pub fn calculate_transaction_roots(

(merkle_root, auth_data_root)
}

// get_block_hash support methods

/// Given a potentially negative index, find the corresponding `Height`.
///
/// This function is used to parse the integer index argument of `get_block_hash`.
fn get_height_from_int(index: i32, tip_height: Height) -> Result<Height> {
if index >= 0 {
let height = index.try_into().expect("Positive i32 always fits in u32");
if height > tip_height.0 {
return Err(Error::invalid_params(
"Provided index is greater than the current tip",
));
}
Ok(Height(height))
} else {
// `index + 1` can't overflow, because `index` is always negative here.
let height = i32::try_from(tip_height.0)
.expect("tip height fits in i32, because Height::MAX fits in i32")
.checked_add(index + 1);

let sanitized_height = match height {
None => return Err(Error::invalid_params("Provided index is not valid")),
Some(h) => {
if h < 0 {
return Err(Error::invalid_params(
"Provided negative index ends up with a negative height",
));
}
let h: u32 = h.try_into().expect("Positive i32 always fits in u32");
if h > tip_height.0 {
return Err(Error::invalid_params(
"Provided index is greater than the current tip",
));
}

h
}
};

Ok(Height(sanitized_height))
}
}

0 comments on commit f08a54f

Please sign in to comment.