Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bump msrv to 1.63.0 #60

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 18 additions & 35 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,38 @@ env:
CARGO_TERM_COLOR: always

jobs:
build:

linting:
runs-on: ubuntu-latest

steps:
# try to build
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
# run all tests
- uses: actions/checkout@v3
- name: Run tests
run: cargo test --verbose
- uses: actions/checkout@v4

linting:
- name: Install latest nightly
uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt, clippy

runs-on: ubuntu-latest
steps:
# Install Rust nightly toolchain
- uses: actions/checkout@v3
- name: Install nightly toolchain
uses: actions-rs/toolchain@v1
with:
profile: default
toolchain: nightly
override: true

# cargo fmt
- uses: actions/checkout@v3
- name: fmt
run: cargo +nightly fmt --all --check
- name: Run cargo fmt
run: cargo +nightly fmt --all --check

# run cargo clippy
- uses: actions/checkout@v3
- name: Clippy
run: cargo +nightly clippy --all
- name: Run cargo clippy
run: cargo +nightly clippy --all-targets

cross-testing:
strategy:
matrix:
rust: [stable, nightly, 1.41]
os: [ubuntu-latest, windows-latest, macos-latest]
feature: [default, with-serde]
toolchain: [nightly, stable, 1.63.0]

runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
toolchain: ${{ matrix.toolchain }}
components: rustfmt, clippy

- name: Run Tests
run: cargo +${{ matrix.toolchain }} test --all

