-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(state-tree)!: implement verify for Merkle in/exclusion proofs (#…
…1216) Description --- feat(state-tree): implement verify for Merkle in/exclusion proofs fix(consensus)!: include substate version in JMT node hashes Motivation and Context --- Implement inclusion and exclusion proofs for JMT. This is useful for command inclusion proofs e.g. eviction proof as well as inclusion proofs for substates. Usage: ```rust let (key, proof_value, proof) = tree.get_proof(current_version, &substate_id).unwrap(); let value_hash = hash_substate(substate); proof.verify_inclusion(&root_hash, &key, &value_hash).unwrap(); proof.verify_exclusion(&root_hash, &some_non_existing_key).unwrap(); ``` How Has This Been Tested? --- Unit tests, manually What process can a PR reviewer use to test or verify this change? --- Breaking Changes --- - [ ] None - [x] Requires data directory to be deleted - [ ] Other - Please specify BREAKING CHANGE: substate changes for JMT state tree include the substate version in the key hash
- Loading branch information
Showing
15 changed files
with
323 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
use std::ops::Range; | ||
|
||
/// An iterator over a hash value that generates one bit for each iteration. | ||
pub struct BitIterator<'a> { | ||
/// The reference to the bytes that represent the `HashValue`. | ||
bytes: &'a [u8], | ||
pos: Range<usize>, | ||
// invariant hash_bytes.len() == HashValue::LENGTH; | ||
// invariant pos.end == hash_bytes.len() * 8; | ||
} | ||
|
||
impl<'a> BitIterator<'a> { | ||
/// Constructs a new `BitIterator` using given `HashValue`. | ||
pub fn new(bytes: &'a [u8]) -> Self { | ||
BitIterator { | ||
bytes, | ||
pos: 0..bytes.len() * 8, | ||
} | ||
} | ||
|
||
/// Returns the `index`-th bit in the bytes. | ||
fn get_bit(&self, index: usize) -> bool { | ||
// MIRAI annotations - important? | ||
// assume!(index < self.pos.end); // assumed precondition | ||
// assume!(self.hash_bytes.len() == 32); // invariant | ||
// assume!(self.pos.end == self.hash_bytes.len() * 8); // invariant | ||
let pos = index / 8; | ||
let bit = 7 - index % 8; | ||
(self.bytes[pos] >> bit) & 1 != 0 | ||
} | ||
} | ||
|
||
impl<'a> Iterator for BitIterator<'a> { | ||
type Item = bool; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
self.pos.next().map(|x| self.get_bit(x)) | ||
} | ||
|
||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
self.pos.size_hint() | ||
} | ||
} | ||
|
||
impl<'a> DoubleEndedIterator for BitIterator<'a> { | ||
fn next_back(&mut self) -> Option<Self::Item> { | ||
self.pos.next_back().map(|x| self.get_bit(x)) | ||
} | ||
} | ||
|
||
impl<'a> ExactSizeIterator for BitIterator<'a> {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
use crate::{Hash, LeafKey}; | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum JmtProofVerifyError { | ||
#[error("Sparse Merkle Tree proof has more than 256 ({num_siblings}) siblings.")] | ||
TooManySiblings { num_siblings: usize }, | ||
#[error("Keys do not match. Key in proof: {actual_key}. Expected key: {expected_key}.")] | ||
KeyMismatch { actual_key: LeafKey, expected_key: LeafKey }, | ||
#[error("Value hashes do not match. Value hash in proof: {actual}. Expected value hash: {expected}.")] | ||
ValueMismatch { actual: Hash, expected: Hash }, | ||
#[error("Expected inclusion proof. Found non-inclusion proof.")] | ||
ExpectedInclusionProof, | ||
#[error("Expected non-inclusion proof, but key exists in proof.")] | ||
ExpectedNonInclusionProof, | ||
#[error( | ||
"Key would not have ended up in the subtree where the provided key in proof is the only existing key, if it \ | ||
existed. So this is not a valid non-inclusion proof." | ||
)] | ||
InvalidNonInclusionProof, | ||
#[error( | ||
"Root hashes do not match. Actual root hash: {actual_root_hash}. Expected root hash: {expected_root_hash}." | ||
)] | ||
RootHashMismatch { | ||
actual_root_hash: Hash, | ||
expected_root_hash: Hash, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ pub use tree::*; | |
mod types; | ||
pub use types::*; | ||
|
||
mod error; | ||
mod store; | ||
|
||
pub use store::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,5 +12,7 @@ pub mod memory_store; | |
mod staged_store; | ||
pub use staged_store::*; | ||
|
||
mod bit_iter; | ||
mod tree; | ||
|
||
pub use tree::*; |
Oops, something went wrong.