Files
darkfi/example/dao_process.rs
2022-02-26 12:28:37 +01:00

121 lines
4.0 KiB
Rust

use halo2_gadgets::primitives::{
poseidon,
poseidon::{ConstantLength, P128Pow5T3},
};
use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
use pasta_curves::{
arithmetic::CurveAffine,
group::{
ff::{Field, PrimeField},
Curve, Group,
},
pallas,
};
use rand::rngs::OsRng;
use simplelog::{ColorChoice::Auto, Config, LevelFilter, TermLogger, TerminalMode::Mixed};
use darkfi::{
crypto::{keypair::Keypair, merkle_node::MerkleNode, schnorr::SchnorrSecret},
Result,
};
fn main() -> Result<()> {
let loglevel = match option_env!("RUST_LOG") {
Some("debug") => LevelFilter::Debug,
Some("trace") => LevelFilter::Trace,
Some(_) | None => LevelFilter::Info,
};
TermLogger::init(loglevel, Config::default(), Mixed, Auto)?;
// =============
// Initial state
// =============
// We have a Merkle tree of some DAO treasuries
let mut tree = BridgeTree::<MerkleNode, 32>::new(100);
for _ in 0..3 {
let some_dao = pallas::Base::random(&mut OsRng);
tree.append(&MerkleNode(some_dao));
}
// And we have our DAO
let dao_authority = Keypair::random(&mut OsRng);
let spend_contract = pallas::Base::random(&mut OsRng);
let current_balance = pallas::Base::from(666);
let current_serial = pallas::Base::random(&mut OsRng);
let current_dao_blind = pallas::Base::random(&mut OsRng);
let message = [spend_contract, current_balance, current_serial, current_dao_blind];
let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init();
let our_dao = hasher.hash(message);
tree.append(&MerkleNode(our_dao));
tree.witness();
// ========
// Proposal
// ========
// We make a proposal to send funds to some public key with the following
// parameters:
let amount_to_send = pallas::Base::from(42);
let destination = pallas::Point::random(&mut OsRng);
let destination_coords = destination.to_affine().coordinates().unwrap();
let proposal_blind = pallas::Base::random(&mut OsRng);
// This proposal is then hashed, and the hash is signed by the DAO authority:
let message =
[amount_to_send, *destination_coords.x(), *destination_coords.y(), proposal_blind];
let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init();
let proposal = hasher.hash(message);
let _signature = dao_authority.secret.sign(&proposal.to_repr());
// ======
// Voting
// ======
// Once the proposal is live, voting can become active.
// Users can now vote on the proposal and their votes are weighted by the
// balance they commit to their vote.
// After the voting process is done, the votes and the blinds are revealed.
let vote0 = pallas::Base::from(44);
let _vote0_blind = pallas::Scalar::random(&mut OsRng);
let vote1 = pallas::Base::from(14);
let _vote1_blind = pallas::Scalar::random(&mut OsRng);
let vote2 = -pallas::Base::from(39); // This is a NO vote
let _vote2_blind = pallas::Scalar::random(&mut OsRng);
// Now let's consider the voting is done, and the votes are revealed.
let votes = vote0 + vote1 + vote2;
if votes < pallas::Base::from(1) {
// In case the sum of the votes is negative, it means that the proposal
// has not passed, therefore we don't do anything.
return Ok(())
}
// ==================
// Proposal execution
// ==================
// The remaining funds in the DAO become the next treasury, so we append
// it to the DAO Merkle tree:
let new_balance = current_balance - amount_to_send;
let new_serial = pallas::Base::random(&mut OsRng);
let new_dao_blind = pallas::Base::random(&mut OsRng);
let message = [spend_contract, new_balance, new_serial, new_dao_blind];
let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init();
let our_new_dao = hasher.hash(message);
tree.append(&MerkleNode(our_new_dao));
tree.witness();
Ok(())
}