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

Make stateproof verifier snark friendly #3895

Merged

Conversation

id-ms
Copy link
Contributor

@id-ms id-ms commented Apr 17, 2022

Summary

The goal of this PR is to change part of the stateproof (compactcert) verifier to be SNARK friendly.
this change contains:
1- The verifier no longer computes the exact number of reveals on the cert. Alternatively, it computes a lower bound on the proven weight.
2- To support 1, the verifier uses a log approximation technic.
3- use SHAKE256 for the coin hashing to be more SNARK friendly
4- use rejection sampling for selecting the next coin
5- the positions to reveal (the result of the coin hashing) are given as part of the cert.

Test Plan

unittest are updated

@id-ms id-ms self-assigned this Apr 17, 2022
@id-ms id-ms linked an issue Apr 17, 2022 that may be closed by this pull request
4 tasks
@id-ms id-ms force-pushed the make-stateproof-verifier-snark-friendly branch from ac56d80 to 6901d2a Compare April 17, 2022 09:23
@codecov-commenter
Copy link

codecov-commenter commented Apr 17, 2022

Codecov Report

Merging #3895 (9c6a06a) into feature/stateproofs (c34780a) will increase coverage by 0.02%.
The diff coverage is 67.37%.

@@                   Coverage Diff                   @@
##           feature/stateproofs    #3895      +/-   ##
=======================================================
+ Coverage                50.06%   50.08%   +0.02%     
=======================================================
  Files                      396      396              
  Lines                    68413    68364      -49     
=======================================================
- Hits                     34251    34242       -9     
+ Misses                   30454    30426      -28     
+ Partials                  3708     3696      -12     
Impacted Files Coverage Δ
crypto/merklesignature/merkleSignatureScheme.go 68.81% <0.00%> (ø)
data/stateproof/message.go 0.00% <ø> (ø)
ledger/ledger.go 60.66% <0.00%> (ø)
data/stateproof/msgp_gen.go 36.25% <12.50%> (-5.94%) ⬇️
crypto/compactcert/msgp_gen.go 39.34% <39.66%> (-2.83%) ⬇️
compactcert/builder.go 66.99% <41.66%> (-2.12%) ⬇️
crypto/compactcert/verifier.go 78.26% <86.66%> (+14.62%) ⬆️
ledger/internal/compactcert.go 77.02% <87.50%> (ø)
crypto/compactcert/builder.go 89.00% <97.91%> (+20.11%) ⬆️
config/consensus.go 85.53% <100.00%> (ø)
... and 17 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c34780a...9c6a06a. Read the comment docs.

@id-ms id-ms requested a review from algonautshant April 19, 2022 15:08
config/consensus.go Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/const.go Outdated Show resolved Hide resolved
crypto/compactcert/const.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
@id-ms id-ms force-pushed the make-stateproof-verifier-snark-friendly branch from 026a39e to 485b44d Compare April 26, 2022 09:06
crypto/compactcert/weights.go Show resolved Hide resolved
crypto/compactcert/weights.go Show resolved Hide resolved
crypto/compactcert/weights.go Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
algoidan and others added 2 commits April 27, 2022 10:24
Co-authored-by: Shant Karakashian <55754073+algonautshant@users.noreply.github.com>
@id-ms id-ms force-pushed the make-stateproof-verifier-snark-friendly branch from 82d799a to 2f03f65 Compare April 27, 2022 07:57
crypto/compactcert/coinGenerator.go Outdated Show resolved Hide resolved
crypto/compactcert/coinGenerator.go Show resolved Hide resolved
crypto/compactcert/coinGenerator.go Outdated Show resolved Hide resolved
crypto/compactcert/coinGenerator.go Outdated Show resolved Hide resolved
crypto/compactcert/coinGenerator.go Show resolved Hide resolved
crypto/compactcert/coinGenerator.go Outdated Show resolved Hide resolved
@id-ms
Copy link
Contributor Author

id-ms commented Apr 28, 2022

@cpeikert could you please take a second look at the coinGenerator.go?
we've removed some unnecessary use of big.Int
https://github.com/algorand/go-algorand/pull/3895/files#diff-4862db594aa7aea35dee5566adeff18c0be35acdd4094abaeb50781613fc964f
Thanks!

