cl/ptx-note-proofs: start data modelling input and outputs
This commit is contained in:
parent
71ede291d2
commit
8e98d89a0b
|
@ -10,7 +10,7 @@ from crypto import (
|
|||
hash_to_curve,
|
||||
)
|
||||
|
||||
from constraints import Constraint
|
||||
from constraints import Constraint, Proof
|
||||
|
||||
|
||||
# TODO: is this used?
|
||||
|
@ -39,6 +39,8 @@ def balance_commitment(value: Field, tx_rand: Field, funge: Point):
|
|||
class InnerNote:
|
||||
value: Field
|
||||
unit: str
|
||||
# TODO: inner notes should hold commitments to constraints.
|
||||
# Constraints themselves will be stored in a key-value store
|
||||
birth_constraint: Constraint
|
||||
death_constraints: list[Constraint]
|
||||
state: Field
|
||||
|
@ -63,12 +65,23 @@ class InnerNote:
|
|||
assert isinstance(self.nonce, Field), f"nonce is {type(self.nonce)}"
|
||||
assert isinstance(self.rand, Field), f"rand is {type(self.rand)}"
|
||||
|
||||
def r(self, index: int):
|
||||
prf("CL_NOTE_COMM_RAND", self.rand, index)
|
||||
def verify_death(self, death_cm: Field, death_proof: Proof) -> bool:
|
||||
constraint = [d for d in self.death_constraints if d.hash() == deah_cm][0]
|
||||
# TODO: verifying the death constraint should include a commitment to the
|
||||
# partial transaction.
|
||||
return constraint.verify(death_proof)
|
||||
|
||||
def verify_birth(self, birth_proof: Proof) -> bool:
|
||||
# TODO: Should verifying the birth constraint include a commitment
|
||||
# to the partial transaction?
|
||||
return self.birth_constraint.verify(birth_proof)
|
||||
|
||||
def verify_value(self) -> bool:
|
||||
return 0 <= self.value and value <= 2**64
|
||||
|
||||
def r(self, index: int):
|
||||
return prf("CL_NOTE_COMM_RAND", self.rand, index)
|
||||
|
||||
@property
|
||||
def fungibility_domain(self) -> Field:
|
||||
"""The fungibility domain of this note"""
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
* Open Issues
|
||||
|
||||
** Note.verify() should take a proof
|
||||
|
||||
We should have two variants, verifyDeath(deathProof) verifyBirth(birthProof)
|
||||
|
||||
** provided commitment to zero may removing the blinding of the pederson commitment
|
||||
|
||||
Since you can subtract the randomness from the commitment to get just the binding part.
|
||||
|
|
|
@ -1,9 +1,30 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
|
||||
from constraints import Proof
|
||||
from note import PublicNote, SecretNote
|
||||
from crypto import Field, Point
|
||||
|
||||
|
||||
@dataclass
|
||||
class InputNote:
|
||||
note: SecretNote
|
||||
death_proof: Proof
|
||||
|
||||
def verify(self):
|
||||
return self.note.verify_death(self.death_proof)
|
||||
|
||||
|
||||
@dataclass
|
||||
class OutputNote:
|
||||
note: PublicNote
|
||||
birth_proof: Proof
|
||||
|
||||
def verify(self):
|
||||
return self.note.verify_birth(self.birth_proof)
|
||||
|
||||
|
||||
# TODO: is this used?
|
||||
@dataclass
|
||||
class Output:
|
||||
note: PublicNote
|
||||
|
@ -15,20 +36,23 @@ class Output:
|
|||
|
||||
@dataclass(unsafe_hash=True)
|
||||
class PartialTransaction:
|
||||
inputs: list[SecretNote]
|
||||
outputs: list[Output]
|
||||
inputs: list[InputNote]
|
||||
outputs: list[OutputNote]
|
||||
rand: Field
|
||||
|
||||
def verify(self) -> bool:
|
||||
raise NotImplementedError()
|
||||
valid_inputs = all(i.verify() for i in self.inputs)
|
||||
valid_outputs = all(o.verify() for o in self.outputs)
|
||||
return valid_inputs and valid_output
|
||||
|
||||
def balance(self) -> Point:
|
||||
output_balance = sum((n.balance for n in self.outputs), start=Point.zero())
|
||||
# TODO: once again just mentioning this inefficiency. we are converting our private
|
||||
# inputs to public inputs to compute the balance, so we don't need an Output class,
|
||||
# we can directly compute the balance commitment from the public output notes.
|
||||
output_balance = sum(
|
||||
(n.note.balance(self.rand) for n in self.outputs),
|
||||
start=Point.zero(),
|
||||
)
|
||||
input_balance = sum(
|
||||
(n.to_public().balance(self.rand) for n in self.inputs), start=Point.zero()
|
||||
(n.note.to_public().balance(self.rand) for n in self.inputs),
|
||||
start=Point.zero(),
|
||||
)
|
||||
return output_balance + input_balance.negate()
|
||||
|
||||
|
@ -37,12 +61,13 @@ class PartialTransaction:
|
|||
return sum(outputs.blinding(self.rand)) - sum(outputs.blinding(self.rand))
|
||||
|
||||
def zero(self) -> Field:
|
||||
output_zero = sum((n.zero for n in self.outputs), start=Point.zero())
|
||||
# TODO: once again just mentioning this inefficiency. we are converting our private
|
||||
# inputs to public inputs to compute the zero commitment, so we don't need an Output class,
|
||||
# we can directly compute the zero commitment from the public output notes.
|
||||
output_zero = sum(
|
||||
(n.note.zero(self.rand) for n in self.outputs),
|
||||
start=Point.zero(),
|
||||
)
|
||||
input_zero = sum(
|
||||
(n.to_public().zero(self.rand) for n in self.inputs), start=Point.zero()
|
||||
(n.note.to_public().zero(self.rand) for n in self.inputs),
|
||||
start=Point.zero(),
|
||||
)
|
||||
|
||||
return output_zero + input_zero.negate()
|
||||
|
|
|
@ -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, Output
|
||||
from partial_transaction import PartialTransaction, InputNote, OutputNote
|
||||
from transaction_bundle import TransactionBundle
|
||||
|
||||
import constraints
|
||||
|
@ -50,17 +50,29 @@ 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),
|
||||
)
|
||||
# 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=[tx_output], rand=tx_rand
|
||||
inputs=[
|
||||
InputNote(
|
||||
note=alices_note,
|
||||
death_proof=constraints.Vacuous().prove(),
|
||||
)
|
||||
],
|
||||
outputs=[
|
||||
OutputNote(
|
||||
note=bobs_note,
|
||||
birth_proof=constraints.Vacuous().prove(),
|
||||
)
|
||||
],
|
||||
rand=tx_rand,
|
||||
)
|
||||
|
||||
bundle = TransactionBundle(bundle=[ptx])
|
||||
|
|
Loading…
Reference in New Issue