Conversation
Test Results 5 files ± 0 221 suites ±0 31m 42s ⏱️ - 1h 31m 44s Results for commit e7813b5. ± Comparison against base commit f7f05f6. This pull request removes 58 and adds 25 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
f50c0ea to
e3cd4c0
Compare
e3cd4c0 to
2ce5e81
Compare
34044ba to
a3d540b
Compare
a3d540b to
2f25caa
Compare
26449d5 to
9328dfd
Compare
| .configuration_for_aggregation | ||
| .protocol_parameters, | ||
| #[cfg(feature = "future_snark")] | ||
| data.epoch.offset_to_signer_retrieval_epoch_saturating(), |
There was a problem hiding this comment.
question(blocking): why did you choose to offset_to_signer_retrieval_epoch_saturating?
There was a problem hiding this comment.
I chose those values because they match what is done in the inform_epoch() function to get the signer_retrieval_epoch and next_signer_retrieval_epoch that are used to get current_signers_with_stake and next_signers_with_stake. The same offset function is used in update_next_signers_with_stake to get next_signers_with_stake before calling precompute_epoch_data. It is possible that this is wrong but it looks consistent
| .configuration_for_next_aggregation | ||
| .protocol_parameters, | ||
| #[cfg(feature = "future_snark")] | ||
| data.epoch.offset_to_next_signer_retrieval_epoch(), |
There was a problem hiding this comment.
question(blocking): why did you choose to offset_to_next_signer_retrieval_epoch?
There was a problem hiding this comment.
See the answer above
| if *entry < existing { | ||
| self.registered_keys_for_concatenation | ||
| .remove(&existing.get_verification_key_for_concatenation()); | ||
| self.registration_entries.remove(&existing); | ||
| } else { | ||
| return Ok(()); | ||
| } |
There was a problem hiding this comment.
issue(blocking): if there is a collision with an existing Schnorr verification key, we keep the one with lower stake, but the BLS verification key is also removed. This could create a split in the effective computation of the AVK by the different versions of the signers and aggregators, and thus stop the certification. Only the Schnorr part should be impacted and not the BLS part with an update of the existing entry instead of a replace. Can you add a test that verifies the expected behavior first, make sure that it breaks and then make it green?
There was a problem hiding this comment.
I update the registration to remove the snark key of entry when it is a duplicate with higher stake
the Schnorr signing key can create the proof by signing a DST, prefix and its verification key the verification key can verify the proof given the prefix
It stores the stake, epoch and pool id and can convert them into a prefix used in the PoBP
…izer and KeyReg - added creation of the pobp to the Initializer struct - added pobp field to StmInitializerWrapper, updated setup, to/from_bytes and added an accessor to the new field - StmInitializerWrapper strip_snark_keys now also removes pobp - updated KeyRegWrapper implementation and added wrapper for StandardSchnorrSignature - KeyRegWrapper now has a verify_proof_of_bound_possession_for_snark function that is called in register()
added proof_of_bound_possession_for_snark field and updated the implemented functions added proof of bound possession field to diverse entities in common, signer and aggregator
added an epoch field to MithrilFixtureBuilder/MithrilFixture and a build_at_epoch/with_epoch entrypoint threaded a real epoch through the test crypto_helper setup functions (previously stubbed to Epoch::default()) added fake_data::signers_with_stakes_at_epoch and the TEST-ONLY init_state_from_fixtures/init_state_from_fixtures_for_genesis container methods, needed when current/next signer sets require different PoBP epochs
…gator threaded the pobp and epoch parameters through signer, common and aggregator un-gated the verify epoch param so mockall automock derives correctly fixed epoch problems in tests and adopted the new build_at_epoch/signers_with_stakes_at_epoch/init_state_from_fixtures helpers across the test suite
for the correctness of the PoBP for the correctness of the deduplication
…snark values not just None
…n for the proof of bound possession
…sion and added an epoch field to KeyRegWrapper
and updated register function doc comment
…hash, id and bytes)
… for the correct epochs
ddab23d to
e7813b5
Compare
| /// Set the epoch for which the signers' Proof of Bound Possession will be created. | ||
| #[cfg(feature = "future_snark")] | ||
| pub fn with_epoch(mut self, epoch: Epoch) -> Self { | ||
| self.epoch = epoch; | ||
| self | ||
| } | ||
|
|
||
| /// Transform the specified parameters to a [MithrilFixture], creating each signer's Proof of | ||
| /// Bound Possession (when applicable) for the given epoch. | ||
| pub fn build_at_epoch(self, epoch: Epoch) -> MithrilFixture { | ||
| #[cfg(not(feature = "future_snark"))] | ||
| let _epoch = epoch; | ||
| #[cfg(feature = "future_snark")] | ||
| let builder = self.with_epoch(epoch); | ||
| #[cfg(not(feature = "future_snark"))] | ||
| let builder = self; | ||
| builder.build() | ||
| } | ||
|
|
||
| /// Transform the specified parameters to a [MithrilFixture]. | ||
| pub fn build(self) -> MithrilFixture { | ||
| let protocol_stake_distribution = self.generate_stake_distribution(); | ||
| let signers = crypto_helper::setup_signers_from_stake_distribution( | ||
| &protocol_stake_distribution, | ||
| &self.protocol_parameters.clone().into(), | ||
| #[cfg(feature = "future_snark")] | ||
| self.epoch, | ||
| ); | ||
|
|
||
| MithrilFixture::new( | ||
| self.protocol_parameters, | ||
| signers, | ||
| protocol_stake_distribution, | ||
| #[cfg(feature = "future_snark")] | ||
| self.epoch, | ||
| ) |
There was a problem hiding this comment.
suggestion(blocking): I think you should reverse the method call order as it just simpler, and remove with_epoch and the associated epoch field since it will be mandatory in the future and is only used when building and prevent easy re-using (see next paragraph).
Another important change is that the build/build_at_epoch method should not consume self anymore, meaning you will be able to call it multiple times to produce signers for different epoch using the same options.
| /// Set the epoch for which the signers' Proof of Bound Possession will be created. | |
| #[cfg(feature = "future_snark")] | |
| pub fn with_epoch(mut self, epoch: Epoch) -> Self { | |
| self.epoch = epoch; | |
| self | |
| } | |
| /// Transform the specified parameters to a [MithrilFixture], creating each signer's Proof of | |
| /// Bound Possession (when applicable) for the given epoch. | |
| pub fn build_at_epoch(self, epoch: Epoch) -> MithrilFixture { | |
| #[cfg(not(feature = "future_snark"))] | |
| let _epoch = epoch; | |
| #[cfg(feature = "future_snark")] | |
| let builder = self.with_epoch(epoch); | |
| #[cfg(not(feature = "future_snark"))] | |
| let builder = self; | |
| builder.build() | |
| } | |
| /// Transform the specified parameters to a [MithrilFixture]. | |
| pub fn build(self) -> MithrilFixture { | |
| let protocol_stake_distribution = self.generate_stake_distribution(); | |
| let signers = crypto_helper::setup_signers_from_stake_distribution( | |
| &protocol_stake_distribution, | |
| &self.protocol_parameters.clone().into(), | |
| #[cfg(feature = "future_snark")] | |
| self.epoch, | |
| ); | |
| MithrilFixture::new( | |
| self.protocol_parameters, | |
| signers, | |
| protocol_stake_distribution, | |
| #[cfg(feature = "future_snark")] | |
| self.epoch, | |
| ) | |
| /// Transform the specified parameters to a [MithrilFixture], creating each signer's Proof of | |
| /// Bound Possession (when applicable) for the given epoch. | |
| pub fn build_at_epoch(&self, epoch: Epoch) -> MithrilFixture { | |
| let protocol_stake_distribution = self.generate_stake_distribution(); | |
| let signers = crypto_helper::setup_signers_from_stake_distribution( | |
| &protocol_stake_distribution, | |
| &self.protocol_parameters.clone().into(), | |
| #[cfg(feature = "future_snark")] | |
| epoch, | |
| ); | |
| MithrilFixture::new( | |
| self.protocol_parameters.clone(), | |
| signers, | |
| protocol_stake_distribution, | |
| #[cfg(feature = "future_snark")] | |
| epoch, | |
| ) | |
| } | |
| /// Transform the specified parameters to a [MithrilFixture], creating each signer's Proof of | |
| /// Bound Possession (when applicable) for the Epoch 1. | |
| pub fn build(&self) -> MithrilFixture { | |
| Self::build_at_epoch(Epoch(1)) | |
| } |
| let current_fixture = MithrilFixtureBuilder::default() | ||
| .with_signers(signers_count) | ||
| .with_protocol_parameters(protocol_parameters.clone()) | ||
| .build_at_epoch(current_retrieval_epoch); | ||
| let next_fixture = MithrilFixtureBuilder::default() | ||
| .with_signers(signers_count) | ||
| .with_protocol_parameters(protocol_parameters) | ||
| .build_at_epoch(time_point.epoch); |
There was a problem hiding this comment.
issue(blocking): you should not rebuild a fixture builder like this, since you may be missing parameters that were used when the fixture was built (e.g. the StakeDistributionGenerationMethod). This caller to use any other builder parameters than the three used here.
suggestion: pass the MithrilFixtureBuilder by reference and refactor it so the build methods does not consume self (see comment in mithril-common/src/test/builder/fixture_builder.rs).
important: this comment apply for all other cases where a builder is rebuilt from a fixture like this in the code base.
Content
This PR includes the addition of a proof of bound possession for the Schnorr signing key. This proof is added in mithril-common under the
future_snarkfeature. It is computed by the Initializers and verified during the registration of the signers. This PR also includes a deduplication mechanism for the Schnorr verification key at the STM level.Summary
Adds Proof of Bound Possession (PoBP) for the Schnorr/SNARK signer verification key, entirely behind
future_snark.Changes
mithril-stm): Schnorr signing/verification keys gaincreate_pobp/verify_pobp;Initializer/StmInitializerWrappercreate and store the proof.KeyRegistration::registergains a deduplication of entries based on the Schnorr verification key.mithril-common): newProofOfBoundPossessionPrefix(stake || epoch || pool_id) feeding the Schnorr challenge; pool_id uses the raw fixed-length Blake2b-224 hash rather than the bech32 string, removing the need for a length-prefixed encoding.mithril-common,mithril-aggregator):KeyRegWrapper::registernow verifies the PoBP alongside the existing KES check;SignerRegistrationVerifier/leader/follower services thread the registrationepochthrough to that verification.Signer/SignerWithStakegainproof_of_bound_possession_for_snark; mirrored intoRegisterSignerMessage, message adapters, and DB persistence (new nullable column via migration) so it survives aggregator restarts and follower sync.SignerBuilder/fixture builders — since PoBP verification must use the exact epoch the proof was bound to.MithrilFixtureBuilder/fake_datagain epoch-aware builders (build_at_epoch,signers_with_stakes_at_epoch) to replace the implicit "always epoch 0" fixtures that broke once epoch-bound verification was enforced; extensive unit and integration test fixes acrossmithril-common/mithril-aggregator(including the aggregator's follower/leader integration suite) to build fixtures at the epoch they're actually registered/re-registered at, including cases where stake is updated mid-test.Notes
#[cfg(feature = "future_snark")]-gated; default builds are unaffected.Pre-submit checklist
Comments
Issue(s)
Closes #3537