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

Issues wrapping ethereum types and deriving scale-codec methods #679

Open
drewstone opened this issue Sep 18, 2022 · 2 comments
Open

Issues wrapping ethereum types and deriving scale-codec methods #679

drewstone opened this issue Sep 18, 2022 · 2 comments

Comments

@drewstone
Copy link
Contributor

drewstone commented Sep 18, 2022

I'm trying to implement wrapper types for ethereum_types types in order to provide other traits necessary for making my code compatible with https://github.com/sigp/lighthouse dependencies and Substrate. The following snippet demonstrates my intention.

macro_rules! uint_declare_wrapper_and_serde {
    ($name: ident, $len: expr) => {
        #[derive(
            Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Add, Sub, Mul, Div, Rem,
            AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, Display, From, Into,
            Encode, EncodeLike, Decode, MaxEncodedLen, TypeInfo,
        )]
        // #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
        pub struct $name(pub ethereum_types::$name);

        impl Encodable for $name {
            fn rlp_append(&self, s: &mut RlpStream) {
                <ethereum_types::$name>::rlp_append(&self.0, s);
            }
        }

        impl Decodable for $name {
            fn decode(rlp: &Rlp) -> Result<Self, RlpDecoderError> {
                Ok($name(<ethereum_types::$name>::rlp_derive(rlp)?))
            }
        }
    };
}

uint_declare_wrapper_and_serde!(U64, 1);
uint_declare_wrapper_and_serde!(U128, 2);
uint_declare_wrapper_and_serde!(U256, 4);

Unfortunately, I keep fighting with the compiler who doesn't think that these types can implement Encode/Decode even though I am importing the package with those features. My TOML is below:

ethereum-types = { version = "0.12.1", features = ["codec", "rlp", "num-traits"], default-features = false }

Errors

error[E0599]: no function or associated item named `max_encoded_len` found for struct `ethereum_types::U64` in the current scope
  --> src/lib.rs:62:30
   |
62 |         pub struct $name(pub ethereum_types::$name);
   |                              ^^^^^^^^^^^^^^ function or associated item not found in `ethereum_types::U64`
...
78 | uint_declare_wrapper_and_serde!(U64, 1);
   | --------------------------------------- in this macro invocation
   |
   = help: items from traits can only be used if the trait is in scope
   = note: this error originates in the macro `uint_declare_wrapper_and_serde` (in Nightly builds, run with -Z macro-backtrace for more info)
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   |
4  | use parity_scale_codec::max_encoded_len::MaxEncodedLen;
   |
@drewstone
Copy link
Contributor Author

drewstone commented Sep 18, 2022

A similar thing happens with a trait for HXX types like H64 and H256, sometimes referencing traits not being present even though they are in the lib.rs.

error[E0599]: no function or associated item named `max_encoded_len` found for struct `ethereum_types::U64` in the current scope
  --> src/lib.rs:62:30
   |
62 |         pub struct $name(pub ethereum_types::$name);
   |                              ^^^^^^^^^^^^^^ function or associated item not found in `ethereum_types::U64`
...
78 | uint_declare_wrapper_and_serde!(U64, 1);
   | --------------------------------------- in this macro invocation
   |
   = help: items from traits can only be used if the trait is in scope
   = note: this error originates in the macro `uint_declare_wrapper_and_serde` (in Nightly builds, run with -Z macro-backtrace for more info)
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   |
4  | use parity_scale_codec::max_encoded_len::MaxEncodedLen;
   |

If I try implementing the trait myself:

impl Encode for $name {
    fn encode(&self) -> Vec<u8> {
        self.0.encode()
    }
}

I get the following error as well:

error[E0599]: the method `encode` exists for struct `ethereum_types::H64`, but its trait bounds were not satisfied
   --> src/macros.rs:199:24
    |
199 |                   self.0.encode()
    |                          ^^^^^^ method cannot be called on `ethereum_types::H64` due to unsatisfied trait bounds
    |
   ::: src/lib.rs:27:1
    |
27  |   arr_ethereum_types_wrapper_impl!(H64, 8);
    |   ---------------------------------------- in this macro invocation
    |
   ::: /Users/drew/.cargo/registry/src/github.com-1ecc6299db9ec823/ethereum-types-0.12.1/src/hash.rs:33:1
    |
33  | / construct_fixed_hash! {
34  | |     #[cfg_attr(feature = "codec", derive(scale_info::TypeInfo))]
35  | |     pub struct H64(8);
36  | | }
    | | -
    | | |
    | | doesn't satisfy `<ethereum_types::H64 as Deref>::Target = _`
    | |_doesn't satisfy `ethereum_types::H64: WrapperTypeEncode`
    |   doesn't satisfy `ethereum_types::H64: parity_scale_codec::Encode`
    |
    = note: the following trait bounds were not satisfied:
            `<ethereum_types::H64 as Deref>::Target = _`
            which is required by `ethereum_types::H64: parity_scale_codec::Encode`
            `ethereum_types::H64: WrapperTypeEncode`
            which is required by `ethereum_types::H64: parity_scale_codec::Encode`
    = help: items from traits can only be used if the trait is in scope
    = note: this error originates in the macro `arr_ethereum_types_wrapper_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   --> |src/lib.rs:4:1
    |
4   | use parity_scale_codec::codec::Encode;
    |

@ordian
Copy link
Member

ordian commented Sep 18, 2022

From what I can see, this is a general rust question. The compiler is your friend and it tells you what's wrong:

help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   --> |src/lib.rs:4:1
    |
4   | use parity_scale_codec::codec::Encode;

In your implementation of the macro, you assume that Encode and Decode are in scope. Generally, that's not a good idea as it leads to the subpar developer experience, as you are seeing directly. Unless you're only planning to use this macro only where it's defined, then you'll have to import the required traits in the scope.

Take a look at how codec is implemented in https://github.com/paritytech/parity-common/blob/master/primitive-types/impls/codec/src/lib.rs. Note the $crate::codec::Encode and

#[doc(hidden)]
pub use parity_scale_codec as codec;

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

No branches or pull requests

2 participants