lib.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. use darkfi_sdk::{
  2. crypto::ContractId,
  3. db::{db_begin_tx, db_end_tx, db_get, db_init, db_lookup, db_set},
  4. define_contract,
  5. error::ContractResult,
  6. msg,
  7. tx::FuncCall,
  8. util::set_return_data,
  9. };
  10. use darkfi_serial::{deserialize, serialize, SerialDecodable, SerialEncodable};
  11. /// Available functions for this contract.
  12. /// We identify them with the first byte passed in through the payload.
  13. #[repr(u8)]
  14. pub enum Function {
  15. Foo = 0x00,
  16. Bar = 0x01,
  17. }
  18. impl From<u8> for Function {
  19. fn from(b: u8) -> Self {
  20. match b {
  21. 0x00 => Self::Foo,
  22. 0x01 => Self::Bar,
  23. _ => panic!("Invalid function ID: {:#04x?}", b),
  24. }
  25. }
  26. }
  27. // An example of deserializing the payload into a struct
  28. #[derive(SerialEncodable, SerialDecodable)]
  29. pub struct FooCallData {
  30. pub a: u64,
  31. pub b: u64,
  32. }
  33. impl FooCallData {
  34. //fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)>;
  35. //fn get_metadata(&self) {
  36. //}
  37. }
  38. #[derive(SerialEncodable, SerialDecodable)]
  39. pub struct BarArgs {
  40. pub x: u32,
  41. }
  42. #[derive(SerialEncodable, SerialDecodable)]
  43. pub struct FooUpdate {
  44. pub name: String,
  45. pub age: u32,
  46. }
  47. define_contract!(
  48. init: init_contract,
  49. exec: process_instruction,
  50. apply: process_update,
  51. metadata: get_metadata
  52. );
  53. fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
  54. msg!("wakeup wagies!");
  55. db_init(cid, "wagies")?;
  56. // Lets write a value in there
  57. let tx_handle = db_begin_tx()?;
  58. db_set(tx_handle, "jason_gulag".as_bytes(), serialize(&110))?;
  59. let db_handle = db_lookup("wagies")?;
  60. db_end_tx(db_handle, tx_handle)?;
  61. // Host will clear delete the batches array after calling this func.
  62. Ok(())
  63. }
  64. fn get_metadata(_cid: ContractId, ix: &[u8]) -> ContractResult {
  65. match Function::from(ix[0]) {
  66. Function::Foo => {
  67. let tx_data = &ix[1..];
  68. // ...
  69. let (func_call_index, func_calls): (u32, Vec<FuncCall>) = deserialize(tx_data)?;
  70. let _call_data: FooCallData =
  71. deserialize(&func_calls[func_call_index as usize].call_data)?;
  72. // Convert call_data to halo2 public inputs
  73. // Pass this to the env
  74. }
  75. Function::Bar => {
  76. // ...
  77. }
  78. }
  79. Ok(())
  80. }
  81. // This is the main entrypoint function where the payload is fed.
  82. // Through here, you can branch out into different functions inside
  83. // this library.
  84. fn process_instruction(_cid: ContractId, ix: &[u8]) -> ContractResult {
  85. match Function::from(ix[0]) {
  86. Function::Foo => {
  87. let tx_data = &ix[1..];
  88. // ...
  89. let (func_call_index, func_calls): (u32, Vec<FuncCall>) = deserialize(tx_data)?;
  90. let call_data: FooCallData =
  91. deserialize(&func_calls[func_call_index as usize].call_data)?;
  92. msg!("call_data {{ a: {}, b: {} }}", call_data.a, call_data.b);
  93. // ...
  94. let update = FooUpdate { name: "john_doe".to_string(), age: 110 };
  95. let mut update_data = vec![Function::Foo as u8];
  96. update_data.extend_from_slice(&serialize(&update));
  97. set_return_data(&update_data)?;
  98. msg!("update is set!");
  99. // Example: try to get a value from the db
  100. let db_handle = db_lookup("wagies")?;
  101. // FIXME: this is just empty right now
  102. let age_data = db_get(db_handle, "jason_gulag".as_bytes())?;
  103. msg!("wagie age data: {:?}", age_data);
  104. }
  105. Function::Bar => {
  106. let tx_data = &ix[1..];
  107. // ...
  108. let _args: BarArgs = deserialize(tx_data)?;
  109. }
  110. }
  111. Ok(())
  112. }
  113. fn process_update(_cid: ContractId, update_data: &[u8]) -> ContractResult {
  114. msg!("Make update!");
  115. match Function::from(update_data[0]) {
  116. Function::Foo => {
  117. let update: FooUpdate = deserialize(&update_data[1..])?;
  118. // Write the wagie to the db
  119. let tx_handle = db_begin_tx()?;
  120. db_set(tx_handle, update.name.as_bytes(), serialize(&update.age))?;
  121. let db_handle = db_lookup("wagies")?;
  122. db_end_tx(db_handle, tx_handle)?;
  123. }
  124. _ => unreachable!(),
  125. }
  126. Ok(())
  127. }