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

feat: Honk recursive verifier Pt. 1 #1488

Merged
merged 15 commits into from
Aug 18, 2023
Merged

Conversation

ledwards2225
Copy link
Contributor

@ledwards2225 ledwards2225 commented Aug 9, 2023

Early-stage UltraHonk recursive verifier.

The idea is to have a single UltraVerifier class that is instantiated with a genuine builder for recursive verification and a simulated builder for native verification. (This is as opposed to Plonk which has two separate implementations). Some notes:

  • At the moment I've created a UltraRecursiveVerifier_ in the stdlib. It is essentially a duplicate of the existing UltraVerifier_ with some very minor changes. Once a Simulator is in place, this will become the one and only verifier and the original will be deleted.
  • Although the UltraRecursiveVerifier_ itself is duplicated from UltraVerifier_, the bulk of the actual verification logic takes place in the SumcheckVerifier, GeminiVerifier, and ShplonkVerifier, which are not duplicated; they are the same classes used by the native verifier. The only addition is a handful of constexpr if's to facilitate differences between native and stdlib behavior, e.g. performing a batch mul (stdlib) vs doing naive accumulation (native).

Checklist:

Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.

  • If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag.
  • I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code.
  • Every change is related to the PR description.
  • I have linked this pull request to relevant issues (if any exist).

@ledwards2225 ledwards2225 changed the title Lde/recursive verifier feat: Honk recursive verifier Aug 9, 2023
@ledwards2225 ledwards2225 self-assigned this Aug 9, 2023
@ledwards2225 ledwards2225 changed the title feat: Honk recursive verifier feat: Honk recursive verifier Pt. 1 Aug 9, 2023
@maramihali maramihali added the crypto cryptography label Aug 10, 2023
@ledwards2225 ledwards2225 force-pushed the lde/recursive_verifier branch 4 times, most recently from bd0057b to 8e07148 Compare August 16, 2023 21:25
@@ -186,136 +186,7 @@ ProverOutput<Curve> GeminiProver_<Curve>::compute_fold_polynomial_evaluations(st
return { fold_poly_opening_pairs, std::move(fold_polynomials) };
};

Copy link
Contributor Author

@ledwards2225 ledwards2225 Aug 16, 2023

Choose a reason for hiding this comment

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

I've moved the definitions of the the GeminiVerifier methods back to the header. This avoids a lot of pain, at least while we need to instantiate it with both native and stdlib Curves. It should be easy to revert once this is no longer the case (see bberg issue no. 673)

@@ -250,25 +250,6 @@ template <class FF, typename Tuple, std::size_t Index = 0> static constexpr auto
}
}

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is unrelated to this work but was unused and should have been removed previously.

@ledwards2225 ledwards2225 force-pushed the lde/recursive_verifier branch from 779f3c2 to af0eae8 Compare August 17, 2023 16:34
Copy link
Contributor

@maramihali maramihali left a comment

Choose a reason for hiding this comment

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

looks good, only had some comments for things that were a bit unclear

* @tparam T
* @tparam LENGTH (used only for containers which specify a length, e.g. array/Univariate)
*/
template <typename T, size_t LENGTH = 0> struct CorrespondingNativeType {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at how this is used in the codem shortening the name to NativeType would still make sense, so it's not that verbose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

}

