mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
bin/tx: bring state_transition function to tx.rs file
This commit is contained in:
160
src/bin/tx.rs
160
src/bin/tx.rs
@@ -4,7 +4,6 @@ use ff::{Field, PrimeField};
|
||||
use rand::rngs::OsRng;
|
||||
use std::path::Path;
|
||||
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use drk::crypto::{
|
||||
coin::Coin,
|
||||
load_params,
|
||||
@@ -15,7 +14,7 @@ use drk::crypto::{
|
||||
save_params, setup_mint_prover, setup_spend_prover,
|
||||
};
|
||||
use drk::serial::{Decodable, Encodable};
|
||||
use drk::state::{state_transition, ProgramState, StateUpdate};
|
||||
use drk::state::{ProgramState, StateUpdate};
|
||||
use drk::tx;
|
||||
|
||||
struct MemoryState {
|
||||
@@ -203,8 +202,6 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let state = Mutex::new(state);
|
||||
let mut state = state.lock().await;
|
||||
// Now we receive the tx data
|
||||
{
|
||||
let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
|
||||
@@ -221,47 +218,47 @@ async fn main() {
|
||||
assert_eq!(state.own_coins.len(), 1);
|
||||
////let (coin, note, secret, witness) = &mut state.own_coins[0];
|
||||
|
||||
//let merkle_path = {
|
||||
// let tree = &mut state.tree;
|
||||
// let (coin, _, _, witness) = &mut state.own_coins[0];
|
||||
// // Check this is the 6th coin we added
|
||||
// assert_eq!(witness.position(), 5);
|
||||
// assert_eq!(tree.root(), witness.root());
|
||||
let merkle_path = {
|
||||
let tree = &mut state.tree;
|
||||
let (coin, _, _, witness) = &mut state.own_coins[0];
|
||||
// Check this is the 6th coin we added
|
||||
assert_eq!(witness.position(), 5);
|
||||
assert_eq!(tree.root(), witness.root());
|
||||
|
||||
// // Add some more random coins in
|
||||
// for _i in 0..10 {
|
||||
// // Don't worry about any of the code in this block
|
||||
// // We're just filling the tree with fake coins
|
||||
// let cmu = MerkleNode::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
|
||||
// tree.append(cmu).unwrap();
|
||||
// witness.append(cmu).unwrap();
|
||||
// assert_eq!(tree.root(), witness.root());
|
||||
// Add some more random coins in
|
||||
for _i in 0..10 {
|
||||
// Don't worry about any of the code in this block
|
||||
// We're just filling the tree with fake coins
|
||||
let cmu = MerkleNode::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
|
||||
tree.append(cmu).unwrap();
|
||||
witness.append(cmu).unwrap();
|
||||
assert_eq!(tree.root(), witness.root());
|
||||
|
||||
// let root = tree.root();
|
||||
// state.merkle_roots.push(root.into());
|
||||
// }
|
||||
let root = tree.root();
|
||||
state.merkle_roots.push(root.into());
|
||||
}
|
||||
|
||||
// assert_eq!(state.merkle_roots.len(), 16);
|
||||
assert_eq!(state.merkle_roots.len(), 16);
|
||||
|
||||
// // This is the value we need to spend the coin
|
||||
// // We use the witness and the merkle root (both in sync with each other)
|
||||
// // to prove our coin exists inside the tree.
|
||||
// // The coin is not revealed publicly but is proved to exist inside
|
||||
// // a merkle tree. Only the root will be revealed, and then the
|
||||
// // verifier checks that merkle root actually existed before.
|
||||
// let merkle_path = witness.path().unwrap();
|
||||
// This is the value we need to spend the coin
|
||||
// We use the witness and the merkle root (both in sync with each other)
|
||||
// to prove our coin exists inside the tree.
|
||||
// The coin is not revealed publicly but is proved to exist inside
|
||||
// a merkle tree. Only the root will be revealed, and then the
|
||||
// verifier checks that merkle root actually existed before.
|
||||
let merkle_path = witness.path().unwrap();
|
||||
|
||||
// // Just test the path is good because we just added a bunch of fake coins
|
||||
// let node = MerkleNode::from_coin(&coin);
|
||||
// let root = tree.root();
|
||||
// drop(tree);
|
||||
// drop(witness);
|
||||
// assert_eq!(merkle_path.root(node), root);
|
||||
// let root = root.into();
|
||||
// assert!(state.is_valid_merkle(&root));
|
||||
// Just test the path is good because we just added a bunch of fake coins
|
||||
let node = MerkleNode::from_coin(&coin);
|
||||
let root = tree.root();
|
||||
drop(tree);
|
||||
drop(witness);
|
||||
assert_eq!(merkle_path.root(node), root);
|
||||
let root = root.into();
|
||||
assert!(state.is_valid_merkle(&root));
|
||||
|
||||
// merkle_path
|
||||
//};
|
||||
merkle_path
|
||||
};
|
||||
|
||||
// Step 3: wallet1 sends payment to wallet2
|
||||
|
||||
@@ -279,12 +276,11 @@ async fn main() {
|
||||
// We need the decrypted note and our private key
|
||||
let builder = tx::TransactionBuilder {
|
||||
clear_inputs: vec![],
|
||||
inputs: vec![],
|
||||
//inputs: vec![tx::TransactionBuilderInputInfo {
|
||||
// merkle_path,
|
||||
// secret: secret.clone(),
|
||||
// note: state.own_coins[0].1.clone(),
|
||||
//}],
|
||||
inputs: vec![tx::TransactionBuilderInputInfo {
|
||||
merkle_path,
|
||||
secret: secret.clone(),
|
||||
note: state.own_coins[0].1.clone(),
|
||||
}],
|
||||
// We can add more outputs to this list.
|
||||
// The only constraint is that sum(value in) == sum(value out)
|
||||
outputs: vec![tx::TransactionBuilderOutputInfo {
|
||||
@@ -302,8 +298,76 @@ async fn main() {
|
||||
// Verify it's valid
|
||||
{
|
||||
let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
|
||||
//let state = state.lock().await;
|
||||
//let update = state_transition(&state, tx).expect("step 3 state transition failed");
|
||||
//state.apply(update);
|
||||
let update = state_transition(&state, tx).expect("step 3 state transition failed");
|
||||
state.apply(update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
use log::*;
|
||||
use drk::state::{VerifyResult, VerifyFailed};
|
||||
|
||||
pub fn state_transition<S: ProgramState>(
|
||||
state: &S,
|
||||
tx: tx::Transaction,
|
||||
) -> VerifyResult<StateUpdate> {
|
||||
// Check deposits are legit
|
||||
|
||||
debug!(target: "STATE TRANSITION", "iterate clear_inputs");
|
||||
|
||||
for (i, input) in tx.clear_inputs.iter().enumerate() {
|
||||
// Check the public key in the clear inputs
|
||||
// It should be a valid public key for the cashier
|
||||
|
||||
|
||||
if !state.is_valid_cashier_public_key(&input.signature_public) {
|
||||
log::error!(target: "STATE TRANSITION", "Not valid cashier public key");
|
||||
return Err(VerifyFailed::InvalidCashierKey(i));
|
||||
}
|
||||
}
|
||||
|
||||
debug!(target: "STATE TRANSITION", "iterate inputs");
|
||||
|
||||
for (i, input) in tx.inputs.iter().enumerate() {
|
||||
// Check merkle roots
|
||||
let merkle = &input.revealed.merkle_root;
|
||||
|
||||
// Merkle is used to know whether this is a coin that existed
|
||||
// in a previous state.
|
||||
if !state.is_valid_merkle(merkle) {
|
||||
return Err(VerifyFailed::InvalidMerkle(i));
|
||||
}
|
||||
|
||||
// The nullifiers should not already exist
|
||||
// It is double spend protection.
|
||||
let nullifier = &input.revealed.nullifier;
|
||||
|
||||
if state.nullifier_exists(nullifier) {
|
||||
return Err(VerifyFailed::DuplicateNullifier(i));
|
||||
}
|
||||
}
|
||||
|
||||
debug!(target: "STATE TRANSITION", "Check the tx Verifies correctly");
|
||||
// Check the tx verifies correctly
|
||||
tx.verify(state.mint_pvk(), state.spend_pvk())?;
|
||||
|
||||
let mut nullifiers = vec![];
|
||||
for input in tx.inputs {
|
||||
nullifiers.push(input.revealed.nullifier);
|
||||
}
|
||||
|
||||
// Newly created coins for this tx
|
||||
let mut coins = vec![];
|
||||
let mut enc_notes = vec![];
|
||||
for output in tx.outputs {
|
||||
// Gather all the coins
|
||||
coins.push(Coin::new(output.revealed.coin));
|
||||
enc_notes.push(output.enc_note);
|
||||
}
|
||||
|
||||
Ok(StateUpdate {
|
||||
nullifiers,
|
||||
coins,
|
||||
enc_notes,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user