From f6fff116ac00665098b94a0537d2439861881743 Mon Sep 17 00:00:00 2001 From: thomaslavaur Date: Fri, 30 Aug 2024 10:07:41 +0200 Subject: [PATCH] add parent to proofs --- cryptarchia/cryptarchia.py | 32 ++++++++++++------------- cryptarchia/test_common.py | 8 ++++--- cryptarchia/test_leader.py | 4 ++-- cryptarchia/test_ledger_state_update.py | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/cryptarchia/cryptarchia.py b/cryptarchia/cryptarchia.py index ec70ffb..99eee26 100644 --- a/cryptarchia/cryptarchia.py +++ b/cryptarchia/cryptarchia.py @@ -177,6 +177,7 @@ class LeaderProof: nullifier: Id evolved_commitment: Id slot: Slot + parent: Id # The produced proof @staticmethod @@ -190,6 +191,9 @@ class LeaderProof: #Secret inputs coin: Coin, #membership witness to check that coin.commitment() is in eligible_notes + + #This is not verified in the proof but solved with cryptographic signatures and conflict resolution + parent: Id ): #These verifications are normally done in the risc0 zk-proof: lottery_ticket = LEADER_VRF.vrf(coin, epoch_nonce, slot) @@ -199,21 +203,20 @@ class LeaderProof: assert(coin.commitment() in eligible_notes) evolved_coin = coin.evolve() - - - return LeaderProof( # TODO: generate the proof with risc0 nullifier=coin_nullifier, evolved_commitment=evolved_coin.commitment(), slot=slot, + parent=parent, ) def verify(self, slot: Slot, _epoch_nonce: Id, _threshold_0: int, _threshold_1: int, - _eligible_notes: set[Id],): - return slot == self.slot #TODO: and verification of the proof with risc0 + _eligible_notes: set[Id], + parent: Id): + return slot == self.slot and parent == self.parent #TODO: add verification of the proof with risc0 @dataclass @@ -299,9 +302,6 @@ class LedgerState: # This nonce is used to derive the seed for the slot leader lottery. # It's updated at every block by hashing the previous nonce with the # leader proof's nullifier. - # - # NOTE that this does not prevent nonce grinding at the last slot - # when the nonce snapshot is taken nonce: Id = None # set of commitments @@ -472,7 +472,7 @@ class Follower: ) -> bool: threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch_state.total_active_stake()) return ( - proof.verify(slot, epoch_state.nonce(), threshold_0, threshold_1, current_state.commitments_lead) # verify slot leader proof + proof.verify(slot, current_state.nonce, threshold_0, threshold_1, current_state.commitments_lead, parent) # verify slot leader proof # Membership verification is included in the proof verification along with the PoS lottery: #and ( # current_state.verify_eligible_to_lead(proof.commitment) @@ -709,15 +709,15 @@ class Leader: coin: Coin def try_prove_slot_leader( - self, epoch: EpochState, slot: Slot, eligible_notes: set[Id] + self, total_stake: int, nonce: Id, slot: Slot, eligible_notes: set[Id], parent: Id ) -> LeaderProof | None: - if self._is_slot_leader(epoch, slot): - threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch.total_active_stake()) - return LeaderProof.new(slot, epoch.nonce(), threshold_0, threshold_1, eligible_notes, self.coin) + if self._is_slot_leader(total_stake, nonce, slot): + threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, total_stake) + return LeaderProof.new(slot, nonce, threshold_0, threshold_1, eligible_notes, self.coin, parent) - def _is_slot_leader(self, epoch: EpochState, slot: Slot): - threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch.total_active_stake()) - r = LEADER_VRF.vrf(self.coin, epoch.nonce(), slot) + def _is_slot_leader(self, total_stake: int, nonce: Id, slot: Slot): + threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, total_stake) + r = LEADER_VRF.vrf(self.coin, nonce, slot) return r < leader_winning_threshold(threshold_0, threshold_1, self.coin.value) diff --git a/cryptarchia/test_common.py b/cryptarchia/test_common.py index b229554..2c2586e 100644 --- a/cryptarchia/test_common.py +++ b/cryptarchia/test_common.py @@ -27,7 +27,7 @@ class TestNode: parent = self.follower.tip_id() epoch_state = self.epoch_state(slot) # TODO: use the correct leader commitment set - if leader_proof := self.leader.try_prove_slot_leader(epoch_state, slot, {self.leader.coin.commitment()}): + if leader_proof := self.leader.try_prove_slot_leader(epoch_state.total_active_stake(), self.follower.tip_state().nonce, slot, {self.leader.coin.commitment()}, parent): orphans = self.follower.unimported_orphans(parent) self.leader.coin = self.leader.coin.evolve() return BlockHeader( @@ -63,18 +63,20 @@ def mk_genesis_state(initial_stake_distribution: list[Coin]) -> LedgerState: def mk_block( - parent: Id, slot: int, coin: Coin, content=bytes(32), orphaned_proofs=[] + parent: Id, slot: int, coin: Coin, leader_commitments=[], content=bytes(32), orphaned_proofs=[] ) -> BlockHeader: assert len(parent) == 32 from hashlib import sha256 + if len(leader_commitments) == 0: + leader_commitments = [coin.commitment()] return BlockHeader( slot=Slot(slot), parent=parent, content_size=len(content), content_id=sha256(content).digest(), # TODO: use the correct leader commitment set - leader_proof=LeaderProof.new(Slot(slot), bytes(32), 2**256, 0, {coin.commitment()}, coin), + leader_proof=LeaderProof.new(Slot(slot), bytes(32), 2**256, 0, set(leader_commitments), coin, parent), orphaned_proofs=orphaned_proofs, ) diff --git a/cryptarchia/test_leader.py b/cryptarchia/test_leader.py index 5c4364d..f1866a4 100644 --- a/cryptarchia/test_leader.py +++ b/cryptarchia/test_leader.py @@ -42,8 +42,8 @@ class TestLeader(TestCase): # interval `p +- margin_of_error` with high probabiltiy leader_rate = ( sum( - # TODO: use the correct leader commitment set - l.try_prove_slot_leader(epoch, Slot(slot), {coin.commitment()}) is not None + # TODO: use the correct leader commitment set and ledger nonce instead of epoch nonce + l.try_prove_slot_leader(epoch.total_active_stake(), epoch.nonce(), Slot(slot), {coin.commitment()}, bytes(32)) is not None for slot in range(N) ) / N diff --git a/cryptarchia/test_ledger_state_update.py b/cryptarchia/test_ledger_state_update.py index 275db67..6ce6d8a 100644 --- a/cryptarchia/test_ledger_state_update.py +++ b/cryptarchia/test_ledger_state_update.py @@ -286,4 +286,4 @@ class TestLedgerStateUpdate(TestCase): # is imported into the main chain follower.on_block(orphan) follower.on_block(block_0_1) - assert follower.tip() == block_0_1 + assert follower.tip() == block_0_1 \ No newline at end of file