@ -3,6 +3,7 @@
use ff ::{ PrimeField , PrimeFieldRepr } ;
use ff ::{ PrimeField , PrimeFieldRepr } ;
use pairing ::bls12_381 ::{ Bls12 , Fr , FrRepr } ;
use pairing ::bls12_381 ::{ Bls12 , Fr , FrRepr } ;
use std ::collections ::HashSet ;
use std ::collections ::HashSet ;
use subtle ::{ ConditionallySelectable , ConstantTimeEq , CtOption } ;
use zcash_primitives ::{
use zcash_primitives ::{
jubjub ::{ edwards , fs ::Fs } ,
jubjub ::{ edwards , fs ::Fs } ,
merkle_tree ::{ CommitmentTree , IncrementalWitness } ,
merkle_tree ::{ CommitmentTree , IncrementalWitness } ,
@ -116,28 +117,29 @@ pub fn scan_block(
let num_outputs = tx . outputs . len ( ) ;
let num_outputs = tx . outputs . len ( ) ;
// Check for spent notes
// Check for spent notes
let shielded_spends : Vec < _ > =
// The only step that is not constant-time is the filter() at the end.
tx . spends
let shielded_spends : Vec < _ > = tx
. into_iter ( )
. spends
. enumerate ( )
. into_iter ( )
. filter_map ( | ( index , spend ) | {
. enumerate ( )
if let Some ( account ) = nullifiers . iter ( ) . find_map ( | & ( nf , acc ) | {
. map ( | ( index , spend ) | {
if nf = = & spend . nf [ .. ] {
// Find the first tracked nullifier that matches this spend, and produce
Some ( acc )
// a WalletShieldedSpend if there is a match, in constant time.
} else {
nullifiers
None
. iter ( )
}
. map ( | & ( nf , account ) | CtOption ::new ( account as u64 , nf . ct_eq ( & spend . nf [ .. ] ) ) )
} ) {
. fold ( CtOption ::new ( 0 , 0. into ( ) ) , | first , next | {
Some ( WalletShieldedSpend {
CtOption ::conditional_select ( & next , & first , first . is_some ( ) )
index ,
} )
nf : spend . nf ,
. map ( | account | WalletShieldedSpend {
account ,
index ,
} )
nf : spend . nf ,
} else {
account : account as usize ,
None
} )
}
} )
} )
. filter ( | spend | spend . is_some ( ) . into ( ) )
. collect ( ) ;
. map ( | spend | spend . unwrap ( ) )
. collect ( ) ;
// Collect the set of accounts that were spent from in this transaction
// Collect the set of accounts that were spent from in this transaction
let spent_from_accounts : HashSet < _ > =
let spent_from_accounts : HashSet < _ > =