feat(leader_coin): add nonce and coin.evolve() api

This commit is contained in:
David Rusu 2024-02-06 19:31:34 +04:00
parent c1e12d6ce8
commit eebf439a30
4 changed files with 38 additions and 12 deletions

View File

@ -79,8 +79,24 @@ class Slot:
@dataclass
class Coin:
pk: int
sk: int
value: int
nonce: bytes = bytes(32)
@property
def pk(self):
return self.sk
def evolve(self) -> "Coin":
sk_bytes = int.to_bytes(self.sk, length=32, byteorder="little")
h = blake2b(digest_size=32)
h.update(b"coin-evolve")
h.update(sk_bytes)
h.update(self.nonce)
evolved_nonce = h.digest()
return Coin(nonce=evolved_nonce, sk=self.sk, value=self.value)
def commitment(self) -> Id:
# TODO: mocked until CL is understood
@ -88,6 +104,8 @@ class Coin:
value_bytes = int.to_bytes(self.value, length=32, byteorder="little")
h = sha256()
h.update(b"coin-commitment")
h.update(self.nonce)
h.update(pk_bytes)
h.update(value_bytes)
return h.digest()
@ -98,9 +116,10 @@ class Coin:
value_bytes = int.to_bytes(self.value, length=32, byteorder="little")
h = sha256()
h.update(b"coin-nullifier")
h.update(self.nonce)
h.update(pk_bytes)
h.update(value_bytes)
h.update(b"\x00") # extra 0 byte to differentiate from commitment
return h.digest()
@ -108,10 +127,17 @@ class Coin:
class MockLeaderProof:
commitment: Id
nullifier: Id
evolved_commitment: Id
@staticmethod
def from_coin(coin: Coin):
return MockLeaderProof(commitment=coin.commitment(), nullifier=coin.nullifier())
evolved_coin = coin.evolve()
return MockLeaderProof(
commitment=coin.commitment(),
nullifier=coin.nullifier(),
evolved_commitment=evolved_coin.commitment(),
)
def verify(self, slot):
# TODO: verification not implemented

View File

@ -23,7 +23,7 @@ def make_block(parent_id: Id, slot: Slot, content: bytes) -> BlockHeader:
content_size=1,
slot=slot,
content_id=content_id,
leader_proof=MockLeaderProof.from_coin(Coin(pk=0, value=10)),
leader_proof=MockLeaderProof.from_coin(Coin(sk=0, value=10)),
)

View File

@ -23,7 +23,7 @@ class TestLeader(TestCase):
epoch_period_nonce_stabilization=3,
time=TimeConfig(slot_duration=1, chain_start_time=0),
)
l = Leader(config=config, coin=Coin(pk=0, value=10))
l = Leader(config=config, coin=Coin(sk=0, value=10))
# We'll use the Margin of Error equation to decide how many samples we need.
# https://en.wikipedia.org/wiki/Margin_of_error

View File

@ -50,7 +50,7 @@ def config() -> Config:
class TestLedgerStateUpdate(TestCase):
def test_ledger_state_prevents_coin_reuse(self):
leader_coin = Coin(pk=0, value=100)
leader_coin = Coin(sk=0, value=100)
genesis = mk_genesis_state([leader_coin])
follower = Follower(genesis, config())
@ -76,9 +76,9 @@ class TestLedgerStateUpdate(TestCase):
assert follower.local_chain.tip() == block
def test_ledger_state_is_properly_updated_on_reorg(self):
coin_1 = Coin(pk=0, value=100)
coin_2 = Coin(pk=1, value=100)
coin_3 = Coin(pk=2, value=100)
coin_1 = Coin(sk=0, value=100)
coin_2 = Coin(sk=1, value=100)
coin_3 = Coin(sk=2, value=100)
genesis = mk_genesis_state([coin_1, coin_2, coin_3])
@ -114,7 +114,7 @@ class TestLedgerStateUpdate(TestCase):
assert follower.ledger_state[block_3.id()].verify_unspent(coin_1.nullifier())
def test_epoch_transition(self):
leader_coins = [Coin(pk=i, value=100) for i in range(4)]
leader_coins = [Coin(sk=i, value=100) for i in range(4)]
genesis = mk_genesis_state(leader_coins)
# An epoch will be 10 slots long, with stake distribution snapshot taken at the start of the epoch
@ -145,12 +145,12 @@ class TestLedgerStateUpdate(TestCase):
# To ensure this is the case, we add a new coin just to the state associated with that slot,
# so that the new block can be accepted only if that is the snapshot used
# first, verify that if we don't change the state, the block is not accepted
block_4 = mk_block(slot=20, parent=block_3.id(), coin=Coin(pk=4, value=100))
block_4 = mk_block(slot=20, parent=block_3.id(), coin=Coin(sk=4, value=100))
follower.on_block(block_4)
assert follower.tip() == block_3
# then we add the coin to the state associated with slot 9
follower.ledger_state[block_2.id()].commitments.add(
Coin(pk=4, value=100).commitment()
Coin(sk=4, value=100).commitment()
)
follower.on_block(block_4)
assert follower.tip() == block_4