Unknown types found, no types for DepartmentDetails - substrate

I am trying to use struct in substrate
#[derive(PartialEq, Eq, PartialOrd, Ord, Default, Clone, Encode, Decode, RuntimeDebug)]
pub struct DepartmentDetails {
pub name: Vec<u8>,
pub location: Vec<u8>,
pub details: Vec<u8>,
pub departmentid: u128,
}
In decl_stroage
Department get(fn department_name): map hasher(blake2_128_concat) u128 => DepartmentDetails;
Though node runs successfully without error, it give error with polkadotjs app, saying:
Unknown types found, no types for DepartmentDetails
https://substrate.dev/recipes/structs.html

Polkadot-js can only construct and display types that it understands.
See the FAQ here.
For development you can add custom type descriptions in the Settings > Developer tab.
For production you can add type descriptions to your polkadot-js based UI via extending the types as described here.

Related

Tightly Coupling pallet error: ambiguous associated type `Currency` in bounds of `T`

I have following config file, I added schelling game pallet as tightly coupling pallet:
use frame_support::{
traits::{Currency, ExistenceRequirement, Get, ReservableCurrency, WithdrawReasons},
};
#[pallet::config]
pub trait Config: frame_system::Config + schelling_game::Config{
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
type Currency: ReservableCurrency<Self::AccountId>;
type RandomnessSource: Randomness<Self::Hash, Self::BlockNumber>;
}
I have following code in the function:
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(2,2))]
pub fn add_profile_fund(origin: OriginFor<T>, citizenid: u128) -> DispatchResult {
let who = ensure_signed(origin)?;
let deposit = <RegistrationFee<T>>::get();
let imb = T::Currency::withdraw(
&who,
deposit,
WithdrawReasons::TRANSFER,
ExistenceRequirement::AllowDeath,
)?;
It gives error:
ambiguous associated type Currency in bounds of T
ambiguous associated type Currency
note: associated type T could derive from schelling_game::Config
help: use fully qualified syntax to disambiguate: <T as pallet::Config>::Currency
When I add
let imb = <T as frame_system::Config>::Currency::withdraw()
It gives error:
cannot find associated type Currency in trait frame_system::Config
not found in frame_system::Config
Edit:
The error is because I have used currency trait in both the pallet. How can I use currency trait in both pallets?
I think the error/warning message has given you the answer you need 🙂 . Could you try:
let imb = <T as pallet::Config>::Currency::withdraw();
and see if this works?
What I am not sure how is Currency ambiguous, as the associated type is only defined in your pallet and not in System Pallet? But well, if the compiler tells us to do so, let's not argue with it for now.
Update:
oh, I think the pallet module exports the Config trait out and the trait is now accessible as schelling_game::Config also as mentioned in the error message. So there are two names now - pallet::Config and schelling_game::Config and rust compiler treats them as ambiguous, but they are the same thing really.

What are the macros #[pallet::genesis_config] and #[pallet::genesis_build] doing on the sudo pallet?

#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
/// The `AccountId` of the sudo key.
pub key: T::AccountId,
}
#[cfg(feature = "std")]
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { key: Default::default() }
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
<Key<T>>::put(&self.key);
}
}
What is happening here with genesis_config and genesis_build macros here? Some reading seemed to suggest that implement the trait GenesisBuild<T,I = ()> but I am confused as the docs read: "T and I are placeholder for pallet trait and pallet instance."
What are pallet instances? I also assume pallet trait means the Config trait for the sudo pallet. Is it some how related to configuring a unique StorageValue for the Genesis block so that each instance of a running node can verify that the same Account is Root? Can someone help break it down for me.
What are pallet instances?
Pallets can be made instantiable. This means a Pallet can be used multiple times in a runtime. Each instance will use the same code (modulo different configuration through the configuration trait), but the storage will be different for each instance.
See: https://docs.substrate.io/how-to-guides/v3/basics/instantiable-pallets/
I also assume pallet trait means the Config trait for the sudo pallet. Is it some how related to configuring a unique StorageValue for the Genesis block so that each instance of a running node can verify that the same Account is Root? Can someone help break it down for me.
Yes Pallet trait means the Config trait.
The point here with GenesisBuild taking two generic arguments is to support all kinds of Pallets. Every Pallet is configurable through the trait, so the GenesisBuild trait needs to take the Config generic parameter T. Some Pallets can be instantiable, so it also needs to take I.
This all boils down to some Rust "quirks" to support instantiable Pallets that are using the default instance and custom instances and also to support Pallets that don't use any instancing at all.
#[pallet::genesis_build] implements the trait sp_runtime::BuildModuleGenesisStorage which puts the initial state into the pallet's storage at genesis time.
(The pallet can put state into child storage also at that point.)
The pub enum/struct with #[pallet::genesis_config] holds the fields that genesis_build reads in order to set up the storage. For example there may be investors at genesis that need a vesting schedule set up (See the vesting pallet: https://github.com/paritytech/substrate/blob/3cdb30e1ecbafe8a866317d4550c921b4d686869/frame/vesting/src/lib.rs#L231 ). So for the sudo pallet, the genesis_config struct holds the root key which is set here:
GenesisConfig {
sudo: SudoConfig {
// Assign network admin rights.
key: root_key,
},
...
}
( https://github.com/paritytech/substrate/blob/3cdb30e1ecbafe8a866317d4550c921b4d686869/bin/node-template/node/src/chain_spec.rs#L150 )
Docs for genesis_config are here: https://docs.substrate.io/rustdocs/latest/frame_support/attr.pallet.html#genesis-config-palletgenesis_config-optional

Substrate: How to validate the originator of unsigned extrinsics?

I need to be able to identify the source of an unsigned extrinsic for spam prevention purposes. Assume there is a set of known authorities from whom I am willing to accept an unsigned extrinsic. I want to check that the sender of the unsigned extrinsic is a member of this authority set (and that they are who they say they are).
From what I can tell there are a couple of different approaches and I would like to better understand the differences between each and the trade-offs involved.
Add a signature as a call parameter and define ValidateUnsigned.
This approach is used in the ImOnline pallet. Roughly speaking:
decl_module!(
// ...
fn my_unsigned_call(_origin,
args: MyArgs<T>,
authority: T::Authority,
signature: T::Signature) {
// Handle the call
todo!()
}
)
impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
// ...
fn validate_unsigned(
_source: TransactionSource,
call: &Self::Call,
) -> TransactionValidity {
if let Call::my_unsigned_call(args, authority, signature) = call {
// Check the sender is in the approved authority set and verify sig
todo!();
}
}
}
Implement SignedExtension for some metadata associated with the pallet trait. This is touched upon in the docs and seems to be implemented in the TransactionPayment pallet. Implementation would be something like this:
struct SenderInfo<T> {
authority: T::Authority,
signature: T::Signature,
}
impl<T: Config + Send + Sync> SignedExtension for SenderInfo<T>
where
<T as frame_system::Config>::Call: IsSubType<Call<T>>,
{
// ...
fn validate_unsigned(
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize
) -> TransactionValidity {
// validate self.authority and self.signature
}
}
This SignedExtension then needs to be aggregated into the SignedExtra of the runtime. (Right?)
I am tending towards using the second option since it seems cleaner: it doesn't require me to pollute my method signatures with extra information that is not even used in the method call. But would this mean that any transaction submitted to the runtime, signed or unsigned, would need to add this customised SignedExtra?
Are there any other considerations I should be aware of?
I'm working on a very similar thing.
I was able to do so with your approach 1.
Basically I do check two things there:
If payload was signed properly - When you think about it, this will tell you only about the user, but it doesn't check if a user is your authority user.
I do check if this account is on my authorities list
My working example is available here https://github.com/korzewski/jackblock/blob/master/pallets/jackblock/src/lib.rs#L401
Although, this is not perfect because I need to keep a second list of Authorities and add them manually.
Currently I'm trying to refactor it, so my authorities accounts are the same as my validators (Aura pallet). Still looking for a solution so maybe you know how to solve it? Basically how to reuse Aura pallet in my own pallet

