I'm trying link the substrate tutorial (https://github.com/substrate-developer-hub/substrate-node-template) to some C library. I wrapped the C library to a crate called cfun, which can called by the node layer.
I figured out I can use the marco runtime_interface to export the native interface for my pallets to call. However, although I can compile successfully, the wasm runtime cannot instantiate.
Any idea what is happening?
// node/cfun/src/lib.rs
#![cfg_attr(not(feature = "std"), no_std)]
#[link(name = "test", kind = "static")]
extern "C" {
pub fn double_int(input: i32) -> i32;
pub fn double_uint(input: u32) -> u32;
}
# node/cint/Cargo.toml
[package]
edition = '2018'
name = 'cint'
version = '2.0.1'
[dependencies]
# local dependencies
sp-runtime-interface = { version = "2.0.1", default-features = false}
cfun = { path = '../cfun', default-features = false, version = '2.0.1', optional = true }
[features]
default = ['std']
std = [
'sp-runtime-interface/std',
'cfun',
]
// node/cint/src/lib.rs
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate cfun;
use sp_runtime_interface::runtime_interface;
#[runtime_interface]
pub trait CFunctions {
fn c_double_uint(input: u32) -> u32 {
unsafe {
cfun::double_uint(input)
}
}
}
// pallets/template/src/lib.rs
// import module at the beginning
extern crate cint;
// ...
// modify the original `do_something` function
// from:
// Something::put(something);
// to:
let smt = cint::c_functions::c_double_uint(something);
Something::put(smt);
Edited 1
# pallets/template.Cargo.toml and runtime/Cargo.toml
# path is a bit different, but both included all interfaces
[dependencies]
# ...
sp-runtime-interface = { version = "2.0.1", default-features = false}
cfun = { path = '../../node/cfun', default-features = false, version = '2.0.1', optional = true }
cint = { path = '../../node/cint', default-features = false, version = '2.0.1'}
[features]
default = ['std']
std = [
# ...
'sp-runtime/std',
'cfun',
'cint/std',
]
Repo:
https://github.com/killalau/substrate-node-template/tree/franky
Related
Here is the repo im using as a reference for adding a image:
https://github.com/emilk/egui/blob/master/examples/retained_image/src/main.rs
Im getting this error when trying to draw a image to the screen on this line of code:
date_backdrop.show(ui);
"mismatched types
expected mutable reference &mut egui::ui::Ui
found mutable reference &mut Ui
perhaps two different versions of crate egui are being used?"
dont understand how to fix this issue. still new to rust
here is my code:
use eframe::egui;
use egui_extras::RetainedImage;
struct InitView;
impl eframe::epi::App for InitView {
fn name(&self) -> &str {
"CheckIt"
}
fn update(&mut self,ctx: &eframe::egui::CtxRef,frame: &mut eframe::epi::Frame<'_>) {
let date_backdrop = RetainedImage::from_image_bytes(
"date_backdrop.png",
include_bytes!("date_backdrop.png"),
)
.unwrap();
//background color
let frame = egui::containers::Frame {
fill: egui::Color32::from_rgb(241, 233, 218),
..Default::default()
};
//main window
egui::CentralPanel::default().frame(frame).show(ctx, |ui| {
ui.heading("This is an image:");
date_backdrop.show(ui);
});
}
}
fn main(){
let app: InitView = InitView;
let win_options = eframe::NativeOptions{
initial_window_size: Some(egui::Vec2::new(386.0, 636.0)),
always_on_top: true,
resizable: false,
..Default::default()
};
eframe::run_native(Box::new(app), win_options);
}
Here is my Cargo.toml:
[package]
name = "checkit"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eframe = "0.14.0"
image = { version = "0.24", default-features = false, features = ["png"] }
egui_extras = { version = "0.20.0", features = ["image"] }
As the error tells, you have two incompatible version of egui in the dependency tree: eframe 0.14 pulls in egui 0.14, while egui_extras 0.20 pulls in egui 0.20. When major version is 0, different minor versions are treated as incompatible, therefore the types from them are not interchangable.
As far as I can see, both eframe and egui_extras depend on the same minor version of egui as their own version, so you have to synchronize these two dependencies to use the same minor version. The easiest way is probably to bump eframe to 0.20.
using this github repo as a reference: https://github.com/emilk/egui/blob/master/examples/retained_image/src/main.rs
Im trying to load an image into my frame using the egui_extras::RetainedImage, but it is giving me an error that the function RetainedImage::from_image_bytes cannot be found in RetainedImage.
I have also checked image.rs class to make sure that the function is even there, which it is.
here is my code:
use eframe::{run_native, epi::App, egui, NativeOptions};
use egui_extras::RetainedImage;
struct InitView {
image: RetainedImage,
tint: egui::Color32,
}
impl Default for InitView {
fn default() -> Self {
Self {
image: RetainedImage::from_image_bytes(
"date_backdrop.png",
include_bytes!("date_backdrop.png"),
)
.unwrap(),
tint: egui::Color32::from_rgb(255, 0, 255),
}
}
}
impl App for InitView {
fn name(&self) -> &str {
"CheckIt"
}
fn update(&mut self,ctx: &eframe::egui::CtxRef,frame: &mut eframe::epi::Frame<'_>) {
//background color
let frame = egui::containers::Frame {
fill: egui::Color32::from_rgb(241, 233, 218),
..Default::default()
};
//main window
egui::CentralPanel::default().frame(frame).show(ctx, |ui| {
ui.label("test");
});
}
}
fn main(){
let app: InitView = InitView{..Default::default()};
let win_options = eframe::NativeOptions{
initial_window_size: Some(egui::Vec2::new(386.0, 636.0)),
always_on_top: true,
resizable: false,
..Default::default()
};
run_native(Box::new(app), win_options);
}
what im i doing wrong? im still new to rust
You need to add the image feature.
Edit your Cargo.toml and replace egui_extras with egui_extras = { version = "0.20.0", features = ["image"] } or run cargo add egui_extras -F "image" in your project root directory.
I'm currently trying substrate tutorial, but it got stack. Please give me an advice.
Following the "use macros in a custom pallet" tutorial, I coded lib.rs file like this.
#![cfg_attr(not(feature = "std"), no_std)]
pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_std::vec::Vec; // Step 3.1 will include this in `Cargo.toml`
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
ClaimCreated(T::AccountId, Vec<u8>),
ClaimRevoked(T::AccountId, Vec<u8>),
}
#[pallet::error]
pub enum Error<T> {
ProofAlreadyClaimed,
NoSuchProof,
NotProofOwner,
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::storage]
pub(super) type Proofs<T: Config> = StorageMap<_, Blake2_128Concat, Vec<u8>, (T::AccountId, T::BlockNumber), ValueQuery>;
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000)]
pub fn create_claim(
origin: OriginFor<T>,
proof: Vec<u8>,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
ensure!(!Proofs::<T>::contains_key(&proof), Error::<T>::ProofAlreadyClaimed);
let current_block = <frame_system::Pallet<T>>::block_number();
Proofs::<T>::insert(&proof, (&sender, current_block));
Self::deposit_event(Event::ClaimCreated(sender, proof));
Ok(())
}
#[pallet::weight(10_000)]
pub fn revoke_claim(
origin: OriginFor<T>,
proof: Vec<u8>,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
ensure!(Proofs::<T>::contains_key(&proof),Error::<T>::NoSuchProof);
let (owner, _) = Proofs::<T>::get(&proof);
ensure!(sender == owner, Error::<T>::NotProofOwner);
Proofs::<T>::remove(&proof);
Self::deposit_event(Event::ClaimRevoked(sender, proof));
Ok(())
}
}
}
Cargo.toml file is like this.
[package]
name = "pallet-template"
version = "4.0.0-dev"
description = "FRAME pallet template for defining custom runtime logic."
authors = ["Substrate DevHub <https://github.com/substrate-developer-hub>"]
homepage = "https://substrate.io/"
edition = "2021"
license = "Unlicense"
publish = false
repository = "https://github.com/substrate-developer-hub/substrate-node-template/"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [
"derive",
] }
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
frame-support = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26"}
frame-system = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" }
frame-benchmarking = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", optional = true }
[dev-dependencies]
sp-core = { default-features = false, version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" }
sp-io = { default-features = false, version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" }
sp-runtime = { default-features = false, version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" }
[dependencies.sp-std]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
branch = 'polkadot-v0.9.26'
[features]
default = ["std"]
std = [
"sp-std/std",
"codec/std",
"scale-info/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
And I used command "cargo check -p node-template-runtime". But I got an Error like this.
ensure!(!Proofs::<T>::contains_key(&proof), Error::<T>::ProofAlreadyClaimed);
^^^^^^^^^^^^ function or associated item cannot be called on
`frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds
Proofs::<T>::insert(&proof, (&sender, current_block));
^^^^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds
ensure!(Proofs::<T>::contains_key(&proof),Error::<T>::NoSuchProof);
^^^^^^^^^^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds
let (owner, _) = Proofs::<T>::get(&proof);
^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds
Proofs::<T>::remove(&proof);
^^^^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds
#[pallet::pallet]
^^^^^^ the trait `MaxEncodedLen` is not implemented for `Vec<u8>`
#[pallet::pallet]
^^^^^^ the trait `core::default::Default` is not implemented for `<T as frame_system::Config>::AccountId`
#[pallet::storage]
^^^^^^^ the trait `core::default::Default` is not implemented for `<T as frame_system::Config>::AccountId`
Somebody, Please help me. I beg you. What should I do next??
Now that the PoA is running with multiple Aura validators in my substrate-node-template. How could I configure that reward amount or value for my Aura validators?
I got it working, PoA will reward the validator who created the block using the tip as the sample value for the fees, here are the steps:
Install the pallet_authorship
pallet-authorship = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.23" }
Configure the pallet to get the current author of the block
pub struct AuraAccountAdapter;
impl frame_support::traits::FindAuthor<AccountId> for AuraAccountAdapter {
fn find_author<'a, I>(digests: I) -> Option<AccountId>
where I: 'a + IntoIterator<Item=(frame_support::ConsensusEngineId, &'a [u8])>
{
pallet_aura::AuraAuthorId::<Runtime>::find_author(digests).and_then(|k| {
AccountId::try_from(k.as_ref()).ok()
})
}
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = AuraAccountAdapter;
type UncleGenerations = ();
type FilterUncle = ();
type EventHandler = ();
}
Create OnUnbalanced implementation of Author and DealWithFees
use crate::{Authorship, Balances};
use frame_support::traits::{Imbalance, OnUnbalanced};
use crate::sp_api_hidden_includes_construct_runtime::hidden_include::traits::Currency;
use crate::AccountId;
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
pub struct Author;
impl OnUnbalanced<NegativeImbalance> for Author {
fn on_nonzero_unbalanced(amount: NegativeImbalance) {
if let Some(author) = Authorship::author() {
Balances::resolve_creating(&author, amount);
}
}
}
pub struct DealWithFees;
impl OnUnbalanced<NegativeImbalance> for DealWithFees {
fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
if let Some(fees) = fees_then_tips.next() {
let mut split = fees.ration(80, 20);
if let Some(tips) = fees_then_tips.next() {
// for tips, if any, 80% to treasury, 20% to block author (though this can be anything)
tips.ration_merge_into(80, 20, &mut split);
}
//Treasury::on_unbalanced(split.0);
Author::on_unbalanced(split.1);
}
}
}
Call the implementation in the pallet_transaction_payment tuple OnChargeTransaction
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, crate::impls::DealWithFees>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
}
Also added in my blog: https://hgminerva.wordpress.com/2022/06/21/how-to-pay-the-block-author-validator-on-a-proof-of-authority-poa-consensus-in-substrate/
I wish that enums in Rust can be used like Haskell's productive type. I want to
access a field's value directly
assign a field's value directly or make a clone with the changing value.
Directly means that not using too long pattern matching code, but just could access like let a_size = a.size.
In Haskell:
data TypeAB = A {size::Int, name::String} | B {size::Int, switch::Bool} deriving Show
main = do
let a = A 1 "abc"
let b = B 1 True
print (size a) -- could access a field's value directly
print (name a) -- could access a field's value directly
print (switch b) -- could access a field's value directly
let aa = a{size=2} -- could make a clone directly with the changing value
print aa
I tried two styles of Rust enum definition like
Style A:
#[derive(Debug)]
enum EntryType {
A(TypeA),
B(TypeB),
}
#[derive(Debug)]
struct TypeA {
size: u32,
name: String,
}
#[derive(Debug)]
struct TypeB {
size: u32,
switch: bool,
}
fn main() {
let mut ta = TypeA {
size: 3,
name: "TAB".to_string(),
};
println!("{:?}", &ta);
ta.size = 2;
ta.name = "TCD".to_string();
println!("{:?}", &ta);
let mut ea = EntryType::A(TypeA {
size: 1,
name: "abc".to_string(),
});
let mut eb = EntryType::B(TypeB {
size: 1,
switch: true,
});
let vec_ab = vec![&ea, &eb];
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
// Want to do like `ta.size = 2` for ea
// Want to do like `ta.name = "bcd".to_string()` for ea
// Want to do like `tb.switch = false` for eb
// ????
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
}
Style B:
#[derive(Debug)]
enum TypeCD {
TypeC { size: u32, name: String },
TypeD { size: u32, switch: bool },
}
fn main() {
// NOTE: Rust requires representative struct name before each constructor
// TODO: Check constructor name can be duplicated
let mut c = TypeCD::TypeC {
size: 1,
name: "abc".to_string(),
};
let mut d = TypeCD::TypeD {
size: 1,
switch: true,
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
// Can't access a field's value like
// let c_size = c.size
let c_size = c.size; // [ERROR]: No field `size` on `TypeCD`
let c_name = c.name; // [ERROR]: No field `name` on `TypeCD`
let d_switch = d.switch; // [ERROR]: No field `switch` on `TypeCD`
// Can't change a field's value like
// c.size = 2;
// c.name = "cde".to_string();
// d.switch = false;
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
}
I couldn't access/assign values directly in any style. Do I have to implement functions or a trait just to access a field's value? Is there some way of deriving things to help this situation?
What about style C:
#[derive(Debug)]
enum Color {
Green { name: String },
Blue { switch: bool },
}
#[derive(Debug)]
struct Something {
size: u32,
color: Color,
}
fn main() {
let c = Something {
size: 1,
color: Color::Green {
name: "green".to_string(),
},
};
let d = Something {
size: 2,
color: Color::Blue { switch: true },
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
let _ = c.size;
}
If all variant have something in common, why separate them?
Of course, I need to access not common field too.
This would imply that Rust should define what to do when the actual type at runtime doesn't contain the field you required. So, I don't think Rust would add this one day.
You could do it yourself. It will require some lines of code, but that matches the behavior of your Haskell code. However, I don't think this is the best thing to do. Haskell is Haskell, I think you should code in Rust and not try to code Haskell by using Rust. That a general rule, some feature of Rust come directly from Haskell, but what you want here is very odd in my opinion for Rust code.
#[derive(Debug)]
enum Something {
A { size: u32, name: String },
B { size: u32, switch: bool },
}
impl Something {
fn size(&self) -> u32 {
match self {
Something::A { size, .. } => *size,
Something::B { size, .. } => *size,
}
}
fn name(&self) -> &String {
match self {
Something::A { name, .. } => name,
Something::B { .. } => panic!("Something::B doesn't have name field"),
}
}
fn switch(&self) -> bool {
match self {
Something::A { .. } => panic!("Something::A doesn't have switch field"),
Something::B { switch, .. } => *switch,
}
}
fn new_size(&self, size: u32) -> Something {
match self {
Something::A { name, .. } => Something::A {
size,
name: name.clone(),
},
Something::B { switch, .. } => Something::B {
size,
switch: *switch,
},
}
}
// etc...
}
fn main() {
let a = Something::A {
size: 1,
name: "Rust is not haskell".to_string(),
};
println!("{:?}", a.size());
println!("{:?}", a.name());
let b = Something::B {
size: 1,
switch: true,
};
println!("{:?}", b.switch());
let aa = a.new_size(2);
println!("{:?}", aa);
}
I think there is currently no built-in way of accessing size directly on the enum type. Until then, enum_dispatch or a macro-based solution may help you.