/**
* @brief This function verifies an Ultra Honk proof for given program settings.
Copy link
Contributor

Choose a reason for hiding this comment

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

not related to this PR but program setting is from an older version of the proof system and should be replaced by flavor, right? (same for the UltraVerifier)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated, thanks

const auto pub_inputs_offset = transcript.template receive_from_prover<uint32_t>("pub_inputs_offset");

// Extract native integer types for these basic quantities for use in subsequent operations
auto circuit_size_native = static_cast<size_t>(circuit_size.get_value());
Copy link
Contributor

Choose a reason for hiding this comment

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

This was a bit confusing to look at. I presume subsequent operations expect size_t and you get uint32_t from the transcript which is why this is needed but I would rather just cast on circuit_size and avoid creating a circuit_size_native(same for the other things).

Copy link
Contributor Author

@ledwards2225 ledwards2225 Aug 18, 2023

Choose a reason for hiding this comment

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

I agree this is ugly. Its a bit more complicated than what you described because when we extract these quantities from the transcript in the recursive setting they are field_t's representing simple quantities (circuit size, public input size, etc.). However, in certain places we need to use them as simple (native) integers (e.g. in the loop below for extracting the public inputs from the transcript). So we could avoid naming these things and just use static_cast<size_t>(stdlib_type.get_value()) if you think that's more clear. Maybe just a better name than "..._native" would be best?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Went ahead and just ditched these in favor of using the static cast in place. Don't love that either but it might be more clear than defining these additional variables

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah it took me a bit to understand the point of native variables and I think the in-place cast (and maybe comments why they're there) might be better

info("Batched eval: num gates = ", builder->get_num_gates() - prev_num_gates);
prev_num_gates = builder->get_num_gates();

// Construct vectors of scalars for batched unshifted and to-be-shifted commitments
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add some more detailed comments here why this diverges from the native implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment added


// Confirm that the native and stdlib transcripts have generated the same manifest
// Confirm that the native and stdlib verifier transcripts have generated the same manifest
EXPECT_EQ(transcript.get_manifest(), native_transcript.get_manifest());

// TODO(luke): This doesn't check much of anything until hashing is constrained in the stdlib transcript
Copy link
Contributor

Choose a reason for hiding this comment

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

what does this mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I implemented the stdlib Transcript for Honk, I "stubbed out" the hashing portion, i.e. it does not currently lay down contraints to emulate hashing. I did this at Codys suggestion for expediency since it was a big pain to get the result to agree with the native hash (pedersen + blake3) and we are going to be changing the hash very soon anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the issue number and a clearer comment

@@ -3,6 +3,12 @@
#include <algorithm>
#include <array>

// TODO(#674): We need the functionality of BarycentricData for both field and field_t. The former is "literal" i.e. is
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// TODO(#674): We need the functionality of BarycentricData for both field and field_t. The former is "literal" i.e. is
// TODO(#674): We need the functionality of BarycentricData for both field and field_ct. The former is "literal" i.e. is

Copy link
Contributor Author

Choose a reason for hiding this comment

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

field and field_t are the names of class templates (native and stdlib, respectively), field_ct is an alias for the specialization of field_t with a particular builder. So I think field and field_t are the correct terms here

Copy link
Contributor

Choose a reason for hiding this comment

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

ah, I see, misunderstood all of this, thanks for clarifying

@@ -3,6 +3,12 @@
#include <algorithm>
#include <array>

// TODO(#674): We need the functionality of BarycentricData for both field and field_t. The former is "literal" i.e. is
// compatible with constexpr operations, and the former is not. The functions for computing the pre-computable arrays in
Copy link
Contributor

Choose a reason for hiding this comment

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

hm literal is a confusing term - i think native (which, at least for me, means non-circuit stuff) is more appropriate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Literal is a c++ term/concept which roughly means "compatible with constexpr expressions". Apparently the concept is being deprecated since this is actually quite difficult to define. Anyway, for our purposes, native vs stdlib is really the important distinction so I've gotten rid of the term "literal"

Copy link
Contributor

Choose a reason for hiding this comment

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

ah! the more you know about c++. Are concepts all together being deprecated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No definitely not. There used to be a std::is_literal_type method that when called on our field would return true (indicating that it's 'constexpr' in some sense). But this particular concept is apparently quite tricky to define so the recommendation is to define your own concept that more specifically qualifies the stuff you need. For example, does it have a constexpr constructor and assignment operator, etc.

@@ -14,6 +14,19 @@ TYPED_TEST_SUITE(BarycentricDataTests, FieldTypes);

#define BARYCENTIC_DATA_TESTS_TYPE_ALIASES using FF = TypeParam;

/**
* @brief Ensure auxilliary arrays (e.g. big_domain) are computed at compile time if possible (i.e. if FF is literal)
Copy link
Contributor

Choose a reason for hiding this comment

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

first, I noticed literal here and was confused what you are refering to

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed language to native

inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
}
// If recursion, invert elements individually, otherwise batch invert
Copy link
Contributor

Choose a reason for hiding this comment

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

add a comment explaining that inversion is quite cheap in circuits and there's no need for batching

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added


namespace proof_system::honk::flavor {

class UltraRecursive {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a comment that this class is mostly similar to the Ultra flavor class except the curve is intantiated with the stdlib types and you have removed stuff that is only relevant for the prover (since only a verifier is instantiated with UltraRecursive)? and other differences that maybe I haven't spotted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks, done

@ledwards2225 ledwards2225 force-pushed the lde/recursive_verifier branch from af0eae8 to 6a22879 Compare August 18, 2023 16:40
@ledwards2225 ledwards2225 merged commit 4669555 into master Aug 18, 2023
@ledwards2225 ledwards2225 deleted the lde/recursive_verifier branch August 18, 2023 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto cryptography
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants