validate.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
  2. use pasta_curves::pallas;
  3. use darkfi::{
  4. crypto::{keypair::PublicKey, types::DrkCircuitField},
  5. Error as DarkFiError,
  6. };
  7. use std::any::{Any, TypeId};
  8. use crate::{
  9. contract::example_contract::{state::State, CONTRACT_ID},
  10. util::{CallDataBase, StateRegistry, Transaction, UpdateBase},
  11. };
  12. type Result<T> = std::result::Result<T, Error>;
  13. #[derive(Debug, Clone, thiserror::Error)]
  14. pub enum Error {
  15. #[error("ValueExists")]
  16. ValueExists,
  17. #[error("DarkFi error: {0}")]
  18. DarkFiError(String),
  19. }
  20. impl From<DarkFiError> for Error {
  21. fn from(err: DarkFiError) -> Self {
  22. Self::DarkFiError(err.to_string())
  23. }
  24. }
  25. #[derive(Clone, SerialEncodable, SerialDecodable)]
  26. pub struct CallData {
  27. pub public_value: pallas::Base,
  28. pub signature_public: PublicKey,
  29. }
  30. impl CallDataBase for CallData {
  31. fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
  32. vec![("example-foo".to_string(), vec![self.public_value])]
  33. }
  34. fn as_any(&self) -> &dyn Any {
  35. self
  36. }
  37. fn signature_public_keys(&self) -> Vec<PublicKey> {
  38. vec![self.signature_public]
  39. }
  40. fn encode_bytes(
  41. &self,
  42. mut writer: &mut dyn std::io::Write,
  43. ) -> core::result::Result<usize, std::io::Error> {
  44. self.encode(&mut writer)
  45. }
  46. }
  47. pub fn state_transition(
  48. states: &StateRegistry,
  49. func_call_index: usize,
  50. parent_tx: &Transaction,
  51. ) -> Result<Box<dyn UpdateBase + Send>> {
  52. let func_call = &parent_tx.func_calls[func_call_index];
  53. let call_data = func_call.call_data.as_any();
  54. assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
  55. let call_data = call_data.downcast_ref::<CallData>();
  56. // This will be inside wasm so unwrap is fine.
  57. let call_data = call_data.unwrap();
  58. let example_state = states.lookup::<State>(*CONTRACT_ID).unwrap();
  59. if example_state.public_exists(&call_data.public_value) {
  60. return Err(Error::ValueExists)
  61. }
  62. Ok(Box::new(Update { public_value: call_data.public_value }))
  63. }
  64. #[derive(Clone)]
  65. pub struct Update {
  66. public_value: pallas::Base,
  67. }
  68. impl UpdateBase for Update {
  69. fn apply(self: Box<Self>, states: &mut StateRegistry) {
  70. let example_state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
  71. example_state.add_public_value(self.public_value);
  72. }
  73. }