state.rs 3.4 KB

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