util.rs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. use std::{any::Any, collections::HashMap, hash::Hasher};
  2. use lazy_static::lazy_static;
  3. use log::debug;
  4. use pasta_curves::{
  5. group::ff::{Field, PrimeField},
  6. pallas,
  7. };
  8. use rand::rngs::OsRng;
  9. use darkfi::{
  10. crypto::{
  11. keypair::{PublicKey, SecretKey},
  12. proof::{ProvingKey, VerifyingKey},
  13. schnorr::{SchnorrPublic, SchnorrSecret, Signature},
  14. types::DrkCircuitField,
  15. Proof,
  16. },
  17. zk::{vm::ZkCircuit, vm_stack::empty_witnesses},
  18. zkas::decoder::ZkBinary,
  19. Error,
  20. };
  21. use darkfi_serial::Encodable;
  22. use crate::error::{DaoError, DaoResult};
  23. /// Parse pallas::Base from a base58-encoded string
  24. pub fn parse_b58(s: &str) -> std::result::Result<pallas::Base, darkfi::Error> {
  25. let bytes = bs58::decode(s).into_vec()?;
  26. if bytes.len() != 32 {
  27. return Err(Error::ParseFailed("Failed parsing DrkTokenId from base58 string"))
  28. }
  29. let ret = pallas::Base::from_repr(bytes.try_into().unwrap());
  30. if ret.is_some().unwrap_u8() == 1 {
  31. return Ok(ret.unwrap())
  32. }
  33. Err(Error::ParseFailed("Failed parsing DrkTokenId from base58 string"))
  34. }
  35. // The token of the DAO treasury.
  36. lazy_static! {
  37. pub static ref DRK_ID: pallas::Base = pallas::Base::random(&mut OsRng);
  38. }
  39. // Governance tokens that are airdropped to users to operate the DAO.
  40. lazy_static! {
  41. pub static ref GOV_ID: pallas::Base = pallas::Base::random(&mut OsRng);
  42. }
  43. #[derive(Eq, PartialEq, Debug)]
  44. pub struct HashableBase(pub pallas::Base);
  45. impl std::hash::Hash for HashableBase {
  46. fn hash<H: Hasher>(&self, state: &mut H) {
  47. let bytes = self.0.to_repr();
  48. bytes.hash(state);
  49. }
  50. }
  51. #[derive(Clone)]
  52. pub struct ZkBinaryContractInfo {
  53. pub k_param: u32,
  54. pub bincode: ZkBinary,
  55. pub proving_key: ProvingKey,
  56. pub verifying_key: VerifyingKey,
  57. }
  58. #[derive(Clone)]
  59. pub struct ZkNativeContractInfo {
  60. pub proving_key: ProvingKey,
  61. pub verifying_key: VerifyingKey,
  62. }
  63. #[derive(Clone)]
  64. pub enum ZkContractInfo {
  65. Binary(ZkBinaryContractInfo),
  66. Native(ZkNativeContractInfo),
  67. }
  68. #[derive(Clone)]
  69. pub struct ZkContractTable {
  70. // Key will be a hash of zk binary contract on chain
  71. table: HashMap<String, ZkContractInfo>,
  72. }
  73. impl ZkContractTable {
  74. pub fn new() -> Self {
  75. Self { table: HashMap::new() }
  76. }
  77. pub fn add_contract(&mut self, key: String, bincode: ZkBinary, k_param: u32) {
  78. let witnesses = empty_witnesses(&bincode);
  79. let circuit = ZkCircuit::new(witnesses, bincode.clone());
  80. let proving_key = ProvingKey::build(k_param, &circuit);
  81. let verifying_key = VerifyingKey::build(k_param, &circuit);
  82. let info = ZkContractInfo::Binary(ZkBinaryContractInfo {
  83. k_param,
  84. bincode,
  85. proving_key,
  86. verifying_key,
  87. });
  88. self.table.insert(key, info);
  89. }
  90. pub fn add_native(
  91. &mut self,
  92. key: String,
  93. proving_key: ProvingKey,
  94. verifying_key: VerifyingKey,
  95. ) {
  96. self.table.insert(
  97. key,
  98. ZkContractInfo::Native(ZkNativeContractInfo { proving_key, verifying_key }),
  99. );
  100. }
  101. pub fn lookup(&self, key: &String) -> Option<&ZkContractInfo> {
  102. self.table.get(key)
  103. }
  104. }
  105. // ANCHOR: transaction
  106. pub struct Transaction {
  107. pub func_calls: Vec<FuncCall>,
  108. // TODO: this is wrong. It should be Vec<Vec<Signature>>
  109. // each Vec<Signature> correspond to ONE function call
  110. pub signatures: Vec<Signature>,
  111. }
  112. // ANCHOR_END: transaction
  113. impl Transaction {
  114. /// Verify ZK contracts for the entire tx
  115. /// In real code, we could parallelize this for loop
  116. /// TODO: fix use of unwrap with Result type stuff
  117. pub fn zk_verify(&self, zk_bins: &ZkContractTable) -> DaoResult<()> {
  118. for func_call in &self.func_calls {
  119. let proofs_public_vals = &func_call.call_data.zk_public_values();
  120. assert_eq!(
  121. proofs_public_vals.len(),
  122. func_call.proofs.len(),
  123. "proof_public_vals.len()={} and func_call.proofs.len()={} do not match",
  124. proofs_public_vals.len(),
  125. func_call.proofs.len()
  126. );
  127. for (i, (proof, (key, public_vals))) in
  128. func_call.proofs.iter().zip(proofs_public_vals.iter()).enumerate()
  129. {
  130. match zk_bins.lookup(key).unwrap() {
  131. ZkContractInfo::Binary(info) => {
  132. let verifying_key = &info.verifying_key;
  133. let verify_result = proof.verify(&verifying_key, public_vals);
  134. if verify_result.is_err() {
  135. return Err(DaoError::VerifyProofFailed(i, key.to_string()))
  136. }
  137. //assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
  138. }
  139. ZkContractInfo::Native(info) => {
  140. let verifying_key = &info.verifying_key;
  141. let verify_result = proof.verify(&verifying_key, public_vals);
  142. if verify_result.is_err() {
  143. return Err(DaoError::VerifyProofFailed(i, key.to_string()))
  144. }
  145. //assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
  146. }
  147. };
  148. debug!(target: "demo", "zk_verify({}) passed [i={}]", key, i);
  149. }
  150. }
  151. Ok(())
  152. }
  153. pub fn verify_sigs(&self) {
  154. let mut unsigned_tx_data = vec![];
  155. for (i, (func_call, signature)) in
  156. self.func_calls.iter().zip(self.signatures.clone()).enumerate()
  157. {
  158. func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
  159. let signature_pub_keys = func_call.call_data.signature_public_keys();
  160. for signature_pub_key in signature_pub_keys {
  161. let verify_result = signature_pub_key.verify(&unsigned_tx_data[..], &signature);
  162. assert!(verify_result, "verify sigs[{}] failed", i);
  163. }
  164. debug!(target: "demo", "verify_sigs({}) passed", i);
  165. }
  166. }
  167. }
  168. pub fn sign(signature_secrets: Vec<SecretKey>, func_calls: &Vec<FuncCall>) -> Vec<Signature> {
  169. let mut signatures = vec![];
  170. let mut unsigned_tx_data = vec![];
  171. for (_i, (signature_secret, func_call)) in
  172. signature_secrets.iter().zip(func_calls.iter()).enumerate()
  173. {
  174. func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
  175. let signature = signature_secret.sign(&unsigned_tx_data[..]);
  176. signatures.push(signature);
  177. }
  178. signatures
  179. }
  180. type ContractId = pallas::Base;
  181. type FuncId = pallas::Base;
  182. // ANCHOR: funccall
  183. pub struct FuncCall {
  184. pub contract_id: ContractId,
  185. pub func_id: FuncId,
  186. pub call_data: Box<dyn CallDataBase + Send + Sync>,
  187. pub proofs: Vec<Proof>,
  188. }
  189. // ANCHOR_END: funccall
  190. impl Encodable for FuncCall {
  191. fn encode<W: std::io::Write>(&self, mut w: W) -> std::result::Result<usize, std::io::Error> {
  192. let mut len = 0;
  193. len += self.contract_id.encode(&mut w)?;
  194. len += self.func_id.encode(&mut w)?;
  195. len += self.proofs.encode(&mut w)?;
  196. len += self.call_data.encode_bytes(&mut w)?;
  197. Ok(len)
  198. }
  199. }
  200. // ANCHOR: calldatabase_trait
  201. pub trait CallDataBase {
  202. // Public values for verifying the proofs
  203. // Needed so we can convert internal types so they can be used in Proof::verify()
  204. fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)>;
  205. // For upcasting to CallData itself so it can be read in state_transition()
  206. fn as_any(&self) -> &dyn Any;
  207. // Public keys we will use to verify transaction signatures.
  208. fn signature_public_keys(&self) -> Vec<PublicKey>;
  209. fn encode_bytes(
  210. &self,
  211. writer: &mut dyn std::io::Write,
  212. ) -> std::result::Result<usize, std::io::Error>;
  213. }
  214. // ANCHOR_END: calldatabase_trait
  215. type GenericContractState = Box<dyn Any + Send>;
  216. pub struct StateRegistry {
  217. pub states: HashMap<HashableBase, GenericContractState>,
  218. }
  219. impl StateRegistry {
  220. pub fn new() -> Self {
  221. Self { states: HashMap::new() }
  222. }
  223. pub fn register(&mut self, contract_id: ContractId, state: GenericContractState) {
  224. debug!(target: "StateRegistry::register()", "contract_id: {:?}", contract_id);
  225. self.states.insert(HashableBase(contract_id), state);
  226. }
  227. pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: ContractId) -> Option<&'a mut S> {
  228. self.states.get_mut(&HashableBase(contract_id)).and_then(|state| state.downcast_mut())
  229. }
  230. pub fn lookup<'a, S: 'static>(&'a self, contract_id: ContractId) -> Option<&'a S> {
  231. self.states.get(&HashableBase(contract_id)).and_then(|state| state.downcast_ref())
  232. }
  233. }
  234. pub trait UpdateBase {
  235. fn apply(self: Box<Self>, states: &mut StateRegistry);
  236. }