dao_process.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use halo2_gadgets::primitives::{
  2. poseidon,
  3. poseidon::{ConstantLength, P128Pow5T3},
  4. };
  5. use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
  6. use pasta_curves::{
  7. arithmetic::CurveAffine,
  8. group::{
  9. ff::{Field, PrimeField},
  10. Curve, Group,
  11. },
  12. pallas,
  13. };
  14. use rand::rngs::OsRng;
  15. use simplelog::{ColorChoice::Auto, Config, LevelFilter, TermLogger, TerminalMode::Mixed};
  16. use darkfi::{
  17. crypto::{keypair::Keypair, merkle_node::MerkleNode, schnorr::SchnorrSecret},
  18. Result,
  19. };
  20. fn main() -> Result<()> {
  21. let loglevel = match option_env!("RUST_LOG") {
  22. Some("debug") => LevelFilter::Debug,
  23. Some("trace") => LevelFilter::Trace,
  24. Some(_) | None => LevelFilter::Info,
  25. };
  26. TermLogger::init(loglevel, Config::default(), Mixed, Auto)?;
  27. // =============
  28. // Initial state
  29. // =============
  30. // We have a Merkle tree of some DAO treasuries
  31. let mut tree = BridgeTree::<MerkleNode, 32>::new(100);
  32. for _ in 0..3 {
  33. let some_dao = pallas::Base::random(&mut OsRng);
  34. tree.append(&MerkleNode(some_dao));
  35. }
  36. // And we have our DAO
  37. let dao_authority = Keypair::random(&mut OsRng);
  38. let spend_contract = pallas::Base::random(&mut OsRng);
  39. let current_balance = pallas::Base::from(666);
  40. let current_serial = pallas::Base::random(&mut OsRng);
  41. let current_dao_blind = pallas::Base::random(&mut OsRng);
  42. let message = [spend_contract, current_balance, current_serial, current_dao_blind];
  43. let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init();
  44. let our_dao = hasher.hash(message);
  45. tree.append(&MerkleNode(our_dao));
  46. tree.witness();
  47. // ========
  48. // Proposal
  49. // ========
  50. // We make a proposal to send funds to some public key with the following
  51. // parameters:
  52. let amount_to_send = pallas::Base::from(42);
  53. let destination = pallas::Point::random(&mut OsRng);
  54. let destination_coords = destination.to_affine().coordinates().unwrap();
  55. let proposal_blind = pallas::Base::random(&mut OsRng);
  56. // This proposal is then hashed, and the hash is signed by the DAO authority:
  57. let message =
  58. [amount_to_send, *destination_coords.x(), *destination_coords.y(), proposal_blind];
  59. let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init();
  60. let proposal = hasher.hash(message);
  61. let _signature = dao_authority.secret.sign(&proposal.to_repr());
  62. // ======
  63. // Voting
  64. // ======
  65. // Once the proposal is live, voting can become active.
  66. // Users can now vote on the proposal and their votes are weighted by the
  67. // balance they commit to their vote.
  68. // After the voting process is done, the votes and the blinds are revealed.
  69. let vote0 = pallas::Base::from(44);
  70. let _vote0_blind = pallas::Scalar::random(&mut OsRng);
  71. let vote1 = pallas::Base::from(14);
  72. let _vote1_blind = pallas::Scalar::random(&mut OsRng);
  73. let vote2 = -pallas::Base::from(39); // This is a NO vote
  74. let _vote2_blind = pallas::Scalar::random(&mut OsRng);
  75. // Now let's consider the voting is done, and the votes are revealed.
  76. let votes = vote0 + vote1 + vote2;
  77. if votes < pallas::Base::from(1) {
  78. // In case the sum of the votes is negative, it means that the proposal
  79. // has not passed, therefore we don't do anything.
  80. return Ok(())
  81. }
  82. // ==================
  83. // Proposal execution
  84. // ==================
  85. // The remaining funds in the DAO become the next treasury, so we append
  86. // it to the DAO Merkle tree:
  87. let new_balance = current_balance - amount_to_send;
  88. let new_serial = pallas::Base::random(&mut OsRng);
  89. let new_dao_blind = pallas::Base::random(&mut OsRng);
  90. let message = [spend_contract, new_balance, new_serial, new_dao_blind];
  91. let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init();
  92. let our_new_dao = hasher.hash(message);
  93. tree.append(&MerkleNode(our_new_dao));
  94. tree.witness();
  95. Ok(())
  96. }