Przeglądaj źródła

node/state: Check that input nullifiers are also not dupe in the tx itself.

parazyd 4 lat temu
rodzic
commit
531653da1a
1 zmienionych plików z 8 dodań i 7 usunięć
  1. 8 7
      src/node/state.rs

+ 8 - 7
src/node/state.rs

@@ -63,6 +63,9 @@ pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyRe
         }
     }
 
+    // Nullifiers in the transaction
+    let mut nullifiers = Vec::with_capacity(tx.inputs.len());
+
     debug!(target: "state_transition", "Iterate inputs");
     for (i, input) in tx.inputs.iter().enumerate() {
         let merkle = &input.revealed.merkle_root;
@@ -78,11 +81,15 @@ pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyRe
         // The nullifiers should not already exist.
         // It is the double-spend protection.
         let nullifier = &input.revealed.nullifier;
-        if state.nullifier_exists(nullifier) {
+        if state.nullifier_exists(nullifier) ||
+            (1..nullifiers.len()).any(|i| nullifiers[i..].contains(&nullifiers[i - 1]))
+        {
             error!(target: "state_transition", "Duplicate nullifier found (input {})", i);
             debug!(target: "state_transition", "nullifier: {:?}", nullifier);
             return Err(VerifyFailed::NullifierExists(i))
         }
+
+        nullifiers.push(input.revealed.nullifier);
     }
 
     debug!(target: "state_transition", "Verifying zk proofs");
@@ -94,12 +101,6 @@ pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyRe
         }
     }
 
-    // Gather all the nullifiers
-    let mut nullifiers = Vec::with_capacity(tx.inputs.len());
-    for input in tx.inputs {
-        nullifiers.push(input.revealed.nullifier);
-    }
-
     // Newly created coins for this transaction
     let mut coins = Vec::with_capacity(tx.outputs.len());
     let mut enc_notes = Vec::with_capacity(tx.outputs.len());