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
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)

View File

@ -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,
)

View File

@ -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

View File

@ -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