-
Notifications
You must be signed in to change notification settings - Fork 249
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
equihash: Add Rust API for Tromp solver #1083
base: main
Are you sure you want to change the base?
Conversation
cb60b5b
to
f3ea80e
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1083 +/- ##
==========================================
+ Coverage 63.23% 66.82% +3.58%
==========================================
Files 124 134 +10
Lines 14507 19622 +5115
==========================================
+ Hits 9174 13113 +3939
- Misses 5333 6509 +1176 ☔ View full report in Codecov by Sentry. |
8e66e0d
to
d33ec1d
Compare
Force-pushed to clean up the commit history; no changes to @teor2345's changes, just regrouping them (and squashing some of the fixes into the original commits that didn't make sense to keep in standalone commits). |
d33ec1d
to
9dbdf18
Compare
Force-pushed to GitHub-linkify an imported source link in a commit message. |
And somehow I managed to click two wrong buttons in a row 🤦 |
.collect() | ||
.collect(); | ||
|
||
// Just in case the solver returns solutions that become the same when compressed. |
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 don't think this should ever be the case. The compressed representation should not be lossy, it just packs the indices together to remove the effective padding bits that exist in the u32
representation.
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.
It may not have been observed, or there could be a subtle difference between the C code and the Rust code in compress_array()
.
Update: Yeah, something must be wrong if identical solutions were observed, I'll check for changes to the logic in equi_miner.c
, everything else looks equivalent to the zcashd logic.
Update: Duplicate solutions were observed prior to a bug fix, is there any chance that the solver could produce duplicate uncompressed solutions?
@@ -70,13 +71,21 @@ unsafe fn worker(eq: *mut CEqui, p: verify::Params, curr_state: &State) -> Vec<V | |||
let nsols = equi_nsols(eq); | |||
let sols = equi_sols(eq); | |||
let solution_len = 1 << p.k; | |||
//println!("{nsols} solutions of length {solution_len} at {sols:?}"); |
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'm inclined to remove this and the other introduced debugging print statements, unless anyone else disagrees.
9dbdf18
to
b201c10
Compare
Force-pushed to clean up the feature flagging in the build script, and add C |
b201c10
to
be16706
Compare
Rebased on current |
Source: zcash/zcash@01d5576 License: MIT
Source: zcash/zcash@01d5576 License: MIT
Co-authored-by: teor <[email protected]>
This avoids linker errors by removing cycles.
Co-authored-by: teor <[email protected]>
be16706
to
ed22417
Compare
Rebased on |
ed22417
to
6571aa9
Compare
Force-pushed to move the new minimal-form compression methods into the new submodule from #1357. |
…rees Also includes some redundant cleanup code for defense in depth.
Source: mikepb/endian.h@0f885cb License: Public Domain (or "BSD OR MIT OR Apache-2.0")
The equivalent change is made to the C worker, which is unused.
6571aa9
to
76131db
Compare
Force-pushed to adjust the minimal-form compression method APIs and integrate them into the existing tests. |
/// `next_nonce` function. | ||
/// | ||
/// Returns zero or more unique solutions. | ||
pub fn solve_200_9<const N: usize>( |
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 don't think there is value in exposing the API for uncompressed solutions; block headers only use compressed solutions, and this crate's other existing API is only for verifying compressed solutions. So I'll probably just make this internal.
What I do want to think about before merging is how to handle configurable parameters. We will need at least two parameter sets (for mainnet and regtest), and depending on how that will be enabled in the C code, we might end up supporting any parameter set. But if we don't then we should probably instead have an enum or a generic parameter for selecting which Equihash parameters to solve with.
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 don't think there is value in exposing the API for uncompressed solutions; block headers only use compressed solutions, and this crate's other existing API is only for verifying compressed solutions. So I'll probably just make this internal.
This is currently true for Zebra's use case. I see no harm in exposing the API for uncompressed solutions either, so solutions could be compressed outside this crate more easily (though it seems unlikely that anyone will actually do that).
What I do want to think about before merging is how to handle configurable parameters. We will need at least two parameter sets (for mainnet and regtest), and depending on how that will be enabled in the C code, we might end up supporting any parameter set. But if we don't then we should probably instead have an enum or a generic parameter for selecting which Equihash parameters to solve with.
It may be useful to allow for configurable parameters for custom testnets to allow for picking even easier parameters instead of disabling PoW checks altogether for ephemeral testnets, or harder ones than those used by regtest for testnets that are intended to be used for longer periods.
Let me know what you decide so we can make the parameters configurable in Zebra if they're configurable here.
Update: Configurable parameters don't seem easy to add, let's allow the Regtest parameters later but leave it there.
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.
This looks like it should work so far, and none of my suggestions are blockers, feel free to resolve any/all of them without making changes.
I'm still reviewing equi_miner.c
in detail, but everything else looks equivalent to the logic in zcashd, at least for the Mainnet parameters.
Update: Collision errors are still being logged here (and DuplicateIdxs errors).
@@ -0,0 +1,47 @@ | |||
// Equihash solver | |||
// Copyright (c) 2016-2016 John Tromp, The Zcash developers |
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.
// Copyright (c) 2016-2016 John Tromp, The Zcash developers | |
// Copyright (c) 2016 John Tromp, The Zcash developers |
// example on how to get the endian conversion functions on different | ||
// platforms. | ||
|
||
// Downloaded from https://raw.githubusercontent.com/mikepb/endian.h/master/endian.h |
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.
// Downloaded from https://raw.githubusercontent.com/mikepb/endian.h/master/endian.h | |
// Downloaded and modified from https://raw.githubusercontent.com/mikepb/endian.h/master/endian.h |
// https://github.com/zcash/zcash/blob/6fdd9f1b81d3b228326c9826fa10696fc516444b/src/crypto/equihash.cpp#L39-L76 | ||
#[cfg(any(feature = "solver", test))] | ||
fn compress_array(array: &[u8], bit_len: usize, byte_pad: usize) -> Vec<u8> { | ||
let index_bytes = (u32::BITS / 8) as usize; |
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.
For consistency:
let index_bytes = (u32::BITS / 8) as usize; | |
let index_bytes = size_of::<u32>(); |
) | ||
.wrapping_shl(8 * (in_width - x - 1) as u32); // Big-endian |
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.
This seems like an unnecessary change from the c++ logic, it should panic in minimal_from_indices()
before it gets here when using parameters that would be affected by the change.
) | |
.wrapping_shl(8 * (in_width - x - 1) as u32); // Big-endian | |
) << (8 * (in_width - x - 1) as u32); // Big-endian |
#[cfg(any(feature = "solver", test))] | ||
pub(crate) fn minimal_from_indices(p: Params, indices: &[u32]) -> Vec<u8> { | ||
let c_bit_len = p.collision_bit_length(); | ||
let index_bytes = (u32::BITS / 8) as usize; |
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.
For consistency:
let index_bytes = (u32::BITS / 8) as usize; | |
let index_bytes = size_of::<u32>(); |
_f: [u8; 0], | ||
_m: PhantomData<(*mut u8, PhantomPinned)>, |
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.
Could we add a short explanation here?
eq->blake2b_update(state, (uchar *)&leb, sizeof(u32)); | ||
eq->blake2b_finalize(state, hash, HASHOUT); | ||
eq->blake2b_free(state); | ||
// Avoid use-after-free and double-free |
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.
It may be a good idea to add this warning to the blake2b_free()
function docs too.
No description provided.