How do I constrain associated types on a non-owned trait? [duplicate]

I have this code:
extern crate serde;
use serde::de::DeserializeOwned;
use serde::Serialize;
trait Bar<'a, T: 'a>
where
T: Serialize,
&'a T: DeserializeOwned,
{
}
I would like to write this using an associated type, because the type T is unimportant to the users of this type. I got this far:
trait Bar {
type T: Serialize;
}
I cannot figure out how to specify the other bound.
Ultimately, I want to use a function like this:
extern crate serde_json;
fn test<I: Bar>(t: I::T) -> String {
serde_json::to_string(&t).unwrap()
}
The "correct" solution is to place the bounds on the trait, but referencing the associated type. In this case, you can also use higher ranked trait bounds to handle the reference:
trait Bar
where
Self::T: Serialize,
// ^^^^^^^ Bounds on an associated type
for<'a> &'a Self::T: DeserializeOwned,
// ^^^^^^^^^^^ Higher-ranked trait bounds
{
type T;
}
However, this doesn't work yet.
I believe that you will need to either:
wait for issue 20671 and/or issue 50346 to be fixed.
wait for the generic associated types feature which introduces where clauses on associated types.
In the meantime, the workaround is to duplicate the bound everywhere it's needed:
fn test<I: Bar>(t: I::T) -> String
where
for<'a> &'a I::T: DeserializeOwned,
{
serde_json::to_string(&t).unwrap()
}

