mirror of
https://github.com/logos-co/nomos-pocs.git
synced 2025-02-19 12:47:27 +00:00
goas: move nonce into note
This commit is contained in:
parent
cffd687e50
commit
1fd4c6bd64
@ -1,6 +1,6 @@
|
|||||||
pub mod mmr;
|
pub mod mmr;
|
||||||
|
|
||||||
use cl::{balance::Unit, ConstraintCommitment, NoteCommitment};
|
use cl::{balance::Unit, Constraint, NoteCommitment};
|
||||||
use ed25519_dalek::{
|
use ed25519_dalek::{
|
||||||
ed25519::{signature::SignerMut, SignatureBytes},
|
ed25519::{signature::SignerMut, SignatureBytes},
|
||||||
Signature, SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH,
|
Signature, SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH,
|
||||||
@ -27,8 +27,8 @@ pub fn new_account(mut rng: impl CryptoRngCore) -> SigningKey {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct ZoneMetadata {
|
pub struct ZoneMetadata {
|
||||||
pub zone_constraint: ConstraintCommitment,
|
pub zone_constraint: Constraint,
|
||||||
pub funds_constraint: ConstraintCommitment,
|
pub funds_constraint: Constraint,
|
||||||
pub unit: Unit,
|
pub unit: Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use cl::ConstraintCommitment;
|
use cl::Constraint;
|
||||||
use common::{
|
use common::{
|
||||||
mmr::MMR, AccountId, IncludedTxWitness, SignedBoundTx, StateWitness, Tx, ZoneMetadata,
|
mmr::MMR, AccountId, IncludedTxWitness, SignedBoundTx, StateWitness, Tx, ZoneMetadata,
|
||||||
};
|
};
|
||||||
@ -49,22 +49,18 @@ impl ZoneNotes {
|
|||||||
self.state = new_state;
|
self.state = new_state;
|
||||||
|
|
||||||
let state_in = self.state_input_witness();
|
let state_in = self.state_input_witness();
|
||||||
self.state_note = cl::OutputWitness::public(
|
self.state_note = cl::OutputWitness::public(cl::NoteWitness {
|
||||||
cl::NoteWitness {
|
state: self.state.commit().0,
|
||||||
state: self.state.commit().0,
|
nonce: state_in.evolved_nonce(b"STATE_NONCE"),
|
||||||
..state_in.note
|
..state_in.note
|
||||||
},
|
});
|
||||||
state_in.evolved_nonce(b"STATE_NONCE"),
|
|
||||||
);
|
|
||||||
|
|
||||||
let fund_in = self.fund_input_witness();
|
let fund_in = self.fund_input_witness();
|
||||||
self.fund_note = cl::OutputWitness::public(
|
self.fund_note = cl::OutputWitness::public(cl::NoteWitness {
|
||||||
cl::NoteWitness {
|
value: self.state.total_balance(),
|
||||||
value: self.state.total_balance(),
|
nonce: state_in.evolved_nonce(b"FUND_NONCE"),
|
||||||
..fund_in.note
|
..fund_in.note
|
||||||
},
|
});
|
||||||
state_in.evolved_nonce(b"FUND_NONCE"),
|
|
||||||
);
|
|
||||||
|
|
||||||
(self, included_tx)
|
(self, included_tx)
|
||||||
}
|
}
|
||||||
@ -75,38 +71,34 @@ fn zone_fund_utxo(
|
|||||||
zone_meta: ZoneMetadata,
|
zone_meta: ZoneMetadata,
|
||||||
mut rng: impl CryptoRngCore,
|
mut rng: impl CryptoRngCore,
|
||||||
) -> cl::OutputWitness {
|
) -> cl::OutputWitness {
|
||||||
cl::OutputWitness::public(
|
cl::OutputWitness::public(cl::NoteWitness {
|
||||||
cl::NoteWitness {
|
value,
|
||||||
value,
|
unit: *common::ZONE_CL_FUNDS_UNIT,
|
||||||
unit: *common::ZONE_CL_FUNDS_UNIT,
|
constraint: zone_meta.funds_constraint,
|
||||||
constraint: zone_meta.funds_constraint,
|
state: zone_meta.id(),
|
||||||
state: zone_meta.id(),
|
nonce: cl::Nonce::random(&mut rng),
|
||||||
},
|
})
|
||||||
cl::NullifierNonce::random(&mut rng),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zone_state_utxo(zone: &StateWitness, mut rng: impl CryptoRngCore) -> cl::OutputWitness {
|
fn zone_state_utxo(zone: &StateWitness, mut rng: impl CryptoRngCore) -> cl::OutputWitness {
|
||||||
cl::OutputWitness::public(
|
cl::OutputWitness::public(cl::NoteWitness {
|
||||||
cl::NoteWitness {
|
value: 1,
|
||||||
value: 1,
|
unit: zone.zone_metadata.unit,
|
||||||
unit: zone.zone_metadata.unit,
|
constraint: zone.zone_metadata.zone_constraint,
|
||||||
constraint: zone.zone_metadata.zone_constraint,
|
state: zone.commit().0,
|
||||||
state: zone.commit().0,
|
nonce: cl::Nonce::random(&mut rng),
|
||||||
},
|
})
|
||||||
cl::NullifierNonce::random(&mut rng),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_atomic_transfer_constraint() -> ConstraintCommitment {
|
pub fn user_atomic_transfer_constraint() -> Constraint {
|
||||||
ledger::constraint::risc0_constraint(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID)
|
ledger::constraint::risc0_constraint(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zone_state_constraint() -> ConstraintCommitment {
|
pub fn zone_state_constraint() -> Constraint {
|
||||||
ledger::constraint::risc0_constraint(goas_risc0_proofs::ZONE_STATE_ID)
|
ledger::constraint::risc0_constraint(goas_risc0_proofs::ZONE_STATE_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zone_fund_constraint() -> ConstraintCommitment {
|
pub fn zone_fund_constraint() -> Constraint {
|
||||||
ledger::constraint::risc0_constraint(goas_risc0_proofs::SPEND_ZONE_FUNDS_ID)
|
ledger::constraint::risc0_constraint(goas_risc0_proofs::SPEND_ZONE_FUNDS_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,8 +209,7 @@ pub fn prove_user_atomic_transfer(atomic_transfer: UserAtomicTransfer) -> ledger
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use cl::{
|
use cl::{
|
||||||
note::derive_unit, BalanceWitness, NoteWitness, NullifierNonce, OutputWitness,
|
note::derive_unit, BalanceWitness, Nonce, NoteWitness, OutputWitness, PartialTxWitness,
|
||||||
PartialTxWitness,
|
|
||||||
};
|
};
|
||||||
use common::{BoundTx, Deposit, Withdraw};
|
use common::{BoundTx, Deposit, Withdraw};
|
||||||
use goas_proof_statements::user_note::UserIntent;
|
use goas_proof_statements::user_note::UserIntent;
|
||||||
@ -237,10 +228,11 @@ mod tests {
|
|||||||
let zone_start =
|
let zone_start =
|
||||||
ZoneNotes::new_with_balances("ZONE", BTreeMap::from_iter([(alice_vk, 32)]), &mut rng);
|
ZoneNotes::new_with_balances("ZONE", BTreeMap::from_iter([(alice_vk, 32)]), &mut rng);
|
||||||
|
|
||||||
let bind = OutputWitness::public(
|
let bind = OutputWitness::public(NoteWitness::basic(
|
||||||
NoteWitness::basic(32, *common::ZONE_CL_FUNDS_UNIT),
|
32,
|
||||||
cl::NullifierNonce::random(&mut rng),
|
*common::ZONE_CL_FUNDS_UNIT,
|
||||||
);
|
&mut rng,
|
||||||
|
));
|
||||||
|
|
||||||
let signed_withdraw = SignedBoundTx::sign(
|
let signed_withdraw = SignedBoundTx::sign(
|
||||||
BoundTx {
|
BoundTx {
|
||||||
@ -324,15 +316,13 @@ mod tests {
|
|||||||
amount: 32,
|
amount: 32,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let user_note = cl::InputWitness::public(cl::OutputWitness::public(
|
let user_note = cl::InputWitness::public(cl::OutputWitness::public(NoteWitness {
|
||||||
NoteWitness::new(
|
value: 1,
|
||||||
1,
|
unit: derive_unit("INTENT"),
|
||||||
derive_unit("INTENT"),
|
constraint: ConstraintProof::nop_constraint(),
|
||||||
ConstraintProof::nop_constraint(),
|
state: user_intent.commit(),
|
||||||
user_intent.commit(),
|
nonce: Nonce::random(&mut rng),
|
||||||
),
|
}));
|
||||||
NullifierNonce::random(&mut rng),
|
|
||||||
));
|
|
||||||
|
|
||||||
let (zone_a, withdraw_included_witnesss) = zone_a.run(Tx::Withdraw(user_intent.withdraw));
|
let (zone_a, withdraw_included_witnesss) = zone_a.run(Tx::Withdraw(user_intent.withdraw));
|
||||||
let (zone_b, deposit_included_witnesss) = zone_b.run(Tx::Deposit(user_intent.deposit));
|
let (zone_b, deposit_included_witnesss) = zone_b.run(Tx::Deposit(user_intent.deposit));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use cl::{BalanceWitness, BundleWitness, NoteWitness, NullifierNonce};
|
use cl::{BalanceWitness, BundleWitness, Nonce, NoteWitness};
|
||||||
use common::{new_account, BoundTx, Deposit, SignedBoundTx, Tx, Withdraw};
|
use common::{new_account, BoundTx, Deposit, SignedBoundTx, Tx, Withdraw};
|
||||||
use executor::ZoneNotes;
|
use executor::ZoneNotes;
|
||||||
use goas_proof_statements::user_note::{UserAtomicTransfer, UserIntent};
|
use goas_proof_statements::user_note::{UserAtomicTransfer, UserIntent};
|
||||||
@ -30,15 +30,13 @@ fn test_atomic_transfer() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let alice_intent_out = cl::OutputWitness::public(
|
let alice_intent_out = cl::OutputWitness::public(NoteWitness {
|
||||||
NoteWitness {
|
value: 1,
|
||||||
value: 1,
|
unit: cl::note::derive_unit("INTENT"),
|
||||||
unit: cl::note::derive_unit("INTENT"),
|
constraint: executor::user_atomic_transfer_constraint(),
|
||||||
constraint: executor::user_atomic_transfer_constraint(),
|
state: alice_intent.commit(),
|
||||||
state: alice_intent.commit(),
|
nonce: Nonce::random(&mut rng),
|
||||||
},
|
});
|
||||||
NullifierNonce::random(&mut rng),
|
|
||||||
);
|
|
||||||
|
|
||||||
let user_ptx = cl::PartialTxWitness {
|
let user_ptx = cl::PartialTxWitness {
|
||||||
inputs: vec![],
|
inputs: vec![],
|
||||||
|
@ -23,14 +23,14 @@ fn test_deposit() {
|
|||||||
let zone_end = zone_start.clone().run(Tx::Deposit(deposit)).0;
|
let zone_end = zone_start.clone().run(Tx::Deposit(deposit)).0;
|
||||||
|
|
||||||
let alice_deposit = cl::InputWitness::from_output(
|
let alice_deposit = cl::InputWitness::from_output(
|
||||||
cl::OutputWitness::random(
|
cl::OutputWitness::new(
|
||||||
NoteWitness::stateless(
|
NoteWitness::stateless(
|
||||||
78,
|
78,
|
||||||
*ZONE_CL_FUNDS_UNIT,
|
*ZONE_CL_FUNDS_UNIT,
|
||||||
ConstraintProof::nop_constraint(), // alice should demand a tx inclusion proof for the deposit
|
ConstraintProof::nop_constraint(), // alice should demand a tx inclusion proof for the deposit
|
||||||
|
&mut rng,
|
||||||
),
|
),
|
||||||
alice_cl_sk.commit(),
|
alice_cl_sk.commit(),
|
||||||
&mut rng,
|
|
||||||
),
|
),
|
||||||
alice_cl_sk,
|
alice_cl_sk,
|
||||||
);
|
);
|
||||||
|
@ -17,10 +17,14 @@ fn test_withdrawal() {
|
|||||||
ZoneNotes::new_with_balances("ZONE", BTreeMap::from_iter([(alice_vk, 100)]), &mut rng);
|
ZoneNotes::new_with_balances("ZONE", BTreeMap::from_iter([(alice_vk, 100)]), &mut rng);
|
||||||
|
|
||||||
let alice_intent = cl::InputWitness::from_output(
|
let alice_intent = cl::InputWitness::from_output(
|
||||||
cl::OutputWitness::random(
|
cl::OutputWitness::new(
|
||||||
NoteWitness::stateless(1, *ZONE_CL_FUNDS_UNIT, ConstraintProof::nop_constraint()), // TODO, intent should be in the constraint
|
NoteWitness::stateless(
|
||||||
|
1,
|
||||||
|
*ZONE_CL_FUNDS_UNIT,
|
||||||
|
ConstraintProof::nop_constraint(),
|
||||||
|
&mut rng,
|
||||||
|
), // TODO, intent should be in the constraint
|
||||||
alice_cl_sk.commit(),
|
alice_cl_sk.commit(),
|
||||||
&mut rng,
|
|
||||||
),
|
),
|
||||||
alice_cl_sk,
|
alice_cl_sk,
|
||||||
);
|
);
|
||||||
@ -32,14 +36,14 @@ fn test_withdrawal() {
|
|||||||
|
|
||||||
let zone_end = zone_start.clone().run(Tx::Withdraw(withdraw)).0;
|
let zone_end = zone_start.clone().run(Tx::Withdraw(withdraw)).0;
|
||||||
|
|
||||||
let alice_withdrawal = cl::OutputWitness::random(
|
let alice_withdrawal = cl::OutputWitness::new(
|
||||||
NoteWitness::stateless(
|
NoteWitness::stateless(
|
||||||
withdraw.amount,
|
withdraw.amount,
|
||||||
*ZONE_CL_FUNDS_UNIT,
|
*ZONE_CL_FUNDS_UNIT,
|
||||||
ConstraintProof::nop_constraint(),
|
ConstraintProof::nop_constraint(),
|
||||||
|
&mut rng,
|
||||||
),
|
),
|
||||||
alice_cl_sk.commit(),
|
alice_cl_sk.commit(),
|
||||||
&mut rng,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let withdraw_ptx = cl::PartialTxWitness {
|
let withdraw_ptx = cl::PartialTxWitness {
|
||||||
|
@ -33,21 +33,19 @@ fn validate_zone_transition(
|
|||||||
assert_eq!(in_note.input.nf_sk.commit(), out_note.output.nf_pk);
|
assert_eq!(in_note.input.nf_sk.commit(), out_note.output.nf_pk);
|
||||||
|
|
||||||
// the nonce is correctly evolved
|
// the nonce is correctly evolved
|
||||||
assert_eq!(in_note.input.evolved_nonce(b"STATE_NONCE"), out_note.output.nonce);
|
assert_eq!(in_note.input.evolved_nonce(b"STATE_NONCE"), out_note.output.note.nonce);
|
||||||
|
|
||||||
// funds are still under control of the zone
|
// funds are still under control of the zone
|
||||||
let expected_note_witness = NoteWitness::new(
|
let expected_note_witness = NoteWitness {
|
||||||
out_state.total_balance(),
|
value: out_state.total_balance(),
|
||||||
*ZONE_CL_FUNDS_UNIT,
|
unit: *ZONE_CL_FUNDS_UNIT,
|
||||||
metadata.funds_constraint,
|
constraint: metadata.funds_constraint,
|
||||||
metadata.id(),
|
state: metadata.id(),
|
||||||
);
|
nonce: in_note.input.evolved_nonce(b"FUND_NONCE")
|
||||||
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out_funds.output,
|
out_funds.output,
|
||||||
OutputWitness::public(
|
OutputWitness::public(expected_note_witness)
|
||||||
expected_note_witness,
|
|
||||||
in_note.input.evolved_nonce(b"FUND_NONCE")
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
// funds belong to the same partial tx
|
// funds belong to the same partial tx
|
||||||
assert_eq!(out_funds.output_root(), out_note.output_root());
|
assert_eq!(out_funds.output_root(), out_note.output_root());
|
||||||
|
@ -50,16 +50,14 @@ mod test {
|
|||||||
let nf_b = NullifierSecret::random(&mut rng);
|
let nf_b = NullifierSecret::random(&mut rng);
|
||||||
let nf_c = NullifierSecret::random(&mut rng);
|
let nf_c = NullifierSecret::random(&mut rng);
|
||||||
|
|
||||||
let nmo_10_utxo =
|
let nmo_10_utxo = OutputWitness::new(NoteWitness::basic(10, nmo, &mut rng), nf_a.commit());
|
||||||
OutputWitness::random(NoteWitness::basic(10, nmo), nf_a.commit(), &mut rng);
|
|
||||||
let nmo_10_in = InputWitness::from_output(nmo_10_utxo, nf_a);
|
let nmo_10_in = InputWitness::from_output(nmo_10_utxo, nf_a);
|
||||||
|
|
||||||
let eth_23_utxo =
|
let eth_23_utxo = OutputWitness::new(NoteWitness::basic(23, eth, &mut rng), nf_b.commit());
|
||||||
OutputWitness::random(NoteWitness::basic(23, eth), nf_b.commit(), &mut rng);
|
|
||||||
let eth_23_in = InputWitness::from_output(eth_23_utxo, nf_b);
|
let eth_23_in = InputWitness::from_output(eth_23_utxo, nf_b);
|
||||||
|
|
||||||
let crv_4840_out =
|
let crv_4840_out =
|
||||||
OutputWitness::random(NoteWitness::basic(4840, crv), nf_c.commit(), &mut rng);
|
OutputWitness::new(NoteWitness::basic(4840, crv, &mut rng), nf_c.commit());
|
||||||
|
|
||||||
let ptx_unbalanced = PartialTxWitness {
|
let ptx_unbalanced = PartialTxWitness {
|
||||||
inputs: vec![nmo_10_in, eth_23_in],
|
inputs: vec![nmo_10_in, eth_23_in],
|
||||||
@ -94,15 +92,13 @@ mod test {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let crv_4840_in = InputWitness::from_output(crv_4840_out, nf_c);
|
let crv_4840_in = InputWitness::from_output(crv_4840_out, nf_c);
|
||||||
let nmo_10_out = OutputWitness::random(
|
let nmo_10_out = OutputWitness::new(
|
||||||
NoteWitness::basic(10, nmo),
|
NoteWitness::basic(10, nmo, &mut rng),
|
||||||
NullifierSecret::random(&mut rng).commit(), // transferring to a random owner
|
NullifierSecret::random(&mut rng).commit(), // transferring to a random owner
|
||||||
&mut rng,
|
|
||||||
);
|
);
|
||||||
let eth_23_out = OutputWitness::random(
|
let eth_23_out = OutputWitness::new(
|
||||||
NoteWitness::basic(23, eth),
|
NoteWitness::basic(23, eth, &mut rng),
|
||||||
NullifierSecret::random(&mut rng).commit(), // transferring to a random owner
|
NullifierSecret::random(&mut rng).commit(), // transferring to a random owner
|
||||||
&mut rng,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let ptx_solved = PartialTxWitness {
|
let ptx_solved = PartialTxWitness {
|
||||||
|
@ -3,53 +3,59 @@
|
|||||||
/// Partial transactions, as the name suggests, are transactions
|
/// Partial transactions, as the name suggests, are transactions
|
||||||
/// which on their own may not balance (i.e. \sum inputs != \sum outputs)
|
/// which on their own may not balance (i.e. \sum inputs != \sum outputs)
|
||||||
use crate::{
|
use crate::{
|
||||||
note::{ConstraintCommitment, NoteWitness},
|
note::{Constraint, NoteWitness},
|
||||||
nullifier::{Nullifier, NullifierNonce, NullifierSecret},
|
nullifier::{Nullifier, NullifierSecret},
|
||||||
|
Nonce,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
pub nullifier: Nullifier,
|
pub nullifier: Nullifier,
|
||||||
pub constraint: ConstraintCommitment,
|
pub constraint: Constraint,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct InputWitness {
|
pub struct InputWitness {
|
||||||
pub note: NoteWitness,
|
pub note: NoteWitness,
|
||||||
pub nf_sk: NullifierSecret,
|
pub nf_sk: NullifierSecret,
|
||||||
pub nonce: NullifierNonce,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputWitness {
|
impl InputWitness {
|
||||||
|
pub fn new(note: NoteWitness, nf_sk: NullifierSecret) -> Self {
|
||||||
|
Self { note, nf_sk }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_output(output: crate::OutputWitness, nf_sk: NullifierSecret) -> Self {
|
pub fn from_output(output: crate::OutputWitness, nf_sk: NullifierSecret) -> Self {
|
||||||
assert_eq!(nf_sk.commit(), output.nf_pk);
|
assert_eq!(nf_sk.commit(), output.nf_pk);
|
||||||
Self {
|
Self::new(output.note, nf_sk)
|
||||||
note: output.note,
|
|
||||||
nf_sk,
|
|
||||||
nonce: output.nonce,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public(output: crate::OutputWitness) -> Self {
|
pub fn public(output: crate::OutputWitness) -> Self {
|
||||||
let nf_sk = NullifierSecret::zero();
|
let nf_sk = NullifierSecret::zero();
|
||||||
assert_eq!(nf_sk.commit(), output.nf_pk); // ensure the output was a public UTXO
|
assert_eq!(nf_sk.commit(), output.nf_pk); // ensure the output was a public UTXO
|
||||||
Self {
|
Self::new(output.note, nf_sk)
|
||||||
note: output.note,
|
|
||||||
nf_sk,
|
|
||||||
nonce: output.nonce,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evolved_nonce(&self, domain: &[u8]) -> NullifierNonce {
|
pub fn evolved_nonce(&self, domain: &[u8]) -> Nonce {
|
||||||
self.nonce.evolve(domain, &self.nf_sk, &self.note)
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(b"NOMOS_COIN_EVOLVE");
|
||||||
|
hasher.update(domain);
|
||||||
|
hasher.update(self.nf_sk.0);
|
||||||
|
hasher.update(self.note.commit(self.nf_sk.commit()).0);
|
||||||
|
|
||||||
|
let nonce_bytes: [u8; 32] = hasher.finalize().into();
|
||||||
|
Nonce::from_bytes(nonce_bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evolve_output(&self, domain: &[u8]) -> crate::OutputWitness {
|
pub fn evolve_output(&self, domain: &[u8]) -> crate::OutputWitness {
|
||||||
crate::OutputWitness {
|
crate::OutputWitness {
|
||||||
note: self.note,
|
note: NoteWitness {
|
||||||
|
nonce: self.evolved_nonce(domain),
|
||||||
|
..self.note
|
||||||
|
},
|
||||||
nf_pk: self.nf_sk.commit(),
|
nf_pk: self.nf_sk.commit(),
|
||||||
nonce: self.evolved_nonce(domain),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +71,7 @@ impl InputWitness {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn note_commitment(&self) -> crate::NoteCommitment {
|
pub fn note_commitment(&self) -> crate::NoteCommitment {
|
||||||
self.note.commit(self.nf_sk.commit(), self.nonce)
|
self.note.commit(self.nf_sk.commit())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ pub mod partial_tx;
|
|||||||
pub use balance::{Balance, BalanceWitness};
|
pub use balance::{Balance, BalanceWitness};
|
||||||
pub use bundle::{Bundle, BundleWitness};
|
pub use bundle::{Bundle, BundleWitness};
|
||||||
pub use input::{Input, InputWitness};
|
pub use input::{Input, InputWitness};
|
||||||
pub use note::{ConstraintCommitment, NoteCommitment, NoteWitness};
|
pub use note::{Constraint, Nonce, NoteCommitment, NoteWitness};
|
||||||
pub use nullifier::{Nullifier, NullifierCommitment, NullifierNonce, NullifierSecret};
|
pub use nullifier::{Nullifier, NullifierCommitment, NullifierSecret};
|
||||||
pub use output::{Output, OutputWitness};
|
pub use output::{Output, OutputWitness};
|
||||||
pub use partial_tx::{
|
pub use partial_tx::{
|
||||||
PartialTx, PartialTxInputWitness, PartialTxOutputWitness, PartialTxWitness, PtxRoot,
|
PartialTx, PartialTxInputWitness, PartialTxOutputWitness, PartialTxWitness, PtxRoot,
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
|
use rand::RngCore;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
use crate::{
|
use crate::{balance::Unit, nullifier::NullifierCommitment};
|
||||||
balance::Unit,
|
|
||||||
nullifier::{NullifierCommitment, NullifierNonce},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct ConstraintCommitment(pub [u8; 32]);
|
pub struct Constraint(pub [u8; 32]);
|
||||||
|
|
||||||
impl ConstraintCommitment {
|
impl Constraint {
|
||||||
pub fn from_vk(constraint_vk: &[u8]) -> Self {
|
pub fn from_vk(constraint_vk: &[u8]) -> Self {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(b"NOMOS_CL_CONSTRAINT_COMMIT");
|
hasher.update(b"NOMOS_CL_CONSTRAINT_COMMIT");
|
||||||
@ -41,29 +39,39 @@ impl NoteCommitment {
|
|||||||
pub struct NoteWitness {
|
pub struct NoteWitness {
|
||||||
pub value: u64,
|
pub value: u64,
|
||||||
pub unit: Unit,
|
pub unit: Unit,
|
||||||
pub constraint: ConstraintCommitment,
|
pub constraint: Constraint,
|
||||||
pub state: [u8; 32],
|
pub state: [u8; 32],
|
||||||
|
pub nonce: Nonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoteWitness {
|
impl NoteWitness {
|
||||||
pub fn new(value: u64, unit: Unit, constraint: ConstraintCommitment, state: [u8; 32]) -> Self {
|
pub fn new(
|
||||||
|
value: u64,
|
||||||
|
unit: Unit,
|
||||||
|
constraint: Constraint,
|
||||||
|
state: [u8; 32],
|
||||||
|
nonce: Nonce,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value,
|
value,
|
||||||
unit,
|
unit,
|
||||||
constraint,
|
constraint,
|
||||||
state,
|
state,
|
||||||
|
nonce,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn basic(value: u64, unit: Unit) -> Self {
|
pub fn basic(value: u64, unit: Unit, rng: impl RngCore) -> Self {
|
||||||
Self::new(value, unit, ConstraintCommitment([0u8; 32]), [0u8; 32])
|
let constraint = Constraint([0u8; 32]);
|
||||||
|
let nonce = Nonce::random(rng);
|
||||||
|
Self::new(value, unit, constraint, [0u8; 32], nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stateless(value: u64, unit: Unit, constraint: ConstraintCommitment) -> Self {
|
pub fn stateless(value: u64, unit: Unit, constraint: Constraint, rng: impl RngCore) -> Self {
|
||||||
Self::new(value, unit, constraint, [0u8; 32])
|
Self::new(value, unit, constraint, [0u8; 32], Nonce::random(rng))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit(&self, nf_pk: NullifierCommitment, nonce: NullifierNonce) -> NoteCommitment {
|
pub fn commit(&self, nf_pk: NullifierCommitment) -> NoteCommitment {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(b"NOMOS_CL_NOTE_COMMIT");
|
hasher.update(b"NOMOS_CL_NOTE_COMMIT");
|
||||||
|
|
||||||
@ -78,15 +86,36 @@ impl NoteWitness {
|
|||||||
// COMMIT TO CONSTRAINT
|
// COMMIT TO CONSTRAINT
|
||||||
hasher.update(self.constraint.0);
|
hasher.update(self.constraint.0);
|
||||||
|
|
||||||
|
// COMMIT TO NONCE
|
||||||
|
hasher.update(self.nonce.as_bytes());
|
||||||
|
|
||||||
// COMMIT TO NULLIFIER
|
// COMMIT TO NULLIFIER
|
||||||
hasher.update(nf_pk.as_bytes());
|
hasher.update(nf_pk.as_bytes());
|
||||||
hasher.update(nonce.as_bytes());
|
|
||||||
|
|
||||||
let commit_bytes: [u8; 32] = hasher.finalize().into();
|
let commit_bytes: [u8; 32] = hasher.finalize().into();
|
||||||
NoteCommitment(commit_bytes)
|
NoteCommitment(commit_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct Nonce([u8; 32]);
|
||||||
|
|
||||||
|
impl Nonce {
|
||||||
|
pub fn random(mut rng: impl RngCore) -> Self {
|
||||||
|
let mut nonce = [0u8; 32];
|
||||||
|
rng.fill_bytes(&mut nonce);
|
||||||
|
Self(nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bytes(bytes: [u8; 32]) -> Self {
|
||||||
|
Self(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -99,9 +128,8 @@ mod test {
|
|||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let nf_pk = NullifierSecret::random(&mut rng).commit();
|
let nf_pk = NullifierSecret::random(&mut rng).commit();
|
||||||
let nf_nonce = NullifierNonce::random(&mut rng);
|
|
||||||
|
|
||||||
let reference_note = NoteWitness::basic(32, nmo);
|
let reference_note = NoteWitness::basic(32, nmo, &mut rng);
|
||||||
|
|
||||||
// different notes under same nullifier produce different commitments
|
// different notes under same nullifier produce different commitments
|
||||||
let mutation_tests = [
|
let mutation_tests = [
|
||||||
@ -114,38 +142,30 @@ mod test {
|
|||||||
..reference_note
|
..reference_note
|
||||||
},
|
},
|
||||||
NoteWitness {
|
NoteWitness {
|
||||||
constraint: ConstraintCommitment::from_vk(&[1u8; 32]),
|
constraint: Constraint::from_vk(&[1u8; 32]),
|
||||||
..reference_note
|
..reference_note
|
||||||
},
|
},
|
||||||
NoteWitness {
|
NoteWitness {
|
||||||
state: [1u8; 32],
|
state: [1u8; 32],
|
||||||
..reference_note
|
..reference_note
|
||||||
},
|
},
|
||||||
|
NoteWitness {
|
||||||
|
nonce: Nonce::random(&mut rng),
|
||||||
|
..reference_note
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for n in mutation_tests {
|
for n in mutation_tests {
|
||||||
assert_ne!(
|
assert_ne!(n.commit(nf_pk), reference_note.commit(nf_pk));
|
||||||
n.commit(nf_pk, nf_nonce),
|
|
||||||
reference_note.commit(nf_pk, nf_nonce)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// commitment to same note with different nullifiers produce different commitments
|
// commitment to same note with different nullifiers produce different commitments
|
||||||
|
|
||||||
let other_nf_pk = NullifierSecret::random(&mut rng).commit();
|
let other_nf_pk = NullifierSecret::random(&mut rng).commit();
|
||||||
let other_nf_nonce = NullifierNonce::random(&mut rng);
|
|
||||||
|
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
reference_note.commit(nf_pk, nf_nonce),
|
reference_note.commit(nf_pk),
|
||||||
reference_note.commit(other_nf_pk, nf_nonce)
|
reference_note.commit(other_nf_pk)
|
||||||
);
|
|
||||||
assert_ne!(
|
|
||||||
reference_note.commit(nf_pk, nf_nonce),
|
|
||||||
reference_note.commit(nf_pk, other_nf_nonce)
|
|
||||||
);
|
|
||||||
assert_ne!(
|
|
||||||
reference_note.commit(nf_pk, nf_nonce),
|
|
||||||
reference_note.commit(other_nf_pk, other_nf_nonce)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,12 @@
|
|||||||
// notes to allow users to hold fewer secrets. A note
|
// notes to allow users to hold fewer secrets. A note
|
||||||
// nonce is used to disambiguate when the same nullifier
|
// nonce is used to disambiguate when the same nullifier
|
||||||
// secret is used for multiple notes.
|
// secret is used for multiple notes.
|
||||||
|
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
use crate::{NoteCommitment, NoteWitness};
|
use crate::NoteCommitment;
|
||||||
|
|
||||||
// TODO: create a nullifier witness and use it throughout.
|
|
||||||
// struct NullifierWitness {
|
|
||||||
// nf_sk: NullifierSecret,
|
|
||||||
// nonce: NullifierNonce
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Maintained privately by note holder
|
// Maintained privately by note holder
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
@ -27,12 +22,6 @@ pub struct NullifierSecret(pub [u8; 16]);
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct NullifierCommitment([u8; 32]);
|
pub struct NullifierCommitment([u8; 32]);
|
||||||
|
|
||||||
// To allow users to maintain fewer nullifier secrets, we
|
|
||||||
// provide a nonce to differentiate notes controlled by the same
|
|
||||||
// secret. Each note is assigned a unique nullifier nonce.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
||||||
pub struct NullifierNonce([u8; 32]);
|
|
||||||
|
|
||||||
// The nullifier attached to input notes to prove an input has not
|
// The nullifier attached to input notes to prove an input has not
|
||||||
// already been spent.
|
// already been spent.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -77,33 +66,6 @@ impl NullifierCommitment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NullifierNonce {
|
|
||||||
pub fn random(mut rng: impl RngCore) -> Self {
|
|
||||||
let mut nonce = [0u8; 32];
|
|
||||||
rng.fill_bytes(&mut nonce);
|
|
||||||
Self(nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_bytes(&self) -> &[u8; 32] {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_bytes(bytes: [u8; 32]) -> Self {
|
|
||||||
Self(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn evolve(&self, domain: &[u8], nf_sk: &NullifierSecret, note: &NoteWitness) -> Self {
|
|
||||||
let mut hasher = Sha256::new();
|
|
||||||
hasher.update(b"NOMOS_COIN_EVOLVE");
|
|
||||||
hasher.update(domain);
|
|
||||||
hasher.update(nf_sk.0);
|
|
||||||
hasher.update(note.commit(nf_sk.commit(), *self).0);
|
|
||||||
|
|
||||||
let nonce_bytes: [u8; 32] = hasher.finalize().into();
|
|
||||||
Self(nonce_bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Nullifier {
|
impl Nullifier {
|
||||||
pub fn new(sk: NullifierSecret, note_cm: NoteCommitment) -> Self {
|
pub fn new(sk: NullifierSecret, note_cm: NoteCommitment) -> Self {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
@ -122,7 +84,7 @@ impl Nullifier {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{note::derive_unit, NoteWitness};
|
use crate::{note::derive_unit, Constraint, Nonce, NoteWitness};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -147,12 +109,20 @@ mod test {
|
|||||||
fn test_nullifier_same_sk_different_nonce() {
|
fn test_nullifier_same_sk_different_nonce() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let sk = NullifierSecret::random(&mut rng);
|
let sk = NullifierSecret::random(&mut rng);
|
||||||
let note = NoteWitness::basic(1, derive_unit("NMO"));
|
let note_1 = NoteWitness {
|
||||||
|
value: 1,
|
||||||
|
unit: derive_unit("NMO"),
|
||||||
|
constraint: Constraint::from_vk(&[]),
|
||||||
|
state: [0u8; 32],
|
||||||
|
nonce: Nonce::random(&mut rng),
|
||||||
|
};
|
||||||
|
let note_2 = NoteWitness {
|
||||||
|
nonce: Nonce::random(&mut rng),
|
||||||
|
..note_1
|
||||||
|
};
|
||||||
|
|
||||||
let nonce_1 = NullifierNonce::random(&mut rng);
|
let note_cm_1 = note_1.commit(sk.commit());
|
||||||
let nonce_2 = NullifierNonce::random(&mut rng);
|
let note_cm_2 = note_2.commit(sk.commit());
|
||||||
let note_cm_1 = note.commit(sk.commit(), nonce_1);
|
|
||||||
let note_cm_2 = note.commit(sk.commit(), nonce_2);
|
|
||||||
|
|
||||||
let nf_1 = Nullifier::new(sk, note_cm_1);
|
let nf_1 = Nullifier::new(sk, note_cm_1);
|
||||||
let nf_2 = Nullifier::new(sk, note_cm_2);
|
let nf_2 = Nullifier::new(sk, note_cm_2);
|
||||||
@ -163,12 +133,25 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_same_sk_same_nonce_different_note() {
|
fn test_same_sk_same_nonce_different_note() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let sk = NullifierSecret::random(&mut rng);
|
let sk = NullifierSecret::random(&mut rng);
|
||||||
let note_1 = NoteWitness::basic(1, derive_unit("NMO"));
|
let nonce = Nonce::random(&mut rng);
|
||||||
let note_2 = NoteWitness::basic(1, derive_unit("ETH"));
|
|
||||||
let nonce = NullifierNonce::random(&mut rng);
|
let note_1 = NoteWitness {
|
||||||
let note_cm_1 = note_1.commit(sk.commit(), nonce);
|
value: 1,
|
||||||
let note_cm_2 = note_2.commit(sk.commit(), nonce);
|
unit: derive_unit("NMO"),
|
||||||
|
constraint: Constraint::from_vk(&[]),
|
||||||
|
state: [0u8; 32],
|
||||||
|
nonce,
|
||||||
|
};
|
||||||
|
|
||||||
|
let note_2 = NoteWitness {
|
||||||
|
unit: derive_unit("ETH"),
|
||||||
|
..note_1
|
||||||
|
};
|
||||||
|
|
||||||
|
let note_cm_1 = note_1.commit(sk.commit());
|
||||||
|
let note_cm_2 = note_2.commit(sk.commit());
|
||||||
|
|
||||||
let nf_1 = Nullifier::new(sk, note_cm_1);
|
let nf_1 = Nullifier::new(sk, note_cm_1);
|
||||||
let nf_2 = Nullifier::new(sk, note_cm_2);
|
let nf_2 = Nullifier::new(sk, note_cm_2);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use rand_core::CryptoRngCore;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
note::{NoteCommitment, NoteWitness},
|
note::{NoteCommitment, NoteWitness},
|
||||||
nullifier::{NullifierCommitment, NullifierNonce},
|
nullifier::NullifierCommitment,
|
||||||
NullifierSecret,
|
NullifierSecret,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,32 +15,20 @@ pub struct Output {
|
|||||||
pub struct OutputWitness {
|
pub struct OutputWitness {
|
||||||
pub note: NoteWitness,
|
pub note: NoteWitness,
|
||||||
pub nf_pk: NullifierCommitment,
|
pub nf_pk: NullifierCommitment,
|
||||||
pub nonce: NullifierNonce,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutputWitness {
|
impl OutputWitness {
|
||||||
pub fn random(
|
pub fn new(note: NoteWitness, nf_pk: NullifierCommitment) -> Self {
|
||||||
note: NoteWitness,
|
Self { note, nf_pk }
|
||||||
owner: NullifierCommitment,
|
|
||||||
mut rng: impl CryptoRngCore,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
note,
|
|
||||||
nf_pk: owner,
|
|
||||||
nonce: NullifierNonce::random(&mut rng),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public(note: NoteWitness, nonce: NullifierNonce) -> Self {
|
pub fn public(note: NoteWitness) -> Self {
|
||||||
Self {
|
let nf_pk = NullifierSecret::zero().commit();
|
||||||
note,
|
Self { note, nf_pk }
|
||||||
nf_pk: NullifierSecret::zero().commit(),
|
|
||||||
nonce,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit_note(&self) -> NoteCommitment {
|
pub fn commit_note(&self) -> NoteCommitment {
|
||||||
self.note.commit(self.nf_pk, self.nonce)
|
self.note.commit(self.nf_pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit(&self) -> Output {
|
pub fn commit(&self) -> Output {
|
||||||
|
@ -167,16 +167,13 @@ mod test {
|
|||||||
let nf_b = NullifierSecret::random(&mut rng);
|
let nf_b = NullifierSecret::random(&mut rng);
|
||||||
let nf_c = NullifierSecret::random(&mut rng);
|
let nf_c = NullifierSecret::random(&mut rng);
|
||||||
|
|
||||||
let nmo_10_utxo =
|
let nmo_10_utxo = OutputWitness::new(NoteWitness::basic(10, nmo, &mut rng), nf_a.commit());
|
||||||
OutputWitness::random(NoteWitness::basic(10, nmo), nf_a.commit(), &mut rng);
|
|
||||||
let nmo_10 = InputWitness::from_output(nmo_10_utxo, nf_a);
|
let nmo_10 = InputWitness::from_output(nmo_10_utxo, nf_a);
|
||||||
|
|
||||||
let eth_23_utxo =
|
let eth_23_utxo = OutputWitness::new(NoteWitness::basic(23, eth, &mut rng), nf_b.commit());
|
||||||
OutputWitness::random(NoteWitness::basic(23, eth), nf_b.commit(), &mut rng);
|
|
||||||
let eth_23 = InputWitness::from_output(eth_23_utxo, nf_b);
|
let eth_23 = InputWitness::from_output(eth_23_utxo, nf_b);
|
||||||
|
|
||||||
let crv_4840 =
|
let crv_4840 = OutputWitness::new(NoteWitness::basic(4840, crv, &mut rng), nf_c.commit());
|
||||||
OutputWitness::random(NoteWitness::basic(4840, crv), nf_c.commit(), &mut rng);
|
|
||||||
|
|
||||||
let ptx_witness = PartialTxWitness {
|
let ptx_witness = PartialTxWitness {
|
||||||
inputs: vec![nmo_10, eth_23],
|
inputs: vec![nmo_10, eth_23],
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
use cl::{note::derive_unit, BalanceWitness};
|
use cl::{note::derive_unit, BalanceWitness};
|
||||||
use rand_core::CryptoRngCore;
|
|
||||||
|
|
||||||
fn receive_utxo(
|
fn receive_utxo(note: cl::NoteWitness, nf_pk: cl::NullifierCommitment) -> cl::OutputWitness {
|
||||||
note: cl::NoteWitness,
|
cl::OutputWitness::new(note, nf_pk)
|
||||||
nf_pk: cl::NullifierCommitment,
|
|
||||||
rng: impl CryptoRngCore,
|
|
||||||
) -> cl::OutputWitness {
|
|
||||||
cl::OutputWitness::random(note, nf_pk, rng)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -20,13 +15,13 @@ fn test_simple_transfer() {
|
|||||||
let recipient_nf_pk = cl::NullifierSecret::random(&mut rng).commit();
|
let recipient_nf_pk = cl::NullifierSecret::random(&mut rng).commit();
|
||||||
|
|
||||||
// Assume the sender has received an unspent output from somewhere
|
// Assume the sender has received an unspent output from somewhere
|
||||||
let utxo = receive_utxo(cl::NoteWitness::basic(10, nmo), sender_nf_pk, &mut rng);
|
let utxo = receive_utxo(cl::NoteWitness::basic(10, nmo, &mut rng), sender_nf_pk);
|
||||||
|
|
||||||
// and wants to send 8 NMO to some recipient and return 2 NMO to itself.
|
// and wants to send 8 NMO to some recipient and return 2 NMO to itself.
|
||||||
let recipient_output =
|
let recipient_output =
|
||||||
cl::OutputWitness::random(cl::NoteWitness::basic(8, nmo), recipient_nf_pk, &mut rng);
|
cl::OutputWitness::new(cl::NoteWitness::basic(8, nmo, &mut rng), recipient_nf_pk);
|
||||||
let change_output =
|
let change_output =
|
||||||
cl::OutputWitness::random(cl::NoteWitness::basic(2, nmo), sender_nf_pk, &mut rng);
|
cl::OutputWitness::new(cl::NoteWitness::basic(2, nmo, &mut rng), sender_nf_pk);
|
||||||
|
|
||||||
let ptx_witness = cl::PartialTxWitness {
|
let ptx_witness = cl::PartialTxWitness {
|
||||||
inputs: vec![cl::InputWitness::from_output(utxo, sender_nf_sk)],
|
inputs: vec![cl::InputWitness::from_output(utxo, sender_nf_sk)],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use cl::ConstraintCommitment;
|
use cl::Constraint;
|
||||||
use ledger_proof_statements::constraint::ConstraintPublic;
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
@ -9,20 +9,20 @@ pub struct ConstraintProof {
|
|||||||
pub risc0_receipt: risc0_zkvm::Receipt,
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn risc0_constraint(risc0_id: [u32; 8]) -> ConstraintCommitment {
|
pub fn risc0_constraint(risc0_id: [u32; 8]) -> Constraint {
|
||||||
// Commit to a RISC0 ID for use as a note constraint
|
// Commit to a RISC0 ID for use as a note constraint
|
||||||
|
|
||||||
let mut bytes = [0u8; 32];
|
let mut bytes = [0u8; 32];
|
||||||
|
|
||||||
for (i, word) in risc0_id.iter().enumerate() {
|
for (i, word) in risc0_id.iter().enumerate() {
|
||||||
let word_bytes = word.to_le_bytes();
|
let word_bytes = word.to_le_bytes();
|
||||||
bytes[i * 4 + 0] = word_bytes[0];
|
bytes[i * 4] = word_bytes[0];
|
||||||
bytes[i * 4 + 1] = word_bytes[1];
|
bytes[i * 4 + 1] = word_bytes[1];
|
||||||
bytes[i * 4 + 2] = word_bytes[2];
|
bytes[i * 4 + 2] = word_bytes[2];
|
||||||
bytes[i * 4 + 3] = word_bytes[3];
|
bytes[i * 4 + 3] = word_bytes[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstraintCommitment::from_vk(&bytes)
|
Constraint::from_vk(&bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstraintProof {
|
impl ConstraintProof {
|
||||||
@ -33,7 +33,7 @@ impl ConstraintProof {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constraint(&self) -> ConstraintCommitment {
|
pub fn constraint(&self) -> Constraint {
|
||||||
risc0_constraint(self.risc0_id)
|
risc0_constraint(self.risc0_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ impl ConstraintProof {
|
|||||||
expected_public == public && self.risc0_receipt.verify(self.risc0_id).is_ok()
|
expected_public == public && self.risc0_receipt.verify(self.risc0_id).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nop_constraint() -> ConstraintCommitment {
|
pub fn nop_constraint() -> Constraint {
|
||||||
risc0_constraint(nomos_cl_risc0_proofs::CONSTRAINT_NOP_ID)
|
risc0_constraint(nomos_cl_risc0_proofs::CONSTRAINT_NOP_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +117,5 @@ impl ProvedPartialTx {
|
|||||||
|
|
||||||
fn note_commitment_leaves(note_commitments: &[cl::NoteCommitment]) -> [[u8; 32]; MAX_NOTE_COMMS] {
|
fn note_commitment_leaves(note_commitments: &[cl::NoteCommitment]) -> [[u8; 32]; MAX_NOTE_COMMS] {
|
||||||
let note_comm_bytes = Vec::from_iter(note_commitments.iter().map(|c| c.as_bytes().to_vec()));
|
let note_comm_bytes = Vec::from_iter(note_commitments.iter().map(|c| c.as_bytes().to_vec()));
|
||||||
let cm_leaves = cl::merkle::padded_leaves::<MAX_NOTE_COMMS>(¬e_comm_bytes);
|
cl::merkle::padded_leaves::<MAX_NOTE_COMMS>(¬e_comm_bytes)
|
||||||
cm_leaves
|
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,8 @@ impl User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive_utxo(
|
fn receive_utxo(note: cl::NoteWitness, nf_pk: cl::NullifierCommitment) -> cl::OutputWitness {
|
||||||
note: cl::NoteWitness,
|
cl::OutputWitness::new(note, nf_pk)
|
||||||
nf_pk: cl::NullifierCommitment,
|
|
||||||
rng: impl CryptoRngCore,
|
|
||||||
) -> cl::OutputWitness {
|
|
||||||
cl::OutputWitness::random(note, nf_pk, rng)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -41,18 +37,17 @@ fn test_simple_transfer() {
|
|||||||
|
|
||||||
// Alice has an unspent note worth 10 NMO
|
// Alice has an unspent note worth 10 NMO
|
||||||
let utxo = receive_utxo(
|
let utxo = receive_utxo(
|
||||||
cl::NoteWitness::stateless(10, nmo, ConstraintProof::nop_constraint()),
|
cl::NoteWitness::stateless(10, nmo, ConstraintProof::nop_constraint(), &mut rng),
|
||||||
alice.pk(),
|
alice.pk(),
|
||||||
&mut rng,
|
|
||||||
);
|
);
|
||||||
let alices_input = cl::InputWitness::from_output(utxo, alice.sk());
|
let alices_input = cl::InputWitness::from_output(utxo, alice.sk());
|
||||||
|
|
||||||
// Alice wants to send 8 NMO to bob
|
// Alice wants to send 8 NMO to bob
|
||||||
let bobs_output = cl::OutputWitness::random(cl::NoteWitness::basic(8, nmo), bob.pk(), &mut rng);
|
let bobs_output = cl::OutputWitness::new(cl::NoteWitness::basic(8, nmo, &mut rng), bob.pk());
|
||||||
|
|
||||||
// .. and return the 2 NMO in change to herself.
|
// .. and return the 2 NMO in change to herself.
|
||||||
let change_output =
|
let change_output =
|
||||||
cl::OutputWitness::random(cl::NoteWitness::basic(2, nmo), alice.pk(), &mut rng);
|
cl::OutputWitness::new(cl::NoteWitness::basic(2, nmo, &mut rng), alice.pk());
|
||||||
|
|
||||||
// Construct the ptx consuming Alices inputs and producing the two outputs.
|
// Construct the ptx consuming Alices inputs and producing the two outputs.
|
||||||
let ptx_witness = cl::PartialTxWitness {
|
let ptx_witness = cl::PartialTxWitness {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user