goas: more robust nonce evolution strategy
This commit is contained in:
parent
75ff879770
commit
213be6ccd7
|
@ -40,7 +40,6 @@ pub struct StateWitness {
|
|||
pub balances: BTreeMap<AccountId, u64>,
|
||||
pub included_txs: Vec<Tx>,
|
||||
pub zone_metadata: ZoneMetadata,
|
||||
pub nonce: [u8; 32],
|
||||
}
|
||||
|
||||
impl StateWitness {
|
||||
|
@ -50,7 +49,6 @@ impl StateWitness {
|
|||
|
||||
pub fn state_roots(&self) -> StateRoots {
|
||||
StateRoots {
|
||||
nonce: self.nonce,
|
||||
tx_root: self.included_txs_root(),
|
||||
zone_id: self.zone_metadata.id(),
|
||||
balance_root: self.balances_root(),
|
||||
|
@ -115,19 +113,6 @@ impl StateWitness {
|
|||
self.balances.values().sum()
|
||||
}
|
||||
|
||||
pub fn evolve_nonce(self) -> Self {
|
||||
let updated_nonce = {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(self.nonce);
|
||||
hasher.update(b"NOMOS_ZONE_NONCE_EVOLVE");
|
||||
hasher.finalize().into()
|
||||
};
|
||||
Self {
|
||||
nonce: updated_nonce,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
fn included_tx_merkle_leaves(&self) -> [[u8; 32]; MAX_TXS] {
|
||||
let tx_bytes = self
|
||||
.included_txs
|
||||
|
@ -221,25 +206,19 @@ impl IncludedTxWitness {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct StateRoots {
|
||||
pub nonce: [u8; 32],
|
||||
pub tx_root: [u8; 32],
|
||||
pub zone_id: [u8; 32],
|
||||
pub balance_root: [u8; 32],
|
||||
}
|
||||
|
||||
impl StateRoots {
|
||||
/// Merkle tree over:
|
||||
/// root
|
||||
/// / \
|
||||
/// io state
|
||||
/// / \ / \
|
||||
/// nonce txs zoneid balances
|
||||
/// Merkle tree over: [txs, zoneid, balances]
|
||||
pub fn commit(&self) -> StateCommitment {
|
||||
StateCommitment(cl::merkle::root([
|
||||
self.nonce,
|
||||
self.tx_root,
|
||||
self.zone_id,
|
||||
self.balance_root,
|
||||
]))
|
||||
let leaves = cl::merkle::padded_leaves::<4>(&[
|
||||
self.tx_root.to_vec(),
|
||||
self.zone_id.to_vec(),
|
||||
self.balance_root.to_vec(),
|
||||
]);
|
||||
StateCommitment(cl::merkle::root(leaves))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ impl ZoneNotes {
|
|||
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);
|
||||
|
@ -46,7 +45,6 @@ impl ZoneNotes {
|
|||
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(
|
||||
|
@ -54,7 +52,7 @@ impl ZoneNotes {
|
|||
state: self.state.commit().0,
|
||||
..state_in.note
|
||||
},
|
||||
state_in.evolved_nonce(),
|
||||
state_in.evolved_nonce(b"STATE_NONCE"),
|
||||
);
|
||||
|
||||
let fund_in = self.fund_input_witness();
|
||||
|
@ -63,7 +61,7 @@ impl ZoneNotes {
|
|||
value: self.state.total_balance(),
|
||||
..fund_in.note
|
||||
},
|
||||
cl::NullifierNonce::from_bytes(self.state.nonce),
|
||||
state_in.evolved_nonce(b"FUND_NONCE"),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
|
|
@ -81,7 +81,6 @@ fn test_deposit() {
|
|||
balances: BTreeMap::from_iter([(alice, 78)]),
|
||||
included_txs: vec![Tx::Deposit(deposit)],
|
||||
zone_metadata: zone_start.state.zone_metadata,
|
||||
nonce: zone_start.state.evolve_nonce().nonce,
|
||||
}
|
||||
.commit()
|
||||
.0
|
||||
|
|
|
@ -101,7 +101,6 @@ fn test_withdrawal() {
|
|||
balances: BTreeMap::from_iter([(alice, 22)]),
|
||||
included_txs: vec![Tx::Withdraw(withdraw)],
|
||||
zone_metadata: zone_start.state.zone_metadata,
|
||||
nonce: zone_start.state.evolve_nonce().nonce,
|
||||
}
|
||||
.commit()
|
||||
.0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use cl::{
|
||||
note::NoteWitness, nullifier::NullifierNonce, output::OutputWitness,
|
||||
note::NoteWitness, output::OutputWitness,
|
||||
PtxRoot,
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ fn validate_zone_transition(
|
|||
);
|
||||
|
||||
// the nonce is correctly evolved
|
||||
assert_eq!(in_note.input.evolved_nonce(), out_note.output.nonce);
|
||||
assert_eq!(in_note.input.evolved_nonce(b"STATE_NONCE"), out_note.output.nonce);
|
||||
|
||||
// funds are still under control of the zone
|
||||
let expected_note_witness = NoteWitness::new(
|
||||
|
@ -52,7 +52,7 @@ fn validate_zone_transition(
|
|||
out_funds.output,
|
||||
OutputWitness::public(
|
||||
expected_note_witness,
|
||||
NullifierNonce::from_bytes(out_state.nonce)
|
||||
in_note.input.evolved_nonce(b"FUND_NONCE")
|
||||
)
|
||||
);
|
||||
// funds belong to the same partial tx
|
||||
|
@ -83,7 +83,6 @@ fn main() {
|
|||
state = state.apply(tx)
|
||||
}
|
||||
|
||||
let state = state.evolve_nonce();
|
||||
validate_zone_transition(zone_in, zone_out, funds_out, in_state_cm, state);
|
||||
|
||||
env::commit(&pub_inputs);
|
||||
|
|
|
@ -52,16 +52,20 @@ impl InputWitness {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn evolved_nonce(&self) -> NullifierNonce {
|
||||
self.nonce.evolve(&self.nf_sk)
|
||||
pub fn evolved_nonce(&self, domain: &[u8]) -> NullifierNonce {
|
||||
self.nonce.evolve(domain, &self.nf_sk, &self.note)
|
||||
}
|
||||
|
||||
pub fn evolve_output(&self, balance_blinding: BalanceWitness) -> crate::OutputWitness {
|
||||
pub fn evolve_output(
|
||||
&self,
|
||||
domain: &[u8],
|
||||
balance_blinding: BalanceWitness,
|
||||
) -> crate::OutputWitness {
|
||||
crate::OutputWitness {
|
||||
note: self.note,
|
||||
balance_blinding,
|
||||
nf_pk: self.nf_sk.commit(),
|
||||
nonce: self.evolved_nonce(),
|
||||
nonce: self.evolved_nonce(domain),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use rand_core::RngCore;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::NoteCommitment;
|
||||
use crate::{NoteCommitment, NoteWitness};
|
||||
|
||||
// TODO: create a nullifier witness and use it throughout.
|
||||
// struct NullifierWitness {
|
||||
|
@ -92,11 +92,12 @@ impl NullifierNonce {
|
|||
Self(bytes)
|
||||
}
|
||||
|
||||
pub fn evolve(&self, nf_sk: &NullifierSecret) -> Self {
|
||||
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(&self.0);
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue