add parent to proofs

This commit is contained in:
thomaslavaur 2024-08-30 10:07:41 +02:00
parent e9c9e976a0
commit f6fff116ac
4 changed files with 24 additions and 22 deletions

View File

@ -177,6 +177,7 @@ class LeaderProof:
nullifier: Id nullifier: Id
evolved_commitment: Id evolved_commitment: Id
slot: Slot slot: Slot
parent: Id
# The produced proof # The produced proof
@staticmethod @staticmethod
@ -190,6 +191,9 @@ class LeaderProof:
#Secret inputs #Secret inputs
coin: Coin, coin: Coin,
#membership witness to check that coin.commitment() is in eligible_notes #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: #These verifications are normally done in the risc0 zk-proof:
lottery_ticket = LEADER_VRF.vrf(coin, epoch_nonce, slot) lottery_ticket = LEADER_VRF.vrf(coin, epoch_nonce, slot)
@ -199,21 +203,20 @@ class LeaderProof:
assert(coin.commitment() in eligible_notes) assert(coin.commitment() in eligible_notes)
evolved_coin = coin.evolve() evolved_coin = coin.evolve()
return LeaderProof( # TODO: generate the proof with risc0 return LeaderProof( # TODO: generate the proof with risc0
nullifier=coin_nullifier, nullifier=coin_nullifier,
evolved_commitment=evolved_coin.commitment(), evolved_commitment=evolved_coin.commitment(),
slot=slot, slot=slot,
parent=parent,
) )
def verify(self, slot: Slot, def verify(self, slot: Slot,
_epoch_nonce: Id, _epoch_nonce: Id,
_threshold_0: int, _threshold_0: int,
_threshold_1: int, _threshold_1: int,
_eligible_notes: set[Id],): _eligible_notes: set[Id],
return slot == self.slot #TODO: and verification of the proof with risc0 parent: Id):
return slot == self.slot and parent == self.parent #TODO: add verification of the proof with risc0
@dataclass @dataclass
@ -299,9 +302,6 @@ class LedgerState:
# This nonce is used to derive the seed for the slot leader lottery. # 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 # It's updated at every block by hashing the previous nonce with the
# leader proof's nullifier. # 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 nonce: Id = None
# set of commitments # set of commitments
@ -472,7 +472,7 @@ class Follower:
) -> bool: ) -> bool:
threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch_state.total_active_stake()) threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch_state.total_active_stake())
return ( 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: # Membership verification is included in the proof verification along with the PoS lottery:
#and ( #and (
# current_state.verify_eligible_to_lead(proof.commitment) # current_state.verify_eligible_to_lead(proof.commitment)
@ -709,15 +709,15 @@ class Leader:
coin: Coin coin: Coin
def try_prove_slot_leader( 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: ) -> LeaderProof | None:
if self._is_slot_leader(epoch, slot): if self._is_slot_leader(total_stake, nonce, slot):
threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch.total_active_stake()) threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, total_stake)
return LeaderProof.new(slot, epoch.nonce(), threshold_0, threshold_1, eligible_notes, self.coin) return LeaderProof.new(slot, nonce, threshold_0, threshold_1, eligible_notes, self.coin, parent)
def _is_slot_leader(self, epoch: EpochState, slot: Slot): def _is_slot_leader(self, total_stake: int, nonce: Id, slot: Slot):
threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, epoch.total_active_stake()) threshold_0, threshold_1 = lottery_threshold(self.config.active_slot_coeff, total_stake)
r = LEADER_VRF.vrf(self.coin, epoch.nonce(), slot) r = LEADER_VRF.vrf(self.coin, nonce, slot)
return r < leader_winning_threshold(threshold_0, threshold_1, self.coin.value) return r < leader_winning_threshold(threshold_0, threshold_1, self.coin.value)

View File

@ -27,7 +27,7 @@ class TestNode:
parent = self.follower.tip_id() parent = self.follower.tip_id()
epoch_state = self.epoch_state(slot) epoch_state = self.epoch_state(slot)
# TODO: use the correct leader commitment set # 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) orphans = self.follower.unimported_orphans(parent)
self.leader.coin = self.leader.coin.evolve() self.leader.coin = self.leader.coin.evolve()
return BlockHeader( return BlockHeader(
@ -63,18 +63,20 @@ def mk_genesis_state(initial_stake_distribution: list[Coin]) -> LedgerState:
def mk_block( 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: ) -> BlockHeader:
assert len(parent) == 32 assert len(parent) == 32
from hashlib import sha256 from hashlib import sha256
if len(leader_commitments) == 0:
leader_commitments = [coin.commitment()]
return BlockHeader( return BlockHeader(
slot=Slot(slot), slot=Slot(slot),
parent=parent, parent=parent,
content_size=len(content), content_size=len(content),
content_id=sha256(content).digest(), content_id=sha256(content).digest(),
# TODO: use the correct leader commitment set # 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, orphaned_proofs=orphaned_proofs,
) )

View File

@ -42,8 +42,8 @@ class TestLeader(TestCase):
# interval `p +- margin_of_error` with high probabiltiy # interval `p +- margin_of_error` with high probabiltiy
leader_rate = ( leader_rate = (
sum( sum(
# TODO: use the correct leader commitment set # TODO: use the correct leader commitment set and ledger nonce instead of epoch nonce
l.try_prove_slot_leader(epoch, Slot(slot), {coin.commitment()}) is not None 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) for slot in range(N)
) )
/ N / N

View File

@ -286,4 +286,4 @@ class TestLedgerStateUpdate(TestCase):
# is imported into the main chain # is imported into the main chain
follower.on_block(orphan) follower.on_block(orphan)
follower.on_block(block_0_1) follower.on_block(block_0_1)
assert follower.tip() == block_0_1 assert follower.tip() == block_0_1