2024-08-11 23:08:40 +04:00
|
|
|
use std::collections::BTreeMap;
|
|
|
|
|
|
2024-08-10 21:09:36 +04:00
|
|
|
use cl::{PartialTxInputWitness, PartialTxOutputWitness};
|
2024-08-11 23:08:40 +04:00
|
|
|
use common::{BoundTx, IncludedTxWitness, StateRoots, StateWitness, Tx, ZoneMetadata};
|
2024-08-10 21:09:36 +04:00
|
|
|
use goas_proof_statements::{
|
|
|
|
|
user_note::{UserAtomicTransfer, UserIntent},
|
|
|
|
|
zone_funds::SpendFundsPrivate,
|
|
|
|
|
zone_state::ZoneStatePrivate,
|
|
|
|
|
};
|
2024-08-11 23:08:40 +04:00
|
|
|
use rand_core::CryptoRngCore;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct ZoneNotes {
|
|
|
|
|
pub state: StateWitness,
|
|
|
|
|
pub state_note: cl::OutputWitness,
|
|
|
|
|
pub fund_note: cl::OutputWitness,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ZoneNotes {
|
|
|
|
|
pub fn new_with_balances(
|
|
|
|
|
zone_name: &str,
|
|
|
|
|
balances: BTreeMap<u32, u64>,
|
|
|
|
|
mut rng: impl CryptoRngCore,
|
|
|
|
|
) -> Self {
|
|
|
|
|
let state = StateWitness {
|
|
|
|
|
balances,
|
|
|
|
|
included_txs: vec![],
|
|
|
|
|
zone_metadata: zone_metadata(zone_name),
|
|
|
|
|
nonce: [0; 32],
|
|
|
|
|
};
|
|
|
|
|
let state_note = zone_state_utxo(&state, &mut rng);
|
|
|
|
|
let fund_note = zone_fund_utxo(state.total_balance(), state.zone_metadata, &mut rng);
|
|
|
|
|
Self {
|
|
|
|
|
state,
|
|
|
|
|
state_note,
|
|
|
|
|
fund_note,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn state_input_witness(&self) -> cl::InputWitness {
|
|
|
|
|
cl::InputWitness::public(self.state_note)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn fund_input_witness(&self) -> cl::InputWitness {
|
|
|
|
|
cl::InputWitness::public(self.fund_note)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn run(mut self, txs: impl IntoIterator<Item = Tx>) -> Self {
|
|
|
|
|
for tx in txs {
|
|
|
|
|
self.state = self.state.apply(tx);
|
|
|
|
|
}
|
|
|
|
|
self.state = self.state.evolve_nonce();
|
|
|
|
|
|
|
|
|
|
let state_in = self.state_input_witness();
|
|
|
|
|
self.state_note = cl::OutputWitness::public(
|
|
|
|
|
cl::NoteWitness {
|
|
|
|
|
state: self.state.commit().0,
|
|
|
|
|
..state_in.note
|
|
|
|
|
},
|
|
|
|
|
state_in.evolved_nonce(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let fund_in = self.fund_input_witness();
|
|
|
|
|
self.fund_note = cl::OutputWitness::public(
|
|
|
|
|
cl::NoteWitness {
|
|
|
|
|
value: self.state.total_balance(),
|
|
|
|
|
..fund_in.note
|
|
|
|
|
},
|
|
|
|
|
cl::NullifierNonce::from_bytes(self.state.nonce),
|
|
|
|
|
);
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn zone_fund_utxo(
|
|
|
|
|
value: u64,
|
|
|
|
|
zone_meta: ZoneMetadata,
|
|
|
|
|
mut rng: impl CryptoRngCore,
|
|
|
|
|
) -> cl::OutputWitness {
|
|
|
|
|
cl::OutputWitness::public(
|
|
|
|
|
cl::NoteWitness {
|
|
|
|
|
value,
|
|
|
|
|
unit: *common::ZONE_CL_FUNDS_UNIT,
|
|
|
|
|
death_constraint: zone_meta.funds_vk,
|
|
|
|
|
state: zone_meta.id(),
|
|
|
|
|
},
|
|
|
|
|
cl::NullifierNonce::random(&mut rng),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn zone_state_utxo(zone: &StateWitness, mut rng: impl CryptoRngCore) -> cl::OutputWitness {
|
|
|
|
|
cl::OutputWitness::public(
|
|
|
|
|
cl::NoteWitness {
|
|
|
|
|
value: 1,
|
|
|
|
|
unit: zone.zone_metadata.unit,
|
|
|
|
|
death_constraint: zone.zone_metadata.zone_vk,
|
|
|
|
|
state: zone.commit().0,
|
|
|
|
|
},
|
|
|
|
|
cl::NullifierNonce::random(&mut rng),
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-08-10 21:09:36 +04:00
|
|
|
|
|
|
|
|
pub fn user_atomic_transfer_death_constraint() -> [u8; 32] {
|
|
|
|
|
ledger::death_constraint::risc0_id_to_cl_death_constraint(
|
|
|
|
|
goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID,
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-08-07 23:37:21 +04:00
|
|
|
|
2024-08-09 20:00:31 +04:00
|
|
|
pub fn zone_state_death_constraint() -> [u8; 32] {
|
|
|
|
|
ledger::death_constraint::risc0_id_to_cl_death_constraint(goas_risc0_proofs::ZONE_STATE_ID)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn zone_fund_death_constraint() -> [u8; 32] {
|
|
|
|
|
ledger::death_constraint::risc0_id_to_cl_death_constraint(
|
|
|
|
|
goas_risc0_proofs::SPEND_ZONE_FUNDS_ID,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn zone_metadata(zone_mnemonic: &str) -> ZoneMetadata {
|
|
|
|
|
ZoneMetadata {
|
|
|
|
|
zone_vk: zone_state_death_constraint(),
|
|
|
|
|
funds_vk: zone_fund_death_constraint(),
|
|
|
|
|
unit: cl::note::unit_point(zone_mnemonic),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-07 23:37:21 +04:00
|
|
|
pub fn prove_zone_stf(
|
|
|
|
|
state: StateWitness,
|
2024-08-09 17:33:01 +02:00
|
|
|
inputs: Vec<BoundTx>,
|
2024-08-07 23:37:21 +04:00
|
|
|
zone_in: cl::PartialTxInputWitness,
|
|
|
|
|
zone_out: cl::PartialTxOutputWitness,
|
2024-08-08 17:50:28 +02:00
|
|
|
funds_out: cl::PartialTxOutputWitness,
|
2024-08-07 23:37:21 +04:00
|
|
|
) -> ledger::DeathProof {
|
|
|
|
|
let private_inputs = ZoneStatePrivate {
|
|
|
|
|
state,
|
|
|
|
|
inputs,
|
|
|
|
|
zone_in,
|
|
|
|
|
zone_out,
|
2024-08-08 17:50:28 +02:00
|
|
|
funds_out,
|
2024-08-07 23:37:21 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
|
|
|
|
.write(&private_inputs)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.build()
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
let prover = risc0_zkvm::default_prover();
|
|
|
|
|
|
|
|
|
|
use std::time::Instant;
|
|
|
|
|
let start_t = Instant::now();
|
|
|
|
|
let opts = risc0_zkvm::ProverOpts::succinct();
|
|
|
|
|
let prove_info = prover
|
|
|
|
|
.prove_with_opts(env, goas_risc0_proofs::ZONE_STATE_ELF, &opts)
|
|
|
|
|
.unwrap();
|
|
|
|
|
println!("STARK 'zone_stf' prover time: {:.2?}", start_t.elapsed());
|
|
|
|
|
let receipt = prove_info.receipt;
|
|
|
|
|
ledger::DeathProof::from_risc0(goas_risc0_proofs::ZONE_STATE_ID, receipt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn prove_zone_fund_withdraw(
|
|
|
|
|
in_zone_funds: cl::PartialTxInputWitness,
|
|
|
|
|
zone_note: cl::PartialTxOutputWitness,
|
|
|
|
|
out_zone_state: &StateWitness,
|
|
|
|
|
) -> ledger::DeathProof {
|
|
|
|
|
let private_inputs = SpendFundsPrivate {
|
|
|
|
|
in_zone_funds,
|
|
|
|
|
zone_note,
|
2024-08-08 17:50:28 +02:00
|
|
|
state_witness: out_zone_state.clone(),
|
2024-08-07 23:37:21 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
|
|
|
|
.write(&private_inputs)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.build()
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
let prover = risc0_zkvm::default_prover();
|
|
|
|
|
|
|
|
|
|
use std::time::Instant;
|
|
|
|
|
let start_t = Instant::now();
|
|
|
|
|
let opts = risc0_zkvm::ProverOpts::succinct();
|
|
|
|
|
let prove_info = prover
|
|
|
|
|
.prove_with_opts(env, goas_risc0_proofs::SPEND_ZONE_FUNDS_ELF, &opts)
|
|
|
|
|
.unwrap();
|
|
|
|
|
println!("STARK 'zone_fund' prover time: {:.2?}", start_t.elapsed());
|
|
|
|
|
let receipt = prove_info.receipt;
|
|
|
|
|
ledger::DeathProof::from_risc0(goas_risc0_proofs::SPEND_ZONE_FUNDS_ID, receipt)
|
|
|
|
|
}
|
2024-08-10 21:09:36 +04:00
|
|
|
|
|
|
|
|
pub fn prove_user_atomic_transfer(
|
|
|
|
|
user_note: PartialTxInputWitness,
|
|
|
|
|
user_intent: UserIntent,
|
|
|
|
|
zone_a: PartialTxOutputWitness,
|
|
|
|
|
zone_b: PartialTxOutputWitness,
|
|
|
|
|
zone_a_roots: StateRoots,
|
|
|
|
|
zone_b_roots: StateRoots,
|
|
|
|
|
withdraw_tx: IncludedTxWitness,
|
|
|
|
|
deposit_tx: IncludedTxWitness,
|
|
|
|
|
) -> ledger::DeathProof {
|
|
|
|
|
let private_inputs = UserAtomicTransfer {
|
|
|
|
|
user_note,
|
|
|
|
|
user_intent,
|
|
|
|
|
zone_a,
|
|
|
|
|
zone_b,
|
|
|
|
|
zone_a_roots,
|
|
|
|
|
zone_b_roots,
|
|
|
|
|
withdraw_tx,
|
|
|
|
|
deposit_tx,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
|
|
|
|
.write(&private_inputs)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.build()
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
let prover = risc0_zkvm::default_prover();
|
|
|
|
|
|
|
|
|
|
use std::time::Instant;
|
|
|
|
|
let start_t = Instant::now();
|
|
|
|
|
let opts = risc0_zkvm::ProverOpts::succinct();
|
|
|
|
|
let prove_info = prover
|
|
|
|
|
.prove_with_opts(env, goas_risc0_proofs::USER_ATOMIC_TRANSFER_ELF, &opts)
|
|
|
|
|
.unwrap();
|
|
|
|
|
println!(
|
|
|
|
|
"STARK 'user atomic transfer' prover time: {:.2?}",
|
|
|
|
|
start_t.elapsed()
|
|
|
|
|
);
|
|
|
|
|
let receipt = prove_info.receipt;
|
|
|
|
|
ledger::DeathProof::from_risc0(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID, receipt)
|
|
|
|
|
}
|