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

Chia proof of space re-implementation #1448

Merged
merged 3 commits into from
May 12, 2023
Merged

Conversation

nazar-pc
Copy link
Member

This is a re-implementation of Chia proof of space in Rust (just the first phase) and fixes #1400

Specification: https://www.notion.so/subspacelabs/PoS-Specification-WIP-08339021db504ce9aa0be6cc2f52a949
Research forum discussion: https://forum.subspace.network/t/performance-of-chia-proof-of-space-re-implementation-in-rust/1478

Here are comparison number, where chia2 is the new implementation:

chia/table                time:   [262.84 ms 263.50 ms 264.42 ms]
chia2/table               time:   [171.15 ms 172.83 ms 174.47 ms]

chia/quality/no-solution  time:   [56.601 ns 56.745 ns 57.000 ns]
chia2/quality/no-solution time:   [20.777 ns 20.827 ns 20.864 ns]

chia/quality/solution     time:   [122.24 µs 122.32 µs 122.47 µs]
chia2/quality/solution    time:   [121.94 ns 122.10 ns 122.35 ns]

chia/proof                time:   [556.02 µs 556.67 µs 557.44 µs]
chia2/proof               time:   [477.94 ns 478.27 ns 478.79 ns]

chia/verification         time:   [34.580 µs 34.800 µs 34.959 µs]
chia2/verification        time:   [12.331 µs 12.333 µs 12.334 µs]

Here is an implementation guide:

  • chia feature, module and enum variant were renamed to chia-legacy
  • new Rust version is added as chia and used by default
  • chiapos module is where Chia proof of space implementation lives, we still use it as a black box just like the C++ version
    • table is implementation of Chia tables (1st to 7th)
    • tables is a higher level abstraction generic over K that allows creation of tables, querying qualities and proofs and has static method for verifying proofs
    • chiapos module exposes tables for specific K supported by current platform (larger K are not supported on 32-bit platforms), also limits K to only those that make the most sense (all K can be enabled with all-chia-k feature flag and increases compilation time significantly)

You may notice a bunch of experimental and even incomplete (generic_const_exprs) Rust features used. The idea behind architecture is to make implementation generic over K while keeping data structures compact and efficient. This is possible with nightly Rust, though awkward at times and generic bounds are quite large (I had a revision where bounds were over 100 lines long, but thankfully was able to get away without that).

While new implementation is faster, it is still not as fast as could be. Once we settle with specific K or very narrow range of K we can optimize it further, there are still compute-bound aspects of the algorithm. C++ chiapos while is slower overall, still manages to derive the first table faster than Rust (is uses much more memory though). It is still beneficial to have generic implementation first such that we can compare it against reference implementation.

table tests are derived from chiapos and are passing successfully. At the same time tables results are not matching C++ and with @dariolina we were not yet able to figure out why. They do a few strange things in the implementation comparing to the paper (see to_chia_seed in tests for instance). But we do have tests that ensure new implementation is self-consistent: qualities and proofs match, valid proofs verify successfully, invalid proofs fail to verify. Overall we decided this is good enough for now to land, but it is a breaking change unfortunately.

Earlier revisions used bitvec create, which was nice, but slow for our use case, very slow. I then write copy_bits function that required a lot of mental gymnastics and still has bitvec sanity check in debug builds to ensure it works properly (it is very tricky, there might still be bugs). There are still improvements that can be done to copy_bits, but quick attempts didn't show massive improvement and given the fact that we'll do K-specific bit manipulation in the future rather than generic bit copying anyway didn't seem worth it. I may refactor copy_bits into a generic standalone library, it seems to be generally useful for Rust ecosystem.

Overall with these changes I was able to get sub-0.5s proving time on my machine:

proving/memory          time:   [351.41 ms 373.59 ms 393.84 ms]
                        thrpt:  [2.5391  elem/s 2.6767  elem/s 2.8456  elem/s]

I tried to leave comments around tricky parts of the implementation, but let me know if something is still not clear. I'm happy to do another implementation walk-though and some diagrams.

Code contributor checklist:

@nazar-pc nazar-pc added performance Related to performance measurement or improvement breaking-consensus This PR introduces breaking changes to the consensus labels May 10, 2023
@nazar-pc nazar-pc requested a review from rg3l3dr as a code owner May 10, 2023 07:02
@nazar-pc nazar-pc force-pushed the chiapos-reimplementation branch 2 times, most recently from 57f7be8 to 0b8ab04 Compare May 10, 2023 14:27
dariolina
dariolina previously approved these changes May 11, 2023
Copy link
Member

@dariolina dariolina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disclaimer for visibility/audits: The new implementation almost exactly matches the Chia's reference implementation (chiapos) results. It finds all the proofs chiapos finds for the same seed & challenge. When there's just one proof for a challenge, our results match chiapos perfectly. However, there are a couple of differences:

  • We find 0.02% more proofs in cases where chiapos misses some due to compression in phase 4. Those proofs are present in chiapos after phase 1, but aren't recoverable after phase 4 (dropped here).

  • When multiple proofs exist for the same challenge, we pick the "first" proof, but it might not be the same as chiapos' first proof because of the reordering it does in later phases. Our proof still matches one of the chiapos proofs for that challenge, but not always the first one.

  • Regarding quality values, the two values chiapos finds are present in our proof. Still, it's difficult to choose their positions in the same way as chiapos due to the reordering it does in later phases.

At this stage, I believe it's best not to spend more time trying to match Chia tests exactly, as our goal isn't to create a Chia network plotter. As a generic PoS implementation, I take the responsibility of declaring it, perfectly good to be integrated with the rest of the protocol.

@nazar-pc
Copy link
Member Author

nazar-pc commented May 11, 2023

Updated test test_against_chiapos to match what @dariolina wrote above: we can verify C++ chiapos's proofs, C++ chiapos can verify our proofs, but they are in different order and sometimes C++ chiapos throws exceptions (there are still bugs there for small k) when we consider proofs are missing.

UPD: Pushed again with additional comments.

@nazar-pc nazar-pc force-pushed the chiapos-reimplementation branch from 4d19fe6 to 8199410 Compare May 11, 2023 10:02
@nazar-pc nazar-pc requested a review from dariolina May 11, 2023 10:03
@nazar-pc
Copy link
Member Author

Merging, feel free to leave review even after merge though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-consensus This PR introduces breaking changes to the consensus performance Related to performance measurement or improvement
Projects
Development

Successfully merging this pull request may close these issues.

Remove extra phases from Chia PoSpace implementation
2 participants