state.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. use log::debug;
  2. use crate::{
  3. crypto::{
  4. coin::Coin, merkle_node::MerkleNode, note::EncryptedNote, nullifier::Nullifier,
  5. proof::VerifyingKey, schnorr,
  6. },
  7. tx::Transaction,
  8. };
  9. pub trait ProgramState {
  10. fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool;
  11. fn is_valid_merkle(&self, merkle: &MerkleNode) -> bool;
  12. fn nullifier_exists(&self, nullifier: &Nullifier) -> bool;
  13. fn mint_vk(&self) -> &VerifyingKey;
  14. fn spend_vk(&self) -> &VerifyingKey;
  15. }
  16. pub struct StateUpdate {
  17. pub nullifiers: Vec<Nullifier>,
  18. pub coins: Vec<Coin>,
  19. pub enc_notes: Vec<EncryptedNote>,
  20. }
  21. pub type VerifyResult<T> = std::result::Result<T, VerifyFailed>;
  22. #[derive(Debug, Clone, thiserror::Error)]
  23. pub enum VerifyFailed {
  24. #[error("Invalid cashier public key for clear input {0}")]
  25. InvalidCashierKey(usize),
  26. #[error("Invalid merkle root for input {0}")]
  27. InvalidMerkle(usize),
  28. #[error("Duplicate nullifier for input {0}")]
  29. DuplicateNullifier(usize),
  30. #[error("Spend proof for input {0}")]
  31. SpendProof(usize),
  32. #[error("Mint proof for input {0}")]
  33. MintProof(usize),
  34. #[error("Invalid signature for clear input {0}")]
  35. ClearInputSignature(usize),
  36. #[error("Invalid signature for input {0}")]
  37. InputSignature(usize),
  38. #[error("Money in does not match money out (value commits)")]
  39. MissingFunds,
  40. #[error("Assets don't match some inputs or outputs (token commits)")]
  41. AssetMismatch,
  42. }
  43. pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyResult<StateUpdate> {
  44. // Check deposits are legit
  45. debug!(target: "STATE TRANSITION", "iterate clear_inputs");
  46. for (i, input) in tx.clear_inputs.iter().enumerate() {
  47. // Check the public key in the clear inputs
  48. // It should be a valid public key for the cashier
  49. if !state.is_valid_cashier_public_key(&input.signature_public) {
  50. log::error!(target: "STATE TRANSITION", "Not valid cashier public key");
  51. return Err(VerifyFailed::InvalidCashierKey(i))
  52. }
  53. }
  54. debug!(target: "STATE TRANSITION", "iterate inputs");
  55. for (i, input) in tx.inputs.iter().enumerate() {
  56. let merkle = &input.revealed.merkle_root;
  57. // Merkle is used to know whether this is a coin that existed
  58. // in a previous state.
  59. if !state.is_valid_merkle(merkle) {
  60. return Err(VerifyFailed::InvalidMerkle(i))
  61. }
  62. // The nullifiers should not already exist
  63. // It is double spend protection.
  64. let nullifier = &input.revealed.nullifier;
  65. if state.nullifier_exists(nullifier) {
  66. return Err(VerifyFailed::DuplicateNullifier(i))
  67. }
  68. }
  69. debug!(target: "STATE TRANSITION", "Check the tx Verifies correctly");
  70. // Check the tx verifies correctly
  71. tx.verify(state.mint_vk(), state.spend_vk())?;
  72. let mut nullifiers = vec![];
  73. for input in tx.inputs {
  74. nullifiers.push(input.revealed.nullifier);
  75. }
  76. // Newly created coins for this tx
  77. let mut coins = vec![];
  78. let mut enc_notes = vec![];
  79. for output in tx.outputs {
  80. // Gather all the coins
  81. coins.push(Coin(output.revealed.coin));
  82. enc_notes.push(output.enc_note);
  83. }
  84. Ok(StateUpdate { nullifiers, coins, enc_notes })
  85. }