builder apis

This commit is contained in:
David Rusu 2025-02-24 18:08:24 +04:00
parent dc2fd35894
commit 7dbda3b822
4 changed files with 89 additions and 46 deletions

View File

@ -86,6 +86,67 @@ pub struct OutputWitness {
}
impl OutputWitness {
pub fn new(
value: u64,
unit: Unit,
nf_pk: NullifierCommitment,
zone_id: ZoneId,
rng: impl RngCore,
) -> Self {
Self {
state: [0; 32],
value,
unit,
nonce: Nonce::random(rng),
zone_id,
nf_pk,
}
}
pub fn reissue(input: InputWitness, rng: impl RngCore) -> Self {
Self::new(
input.value,
input.unit_witness.unit(),
input.nf_sk.commit(),
input.zone_id,
rng,
)
}
pub fn split_input(
input: InputWitness,
amount: u64,
to_pk: NullifierCommitment,
to_zone: ZoneId,
mut rng: impl RngCore,
) -> (OutputWitness, OutputWitness) {
assert!(input.value > amount);
let transfer = OutputWitness::reissue(input, &mut rng)
.set_value(amount)
.set_nf_pk(to_pk)
.set_zone(to_zone);
let change = OutputWitness::reissue(input, &mut rng).set_value(input.value - amount);
(transfer, change)
}
pub fn set_value(mut self, value: u64) -> Self {
self.value = value;
self
}
pub fn set_nf_pk(mut self, nf_pk: NullifierCommitment) -> Self {
self.nf_pk = nf_pk;
self
}
pub fn set_zone(mut self, zone_id: ZoneId) -> Self {
self.zone_id = zone_id;
self
}
pub fn note_commitment(&self) -> NoteCommitment {
NoteCommitment::commit(
self.state,

View File

@ -53,7 +53,7 @@ pub struct Tx {
pub updates: Vec<LedgerUpdate>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct TxWitness {
pub inputs: Vec<InputWitness>,
pub outputs: Vec<(OutputWitness, Vec<u8>)>,
@ -107,6 +107,17 @@ impl LedgerUpdateWitness {
}
impl TxWitness {
pub fn add_input(mut self, input: InputWitness, input_cm_proof: (MMR, MMRProof)) -> Self {
self.inputs.push(input);
self.frontier_paths.push(input_cm_proof);
self
}
pub fn add_output(mut self, output: OutputWitness, data: Vec<u8>) -> Self {
self.outputs.push((output, data));
self
}
pub fn compute_updates(&self, inputs: &[InputDerivedFields]) -> Vec<LedgerUpdateWitness> {
let mut updates = BTreeMap::new();
assert_eq!(self.inputs.len(), self.frontier_paths.len());

View File

@ -57,8 +57,9 @@ impl LedgerState {
self.nullifiers.root()
}
pub fn add_commitment(&mut self, cm: &NoteCommitment) -> MMRProof {
self.commitments.push(&cm.0)
pub fn add_commitment(&mut self, cm: &NoteCommitment) -> (MMR, MMRProof) {
let proof = self.commitments.push(&cm.0);
(self.commitments.clone(), proof)
}
pub fn add_nullifiers(&mut self, nfs: Vec<Nullifier>) -> BatchUpdateProof {

View File

@ -19,6 +19,9 @@ use ledger_proof_statements::stf::StfPublic;
use rand::Rng;
use rand_core::CryptoRngCore;
const ZONE_A: ZoneId = [0u8; 32];
const ZONE_B: ZoneId = [1u8; 32];
fn nmo() -> UnitWitness {
UnitWitness {
spending_covenant: NOP_COVENANT,
@ -53,38 +56,14 @@ fn cross_transfer_transition(
mut ledger_out: LedgerState,
) -> (ProvedLedgerTransition, ProvedLedgerTransition) {
assert!(amount <= input.value);
println!("nfs in zone_a: {}", ledger_in.nullifiers.len());
println!("nfs in zone_b: {}", ledger_out.nullifiers.len());
let mut rng = rand::thread_rng();
let change = input.value - amount;
let transfer = OutputWitness {
state: Default::default(),
value: amount,
unit: nmo().unit(),
nonce: Nonce::random(&mut rng),
zone_id: to_zone,
nf_pk: to.pk(),
};
let change = OutputWitness {
state: Default::default(),
value: change,
unit: nmo().unit(),
nonce: Nonce::random(&mut rng),
zone_id: input.zone_id,
nf_pk: input.nf_sk.commit(), // return change to sender
};
let (transfer, change) = OutputWitness::split_input(input, amount, to.pk(), to_zone, &mut rng);
// Construct the tx consuming the input and producing the two outputs.
let tx_witness = TxWitness {
inputs: vec![input],
outputs: vec![(transfer, vec![]), (change, vec![])],
data: Default::default(),
mints: vec![],
burns: vec![],
frontier_paths: vec![input_proof],
};
let tx_witness = TxWitness::default()
.add_input(input, input_proof)
.add_output(transfer, vec![])
.add_output(change, vec![]);
let proved_tx = ProvedTx::prove(
tx_witness.clone(),
@ -129,34 +108,25 @@ fn cross_transfer_transition(
fn zone_update_cross() {
let mut rng = rand::thread_rng();
let zone_a_id = [0; 32];
let zone_b_id = [1; 32];
// alice is sending 8 NMO to bob.
let alice = User::random(&mut rng);
let bob = User::random(&mut rng);
// Alice has an unspent note worth 10 NMO
let utxo = OutputWitness {
state: Default::default(),
value: 10,
unit: nmo().unit(),
nonce: Nonce::random(&mut rng),
zone_id: zone_a_id,
nf_pk: alice.pk(),
};
let utxo = OutputWitness::new(10, nmo().unit(), alice.pk(), ZONE_A, &mut rng);
let alice_input = InputWitness::from_output(utxo, alice.sk(), nmo());
let mut ledger_a = LedgerState::default();
// To make the scenario a bit more realistic, we fill the nullifier set with a bunch of nullififiers
ledger_a.add_nullifiers(
std::iter::repeat_with(|| Nullifier(rng.gen()))
.take(2_usize.pow(10))
.collect(),
);
let alice_cm_path = ledger_a.add_commitment(&utxo.note_commitment());
let alice_cm_proof = (ledger_a.commitments.clone(), alice_cm_path);
let alice_cm_proof = ledger_a.add_commitment(&utxo.note_commitment());
let ledger_b = LedgerState::default();
@ -177,7 +147,7 @@ fn zone_update_cross() {
alice_cm_proof,
bob,
8,
zone_b_id,
ZONE_B,
ledger_a,
ledger_b,
);