Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zcash_client_sqlite: BlockSource::with_blocks impls behave unintuitively with from_height set to an unknown block #892

Closed
str4d opened this issue Aug 9, 2023 · 2 comments
Labels

Comments

@str4d
Copy link
Contributor

str4d commented Aug 9, 2023

BlockSource::with_blocks is documented thusly:

/// Scan the specified `limit` number of blocks from the blockchain, starting at
/// `from_height`, applying the provided callback to each block. If `from_height`
/// is `None` then scanning will begin at the first available block.

The documentation is clear that from_height = Some(h) means "scan from height h", while from_height = None means "scan from the first available block". However, it is not clear what should happen if from_height = Some(h) but h is unknown to the cache.

The implementations of this trait in zcash_client_sqlite behave similarly to the None case: up to limit blocks are made available starting from the first block with height >= h that the cache knows about. This is due to the following SQL query being used:

let mut stmt_blocks = block_source
.0
.prepare(
"SELECT height, data FROM compactblocks
WHERE height >= ?
ORDER BY height ASC LIMIT ?",
)
.map_err(to_chain_error)?;
let mut rows = stmt_blocks
.query(params![
from_height.map_or(0u32, u32::from),

(and equivalently for FsBlockDb).

This behaviour crept in across several refactors:

I found this issue because in some tests, the iOS SDK incorrectly set from_height = 0 as a side-effect of earlier logic, but due to the unintuitive behaviour of the FsBlockDb::with_blocks impl, it "self-corrected" to the intended first block in the database, hiding the bug (until it was exposed due to the change to move continuity testing into scan_cached_blocks).

We need to decide what the intended behaviour of BlockSource::with_blocks is, and then ensure that the documentation and implementations are consistent with it.

@str4d str4d added the bug label Aug 9, 2023
@str4d str4d changed the title zcash_client_sqlite: BlockSource::with_blocks impls behave unintuitively with from_height before any known block zcash_client_sqlite: BlockSource::with_blocks impls behave unintuitively with from_height set to an unknown block Aug 9, 2023
@str4d
Copy link
Contributor Author

str4d commented Aug 9, 2023

Possible behaviours:

  • Keep it as-is: start scanning from whichever cache block is known above that height.
  • Scan zero blocks (because there are none to scan that are known to the cache starting from that height).
  • Scan as many blocks as are known that fall in the range from_height..(from_height + limit).
  • Return an error (i.e. require the caller to only set from_height = Some(h) if h exists in the cache).

@nuttycom
Copy link
Contributor

nuttycom commented Aug 9, 2023

I think that if the specified block height isn't available in the cache, we should return an error; having the scan silently skip over part of the range is likely to cause subtle misbehavior that is difficult to debug, whereas handling the error is easy - just go get the block.

str4d added a commit that referenced this issue Aug 9, 2023
Previously this was not clearly specified, and the implementations in
`zcash_client_sqlite` behaved similarly to when `from_height = None`.

Closes #892.
@str4d str4d closed this as completed in 44abd34 Aug 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants