lib.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. use darkfi_sdk::{
  2. crypto::{MerkleNode, Nullifier},
  3. entrypoint,
  4. error::ContractResult,
  5. incrementalmerkletree::bridgetree::BridgeTree,
  6. };
  7. use darkfi_serial::{deserialize, SerialDecodable, SerialEncodable};
  8. /// Available functions for this contract.
  9. /// We identify them with the first byte passed in through the payload.
  10. #[repr(u8)]
  11. pub enum Function {
  12. Transfer = 0x00,
  13. }
  14. impl From<u8> for Function {
  15. fn from(b: u8) -> Self {
  16. match b {
  17. 0x00 => Self::Transfer,
  18. _ => panic!("Invalid function ID: {:#04x?}", b),
  19. }
  20. }
  21. }
  22. pub mod transfer;
  23. /// `State` represents this contract's state on-chain. The contract's
  24. /// entrypoint knows its own `ContractId` since it's passed in by the
  25. /// wasm runtime, so it knows what to request. Retrieval of the state
  26. /// from the blockchain is done with a host function called `lookup_state`.
  27. /// For more info, see:
  28. /// * `darkfi/src/blockchain/statestore.rs`
  29. /// * ~~~`darkfi/src/runtime/chain_state.rs`~~~
  30. #[repr(C)]
  31. #[derive(Clone, SerialEncodable, SerialDecodable)]
  32. pub struct State {
  33. /// The Merkle tree of all coins used by this contract.
  34. pub tree: BridgeTree<MerkleNode, 32>,
  35. /// List of all previous and current Merkle roots.
  36. pub merkle_roots: Vec<MerkleNode>,
  37. /// Published nullifiers that have been seen.
  38. pub nullifiers: Vec<Nullifier>,
  39. }
  40. impl State {
  41. pub fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
  42. self.merkle_roots.iter().any(|m| m == merkle_root)
  43. }
  44. pub fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
  45. self.nullifiers.iter().any(|n| n == nullifier)
  46. }
  47. }
  48. #[cfg(not(feature = "no-entrypoint"))]
  49. entrypoint!(process_instruction);
  50. fn process_instruction(state: &[u8], ix: &[u8]) -> ContractResult {
  51. // This is the entrypoint function of the smart contract which gets executed
  52. // by the wasm runtime. The `contract_id` passed in is used to lookup the
  53. // current state from the ledger using the `lookup_state` function.
  54. // `ix` is an arbitrary payload fed into the contract. In this case, the
  55. // first byte of the payload is a pointer to a function we with to run, and
  56. // the remainter is a serialized `Transaction` object we'll try to deserialize
  57. // and work with.
  58. let mut state: State = deserialize(state)?;
  59. match Function::from(ix[0]) {
  60. Function::Transfer => {
  61. let transaction = deserialize(&ix[1..])?;
  62. transfer::exec(&mut state, transaction)?;
  63. // If `transfer` succeeded, `state` will contain the updated state, so
  64. // we can change it in the VM environment which is accessible by the
  65. // host. Then if everything else outside of the wasm execution is
  66. // valid, the host can reference this new state and update it on the
  67. // ledger.
  68. //apply_state(&serialize(&state))?;
  69. }
  70. }
  71. Ok(())
  72. }