@id-ms id-ms force-pushed the make-stateproof-verifier-snark-friendly branch from e929cab to ab2a2ff Compare April 28, 2022 20:37
crypto/compactcert/builder.go Outdated Show resolved Hide resolved
crypto/compactcert/builder.go Show resolved Hide resolved
copy(cpy, b.Params.StateProofMessageHash[:]) // TODO: onmce cfalcon is fixed can remove this copy.
if err := p.PK.VerifyBytes(uint64(b.SigRound), cpy, sig); err != nil {
cpy := make([]byte, len(b.data))
copy(cpy, b.data[:]) // TODO: onmce cfalcon is fixed can remove this copy.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this copy still needed here?
The TODO comment seems can be resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we still have a might have problem with c-falcon. when everything will be ready to merge into master we will remove it.

crypto/compactcert/builder.go Show resolved Hide resolved
crypto/compactcert/builder.go Show resolved Hide resolved
crypto/compactcert/builder.go Outdated Show resolved Hide resolved
crypto/compactcert/builder.go Show resolved Hide resolved
crypto/compactcert/builder.go Show resolved Hide resolved
@@ -115,7 +120,7 @@ func (ccw *Worker) initBuilders() {
continue
}

if builder.Present(pos) {
if isPresent, err := builder.Present(pos); err != nil || isPresent {
Copy link
Contributor

Choose a reason for hiding this comment

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

The error message below needs to be updated here to also consider the possibility of the err and not just isPresent.

crypto/compactcert/builder.go Outdated Show resolved Hide resolved
crypto/compactcert/builder.go Show resolved Hide resolved
crypto/compactcert/builder.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
crypto/compactcert/weights.go Outdated Show resolved Hide resolved
lo := uint64(0)
hi := uint64(len(b.sigs))

again:
if lo >= hi {
return 0, fmt.Errorf("coinIndex: lo %d >= hi %d", lo, hi)
return 0, fmt.Errorf("%w: lo %d >= hi %d", ErrInternalCoinIndexError, lo, hi)
Copy link
Contributor

Choose a reason for hiding this comment

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

This should never happen in the code path. It is expected to have:

b.sigs[0].L = 0 // by construction
b.sigs[last].L + b.sigs[last].Weight == signedWeight  // b.sigs[last].L + b.sigs[last].Weight == signedWeight and coinWeight in [0, signedWeight) 

In case it happens, the error should say something like:
coinIndex unexpected behavior: lo = %d hi = %d coinWeight = %d

}

if hdr.Round != votersHdr.Round+basics.Round(proto.CompactCertRounds) {
err = fmt.Errorf("certifying block %d not %d ahead of voters %d",
err := fmt.Errorf("certifying block %d not %d ahead of voters %d",
Copy link
Contributor

Choose a reason for hiding this comment

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

The convention followed elsewhere in the code, is to identify the reporter of the error, by mentioning the name of the function.
For example:

./cow_creatables.go�155:		return fmt.Errorf("DeleteAppParams: %s not found in deltas for %d", addr.String(), aidx)
./cow_creatables.go�163:		return fmt.Errorf("DeleteAppLocalState: %s not found in deltas for %d", addr.String(), aidx)
./cow_creatables.go�171:		return fmt.Errorf("DeleteAssetHolding: %s not found in deltas for %d", addr.String(), aidx)
./cow_creatables.go�179:		return fmt.Errorf("DeleteAssetParams: %s not found in deltas for %d", addr.String(), aidx)

This convention is not followed in many places in the compactCert code.

@@ -64,15 +64,20 @@ func (ccw *Worker) builderForRound(rnd basics.Round) (builder, error) {
}
ccw.Message = msg

p, err := ledger.CompactCertParams(msg, votersHdr, hdr)
provenWeight, err := ledger.GetProvenWeight(votersHdr, hdr)
if err != nil {
return builder{}, err
Copy link
Contributor

Choose a reason for hiding this comment

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

Returning the error directly like this is problematic. When eventually the error is logged or reported to the user, it will be very difficult, if not impossible, to know where the error came from.
The convention followed is to wrap the received error before reporting it upwards.
For example, see below (which should be %w and not %v):

		ccw.log.Warnf("ccw.handleSigMessage(): decode: %v", err)

compactcert/builder.go Outdated Show resolved Hide resolved
compactcert/builder.go Outdated Show resolved Hide resolved
compactcert/builder.go Outdated Show resolved Hide resolved
compactcert/builder.go Outdated Show resolved Hide resolved
compactcert/builder.go Outdated Show resolved Hide resolved
compactcert/builder.go Outdated Show resolved Hide resolved
id-ms and others added 2 commits May 4, 2022 09:42
Co-authored-by: Shant Karakashian <55754073+algonautshant@users.noreply.github.com>
Copy link
Contributor

@algonautshant algonautshant left a comment

Choose a reason for hiding this comment

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

Looks great!
The logic implementation is correct, well structured, and readable. Very well documented.
I don't have any more suggestions to change anything.
The tests cover the code very well.
Thank you for addressing my previous comments.

A few areas needs some improvement, which can be addressed in a separate PR:

  • The error reporting in many places do not list the function generating the error. These error messages need updating to identify the function generating them, as is the convention in the code.
  • When a function gets an error and returns it, it needs to wrap it and identify itself, so that when the error is logged upstream, not only the originator of the error is identified, but also the context in which the error occurred.
  • The tests do not cover many of the error cases. Most of these cases are fairly simple and basic, but some of them report in the error messages, local variable values. If these messages are not tested, possible panic situation may go unnoticed, and the program panics when it should just be an error.

crypto/compactcert/builder.go Outdated Show resolved Hide resolved
if !s.Signature.IsVersionEqual(version) {
return ErrInvalidSignatureVersion
// IsSaltVersionEqual validates that the version of the signature is matching the expected version
func (s *Signature) IsSaltVersionEqual(version byte) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

We need a test for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is being tested in TestFalconSignature_ValidateVersion and more important, it is being tested in TestBuilder_AddRejectsInvalidSigVersion .

@@ -267,23 +267,23 @@ func (v *Verifier) VerifyBytes(round uint64, msg []byte, sig Signature) error {
func (s *Signature) GetFixedLengthHashableRepresentation() ([]byte, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unit test is missing for this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is being tested here TestSimulateSignatureVerification

crypto/compactcert/builder_test.go Show resolved Hide resolved
crypto/compactcert/builder_test.go Outdated Show resolved Hide resolved
crypto/compactcert/builder.go Show resolved Hide resolved
crypto/compactcert/builder_test.go Outdated Show resolved Hide resolved
crypto/compactcert/builder_test.go Show resolved Hide resolved
crypto/compactcert/builder_test.go Outdated Show resolved Hide resolved
crypto/compactcert/verifier_test.go Show resolved Hide resolved
@id-ms id-ms merged commit 8a53a76 into algorand:feature/stateproofs May 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

make stateproofs verification SNARK-friendly
3 participants