lib.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 darkfi_sdk::{
  19. crypto::ContractId,
  20. db::{db_get, db_init, db_lookup, db_set},
  21. define_contract,
  22. error::ContractResult,
  23. msg,
  24. pasta::pallas,
  25. tx::FuncCall,
  26. util::{set_return_data, put_object_bytes, get_object_bytes, get_object_size},
  27. };
  28. use darkfi_serial::{deserialize, serialize, Encodable, SerialDecodable, SerialEncodable, WriteExt, ReadExt};
  29. /// Available functions for this contract.
  30. /// We identify them with the first byte passed in through the payload.
  31. #[repr(u8)]
  32. pub enum Function {
  33. Foo = 0x00,
  34. Bar = 0x01,
  35. }
  36. impl From<u8> for Function {
  37. fn from(b: u8) -> Self {
  38. match b {
  39. 0x00 => Self::Foo,
  40. 0x01 => Self::Bar,
  41. _ => panic!("Invalid function ID: {:#04x?}", b),
  42. }
  43. }
  44. }
  45. // An example of deserializing the payload into a struct
  46. #[derive(SerialEncodable, SerialDecodable)]
  47. pub struct FooCallData {
  48. pub a: u64,
  49. pub b: u64,
  50. }
  51. impl FooCallData {
  52. //fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)>;
  53. //fn get_metadata(&self) {
  54. //}
  55. }
  56. #[derive(SerialEncodable, SerialDecodable)]
  57. pub struct BarArgs {
  58. pub x: u32,
  59. }
  60. #[derive(SerialEncodable, SerialDecodable)]
  61. pub struct FooUpdate {
  62. pub name: String,
  63. pub age: u32,
  64. }
  65. define_contract!(
  66. init: init_contract,
  67. exec: process_instruction,
  68. apply: process_update,
  69. metadata: get_metadata
  70. );
  71. fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
  72. msg!("wakeup wagies!");
  73. // Initialize a state tree. db_init will fail if the tree already exists.
  74. // Otherwise, it will return a `DbHandle` that can be used further on.
  75. // TODO: If the deploy execution fails, whatever is initialized with db_init
  76. // should be deleted from sled afterwards. There's no way to create a
  77. // tree but only apply the creation when we're done, so db_init creates
  78. // it and upon failure it should delete it
  79. let wagies_handle = db_init(cid, "wagies")?;
  80. db_set(wagies_handle, &serialize(&"jason_gulag".to_string()), &serialize(&110))?;
  81. Ok(())
  82. }
  83. fn get_metadata(_cid: ContractId, ix: &[u8]) -> ContractResult {
  84. match Function::from(ix[0]) {
  85. Function::Foo => {
  86. let tx_data = &ix[1..];
  87. // ...
  88. let (func_call_index, func_calls): (u32, Vec<FuncCall>) = deserialize(tx_data)?;
  89. let _call_data: FooCallData =
  90. deserialize(&func_calls[func_call_index as usize].call_data)?;
  91. let zk_public_values = vec![
  92. (
  93. "DaoProposeInput".to_string(),
  94. vec![pallas::Base::from(110), pallas::Base::from(4)],
  95. ),
  96. ("DaoProposeInput".to_string(), vec![pallas::Base::from(7), pallas::Base::from(4)]),
  97. (
  98. "DaoProposeMain".to_string(),
  99. vec![
  100. pallas::Base::from(1),
  101. pallas::Base::from(3),
  102. pallas::Base::from(5),
  103. pallas::Base::from(7),
  104. ],
  105. ),
  106. ];
  107. let signature_public_keys: Vec<pallas::Point> = vec![
  108. //pallas::Point::identity()
  109. ];
  110. let mut metadata = Vec::new();
  111. zk_public_values.encode(&mut metadata)?;
  112. signature_public_keys.encode(&mut metadata)?;
  113. set_return_data(&metadata)?;
  114. msg!("metadata returned!");
  115. // Convert call_data to halo2 public inputs
  116. // Pass this to the env
  117. }
  118. Function::Bar => {
  119. // ...
  120. }
  121. }
  122. Ok(())
  123. }
  124. // This is the main entrypoint function where the payload is fed.
  125. // Through here, you can branch out into different functions inside
  126. // this library.
  127. fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
  128. msg!("process_instruction():");
  129. msg!(" ix: {:x?}", ix);
  130. msg!(" cid: {:x?}", cid);
  131. //let bytes = [0xde, 0xad, 0xbe, 0xef];
  132. let bytes = [0x3a, 0x14, 0x15, 0x92, 0x63, 0x35];
  133. let obj = put_object_bytes(&bytes);
  134. let obj_size = get_object_size(obj as u32);
  135. msg!(" obj_size: {}", obj_size);
  136. let mut buf = vec![0u8; obj_size as usize];
  137. get_object_bytes(&mut buf, obj as u32);
  138. msg!(" buf (bytes): {:x?}", &buf);
  139. match Function::from(ix[0]) {
  140. Function::Foo => {
  141. let tx_data = &ix[1..];
  142. // ...
  143. let (func_call_index, func_calls): (u32, Vec<FuncCall>) = deserialize(tx_data)?;
  144. let call_data: FooCallData =
  145. deserialize(&func_calls[func_call_index as usize].call_data)?;
  146. msg!("call_data {{ a: {}, b: {} }}", call_data.a, call_data.b);
  147. // ...
  148. let update = FooUpdate { name: "john_doe".to_string(), age: 110 };
  149. let mut update_data = vec![Function::Foo as u8];
  150. update_data.extend_from_slice(&serialize(&update));
  151. set_return_data(&update_data)?;
  152. msg!("update is set!");
  153. // Example: try to get a value from the db
  154. let db_handle = db_lookup(cid, "wagies")?;
  155. if let Some(age_data) = db_get(db_handle, &serialize(&"jason_gulag".to_string()))? {
  156. let age_data: u32 = deserialize(&age_data)?;
  157. msg!("wagie age data: {}", age_data);
  158. } else {
  159. msg!("didn't find wagie age data");
  160. }
  161. }
  162. Function::Bar => {
  163. //let tx_data = &ix[1..];
  164. // ...
  165. //let _args: BarArgs = deserialize(tx_data)?;
  166. }
  167. }
  168. msg!("process_instruction() [END]");
  169. Ok(())
  170. }
  171. fn process_update(_cid: ContractId, update_data: &[u8]) -> ContractResult {
  172. msg!("Make 1 update!");
  173. match Function::from(update_data[0]) {
  174. Function::Foo => {
  175. msg!("fooupp");
  176. let update: FooUpdate = deserialize(&update_data[1..])?;
  177. // Write the wagie to the db
  178. //let tx_handle = db_begin_tx()?;
  179. //db_set(tx_handle, &serialize(&update.name), &serialize(&update.age))?;
  180. //let db_handle = db_lookup("wagies")?;
  181. //db_end_tx(db_handle, tx_handle)?;
  182. }
  183. Function::Bar => {
  184. }
  185. }
  186. msg!("process_update() finished");
  187. Ok(())
  188. }