- name: Cross compile
run: cargo test --verbose --features ${{ matrix.feature }}
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license = "MIT"
repository = "https://github.com/mit-dci/rustreexo"
readme = "README.md"
homepage = "https://github.com/mit-dci/rustreexo"
rust-version = "1.63.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
Expand All @@ -17,7 +18,6 @@ serde = { version = "1.0", features = ["derive"], optional = true }
[dev-dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.81"
starknet-crypto = "0.7.2"

[features]
with-serde = ["serde"]
Expand Down
62 changes: 30 additions & 32 deletions examples/custom-hash-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,16 @@

use rustreexo::accumulator::mem_forest::MemForest;
use rustreexo::accumulator::node_hash::AccumulatorHash;
use starknet_crypto::poseidon_hash_many;
use starknet_crypto::Felt;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// We need a stateful wrapper around the actual hash, this is because we use those different
/// values inside our accumulator. Here we use an enum to represent the different states, you
/// may want to use a struct with more data, depending on your needs.
enum PoseidonHash {
enum CustomHash {
/// This means this holds an actual value
///
/// It usually represents a node in the accumulator that haven't been deleted.
Hash(Felt),
Hash([u8; 32]),
/// Placeholder is a value that haven't been deleted, but we don't have the actual value.
/// The only thing that matters about it is that it's not empty. You can implement this
/// the way you want, just make sure that [NodeHash::is_placeholder] and [NodeHash::placeholder]
Expand All @@ -44,39 +42,39 @@ enum PoseidonHash {
}

// you'll need to implement Display for your hash type, so you can print it.
impl std::fmt::Display for PoseidonHash {
impl std::fmt::Display for CustomHash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PoseidonHash::Hash(h) => write!(f, "Hash({})", h),
PoseidonHash::Placeholder => write!(f, "Placeholder"),
PoseidonHash::Empty => write!(f, "Empty"),
CustomHash::Hash(h) => write!(f, "Hash({:?})", h),
CustomHash::Placeholder => write!(f, "Placeholder"),
CustomHash::Empty => write!(f, "Empty"),
}
}
}

// this is the implementation of the NodeHash trait for our custom hash type. And it's the only
// thing you need to do to use your custom hash type with the accumulator data structures.
impl AccumulatorHash for PoseidonHash {
impl AccumulatorHash for CustomHash {
// returns a new placeholder type such that is_placeholder returns true
fn placeholder() -> Self {
PoseidonHash::Placeholder
CustomHash::Placeholder
}

// returns an empty hash such that is_empty returns true
fn empty() -> Self {
PoseidonHash::Empty
CustomHash::Empty
}

// returns true if this is a placeholder. This should be true iff this type was created by
// calling placeholder.
fn is_placeholder(&self) -> bool {
matches!(self, PoseidonHash::Placeholder)
matches!(self, CustomHash::Placeholder)
}

// returns true if this is an empty hash. This should be true iff this type was created by
// calling empty.
fn is_empty(&self) -> bool {
matches!(self, PoseidonHash::Empty)
matches!(self, CustomHash::Empty)
}

// used for serialization, writes the hash to the writer
Expand All @@ -87,9 +85,9 @@ impl AccumulatorHash for PoseidonHash {
W: std::io::Write,
{
match self {
PoseidonHash::Hash(h) => writer.write_all(&h.to_bytes_be()),
PoseidonHash::Placeholder => writer.write_all(&[0u8; 32]),
PoseidonHash::Empty => writer.write_all(&[0u8; 32]),
CustomHash::Hash(h) => writer.write_all(h),
CustomHash::Placeholder => writer.write_all(&[0u8; 32]),
CustomHash::Empty => writer.write_all(&[0u8; 32]),
}
}

Expand All @@ -100,12 +98,12 @@ impl AccumulatorHash for PoseidonHash {
where
R: std::io::Read,
{
let mut buf = [0u8; 32];
reader.read_exact(&mut buf)?;
if buf.iter().all(|&b| b == 0) {
Ok(PoseidonHash::Empty)
let mut h = [0u8; 32];
reader.read_exact(&mut h)?;
if h.iter().all(|&x| x == 0) {
Ok(CustomHash::Placeholder)
} else {
Ok(PoseidonHash::Hash(Felt::from_bytes_be(&buf)))
Ok(CustomHash::Hash(h))
}
}

Expand All @@ -114,25 +112,25 @@ impl AccumulatorHash for PoseidonHash {
// exact same algorithm to calculate the next hash. Rustreexo won't call this method, unless
// **both** children are not empty.
fn parent_hash(left: &Self, right: &Self) -> Self {
if let (PoseidonHash::Hash(left), PoseidonHash::Hash(right)) = (left, right) {
return PoseidonHash::Hash(poseidon_hash_many(&[*left, *right]));
match (left, right) {
(CustomHash::Hash(l), CustomHash::Hash(r)) => {
let mut h = [0u8; 32];
for i in 0..32 {
h[i] = l[i] ^ r[i];
}
CustomHash::Hash(h)
}
_ => unreachable!(),
}

// This should never happen, since rustreexo won't call this method unless both children
// are not empty.
unreachable!()
}
}

fn main() {
// Create a vector with two utxos that will be added to the MemForest
let elements = vec![
PoseidonHash::Hash(Felt::from(1)),
PoseidonHash::Hash(Felt::from(2)),
];
let elements = vec![CustomHash::Hash([1; 32]), CustomHash::Hash([2; 32])];

// Create a new MemForest, and add the utxos to it
let mut p = MemForest::<PoseidonHash>::new_with_hash();
let mut p = MemForest::<CustomHash>::new_with_hash();
p.modify(&elements, &[]).unwrap();

// Create a proof that the first utxo is in the MemForest
Expand Down
4 changes: 4 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[toolchain]
channel = "1.63.0"
components = [ "rustfmt", "clippy" ]
profile = "default"
7 changes: 5 additions & 2 deletions src/accumulator/pollard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ impl<Hash: AccumulatorHash> Pollard<Hash> {

/// Creates a new empty [Pollard]
pub fn new() -> Pollard<Hash> {
let roots: [Option<Rc<PollardNode<Hash>>>; 64] = [const { None }; 64];
let roots: [Option<Rc<PollardNode<Hash>>>; 64] = std::array::from_fn(|_| None);
Pollard::<Hash> { roots, leaves: 0 }
}
}
Expand Down Expand Up @@ -849,7 +849,10 @@ impl<Hash: AccumulatorHash> Pollard<Hash> {
// my parent is a root, I'm a root now
for i in 0..64 {
let aunt = node.aunt().unwrap();
let Some(root) = self.roots[i].as_ref() else {

let root = if let Some(root) = self.roots[i].as_ref() {
root
} else {
continue;
};
if root.hash() == aunt.hash() {
Expand Down
19 changes: 6 additions & 13 deletions src/accumulator/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,13 +462,9 @@ impl<Hash: AccumulatorHash> Proof<Hash> {
let mut computed = Vec::with_capacity(nodes.len() * 2);
let mut computed_index = 0;
let mut provided_index = 0;
loop {
let Some((next_pos, (next_hash_old, next_hash_new))) =
Self::get_next(&computed, &nodes, &mut computed_index, &mut provided_index)
else {
break;
};

while let Some((next_pos, (next_hash_old, next_hash_new))) =
Self::get_next(&computed, &nodes, &mut computed_index, &mut provided_index)
{
if util::is_root_position(next_pos, num_leaves, total_rows) {
calculated_root_hashes.push((next_hash_old, next_hash_new));
continue;
Expand Down Expand Up @@ -547,13 +543,10 @@ impl<Hash: AccumulatorHash> Proof<Hash> {
let mut computed = Vec::with_capacity(nodes.len() * 2);
let mut computed_index = 0;
let mut provided_index = 0;
loop {
let Some((next_pos, next_hash)) =
Self::get_next(&computed, &nodes, &mut computed_index, &mut provided_index)
else {
break;
};

while let Some((next_pos, next_hash)) =
Self::get_next(&computed, &nodes, &mut computed_index, &mut provided_index)
{
if util::is_root_position(next_pos, num_leaves, total_rows) {
calculated_root_hashes.push(next_hash);
continue;
Expand Down
1 change: 1 addition & 0 deletions src/accumulator/stump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ mod test {
}
fn parent_hash(left: &Self, right: &Self) -> Self {
let mut hash = [0; 32];
#[allow(clippy::needless_range_loop)]
for i in 0..32 {
hash[i] = left.0[i] ^ right.0[i];
}
Expand Down
Loading