Using traits as types in enums

Here's my code:
trait UnaryOperator {
fn apply(&self, expr: Expression) -> Expression;
}
pub enum Expression {
UnaryOp(UnaryOperator, Expression),
Value(i64)
}
Which gives the following errors:
error: the trait 'core::marker::sized' is not implemented for type 'parser::UnaryOperator'
note: 'parser::UnaryOperator' does not have a constant size known at compile-time
I'm not sure how to accomplish what I want. I've tried:
trait UnaryOperator: Sized {
...
}
As well as
pub enum Expression {
UnaryOp(UnaryOperator + Sized, Expression),
...
}
And neither solved the issue.
I've seen ways to possibly accomplish what I want with generics, but then it seems like two expressions with different operators would be different types, but that's not what I want. I want all expressions to be the same type regardless of what the operators are.
Traits do not have a known size - they are unsized. To see why, check this out:
trait AddOne {
fn add_one(&self) -> u8;
}
struct Alpha {
a: u8,
}
struct Beta {
a: [u8; 1024],
}
impl AddOne for Alpha {
fn add_one(&self) -> { 0 }
}
impl AddOne for Beta {
fn add_one(&self) -> { 0 }
}
Both Alpha and Beta implement AddOne, so how big should some arbitrary AddOne be? Oh, and remember that other crates may implement your trait sometime in the future.
That's why you get the first error. There are 3 main solutions (note that none of these solutions immediately fix your problem...):
Use a Box<Trait>. This is kind-of-similar-but-different to languages like Java, where you just accept an interface. This has a known size (a pointer's worth) and owns the trait. This has the downside of requiring an allocation.
trait UnaryOperator {
fn apply(&self, expr: Expression) -> Expression;
}
pub enum Expression {
UnaryOp(Box<UnaryOperator>, Expression),
Value(i64)
}
Use a reference to the trait. This also has a known size (a pointer's worth two pointers' worth, see Matthieu M.'s comment). The downside is that something has to own the object and you need to track the lifetime:
trait UnaryOperator {
fn apply<'a>(&self, expr: Expression<'a>) -> Expression<'a>;
}
pub enum Expression<'a> {
UnaryOp(&'a UnaryOperator, Expression<'a>),
Value(i64)
}
Use a generic. This has a fixed size because each usage of the enum will have been specialized for the specific type. This has the downside of causing code bloat if you have many distinct specializations. Update As you point out, this means that Expression<A> and Expression<B> would have different types. Depending on your usage, this could be a problem. You wouldn't be able to easily create a Vec<Expression<A>> if you had both.
trait UnaryOperator {
fn apply<U>(&self, expr: Expression<U>) -> Expression<U>;
}
pub enum Expression<U>
where U: UnaryOperator
{
UnaryOp(U, Expression<U>),
Value(i64)
}
Now, all of these fail as written because you have a recursive type definition. Let's look at this simplification:
enum Expression {
A(Expression),
B(u8),
}
How big is Expression? Well, it needs to have enough space to hold... an Expression! Which needs to be able to hold an Expression.... you see where this is going.
You need to add some amount of indirection here. Similar concepts to #1 and #2 apply - you can use a Box or a reference to get a fixed size:
enum Expression {
A(Box<Expression>),
B(u8),
}

Resources