feat(cl/1to1_xfr): fungibility domain uses hash_to_curve

This commit is contained in:
David Rusu 2024-05-28 23:28:57 +04:00
parent 5044486f36
commit 7074a3b0a2
2 changed files with 41 additions and 22 deletions

View File

@ -1,6 +1,14 @@
from dataclasses import dataclass
from crypto import Field, Point, prf
from crypto import (
Field,
Point,
prf,
pederson_commit,
_str_to_vec,
merkle_root,
hash_to_curve,
)
from constraints import Constraint
@ -21,6 +29,10 @@ def nf_pk(nf_sk) -> Field:
return prf("CL_NOTE_NF", nf_sk)
def balance_commitment(value: Field, tx_rand: Field, funge: Point):
return pederson_commit(value, tx_rand, funge)
@dataclass(unsafe_hash=True)
class InnerNote:
value: Field
@ -40,15 +52,15 @@ class InnerNote:
@property
def fungibility_domain(self) -> Field:
"""The fungibility domain of this note"""
return crypto.prf(
"CL_NOTE_NULL", self.birth_constraint.hash(), *crypto.str_to_vec(unit)
return hash_to_curve(
"CL_NOTE_NULL", self.birth_constraint.hash(), *_str_to_vec(self.unit)
)
def death_constraints_root(self) -> Field:
"""
Returns the merkle root over the set of death constraints
"""
return crypto.merkle_root(self.death_constraints)
return merkle_root(self.death_constraints)
@dataclass(unsafe_hash=True)
@ -56,13 +68,23 @@ class PublicNote:
note: InnerNote
nf_pk: Field
def blinding(self, rand: Field) -> Field:
def blinding(self, tx_rand: Field) -> Field:
"""Blinding factor used in balance commitments"""
return prf("CL_NOTE_BAL_BLIND", rand, self.nonce, self.nf_pk)
return prf("CL_NOTE_BAL_BLIND", tx_rand, self.note.nonce, self.nf_pk)
def balance(self, rand):
"""
Returns the pederson commitment to the notes value.
"""
return balance_commitment(
self.note.value,
self.blinding(rand),
self.note.fungibility_domain,
)
def commit(self) -> Field:
# blinding factors between data elems ensure no information is leaked in merkle paths
return crypto.merkle_root(
return merkle_root(
self.note.r(0),
self.note.birth_constraint.hash(),
self.note.r(1),
@ -96,19 +118,9 @@ class SecretNote:
"""
return prf("NULLIFIER", self.nonce, self.nf_sk)
def balance(self, rand):
"""
Returns the pederson commitment to the notes value.
"""
return crypto.pederson_commit(
self.note.value, self.blinding(rand), self.note.fungibility_domain
)
def zero(self, rand):
"""
Returns the pederson commitment to zero using the same blinding as the balance
commitment.
"""
return crypto.pederson_commit(
0, self.blinding(rand), self.note.fungibility_domain
)
return pederson_commit(0, self.blinding(rand), self.note.fungibility_domain)

View File

@ -3,7 +3,7 @@ from dataclasses import dataclass
from crypto import Field, prf
from note import InnerNote, PublicNote, SecretNote, nf_pk
from partial_transaction import PartialTransaction
from partial_transaction import PartialTransaction, Output
from transaction_bundle import TransactionBundle
import constraints
@ -37,6 +37,7 @@ class TestTransfer(TestCase):
nf_sk=alice.sk,
)
tx_rand = Field.random()
bobs_note = PublicNote(
note=InnerNote(
value=100,
@ -49,11 +50,17 @@ class TestTransfer(TestCase):
),
nf_pk=bob.pk,
)
tx_output = Output(
note=bobs_note,
# TODO: why do we need an Output struct if we can
# compute the balance and zero commitment form the
# PublicNote itself?
balance=bobs_note.balance(tx_rand),
zero=bobs_note.zero(tx_rand),
)
ptx = PartialTransaction(
inputs=[alices_note],
outputs=[alices_note],
rand=Field.random(),
inputs=[alices_note], outputs=[alices_note], rand=tx_rand
)
bundle = TransactionBundle(bundle=[ptx])