mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-01 08:12:14 +00:00
Test nullifiers in constant time
Checking for spent notes in a block is still not completely constant time, due to filtering out negative results of the constant-time comparison. Part of #84.
This commit is contained in:
parent
2774d2730f
commit
2bafc688ff
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -493,6 +493,11 @@ dependencies = [
|
|||||||
"opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "0.14.9"
|
version = "0.14.9"
|
||||||
@ -545,6 +550,7 @@ dependencies = [
|
|||||||
"rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"zcash_primitives 0.0.0",
|
"zcash_primitives 0.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -642,6 +648,7 @@ dependencies = [
|
|||||||
"checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967"
|
"checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967"
|
||||||
"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
|
"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
|
||||||
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
|
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
|
||||||
|
"checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082"
|
||||||
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
@ -12,6 +12,7 @@ ff = { path = "../ff" }
|
|||||||
hex = "0.3"
|
hex = "0.3"
|
||||||
pairing = { path = "../pairing" }
|
pairing = { path = "../pairing" }
|
||||||
protobuf = "2"
|
protobuf = "2"
|
||||||
|
subtle = "2"
|
||||||
zcash_primitives = { path = "../zcash_primitives" }
|
zcash_primitives = { path = "../zcash_primitives" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -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<_> =
|
||||||
|
Loading…
Reference in New Issue
Block a user