Implementing the trait std::convert::AsRef<[u8]> for [u8] does not work

Hey Everyone ! Beginner here! May be something super obvious that I am missing .

Disclaimer : I have already looked at How to implement the trait std::convert::AsRef<[u8]> for generic structure but this situation is different as I have implemented (hopefully correctly) the trait but it still won't compile.

I'm trying to make a merkle tree of hashes. I am using Seahorse and trying to import the merkle tree in the Anchor code :

use std::{cell::RefCell, rc::Rc};
use anchor_spl::{
    associated_token::{self, AssociatedToken},
    token::{self, Mint, Token, TokenAccount},
};
use crate::{id, seahorse_util::*};
use anchor_lang::{prelude::*, solana_program};
use solana_merkle_tree::merkle_tree;

pub trait AsRef {
    fn as_ref(&self) -> &[u8];
}

impl AsRef for [u8]
{
    fn as_ref(&self) -> &[u8] {
       return std::convert::AsRef::as_ref(&self);
    }
}

#[account]
#[derive(Debug, PartialEq, Copy)]
pub struct Calculator {
    pub owner: Pubkey,
    pub display: u8,
    pub hash: [u8; 32]
}

This is the part where I am trying to create a merkle tree

merkle_tree::MerkleTree::new(&mut *calculator.borrow_mut().hash.borrow_mut());

This is the compiler message:

stack@DESKTOP-MLB9OKV:~/desktop/seahorse_anchor_solana/calculator$ anchor build
Warning: cargo-build-bpf is deprecated. Please, use cargo-build-sbf
cargo-build-bpf child: /home/stack/.local/share/solana/install/active_release/bin/cargo-build-sbf --arch bpf
   Compiling calculator v0.1.0 (/mnt/c/Users/Stack/Desktop/seahorse_anchor_solana/calculator/programs/calculator)
error[E0277]: the trait bound `u8: std::convert::AsRef<[u8]>` is not satisfied
   --> programs/calculator/src/dot/program.rs:164:50
    |
164 |                     merkle_tree::MerkleTree::new(&mut *calculator.borrow_mut().hash.borrow_mut());
    |                     ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::AsRef<[u8]>` is not implemented for `u8`
    |                     |
    |                     required by a bound introduced by this call
    |
note: required by a bound in `MerkleTree::new`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `calculator` due to previous error

I have also tried to specifically use

merkle_tree::MerkleTree::new(std::convert::AsRef::as_ref(&calculator.borrow_mut().hash.borrow_mut()));

But with no success.

This error arises even at a string which definately supports AsRef:

merkle_tree::MerkleTree::new(&b"this_string_is_32_chars_long_now");

I don't fully understand your code yet, but a remark:

Here you define your own trait with the name AsRef. It is distinct from std::convert::AsRef. Is that what you intend to do?

Also its signature is different: std::convert::AsRef has one type parameter. (see Playground)

1 Like

Hey, I was trying to implement the solution from the other thread.

What I am trying to do is fix the error with any means necessary.

I tried importing std::convert::AsRef

Same issue arises:

stack@DESKTOP-MLB9OKV:~/desktop/seahorse_anchor_solana/calculator$ anchor build
Warning: cargo-build-bpf is deprecated. Please, use cargo-build-sbf
cargo-build-bpf child: /home/stack/.local/share/solana/install/active_release/bin/cargo-build-sbf --arch bpf
   Compiling calculator v0.1.0 (/mnt/c/Users/Stack/Desktop/seahorse_anchor_solana/calculator/programs/calculator)
error[E0277]: the trait bound `u8: AsRef<[u8]>` is not satisfied
   --> programs/calculator/src/dot/program.rs:146:50
    |
146 |                     merkle_tree::MerkleTree::new(std::convert::AsRef::as_ref(&mut *calculator.borrow_mut().hash.borrow_mut()));
    |                     ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsRef<[u8]>` is not implemented for `u8`
    |                     |
    |                     required by a bound introduced by this call
    |
note: required by a bound in `MerkleTree::new`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `calculator` due to previous error

I shouldn't have to implement AsRef by myself as an implementation exists for [u8] but using it results in the same error

Thanks!

Look at the error message. It is talking about u8, not [u8]. This is probably a simple type mismatch. Do you control/did you write the Merkle tree implementation? If so, you probably incorrectly applied an AsRef<u8> bound, rather than AsRef<[u8]>.

I used the anchor-merkle-tree crate

The constructor for the merkle tree is in merkle_tree.rs line 99:

    pub fn new<T: AsRef<[u8]>>(items: &[T]) -> Self {
        let cap = MerkleTree::calculate_vec_capacity(items.len());
        let mut mt = MerkleTree {
            leaf_count: items.len(),
            nodes: Vec::with_capacity(cap),
        };
...
...

Here the AsRef requires [u8] is that right ?

Are my arguements wrong ?

merkle_tree::MerkleTree::new(&mut *calculator.borrow_mut().hash.borrow_mut());

The constructor wants an argument of type &[&[u8]] (or similar slice of as-ref-slices) and you're providing &[u8].

1 Like

Thanks everyone for replying!

To my surprise this compiles and yields an empty merkle tree:

merkle_tree::MerkleTree::new::<[u8; 0]>(&[]);

Why does this work and compile while this

merkle_tree::MerkleTree::new::(&mut *calculator.borrow_mut().hash.borrow_mut());

does not ?

In the first example you're passing an argument of type &[[u8; 0]]; in the latter you're giving &[u8]. If you specify the generic type explicitly in the second, you'll get a more meaningful error, I expect.

Because [u8; 0] implements AsRef<[u8]>.

It is not the case that the type parameter is always the same as the type you pass to the function. In this case, the type parameter T is not passed to the function; the function expects a &[T] instead. So your empty array in the above call has type &[[u8; 0]].

Found it guys !

merkle_tree::MerkleTree::new::<[u8; 32]>(& [*calculator.borrow_mut().hash.borrow_mut()]);

it need both the <[u8; 32]> and the [*calculator.borrow_mut().hash.borrow_mut()]

Thanks everyone!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.