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 merkle signer SNARK friendly #3263

Conversation

id-ms
Copy link
Contributor

@id-ms id-ms commented Dec 1, 2021

Summary

In this PR we change how the Merkle key store is being hashed.

  • The index of the merkle leaf is now part of the signature
  • we no longer hash a msgpack representation of the MSS's structs (use of an arbitrary hash input is bad for the SNARK verifier).
  • integrate an updated falcon lib which uses two formats of signature
  • when committing on falcon signature we commit on the CT format

Test Plan

@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch from 7c23285 to e5f410f Compare December 1, 2021 10:42
@codecov-commenter
Copy link

codecov-commenter commented Dec 1, 2021

Codecov Report

Merging #3263 (70f0dd2) into feature/dilithium-scheme-integration (ca330c6) will decrease coverage by 0.00%.
The diff coverage is 62.27%.

Impacted file tree graph

@@                           Coverage Diff                            @@
##           feature/dilithium-scheme-integration    #3263      +/-   ##
========================================================================
- Coverage                                 47.84%   47.83%   -0.01%     
========================================================================
  Files                                       381      382       +1     
  Lines                                     61651    61643       -8     
========================================================================
- Hits                                      29496    29489       -7     
+ Misses                                    28734    28732       -2     
- Partials                                   3421     3422       +1     
Impacted Files Coverage Δ
crypto/invalidsigner.go 55.55% <0.00%> (-15.88%) ⬇️
crypto/merklearray/merkle.go 87.61% <ø> (ø)
crypto/msgp_gen.go 36.22% <ø> (ø)
crypto/sig_abstractions.go 80.95% <ø> (ø)
data/basics/ccertpart.go 0.00% <0.00%> (ø)
ledger/ledgercore/votersForRound.go 0.00% <0.00%> (ø)
crypto/merklekeystore/keystore.go 59.52% <36.00%> (-15.16%) ⬇️
crypto/compactcert/builder.go 65.51% <50.00%> (+0.68%) ⬆️
crypto/merklekeystore/msgp_gen.go 51.96% <56.52%> (+0.47%) ⬆️
crypto/compactcert/verifier.go 65.00% <60.00%> (-4.24%) ⬇️
... and 18 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 ca330c6...70f0dd2. Read the comment docs.

