Files
darkfi/bin/dao/daod/src/contract/money_contract/state.rs

117 lines
3.4 KiB
Rust

use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
use darkfi::crypto::{
coin::Coin,
constants::MERKLE_DEPTH,
keypair::{PublicKey, SecretKey},
merkle_node::MerkleNode,
nullifier::Nullifier,
};
use super::transfer;
use crate::note::EncryptedNote2;
type MerkleTree = BridgeTree<MerkleNode, MERKLE_DEPTH>;
pub struct OwnCoin {
pub coin: Coin,
pub note: transfer::wallet::Note,
pub leaf_position: incrementalmerkletree::Position,
}
pub struct WalletCache {
// Normally this would be a HashMap, but SecretKey is not Hash-able
// TODO: This can be HashableBase
cache: Vec<(SecretKey, Vec<OwnCoin>)>,
}
impl WalletCache {
pub fn new() -> Self {
Self { cache: Vec::new() }
}
/// Must be called at the start to begin tracking received coins for this secret.
pub fn track(&mut self, secret: SecretKey) {
self.cache.push((secret, Vec::new()));
}
/// Get all coins received by this secret key
/// track() must be called on this secret before calling this or the function will panic.
pub fn get_received(&mut self, secret: &SecretKey) -> Vec<OwnCoin> {
for (other_secret, own_coins) in self.cache.iter_mut() {
if *secret == *other_secret {
// clear own_coins vec, and return current contents
return std::mem::replace(own_coins, Vec::new())
}
}
panic!("you forget to track() this secret!");
}
pub fn try_decrypt_note(
&mut self,
coin: Coin,
ciphertext: EncryptedNote2,
tree: &mut MerkleTree,
) {
// Loop through all our secret keys...
for (secret, own_coins) in self.cache.iter_mut() {
// .. attempt to decrypt the note ...
if let Ok(note) = ciphertext.decrypt(secret) {
let leaf_position = tree.witness().expect("coin should be in tree");
own_coins.push(OwnCoin { coin, note, leaf_position });
}
}
}
}
/// The state machine, held in memory.
pub struct State {
/// The entire Merkle tree state
pub tree: MerkleTree,
/// List of all previous and the current Merkle roots.
/// This is the hashed value of all the children.
pub merkle_roots: Vec<MerkleNode>,
/// Nullifiers prevent double spending
pub nullifiers: Vec<Nullifier>,
/// Public key of the cashier
pub cashier_signature_public: PublicKey,
/// Public key of the faucet
pub faucet_signature_public: PublicKey,
pub wallet_cache: WalletCache,
}
impl State {
pub fn new(
cashier_signature_public: PublicKey,
faucet_signature_public: PublicKey,
) -> Box<Self> {
Box::new(Self {
tree: MerkleTree::new(100),
merkle_roots: vec![],
nullifiers: vec![],
cashier_signature_public,
faucet_signature_public,
wallet_cache: WalletCache::new(),
})
}
pub fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
public == &self.cashier_signature_public
}
pub fn is_valid_faucet_public_key(&self, public: &PublicKey) -> bool {
public == &self.faucet_signature_public
}
pub fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
self.merkle_roots.iter().any(|m| m == merkle_root)
}
pub fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
self.nullifiers.iter().any(|n| n == nullifier)
}
}