My objective is to store hash values in the substrate chain. I have declared the storage and the module for it in the following code:
use support::{decl_module, decl_storage, dispatch::Result, ensure, StorageMap};
use system::ensure_signed;
pub trait Trait: balances::Trait {}
decl_storage! {
trait Store for Module<T: Trait> as KittyStorage {
Value: map str => Option<T::AccountId>;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn set_value(origin, value: u64) -> Result {
let sender = ensure_signed(origin)?;
ensure!(!<Value<T>>::exists(value), "key already exists");
<Value<T>>::insert(value, sender);
Ok(())
}
}
}
The code was working fine as expected as long as I was using u64 in the line but I received an error when I changed it to str:
Value: map str => Option<T::AccountId>;
The error is:
error[E0277]: the trait bound `str: _::_parity_scale_codec::EncodeLike` is not satisfied
--> /Users/aviralsrivastava/dev/substrate-package/substrate-node-template/runtime/src/substratekitties.rs:6:1
|
6 | / decl_storage! {
7 | | trait Store for Module<T: Trait> as KittyStorage {
8 | | Value: map str => Option<T::AccountId>;
9 | | }
10 | | }
| |_^ the trait `_::_parity_scale_codec::EncodeLike` is not implemented for `str`
|
I tried reading about it but could not find any other method of storing a string. Although, my string will be of fixed size as it will always be SHA256.
You should be using a hash of known size, so do something like:
type MyHash = [u8; 32];
This would be a 256-bit hash.
Then you can create a storage item:
Value: map MyHash => Option<T::AccountId>;
You can also use the Hash primitive defined in your runtime with T::Hash, which makes it compatible with the default hashing primitives in your runtime. That would look like:
Value: map T::Hash => Option<T::AccountId>;
In Substrate, it is H256 by default (which is basically the same thing as above, but more general as it can change and be redefined by the runtime).
Related
I unfortunately must use sql_query(). However, I'm wondering if there is a way to serialize the database results into a nested struct. I'd like to avoid creating a flattened data type to receive the results from the data and instead use the data struct with nested struct definitions, similar to deserializing json with #[serde(flatten)]
I've attempted this with the following code:
use diesel::*;
use serde::Deserialize;
use diesel::r2d2::{ConnectionManager, PooledConnection};
type DB = diesel::pg::Pg;
type DbConn = PooledConnection<ConnectionManager<PgConnection>>;
diesel::table! {
foo (id) {
id -> Int4,
}
}
diesel::table! {
bar (id) {
id -> Int4,
foo_id -> Int4,
}
}
#[derive(Deserialize, Queryable)]
#[diesel(table_name=foo)]
pub struct Foo {
pub id: i32,
}
#[derive(Deserialize, Queryable, QueryableByName)]
pub struct Nested {
#[sql_type = "Integer"]
pub bar_id: i32,
pub foo: Foo
}
pub fn get_nested(conn: & mut DbConn) {
sql_query("select * from bar join foo on foo.id = bar.foo_id")
.get_results::<Nested>(conn);
}
But it complains
error: Cannot determine the SQL type of foo
--> src/main.rs:30:9
|
30 | pub foo: Foo
| ^^^
|
= help: Your struct must either be annotated with `#[diesel(table_name = foo)]` or have this field annotated with `#[diesel(sql_type = ...)]`
error[E0277]: the trait bound `Untyped: load_dsl::private::CompatibleType<Nested, Pg>` is not satisfied
--> src/main.rs:35:32
|
35 | .get_results::<Nested>(conn);
| ----------- ^^^^ the trait `load_dsl::private::CompatibleType<Nested, Pg>` is not implemented for `Untyped`
| |
| required by a bound introduced by this call
|
= help: the trait `load_dsl::private::CompatibleType<U, DB>` is implemented for `Untyped`
= note: required for `SqlQuery` to implement `LoadQuery<'_, _, Nested>`
note: required by a bound in `get_results`
--> /home/rogers/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.3/src/query_dsl/mod.rs:1695:15
|
1695 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust_test` due to 2 previous errors
[Finished running. Exit status: 101]
Is there a way to serialize the database values into a nested structs when doing raw sql queries in diesel?
To cite from the relevant documentation:
If a field is another struct which implements QueryableByName, instead of a column, you can annotate that struct with #[diesel(embed)]. Then all fields contained by that inner struct are loaded into the embedded struct.
That means that:
Your struct Foo needs to derive QueryableByName as well
The field foo of the Nested struct needs to be annotated with #[diesel(embed)]
I have this code to initialize the metrics registry
use once_cell::sync::Lazy;
pub static REQUEST_COUNTER: Lazy<IntCounter> = Lazy::new(|| {
register_int_counter!("requests_total", "Request counter").expect(REGISTRY_ERR)});
pub static ERROR_COUNTER: Lazy<IntCounter> = Lazy::new(|| {
register_int_counter!("errors_total", "Error counter").expect(REGISTRY_ERR)});
...
pub fn create_registry() -> Registry {
let registry = Registry::new();
registry.register(Box::new(REQUEST_COUNTER.clone())).expect(REGISTRY_ERR);
registry.register(Box::new(ERROR_COUNTER.clone())).expect(REGISTRY_ERR);
...
registry
}
I want to extract the repetitive part into a new function
pub fn create_registry() -> Registry {
...
register_collector(®istry, &REQUEST_COUNTER);
...
registry
}
fn register_collector <T> (registry: &Registry, collector: &Lazy<T>) where T: Collector + Clone {
registry.register(Box::new(collector.clone())).expect(REGISTRY_ERR);
}
but rust compiler shows an error for this function signature:
|
37 | registry.register(Box::new(collector.clone())).expect(REGISTRY_ERR);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Collector` is not implemented for `&once_cell::sync::Lazy<T>`
|
= note: required for the cast to the object type `dyn Collector`
What is the correct signature for "register_collector" function?
register_collector is passed a borrowed Lazy reference, so it needs to be dereferenced with *:
.register(Box::new((*collector).clone()))
Suppose I have a trait representing a pure function; memory has been provided for the outputs, and both inputs and outputs are expected to be serde/bincode encoded. Is it possible to make this do what I want, or restructure things to enable the same end idiomatically?
trait Pure {
fn pure(inputs: &[&[u8]], outputs: &[&mut [u8]]);
}
struct Identity {}
impl Pure for Identity {
fn pure(inputs: &[&[u8]], outputs: &[&mut [u8]]) {
let x: u32 = bincode::deserialize(inputs[0]).expect("input decode failed");
bincode::serialize_into(outputs[0], &x).unwrap();
}
}
makes the compiler complain:
error[E0508]: cannot move out of type `[&mut [u8]]`, a non-copy slice
--> src/main.rs:10:33
|
10 | bincode::serialize_into(outputs[0], &x).unwrap();
| ^^^^^^^^^^
| |
| cannot move out of here
| move occurs because `outputs[_]` has type `&mut [u8]`, which does not implement the `Copy` trait
There are two issues with your code. First, if you want to be able to mutate the inner references, then you must have a mutable outer reference. IOW, your pure function should take a &mut[&mut [u8]] for parameter.
Second, in order to pass the mutable reference to deserialize_into, you need to reborrow it, to make it clear to the compiler that you are not permanently taking it out of output:
trait Pure {
fn pure(inputs: &[&[u8]], outputs: &mut[&mut [u8]]);
// ^^^ add this
}
struct Identity {}
impl Pure for Identity {
fn pure(inputs: &[&[u8]], outputs: &mut[&mut [u8]]) {
// ^^^ add this
let x: u32 = bincode::deserialize(inputs[0]).expect("input decode failed");
bincode::serialize_into(&mut*outputs[0], &x).unwrap();
// ^^^^^ add this
}
}
Playground
I'm building a wrapper around a DLL. This DLL gives me access to a database engine which implements an OOP design pattern. This requires me to create multiple overlapping traits that cover all the functionality:
pub trait CursorStatement { /* ... */ }
pub trait CursorTable { /* ... */ }
pub trait CursorStatementTable { /* ... */ }
...
I want to be able to bring these traits in scope so that I can call the functions without having to list every trait. Right now I'm doing:
mod traittest;
use traittest::*;
fn test() -> Result<(), AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
The problem with use foo::* is that it puts everything from the module into my namespace, which I don't want.
In the example above, I don't have to type traittest::Table or traittest::Cursor, I just have to type Table or Cursor. However, I want to have to prefix those objects with the module name so when I'm reading the code I know where the objects came from. I might want to create a Table object in my local file that is distinguished from the one coming from the module.
I also don't want to have to do the following because if I later have to add a new trait I will have to update a bunch of other source files that depend on this module:
mod traittest;
use traittest::{CursorStatement, CursorStatementTable, CursorTable, /* ... */};
I tried creating a Traits supertrait that would inherit all other traits as shown in Is there any way to create a type alias for multiple traits?, but it doesn't work because I can't implement the trait for anything because there's nothing that would be an implementation of every trait in the file:
pub trait Traits: CursorStatement, CursorTable, CursorStatementHandle, /* ... */ {}
If I could create a named scope for all the traits, that would work, but I can't figure out how to make Rust happy with this idea:
let traits = {
pub trait CursorTable { /* ... */ }
}
It looks like this trait_group macro might do the trick but it's not obvious to me how I could use it to solve my problem.
Here's my entire program
mod traittest {
#[derive(Debug)]
pub struct AceError {
code: u32,
description: String,
}
pub trait CursorTable {
fn get_handle(&self) -> u32; // impl's must write this function
fn fields(&self) -> String {
return format!("(get_handle() -> {})", self.get_handle());
}
}
pub struct Table {
pub handle: u32,
pub table_name: String,
}
pub struct Cursor {
pub handle: u32,
}
impl Table {
pub fn new(handle: u32, table_name: &str) -> Result<Table, AceError> {
let table = Table {
handle: handle,
table_name: table_name.to_string(),
};
return Ok(table);
}
}
impl CursorTable for Table {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
impl CursorTable for Cursor {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
pub trait Traits: CursorTable {} /* super trait to bring all other traits in scope */
}
use traittest::Traits;
fn test() -> Result<(), traittest::AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
and here's the error I get:
warning: unused import: `traittest::Traits`
--> src/main.rs:49:5
|
49 | use traittest::Traits;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0599]: no method named `fields` found for struct `traittest::Table` in the current scope
--> src/main.rs:54:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Table>` here
| the method is available for `std::sync::Arc<traittest::Table>` here
| the method is available for `std::rc::Rc<traittest::Table>` here
...
15 | pub struct Table {
| ---------------- method `fields` not found for this
...
54 | println!("t.fields={}", t.fields());
| ^^^^^^ method not found in `traittest::Table`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
error[E0599]: no method named `fields` found for struct `traittest::Cursor` in the current scope
--> src/main.rs:55:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Cursor>` here
| the method is available for `std::sync::Arc<traittest::Cursor>` here
| the method is available for `std::rc::Rc<traittest::Cursor>` here
...
20 | pub struct Cursor {
| ----------------- method `fields` not found for this
...
55 | println!("c.fields={}", c.fields());
| ^^^^^^ method not found in `traittest::Cursor`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
I finally figured out a solution I can live with, in case anybody else is looking for a solution to this problem.
In your module where you define your traits, create a sub-module with all the traits, like so:
pub mod Traits
{
pub trait CursorTrait
{
fn get_handle ( &self ) -> u32; // impl's must write this function
fn fields ( &self ) -> String
{
return format! ( "(get_handle() -> {})", self.get_handle() );
}
}
}
Now in your other modules, if you want to bring the traits in scope without bringing in the entire module, you can just bring in the submodule, like so:
mod foo; use foo::Traits::*;
I'm working on a toy validator addition module to better understand the workings of the session module. Here is my complete attempt on github.
I've got my code nearly working but I'm running into type-checking errors in my implementation of OnSessionEnding.
impl<T: Trait> OnSessionEnding<T::AccountId> for Module<T> {
fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) -> Option<Vec<T::AccountId>> {
match <QueuedValidator<T>>::get() {
Some(n00b) => {
// Get the list of current validators from the session module
let mut validators = session::Module::<T>::validators();
validators.push(T::ValidatorIdOf::convert(n00b.clone()).unwrap());
Some(validators.into())
}
None => None
}
}
}
// https://github.com/paritytech/substrate/blob/4a17a8aaa5042759d934abb10b1703ffdff7d902/bin/node-template/runtime/src/add_validator.rs#L66-L79
I'm not sure what the type-checker needs to understand that ValidatorId and AccountId are truly the same type as I've declared them to be.
impl session::Trait for Runtime {
// --snip--
type ValidatorId = <Self as system::Trait>::AccountId;
type ValidatorIdOf = ConvertInto;
}
// https://github.com/paritytech/substrate/blob/4a17a8aaa5042759d934abb10b1703ffdff7d902/bin/node-template/runtime/src/lib.rs#L250-L262
The exact error is
error[E0277]: the trait bound `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>: core::convert::From<add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>>` is not satisfied
--> /home/joshy/ProgrammingProjects/substrate/bin/node-template/runtime/src/add_validator.rs:73:10
|
73 | Some(validators.into())
| ^^^^^^^^^^^^^^^^^ the trait `core::convert::From<add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>>` is not implemented for `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>`
|
= note: required because of the requirements on the impl of `core::convert::Into<add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>>` for `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>`
Or without the final .into() it becomes
error[E0308]: mismatched types
--> /home/joshy/ProgrammingProjects/substrate/bin/node-template/runtime/src/add_validator.rs:73:10
|
73 | Some(validators)
| ^^^^^^^^^^ expected palette_system::Trait::AccountId, found pallet_session::Trait::ValidatorId
|
= note: expected type `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>`
found type `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>`
To fix the build above, change the OnSessionEnding's type parameter to T::ValidatorId.
- impl<T: Trait> OnSessionEnding<T::AccountId> for Module<T> {
+ impl<T: Trait> OnSessionEnding<T::ValidatorId> for Module<T> {
Here is the full working implementation
impl<T: Trait> OnSessionEnding<T::ValidatorId> for Module<T> {
fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) -> Option<Vec<T::ValidatorId>> {
match <QueuedValidator<T>>::get() {
Some(n00b) => {
// Get the list of current validators from the session module
let mut validators = session::Module::<T>::validators();
// Add the new validator to the list
//TODO handle the unwrapping better
validators.push(T::ValidatorIdOf::convert(n00b.clone()).unwrap());
// Clear the queued validator from local storage
<QueuedValidator<T>>::kill();
// Return the vector of new validators
Some(validators)
}
None => None
}
}
}
(This answer is courtesy of #sushisource:matrix.org)