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

trie panics with cannot convert a slice of length 29 to FixedBytes<32> with small data #9

Open
ufoscout opened this issue Apr 17, 2024 · 2 comments

Comments

@ufoscout
Copy link

I am trying to replace triehash::ordered_trie_root with an equivalent function based on alloy-trie. Even if it works pretty well, sometimes alloy-trie panics with a cannot convert a slice of length 29 to FixedBytes<32> error. Here is a complete reproducer for the issue:

use std::collections::BTreeMap;

use alloy_primitives::{keccak256, B256};
use alloy_rlp::Encodable;
use alloy_trie::HashBuilder;
use nybbles::Nibbles;

fn triehash_ordered_trie_root<I>(iter: I) -> B256
where
    I: IntoIterator,
    I::Item: AsRef<[u8]>,
{
    struct Keccak256Hasher;
    impl hash_db::Hasher for Keccak256Hasher {
        type Out = B256;
        type StdHasher = plain_hasher::PlainHasher;

        const LENGTH: usize = 32;

        fn hash(x: &[u8]) -> Self::Out {
            keccak256(x)
        }
    }

    triehash::ordered_trie_root::<Keccak256Hasher, _>(iter)
}

fn alloy_ordered_trie_root<I>(iter: I) -> B256
where
    I: IntoIterator,
    I::Item: AsRef<[u8]>,
{

    let hashed = iter
    .into_iter()
    .enumerate()
    .map(|(i, v)| {
        let mut buf = Vec::new();
        i.encode(&mut buf);
        (buf, v)
    })
    .collect::<BTreeMap<_, _>>();

    let mut hb = HashBuilder::default();

    hashed.iter().for_each(|(key, val)| {
        let nibbles = Nibbles::unpack(key);
        hb.add_leaf(nibbles, val.as_ref());
    });

    hb.root()
}

// This fails with error:
// cannot convert a slice of length 29 to FixedBytes<32>
#[test]
fn small_data() {
    let data = &["cake", "pie", "candy"];
    assert_eq!(triehash_ordered_trie_root(data), alloy_ordered_trie_root(data));
}

// This succeeds.
#[test]
fn big_data() {
    let data = &["a_very_big_cake", "a_very_big_pie", "a_lots_of_candies"];
    assert_eq!(triehash_ordered_trie_root(data), alloy_ordered_trie_root(data));
}
@DaniPopes
Copy link
Member

DaniPopes commented Apr 17, 2024

cc @rkrasiuk @klkvr

Should we also add these helpers in this crate?

@0xaatif
Copy link

0xaatif commented Jul 14, 2024

I'm hitting this too, here's a simpler repro:

let mut builder = alloy_trie::HashBuilder::default();
for i in [0x01, 0x02, 0x80] {
    let nibbles = alloy_trie::Nibbles::unpack([i]);
    builder.add_leaf(nibbles, &[])
}
builder.root(); // boom
alloy-trie = "0.4.1"
thread 'main' panicked at /../alloy-trie-0.4.1/src/nodes/branch.rs:164:35:
cannot convert a slice of length 21 to FixedBytes<32>
stack backtrace:
   0: rust_begin_unwind
             at /rustc/../library/std/src/panicking.rs:652:5
   1: core::panicking::panic_fmt
             at /rustc/../library/core/src/panicking.rs:72:14
   2: alloy_primitives::bits::fixed::FixedBytes<_>::from_slice
             at /../alloy-primitives-0.7.7/src/bits/fixed.rs:476:23
   3: alloy_trie::nodes::branch::BranchNodeRef::child_hashes
             at /../alloy-trie-0.4.1/src/nodes/branch.rs:164:35
   4: alloy_trie::hash_builder::HashBuilder::push_branch_node
             at /../alloy-trie-0.4.1/src/hash_builder/mod.rs:314:24
   5: alloy_trie::hash_builder::HashBuilder::update
             at /../alloy-trie-0.4.1/src/hash_builder/mod.rs:279:32
   6: alloy_trie::hash_builder::HashBuilder::root
             at /../alloy-trie-0.4.1/src/hash_builder/mod.rs:137:13
   7: sketchbook::main
             at ./src/main.rs:7:5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants