mirror of
https://github.com/logos-co/nomos-pocs.git
synced 2025-01-11 09:56:11 +00:00
goas: rename DeathConstraint to Constraint
This commit is contained in:
parent
23df7331c8
commit
cffd687e50
@ -1,6 +1,6 @@
|
|||||||
pub mod mmr;
|
pub mod mmr;
|
||||||
|
|
||||||
use cl::{balance::Unit, NoteCommitment};
|
use cl::{balance::Unit, ConstraintCommitment, 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,16 +27,16 @@ 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_vk: [u8; 32],
|
pub zone_constraint: ConstraintCommitment,
|
||||||
pub funds_vk: [u8; 32],
|
pub funds_constraint: ConstraintCommitment,
|
||||||
pub unit: Unit,
|
pub unit: Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZoneMetadata {
|
impl ZoneMetadata {
|
||||||
pub fn id(&self) -> [u8; 32] {
|
pub fn id(&self) -> [u8; 32] {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(self.zone_vk);
|
hasher.update(self.zone_constraint.0);
|
||||||
hasher.update(self.funds_vk);
|
hasher.update(self.funds_constraint.0);
|
||||||
hasher.update(self.unit);
|
hasher.update(self.unit);
|
||||||
hasher.finalize().into()
|
hasher.finalize().into()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use cl::ConstraintCommitment;
|
||||||
use common::{
|
use common::{
|
||||||
mmr::MMR, AccountId, IncludedTxWitness, SignedBoundTx, StateWitness, Tx, ZoneMetadata,
|
mmr::MMR, AccountId, IncludedTxWitness, SignedBoundTx, StateWitness, Tx, ZoneMetadata,
|
||||||
};
|
};
|
||||||
@ -78,7 +79,7 @@ fn zone_fund_utxo(
|
|||||||
cl::NoteWitness {
|
cl::NoteWitness {
|
||||||
value,
|
value,
|
||||||
unit: *common::ZONE_CL_FUNDS_UNIT,
|
unit: *common::ZONE_CL_FUNDS_UNIT,
|
||||||
death_constraint: zone_meta.funds_vk,
|
constraint: zone_meta.funds_constraint,
|
||||||
state: zone_meta.id(),
|
state: zone_meta.id(),
|
||||||
},
|
},
|
||||||
cl::NullifierNonce::random(&mut rng),
|
cl::NullifierNonce::random(&mut rng),
|
||||||
@ -90,33 +91,29 @@ fn zone_state_utxo(zone: &StateWitness, mut rng: impl CryptoRngCore) -> cl::Outp
|
|||||||
cl::NoteWitness {
|
cl::NoteWitness {
|
||||||
value: 1,
|
value: 1,
|
||||||
unit: zone.zone_metadata.unit,
|
unit: zone.zone_metadata.unit,
|
||||||
death_constraint: zone.zone_metadata.zone_vk,
|
constraint: zone.zone_metadata.zone_constraint,
|
||||||
state: zone.commit().0,
|
state: zone.commit().0,
|
||||||
},
|
},
|
||||||
cl::NullifierNonce::random(&mut rng),
|
cl::NullifierNonce::random(&mut rng),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_atomic_transfer_death_constraint() -> [u8; 32] {
|
pub fn user_atomic_transfer_constraint() -> ConstraintCommitment {
|
||||||
ledger::death_constraint::risc0_id_to_cl_death_constraint(
|
ledger::constraint::risc0_constraint(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID)
|
||||||
goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zone_state_death_constraint() -> [u8; 32] {
|
pub fn zone_state_constraint() -> ConstraintCommitment {
|
||||||
ledger::death_constraint::risc0_id_to_cl_death_constraint(goas_risc0_proofs::ZONE_STATE_ID)
|
ledger::constraint::risc0_constraint(goas_risc0_proofs::ZONE_STATE_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zone_fund_death_constraint() -> [u8; 32] {
|
pub fn zone_fund_constraint() -> ConstraintCommitment {
|
||||||
ledger::death_constraint::risc0_id_to_cl_death_constraint(
|
ledger::constraint::risc0_constraint(goas_risc0_proofs::SPEND_ZONE_FUNDS_ID)
|
||||||
goas_risc0_proofs::SPEND_ZONE_FUNDS_ID,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zone_metadata(zone_mnemonic: &str) -> ZoneMetadata {
|
pub fn zone_metadata(zone_mnemonic: &str) -> ZoneMetadata {
|
||||||
ZoneMetadata {
|
ZoneMetadata {
|
||||||
zone_vk: zone_state_death_constraint(),
|
zone_constraint: zone_state_constraint(),
|
||||||
funds_vk: zone_fund_death_constraint(),
|
funds_constraint: zone_fund_constraint(),
|
||||||
unit: cl::note::derive_unit(zone_mnemonic),
|
unit: cl::note::derive_unit(zone_mnemonic),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +124,7 @@ pub fn prove_zone_stf(
|
|||||||
zone_in: cl::PartialTxInputWitness,
|
zone_in: cl::PartialTxInputWitness,
|
||||||
zone_out: cl::PartialTxOutputWitness,
|
zone_out: cl::PartialTxOutputWitness,
|
||||||
funds_out: cl::PartialTxOutputWitness,
|
funds_out: cl::PartialTxOutputWitness,
|
||||||
) -> ledger::DeathProof {
|
) -> ledger::ConstraintProof {
|
||||||
let private_inputs = ZoneStatePrivate {
|
let private_inputs = ZoneStatePrivate {
|
||||||
state,
|
state,
|
||||||
inputs,
|
inputs,
|
||||||
@ -156,14 +153,14 @@ pub fn prove_zone_stf(
|
|||||||
prove_info.stats.total_cycles
|
prove_info.stats.total_cycles
|
||||||
);
|
);
|
||||||
let receipt = prove_info.receipt;
|
let receipt = prove_info.receipt;
|
||||||
ledger::DeathProof::from_risc0(goas_risc0_proofs::ZONE_STATE_ID, receipt)
|
ledger::ConstraintProof::from_risc0(goas_risc0_proofs::ZONE_STATE_ID, receipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prove_zone_fund_constraint(
|
pub fn prove_zone_fund_constraint(
|
||||||
in_zone_funds: cl::PartialTxInputWitness,
|
in_zone_funds: cl::PartialTxInputWitness,
|
||||||
zone_note: cl::PartialTxOutputWitness,
|
zone_note: cl::PartialTxOutputWitness,
|
||||||
out_zone_state: &StateWitness,
|
out_zone_state: &StateWitness,
|
||||||
) -> ledger::DeathProof {
|
) -> ledger::ConstraintProof {
|
||||||
let private_inputs = SpendFundsPrivate {
|
let private_inputs = SpendFundsPrivate {
|
||||||
in_zone_funds,
|
in_zone_funds,
|
||||||
zone_note,
|
zone_note,
|
||||||
@ -190,10 +187,10 @@ pub fn prove_zone_fund_constraint(
|
|||||||
prove_info.stats.total_cycles
|
prove_info.stats.total_cycles
|
||||||
);
|
);
|
||||||
let receipt = prove_info.receipt;
|
let receipt = prove_info.receipt;
|
||||||
ledger::DeathProof::from_risc0(goas_risc0_proofs::SPEND_ZONE_FUNDS_ID, receipt)
|
ledger::ConstraintProof::from_risc0(goas_risc0_proofs::SPEND_ZONE_FUNDS_ID, receipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prove_user_atomic_transfer(atomic_transfer: UserAtomicTransfer) -> ledger::DeathProof {
|
pub fn prove_user_atomic_transfer(atomic_transfer: UserAtomicTransfer) -> ledger::ConstraintProof {
|
||||||
let env = risc0_zkvm::ExecutorEnv::builder()
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
||||||
.write(&atomic_transfer)
|
.write(&atomic_transfer)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -214,7 +211,7 @@ pub fn prove_user_atomic_transfer(atomic_transfer: UserAtomicTransfer) -> ledger
|
|||||||
prove_info.stats.total_cycles
|
prove_info.stats.total_cycles
|
||||||
);
|
);
|
||||||
let receipt = prove_info.receipt;
|
let receipt = prove_info.receipt;
|
||||||
ledger::DeathProof::from_risc0(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID, receipt)
|
ledger::ConstraintProof::from_risc0(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID, receipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -225,7 +222,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use common::{BoundTx, Deposit, Withdraw};
|
use common::{BoundTx, Deposit, Withdraw};
|
||||||
use goas_proof_statements::user_note::UserIntent;
|
use goas_proof_statements::user_note::UserIntent;
|
||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
use ledger::ConstraintProof;
|
||||||
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -277,7 +275,7 @@ mod tests {
|
|||||||
ptx.output_witness(1),
|
ptx.output_witness(1),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(proof.verify(DeathConstraintPublic {
|
assert!(proof.verify(ConstraintPublic {
|
||||||
nf: zone_start.state_input_witness().nullifier(),
|
nf: zone_start.state_input_witness().nullifier(),
|
||||||
ptx_root: ptx.commit().root(),
|
ptx_root: ptx.commit().root(),
|
||||||
}))
|
}))
|
||||||
@ -297,7 +295,7 @@ mod tests {
|
|||||||
let proof =
|
let proof =
|
||||||
prove_zone_fund_constraint(ptx.input_witness(0), ptx.output_witness(0), &zone.state);
|
prove_zone_fund_constraint(ptx.input_witness(0), ptx.output_witness(0), &zone.state);
|
||||||
|
|
||||||
assert!(proof.verify(DeathConstraintPublic {
|
assert!(proof.verify(ConstraintPublic {
|
||||||
nf: zone.fund_input_witness().nullifier(),
|
nf: zone.fund_input_witness().nullifier(),
|
||||||
ptx_root: ptx.commit().root(),
|
ptx_root: ptx.commit().root(),
|
||||||
}))
|
}))
|
||||||
@ -327,7 +325,12 @@ mod tests {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let user_note = cl::InputWitness::public(cl::OutputWitness::public(
|
let user_note = cl::InputWitness::public(cl::OutputWitness::public(
|
||||||
NoteWitness::new(1, derive_unit("INTENT"), [0u8; 32], user_intent.commit()),
|
NoteWitness::new(
|
||||||
|
1,
|
||||||
|
derive_unit("INTENT"),
|
||||||
|
ConstraintProof::nop_constraint(),
|
||||||
|
user_intent.commit(),
|
||||||
|
),
|
||||||
NullifierNonce::random(&mut rng),
|
NullifierNonce::random(&mut rng),
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -353,7 +356,7 @@ mod tests {
|
|||||||
|
|
||||||
let proof = prove_user_atomic_transfer(user_atomic_transfer);
|
let proof = prove_user_atomic_transfer(user_atomic_transfer);
|
||||||
|
|
||||||
assert!(proof.verify(DeathConstraintPublic {
|
assert!(proof.verify(ConstraintPublic {
|
||||||
nf: user_note.nullifier(),
|
nf: user_note.nullifier(),
|
||||||
ptx_root: ptx.commit().root(),
|
ptx_root: ptx.commit().root(),
|
||||||
}))
|
}))
|
||||||
|
@ -34,7 +34,7 @@ fn test_atomic_transfer() {
|
|||||||
NoteWitness {
|
NoteWitness {
|
||||||
value: 1,
|
value: 1,
|
||||||
unit: cl::note::derive_unit("INTENT"),
|
unit: cl::note::derive_unit("INTENT"),
|
||||||
death_constraint: executor::user_atomic_transfer_death_constraint(),
|
constraint: executor::user_atomic_transfer_constraint(),
|
||||||
state: alice_intent.commit(),
|
state: alice_intent.commit(),
|
||||||
},
|
},
|
||||||
NullifierNonce::random(&mut rng),
|
NullifierNonce::random(&mut rng),
|
||||||
@ -86,7 +86,7 @@ fn test_atomic_transfer() {
|
|||||||
&mut alice,
|
&mut alice,
|
||||||
);
|
);
|
||||||
|
|
||||||
let death_proofs = BTreeMap::from_iter([
|
let constraint_proofs = BTreeMap::from_iter([
|
||||||
(
|
(
|
||||||
alice_intent_in.nullifier(),
|
alice_intent_in.nullifier(),
|
||||||
executor::prove_user_atomic_transfer(UserAtomicTransfer {
|
executor::prove_user_atomic_transfer(UserAtomicTransfer {
|
||||||
@ -153,7 +153,7 @@ fn test_atomic_transfer() {
|
|||||||
|
|
||||||
let atomic_transfer_proof = ledger::partial_tx::ProvedPartialTx::prove(
|
let atomic_transfer_proof = ledger::partial_tx::ProvedPartialTx::prove(
|
||||||
&atomic_transfer_ptx,
|
&atomic_transfer_ptx,
|
||||||
death_proofs,
|
constraint_proofs,
|
||||||
¬e_commitments,
|
¬e_commitments,
|
||||||
)
|
)
|
||||||
.expect("atomic transfer proof failed");
|
.expect("atomic transfer proof failed");
|
||||||
|
@ -3,7 +3,7 @@ use std::collections::BTreeMap;
|
|||||||
use cl::{BalanceWitness, NoteWitness, NullifierSecret};
|
use cl::{BalanceWitness, NoteWitness, NullifierSecret};
|
||||||
use common::{mmr::MMR, new_account, BoundTx, SignedBoundTx, StateWitness, Tx, ZONE_CL_FUNDS_UNIT};
|
use common::{mmr::MMR, new_account, BoundTx, SignedBoundTx, StateWitness, Tx, ZONE_CL_FUNDS_UNIT};
|
||||||
use executor::ZoneNotes;
|
use executor::ZoneNotes;
|
||||||
use ledger::death_constraint::DeathProof;
|
use ledger::constraint::ConstraintProof;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deposit() {
|
fn test_deposit() {
|
||||||
@ -27,7 +27,7 @@ fn test_deposit() {
|
|||||||
NoteWitness::stateless(
|
NoteWitness::stateless(
|
||||||
78,
|
78,
|
||||||
*ZONE_CL_FUNDS_UNIT,
|
*ZONE_CL_FUNDS_UNIT,
|
||||||
DeathProof::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
|
||||||
),
|
),
|
||||||
alice_cl_sk.commit(),
|
alice_cl_sk.commit(),
|
||||||
&mut rng,
|
&mut rng,
|
||||||
@ -49,7 +49,7 @@ fn test_deposit() {
|
|||||||
&mut alice,
|
&mut alice,
|
||||||
);
|
);
|
||||||
|
|
||||||
let death_proofs = BTreeMap::from_iter([
|
let constraint_proofs = BTreeMap::from_iter([
|
||||||
(
|
(
|
||||||
zone_start.state_input_witness().nullifier(),
|
zone_start.state_input_witness().nullifier(),
|
||||||
executor::prove_zone_stf(
|
executor::prove_zone_stf(
|
||||||
@ -62,7 +62,10 @@ fn test_deposit() {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
alice_deposit.nullifier(),
|
alice_deposit.nullifier(),
|
||||||
ledger::DeathProof::prove_nop(alice_deposit.nullifier(), deposit_ptx.commit().root()),
|
ledger::ConstraintProof::prove_nop(
|
||||||
|
alice_deposit.nullifier(),
|
||||||
|
deposit_ptx.commit().root(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -71,8 +74,11 @@ fn test_deposit() {
|
|||||||
alice_deposit.note_commitment(),
|
alice_deposit.note_commitment(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let deposit_proof =
|
let deposit_proof = ledger::partial_tx::ProvedPartialTx::prove(
|
||||||
ledger::partial_tx::ProvedPartialTx::prove(&deposit_ptx, death_proofs, ¬e_commitments)
|
&deposit_ptx,
|
||||||
|
constraint_proofs,
|
||||||
|
¬e_commitments,
|
||||||
|
)
|
||||||
.expect("deposit proof failed");
|
.expect("deposit proof failed");
|
||||||
|
|
||||||
assert!(deposit_proof.verify());
|
assert!(deposit_proof.verify());
|
||||||
|
@ -3,7 +3,7 @@ use std::collections::BTreeMap;
|
|||||||
use cl::{BalanceWitness, NoteWitness, NullifierSecret};
|
use cl::{BalanceWitness, NoteWitness, NullifierSecret};
|
||||||
use common::{mmr::MMR, new_account, BoundTx, SignedBoundTx, StateWitness, Tx, ZONE_CL_FUNDS_UNIT};
|
use common::{mmr::MMR, new_account, BoundTx, SignedBoundTx, StateWitness, Tx, ZONE_CL_FUNDS_UNIT};
|
||||||
use executor::ZoneNotes;
|
use executor::ZoneNotes;
|
||||||
use ledger::death_constraint::DeathProof;
|
use ledger::constraint::ConstraintProof;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_withdrawal() {
|
fn test_withdrawal() {
|
||||||
@ -18,7 +18,7 @@ fn test_withdrawal() {
|
|||||||
|
|
||||||
let alice_intent = cl::InputWitness::from_output(
|
let alice_intent = cl::InputWitness::from_output(
|
||||||
cl::OutputWitness::random(
|
cl::OutputWitness::random(
|
||||||
NoteWitness::stateless(1, *ZONE_CL_FUNDS_UNIT, DeathProof::nop_constraint()), // TODO, intent should be in the death constraint
|
NoteWitness::stateless(1, *ZONE_CL_FUNDS_UNIT, ConstraintProof::nop_constraint()), // TODO, intent should be in the constraint
|
||||||
alice_cl_sk.commit(),
|
alice_cl_sk.commit(),
|
||||||
&mut rng,
|
&mut rng,
|
||||||
),
|
),
|
||||||
@ -36,7 +36,7 @@ fn test_withdrawal() {
|
|||||||
NoteWitness::stateless(
|
NoteWitness::stateless(
|
||||||
withdraw.amount,
|
withdraw.amount,
|
||||||
*ZONE_CL_FUNDS_UNIT,
|
*ZONE_CL_FUNDS_UNIT,
|
||||||
DeathProof::nop_constraint(),
|
ConstraintProof::nop_constraint(),
|
||||||
),
|
),
|
||||||
alice_cl_sk.commit(),
|
alice_cl_sk.commit(),
|
||||||
&mut rng,
|
&mut rng,
|
||||||
@ -60,7 +60,7 @@ fn test_withdrawal() {
|
|||||||
&mut alice,
|
&mut alice,
|
||||||
);
|
);
|
||||||
|
|
||||||
let death_proofs = BTreeMap::from_iter([
|
let constraint_proofs = BTreeMap::from_iter([
|
||||||
(
|
(
|
||||||
zone_start.state_input_witness().nullifier(),
|
zone_start.state_input_witness().nullifier(),
|
||||||
executor::prove_zone_stf(
|
executor::prove_zone_stf(
|
||||||
@ -81,7 +81,7 @@ fn test_withdrawal() {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
alice_intent.nullifier(),
|
alice_intent.nullifier(),
|
||||||
DeathProof::prove_nop(alice_intent.nullifier(), withdraw_ptx.commit().root()),
|
ConstraintProof::prove_nop(alice_intent.nullifier(), withdraw_ptx.commit().root()),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -91,8 +91,11 @@ fn test_withdrawal() {
|
|||||||
alice_intent.note_commitment(),
|
alice_intent.note_commitment(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let withdraw_proof =
|
let withdraw_proof = ledger::partial_tx::ProvedPartialTx::prove(
|
||||||
ledger::partial_tx::ProvedPartialTx::prove(&withdraw_ptx, death_proofs, ¬e_commitments)
|
&withdraw_ptx,
|
||||||
|
constraint_proofs,
|
||||||
|
¬e_commitments,
|
||||||
|
)
|
||||||
.expect("withdraw proof failed");
|
.expect("withdraw proof failed");
|
||||||
|
|
||||||
assert!(withdraw_proof.verify());
|
assert!(withdraw_proof.verify());
|
||||||
|
@ -9,6 +9,6 @@ pub fn assert_is_zone_note(
|
|||||||
) {
|
) {
|
||||||
assert_eq!(state_roots.commit().0, note.state);
|
assert_eq!(state_roots.commit().0, note.state);
|
||||||
assert_eq!(zone_meta.id(), state_roots.zone_id);
|
assert_eq!(zone_meta.id(), state_roots.zone_id);
|
||||||
assert_eq!(zone_meta.zone_vk, note.death_constraint);
|
assert_eq!(zone_meta.zone_constraint, note.constraint);
|
||||||
assert_eq!(zone_meta.unit, note.unit);
|
assert_eq!(zone_meta.unit, note.unit);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
/// Thep User Note will encode the logic that orchestrates the withdrawal from zone A
|
/// Thep User Note will encode the logic that orchestrates the withdrawal from zone A
|
||||||
/// and deposit to zone B.
|
/// and deposit to zone B.
|
||||||
///
|
///
|
||||||
/// The User Notes death constraint requires the following statements to be satisfied
|
/// The User Notes constraint requires the following statements to be satisfied
|
||||||
/// in order for the fee to be captured.
|
/// in order for the fee to be captured.
|
||||||
///
|
///
|
||||||
/// 1. w_tx = withdraw(amt=100 NMO, from=Alice) tx was included in Zone A.
|
/// 1. w_tx = withdraw(amt=100 NMO, from=Alice) tx was included in Zone A.
|
||||||
@ -22,7 +22,7 @@
|
|||||||
/// Details:
|
/// Details:
|
||||||
/// - the withdrawal in zone A must not be a general withdrawal tx, it must be bound to the user note.
|
/// - the withdrawal in zone A must not be a general withdrawal tx, it must be bound to the user note.
|
||||||
/// i.e. the user_note must be present in the ptx for the withdrawal to be valid in Zone A.
|
/// i.e. the user_note must be present in the ptx for the withdrawal to be valid in Zone A.
|
||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ pub struct UserAtomicTransfer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UserAtomicTransfer {
|
impl UserAtomicTransfer {
|
||||||
pub fn assert_constraints(&self) -> DeathConstraintPublic {
|
pub fn assert_constraints(&self) -> ConstraintPublic {
|
||||||
// user committed to these actions in the user note
|
// user committed to these actions in the user note
|
||||||
assert_eq!(self.user_intent.commit(), self.user_note.input.note.state);
|
assert_eq!(self.user_intent.commit(), self.user_note.input.note.state);
|
||||||
|
|
||||||
@ -103,6 +103,6 @@ impl UserAtomicTransfer {
|
|||||||
|
|
||||||
let ptx_root = cl::PtxRoot(cl::merkle::node(input_root, output_root));
|
let ptx_root = cl::PtxRoot(cl::merkle::node(input_root, output_root));
|
||||||
let nf = self.user_note.input.nullifier();
|
let nf = self.user_note.input.nullifier();
|
||||||
DeathConstraintPublic { ptx_root, nf }
|
ConstraintPublic { ptx_root, nf }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use cl::merkle;
|
use cl::merkle;
|
||||||
use cl::partial_tx::PtxRoot;
|
use cl::partial_tx::PtxRoot;
|
||||||
use goas_proof_statements::zone_funds::SpendFundsPrivate;
|
use goas_proof_statements::zone_funds::SpendFundsPrivate;
|
||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
use risc0_zkvm::guest::env;
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -25,5 +25,5 @@ fn main() {
|
|||||||
|
|
||||||
let nf = in_zone_funds.input.nullifier();
|
let nf = in_zone_funds.input.nullifier();
|
||||||
|
|
||||||
env::commit(&DeathConstraintPublic { ptx_root, nf });
|
env::commit(&ConstraintPublic { ptx_root, nf });
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use goas_proof_statements::user_note::UserAtomicTransfer;
|
use goas_proof_statements::user_note::UserAtomicTransfer;
|
||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
use risc0_zkvm::guest::env;
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let transfer: UserAtomicTransfer = env::read();
|
let transfer: UserAtomicTransfer = env::read();
|
||||||
let public: DeathConstraintPublic = transfer.assert_constraints();
|
let public: ConstraintPublic = transfer.assert_constraints();
|
||||||
env::commit(&public);
|
env::commit(&public);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use cl::{
|
|||||||
|
|
||||||
use common::*;
|
use common::*;
|
||||||
use goas_proof_statements::zone_state::ZoneStatePrivate;
|
use goas_proof_statements::zone_state::ZoneStatePrivate;
|
||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
use risc0_zkvm::guest::env;
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
fn validate_zone_transition(
|
fn validate_zone_transition(
|
||||||
@ -26,8 +26,8 @@ fn validate_zone_transition(
|
|||||||
assert_eq!(out_note.output.note.unit, metadata.unit);
|
assert_eq!(out_note.output.note.unit, metadata.unit);
|
||||||
|
|
||||||
// ensure constraints match metadata
|
// ensure constraints match metadata
|
||||||
assert_eq!(in_note.input.note.death_constraint, metadata.zone_vk);
|
assert_eq!(in_note.input.note.constraint, metadata.zone_constraint);
|
||||||
assert_eq!(out_note.output.note.death_constraint, metadata.zone_vk);
|
assert_eq!(out_note.output.note.constraint, metadata.zone_constraint);
|
||||||
|
|
||||||
// nullifier secret is propagated
|
// nullifier secret is propagated
|
||||||
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);
|
||||||
@ -39,7 +39,7 @@ fn validate_zone_transition(
|
|||||||
let expected_note_witness = NoteWitness::new(
|
let expected_note_witness = NoteWitness::new(
|
||||||
out_state.total_balance(),
|
out_state.total_balance(),
|
||||||
*ZONE_CL_FUNDS_UNIT,
|
*ZONE_CL_FUNDS_UNIT,
|
||||||
metadata.funds_vk,
|
metadata.funds_constraint,
|
||||||
metadata.id(),
|
metadata.id(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -65,7 +65,7 @@ fn main() {
|
|||||||
let input_root = zone_in.input_root();
|
let input_root = zone_in.input_root();
|
||||||
let output_root = zone_out.output_root();
|
let output_root = zone_out.output_root();
|
||||||
|
|
||||||
let pub_inputs = DeathConstraintPublic {
|
let pub_inputs = ConstraintPublic {
|
||||||
ptx_root: PtxRoot(cl::merkle::node(input_root, output_root)),
|
ptx_root: PtxRoot(cl::merkle::node(input_root, output_root)),
|
||||||
nf: zone_in.input.nullifier(),
|
nf: zone_in.input.nullifier(),
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,7 @@ pub struct UnitBalance {
|
|||||||
|
|
||||||
impl UnitBalance {
|
impl UnitBalance {
|
||||||
pub fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
return self.pos == self.neg;
|
self.pos == self.neg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
/// 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::{DeathCommitment, NoteWitness},
|
note::{ConstraintCommitment, NoteWitness},
|
||||||
nullifier::{Nullifier, NullifierNonce, NullifierSecret},
|
nullifier::{Nullifier, NullifierNonce, NullifierSecret},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[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 death_cm: DeathCommitment,
|
pub constraint: ConstraintCommitment,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
@ -60,7 +60,7 @@ impl InputWitness {
|
|||||||
pub fn commit(&self) -> Input {
|
pub fn commit(&self) -> Input {
|
||||||
Input {
|
Input {
|
||||||
nullifier: self.nullifier(),
|
nullifier: self.nullifier(),
|
||||||
death_cm: self.note.death_commitment(),
|
constraint: self.note.constraint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ impl Input {
|
|||||||
pub fn to_bytes(&self) -> [u8; 64] {
|
pub fn to_bytes(&self) -> [u8; 64] {
|
||||||
let mut bytes = [0u8; 64];
|
let mut bytes = [0u8; 64];
|
||||||
bytes[..32].copy_from_slice(self.nullifier.as_bytes());
|
bytes[..32].copy_from_slice(self.nullifier.as_bytes());
|
||||||
bytes[32..64].copy_from_slice(&self.death_cm.0);
|
bytes[32..64].copy_from_slice(&self.constraint.0);
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ 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::{DeathCommitment, NoteCommitment, NoteWitness};
|
pub use note::{ConstraintCommitment, NoteCommitment, NoteWitness};
|
||||||
pub use nullifier::{Nullifier, NullifierCommitment, NullifierNonce, NullifierSecret};
|
pub use nullifier::{Nullifier, NullifierCommitment, NullifierNonce, NullifierSecret};
|
||||||
pub use output::{Output, OutputWitness};
|
pub use output::{Output, OutputWitness};
|
||||||
pub use partial_tx::{
|
pub use partial_tx::{
|
||||||
|
@ -7,15 +7,17 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct DeathCommitment(pub [u8; 32]);
|
pub struct ConstraintCommitment(pub [u8; 32]);
|
||||||
|
|
||||||
pub fn death_commitment(death_constraint: &[u8]) -> DeathCommitment {
|
impl ConstraintCommitment {
|
||||||
|
pub fn from_vk(constraint_vk: &[u8]) -> Self {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(b"NOMOS_CL_DEATH_COMMIT");
|
hasher.update(b"NOMOS_CL_CONSTRAINT_COMMIT");
|
||||||
hasher.update(death_constraint);
|
hasher.update(constraint_vk);
|
||||||
let death_cm: [u8; 32] = hasher.finalize().into();
|
let constraint_cm: [u8; 32] = hasher.finalize().into();
|
||||||
|
|
||||||
DeathCommitment(death_cm)
|
Self(constraint_cm)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_unit(unit: &str) -> Unit {
|
pub fn derive_unit(unit: &str) -> Unit {
|
||||||
@ -39,26 +41,26 @@ impl NoteCommitment {
|
|||||||
pub struct NoteWitness {
|
pub struct NoteWitness {
|
||||||
pub value: u64,
|
pub value: u64,
|
||||||
pub unit: Unit,
|
pub unit: Unit,
|
||||||
pub death_constraint: [u8; 32], // death constraint verification key
|
pub constraint: ConstraintCommitment,
|
||||||
pub state: [u8; 32],
|
pub state: [u8; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoteWitness {
|
impl NoteWitness {
|
||||||
pub fn new(value: u64, unit: Unit, death_constraint: [u8; 32], state: [u8; 32]) -> Self {
|
pub fn new(value: u64, unit: Unit, constraint: ConstraintCommitment, state: [u8; 32]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value,
|
value,
|
||||||
unit,
|
unit,
|
||||||
death_constraint,
|
constraint,
|
||||||
state,
|
state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn basic(value: u64, unit: Unit) -> Self {
|
pub fn basic(value: u64, unit: Unit) -> Self {
|
||||||
Self::new(value, unit, [0u8; 32], [0u8; 32])
|
Self::new(value, unit, ConstraintCommitment([0u8; 32]), [0u8; 32])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stateless(value: u64, unit: Unit, death_constraint: [u8; 32]) -> Self {
|
pub fn stateless(value: u64, unit: Unit, constraint: ConstraintCommitment) -> Self {
|
||||||
Self::new(value, unit, death_constraint, [0u8; 32])
|
Self::new(value, unit, constraint, [0u8; 32])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit(&self, nf_pk: NullifierCommitment, nonce: NullifierNonce) -> NoteCommitment {
|
pub fn commit(&self, nf_pk: NullifierCommitment, nonce: NullifierNonce) -> NoteCommitment {
|
||||||
@ -73,8 +75,8 @@ impl NoteWitness {
|
|||||||
// COMMIT TO STATE
|
// COMMIT TO STATE
|
||||||
hasher.update(self.state);
|
hasher.update(self.state);
|
||||||
|
|
||||||
// COMMIT TO DEATH CONSTRAINT
|
// COMMIT TO CONSTRAINT
|
||||||
hasher.update(self.death_constraint);
|
hasher.update(self.constraint.0);
|
||||||
|
|
||||||
// COMMIT TO NULLIFIER
|
// COMMIT TO NULLIFIER
|
||||||
hasher.update(nf_pk.as_bytes());
|
hasher.update(nf_pk.as_bytes());
|
||||||
@ -83,10 +85,6 @@ impl NoteWitness {
|
|||||||
let commit_bytes: [u8; 32] = hasher.finalize().into();
|
let commit_bytes: [u8; 32] = hasher.finalize().into();
|
||||||
NoteCommitment(commit_bytes)
|
NoteCommitment(commit_bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn death_commitment(&self) -> DeathCommitment {
|
|
||||||
death_commitment(&self.death_constraint)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -116,7 +114,7 @@ mod test {
|
|||||||
..reference_note
|
..reference_note
|
||||||
},
|
},
|
||||||
NoteWitness {
|
NoteWitness {
|
||||||
death_constraint: [1u8; 32],
|
constraint: ConstraintCommitment::from_vk(&[1u8; 32]),
|
||||||
..reference_note
|
..reference_note
|
||||||
},
|
},
|
||||||
NoteWitness {
|
NoteWitness {
|
||||||
|
87
goas/cl/ledger/src/constraint.rs
Normal file
87
goas/cl/ledger/src/constraint.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
use cl::ConstraintCommitment;
|
||||||
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
|
|
||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ConstraintProof {
|
||||||
|
pub risc0_id: [u32; 8],
|
||||||
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn risc0_constraint(risc0_id: [u32; 8]) -> ConstraintCommitment {
|
||||||
|
// Commit to a RISC0 ID for use as a note constraint
|
||||||
|
|
||||||
|
let mut bytes = [0u8; 32];
|
||||||
|
|
||||||
|
for (i, word) in risc0_id.iter().enumerate() {
|
||||||
|
let word_bytes = word.to_le_bytes();
|
||||||
|
bytes[i * 4 + 0] = word_bytes[0];
|
||||||
|
bytes[i * 4 + 1] = word_bytes[1];
|
||||||
|
bytes[i * 4 + 2] = word_bytes[2];
|
||||||
|
bytes[i * 4 + 3] = word_bytes[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstraintCommitment::from_vk(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstraintProof {
|
||||||
|
pub fn from_risc0(risc0_id: [u32; 8], risc0_receipt: risc0_zkvm::Receipt) -> Self {
|
||||||
|
Self {
|
||||||
|
risc0_id,
|
||||||
|
risc0_receipt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn constraint(&self) -> ConstraintCommitment {
|
||||||
|
risc0_constraint(self.risc0_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public(&self) -> Result<ConstraintPublic> {
|
||||||
|
Ok(self.risc0_receipt.journal.decode()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(&self, expected_public: ConstraintPublic) -> bool {
|
||||||
|
let Ok(public) = self.public() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
expected_public == public && self.risc0_receipt.verify(self.risc0_id).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nop_constraint() -> ConstraintCommitment {
|
||||||
|
risc0_constraint(nomos_cl_risc0_proofs::CONSTRAINT_NOP_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prove_nop(nf: cl::Nullifier, ptx_root: cl::PtxRoot) -> Self {
|
||||||
|
let constraint_public = ConstraintPublic { nf, ptx_root };
|
||||||
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
||||||
|
.write(&constraint_public)
|
||||||
|
.unwrap()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Obtain the default prover.
|
||||||
|
let prover = risc0_zkvm::default_prover();
|
||||||
|
|
||||||
|
let start_t = std::time::Instant::now();
|
||||||
|
|
||||||
|
// Proof information by proving the specified ELF binary.
|
||||||
|
// This struct contains the receipt along with statistics about execution of the guest
|
||||||
|
let opts = risc0_zkvm::ProverOpts::succinct();
|
||||||
|
let prove_info = prover
|
||||||
|
.prove_with_opts(env, nomos_cl_risc0_proofs::CONSTRAINT_NOP_ELF, &opts)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"STARK 'constraint-nop' prover time: {:.2?}, total_cycles: {}",
|
||||||
|
start_t.elapsed(),
|
||||||
|
prove_info.stats.total_cycles
|
||||||
|
);
|
||||||
|
|
||||||
|
// extract the receipt.
|
||||||
|
let receipt = prove_info.receipt;
|
||||||
|
|
||||||
|
Self::from_risc0(nomos_cl_risc0_proofs::CONSTRAINT_NOP_ID, receipt)
|
||||||
|
}
|
||||||
|
}
|
@ -1,90 +0,0 @@
|
|||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
|
||||||
use sha2::{Digest, Sha256};
|
|
||||||
|
|
||||||
use crate::error::Result;
|
|
||||||
|
|
||||||
pub type Risc0DeathConstraintId = [u32; 8];
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DeathProof {
|
|
||||||
pub constraint: Risc0DeathConstraintId,
|
|
||||||
pub risc0_receipt: risc0_zkvm::Receipt,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn risc0_id_to_cl_death_constraint(risc0_id: Risc0DeathConstraintId) -> [u8; 32] {
|
|
||||||
// RISC0 proof ids have the format: [u32; 8], and cl death constraint ids have the format [u8; 32].
|
|
||||||
// CL death constraints are meaningless beyond being binding, therefore we merely need a collision
|
|
||||||
// resisitant mapping of RISC0 ids to cl death constraints.
|
|
||||||
|
|
||||||
let mut hasher = Sha256::new();
|
|
||||||
hasher.update(b"NOMOS_RISC0_ID_TO_CL_DEATH_CONSTRAINT");
|
|
||||||
for word in risc0_id {
|
|
||||||
hasher.update(u32::to_ne_bytes(word));
|
|
||||||
}
|
|
||||||
let death_constraint: [u8; 32] = hasher.finalize().into();
|
|
||||||
death_constraint
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DeathProof {
|
|
||||||
pub fn from_risc0(
|
|
||||||
risc0_id: Risc0DeathConstraintId,
|
|
||||||
risc0_receipt: risc0_zkvm::Receipt,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
constraint: risc0_id,
|
|
||||||
risc0_receipt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn death_commitment(&self) -> cl::DeathCommitment {
|
|
||||||
cl::note::death_commitment(&risc0_id_to_cl_death_constraint(self.constraint))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn public(&self) -> Result<DeathConstraintPublic> {
|
|
||||||
Ok(self.risc0_receipt.journal.decode()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify(&self, expected_public: DeathConstraintPublic) -> bool {
|
|
||||||
let Ok(public) = self.public() else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
expected_public == public && self.risc0_receipt.verify(self.constraint).is_ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nop_constraint() -> [u8; 32] {
|
|
||||||
risc0_id_to_cl_death_constraint(nomos_cl_risc0_proofs::DEATH_CONSTRAINT_NOP_ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prove_nop(nf: cl::Nullifier, ptx_root: cl::PtxRoot) -> Self {
|
|
||||||
let death_public = DeathConstraintPublic { nf, ptx_root };
|
|
||||||
let env = risc0_zkvm::ExecutorEnv::builder()
|
|
||||||
.write(&death_public)
|
|
||||||
.unwrap()
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Obtain the default prover.
|
|
||||||
let prover = risc0_zkvm::default_prover();
|
|
||||||
|
|
||||||
let start_t = std::time::Instant::now();
|
|
||||||
|
|
||||||
// Proof information by proving the specified ELF binary.
|
|
||||||
// This struct contains the receipt along with statistics about execution of the guest
|
|
||||||
let opts = risc0_zkvm::ProverOpts::succinct();
|
|
||||||
let prove_info = prover
|
|
||||||
.prove_with_opts(env, nomos_cl_risc0_proofs::DEATH_CONSTRAINT_NOP_ELF, &opts)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"STARK 'death-nop' prover time: {:.2?}, total_cycles: {}",
|
|
||||||
start_t.elapsed(),
|
|
||||||
prove_info.stats.total_cycles
|
|
||||||
);
|
|
||||||
|
|
||||||
// extract the receipt.
|
|
||||||
let receipt = prove_info.receipt;
|
|
||||||
|
|
||||||
Self::from_risc0(nomos_cl_risc0_proofs::DEATH_CONSTRAINT_NOP_ID, receipt)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
pub mod bundle;
|
pub mod bundle;
|
||||||
pub mod death_constraint;
|
pub mod constraint;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod partial_tx;
|
pub mod partial_tx;
|
||||||
|
|
||||||
pub use death_constraint::DeathProof;
|
pub use constraint::ConstraintProof;
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use ledger_proof_statements::{
|
use ledger_proof_statements::{
|
||||||
death_constraint::DeathConstraintPublic,
|
constraint::ConstraintPublic,
|
||||||
ptx::{PtxPrivate, PtxPublic},
|
ptx::{PtxPrivate, PtxPublic},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
death_constraint::DeathProof, error::{Error, Result}
|
constraint::ConstraintProof,
|
||||||
|
error::{Error, Result},
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_NOTE_COMMS: usize = 2usize.pow(8);
|
const MAX_NOTE_COMMS: usize = 2usize.pow(8);
|
||||||
|
|
||||||
|
|
||||||
pub struct ProvedPartialTx {
|
pub struct ProvedPartialTx {
|
||||||
pub ptx: cl::PartialTx,
|
pub ptx: cl::PartialTx,
|
||||||
pub cm_root: [u8; 32],
|
pub cm_root: [u8; 32],
|
||||||
pub death_proofs: BTreeMap<cl::Nullifier, DeathProof>,
|
pub constraint_proofs: BTreeMap<cl::Nullifier, ConstraintProof>,
|
||||||
pub risc0_receipt: risc0_zkvm::Receipt,
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProvedPartialTx {
|
impl ProvedPartialTx {
|
||||||
pub fn prove(
|
pub fn prove(
|
||||||
ptx: &cl::PartialTxWitness,
|
ptx: &cl::PartialTxWitness,
|
||||||
death_proofs: BTreeMap<cl::Nullifier, DeathProof>,
|
constraint_proofs: BTreeMap<cl::Nullifier, ConstraintProof>,
|
||||||
note_commitments: &[cl::NoteCommitment],
|
note_commitments: &[cl::NoteCommitment],
|
||||||
) -> Result<ProvedPartialTx> {
|
) -> Result<ProvedPartialTx> {
|
||||||
let cm_leaves = note_commitment_leaves(note_commitments);
|
let cm_leaves = note_commitment_leaves(note_commitments);
|
||||||
@ -67,14 +67,12 @@ impl ProvedPartialTx {
|
|||||||
start_t.elapsed(),
|
start_t.elapsed(),
|
||||||
prove_info.stats.total_cycles
|
prove_info.stats.total_cycles
|
||||||
);
|
);
|
||||||
// extract the receipt.
|
|
||||||
let receipt = prove_info.receipt;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
ptx: ptx.commit(),
|
ptx: ptx.commit(),
|
||||||
cm_root,
|
cm_root,
|
||||||
risc0_receipt: receipt,
|
risc0_receipt: prove_info.receipt,
|
||||||
death_proofs,
|
constraint_proofs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +84,11 @@ impl ProvedPartialTx {
|
|||||||
let Ok(proved_ptx_inputs) = self.public() else {
|
let Ok(proved_ptx_inputs) = self.public() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if (PtxPublic { ptx: self.ptx.clone(), cm_root: self.cm_root }) != proved_ptx_inputs {
|
let expected_ptx_inputs = PtxPublic {
|
||||||
|
ptx: self.ptx.clone(),
|
||||||
|
cm_root: self.cm_root,
|
||||||
|
};
|
||||||
|
if expected_ptx_inputs != proved_ptx_inputs {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,15 +96,15 @@ impl ProvedPartialTx {
|
|||||||
|
|
||||||
for input in self.ptx.inputs.iter() {
|
for input in self.ptx.inputs.iter() {
|
||||||
let nf = input.nullifier;
|
let nf = input.nullifier;
|
||||||
let Some(death_proof) = self.death_proofs.get(&nf) else {
|
let Some(constraint_proof) = self.constraint_proofs.get(&nf) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if input.death_cm != death_proof.death_commitment() {
|
if input.constraint != constraint_proof.constraint() {
|
||||||
// ensure the death proof is actually for this input
|
// ensure the constraint proof is actually for this input
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if !death_proof.verify(DeathConstraintPublic { nf, ptx_root }) {
|
if !constraint_proof.verify(ConstraintPublic { nf, ptx_root }) {
|
||||||
// verify the death constraint was satisfied
|
// verify the constraint was satisfied
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use cl::{note::derive_unit, BalanceWitness};
|
use cl::{note::derive_unit, BalanceWitness};
|
||||||
use ledger::{bundle::ProvedBundle, death_constraint::DeathProof, partial_tx::ProvedPartialTx};
|
use ledger::{bundle::ProvedBundle, constraint::ConstraintProof, partial_tx::ProvedPartialTx};
|
||||||
use rand_core::CryptoRngCore;
|
use rand_core::CryptoRngCore;
|
||||||
|
|
||||||
struct User(cl::NullifierSecret);
|
struct User(cl::NullifierSecret);
|
||||||
@ -41,7 +41,7 @@ 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, DeathProof::nop_constraint()),
|
cl::NoteWitness::stateless(10, nmo, ConstraintProof::nop_constraint()),
|
||||||
alice.pk(),
|
alice.pk(),
|
||||||
&mut rng,
|
&mut rng,
|
||||||
);
|
);
|
||||||
@ -61,17 +61,18 @@ fn test_simple_transfer() {
|
|||||||
balance_blinding: BalanceWitness::random_blinding(&mut rng),
|
balance_blinding: BalanceWitness::random_blinding(&mut rng),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prove the death constraints for alices input (she uses the no-op death constraint)
|
// Prove the constraints for alices input (she uses the no-op constraint)
|
||||||
let death_proofs = BTreeMap::from_iter(ptx_witness.inputs.iter().map(|i| {
|
let constraint_proofs = BTreeMap::from_iter(ptx_witness.inputs.iter().map(|i| {
|
||||||
(
|
(
|
||||||
i.nullifier(),
|
i.nullifier(),
|
||||||
DeathProof::prove_nop(i.nullifier(), ptx_witness.commit().root()),
|
ConstraintProof::prove_nop(i.nullifier(), ptx_witness.commit().root()),
|
||||||
)
|
)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// assume we only have one note commitment on chain for now ...
|
// assume we only have one note commitment on chain for now ...
|
||||||
let note_commitments = vec![utxo.commit_note()];
|
let note_commitments = vec![utxo.commit_note()];
|
||||||
let proved_ptx = ProvedPartialTx::prove(&ptx_witness, death_proofs, ¬e_commitments).unwrap();
|
let proved_ptx =
|
||||||
|
ProvedPartialTx::prove(&ptx_witness, constraint_proofs, ¬e_commitments).unwrap();
|
||||||
|
|
||||||
assert!(proved_ptx.verify()); // It's a valid ptx.
|
assert!(proved_ptx.verify()); // It's a valid ptx.
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use cl::{Nullifier, PtxRoot};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct DeathConstraintPublic {
|
pub struct ConstraintPublic {
|
||||||
pub nf: Nullifier,
|
pub nf: Nullifier,
|
||||||
pub ptx_root: PtxRoot,
|
pub ptx_root: PtxRoot,
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
pub mod death_constraint;
|
pub mod constraint;
|
||||||
pub mod ptx;
|
pub mod ptx;
|
||||||
pub mod bundle;
|
pub mod bundle;
|
||||||
|
@ -7,5 +7,5 @@ edition = "2021"
|
|||||||
risc0-build = { version = "1.0" }
|
risc0-build = { version = "1.0" }
|
||||||
|
|
||||||
[package.metadata.risc0]
|
[package.metadata.risc0]
|
||||||
methods = ["bundle", "death_constraint_nop", "ptx"]
|
methods = ["bundle", "constraint_nop", "ptx"]
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "death_constraint_nop"
|
name = "constraint_nop"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
8
goas/cl/risc0_proofs/constraint_nop/src/main.rs
Normal file
8
goas/cl/risc0_proofs/constraint_nop/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/// Constraint No-op Proof
|
||||||
|
use ledger_proof_statements::constraint::ConstraintPublic;
|
||||||
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let public: ConstraintPublic = env::read();
|
||||||
|
env::commit(&public);
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
/// Death Constraint No-op Proof
|
|
||||||
use ledger_proof_statements::death_constraint::DeathConstraintPublic;
|
|
||||||
use risc0_zkvm::guest::env;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let public: DeathConstraintPublic = env::read();
|
|
||||||
env::commit(&public);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user