-
Notifications
You must be signed in to change notification settings - Fork 120
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
Implement Trusted Vector Preallocation #1920
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing all this work, it looks great.
I'd like some tests to make sure that the maximum preallocation is within the maximum block or message size. Otherwise, the code is really good.
I also have a bunch of suggestions and nitpicks around documentation.
While reviewing this PR, I discovered that Zebra preallocates a few other types. So after the fix in #1925 merges, this PR will need a SafePreallocate
impl for JoinSplitData
, String
, and Script
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also discovered String
and Script
preallocations, which I fixed in #1925.
Note that equihash::Solution
and transparent::Input::Coinbase
also do manual allocations, but their checks are very strict.
Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net>
Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit
Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net>
Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit
Looks like you're ready for another review here. I should get to it next week, but we're prioritising the Orchard network upgrade right now, so it might slip to early the week after. |
Fix imports in block.rs
Looks good so far, see preston-evans98#1 for a fix to the merge conflict with #1946. We'll probably want to move the tests to their own modules inside each test submodule. But we can do that in a follow-up PR. I'm just doing some testing now, then I'll do a detailed review early next week. |
Resolve merge conflict and implement TrustedPreallocate for Spend<SharedAnchor>
The Google Cloud Build error is a network failure downloading the Rust docker image. |
#[test] | ||
/// Confirm that each MetaAddr takes exactly META_ADDR_SIZE bytes when serialized. | ||
/// This verifies that our calculated `TrustedPreallocate::max_allocation()` is indeed an upper bound. | ||
fn meta_addr_size_is_correct() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MetaAddr
tests should be proptests, but I can make that change in a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(In case we add more address types in future, for example, Tor onion addresses.)
#[test] | ||
/// Confirm that each InventoryHash takes exactly INV_HASH_SIZE bytes when serialized. | ||
/// This verifies that our calculated `TrustedPreallocate::max_allocation()` is indeed an upper bound. | ||
fn inv_hash_size_is_correct() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, the inv tests should be proptests, in case we add more variants in future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
Let's merge this now, then I'll submit 2 small cleanup PRs.
Motivation
Resolve #1880.
Solution
Implement the
SafePreallocate
trait, setting sane limits on blind preallocation of vectors. Implement proptests (where applicable) and unit tests to verify that the limits set by SafePreallocate are loose enough that all structurally valid messages can be deserialized.This implementation deviates from the specification in #1880 in order to remove the use of
min_specialization
. Instead, we tighten the trait bound fromimpl<T> zcash_deserialize for Vec<T>
, toimpl<T: SafePreallocate> zcash_deserialize for Vec<T>
, and implementSafePreallocate
for all necessary types. If we need to deserialize a Vector type which can't be safely PreAllocated in future, we'll just have to write a manual impl for it.Also note that the bounds in this implementation differ slightly from those in #1880 in order to remove special cases. For example, we don't set the
max_allocation()
forMetaAddr
to 1000 as described in the Bitcoin specification. Instead, we set the limit based on theMAX_PROTOCOL_MESSAGE_SIZE
and the serialized length of a MetaAddr. This mitigates the risk of that future changes to the Zcash protocol will render the bounds in SafePreallocate obsolete, potentially causing Zebra to fall out of consensus.The code in this pull request has:
Review
This is low priority. @teor2345
Related Issues
#1880, #1917
Follow Up Work
Improve the efficiency of the proptests for
SafePreallocate
.