util.rs 9.2 KB

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