ICH: Replace old, transitive metadata hashing with direct hashing approach.
Instead of collecting all potential inputs to some metadata entry and hashing those, we directly hash the values we are storing in metadata. This is more accurate and doesn't suffer from quadratic blow-up when many entries have the same dependencies.
This commit is contained in:
parent
bc7af816f3
commit
ca2dce9b48
27 changed files with 689 additions and 341 deletions
|
|
@ -29,16 +29,23 @@ pub struct Blake2bCtx {
|
|||
t: [u64; 2],
|
||||
c: usize,
|
||||
outlen: u16,
|
||||
finalized: bool
|
||||
finalized: bool,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fnv_hash: u64,
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
impl ::std::fmt::Debug for Blake2bCtx {
|
||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||
try!(write!(fmt, "hash: "));
|
||||
for v in &self.h {
|
||||
try!(write!(fmt, "{:x}", v));
|
||||
}
|
||||
Ok(())
|
||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(fmt, "{:x}", self.fnv_hash)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
impl ::std::fmt::Debug for Blake2bCtx {
|
||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(fmt, "Enable debug_assertions() for more info.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +164,9 @@ fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx {
|
|||
c: 0,
|
||||
outlen: outlen as u16,
|
||||
finalized: false,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fnv_hash: 0xcbf29ce484222325,
|
||||
};
|
||||
|
||||
ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64);
|
||||
|
|
@ -194,6 +204,16 @@ fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) {
|
|||
checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy);
|
||||
ctx.c += bytes_to_copy;
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
// compute additional FNV hash for simpler to read debug output
|
||||
const MAGIC_PRIME: u64 = 0x00000100000001b3;
|
||||
|
||||
for &byte in data {
|
||||
ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn blake2b_final(ctx: &mut Blake2bCtx)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#![feature(discriminant_value)]
|
||||
#![feature(specialization)]
|
||||
#![feature(manually_drop)]
|
||||
#![feature(struct_field_attributes)]
|
||||
|
||||
#![cfg_attr(unix, feature(libc))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
|
|
|||
|
|
@ -40,13 +40,18 @@ fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
|
|||
/// This hasher currently always uses the stable Blake2b algorithm
|
||||
/// and allows for variable output lengths through its type
|
||||
/// parameter.
|
||||
#[derive(Debug)]
|
||||
pub struct StableHasher<W> {
|
||||
state: Blake2bHasher,
|
||||
bytes_hashed: u64,
|
||||
width: PhantomData<W>,
|
||||
}
|
||||
|
||||
impl<W: StableHasherResult> ::std::fmt::Debug for StableHasher<W> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{:?}", self.state)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait StableHasherResult: Sized {
|
||||
fn finish(hasher: StableHasher<Self>) -> Self;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue