state.rs 4.2 KB

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