state.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use bellman::groth16;
  2. use bls12_381::Bls12;
  3. use std::fmt;
  4. use crate::{
  5. crypto::{coin::Coin, merkle_node::MerkleNode, note::EncryptedNote, nullifier::Nullifier},
  6. tx,
  7. };
  8. pub trait ProgramState {
  9. fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool;
  10. fn is_valid_merkle(&self, merkle: &MerkleNode) -> bool;
  11. fn nullifier_exists(&self, nullifier: &Nullifier) -> bool;
  12. fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12>;
  13. fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12>;
  14. }
  15. pub struct StateUpdate {
  16. pub nullifiers: Vec<Nullifier>,
  17. pub coins: Vec<Coin>,
  18. pub enc_notes: Vec<EncryptedNote>,
  19. }
  20. pub type VerifyResult<T> = std::result::Result<T, VerifyFailed>;
  21. #[derive(Debug)]
  22. pub enum VerifyFailed {
  23. InvalidCashierKey(usize),
  24. InvalidMerkle(usize),
  25. DuplicateNullifier(usize),
  26. SpendProof(usize),
  27. MintProof(usize),
  28. ClearInputSignature(usize),
  29. InputSignature(usize),
  30. MissingFunds,
  31. }
  32. impl std::error::Error for VerifyFailed {}
  33. impl fmt::Display for VerifyFailed {
  34. fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
  35. match *self {
  36. VerifyFailed::InvalidCashierKey(i) => {
  37. write!(f, "Invalid cashier public key for clear input {}", i)
  38. }
  39. VerifyFailed::InvalidMerkle(i) => {
  40. write!(f, "Invalid merkle root for input {}", i)
  41. }
  42. VerifyFailed::DuplicateNullifier(i) => {
  43. write!(f, "Duplicate nullifier for input {}", i)
  44. }
  45. VerifyFailed::SpendProof(i) => write!(f, "Spend proof for input {}", i),
  46. VerifyFailed::MintProof(i) => write!(f, "Mint proof for input {}", i),
  47. VerifyFailed::ClearInputSignature(i) => {
  48. write!(f, "Invalid signature for clear input {}", i)
  49. }
  50. VerifyFailed::InputSignature(i) => write!(f, "Invalid signature for input {}", i),
  51. VerifyFailed::MissingFunds => {
  52. f.write_str("Money in does not match money out (value commits)")
  53. }
  54. }
  55. }
  56. }
  57. pub fn state_transition<S: ProgramState>(
  58. state: &S,
  59. tx: tx::Transaction,
  60. ) -> VerifyResult<StateUpdate> {
  61. // Check deposits are legit
  62. for (i, input) in tx.clear_inputs.iter().enumerate() {
  63. // Check the public key in the clear inputs
  64. // It should be a valid public key for the cashier
  65. if !state.is_valid_cashier_public_key(&input.signature_public) {
  66. return Err(VerifyFailed::InvalidCashierKey(i));
  67. }
  68. }
  69. for (i, input) in tx.inputs.iter().enumerate() {
  70. // Check merkle roots
  71. let merkle = &input.revealed.merkle_root;
  72. // Merkle is used to know whether this is a coin that existed
  73. // in a previous state.
  74. if !state.is_valid_merkle(merkle) {
  75. return Err(VerifyFailed::InvalidMerkle(i));
  76. }
  77. // The nullifiers should not already exist
  78. // It is double spend protection.
  79. let nullifier = &input.revealed.nullifier;
  80. if state.nullifier_exists(nullifier) {
  81. return Err(VerifyFailed::DuplicateNullifier(i));
  82. }
  83. }
  84. // Check the tx verifies correctly
  85. tx.verify(state.mint_pvk(), state.spend_pvk())?;
  86. let mut nullifiers = vec![];
  87. for input in tx.inputs {
  88. nullifiers.push(input.revealed.nullifier);
  89. }
  90. // Newly created coins for this tx
  91. let mut coins = vec![];
  92. let mut enc_notes = vec![];
  93. for output in tx.outputs {
  94. // Gather all the coins
  95. coins.push(Coin::new(output.revealed.coin));
  96. enc_notes.push(output.enc_note);
  97. }
  98. Ok(StateUpdate {
  99. nullifiers,
  100. coins,
  101. enc_notes,
  102. })
  103. }