@algonautshant algonautshant self-requested a review December 1, 2021 18:25
@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch from e5f410f to a99b0de Compare December 2, 2021 08:25
crypto/compactcert/builder_test.go Outdated Show resolved Hide resolved
crypto/compactcert/builder_test.go Outdated Show resolved Hide resolved
@@ -36,8 +37,7 @@ import (

type TestMessage string

// TODO: change to CurrentVersion when updated
var CompactCertRounds = config.Consensus[protocol.ConsensusFuture].CompactCertRounds
const CompactCertRoundsForTests = 128

func (m TestMessage) ToBeHashed() (protocol.HashID, []byte) {
Copy link
Contributor

Choose a reason for hiding this comment

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

TestMessage and it's functions do not need to be exported. Use small case for the first letter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've made TestMessage private as you've recommended.
However, ToBeHash is an interface implmenation function so it can't be chagned.


sigBytes := ssc.Sig.Signature.GetSerializedSignature()

sigSlotCommitment := make([]byte, 0, len(binaryLValue)+len(sigBytes))
Copy link
Contributor

Choose a reason for hiding this comment

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

The intend here is to get a fixed sized byte array. However, this function makes no compiler enforced commitment to a fixed size array.
It very difficult to know if GetSerializedSignature will indeed return a fixed size array every time.

// GetVerificationBytes returns a serialized version of the public key data (without the use of the msgpack).
GetVerificationBytes() []byte
// GetSerializedSignature returns a serialized version of the signature
GetSerializedSignature(signature ByteSignature) []byte
Copy link
Contributor

Choose a reason for hiding this comment

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

The problem with implementing this function as an interface is that the caller of GetSerializedSignature will not know what size array it will be receiving.

In some cases, it is important to receive a fixed size array every time. This interface will not permit the compiler to to that enforcement, and in the future someone might change a function implementation which breaks that requirement.

}

// ToBeHashed implements the crypto.Hashable interface.
// In order to create a more SNARK-friendly commitments on the signature we must avoid using the msgpack infrastructure.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change for all uses of ToBeHashed?
Shouldn't this less efficient implementation be restricted only when the target is an SNARK commitment?
If this function is only used in the SNARK context, maybe the name should indicate that this is different, and may not be as efficient to transport as the msgp serialization.

Choose a reason for hiding this comment

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

Agree; see also my comment above about the naming of GetSerializedSignature. The purpose of that function is much narrower than general serialization.

@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch 3 times, most recently from b882c83 to b733a04 Compare December 14, 2021 09:27
@id-ms id-ms linked an issue Dec 15, 2021 that may be closed by this pull request
@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch from b733a04 to da92a85 Compare December 19, 2021 10:07
@id-ms id-ms marked this pull request as ready for review December 20, 2021 10:42
@id-ms id-ms linked an issue Dec 20, 2021 that may be closed by this pull request
@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch 2 times, most recently from b277b6d to bba3ba1 Compare January 4, 2022 11:58
@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch from bba3ba1 to 5445566 Compare January 4, 2022 12:05
@id-ms id-ms force-pushed the make-merkle-signer-snark-friendly branch from ea9a758 to f33bc88 Compare January 4, 2022 17:02
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!
I have some comments, mainly clarifications/comment requests.
Also, I added some comments in #2990 which could be addressed here, since the changes here may be impacted by those.

crypto/falconWrapper.go Show resolved Hide resolved
crypto/falconWrapper.go Show resolved Hide resolved
crypto/falconWrapper.go Outdated Show resolved Hide resolved
crypto/falconWrapper_test.go Show resolved Hide resolved

// Signature is a byte signature on a crypto.Hashable object,
// crypto.GenericVerifyingKey and includes a merkle proof for the key.
Signature struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`
crypto.ByteSignature `codec:"bsig"`

Proof Proof `codec:"prf"`
VerifyingKey crypto.GenericVerifyingKey `codec:"vkey"`
MerkleArrayIndex uint64 `codec:"idx"`
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 please update the comment above (line 30)?
Will be nice to improve the comment by adding some more explanation on Proof, VerifyingKey and MerkleArrayIndex.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agree. let me know if it looks better now.

crypto/merklekeystore/keystore.go Show resolved Hide resolved
)
if err != nil {
return err
}

return sig.VerifyingKey.GetVerifier().Verify(obj, sig.ByteSignature)
return sig.VerifyingKey.GetVerifier().Verify(msg, sig.ByteSignature)
Copy link
Contributor

Choose a reason for hiding this comment

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

In this location, GetVerifier can it return Ed25519Type or it always need to be FalconPublicKey?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the GetVerifier could use ed25519 crypto type. this module is built to support it.

)
if err != nil {
return err
}

return sig.VerifyingKey.GetVerifier().Verify(obj, sig.ByteSignature)
return sig.VerifyingKey.GetVerifier().Verify(msg, sig.ByteSignature)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the Falcon verification is not made only for the root of the merkle tree?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The falcon verification is needed to verify that a given signature is valid under this ephemeral pk.

crypto/compactcert/verifier.go Show resolved Hide resolved
crypto/falconWrapper.go Outdated Show resolved Hide resolved
crypto/falconWrapper.go Show resolved Hide resolved
return d.PublicKey[:]
}

// GetSerializedSignature returns a serialized version of the signature

Choose a reason for hiding this comment

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

The name and documentation do not really match what this function does. It simply converts a byte array from a COMPRESSED-format signature to a CT-format signature; this is orthogonal to serialization. So I would suggest a name like ConvertCompressedToCT. Also, a FalconVerifier is not needed here, and it would be best not to require one.

crypto/merklekeystore/keystore.go Outdated Show resolved Hide resolved
if err := checkKeystoreParams(firstValid, round, interval); err != nil {
return err
}
func (v *Verifier) Verify(round uint64, msg crypto.Hashable, sig Signature) error {

Choose a reason for hiding this comment

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

As far as I can tell so far, the logic of this function (which is the most important part) looks sound and SNARKable, assuming that merklearray.Verify is. But I cannot find that function in this PR. Is it somewhere else?

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 will have a different PR for that.

crypto/sig_abstractions.go Outdated Show resolved Hide resolved
GetVerificationBytes() []byte
// GetSerializedSignature returns a serialized version of the signature
// muse be const sized
GetSerializedSignature(signature ByteSignature) ([]byte, error)

Choose a reason for hiding this comment

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

The name and documentation ("serialized") are not really descriptive of the intended purpose here. It’s more that this is a "hashable (fixed-length) representation" for the SNARK.

}

// ToBeHashed implements the crypto.Hashable interface.
// In order to create a more SNARK-friendly commitments on the signature we must avoid using the msgpack infrastructure.

Choose a reason for hiding this comment

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

Agree; see also my comment above about the naming of GetSerializedSignature. The purpose of that function is much narrower than general serialization.

@id-ms id-ms merged commit b93f0e5 into algorand:feature/dilithium-scheme-integration Jan 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants