From 4592471e2fd99b65566540c44372f4f1f60c386d Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 15 Jul 2025 18:38:31 +0300 Subject: [PATCH 01/16] introduce sails client for gbuiltin-proxy --- Cargo.lock | 11 ++++++++ Cargo.toml | 1 + rs/Cargo.toml | 1 + rs/src/builtins.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++ rs/src/lib.rs | 2 ++ 5 files changed, 84 insertions(+) create mode 100644 rs/src/builtins.rs diff --git a/Cargo.lock b/Cargo.lock index 31b21859b..d04c28167 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2666,6 +2666,16 @@ dependencies = [ "gear-dlmalloc", ] +[[package]] +name = "gbuiltin-proxy" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2beac2a698e3438d9bc0acd884ea39ef3cd2ee2ed5e07779c1f69812e52cb4c5" +dependencies = [ + "gprimitives", + "parity-scale-codec", +] + [[package]] name = "gclient" version = "1.8.1" @@ -6846,6 +6856,7 @@ dependencies = [ "alloy-sol-types", "convert_case 0.7.1", "futures", + "gbuiltin-proxy", "gclient", "gcore", "gear-core", diff --git a/Cargo.toml b/Cargo.toml index e64c11b90..633836875 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ gclient = "=1.8.1" gcore = "=1.8.1" gear-core = { version = "=1.8.1", default-features = false } gear-core-errors = "=1.8.1" +gbuiltin-proxy = "=1.8.1" gprimitives = { version = "=1.8.1", features = ["codec"] } gstd = "=1.8.1" gtest = "=1.8.1" diff --git a/rs/Cargo.toml b/rs/Cargo.toml index e3e3d4c80..f8cb73ec7 100644 --- a/rs/Cargo.toml +++ b/rs/Cargo.toml @@ -19,6 +19,7 @@ gcore.workspace = true gprimitives.workspace = true gstd = { workspace = true, optional = true } gwasm-builder = { workspace = true, optional = true } +gbuiltin-proxy.workspace = true hashbrown.workspace = true hex.workspace = true keccak-const = { workspace = true, optional = true } diff --git a/rs/src/builtins.rs b/rs/src/builtins.rs new file mode 100644 index 000000000..98783523e --- /dev/null +++ b/rs/src/builtins.rs @@ -0,0 +1,69 @@ +use crate::{ + calls::{ActionIo, Call, Remoting, RemotingAction}, + errors::{Error, Result}, + prelude::{Decode, Encode, Vec}, +}; +use gbuiltin_proxy::{ProxyType, Request as ProxyRequest}; +use gprimitives::ActorId; + +// 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 +const PROXY_BUILTIN_ID: ActorId = ActorId::new([ + 0x82, 0x63, 0xcd, 0x9f, 0xc6, 0x48, 0xe1, 0x01, 0xf1, 0xcd, 0x85, 0x85, 0xdc, 0x0b, 0x19, 0x34, + 0x45, 0xc3, 0x75, 0x0a, 0x63, 0xbf, 0x64, 0xa3, 0x9c, 0xdf, 0x58, 0xde, 0x14, 0x82, 0x62, 0x99, +]); + +pub struct ProxyBuiltin { + remoting: R, +} + +impl ProxyBuiltin { + pub fn new(remoting: R) -> Self { + Self { remoting } + } + + pub fn add_proxy( + &self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call, Args = R::Args> { + let request = ProxyRequest::AddProxy { + delegate, + proxy_type, + }; + RemotingAction::<_, AddProxy>::new(self.remoting.clone(), request) + } +} + +pub struct AddProxy(()); + +impl AddProxy { + pub fn encode_call(delegate: ActorId, proxy_type: ProxyType) -> Vec { + let request = ProxyRequest::AddProxy { + delegate, + proxy_type, + }; + ::encode_call(&request) + } +} + +impl ActionIo for AddProxy { + const ROUTE: &'static [u8] = b""; + type Params = ProxyRequest; + type Reply = Vec; + + fn encode_call(value: &ProxyRequest) -> Vec { + if !matches!(value, ProxyRequest::AddProxy { .. }) { + panic!( + "Invalid param received. Expected `ProxyRequest::AddProxy`, received `{value:?}`" + ); + } + + value.encode() + } + + fn decode_reply(payload: impl AsRef<[u8]>) -> Result { + let mut value = payload.as_ref(); + + Decode::decode(&mut value).map_err(Error::Codec) + } +} diff --git a/rs/src/lib.rs b/rs/src/lib.rs index a30de840d..88b3d658b 100644 --- a/rs/src/lib.rs +++ b/rs/src/lib.rs @@ -38,3 +38,5 @@ pub mod prelude; #[cfg(feature = "ethexe")] pub mod solidity; mod types; + +pub mod builtins; From 54739beafc246c5e975a868d503f18ac8beecb9d Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Thu, 17 Jul 2025 17:26:37 +0300 Subject: [PATCH 02/16] introduce tests for proxy builtin client --- Cargo.lock | 19 +++ Cargo.toml | 2 +- examples/builtins/app/Cargo.toml | 17 +++ examples/builtins/app/build.rs | 3 + examples/builtins/app/src/lib.rs | 44 ++++++ examples/builtins/app/tests/gclient.rs | 60 +++++++++ examples/builtins/client/Cargo.toml | 11 ++ examples/builtins/client/build.rs | 3 + .../client/builtins_example_client.idl | 18 +++ .../client/src/builtins_example_client.rs | 126 ++++++++++++++++++ examples/builtins/client/src/lib.rs | 4 + rs/src/builtins.rs | 96 +++++++++++-- 12 files changed, 391 insertions(+), 12 deletions(-) create mode 100644 examples/builtins/app/Cargo.toml create mode 100644 examples/builtins/app/build.rs create mode 100644 examples/builtins/app/src/lib.rs create mode 100644 examples/builtins/app/tests/gclient.rs create mode 100644 examples/builtins/client/Cargo.toml create mode 100644 examples/builtins/client/build.rs create mode 100644 examples/builtins/client/builtins_example_client.idl create mode 100644 examples/builtins/client/src/builtins_example_client.rs create mode 100644 examples/builtins/client/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d04c28167..7bf176210 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -922,6 +922,25 @@ dependencies = [ "serde", ] +[[package]] +name = "builtins-example-app" +version = "0.8.1" +dependencies = [ + "builtins-example-client", + "gclient", + "log", + "sails-rs", + "tokio", +] + +[[package]] +name = "builtins-example-client" +version = "0.8.1" +dependencies = [ + "builtins-example-app", + "sails-rs", +] + [[package]] name = "bumpalo" version = "3.17.0" diff --git a/Cargo.toml b/Cargo.toml index 633836875..9849c45d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ members = [ "rs/idl-parser", "rs/macros", "rs/macros/core", - "rs/sol-gen", + "rs/sol-gen", "examples/builtins/app", "examples/builtins/client", ] [workspace.dependencies] diff --git a/examples/builtins/app/Cargo.toml b/examples/builtins/app/Cargo.toml new file mode 100644 index 000000000..e35cf9eec --- /dev/null +++ b/examples/builtins/app/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "builtins-example-app" +version.workspace = true +edition.workspace = true + +[dependencies] +sails-rs.workspace = true + +[build-dependencies] +sails-rs = { workspace = true, features = ["wasm-builder"] } + +[dev-dependencies] +tokio = { workspace = true, features = ["rt", "macros"] } +gclient.workspace = true +log.workspace = true +sails-rs = { workspace = true, features = ["gclient"] } +builtins-example-client = { path = "../client" } diff --git a/examples/builtins/app/build.rs b/examples/builtins/app/build.rs new file mode 100644 index 000000000..0b315b06e --- /dev/null +++ b/examples/builtins/app/build.rs @@ -0,0 +1,3 @@ +fn main() { + sails_rs::build_wasm(); +} diff --git a/examples/builtins/app/src/lib.rs b/examples/builtins/app/src/lib.rs new file mode 100644 index 000000000..a1dbeee99 --- /dev/null +++ b/examples/builtins/app/src/lib.rs @@ -0,0 +1,44 @@ +#![no_std] + +use sails_rs::{builtins::*, calls::Call, gstd::calls::GStdRemoting, prelude::*}; + +struct ProxyBroker; + +#[sails_rs::service] +impl ProxyBroker { + #[export] + pub async fn add_proxy(&mut self, delegate: ActorId, proxy_type: ProxyType) -> Vec { + let proxy_builtin_client = ProxyBuiltin::new(GStdRemoting::new()); + + // todo [sab] error type + proxy_builtin_client + .add_proxy(delegate, proxy_type) + .send_recv(PROXY_BUILTIN_ID) + .await + .unwrap_or_else(|e| panic!("failed sending proxy builtin request: {e}")) + } +} + +#[derive(Default)] +pub struct Program(()); + +#[sails_rs::program] +impl Program { + // Program's constructor + pub fn new() -> Self { + Self(()) + } + + // Exposed service + pub fn proxy_broker(&self) -> ProxyBroker { + ProxyBroker + } +} + +#[cfg(not(target_arch = "wasm32"))] +pub use code::WASM_BINARY_OPT as WASM_BINARY; + +#[cfg(not(target_arch = "wasm32"))] +mod code { + include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +} diff --git a/examples/builtins/app/tests/gclient.rs b/examples/builtins/app/tests/gclient.rs new file mode 100644 index 000000000..891c8b732 --- /dev/null +++ b/examples/builtins/app/tests/gclient.rs @@ -0,0 +1,60 @@ +use builtins_example_app::WASM_BINARY; +use builtins_example_client::{ + BuiltinsExampleClientFactory, ProxyBroker, ProxyType, + traits::{BuiltinsExampleClientFactory as _, ProxyBroker as _}, +}; +use gclient::GearApi; +use sails_rs::{ + H256, + builtins::{PROXY_BUILTIN_ID, ProxyBuiltin, ProxyType as SailsProxyType}, + calls::{Activation, Call}, + gclient::calls::GClientRemoting, +}; + +#[tokio::test] +async fn test_raw_proxy_builtin_call() { + let api = GearApi::dev().await.unwrap(); + + let remoting = GClientRemoting::new(api.clone()); + + let proxy = ProxyBuiltin::new(remoting); + let random_actor_id = H256::random().into(); + let res = proxy + .add_proxy(random_actor_id, SailsProxyType::Any) + .send_recv(PROXY_BUILTIN_ID) + .await + .expect("Failed to send proxy request"); + + assert_eq!(res, Vec::::new()); +} + +#[tokio::test] +async fn test_proxy_builtin_program_call() { + let api = GearApi::dev().await.unwrap(); + + let (code_id, _) = api + .upload_code(WASM_BINARY) + .await + .expect("Failed to upload program code"); + + let remoting = GClientRemoting::new(api.clone()); + + let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) + .new() + .send_recv(code_id, b"builtins-example-app") + .await + .expect("Failed program init message"); + + api.transfer_keep_alive(builtins_broker_pid, 100_000_000_000_000_000_000) + .await + .expect("Failed to transfer funds to program"); + + let mut proxy_broker_client = ProxyBroker::new(remoting.clone()); + let resp = proxy_broker_client + .add_proxy(H256::random().into(), ProxyType::Any) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send proxy request"); + + assert_eq!(resp, Vec::::new()); +} diff --git a/examples/builtins/client/Cargo.toml b/examples/builtins/client/Cargo.toml new file mode 100644 index 000000000..508eeef83 --- /dev/null +++ b/examples/builtins/client/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "builtins-example-client" +version.workspace = true +edition.workspace = true + +[dependencies] +sails-rs.workspace = true + +[build-dependencies] +builtins-example-app = { path = "../app" } +sails-rs = { workspace = true, features = ["build"] } \ No newline at end of file diff --git a/examples/builtins/client/build.rs b/examples/builtins/client/build.rs new file mode 100644 index 000000000..b2ebabdfe --- /dev/null +++ b/examples/builtins/client/build.rs @@ -0,0 +1,3 @@ +fn main() { + sails_rs::build_client::(); +} diff --git a/examples/builtins/client/builtins_example_client.idl b/examples/builtins/client/builtins_example_client.idl new file mode 100644 index 000000000..207578974 --- /dev/null +++ b/examples/builtins/client/builtins_example_client.idl @@ -0,0 +1,18 @@ +/// `TypeInfo` implementor copy of `gbuiltin_proxy::ProxyType`. +type ProxyType = enum { + Any, + NonTransfer, + Governance, + Staking, + IdentityJudgement, + CancelProxy, +}; + +constructor { + New : (); +}; + +service ProxyBroker { + AddProxy : (delegate: actor_id, proxy_type: ProxyType) -> vec u8; +}; + diff --git a/examples/builtins/client/src/builtins_example_client.rs b/examples/builtins/client/src/builtins_example_client.rs new file mode 100644 index 000000000..2c4e1ccce --- /dev/null +++ b/examples/builtins/client/src/builtins_example_client.rs @@ -0,0 +1,126 @@ +// Code generated by sails-client-gen. DO NOT EDIT. +#[allow(unused_imports)] +use sails_rs::collections::BTreeMap; +#[allow(unused_imports)] +use sails_rs::{ + String, + calls::{Activation, Call, Query, Remoting, RemotingAction}, + prelude::*, +}; +pub struct BuiltinsExampleClientFactory { + #[allow(dead_code)] + remoting: R, +} +impl BuiltinsExampleClientFactory { + #[allow(unused)] + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} +impl traits::BuiltinsExampleClientFactory for BuiltinsExampleClientFactory { + type Args = R::Args; + fn new(&self) -> impl Activation { + RemotingAction::<_, builtins_example_client_factory::io::New>::new( + self.remoting.clone(), + (), + ) + } +} + +pub mod builtins_example_client_factory { + use super::*; + pub mod io { + use super::*; + use sails_rs::calls::ActionIo; + pub struct New(()); + impl New { + #[allow(dead_code)] + pub fn encode_call() -> Vec { + ::encode_call(&()) + } + } + impl ActionIo for New { + const ROUTE: &'static [u8] = &[12, 78, 101, 119]; + type Params = (); + type Reply = (); + } + } +} +pub struct ProxyBroker { + remoting: R, +} +impl ProxyBroker { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} +impl traits::ProxyBroker for ProxyBroker { + type Args = R::Args; + fn add_proxy( + &mut self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, proxy_broker::io::AddProxy>::new( + self.remoting.clone(), + (delegate, proxy_type), + ) + } +} + +pub mod proxy_broker { + use super::*; + + pub mod io { + use super::*; + use sails_rs::calls::ActionIo; + pub struct AddProxy(()); + impl AddProxy { + #[allow(dead_code)] + pub fn encode_call(delegate: ActorId, proxy_type: super::ProxyType) -> Vec { + ::encode_call(&(delegate, proxy_type)) + } + } + impl ActionIo for AddProxy { + const ROUTE: &'static [u8] = &[ + 44, 80, 114, 111, 120, 121, 66, 114, 111, 107, 101, 114, 32, 65, 100, 100, 80, 114, + 111, 120, 121, + ]; + type Params = (ActorId, super::ProxyType); + type Reply = Vec; + } + } +} +/// `TypeInfo` implementor copy of `gbuiltin_proxy::ProxyType`. +#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] +#[codec(crate = sails_rs::scale_codec)] +#[scale_info(crate = sails_rs::scale_info)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, + IdentityJudgement, + CancelProxy, +} + +pub mod traits { + use super::*; + #[allow(dead_code)] + pub trait BuiltinsExampleClientFactory { + type Args; + #[allow(clippy::new_ret_no_self)] + #[allow(clippy::wrong_self_convention)] + fn new(&self) -> impl Activation; + } + + #[allow(clippy::type_complexity)] + pub trait ProxyBroker { + type Args; + fn add_proxy( + &mut self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call, Args = Self::Args>; + } +} diff --git a/examples/builtins/client/src/lib.rs b/examples/builtins/client/src/lib.rs new file mode 100644 index 000000000..658225503 --- /dev/null +++ b/examples/builtins/client/src/lib.rs @@ -0,0 +1,4 @@ +#![no_std] + +// Incorporate code generated based on the IDL file +include!("builtins_example_client.rs"); diff --git a/rs/src/builtins.rs b/rs/src/builtins.rs index 98783523e..0a8123e6e 100644 --- a/rs/src/builtins.rs +++ b/rs/src/builtins.rs @@ -3,20 +3,90 @@ use crate::{ errors::{Error, Result}, prelude::{Decode, Encode, Vec}, }; -use gbuiltin_proxy::{ProxyType, Request as ProxyRequest}; +use gbuiltin_proxy::{ProxyType as GearProxyType, Request as GearProxyRequest}; use gprimitives::ActorId; +use scale_info::TypeInfo; -// 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 -const PROXY_BUILTIN_ID: ActorId = ActorId::new([ +pub trait BuiltinsRemoting: Remoting {} + +#[cfg(feature = "gstd")] +impl BuiltinsRemoting for crate::gstd::calls::GStdRemoting {} + +#[cfg(feature = "gclient")] +#[cfg(not(target_arch = "wasm32"))] +impl BuiltinsRemoting for crate::gclient::calls::GClientRemoting {} + +// todo [sab] make typeinfo types on gear + +// todo [sab] package must provide the address 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 +pub const PROXY_BUILTIN_ID: ActorId = ActorId::new([ 0x82, 0x63, 0xcd, 0x9f, 0xc6, 0x48, 0xe1, 0x01, 0xf1, 0xcd, 0x85, 0x85, 0xdc, 0x0b, 0x19, 0x34, 0x45, 0xc3, 0x75, 0x0a, 0x63, 0xbf, 0x64, 0xa3, 0x9c, 0xdf, 0x58, 0xde, 0x14, 0x82, 0x62, 0x99, ]); +/// `TypeInfo` implementor copy of `gbuiltin_proxy::Request`. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode, TypeInfo)] +pub enum ProxyRequest { + AddProxy { + delegate: ActorId, + proxy_type: ProxyType, + }, + RemoveProxy { + delegate: ActorId, + proxy_type: ProxyType, + }, +} + +impl From for ProxyRequest { + fn from(request: GearProxyRequest) -> Self { + match request { + GearProxyRequest::AddProxy { + delegate, + proxy_type, + } => Self::AddProxy { + delegate, + proxy_type: proxy_type.into(), + }, + GearProxyRequest::RemoveProxy { + delegate, + proxy_type, + } => Self::RemoveProxy { + delegate, + proxy_type: proxy_type.into(), + }, + } + } +} + +/// `TypeInfo` implementor copy of `gbuiltin_proxy::ProxyType`. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode, TypeInfo)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, + IdentityJudgement, + CancelProxy, +} + +impl From for ProxyType { + fn from(proxy_type: GearProxyType) -> Self { + match proxy_type { + GearProxyType::Any => Self::Any, + GearProxyType::NonTransfer => Self::NonTransfer, + GearProxyType::Governance => Self::Governance, + GearProxyType::Staking => Self::Staking, + GearProxyType::IdentityJudgement => Self::IdentityJudgement, + GearProxyType::CancelProxy => Self::CancelProxy, + } + } +} + pub struct ProxyBuiltin { remoting: R, } -impl ProxyBuiltin { +impl ProxyBuiltin { pub fn new(remoting: R) -> Self { Self { remoting } } @@ -24,11 +94,11 @@ impl ProxyBuiltin { pub fn add_proxy( &self, delegate: ActorId, - proxy_type: ProxyType, + proxy_type: impl Into, ) -> impl Call, Args = R::Args> { let request = ProxyRequest::AddProxy { delegate, - proxy_type, + proxy_type: proxy_type.into(), }; RemotingAction::<_, AddProxy>::new(self.remoting.clone(), request) } @@ -37,10 +107,10 @@ impl ProxyBuiltin { pub struct AddProxy(()); impl AddProxy { - pub fn encode_call(delegate: ActorId, proxy_type: ProxyType) -> Vec { + pub fn encode_call(delegate: ActorId, proxy_type: impl Into) -> Vec { let request = ProxyRequest::AddProxy { delegate, - proxy_type, + proxy_type: proxy_type.into(), }; ::encode_call(&request) } @@ -54,7 +124,7 @@ impl ActionIo for AddProxy { fn encode_call(value: &ProxyRequest) -> Vec { if !matches!(value, ProxyRequest::AddProxy { .. }) { panic!( - "Invalid param received. Expected `ProxyRequest::AddProxy`, received `{value:?}`" + "internal error: invalid param received. Expected `ProxyRequest::AddProxy`, received: {value:?}" ); } @@ -62,8 +132,12 @@ impl ActionIo for AddProxy { } fn decode_reply(payload: impl AsRef<[u8]>) -> Result { - let mut value = payload.as_ref(); + let value = payload.as_ref(); + if !value.is_empty() { + // todo [sab] change to error type + panic!("Invalid reply received. Expected empty payload, received `{value:?}`"); + } - Decode::decode(&mut value).map_err(Error::Codec) + Ok(Default::default()) } } From e0641c55d1bc60125b808370443ebef20f7f670f Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Fri, 18 Jul 2025 18:02:57 +0300 Subject: [PATCH 03/16] introduce sails-typed client for other builtins --- Cargo.lock | 52 ++++++ Cargo.toml | 3 + examples/builtins/app/tests/gclient.rs | 8 + rs/Cargo.toml | 3 + rs/src/builtins/bls381.rs | 210 ++++++++++++++++++++++ rs/src/builtins/mod.rs | 99 ++++++++++ rs/src/{builtins.rs => builtins/proxy.rs} | 102 +++-------- rs/src/builtins/staking.rs | 150 ++++++++++++++++ 8 files changed, 552 insertions(+), 75 deletions(-) create mode 100644 rs/src/builtins/bls381.rs create mode 100644 rs/src/builtins/mod.rs rename rs/src/{builtins.rs => builtins/proxy.rs} (55%) create mode 100644 rs/src/builtins/staking.rs diff --git a/Cargo.lock b/Cargo.lock index 7bf176210..49ac0a599 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -383,6 +383,20 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "ark-scale" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "ark-serialize" version = "0.4.2" @@ -2685,6 +2699,31 @@ dependencies = [ "gear-dlmalloc", ] +[[package]] +name = "gbuiltin-bls381" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490015fd6c0b7a2cfd96257a3ee71bd636ad1cc89a73c2f6f62e419a3ecad8f3" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-scale", + "ark-serialize", + "parity-scale-codec", +] + +[[package]] +name = "gbuiltin-eth-bridge" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "370e03a4190a34bbe99ab6736dc162d4c08c6a69cec8deffcd35ac7fc9f8aa82" +dependencies = [ + "gprimitives", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "gbuiltin-proxy" version = "1.8.1" @@ -2695,6 +2734,16 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "gbuiltin-staking" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa90eb350f6bbaff596fed23833a892f28871c69de0648e59f93616c473c6e64" +dependencies = [ + "gprimitives", + "parity-scale-codec", +] + [[package]] name = "gclient" version = "1.8.1" @@ -6875,7 +6924,10 @@ dependencies = [ "alloy-sol-types", "convert_case 0.7.1", "futures", + "gbuiltin-bls381", + "gbuiltin-eth-bridge", "gbuiltin-proxy", + "gbuiltin-staking", "gclient", "gcore", "gear-core", diff --git a/Cargo.toml b/Cargo.toml index 9849c45d4..634ed593c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,9 @@ gcore = "=1.8.1" gear-core = { version = "=1.8.1", default-features = false } gear-core-errors = "=1.8.1" gbuiltin-proxy = "=1.8.1" +gbuiltin-staking = "=1.8.1" +gbuiltin-eth-bridge = "=1.8.1" +gbuiltin-bls381 = "=1.8.1" gprimitives = { version = "=1.8.1", features = ["codec"] } gstd = "=1.8.1" gtest = "=1.8.1" diff --git a/examples/builtins/app/tests/gclient.rs b/examples/builtins/app/tests/gclient.rs index 891c8b732..5412f7555 100644 --- a/examples/builtins/app/tests/gclient.rs +++ b/examples/builtins/app/tests/gclient.rs @@ -26,6 +26,14 @@ async fn test_raw_proxy_builtin_call() { .expect("Failed to send proxy request"); assert_eq!(res, Vec::::new()); + + let res = proxy + .remove_proxy(random_actor_id, SailsProxyType::Any) + .send_recv(PROXY_BUILTIN_ID) + .await + .expect("Failed to send proxy request"); + + assert_eq!(res, Vec::::new()); } #[tokio::test] diff --git a/rs/Cargo.toml b/rs/Cargo.toml index f8cb73ec7..539078336 100644 --- a/rs/Cargo.toml +++ b/rs/Cargo.toml @@ -20,6 +20,9 @@ gprimitives.workspace = true gstd = { workspace = true, optional = true } gwasm-builder = { workspace = true, optional = true } gbuiltin-proxy.workspace = true +gbuiltin-staking.workspace = true +gbuiltin-eth-bridge.workspace = true +gbuiltin-bls381.workspace = true hashbrown.workspace = true hex.workspace = true keccak-const = { workspace = true, optional = true } diff --git a/rs/src/builtins/bls381.rs b/rs/src/builtins/bls381.rs new file mode 100644 index 000000000..4f9b42cb6 --- /dev/null +++ b/rs/src/builtins/bls381.rs @@ -0,0 +1,210 @@ +use crate::{ + ActorId, + builtins::{BuiltinsRemoting, builtin_action}, + calls::{ActionIo, Call, RemotingAction}, + errors::{Error, Result}, + prelude::{Decode, Encode, TypeInfo, Vec}, +}; +use gbuiltin_bls381::{Request as GearBls381Request, Response as GearBls381Response}; + +// todo [sab] make typeinfo types on gear +// todo [sab] package must provide the address 0x6b6e292c382945e80bf51af2ba7fe9f458dcff81ae6075c46f9095e1bbecdc37 +pub const BLS381_BUILTIN_ID: ActorId = ActorId::new([ + 0x6b, 0x6e, 0x29, 0x2c, 0x38, 0x29, 0x45, 0xe8, 0x0b, 0xf5, 0x1a, 0xf2, 0xba, 0x7f, 0xe9, 0xf4, + 0x58, 0xdc, 0xff, 0x81, 0xae, 0x60, 0x75, 0xc4, 0x6f, 0x90, 0x95, 0xe1, 0xbb, 0xec, 0xdc, 0x37, +]); + +builtin_action!( + Bls381Request, + Bls381Builtin, + MultiMillerLoop { a: Vec, b: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + FinalExponentiation { f: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + MultiScalarMultiplicationG1 { bases: Vec, scalars: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + MultiScalarMultiplicationG2 { bases: Vec, scalars: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + ProjectiveMultiplicationG1 { base: Vec, scalar: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + ProjectiveMultiplicationG2 { base: Vec, scalar: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + AggregateG1 { points: Vec } => Bls381Response +); + +builtin_action!( + Bls381Request, + Bls381Builtin, + MapToG2Affine { message: Vec } => Bls381Response +); + +pub struct Bls381Builtin { + remoting: R, +} + +impl Bls381Builtin { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} + +/// `TypeInfo` implementor copy of `gbuiltin_bls381::Request`. +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] +pub enum Bls381Request { + /// Request to pairing multi Miller loop for *BLS12-381*. + /// + /// Encoded: + /// - `a`: [`ArkScale>`]. + /// - `b`: [`ArkScale>`]. + #[codec(index = 0)] + MultiMillerLoop { a: Vec, b: Vec }, + + /// Request to pairing final exponentiation for *BLS12-381*. + /// + /// Encoded: [`ArkScale<`]. + #[codec(index = 1)] + FinalExponentiation { f: Vec }, + + /// Request to multi scalar multiplication on *G1* for *BLS12-381* + /// + /// Encoded: + /// - `bases`: [`ArkScale>`]. + /// - `scalars`: [`ArkScale>`]. + #[codec(index = 2)] + MultiScalarMultiplicationG1 { bases: Vec, scalars: Vec }, + + /// Request to multi scalar multiplication on *G2* for *BLS12-381* + /// + /// Encoded: + /// - `bases`: [`ArkScale>`]. + /// - `scalars`: [`ArkScale>`]. + #[codec(index = 3)] + MultiScalarMultiplicationG2 { bases: Vec, scalars: Vec }, + + /// Request to projective multiplication on *G1* for *BLS12-381*. + /// + /// Encoded: + /// - `base`: [`ArkScaleProjective`]. + /// - `scalar`: [`ArkScale>`]. + #[codec(index = 4)] + ProjectiveMultiplicationG1 { base: Vec, scalar: Vec }, + + /// Request to projective multiplication on *G2* for *BLS12-381*. + /// + /// Encoded: + /// - `base`: [`ArkScaleProjective`]. + /// - `scalar`: [`ArkScale>`]. + #[codec(index = 5)] + ProjectiveMultiplicationG2 { base: Vec, scalar: Vec }, + + /// Request to aggregate *G1* points for *BLS12-381*. + /// + /// Encoded: [`ArkScale>`]. + #[codec(index = 6)] + AggregateG1 { points: Vec }, + + /// Request to map an arbitrary message to *G2Affine* point for *BLS12-381*. + /// + /// Raw message bytes to map. + #[codec(index = 7)] + MapToG2Affine { message: Vec }, +} + +impl From for Bls381Request { + fn from(request: GearBls381Request) -> Self { + match request { + GearBls381Request::MultiMillerLoop { a, b } => Self::MultiMillerLoop { a, b }, + GearBls381Request::FinalExponentiation { f } => Self::FinalExponentiation { f }, + GearBls381Request::MultiScalarMultiplicationG1 { bases, scalars } => { + Self::MultiScalarMultiplicationG1 { bases, scalars } + } + GearBls381Request::MultiScalarMultiplicationG2 { bases, scalars } => { + Self::MultiScalarMultiplicationG2 { bases, scalars } + } + GearBls381Request::ProjectiveMultiplicationG1 { base, scalar } => { + Self::ProjectiveMultiplicationG1 { base, scalar } + } + GearBls381Request::ProjectiveMultiplicationG2 { base, scalar } => { + Self::ProjectiveMultiplicationG2 { base, scalar } + } + GearBls381Request::AggregateG1 { points } => Self::AggregateG1 { points }, + GearBls381Request::MapToG2Affine { message } => Self::MapToG2Affine { message }, + } + } +} + +/// `TypeInfo` implementor copy of `gbuiltin_bls381::Response`. +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] +pub enum Bls381Response { + /// Result of the multi Miller loop, encoded: [`ArkScale`]. + #[codec(index = 0)] + MultiMillerLoop(Vec), + /// Result of the final exponentiation, encoded: [`ArkScale`]. + #[codec(index = 1)] + FinalExponentiation(Vec), + /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. + #[codec(index = 2)] + MultiScalarMultiplicationG1(Vec), + /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. + #[codec(index = 3)] + MultiScalarMultiplicationG2(Vec), + /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. + #[codec(index = 4)] + ProjectiveMultiplicationG1(Vec), + /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. + #[codec(index = 5)] + ProjectiveMultiplicationG2(Vec), + /// Result of the aggregation, encoded: [`ArkScale`]. + #[codec(index = 6)] + AggregateG1(Vec), + /// Result of the mapping, encoded: [`ArkScale`]. + #[codec(index = 7)] + MapToG2Affine(Vec), +} + +impl From for Bls381Response { + fn from(response: GearBls381Response) -> Self { + match response { + GearBls381Response::MultiMillerLoop(value) => Self::MultiMillerLoop(value), + GearBls381Response::FinalExponentiation(value) => Self::FinalExponentiation(value), + GearBls381Response::MultiScalarMultiplicationG1(value) => { + Self::MultiScalarMultiplicationG1(value) + } + GearBls381Response::MultiScalarMultiplicationG2(value) => { + Self::MultiScalarMultiplicationG2(value) + } + GearBls381Response::ProjectiveMultiplicationG1(value) => { + Self::ProjectiveMultiplicationG1(value) + } + GearBls381Response::ProjectiveMultiplicationG2(value) => { + Self::ProjectiveMultiplicationG2(value) + } + GearBls381Response::AggregateG1(value) => Self::AggregateG1(value), + GearBls381Response::MapToG2Affine(value) => Self::MapToG2Affine(value), + } + } +} diff --git a/rs/src/builtins/mod.rs b/rs/src/builtins/mod.rs new file mode 100644 index 000000000..e851ecf34 --- /dev/null +++ b/rs/src/builtins/mod.rs @@ -0,0 +1,99 @@ +mod proxy; +mod staking; +mod bls381; + +pub use proxy::*; +pub use staking::*; +pub use bls381::*; + +use crate::calls::Remoting; + +pub trait BuiltinsRemoting: Remoting {} + +#[cfg(feature = "gstd")] +impl BuiltinsRemoting for crate::gstd::calls::GStdRemoting {} + +#[cfg(feature = "gclient")] +#[cfg(not(target_arch = "wasm32"))] +impl BuiltinsRemoting for crate::gclient::calls::GClientRemoting {} + +macro_rules! builtin_action { + ( + $enum_name:ident, + $builtin_name:ident, + $variant:ident $( { $($field:ident : $field_type:ty),* $(,)? } )? + $( => $reply_ty:ty )? + ) => { + pub struct $variant(()); + + impl ActionIo for $variant { + const ROUTE: &'static [u8] = b""; + type Params = $enum_name; + type Reply = builtin_action!(@reply_type $( $reply_ty )?); + + fn encode_call(value: &$enum_name) -> Vec { + builtin_action!(@match_variant value, $enum_name, $variant $(, { $($field),* })?); + value.encode() + } + + fn decode_reply(payload: impl AsRef<[u8]>) -> Result { + let value = payload.as_ref(); + builtin_action!(@decode_body value $( $reply_ty )?) + } + } + + impl $builtin_name { + paste::item! { + pub fn [<$variant:snake>]( + &self + $(, $($field : $field_type),* )? + ) -> impl Call::Reply, Args = R::Args> { + let request = $enum_name::$variant $( { $($field),* } )?; + RemotingAction::<_, $variant>::new(self.remoting.clone(), request) + } + } + } + }; + + // Helper arm: extract reply type or default + (@reply_type $reply_ty:ty) => { $reply_ty }; + (@reply_type) => { Vec }; + + // Helper: Match variant with fields + (@match_variant $value:ident, $enum_name:ident, $variant:ident, { $($field:ident),* }) => { + if !matches!($value, $enum_name::$variant { .. }) { + panic!( + "internal error: invalid param received. Expected `{}::{}`, received: {:?}", + stringify!($enum_name), stringify!($variant), $value + ); + } + }; + + // Helper: Match unit variant + (@match_variant $value:ident, $enum_name:ident, $variant:ident) => { + if !matches!($value, $enum_name::$variant) { + panic!( + "internal error: invalid param received. Expected `{}::{}`, received: {:?}", + stringify!($enum_name), stringify!($variant), $value + ); + } + }; + + // Helper arm: decode body based on presence of reply type + (@decode_body $value:ident $reply_ty:ty) => {{ + let mut val = $value; + <$reply_ty as Decode>::decode(&mut val).map_err(Error::Codec) + }}; + (@decode_body $value:ident) => {{ + if !$value.is_empty() { + // todo [sab] change to error type + panic!( + "internal error: expected empty reply for unit variant, received: {:?}", + $value + ); + } + Ok(Default::default()) + }}; +} + +pub(crate) use builtin_action; diff --git a/rs/src/builtins.rs b/rs/src/builtins/proxy.rs similarity index 55% rename from rs/src/builtins.rs rename to rs/src/builtins/proxy.rs index 0a8123e6e..5bbc63e50 100644 --- a/rs/src/builtins.rs +++ b/rs/src/builtins/proxy.rs @@ -1,29 +1,41 @@ use crate::{ - calls::{ActionIo, Call, Remoting, RemotingAction}, - errors::{Error, Result}, - prelude::{Decode, Encode, Vec}, + ActorId, + builtins::{BuiltinsRemoting, builtin_action}, + calls::{ActionIo, Call, RemotingAction}, + errors::Result, + prelude::{Decode, Encode, TypeInfo, Vec}, }; use gbuiltin_proxy::{ProxyType as GearProxyType, Request as GearProxyRequest}; -use gprimitives::ActorId; -use scale_info::TypeInfo; - -pub trait BuiltinsRemoting: Remoting {} - -#[cfg(feature = "gstd")] -impl BuiltinsRemoting for crate::gstd::calls::GStdRemoting {} - -#[cfg(feature = "gclient")] -#[cfg(not(target_arch = "wasm32"))] -impl BuiltinsRemoting for crate::gclient::calls::GClientRemoting {} // todo [sab] make typeinfo types on gear - // todo [sab] package must provide the address 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 pub const PROXY_BUILTIN_ID: ActorId = ActorId::new([ 0x82, 0x63, 0xcd, 0x9f, 0xc6, 0x48, 0xe1, 0x01, 0xf1, 0xcd, 0x85, 0x85, 0xdc, 0x0b, 0x19, 0x34, 0x45, 0xc3, 0x75, 0x0a, 0x63, 0xbf, 0x64, 0xa3, 0x9c, 0xdf, 0x58, 0xde, 0x14, 0x82, 0x62, 0x99, ]); +builtin_action! { + ProxyRequest, + ProxyBuiltin, + AddProxy { delegate: ActorId, proxy_type: ProxyType } +} + +builtin_action! { + ProxyRequest, + ProxyBuiltin, + RemoveProxy { delegate: ActorId, proxy_type: ProxyType } +} + +pub struct ProxyBuiltin { + remoting: R, +} + +impl ProxyBuiltin { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} + /// `TypeInfo` implementor copy of `gbuiltin_proxy::Request`. #[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode, TypeInfo)] pub enum ProxyRequest { @@ -81,63 +93,3 @@ impl From for ProxyType { } } } - -pub struct ProxyBuiltin { - remoting: R, -} - -impl ProxyBuiltin { - pub fn new(remoting: R) -> Self { - Self { remoting } - } - - pub fn add_proxy( - &self, - delegate: ActorId, - proxy_type: impl Into, - ) -> impl Call, Args = R::Args> { - let request = ProxyRequest::AddProxy { - delegate, - proxy_type: proxy_type.into(), - }; - RemotingAction::<_, AddProxy>::new(self.remoting.clone(), request) - } -} - -pub struct AddProxy(()); - -impl AddProxy { - pub fn encode_call(delegate: ActorId, proxy_type: impl Into) -> Vec { - let request = ProxyRequest::AddProxy { - delegate, - proxy_type: proxy_type.into(), - }; - ::encode_call(&request) - } -} - -impl ActionIo for AddProxy { - const ROUTE: &'static [u8] = b""; - type Params = ProxyRequest; - type Reply = Vec; - - fn encode_call(value: &ProxyRequest) -> Vec { - if !matches!(value, ProxyRequest::AddProxy { .. }) { - panic!( - "internal error: invalid param received. Expected `ProxyRequest::AddProxy`, received: {value:?}" - ); - } - - value.encode() - } - - fn decode_reply(payload: impl AsRef<[u8]>) -> Result { - let value = payload.as_ref(); - if !value.is_empty() { - // todo [sab] change to error type - panic!("Invalid reply received. Expected empty payload, received `{value:?}`"); - } - - Ok(Default::default()) - } -} diff --git a/rs/src/builtins/staking.rs b/rs/src/builtins/staking.rs new file mode 100644 index 000000000..7d6ead81f --- /dev/null +++ b/rs/src/builtins/staking.rs @@ -0,0 +1,150 @@ +use crate::{ + ActorId, + builtins::{BuiltinsRemoting, builtin_action}, + calls::{ActionIo, Call, RemotingAction}, + errors::Result, + prelude::{Decode, Encode, TypeInfo, Vec}, +}; +use gbuiltin_staking::{Request as GearStakingRequest, RewardAccount as GearRewardAccount}; + +// todo [sab] package must provide the address 77f65ef190e11bfecb8fc8970fd3749e94bed66a23ec2f7a3623e785d0816761 +pub const STAKING_BUILTIN_ID: ActorId = ActorId::new([ + 0x77, 0xf6, 0x5e, 0xf1, 0x90, 0xe1, 0x1b, 0xfe, 0xcb, 0x8f, 0xc8, 0x97, 0x0f, 0xd3, 0x74, 0x9e, + 0x94, 0xbe, 0xd6, 0x6a, 0x23, 0xec, 0x2f, 0x7a, 0x36, 0x23, 0xe7, 0x85, 0xd0, 0x81, 0x67, 0x61, +]); + +builtin_action!( + StakingRequest, + StakingBuiltin, + Bond { + value: u128, + payee: RewardAccount + } +); + +builtin_action!(StakingRequest, StakingBuiltin, BondExtra { value: u128 }); + +builtin_action!(StakingRequest, StakingBuiltin, Unbond { value: u128 }); + +builtin_action!( + StakingRequest, + StakingBuiltin, + WithdrawUnbonded { + num_slashing_spans: u32 + } +); + +builtin_action!( + StakingRequest, + StakingBuiltin, + Nominate { targets: Vec } +); + +builtin_action!(StakingRequest, StakingBuiltin, Chill); + +builtin_action!( + StakingRequest, + StakingBuiltin, + PayoutStakers { + validator_stash: ActorId, + era: u32 + } +); + +builtin_action!(StakingRequest, StakingBuiltin, Rebond { value: u128 }); + +builtin_action!( + StakingRequest, + StakingBuiltin, + SetPayee { + payee: RewardAccount + } +); + +pub struct StakingBuiltin { + remoting: R, +} + +impl StakingBuiltin { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} + +/// `TypeInfo` implementor copy of `gbuiltin_staking::Request`. +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub enum StakingRequest { + /// Bond up to the `value` from the sender to self as the controller. + Bond { value: u128, payee: RewardAccount }, + /// Add up to the `value` to the sender's bonded amount. + BondExtra { value: u128 }, + /// Unbond up to the `value` to allow withdrawal after undonding period. + Unbond { value: u128 }, + /// Withdraw unbonded chunks for which undonding period has elapsed. + WithdrawUnbonded { num_slashing_spans: u32 }, + /// Add sender as a nominator of `targets` or update the existing targets. + Nominate { targets: Vec }, + /// Declare intention to [temporarily] stop nominating while still having funds bonded. + Chill, + /// Request stakers payout for the given era. + PayoutStakers { validator_stash: ActorId, era: u32 }, + /// Rebond a portion of the sender's stash scheduled to be unlocked. + Rebond { value: u128 }, + /// Set the reward destination. + SetPayee { payee: RewardAccount }, +} + +impl From for StakingRequest { + fn from(value: GearStakingRequest) -> Self { + match value { + GearStakingRequest::Bond { value, payee } => { + let payee = payee.into(); + StakingRequest::Bond { value, payee } + } + GearStakingRequest::BondExtra { value } => StakingRequest::BondExtra { value }, + GearStakingRequest::Unbond { value } => StakingRequest::Unbond { value }, + GearStakingRequest::WithdrawUnbonded { num_slashing_spans } => { + StakingRequest::WithdrawUnbonded { num_slashing_spans } + } + GearStakingRequest::Nominate { targets } => StakingRequest::Nominate { targets }, + GearStakingRequest::Chill => StakingRequest::Chill, + GearStakingRequest::PayoutStakers { + validator_stash, + era, + } => StakingRequest::PayoutStakers { + validator_stash, + era, + }, + GearStakingRequest::Rebond { value } => StakingRequest::Rebond { value }, + GearStakingRequest::SetPayee { payee } => { + let payee = payee.into(); + StakingRequest::SetPayee { payee } + } + } + } +} + +/// `TypeInfo` implementor copy of `gbuiltin_staking::RewardAccount`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub enum RewardAccount { + /// Pay rewards to the sender's account and increase the amount at stake. + Staked, + /// Pay rewards to the sender's account (usually, the one derived from `program_id`) + /// without increasing the amount at stake. + Program, + /// Pay rewards to a custom account. + Custom(ActorId), + /// Opt for not receiving any rewards at all. + None, +} + +impl From for RewardAccount { + fn from(value: GearRewardAccount) -> Self { + match value { + GearRewardAccount::Staked => RewardAccount::Staked, + GearRewardAccount::Program => RewardAccount::Program, + GearRewardAccount::Custom(account) => RewardAccount::Custom(account), + GearRewardAccount::None => RewardAccount::None, + } + } +} From 5c782af17b75e22680a0fb8aea905da97be0d2c6 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 21 Jul 2025 17:13:46 +0300 Subject: [PATCH 04/16] Define remotings for all builtins, add all builtin brokers, restructure --- examples/builtins/app/src/bls381.rs | 173 +++++ examples/builtins/app/src/eth_bridge.rs | 21 + examples/builtins/app/src/lib.rs | 43 +- examples/builtins/app/src/proxy.rs | 36 + examples/builtins/app/src/staking.rs | 109 +++ examples/builtins/app/tests/extrinsic.rs | 33 + .../app/tests/{gclient.rs => program.rs} | 31 +- examples/builtins/client/build.rs | 2 +- .../client/builtins_example_client.idl | 70 +- .../client/src/builtins_example_client.rs | 639 +++++++++++++++++- rs/src/builtins/bls381.rs | 10 +- rs/src/builtins/eth_bridge.rs | 38 ++ rs/src/builtins/mod.rs | 6 +- rs/src/builtins/proxy.rs | 11 +- rs/src/builtins/staking.rs | 9 +- 15 files changed, 1172 insertions(+), 59 deletions(-) create mode 100644 examples/builtins/app/src/bls381.rs create mode 100644 examples/builtins/app/src/eth_bridge.rs create mode 100644 examples/builtins/app/src/proxy.rs create mode 100644 examples/builtins/app/src/staking.rs create mode 100644 examples/builtins/app/tests/extrinsic.rs rename examples/builtins/app/tests/{gclient.rs => program.rs} (58%) create mode 100644 rs/src/builtins/eth_bridge.rs diff --git a/examples/builtins/app/src/bls381.rs b/examples/builtins/app/src/bls381.rs new file mode 100644 index 000000000..695844ad7 --- /dev/null +++ b/examples/builtins/app/src/bls381.rs @@ -0,0 +1,173 @@ +use super::*; + +pub struct Bls381Broker; + +// Requests +// /// Request to pairing multi Miller loop for *BLS12-381*. +// /// +// /// Encoded: +// /// - `a`: [`ArkScale>`]. +// /// - `b`: [`ArkScale>`]. +// #[codec(index = 0)] +// MultiMillerLoop { a: Vec, b: Vec }, + +// /// Request to pairing final exponentiation for *BLS12-381*. +// /// +// /// Encoded: [`ArkScale<`]. +// #[codec(index = 1)] +// FinalExponentiation { f: Vec }, + +// /// Request to multi scalar multiplication on *G1* for *BLS12-381* +// /// +// /// Encoded: +// /// - `bases`: [`ArkScale>`]. +// /// - `scalars`: [`ArkScale>`]. +// #[codec(index = 2)] +// MultiScalarMultiplicationG1 { bases: Vec, scalars: Vec }, + +// /// Request to multi scalar multiplication on *G2* for *BLS12-381* +// /// +// /// Encoded: +// /// - `bases`: [`ArkScale>`]. +// /// - `scalars`: [`ArkScale>`]. +// #[codec(index = 3)] +// MultiScalarMultiplicationG2 { bases: Vec, scalars: Vec }, + +// /// Request to projective multiplication on *G1* for *BLS12-381*. +// /// +// /// Encoded: +// /// - `base`: [`ArkScaleProjective`]. +// /// - `scalar`: [`ArkScale>`]. +// #[codec(index = 4)] +// ProjectiveMultiplicationG1 { base: Vec, scalar: Vec }, + +// /// Request to projective multiplication on *G2* for *BLS12-381*. +// /// +// /// Encoded: +// /// - `base`: [`ArkScaleProjective`]. +// /// - `scalar`: [`ArkScale>`]. +// #[codec(index = 5)] +// ProjectiveMultiplicationG2 { base: Vec, scalar: Vec }, + +// /// Request to aggregate *G1* points for *BLS12-381*. +// /// +// /// Encoded: [`ArkScale>`]. +// #[codec(index = 6)] +// AggregateG1 { points: Vec }, + +// /// Request to map an arbitrary message to *G2Affine* point for *BLS12-381*. +// /// +// /// Raw message bytes to map. +// #[codec(index = 7)] +// MapToG2Affine { message: Vec }, + +#[sails_rs::service] +impl Bls381Broker { + #[export] + pub async fn multi_miller_loop( + &mut self, + a: Vec, + b: Vec, + ) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .multi_miller_loop(a, b) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn final_exponentiation(&mut self, f: Vec) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .final_exponentiation(f) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn multi_scalar_multiplication_g1( + &mut self, + bases: Vec, + scalars: Vec, + ) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .multi_scalar_multiplication_g1(bases, scalars) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn multi_scalar_multiplication_g2( + &mut self, + bases: Vec, + scalars: Vec, + ) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .multi_scalar_multiplication_g2(bases, scalars) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn projective_multiplication_g1( + &mut self, + base: Vec, + scalar: Vec, + ) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .projective_multiplication_g1(base, scalar) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn projective_multiplication_g2( + &mut self, + base: Vec, + scalar: Vec, + ) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .projective_multiplication_g2(base, scalar) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn aggregate_g1(&mut self, points: Vec) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .aggregate_g1(points) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } + + #[export] + pub async fn map_to_g2_affine(&mut self, message: Vec) -> Result { + let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); + + bls381_builtin_client + .map_to_g2_affine(message) + .send_recv(BLS381_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending bls381 builtin request: {e}")) + } +} diff --git a/examples/builtins/app/src/eth_bridge.rs b/examples/builtins/app/src/eth_bridge.rs new file mode 100644 index 000000000..e4e7ffe24 --- /dev/null +++ b/examples/builtins/app/src/eth_bridge.rs @@ -0,0 +1,21 @@ +use super::*; + +pub struct EthBridgeBroker; + +#[sails_rs::service] +impl EthBridgeBroker { + #[export] + pub async fn send_eth_message( + &mut self, + destination: H160, + payload: Vec, + ) -> Result { + let eth_bridge_builtin_client = EthBridgeRemoting::new(GStdRemoting::new()); + + eth_bridge_builtin_client + .send_eth_message(destination, payload) + .send_recv(ETH_BRIDGE_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending eth bridge builtin request: {e}")) + } +} diff --git a/examples/builtins/app/src/lib.rs b/examples/builtins/app/src/lib.rs index a1dbeee99..8aca6325e 100644 --- a/examples/builtins/app/src/lib.rs +++ b/examples/builtins/app/src/lib.rs @@ -1,38 +1,41 @@ #![no_std] +mod bls381; +mod eth_bridge; +mod proxy; +mod staking; + +use bls381::Bls381Broker; +use eth_bridge::EthBridgeBroker; +use proxy::ProxyBroker; use sails_rs::{builtins::*, calls::Call, gstd::calls::GStdRemoting, prelude::*}; - -struct ProxyBroker; - -#[sails_rs::service] -impl ProxyBroker { - #[export] - pub async fn add_proxy(&mut self, delegate: ActorId, proxy_type: ProxyType) -> Vec { - let proxy_builtin_client = ProxyBuiltin::new(GStdRemoting::new()); - - // todo [sab] error type - proxy_builtin_client - .add_proxy(delegate, proxy_type) - .send_recv(PROXY_BUILTIN_ID) - .await - .unwrap_or_else(|e| panic!("failed sending proxy builtin request: {e}")) - } -} +use staking::StakingBroker; #[derive(Default)] -pub struct Program(()); +pub struct BuiltinsBroker(()); #[sails_rs::program] -impl Program { +impl BuiltinsBroker { // Program's constructor pub fn new() -> Self { Self(()) } - // Exposed service pub fn proxy_broker(&self) -> ProxyBroker { ProxyBroker } + + pub fn staking_broker(&self) -> StakingBroker { + StakingBroker + } + + pub fn bls381_broker(&self) -> Bls381Broker { + Bls381Broker + } + + pub fn eth_bridge_broker(&self) -> EthBridgeBroker { + EthBridgeBroker + } } #[cfg(not(target_arch = "wasm32"))] diff --git a/examples/builtins/app/src/proxy.rs b/examples/builtins/app/src/proxy.rs new file mode 100644 index 000000000..8a091cce3 --- /dev/null +++ b/examples/builtins/app/src/proxy.rs @@ -0,0 +1,36 @@ +use super::*; + +pub struct ProxyBroker; + +#[sails_rs::service] +impl ProxyBroker { + #[export] + pub async fn add_proxy( + &mut self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> Result, String> { + let proxy_builtin_client = ProxyBuiltin::new(GStdRemoting::new()); + + proxy_builtin_client + .add_proxy(delegate, proxy_type) + .send_recv(PROXY_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending proxy builtin request: {e}")) + } + + #[export] + pub async fn remove_proxy( + &mut self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> Result, String> { + let proxy_builtin_client = ProxyBuiltin::new(GStdRemoting::new()); + + proxy_builtin_client + .remove_proxy(delegate, proxy_type) + .send_recv(PROXY_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending proxy builtin request: {e}")) + } +} diff --git a/examples/builtins/app/src/staking.rs b/examples/builtins/app/src/staking.rs new file mode 100644 index 000000000..b44c222d7 --- /dev/null +++ b/examples/builtins/app/src/staking.rs @@ -0,0 +1,109 @@ +use super::*; + +pub struct StakingBroker; + +#[sails_rs::service] +impl StakingBroker { + #[export] + pub async fn bond(&mut self, value: u128, payee: RewardAccount) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .bond(value, payee) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn bond_extra(&mut self, value: u128) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .bond_extra(value) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn unbond(&mut self, value: u128) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .unbond(value) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn withdraw_unbonded(&mut self, num_slashing_spans: u32) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .withdraw_unbonded(num_slashing_spans) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn nominate(&mut self, targets: Vec) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .nominate(targets) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn chill(&mut self) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .chill() + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn payout_stakers( + &mut self, + validator_stash: ActorId, + era: u32, + ) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .payout_stakers(validator_stash, era) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn rebond(&mut self, value: u128) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .rebond(value) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } + + #[export] + pub async fn set_payee(&mut self, payee: RewardAccount) -> Result, String> { + let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); + + staking_builtin_client + .set_payee(payee) + .send_recv(STAKING_BUILTIN_ID) + .await + .map_err(|e| format!("failed sending staking builtin request: {e}")) + } +} diff --git a/examples/builtins/app/tests/extrinsic.rs b/examples/builtins/app/tests/extrinsic.rs new file mode 100644 index 000000000..fe42776e2 --- /dev/null +++ b/examples/builtins/app/tests/extrinsic.rs @@ -0,0 +1,33 @@ +use gclient::GearApi; +/// These tests make interact with builtins from non-app (program) context via extrinsics (calls). +use sails_rs::{ + H256, + builtins::{PROXY_BUILTIN_ID, ProxyBuiltin, ProxyType as SailsProxyType}, + calls::Call, + gclient::calls::GClientRemoting, +}; + +#[tokio::test] +async fn call_proxy_builtin_with_extrinsic() { + let api = GearApi::dev().await.unwrap(); + + let remoting = GClientRemoting::new(api.clone()); + + let proxy = ProxyBuiltin::new(remoting); + let random_actor_id = H256::random().into(); + let res = proxy + .add_proxy(random_actor_id, SailsProxyType::Any) + .send_recv(PROXY_BUILTIN_ID) + .await + .expect("Failed to send proxy request"); + + assert_eq!(res, Vec::::new()); + + let res = proxy + .remove_proxy(random_actor_id, SailsProxyType::Any) + .send_recv(PROXY_BUILTIN_ID) + .await + .expect("Failed to send proxy request"); + + assert_eq!(res, Vec::::new()); +} diff --git a/examples/builtins/app/tests/gclient.rs b/examples/builtins/app/tests/program.rs similarity index 58% rename from examples/builtins/app/tests/gclient.rs rename to examples/builtins/app/tests/program.rs index 5412f7555..dda36c594 100644 --- a/examples/builtins/app/tests/gclient.rs +++ b/examples/builtins/app/tests/program.rs @@ -1,3 +1,4 @@ +/// These tests make interact with builtins from app context. use builtins_example_app::WASM_BINARY; use builtins_example_client::{ BuiltinsExampleClientFactory, ProxyBroker, ProxyType, @@ -6,38 +7,12 @@ use builtins_example_client::{ use gclient::GearApi; use sails_rs::{ H256, - builtins::{PROXY_BUILTIN_ID, ProxyBuiltin, ProxyType as SailsProxyType}, calls::{Activation, Call}, gclient::calls::GClientRemoting, }; #[tokio::test] -async fn test_raw_proxy_builtin_call() { - let api = GearApi::dev().await.unwrap(); - - let remoting = GClientRemoting::new(api.clone()); - - let proxy = ProxyBuiltin::new(remoting); - let random_actor_id = H256::random().into(); - let res = proxy - .add_proxy(random_actor_id, SailsProxyType::Any) - .send_recv(PROXY_BUILTIN_ID) - .await - .expect("Failed to send proxy request"); - - assert_eq!(res, Vec::::new()); - - let res = proxy - .remove_proxy(random_actor_id, SailsProxyType::Any) - .send_recv(PROXY_BUILTIN_ID) - .await - .expect("Failed to send proxy request"); - - assert_eq!(res, Vec::::new()); -} - -#[tokio::test] -async fn test_proxy_builtin_program_call() { +async fn call_proxy_builtin_from_app() { let api = GearApi::dev().await.unwrap(); let (code_id, _) = api @@ -64,5 +39,5 @@ async fn test_proxy_builtin_program_call() { .await .expect("Failed to send proxy request"); - assert_eq!(resp, Vec::::new()); + assert_eq!(resp, Ok(Vec::::new())); } diff --git a/examples/builtins/client/build.rs b/examples/builtins/client/build.rs index b2ebabdfe..649d13b60 100644 --- a/examples/builtins/client/build.rs +++ b/examples/builtins/client/build.rs @@ -1,3 +1,3 @@ fn main() { - sails_rs::build_client::(); + sails_rs::build_client::(); } diff --git a/examples/builtins/client/builtins_example_client.idl b/examples/builtins/client/builtins_example_client.idl index 207578974..27b22ce3c 100644 --- a/examples/builtins/client/builtins_example_client.idl +++ b/examples/builtins/client/builtins_example_client.idl @@ -8,11 +8,79 @@ type ProxyType = enum { CancelProxy, }; +/// `TypeInfo` implementor copy of `gbuiltin_staking::RewardAccount`. +type RewardAccount = enum { + /// Pay rewards to the sender's account and increase the amount at stake. + Staked, + /// Pay rewards to the sender's account (usually, the one derived from `program_id`) + /// without increasing the amount at stake. + Program, + /// Pay rewards to a custom account. + Custom: actor_id, + /// Opt for not receiving any rewards at all. + None, +}; + +/// `TypeInfo` implementor copy of `gbuiltin_bls381::Response`. +type Bls381Response = enum { + /// Result of the multi Miller loop, encoded: [`ArkScale`]. + MultiMillerLoop: vec u8, + /// Result of the final exponentiation, encoded: [`ArkScale`]. + FinalExponentiation: vec u8, + /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. + MultiScalarMultiplicationG1: vec u8, + /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. + MultiScalarMultiplicationG2: vec u8, + /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. + ProjectiveMultiplicationG1: vec u8, + /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. + ProjectiveMultiplicationG2: vec u8, + /// Result of the aggregation, encoded: [`ArkScale`]. + AggregateG1: vec u8, + /// Result of the mapping, encoded: [`ArkScale`]. + MapToG2Affine: vec u8, +}; + +type Response = enum { + EthMessageQueued: struct { + nonce: u256, + hash: h256, + }, +}; + constructor { New : (); }; service ProxyBroker { - AddProxy : (delegate: actor_id, proxy_type: ProxyType) -> vec u8; + AddProxy : (delegate: actor_id, proxy_type: ProxyType) -> result (vec u8, str); + RemoveProxy : (delegate: actor_id, proxy_type: ProxyType) -> result (vec u8, str); +}; + +service StakingBroker { + Bond : (value: u128, payee: RewardAccount) -> result (vec u8, str); + BondExtra : (value: u128) -> result (vec u8, str); + Chill : () -> result (vec u8, str); + Nominate : (targets: vec actor_id) -> result (vec u8, str); + PayoutStakers : (validator_stash: actor_id, era: u32) -> result (vec u8, str); + Rebond : (value: u128) -> result (vec u8, str); + SetPayee : (payee: RewardAccount) -> result (vec u8, str); + Unbond : (value: u128) -> result (vec u8, str); + WithdrawUnbonded : (num_slashing_spans: u32) -> result (vec u8, str); +}; + +service Bls381Broker { + AggregateG1 : (points: vec u8) -> result (Bls381Response, str); + FinalExponentiation : (f: vec u8) -> result (Bls381Response, str); + MapToG2Affine : (message: vec u8) -> result (Bls381Response, str); + MultiMillerLoop : (a: vec u8, b: vec u8) -> result (Bls381Response, str); + MultiScalarMultiplicationG1 : (bases: vec u8, scalars: vec u8) -> result (Bls381Response, str); + MultiScalarMultiplicationG2 : (bases: vec u8, scalars: vec u8) -> result (Bls381Response, str); + ProjectiveMultiplicationG1 : (base: vec u8, scalar: vec u8) -> result (Bls381Response, str); + ProjectiveMultiplicationG2 : (base: vec u8, scalar: vec u8) -> result (Bls381Response, str); +}; + +service EthBridgeBroker { + SendEthMessage : (destination: h160, payload: vec u8) -> result (Response, str); }; diff --git a/examples/builtins/client/src/builtins_example_client.rs b/examples/builtins/client/src/builtins_example_client.rs index 2c4e1ccce..20184fea9 100644 --- a/examples/builtins/client/src/builtins_example_client.rs +++ b/examples/builtins/client/src/builtins_example_client.rs @@ -60,12 +60,22 @@ impl traits::ProxyBroker for ProxyBroker { &mut self, delegate: ActorId, proxy_type: ProxyType, - ) -> impl Call, Args = R::Args> { + ) -> impl Call, String>, Args = R::Args> { RemotingAction::<_, proxy_broker::io::AddProxy>::new( self.remoting.clone(), (delegate, proxy_type), ) } + fn remove_proxy( + &mut self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, proxy_broker::io::RemoveProxy>::new( + self.remoting.clone(), + (delegate, proxy_type), + ) + } } pub mod proxy_broker { @@ -87,7 +97,490 @@ pub mod proxy_broker { 111, 120, 121, ]; type Params = (ActorId, super::ProxyType); - type Reply = Vec; + type Reply = Result, String>; + } + pub struct RemoveProxy(()); + impl RemoveProxy { + #[allow(dead_code)] + pub fn encode_call(delegate: ActorId, proxy_type: super::ProxyType) -> Vec { + ::encode_call(&(delegate, proxy_type)) + } + } + impl ActionIo for RemoveProxy { + const ROUTE: &'static [u8] = &[ + 44, 80, 114, 111, 120, 121, 66, 114, 111, 107, 101, 114, 44, 82, 101, 109, 111, + 118, 101, 80, 114, 111, 120, 121, + ]; + type Params = (ActorId, super::ProxyType); + type Reply = Result, String>; + } + } +} +pub struct StakingBroker { + remoting: R, +} +impl StakingBroker { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} +impl traits::StakingBroker for StakingBroker { + type Args = R::Args; + fn bond( + &mut self, + value: u128, + payee: RewardAccount, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::Bond>::new(self.remoting.clone(), (value, payee)) + } + fn bond_extra( + &mut self, + value: u128, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::BondExtra>::new(self.remoting.clone(), value) + } + fn chill(&mut self) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::Chill>::new(self.remoting.clone(), ()) + } + fn nominate( + &mut self, + targets: Vec, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::Nominate>::new(self.remoting.clone(), targets) + } + fn payout_stakers( + &mut self, + validator_stash: ActorId, + era: u32, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::PayoutStakers>::new( + self.remoting.clone(), + (validator_stash, era), + ) + } + fn rebond( + &mut self, + value: u128, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::Rebond>::new(self.remoting.clone(), value) + } + fn set_payee( + &mut self, + payee: RewardAccount, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::SetPayee>::new(self.remoting.clone(), payee) + } + fn unbond( + &mut self, + value: u128, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::Unbond>::new(self.remoting.clone(), value) + } + fn withdraw_unbonded( + &mut self, + num_slashing_spans: u32, + ) -> impl Call, String>, Args = R::Args> { + RemotingAction::<_, staking_broker::io::WithdrawUnbonded>::new( + self.remoting.clone(), + num_slashing_spans, + ) + } +} + +pub mod staking_broker { + use super::*; + + pub mod io { + use super::*; + use sails_rs::calls::ActionIo; + pub struct Bond(()); + impl Bond { + #[allow(dead_code)] + pub fn encode_call(value: u128, payee: super::RewardAccount) -> Vec { + ::encode_call(&(value, payee)) + } + } + impl ActionIo for Bond { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 16, 66, 111, 110, + 100, + ]; + type Params = (u128, super::RewardAccount); + type Reply = Result, String>; + } + pub struct BondExtra(()); + impl BondExtra { + #[allow(dead_code)] + pub fn encode_call(value: u128) -> Vec { + ::encode_call(&value) + } + } + impl ActionIo for BondExtra { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 36, 66, 111, 110, + 100, 69, 120, 116, 114, 97, + ]; + type Params = u128; + type Reply = Result, String>; + } + pub struct Chill(()); + impl Chill { + #[allow(dead_code)] + pub fn encode_call() -> Vec { + ::encode_call(&()) + } + } + impl ActionIo for Chill { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 20, 67, 104, 105, + 108, 108, + ]; + type Params = (); + type Reply = Result, String>; + } + pub struct Nominate(()); + impl Nominate { + #[allow(dead_code)] + pub fn encode_call(targets: Vec) -> Vec { + ::encode_call(&targets) + } + } + impl ActionIo for Nominate { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 32, 78, 111, 109, + 105, 110, 97, 116, 101, + ]; + type Params = Vec; + type Reply = Result, String>; + } + pub struct PayoutStakers(()); + impl PayoutStakers { + #[allow(dead_code)] + pub fn encode_call(validator_stash: ActorId, era: u32) -> Vec { + ::encode_call(&(validator_stash, era)) + } + } + impl ActionIo for PayoutStakers { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 52, 80, 97, 121, + 111, 117, 116, 83, 116, 97, 107, 101, 114, 115, + ]; + type Params = (ActorId, u32); + type Reply = Result, String>; + } + pub struct Rebond(()); + impl Rebond { + #[allow(dead_code)] + pub fn encode_call(value: u128) -> Vec { + ::encode_call(&value) + } + } + impl ActionIo for Rebond { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 24, 82, 101, 98, + 111, 110, 100, + ]; + type Params = u128; + type Reply = Result, String>; + } + pub struct SetPayee(()); + impl SetPayee { + #[allow(dead_code)] + pub fn encode_call(payee: super::RewardAccount) -> Vec { + ::encode_call(&payee) + } + } + impl ActionIo for SetPayee { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 32, 83, 101, 116, + 80, 97, 121, 101, 101, + ]; + type Params = super::RewardAccount; + type Reply = Result, String>; + } + pub struct Unbond(()); + impl Unbond { + #[allow(dead_code)] + pub fn encode_call(value: u128) -> Vec { + ::encode_call(&value) + } + } + impl ActionIo for Unbond { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 24, 85, 110, 98, + 111, 110, 100, + ]; + type Params = u128; + type Reply = Result, String>; + } + pub struct WithdrawUnbonded(()); + impl WithdrawUnbonded { + #[allow(dead_code)] + pub fn encode_call(num_slashing_spans: u32) -> Vec { + ::encode_call(&num_slashing_spans) + } + } + impl ActionIo for WithdrawUnbonded { + const ROUTE: &'static [u8] = &[ + 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 64, 87, 105, 116, + 104, 100, 114, 97, 119, 85, 110, 98, 111, 110, 100, 101, 100, + ]; + type Params = u32; + type Reply = Result, String>; + } + } +} +pub struct Bls381Broker { + remoting: R, +} +impl Bls381Broker { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} +impl traits::Bls381Broker for Bls381Broker { + type Args = R::Args; + fn aggregate_g_1( + &mut self, + points: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::AggregateG1>::new(self.remoting.clone(), points) + } + fn final_exponentiation( + &mut self, + f: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::FinalExponentiation>::new(self.remoting.clone(), f) + } + fn map_to_g_2_affine( + &mut self, + message: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::MapToG2Affine>::new(self.remoting.clone(), message) + } + fn multi_miller_loop( + &mut self, + a: Vec, + b: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::MultiMillerLoop>::new(self.remoting.clone(), (a, b)) + } + fn multi_scalar_multiplication_g_1( + &mut self, + bases: Vec, + scalars: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::MultiScalarMultiplicationG1>::new( + self.remoting.clone(), + (bases, scalars), + ) + } + fn multi_scalar_multiplication_g_2( + &mut self, + bases: Vec, + scalars: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::MultiScalarMultiplicationG2>::new( + self.remoting.clone(), + (bases, scalars), + ) + } + fn projective_multiplication_g_1( + &mut self, + base: Vec, + scalar: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::ProjectiveMultiplicationG1>::new( + self.remoting.clone(), + (base, scalar), + ) + } + fn projective_multiplication_g_2( + &mut self, + base: Vec, + scalar: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, bls_381_broker::io::ProjectiveMultiplicationG2>::new( + self.remoting.clone(), + (base, scalar), + ) + } +} + +pub mod bls_381_broker { + use super::*; + + pub mod io { + use super::*; + use sails_rs::calls::ActionIo; + pub struct AggregateG1(()); + impl AggregateG1 { + #[allow(dead_code)] + pub fn encode_call(points: Vec) -> Vec { + ::encode_call(&points) + } + } + impl ActionIo for AggregateG1 { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 44, 65, 103, 103, 114, + 101, 103, 97, 116, 101, 71, 49, + ]; + type Params = Vec; + type Reply = Result; + } + pub struct FinalExponentiation(()); + impl FinalExponentiation { + #[allow(dead_code)] + pub fn encode_call(f: Vec) -> Vec { + ::encode_call(&f) + } + } + impl ActionIo for FinalExponentiation { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 76, 70, 105, 110, 97, + 108, 69, 120, 112, 111, 110, 101, 110, 116, 105, 97, 116, 105, 111, 110, + ]; + type Params = Vec; + type Reply = Result; + } + pub struct MapToG2Affine(()); + impl MapToG2Affine { + #[allow(dead_code)] + pub fn encode_call(message: Vec) -> Vec { + ::encode_call(&message) + } + } + impl ActionIo for MapToG2Affine { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 52, 77, 97, 112, 84, + 111, 71, 50, 65, 102, 102, 105, 110, 101, + ]; + type Params = Vec; + type Reply = Result; + } + pub struct MultiMillerLoop(()); + impl MultiMillerLoop { + #[allow(dead_code)] + pub fn encode_call(a: Vec, b: Vec) -> Vec { + ::encode_call(&(a, b)) + } + } + impl ActionIo for MultiMillerLoop { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 60, 77, 117, 108, 116, + 105, 77, 105, 108, 108, 101, 114, 76, 111, 111, 112, + ]; + type Params = (Vec, Vec); + type Reply = Result; + } + pub struct MultiScalarMultiplicationG1(()); + impl MultiScalarMultiplicationG1 { + #[allow(dead_code)] + pub fn encode_call(bases: Vec, scalars: Vec) -> Vec { + ::encode_call(&(bases, scalars)) + } + } + impl ActionIo for MultiScalarMultiplicationG1 { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 108, 77, 117, 108, 116, + 105, 83, 99, 97, 108, 97, 114, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 71, 49, + ]; + type Params = (Vec, Vec); + type Reply = Result; + } + pub struct MultiScalarMultiplicationG2(()); + impl MultiScalarMultiplicationG2 { + #[allow(dead_code)] + pub fn encode_call(bases: Vec, scalars: Vec) -> Vec { + ::encode_call(&(bases, scalars)) + } + } + impl ActionIo for MultiScalarMultiplicationG2 { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 108, 77, 117, 108, 116, + 105, 83, 99, 97, 108, 97, 114, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 71, 50, + ]; + type Params = (Vec, Vec); + type Reply = Result; + } + pub struct ProjectiveMultiplicationG1(()); + impl ProjectiveMultiplicationG1 { + #[allow(dead_code)] + pub fn encode_call(base: Vec, scalar: Vec) -> Vec { + ::encode_call(&(base, scalar)) + } + } + impl ActionIo for ProjectiveMultiplicationG1 { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 104, 80, 114, 111, 106, + 101, 99, 116, 105, 118, 101, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 71, 49, + ]; + type Params = (Vec, Vec); + type Reply = Result; + } + pub struct ProjectiveMultiplicationG2(()); + impl ProjectiveMultiplicationG2 { + #[allow(dead_code)] + pub fn encode_call(base: Vec, scalar: Vec) -> Vec { + ::encode_call(&(base, scalar)) + } + } + impl ActionIo for ProjectiveMultiplicationG2 { + const ROUTE: &'static [u8] = &[ + 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 104, 80, 114, 111, 106, + 101, 99, 116, 105, 118, 101, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 71, 50, + ]; + type Params = (Vec, Vec); + type Reply = Result; + } + } +} +pub struct EthBridgeBroker { + remoting: R, +} +impl EthBridgeBroker { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} +impl traits::EthBridgeBroker for EthBridgeBroker { + type Args = R::Args; + fn send_eth_message( + &mut self, + destination: H160, + payload: Vec, + ) -> impl Call, Args = R::Args> { + RemotingAction::<_, eth_bridge_broker::io::SendEthMessage>::new( + self.remoting.clone(), + (destination, payload), + ) + } +} + +pub mod eth_bridge_broker { + use super::*; + + pub mod io { + use super::*; + use sails_rs::calls::ActionIo; + pub struct SendEthMessage(()); + impl SendEthMessage { + #[allow(dead_code)] + pub fn encode_call(destination: H160, payload: Vec) -> Vec { + ::encode_call(&(destination, payload)) + } + } + impl ActionIo for SendEthMessage { + const ROUTE: &'static [u8] = &[ + 60, 69, 116, 104, 66, 114, 105, 100, 103, 101, 66, 114, 111, 107, 101, 114, 56, 83, + 101, 110, 100, 69, 116, 104, 77, 101, 115, 115, 97, 103, 101, + ]; + type Params = (H160, Vec); + type Reply = Result; } } } @@ -103,6 +596,49 @@ pub enum ProxyType { IdentityJudgement, CancelProxy, } +/// `TypeInfo` implementor copy of `gbuiltin_staking::RewardAccount`. +#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] +#[codec(crate = sails_rs::scale_codec)] +#[scale_info(crate = sails_rs::scale_info)] +pub enum RewardAccount { + /// Pay rewards to the sender's account and increase the amount at stake. + Staked, + /// Pay rewards to the sender's account (usually, the one derived from `program_id`) + /// without increasing the amount at stake. + Program, + /// Pay rewards to a custom account. + Custom(ActorId), + /// Opt for not receiving any rewards at all. + None, +} +/// `TypeInfo` implementor copy of `gbuiltin_bls381::Response`. +#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] +#[codec(crate = sails_rs::scale_codec)] +#[scale_info(crate = sails_rs::scale_info)] +pub enum Bls381Response { + /// Result of the multi Miller loop, encoded: [`ArkScale`]. + MultiMillerLoop(Vec), + /// Result of the final exponentiation, encoded: [`ArkScale`]. + FinalExponentiation(Vec), + /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. + MultiScalarMultiplicationG1(Vec), + /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. + MultiScalarMultiplicationG2(Vec), + /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. + ProjectiveMultiplicationG1(Vec), + /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. + ProjectiveMultiplicationG2(Vec), + /// Result of the aggregation, encoded: [`ArkScale`]. + AggregateG1(Vec), + /// Result of the mapping, encoded: [`ArkScale`]. + MapToG2Affine(Vec), +} +#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] +#[codec(crate = sails_rs::scale_codec)] +#[scale_info(crate = sails_rs::scale_info)] +pub enum Response { + EthMessageQueued { nonce: U256, hash: H256 }, +} pub mod traits { use super::*; @@ -121,6 +657,103 @@ pub mod traits { &mut self, delegate: ActorId, proxy_type: ProxyType, - ) -> impl Call, Args = Self::Args>; + ) -> impl Call, String>, Args = Self::Args>; + fn remove_proxy( + &mut self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call, String>, Args = Self::Args>; + } + + #[allow(clippy::type_complexity)] + pub trait StakingBroker { + type Args; + fn bond( + &mut self, + value: u128, + payee: RewardAccount, + ) -> impl Call, String>, Args = Self::Args>; + fn bond_extra( + &mut self, + value: u128, + ) -> impl Call, String>, Args = Self::Args>; + fn chill(&mut self) -> impl Call, String>, Args = Self::Args>; + fn nominate( + &mut self, + targets: Vec, + ) -> impl Call, String>, Args = Self::Args>; + fn payout_stakers( + &mut self, + validator_stash: ActorId, + era: u32, + ) -> impl Call, String>, Args = Self::Args>; + fn rebond( + &mut self, + value: u128, + ) -> impl Call, String>, Args = Self::Args>; + fn set_payee( + &mut self, + payee: RewardAccount, + ) -> impl Call, String>, Args = Self::Args>; + fn unbond( + &mut self, + value: u128, + ) -> impl Call, String>, Args = Self::Args>; + fn withdraw_unbonded( + &mut self, + num_slashing_spans: u32, + ) -> impl Call, String>, Args = Self::Args>; + } + + #[allow(clippy::type_complexity)] + pub trait Bls381Broker { + type Args; + fn aggregate_g_1( + &mut self, + points: Vec, + ) -> impl Call, Args = Self::Args>; + fn final_exponentiation( + &mut self, + f: Vec, + ) -> impl Call, Args = Self::Args>; + fn map_to_g_2_affine( + &mut self, + message: Vec, + ) -> impl Call, Args = Self::Args>; + fn multi_miller_loop( + &mut self, + a: Vec, + b: Vec, + ) -> impl Call, Args = Self::Args>; + fn multi_scalar_multiplication_g_1( + &mut self, + bases: Vec, + scalars: Vec, + ) -> impl Call, Args = Self::Args>; + fn multi_scalar_multiplication_g_2( + &mut self, + bases: Vec, + scalars: Vec, + ) -> impl Call, Args = Self::Args>; + fn projective_multiplication_g_1( + &mut self, + base: Vec, + scalar: Vec, + ) -> impl Call, Args = Self::Args>; + fn projective_multiplication_g_2( + &mut self, + base: Vec, + scalar: Vec, + ) -> impl Call, Args = Self::Args>; + } + + #[allow(clippy::type_complexity)] + pub trait EthBridgeBroker { + type Args; + fn send_eth_message( + &mut self, + destination: H160, + payload: Vec, + ) -> impl Call, Args = Self::Args>; } } diff --git a/rs/src/builtins/bls381.rs b/rs/src/builtins/bls381.rs index 4f9b42cb6..d1dcbab04 100644 --- a/rs/src/builtins/bls381.rs +++ b/rs/src/builtins/bls381.rs @@ -7,8 +7,7 @@ use crate::{ }; use gbuiltin_bls381::{Request as GearBls381Request, Response as GearBls381Response}; -// todo [sab] make typeinfo types on gear -// todo [sab] package must provide the address 0x6b6e292c382945e80bf51af2ba7fe9f458dcff81ae6075c46f9095e1bbecdc37 +/// Gear protocol BLS381 builtin id is 0x6b6e292c382945e80bf51af2ba7fe9f458dcff81ae6075c46f9095e1bbecdc37 pub const BLS381_BUILTIN_ID: ActorId = ActorId::new([ 0x6b, 0x6e, 0x29, 0x2c, 0x38, 0x29, 0x45, 0xe8, 0x0b, 0xf5, 0x1a, 0xf2, 0xba, 0x7f, 0xe9, 0xf4, 0x58, 0xdc, 0xff, 0x81, 0xae, 0x60, 0x75, 0xc4, 0x6f, 0x90, 0x95, 0xe1, 0xbb, 0xec, 0xdc, 0x37, @@ -208,3 +207,10 @@ impl From for Bls381Response { } } } + +#[test] +fn test_id() { + let expected = hex::decode("6b6e292c382945e80bf51af2ba7fe9f458dcff81ae6075c46f9095e1bbecdc37") + .expect("Failed to decode hex"); + assert_eq!(BLS381_BUILTIN_ID.into_bytes().to_vec(), expected); +} diff --git a/rs/src/builtins/eth_bridge.rs b/rs/src/builtins/eth_bridge.rs new file mode 100644 index 000000000..358066063 --- /dev/null +++ b/rs/src/builtins/eth_bridge.rs @@ -0,0 +1,38 @@ +use crate::{ + ActorId, + builtins::{BuiltinsRemoting, builtin_action}, + calls::{ActionIo, Call, RemotingAction}, + errors::{Error, Result}, + prelude::{Decode, Encode, Vec}, +}; +pub use gbuiltin_eth_bridge::{Request as EthBridgeRequest, Response as EthBridgeResponse}; +use gprimitives::H160; + +/// Gear protocol eth-bridge builtin id is 0xf2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf +pub const ETH_BRIDGE_BUILTIN_ID: ActorId = ActorId::new([ + 0xf2, 0x81, 0x6c, 0xed, 0x0b, 0x15, 0x74, 0x95, 0x95, 0x39, 0x2d, 0x3a, 0x18, 0xb5, 0xa2, 0x36, + 0x3d, 0x6f, 0xef, 0xe5, 0xb3, 0xb6, 0x15, 0x37, 0x39, 0xf2, 0x18, 0x15, 0x1b, 0x7a, 0xcd, 0xbf, +]); + +builtin_action!( + EthBridgeRequest, + EthBridgeRemoting, + SendEthMessage { destination: H160, payload: Vec } => EthBridgeResponse +); + +pub struct EthBridgeRemoting { + remoting: R, +} + +impl EthBridgeRemoting { + pub fn new(remoting: R) -> Self { + Self { remoting } + } +} + +#[test] +fn test_id() { + let expected = hex::decode("f2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf") + .expect("Failed to decode hex"); + assert_eq!(ETH_BRIDGE_BUILTIN_ID.into_bytes().to_vec(), expected); +} diff --git a/rs/src/builtins/mod.rs b/rs/src/builtins/mod.rs index e851ecf34..8f21ce411 100644 --- a/rs/src/builtins/mod.rs +++ b/rs/src/builtins/mod.rs @@ -1,10 +1,12 @@ +mod bls381; +mod eth_bridge; mod proxy; mod staking; -mod bls381; +pub use bls381::*; +pub use eth_bridge::*; pub use proxy::*; pub use staking::*; -pub use bls381::*; use crate::calls::Remoting; diff --git a/rs/src/builtins/proxy.rs b/rs/src/builtins/proxy.rs index 5bbc63e50..23fb5eaf5 100644 --- a/rs/src/builtins/proxy.rs +++ b/rs/src/builtins/proxy.rs @@ -8,7 +8,9 @@ use crate::{ use gbuiltin_proxy::{ProxyType as GearProxyType, Request as GearProxyRequest}; // todo [sab] make typeinfo types on gear -// todo [sab] package must provide the address 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 +// todo [sab] package must provide the address + +/// Gear protocol proxy builtin id is 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 pub const PROXY_BUILTIN_ID: ActorId = ActorId::new([ 0x82, 0x63, 0xcd, 0x9f, 0xc6, 0x48, 0xe1, 0x01, 0xf1, 0xcd, 0x85, 0x85, 0xdc, 0x0b, 0x19, 0x34, 0x45, 0xc3, 0x75, 0x0a, 0x63, 0xbf, 0x64, 0xa3, 0x9c, 0xdf, 0x58, 0xde, 0x14, 0x82, 0x62, 0x99, @@ -93,3 +95,10 @@ impl From for ProxyType { } } } + +#[test] +fn test_id() { + let expected = hex::decode("8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299") + .expect("Failed to decode hex"); + assert_eq!(PROXY_BUILTIN_ID.into_bytes().to_vec(), expected); +} diff --git a/rs/src/builtins/staking.rs b/rs/src/builtins/staking.rs index 7d6ead81f..57197bbff 100644 --- a/rs/src/builtins/staking.rs +++ b/rs/src/builtins/staking.rs @@ -7,7 +7,7 @@ use crate::{ }; use gbuiltin_staking::{Request as GearStakingRequest, RewardAccount as GearRewardAccount}; -// todo [sab] package must provide the address 77f65ef190e11bfecb8fc8970fd3749e94bed66a23ec2f7a3623e785d0816761 +/// Gear protocol staking builtin id is 0x77f65ef190e11bfecb8fc8970fd3749e94bed66a23ec2f7a3623e785d0816761 pub const STAKING_BUILTIN_ID: ActorId = ActorId::new([ 0x77, 0xf6, 0x5e, 0xf1, 0x90, 0xe1, 0x1b, 0xfe, 0xcb, 0x8f, 0xc8, 0x97, 0x0f, 0xd3, 0x74, 0x9e, 0x94, 0xbe, 0xd6, 0x6a, 0x23, 0xec, 0x2f, 0x7a, 0x36, 0x23, 0xe7, 0x85, 0xd0, 0x81, 0x67, 0x61, @@ -148,3 +148,10 @@ impl From for RewardAccount { } } } + +#[test] +fn test_id() { + let expected = hex::decode("77f65ef190e11bfecb8fc8970fd3749e94bed66a23ec2f7a3623e785d0816761") + .expect("Failed to decode hex"); + assert_eq!(STAKING_BUILTIN_ID.into_bytes().to_vec(), expected); +} From d717e919bcc6088605efbfbbd9c7ff757519f843 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 21 Jul 2025 19:44:47 +0300 Subject: [PATCH 05/16] Add more tests --- examples/builtins/app/tests/extrinsic.rs | 88 +++++++++++++++++++++++- examples/builtins/app/tests/program.rs | 12 +++- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/examples/builtins/app/tests/extrinsic.rs b/examples/builtins/app/tests/extrinsic.rs index fe42776e2..9c8ae8cc7 100644 --- a/examples/builtins/app/tests/extrinsic.rs +++ b/examples/builtins/app/tests/extrinsic.rs @@ -2,7 +2,10 @@ use gclient::GearApi; /// These tests make interact with builtins from non-app (program) context via extrinsics (calls). use sails_rs::{ H256, - builtins::{PROXY_BUILTIN_ID, ProxyBuiltin, ProxyType as SailsProxyType}, + builtins::{ + PROXY_BUILTIN_ID, ProxyBuiltin, ProxyType as SailsProxyType, RewardAccount, + STAKING_BUILTIN_ID, StakingBuiltin, + }, calls::Call, gclient::calls::GClientRemoting, }; @@ -31,3 +34,86 @@ async fn call_proxy_builtin_with_extrinsic() { assert_eq!(res, Vec::::new()); } + +#[tokio::test] +async fn call_staking_builtin_with_extrinsic() { + let api = GearApi::dev().await.unwrap(); + + let remoting = GClientRemoting::new(api.clone()); + let staking_builtin_client = StakingBuiltin::new(remoting); + + let res = staking_builtin_client + .bond(1_000_000_000_000, RewardAccount::None) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send bond request"); + + assert_eq!(res, Vec::::new()); + + let res = staking_builtin_client + .bond_extra(500_000_000_000) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send bond_extra request"); + + assert_eq!(res, Vec::::new()); + + let res = staking_builtin_client + .rebond(2_000_000_000_000) + .send_recv(STAKING_BUILTIN_ID) + .await + .unwrap_err() + .to_string(); + assert!(res.contains("NoUnlockChunk")); + + let res = staking_builtin_client + .set_payee(RewardAccount::Staked) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send set_payee request"); + + assert_eq!(res, Vec::::new()); + + let balance = api.free_balance(api.account_id()).await; + println!("Balance before staking: {balance:?}"); + + let res = staking_builtin_client + .unbond(200_000_000_000) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send unbond request"); + + assert_eq!(res, Vec::::new()); + + let res = staking_builtin_client + .chill() + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send chill request"); + + assert_eq!(res, Vec::::new()); + + let res = staking_builtin_client + .withdraw_unbonded(1) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send withdraw_unbonded request"); + + assert_eq!(res, Vec::::new()); + + let res = staking_builtin_client + .nominate(vec![H256::random().into()]) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send nominate request"); + + assert_eq!(res, Vec::::new()); + + let res = staking_builtin_client + .payout_stakers(H256::random().into(), 1) + .send_recv(STAKING_BUILTIN_ID) + .await + .expect("Failed to send payout_stakers request"); + + assert_eq!(res, Vec::::new()); +} diff --git a/examples/builtins/app/tests/program.rs b/examples/builtins/app/tests/program.rs index dda36c594..910cb5e9a 100644 --- a/examples/builtins/app/tests/program.rs +++ b/examples/builtins/app/tests/program.rs @@ -11,6 +11,8 @@ use sails_rs::{ gclient::calls::GClientRemoting, }; +const ONE_VARA: u128 = 1_000_000_000_000; + #[tokio::test] async fn call_proxy_builtin_from_app() { let api = GearApi::dev().await.unwrap(); @@ -28,7 +30,7 @@ async fn call_proxy_builtin_from_app() { .await .expect("Failed program init message"); - api.transfer_keep_alive(builtins_broker_pid, 100_000_000_000_000_000_000) + api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) .await .expect("Failed to transfer funds to program"); @@ -40,4 +42,12 @@ async fn call_proxy_builtin_from_app() { .expect("Failed to send proxy request"); assert_eq!(resp, Ok(Vec::::new())); + + let resp = proxy_broker_client + .remove_proxy(H256::random().into(), ProxyType::Any) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send proxy request"); + + assert_eq!(resp, Ok(Vec::::new())); } From bf0feaa132ccf7045c95534ec4205f134a8c7edc Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 21 Jul 2025 21:19:16 +0300 Subject: [PATCH 06/16] add staking tests --- examples/builtins/app/tests/extrinsic.rs | 29 +++----- examples/builtins/app/tests/program.rs | 87 ++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 25 deletions(-) diff --git a/examples/builtins/app/tests/extrinsic.rs b/examples/builtins/app/tests/extrinsic.rs index 9c8ae8cc7..1d7ad24b4 100644 --- a/examples/builtins/app/tests/extrinsic.rs +++ b/examples/builtins/app/tests/extrinsic.rs @@ -74,16 +74,7 @@ async fn call_staking_builtin_with_extrinsic() { assert_eq!(res, Vec::::new()); - let balance = api.free_balance(api.account_id()).await; - println!("Balance before staking: {balance:?}"); - - let res = staking_builtin_client - .unbond(200_000_000_000) - .send_recv(STAKING_BUILTIN_ID) - .await - .expect("Failed to send unbond request"); - - assert_eq!(res, Vec::::new()); + // todo [sab] invalid gas count for `unbond` call let res = staking_builtin_client .chill() @@ -93,27 +84,23 @@ async fn call_staking_builtin_with_extrinsic() { assert_eq!(res, Vec::::new()); - let res = staking_builtin_client - .withdraw_unbonded(1) - .send_recv(STAKING_BUILTIN_ID) - .await - .expect("Failed to send withdraw_unbonded request"); - - assert_eq!(res, Vec::::new()); + // todo [sab] invalid gas count for `withdraw_unbonded` call let res = staking_builtin_client .nominate(vec![H256::random().into()]) .send_recv(STAKING_BUILTIN_ID) .await - .expect("Failed to send nominate request"); + .unwrap_err() + .to_string(); - assert_eq!(res, Vec::::new()); + assert!(res.contains("InsufficientBond")); let res = staking_builtin_client .payout_stakers(H256::random().into(), 1) .send_recv(STAKING_BUILTIN_ID) .await - .expect("Failed to send payout_stakers request"); + .unwrap_err() + .to_string(); - assert_eq!(res, Vec::::new()); + assert!(res.contains("NotStash")); } diff --git a/examples/builtins/app/tests/program.rs b/examples/builtins/app/tests/program.rs index 910cb5e9a..02d4aa2fb 100644 --- a/examples/builtins/app/tests/program.rs +++ b/examples/builtins/app/tests/program.rs @@ -1,8 +1,8 @@ /// These tests make interact with builtins from app context. use builtins_example_app::WASM_BINARY; use builtins_example_client::{ - BuiltinsExampleClientFactory, ProxyBroker, ProxyType, - traits::{BuiltinsExampleClientFactory as _, ProxyBroker as _}, + BuiltinsExampleClientFactory, ProxyBroker, ProxyType, RewardAccount, StakingBroker, + traits::{BuiltinsExampleClientFactory as _, ProxyBroker as _, StakingBroker as _}, }; use gclient::GearApi; use sails_rs::{ @@ -34,9 +34,10 @@ async fn call_proxy_builtin_from_app() { .await .expect("Failed to transfer funds to program"); + let proxy_addr = H256::random().into(); let mut proxy_broker_client = ProxyBroker::new(remoting.clone()); let resp = proxy_broker_client - .add_proxy(H256::random().into(), ProxyType::Any) + .add_proxy(proxy_addr, ProxyType::Any) .send_recv(builtins_broker_pid) .await .expect("Failed to send proxy request"); @@ -44,10 +45,88 @@ async fn call_proxy_builtin_from_app() { assert_eq!(resp, Ok(Vec::::new())); let resp = proxy_broker_client - .remove_proxy(H256::random().into(), ProxyType::Any) + .remove_proxy(proxy_addr, ProxyType::Any) .send_recv(builtins_broker_pid) .await .expect("Failed to send proxy request"); assert_eq!(resp, Ok(Vec::::new())); } + +#[tokio::test] +async fn call_staking_builtin_from_app() { + let api = GearApi::dev().await.unwrap(); + + let (code_id, _) = api + .upload_code(WASM_BINARY) + .await + .expect("Failed to upload program code"); + + let remoting = GClientRemoting::new(api.clone()); + + let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) + .new() + .send_recv(code_id, b"builtins-example-app") + .await + .expect("Failed program init message"); + + api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) + .await + .expect("Failed to transfer funds to program"); + + let mut staking_builtin_client = StakingBroker::new(remoting.clone()); + + let resp = staking_builtin_client + .bond(5 * ONE_VARA, RewardAccount::None) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send bond request"); + assert_eq!(resp, Ok(Vec::::new())); + + let resp = staking_builtin_client + .bond_extra(2 * ONE_VARA) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send bond_extra request"); + assert_eq!(resp, Ok(Vec::::new())); + + let resp = staking_builtin_client + .rebond(4 * ONE_VARA) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send rebond request") + .unwrap_err(); + + assert!(resp.to_string().contains("NoUnlockChunk")); + + let resp = staking_builtin_client + .set_payee(RewardAccount::Program) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send set_payee request"); + + assert_eq!(resp, Ok(Vec::::new())); + + // todo [sab] invalid gas count for `unbond` call + + let resp = staking_builtin_client + .chill() + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send chill request"); + + assert_eq!(resp, Ok(Vec::::new())); + + // todo [sab] invalid gas count for `withdraw_unbonded` call + + let resp = staking_builtin_client + .nominate(vec![H256::random().into()]) + .send_recv(builtins_broker_pid) + .await + .expect("Failed to send nominate request") + .unwrap_err(); + + assert!(resp.to_string().contains("InsufficientBond")); + + // todo [sab] invalid gas count for `payout_stakers` call +} From 43ad242c0542f6c0c3f8a4f245fed65c5d16afce Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 22 Jul 2025 18:50:33 +0300 Subject: [PATCH 07/16] prepare for gas calc bug showcase --- examples/builtins/app/src/bls381.rs | 59 ------ examples/builtins/app/tests/extrinsic.rs | 110 ++++++----- examples/builtins/app/tests/program.rs | 223 ++++++++++++++++------- 3 files changed, 226 insertions(+), 166 deletions(-) diff --git a/examples/builtins/app/src/bls381.rs b/examples/builtins/app/src/bls381.rs index 695844ad7..61dd5a428 100644 --- a/examples/builtins/app/src/bls381.rs +++ b/examples/builtins/app/src/bls381.rs @@ -2,65 +2,6 @@ use super::*; pub struct Bls381Broker; -// Requests -// /// Request to pairing multi Miller loop for *BLS12-381*. -// /// -// /// Encoded: -// /// - `a`: [`ArkScale>`]. -// /// - `b`: [`ArkScale>`]. -// #[codec(index = 0)] -// MultiMillerLoop { a: Vec, b: Vec }, - -// /// Request to pairing final exponentiation for *BLS12-381*. -// /// -// /// Encoded: [`ArkScale<`]. -// #[codec(index = 1)] -// FinalExponentiation { f: Vec }, - -// /// Request to multi scalar multiplication on *G1* for *BLS12-381* -// /// -// /// Encoded: -// /// - `bases`: [`ArkScale>`]. -// /// - `scalars`: [`ArkScale>`]. -// #[codec(index = 2)] -// MultiScalarMultiplicationG1 { bases: Vec, scalars: Vec }, - -// /// Request to multi scalar multiplication on *G2* for *BLS12-381* -// /// -// /// Encoded: -// /// - `bases`: [`ArkScale>`]. -// /// - `scalars`: [`ArkScale>`]. -// #[codec(index = 3)] -// MultiScalarMultiplicationG2 { bases: Vec, scalars: Vec }, - -// /// Request to projective multiplication on *G1* for *BLS12-381*. -// /// -// /// Encoded: -// /// - `base`: [`ArkScaleProjective`]. -// /// - `scalar`: [`ArkScale>`]. -// #[codec(index = 4)] -// ProjectiveMultiplicationG1 { base: Vec, scalar: Vec }, - -// /// Request to projective multiplication on *G2* for *BLS12-381*. -// /// -// /// Encoded: -// /// - `base`: [`ArkScaleProjective`]. -// /// - `scalar`: [`ArkScale>`]. -// #[codec(index = 5)] -// ProjectiveMultiplicationG2 { base: Vec, scalar: Vec }, - -// /// Request to aggregate *G1* points for *BLS12-381*. -// /// -// /// Encoded: [`ArkScale>`]. -// #[codec(index = 6)] -// AggregateG1 { points: Vec }, - -// /// Request to map an arbitrary message to *G2Affine* point for *BLS12-381*. -// /// -// /// Raw message bytes to map. -// #[codec(index = 7)] -// MapToG2Affine { message: Vec }, - #[sails_rs::service] impl Bls381Broker { #[export] diff --git a/examples/builtins/app/tests/extrinsic.rs b/examples/builtins/app/tests/extrinsic.rs index 1d7ad24b4..c33568b4f 100644 --- a/examples/builtins/app/tests/extrinsic.rs +++ b/examples/builtins/app/tests/extrinsic.rs @@ -1,15 +1,13 @@ use gclient::GearApi; /// These tests make interact with builtins from non-app (program) context via extrinsics (calls). use sails_rs::{ - H256, builtins::{ - PROXY_BUILTIN_ID, ProxyBuiltin, ProxyType as SailsProxyType, RewardAccount, - STAKING_BUILTIN_ID, StakingBuiltin, - }, - calls::Call, - gclient::calls::GClientRemoting, + Bls381Builtin, Bls381Request, ProxyBuiltin, ProxyType as SailsProxyType, RewardAccount, StakingBuiltin, BLS381_BUILTIN_ID, PROXY_BUILTIN_ID, STAKING_BUILTIN_ID + }, calls::Call, gclient::calls::GClientRemoting, H256 }; +const ONE_VARA: u128 = 1_000_000_000_000; + #[tokio::test] async fn call_proxy_builtin_with_extrinsic() { let api = GearApi::dev().await.unwrap(); @@ -43,64 +41,88 @@ async fn call_staking_builtin_with_extrinsic() { let staking_builtin_client = StakingBuiltin::new(remoting); let res = staking_builtin_client - .bond(1_000_000_000_000, RewardAccount::None) + .bond(5 * ONE_VARA, RewardAccount::None) .send_recv(STAKING_BUILTIN_ID) .await .expect("Failed to send bond request"); assert_eq!(res, Vec::::new()); - let res = staking_builtin_client - .bond_extra(500_000_000_000) - .send_recv(STAKING_BUILTIN_ID) - .await - .expect("Failed to send bond_extra request"); + // let res = staking_builtin_client + // .bond_extra(500_000_000_000) + // .send_recv(STAKING_BUILTIN_ID) + // .await + // .expect("Failed to send bond_extra request"); - assert_eq!(res, Vec::::new()); + // assert_eq!(res, Vec::::new()); - let res = staking_builtin_client - .rebond(2_000_000_000_000) - .send_recv(STAKING_BUILTIN_ID) - .await - .unwrap_err() - .to_string(); - assert!(res.contains("NoUnlockChunk")); + // let res = staking_builtin_client + // .rebond(2_000_000_000_000) + // .send_recv(STAKING_BUILTIN_ID) + // .await + // .unwrap_err() + // .to_string(); + // assert!(res.contains("NoUnlockChunk")); - let res = staking_builtin_client - .set_payee(RewardAccount::Staked) - .send_recv(STAKING_BUILTIN_ID) - .await - .expect("Failed to send set_payee request"); + // let res = staking_builtin_client + // .set_payee(RewardAccount::Staked) + // .send_recv(STAKING_BUILTIN_ID) + // .await + // .expect("Failed to send set_payee request"); - assert_eq!(res, Vec::::new()); + // assert_eq!(res, Vec::::new()); // todo [sab] invalid gas count for `unbond` call - let res = staking_builtin_client - .chill() + let _res = staking_builtin_client + .unbond(2 * ONE_VARA) .send_recv(STAKING_BUILTIN_ID) .await - .expect("Failed to send chill request"); + .expect("Failed to send unbond request"); - assert_eq!(res, Vec::::new()); + // let res = staking_builtin_client + // .chill() + // .send_recv(STAKING_BUILTIN_ID) + // .await + // .expect("Failed to send chill request"); + + // assert_eq!(res, Vec::::new()); // todo [sab] invalid gas count for `withdraw_unbonded` call - let res = staking_builtin_client - .nominate(vec![H256::random().into()]) - .send_recv(STAKING_BUILTIN_ID) - .await - .unwrap_err() - .to_string(); + // let res = staking_builtin_client + // .nominate(vec![H256::random().into()]) + // .send_recv(STAKING_BUILTIN_ID) + // .await + // .unwrap_err() + // .to_string(); - assert!(res.contains("InsufficientBond")); + // assert!(res.contains("InsufficientBond")); - let res = staking_builtin_client - .payout_stakers(H256::random().into(), 1) - .send_recv(STAKING_BUILTIN_ID) - .await - .unwrap_err() - .to_string(); + // let res = staking_builtin_client + // .payout_stakers(H256::random().into(), 1) + // .send_recv(STAKING_BUILTIN_ID) + // .await + // .unwrap_err() + // .to_string(); - assert!(res.contains("NotStash")); + // assert!(res.contains("NotStash")); } + +// #[tokio::test] +// async fn call_bls381_builtin_with_extrinsic() { +// use sails_rs::Encode; +// let api = GearApi::dev().await.unwrap(); + +// let remoting = GClientRemoting::new(api.clone()); +// let bls381_builtin_client = Bls381Builtin::new(remoting); + +// let res = bls381_builtin_client +// .multi_miller_loop(vec![1u8, 2, 3].encode(), vec![4u8, 5, 6].encode()) +// .send_recv(BLS381_BUILTIN_ID) +// .await +// .unwrap_err() +// .to_string(); + +// println!("Response: {:?}", res); +// } \ No newline at end of file diff --git a/examples/builtins/app/tests/program.rs b/examples/builtins/app/tests/program.rs index 02d4aa2fb..1fc25defd 100644 --- a/examples/builtins/app/tests/program.rs +++ b/examples/builtins/app/tests/program.rs @@ -1,57 +1,57 @@ /// These tests make interact with builtins from app context. use builtins_example_app::WASM_BINARY; use builtins_example_client::{ - BuiltinsExampleClientFactory, ProxyBroker, ProxyType, RewardAccount, StakingBroker, - traits::{BuiltinsExampleClientFactory as _, ProxyBroker as _, StakingBroker as _}, + traits::{Bls381Broker as _, BuiltinsExampleClientFactory as _, ProxyBroker as _, StakingBroker as _}, Bls381Broker, Bls381Response, BuiltinsExampleClientFactory, ProxyBroker, ProxyType, RewardAccount, StakingBroker }; use gclient::GearApi; use sails_rs::{ H256, calls::{Activation, Call}, gclient::calls::GClientRemoting, + Encode, }; const ONE_VARA: u128 = 1_000_000_000_000; -#[tokio::test] -async fn call_proxy_builtin_from_app() { - let api = GearApi::dev().await.unwrap(); +// #[tokio::test] +// async fn call_proxy_builtin_from_app() { +// let api = GearApi::dev().await.unwrap(); - let (code_id, _) = api - .upload_code(WASM_BINARY) - .await - .expect("Failed to upload program code"); +// let (code_id, _) = api +// .upload_code(WASM_BINARY) +// .await +// .expect("Failed to upload program code"); - let remoting = GClientRemoting::new(api.clone()); +// let remoting = GClientRemoting::new(api.clone()); - let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) - .new() - .send_recv(code_id, b"builtins-example-app") - .await - .expect("Failed program init message"); +// let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) +// .new() +// .send_recv(code_id, b"builtins-example-app") +// .await +// .expect("Failed program init message"); - api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) - .await - .expect("Failed to transfer funds to program"); +// api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) +// .await +// .expect("Failed to transfer funds to program"); - let proxy_addr = H256::random().into(); - let mut proxy_broker_client = ProxyBroker::new(remoting.clone()); - let resp = proxy_broker_client - .add_proxy(proxy_addr, ProxyType::Any) - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send proxy request"); +// let proxy_addr = H256::random().into(); +// let mut proxy_broker_client = ProxyBroker::new(remoting.clone()); +// let resp = proxy_broker_client +// .add_proxy(proxy_addr, ProxyType::Any) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send proxy request"); - assert_eq!(resp, Ok(Vec::::new())); +// assert_eq!(resp, Ok(Vec::::new())); - let resp = proxy_broker_client - .remove_proxy(proxy_addr, ProxyType::Any) - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send proxy request"); +// let resp = proxy_broker_client +// .remove_proxy(proxy_addr, ProxyType::Any) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send proxy request"); - assert_eq!(resp, Ok(Vec::::new())); -} +// assert_eq!(resp, Ok(Vec::::new())); +// } #[tokio::test] async fn call_staking_builtin_from_app() { @@ -76,6 +76,8 @@ async fn call_staking_builtin_from_app() { let mut staking_builtin_client = StakingBroker::new(remoting.clone()); + // todo [sab] invalid gas count for `unbond` call + let resp = staking_builtin_client .bond(5 * ONE_VARA, RewardAccount::None) .send_recv(builtins_broker_pid) @@ -83,50 +85,145 @@ async fn call_staking_builtin_from_app() { .expect("Failed to send bond request"); assert_eq!(resp, Ok(Vec::::new())); - let resp = staking_builtin_client - .bond_extra(2 * ONE_VARA) - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send bond_extra request"); - assert_eq!(resp, Ok(Vec::::new())); + // let resp = staking_builtin_client + // .bond_extra(2 * ONE_VARA) + // .send_recv(builtins_broker_pid) + // .await + // .expect("Failed to send bond_extra request"); + // assert_eq!(resp, Ok(Vec::::new())); - let resp = staking_builtin_client - .rebond(4 * ONE_VARA) - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send rebond request") - .unwrap_err(); + // let resp = staking_builtin_client + // .rebond(4 * ONE_VARA) + // .send_recv(builtins_broker_pid) + // .await + // .expect("Failed to send rebond request") + // .unwrap_err(); + + // assert!(resp.to_string().contains("NoUnlockChunk")); - assert!(resp.to_string().contains("NoUnlockChunk")); + // let resp = staking_builtin_client + // .set_payee(RewardAccount::Program) + // .send_recv(builtins_broker_pid) + // .await + // .expect("Failed to send set_payee request"); + + // assert_eq!(resp, Ok(Vec::::new())); let resp = staking_builtin_client - .set_payee(RewardAccount::Program) + .unbond(2 * ONE_VARA) .send_recv(builtins_broker_pid) - .await - .expect("Failed to send set_payee request"); + .await; - assert_eq!(resp, Ok(Vec::::new())); + println!("Resp: {:#?}", resp); // todo [sab] invalid gas count for `unbond` call - let resp = staking_builtin_client - .chill() - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send chill request"); + // let resp = staking_builtin_client + // .chill() + // .send_recv(builtins_broker_pid) + // .await + // .expect("Failed to send chill request"); - assert_eq!(resp, Ok(Vec::::new())); + // assert_eq!(resp, Ok(Vec::::new())); // todo [sab] invalid gas count for `withdraw_unbonded` call - let resp = staking_builtin_client - .nominate(vec![H256::random().into()]) - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send nominate request") - .unwrap_err(); + // let resp = staking_builtin_client + // .nominate(vec![H256::random().into()]) + // .send_recv(builtins_broker_pid) + // .await + // .expect("Failed to send nominate request") + // .unwrap_err(); - assert!(resp.to_string().contains("InsufficientBond")); + // assert!(resp.to_string().contains("InsufficientBond")); // todo [sab] invalid gas count for `payout_stakers` call } + +// #[tokio::test] +// async fn call_bls381_builtin_from_app() { +// let api = GearApi::dev().await.unwrap(); + +// let (code_id, _) = api +// .upload_code(WASM_BINARY) +// .await +// .expect("Failed to upload program code"); + +// let remoting = GClientRemoting::new(api.clone()); + +// let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) +// .new() +// .send_recv(code_id, b"builtins-example-app") +// .await +// .expect("Failed program init message"); + +// api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) +// .await +// .expect("Failed to transfer funds to program"); + +// let mut bls381_builtin_client = Bls381Broker::new(remoting.clone()); + +// let resp = bls381_builtin_client +// .multi_miller_loop(vec![1, 2, 3].encode(), vec![4, 5, 6].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send multi_miller_loop request"); + +// assert!(matches!(resp, Ok(Bls381Response::MultiMillerLoop(_)))); + +// let resp = bls381_builtin_client +// .final_exponentiation(vec![7, 8, 9].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send final_exponentiation request"); + +// assert!(matches!(resp, Ok(Bls381Response::FinalExponentiation(_)))); + +// let resp = bls381_builtin_client +// .multi_scalar_multiplication_g_1(vec![10, 11].encode(), vec![12, 13].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send multi_scalar_multiplication_g1 request"); + +// assert!(matches!(resp, Ok(Bls381Response::MultiScalarMultiplicationG1(_)))); + +// let resp = bls381_builtin_client +// .multi_scalar_multiplication_g_2(vec![14, 15].encode(), vec![16, 17].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send multi_scalar_multiplication_g2 request"); + +// assert!(matches!(resp, Ok(Bls381Response::MultiScalarMultiplicationG2(_)))); + +// let resp = bls381_builtin_client +// .projective_multiplication_g_1(vec![18, 19].encode(), vec![20, 21].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send projective_multiplication_g1 request"); + +// assert!(matches!(resp, Ok(Bls381Response::ProjectiveMultiplicationG1(_)))); + +// let resp = bls381_builtin_client +// .projective_multiplication_g_2(vec![22, 23].encode(), vec![24, 25].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send projective_multiplication_g2 request"); + +// assert!(matches!(resp, Ok(Bls381Response::ProjectiveMultiplicationG2(_)))); + +// let resp = bls381_builtin_client +// .aggregate_g_1(vec![26, 27].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send aggregate_g_1 request"); + +// assert!(matches!(resp, Ok(Bls381Response::AggregateG1(_)))); + +// let resp = bls381_builtin_client +// .map_to_g_2_affine(vec![28, 29].encode()) +// .send_recv(builtins_broker_pid) +// .await +// .expect("Failed to send map_to_g_2_affine request"); + +// assert!(matches!(resp, Ok(Bls381Response::MapToG2Affine(_)))); +// } From baa72737cc88fcd1fc16a18de5beb748d15a929c Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 22 Jul 2025 18:51:07 +0300 Subject: [PATCH 08/16] prepare for gas calc bug showcase #2 --- examples/builtins/app/tests/extrinsic.rs | 38 ++++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/builtins/app/tests/extrinsic.rs b/examples/builtins/app/tests/extrinsic.rs index c33568b4f..e4e998778 100644 --- a/examples/builtins/app/tests/extrinsic.rs +++ b/examples/builtins/app/tests/extrinsic.rs @@ -8,30 +8,30 @@ use sails_rs::{ const ONE_VARA: u128 = 1_000_000_000_000; -#[tokio::test] -async fn call_proxy_builtin_with_extrinsic() { - let api = GearApi::dev().await.unwrap(); +// #[tokio::test] +// async fn call_proxy_builtin_with_extrinsic() { +// let api = GearApi::dev().await.unwrap(); - let remoting = GClientRemoting::new(api.clone()); +// let remoting = GClientRemoting::new(api.clone()); - let proxy = ProxyBuiltin::new(remoting); - let random_actor_id = H256::random().into(); - let res = proxy - .add_proxy(random_actor_id, SailsProxyType::Any) - .send_recv(PROXY_BUILTIN_ID) - .await - .expect("Failed to send proxy request"); +// let proxy = ProxyBuiltin::new(remoting); +// let random_actor_id = H256::random().into(); +// let res = proxy +// .add_proxy(random_actor_id, SailsProxyType::Any) +// .send_recv(PROXY_BUILTIN_ID) +// .await +// .expect("Failed to send proxy request"); - assert_eq!(res, Vec::::new()); +// assert_eq!(res, Vec::::new()); - let res = proxy - .remove_proxy(random_actor_id, SailsProxyType::Any) - .send_recv(PROXY_BUILTIN_ID) - .await - .expect("Failed to send proxy request"); +// let res = proxy +// .remove_proxy(random_actor_id, SailsProxyType::Any) +// .send_recv(PROXY_BUILTIN_ID) +// .await +// .expect("Failed to send proxy request"); - assert_eq!(res, Vec::::new()); -} +// assert_eq!(res, Vec::::new()); +// } #[tokio::test] async fn call_staking_builtin_with_extrinsic() { From e304cc8044ade287f2ff8d985c1e556e74df8702 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 23 Jul 2025 12:27:22 +0300 Subject: [PATCH 09/16] Change tests approach to be codec tests --- Cargo.lock | 19 - Cargo.toml | 2 +- examples/builtins/app/Cargo.toml | 17 - examples/builtins/app/build.rs | 3 - examples/builtins/app/src/bls381.rs | 114 --- examples/builtins/app/src/eth_bridge.rs | 21 - examples/builtins/app/src/lib.rs | 47 -- examples/builtins/app/src/proxy.rs | 36 - examples/builtins/app/src/staking.rs | 109 --- examples/builtins/app/tests/extrinsic.rs | 128 --- examples/builtins/app/tests/program.rs | 229 ------ examples/builtins/client/Cargo.toml | 11 - examples/builtins/client/build.rs | 3 - .../client/builtins_example_client.idl | 86 -- .../client/src/builtins_example_client.rs | 759 ------------------ examples/builtins/client/src/lib.rs | 4 - rs/src/builtins/bls381.rs | 96 ++- rs/src/builtins/eth_bridge.rs | 27 +- rs/src/builtins/mod.rs | 48 +- rs/src/builtins/proxy.rs | 34 +- rs/src/builtins/staking.rs | 56 +- 21 files changed, 220 insertions(+), 1629 deletions(-) delete mode 100644 examples/builtins/app/Cargo.toml delete mode 100644 examples/builtins/app/build.rs delete mode 100644 examples/builtins/app/src/bls381.rs delete mode 100644 examples/builtins/app/src/eth_bridge.rs delete mode 100644 examples/builtins/app/src/lib.rs delete mode 100644 examples/builtins/app/src/proxy.rs delete mode 100644 examples/builtins/app/src/staking.rs delete mode 100644 examples/builtins/app/tests/extrinsic.rs delete mode 100644 examples/builtins/app/tests/program.rs delete mode 100644 examples/builtins/client/Cargo.toml delete mode 100644 examples/builtins/client/build.rs delete mode 100644 examples/builtins/client/builtins_example_client.idl delete mode 100644 examples/builtins/client/src/builtins_example_client.rs delete mode 100644 examples/builtins/client/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 49ac0a599..4daaf3268 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,25 +936,6 @@ dependencies = [ "serde", ] -[[package]] -name = "builtins-example-app" -version = "0.8.1" -dependencies = [ - "builtins-example-client", - "gclient", - "log", - "sails-rs", - "tokio", -] - -[[package]] -name = "builtins-example-client" -version = "0.8.1" -dependencies = [ - "builtins-example-app", - "sails-rs", -] - [[package]] name = "bumpalo" version = "3.17.0" diff --git a/Cargo.toml b/Cargo.toml index 634ed593c..17d16f98a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ members = [ "rs/idl-parser", "rs/macros", "rs/macros/core", - "rs/sol-gen", "examples/builtins/app", "examples/builtins/client", + "rs/sol-gen", ] [workspace.dependencies] diff --git a/examples/builtins/app/Cargo.toml b/examples/builtins/app/Cargo.toml deleted file mode 100644 index e35cf9eec..000000000 --- a/examples/builtins/app/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "builtins-example-app" -version.workspace = true -edition.workspace = true - -[dependencies] -sails-rs.workspace = true - -[build-dependencies] -sails-rs = { workspace = true, features = ["wasm-builder"] } - -[dev-dependencies] -tokio = { workspace = true, features = ["rt", "macros"] } -gclient.workspace = true -log.workspace = true -sails-rs = { workspace = true, features = ["gclient"] } -builtins-example-client = { path = "../client" } diff --git a/examples/builtins/app/build.rs b/examples/builtins/app/build.rs deleted file mode 100644 index 0b315b06e..000000000 --- a/examples/builtins/app/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - sails_rs::build_wasm(); -} diff --git a/examples/builtins/app/src/bls381.rs b/examples/builtins/app/src/bls381.rs deleted file mode 100644 index 61dd5a428..000000000 --- a/examples/builtins/app/src/bls381.rs +++ /dev/null @@ -1,114 +0,0 @@ -use super::*; - -pub struct Bls381Broker; - -#[sails_rs::service] -impl Bls381Broker { - #[export] - pub async fn multi_miller_loop( - &mut self, - a: Vec, - b: Vec, - ) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .multi_miller_loop(a, b) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn final_exponentiation(&mut self, f: Vec) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .final_exponentiation(f) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn multi_scalar_multiplication_g1( - &mut self, - bases: Vec, - scalars: Vec, - ) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .multi_scalar_multiplication_g1(bases, scalars) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn multi_scalar_multiplication_g2( - &mut self, - bases: Vec, - scalars: Vec, - ) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .multi_scalar_multiplication_g2(bases, scalars) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn projective_multiplication_g1( - &mut self, - base: Vec, - scalar: Vec, - ) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .projective_multiplication_g1(base, scalar) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn projective_multiplication_g2( - &mut self, - base: Vec, - scalar: Vec, - ) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .projective_multiplication_g2(base, scalar) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn aggregate_g1(&mut self, points: Vec) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .aggregate_g1(points) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } - - #[export] - pub async fn map_to_g2_affine(&mut self, message: Vec) -> Result { - let bls381_builtin_client = Bls381Builtin::new(GStdRemoting::new()); - - bls381_builtin_client - .map_to_g2_affine(message) - .send_recv(BLS381_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending bls381 builtin request: {e}")) - } -} diff --git a/examples/builtins/app/src/eth_bridge.rs b/examples/builtins/app/src/eth_bridge.rs deleted file mode 100644 index e4e7ffe24..000000000 --- a/examples/builtins/app/src/eth_bridge.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::*; - -pub struct EthBridgeBroker; - -#[sails_rs::service] -impl EthBridgeBroker { - #[export] - pub async fn send_eth_message( - &mut self, - destination: H160, - payload: Vec, - ) -> Result { - let eth_bridge_builtin_client = EthBridgeRemoting::new(GStdRemoting::new()); - - eth_bridge_builtin_client - .send_eth_message(destination, payload) - .send_recv(ETH_BRIDGE_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending eth bridge builtin request: {e}")) - } -} diff --git a/examples/builtins/app/src/lib.rs b/examples/builtins/app/src/lib.rs deleted file mode 100644 index 8aca6325e..000000000 --- a/examples/builtins/app/src/lib.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![no_std] - -mod bls381; -mod eth_bridge; -mod proxy; -mod staking; - -use bls381::Bls381Broker; -use eth_bridge::EthBridgeBroker; -use proxy::ProxyBroker; -use sails_rs::{builtins::*, calls::Call, gstd::calls::GStdRemoting, prelude::*}; -use staking::StakingBroker; - -#[derive(Default)] -pub struct BuiltinsBroker(()); - -#[sails_rs::program] -impl BuiltinsBroker { - // Program's constructor - pub fn new() -> Self { - Self(()) - } - - pub fn proxy_broker(&self) -> ProxyBroker { - ProxyBroker - } - - pub fn staking_broker(&self) -> StakingBroker { - StakingBroker - } - - pub fn bls381_broker(&self) -> Bls381Broker { - Bls381Broker - } - - pub fn eth_bridge_broker(&self) -> EthBridgeBroker { - EthBridgeBroker - } -} - -#[cfg(not(target_arch = "wasm32"))] -pub use code::WASM_BINARY_OPT as WASM_BINARY; - -#[cfg(not(target_arch = "wasm32"))] -mod code { - include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -} diff --git a/examples/builtins/app/src/proxy.rs b/examples/builtins/app/src/proxy.rs deleted file mode 100644 index 8a091cce3..000000000 --- a/examples/builtins/app/src/proxy.rs +++ /dev/null @@ -1,36 +0,0 @@ -use super::*; - -pub struct ProxyBroker; - -#[sails_rs::service] -impl ProxyBroker { - #[export] - pub async fn add_proxy( - &mut self, - delegate: ActorId, - proxy_type: ProxyType, - ) -> Result, String> { - let proxy_builtin_client = ProxyBuiltin::new(GStdRemoting::new()); - - proxy_builtin_client - .add_proxy(delegate, proxy_type) - .send_recv(PROXY_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending proxy builtin request: {e}")) - } - - #[export] - pub async fn remove_proxy( - &mut self, - delegate: ActorId, - proxy_type: ProxyType, - ) -> Result, String> { - let proxy_builtin_client = ProxyBuiltin::new(GStdRemoting::new()); - - proxy_builtin_client - .remove_proxy(delegate, proxy_type) - .send_recv(PROXY_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending proxy builtin request: {e}")) - } -} diff --git a/examples/builtins/app/src/staking.rs b/examples/builtins/app/src/staking.rs deleted file mode 100644 index b44c222d7..000000000 --- a/examples/builtins/app/src/staking.rs +++ /dev/null @@ -1,109 +0,0 @@ -use super::*; - -pub struct StakingBroker; - -#[sails_rs::service] -impl StakingBroker { - #[export] - pub async fn bond(&mut self, value: u128, payee: RewardAccount) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .bond(value, payee) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn bond_extra(&mut self, value: u128) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .bond_extra(value) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn unbond(&mut self, value: u128) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .unbond(value) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn withdraw_unbonded(&mut self, num_slashing_spans: u32) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .withdraw_unbonded(num_slashing_spans) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn nominate(&mut self, targets: Vec) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .nominate(targets) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn chill(&mut self) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .chill() - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn payout_stakers( - &mut self, - validator_stash: ActorId, - era: u32, - ) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .payout_stakers(validator_stash, era) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn rebond(&mut self, value: u128) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .rebond(value) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } - - #[export] - pub async fn set_payee(&mut self, payee: RewardAccount) -> Result, String> { - let staking_builtin_client = StakingBuiltin::new(GStdRemoting::new()); - - staking_builtin_client - .set_payee(payee) - .send_recv(STAKING_BUILTIN_ID) - .await - .map_err(|e| format!("failed sending staking builtin request: {e}")) - } -} diff --git a/examples/builtins/app/tests/extrinsic.rs b/examples/builtins/app/tests/extrinsic.rs deleted file mode 100644 index e4e998778..000000000 --- a/examples/builtins/app/tests/extrinsic.rs +++ /dev/null @@ -1,128 +0,0 @@ -use gclient::GearApi; -/// These tests make interact with builtins from non-app (program) context via extrinsics (calls). -use sails_rs::{ - builtins::{ - Bls381Builtin, Bls381Request, ProxyBuiltin, ProxyType as SailsProxyType, RewardAccount, StakingBuiltin, BLS381_BUILTIN_ID, PROXY_BUILTIN_ID, STAKING_BUILTIN_ID - }, calls::Call, gclient::calls::GClientRemoting, H256 -}; - -const ONE_VARA: u128 = 1_000_000_000_000; - -// #[tokio::test] -// async fn call_proxy_builtin_with_extrinsic() { -// let api = GearApi::dev().await.unwrap(); - -// let remoting = GClientRemoting::new(api.clone()); - -// let proxy = ProxyBuiltin::new(remoting); -// let random_actor_id = H256::random().into(); -// let res = proxy -// .add_proxy(random_actor_id, SailsProxyType::Any) -// .send_recv(PROXY_BUILTIN_ID) -// .await -// .expect("Failed to send proxy request"); - -// assert_eq!(res, Vec::::new()); - -// let res = proxy -// .remove_proxy(random_actor_id, SailsProxyType::Any) -// .send_recv(PROXY_BUILTIN_ID) -// .await -// .expect("Failed to send proxy request"); - -// assert_eq!(res, Vec::::new()); -// } - -#[tokio::test] -async fn call_staking_builtin_with_extrinsic() { - let api = GearApi::dev().await.unwrap(); - - let remoting = GClientRemoting::new(api.clone()); - let staking_builtin_client = StakingBuiltin::new(remoting); - - let res = staking_builtin_client - .bond(5 * ONE_VARA, RewardAccount::None) - .send_recv(STAKING_BUILTIN_ID) - .await - .expect("Failed to send bond request"); - - assert_eq!(res, Vec::::new()); - - // let res = staking_builtin_client - // .bond_extra(500_000_000_000) - // .send_recv(STAKING_BUILTIN_ID) - // .await - // .expect("Failed to send bond_extra request"); - - // assert_eq!(res, Vec::::new()); - - // let res = staking_builtin_client - // .rebond(2_000_000_000_000) - // .send_recv(STAKING_BUILTIN_ID) - // .await - // .unwrap_err() - // .to_string(); - // assert!(res.contains("NoUnlockChunk")); - - // let res = staking_builtin_client - // .set_payee(RewardAccount::Staked) - // .send_recv(STAKING_BUILTIN_ID) - // .await - // .expect("Failed to send set_payee request"); - - // assert_eq!(res, Vec::::new()); - - // todo [sab] invalid gas count for `unbond` call - - let _res = staking_builtin_client - .unbond(2 * ONE_VARA) - .send_recv(STAKING_BUILTIN_ID) - .await - .expect("Failed to send unbond request"); - - // let res = staking_builtin_client - // .chill() - // .send_recv(STAKING_BUILTIN_ID) - // .await - // .expect("Failed to send chill request"); - - // assert_eq!(res, Vec::::new()); - - // todo [sab] invalid gas count for `withdraw_unbonded` call - - // let res = staking_builtin_client - // .nominate(vec![H256::random().into()]) - // .send_recv(STAKING_BUILTIN_ID) - // .await - // .unwrap_err() - // .to_string(); - - // assert!(res.contains("InsufficientBond")); - - // let res = staking_builtin_client - // .payout_stakers(H256::random().into(), 1) - // .send_recv(STAKING_BUILTIN_ID) - // .await - // .unwrap_err() - // .to_string(); - - // assert!(res.contains("NotStash")); -} - -// #[tokio::test] -// async fn call_bls381_builtin_with_extrinsic() { -// use sails_rs::Encode; -// let api = GearApi::dev().await.unwrap(); - -// let remoting = GClientRemoting::new(api.clone()); -// let bls381_builtin_client = Bls381Builtin::new(remoting); - -// let res = bls381_builtin_client -// .multi_miller_loop(vec![1u8, 2, 3].encode(), vec![4u8, 5, 6].encode()) -// .send_recv(BLS381_BUILTIN_ID) -// .await -// .unwrap_err() -// .to_string(); - -// println!("Response: {:?}", res); -// } \ No newline at end of file diff --git a/examples/builtins/app/tests/program.rs b/examples/builtins/app/tests/program.rs deleted file mode 100644 index 1fc25defd..000000000 --- a/examples/builtins/app/tests/program.rs +++ /dev/null @@ -1,229 +0,0 @@ -/// These tests make interact with builtins from app context. -use builtins_example_app::WASM_BINARY; -use builtins_example_client::{ - traits::{Bls381Broker as _, BuiltinsExampleClientFactory as _, ProxyBroker as _, StakingBroker as _}, Bls381Broker, Bls381Response, BuiltinsExampleClientFactory, ProxyBroker, ProxyType, RewardAccount, StakingBroker -}; -use gclient::GearApi; -use sails_rs::{ - H256, - calls::{Activation, Call}, - gclient::calls::GClientRemoting, - Encode, -}; - -const ONE_VARA: u128 = 1_000_000_000_000; - -// #[tokio::test] -// async fn call_proxy_builtin_from_app() { -// let api = GearApi::dev().await.unwrap(); - -// let (code_id, _) = api -// .upload_code(WASM_BINARY) -// .await -// .expect("Failed to upload program code"); - -// let remoting = GClientRemoting::new(api.clone()); - -// let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) -// .new() -// .send_recv(code_id, b"builtins-example-app") -// .await -// .expect("Failed program init message"); - -// api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) -// .await -// .expect("Failed to transfer funds to program"); - -// let proxy_addr = H256::random().into(); -// let mut proxy_broker_client = ProxyBroker::new(remoting.clone()); -// let resp = proxy_broker_client -// .add_proxy(proxy_addr, ProxyType::Any) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send proxy request"); - -// assert_eq!(resp, Ok(Vec::::new())); - -// let resp = proxy_broker_client -// .remove_proxy(proxy_addr, ProxyType::Any) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send proxy request"); - -// assert_eq!(resp, Ok(Vec::::new())); -// } - -#[tokio::test] -async fn call_staking_builtin_from_app() { - let api = GearApi::dev().await.unwrap(); - - let (code_id, _) = api - .upload_code(WASM_BINARY) - .await - .expect("Failed to upload program code"); - - let remoting = GClientRemoting::new(api.clone()); - - let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) - .new() - .send_recv(code_id, b"builtins-example-app") - .await - .expect("Failed program init message"); - - api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) - .await - .expect("Failed to transfer funds to program"); - - let mut staking_builtin_client = StakingBroker::new(remoting.clone()); - - // todo [sab] invalid gas count for `unbond` call - - let resp = staking_builtin_client - .bond(5 * ONE_VARA, RewardAccount::None) - .send_recv(builtins_broker_pid) - .await - .expect("Failed to send bond request"); - assert_eq!(resp, Ok(Vec::::new())); - - // let resp = staking_builtin_client - // .bond_extra(2 * ONE_VARA) - // .send_recv(builtins_broker_pid) - // .await - // .expect("Failed to send bond_extra request"); - // assert_eq!(resp, Ok(Vec::::new())); - - // let resp = staking_builtin_client - // .rebond(4 * ONE_VARA) - // .send_recv(builtins_broker_pid) - // .await - // .expect("Failed to send rebond request") - // .unwrap_err(); - - // assert!(resp.to_string().contains("NoUnlockChunk")); - - // let resp = staking_builtin_client - // .set_payee(RewardAccount::Program) - // .send_recv(builtins_broker_pid) - // .await - // .expect("Failed to send set_payee request"); - - // assert_eq!(resp, Ok(Vec::::new())); - - let resp = staking_builtin_client - .unbond(2 * ONE_VARA) - .send_recv(builtins_broker_pid) - .await; - - println!("Resp: {:#?}", resp); - - // todo [sab] invalid gas count for `unbond` call - - // let resp = staking_builtin_client - // .chill() - // .send_recv(builtins_broker_pid) - // .await - // .expect("Failed to send chill request"); - - // assert_eq!(resp, Ok(Vec::::new())); - - // todo [sab] invalid gas count for `withdraw_unbonded` call - - // let resp = staking_builtin_client - // .nominate(vec![H256::random().into()]) - // .send_recv(builtins_broker_pid) - // .await - // .expect("Failed to send nominate request") - // .unwrap_err(); - - // assert!(resp.to_string().contains("InsufficientBond")); - - // todo [sab] invalid gas count for `payout_stakers` call -} - -// #[tokio::test] -// async fn call_bls381_builtin_from_app() { -// let api = GearApi::dev().await.unwrap(); - -// let (code_id, _) = api -// .upload_code(WASM_BINARY) -// .await -// .expect("Failed to upload program code"); - -// let remoting = GClientRemoting::new(api.clone()); - -// let builtins_broker_pid = BuiltinsExampleClientFactory::new(remoting.clone()) -// .new() -// .send_recv(code_id, b"builtins-example-app") -// .await -// .expect("Failed program init message"); - -// api.transfer_keep_alive(builtins_broker_pid, 10_000 * ONE_VARA) -// .await -// .expect("Failed to transfer funds to program"); - -// let mut bls381_builtin_client = Bls381Broker::new(remoting.clone()); - -// let resp = bls381_builtin_client -// .multi_miller_loop(vec![1, 2, 3].encode(), vec![4, 5, 6].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send multi_miller_loop request"); - -// assert!(matches!(resp, Ok(Bls381Response::MultiMillerLoop(_)))); - -// let resp = bls381_builtin_client -// .final_exponentiation(vec![7, 8, 9].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send final_exponentiation request"); - -// assert!(matches!(resp, Ok(Bls381Response::FinalExponentiation(_)))); - -// let resp = bls381_builtin_client -// .multi_scalar_multiplication_g_1(vec![10, 11].encode(), vec![12, 13].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send multi_scalar_multiplication_g1 request"); - -// assert!(matches!(resp, Ok(Bls381Response::MultiScalarMultiplicationG1(_)))); - -// let resp = bls381_builtin_client -// .multi_scalar_multiplication_g_2(vec![14, 15].encode(), vec![16, 17].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send multi_scalar_multiplication_g2 request"); - -// assert!(matches!(resp, Ok(Bls381Response::MultiScalarMultiplicationG2(_)))); - -// let resp = bls381_builtin_client -// .projective_multiplication_g_1(vec![18, 19].encode(), vec![20, 21].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send projective_multiplication_g1 request"); - -// assert!(matches!(resp, Ok(Bls381Response::ProjectiveMultiplicationG1(_)))); - -// let resp = bls381_builtin_client -// .projective_multiplication_g_2(vec![22, 23].encode(), vec![24, 25].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send projective_multiplication_g2 request"); - -// assert!(matches!(resp, Ok(Bls381Response::ProjectiveMultiplicationG2(_)))); - -// let resp = bls381_builtin_client -// .aggregate_g_1(vec![26, 27].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send aggregate_g_1 request"); - -// assert!(matches!(resp, Ok(Bls381Response::AggregateG1(_)))); - -// let resp = bls381_builtin_client -// .map_to_g_2_affine(vec![28, 29].encode()) -// .send_recv(builtins_broker_pid) -// .await -// .expect("Failed to send map_to_g_2_affine request"); - -// assert!(matches!(resp, Ok(Bls381Response::MapToG2Affine(_)))); -// } diff --git a/examples/builtins/client/Cargo.toml b/examples/builtins/client/Cargo.toml deleted file mode 100644 index 508eeef83..000000000 --- a/examples/builtins/client/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "builtins-example-client" -version.workspace = true -edition.workspace = true - -[dependencies] -sails-rs.workspace = true - -[build-dependencies] -builtins-example-app = { path = "../app" } -sails-rs = { workspace = true, features = ["build"] } \ No newline at end of file diff --git a/examples/builtins/client/build.rs b/examples/builtins/client/build.rs deleted file mode 100644 index 649d13b60..000000000 --- a/examples/builtins/client/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - sails_rs::build_client::(); -} diff --git a/examples/builtins/client/builtins_example_client.idl b/examples/builtins/client/builtins_example_client.idl deleted file mode 100644 index 27b22ce3c..000000000 --- a/examples/builtins/client/builtins_example_client.idl +++ /dev/null @@ -1,86 +0,0 @@ -/// `TypeInfo` implementor copy of `gbuiltin_proxy::ProxyType`. -type ProxyType = enum { - Any, - NonTransfer, - Governance, - Staking, - IdentityJudgement, - CancelProxy, -}; - -/// `TypeInfo` implementor copy of `gbuiltin_staking::RewardAccount`. -type RewardAccount = enum { - /// Pay rewards to the sender's account and increase the amount at stake. - Staked, - /// Pay rewards to the sender's account (usually, the one derived from `program_id`) - /// without increasing the amount at stake. - Program, - /// Pay rewards to a custom account. - Custom: actor_id, - /// Opt for not receiving any rewards at all. - None, -}; - -/// `TypeInfo` implementor copy of `gbuiltin_bls381::Response`. -type Bls381Response = enum { - /// Result of the multi Miller loop, encoded: [`ArkScale`]. - MultiMillerLoop: vec u8, - /// Result of the final exponentiation, encoded: [`ArkScale`]. - FinalExponentiation: vec u8, - /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. - MultiScalarMultiplicationG1: vec u8, - /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. - MultiScalarMultiplicationG2: vec u8, - /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. - ProjectiveMultiplicationG1: vec u8, - /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. - ProjectiveMultiplicationG2: vec u8, - /// Result of the aggregation, encoded: [`ArkScale`]. - AggregateG1: vec u8, - /// Result of the mapping, encoded: [`ArkScale`]. - MapToG2Affine: vec u8, -}; - -type Response = enum { - EthMessageQueued: struct { - nonce: u256, - hash: h256, - }, -}; - -constructor { - New : (); -}; - -service ProxyBroker { - AddProxy : (delegate: actor_id, proxy_type: ProxyType) -> result (vec u8, str); - RemoveProxy : (delegate: actor_id, proxy_type: ProxyType) -> result (vec u8, str); -}; - -service StakingBroker { - Bond : (value: u128, payee: RewardAccount) -> result (vec u8, str); - BondExtra : (value: u128) -> result (vec u8, str); - Chill : () -> result (vec u8, str); - Nominate : (targets: vec actor_id) -> result (vec u8, str); - PayoutStakers : (validator_stash: actor_id, era: u32) -> result (vec u8, str); - Rebond : (value: u128) -> result (vec u8, str); - SetPayee : (payee: RewardAccount) -> result (vec u8, str); - Unbond : (value: u128) -> result (vec u8, str); - WithdrawUnbonded : (num_slashing_spans: u32) -> result (vec u8, str); -}; - -service Bls381Broker { - AggregateG1 : (points: vec u8) -> result (Bls381Response, str); - FinalExponentiation : (f: vec u8) -> result (Bls381Response, str); - MapToG2Affine : (message: vec u8) -> result (Bls381Response, str); - MultiMillerLoop : (a: vec u8, b: vec u8) -> result (Bls381Response, str); - MultiScalarMultiplicationG1 : (bases: vec u8, scalars: vec u8) -> result (Bls381Response, str); - MultiScalarMultiplicationG2 : (bases: vec u8, scalars: vec u8) -> result (Bls381Response, str); - ProjectiveMultiplicationG1 : (base: vec u8, scalar: vec u8) -> result (Bls381Response, str); - ProjectiveMultiplicationG2 : (base: vec u8, scalar: vec u8) -> result (Bls381Response, str); -}; - -service EthBridgeBroker { - SendEthMessage : (destination: h160, payload: vec u8) -> result (Response, str); -}; - diff --git a/examples/builtins/client/src/builtins_example_client.rs b/examples/builtins/client/src/builtins_example_client.rs deleted file mode 100644 index 20184fea9..000000000 --- a/examples/builtins/client/src/builtins_example_client.rs +++ /dev/null @@ -1,759 +0,0 @@ -// Code generated by sails-client-gen. DO NOT EDIT. -#[allow(unused_imports)] -use sails_rs::collections::BTreeMap; -#[allow(unused_imports)] -use sails_rs::{ - String, - calls::{Activation, Call, Query, Remoting, RemotingAction}, - prelude::*, -}; -pub struct BuiltinsExampleClientFactory { - #[allow(dead_code)] - remoting: R, -} -impl BuiltinsExampleClientFactory { - #[allow(unused)] - pub fn new(remoting: R) -> Self { - Self { remoting } - } -} -impl traits::BuiltinsExampleClientFactory for BuiltinsExampleClientFactory { - type Args = R::Args; - fn new(&self) -> impl Activation { - RemotingAction::<_, builtins_example_client_factory::io::New>::new( - self.remoting.clone(), - (), - ) - } -} - -pub mod builtins_example_client_factory { - use super::*; - pub mod io { - use super::*; - use sails_rs::calls::ActionIo; - pub struct New(()); - impl New { - #[allow(dead_code)] - pub fn encode_call() -> Vec { - ::encode_call(&()) - } - } - impl ActionIo for New { - const ROUTE: &'static [u8] = &[12, 78, 101, 119]; - type Params = (); - type Reply = (); - } - } -} -pub struct ProxyBroker { - remoting: R, -} -impl ProxyBroker { - pub fn new(remoting: R) -> Self { - Self { remoting } - } -} -impl traits::ProxyBroker for ProxyBroker { - type Args = R::Args; - fn add_proxy( - &mut self, - delegate: ActorId, - proxy_type: ProxyType, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, proxy_broker::io::AddProxy>::new( - self.remoting.clone(), - (delegate, proxy_type), - ) - } - fn remove_proxy( - &mut self, - delegate: ActorId, - proxy_type: ProxyType, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, proxy_broker::io::RemoveProxy>::new( - self.remoting.clone(), - (delegate, proxy_type), - ) - } -} - -pub mod proxy_broker { - use super::*; - - pub mod io { - use super::*; - use sails_rs::calls::ActionIo; - pub struct AddProxy(()); - impl AddProxy { - #[allow(dead_code)] - pub fn encode_call(delegate: ActorId, proxy_type: super::ProxyType) -> Vec { - ::encode_call(&(delegate, proxy_type)) - } - } - impl ActionIo for AddProxy { - const ROUTE: &'static [u8] = &[ - 44, 80, 114, 111, 120, 121, 66, 114, 111, 107, 101, 114, 32, 65, 100, 100, 80, 114, - 111, 120, 121, - ]; - type Params = (ActorId, super::ProxyType); - type Reply = Result, String>; - } - pub struct RemoveProxy(()); - impl RemoveProxy { - #[allow(dead_code)] - pub fn encode_call(delegate: ActorId, proxy_type: super::ProxyType) -> Vec { - ::encode_call(&(delegate, proxy_type)) - } - } - impl ActionIo for RemoveProxy { - const ROUTE: &'static [u8] = &[ - 44, 80, 114, 111, 120, 121, 66, 114, 111, 107, 101, 114, 44, 82, 101, 109, 111, - 118, 101, 80, 114, 111, 120, 121, - ]; - type Params = (ActorId, super::ProxyType); - type Reply = Result, String>; - } - } -} -pub struct StakingBroker { - remoting: R, -} -impl StakingBroker { - pub fn new(remoting: R) -> Self { - Self { remoting } - } -} -impl traits::StakingBroker for StakingBroker { - type Args = R::Args; - fn bond( - &mut self, - value: u128, - payee: RewardAccount, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::Bond>::new(self.remoting.clone(), (value, payee)) - } - fn bond_extra( - &mut self, - value: u128, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::BondExtra>::new(self.remoting.clone(), value) - } - fn chill(&mut self) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::Chill>::new(self.remoting.clone(), ()) - } - fn nominate( - &mut self, - targets: Vec, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::Nominate>::new(self.remoting.clone(), targets) - } - fn payout_stakers( - &mut self, - validator_stash: ActorId, - era: u32, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::PayoutStakers>::new( - self.remoting.clone(), - (validator_stash, era), - ) - } - fn rebond( - &mut self, - value: u128, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::Rebond>::new(self.remoting.clone(), value) - } - fn set_payee( - &mut self, - payee: RewardAccount, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::SetPayee>::new(self.remoting.clone(), payee) - } - fn unbond( - &mut self, - value: u128, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::Unbond>::new(self.remoting.clone(), value) - } - fn withdraw_unbonded( - &mut self, - num_slashing_spans: u32, - ) -> impl Call, String>, Args = R::Args> { - RemotingAction::<_, staking_broker::io::WithdrawUnbonded>::new( - self.remoting.clone(), - num_slashing_spans, - ) - } -} - -pub mod staking_broker { - use super::*; - - pub mod io { - use super::*; - use sails_rs::calls::ActionIo; - pub struct Bond(()); - impl Bond { - #[allow(dead_code)] - pub fn encode_call(value: u128, payee: super::RewardAccount) -> Vec { - ::encode_call(&(value, payee)) - } - } - impl ActionIo for Bond { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 16, 66, 111, 110, - 100, - ]; - type Params = (u128, super::RewardAccount); - type Reply = Result, String>; - } - pub struct BondExtra(()); - impl BondExtra { - #[allow(dead_code)] - pub fn encode_call(value: u128) -> Vec { - ::encode_call(&value) - } - } - impl ActionIo for BondExtra { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 36, 66, 111, 110, - 100, 69, 120, 116, 114, 97, - ]; - type Params = u128; - type Reply = Result, String>; - } - pub struct Chill(()); - impl Chill { - #[allow(dead_code)] - pub fn encode_call() -> Vec { - ::encode_call(&()) - } - } - impl ActionIo for Chill { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 20, 67, 104, 105, - 108, 108, - ]; - type Params = (); - type Reply = Result, String>; - } - pub struct Nominate(()); - impl Nominate { - #[allow(dead_code)] - pub fn encode_call(targets: Vec) -> Vec { - ::encode_call(&targets) - } - } - impl ActionIo for Nominate { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 32, 78, 111, 109, - 105, 110, 97, 116, 101, - ]; - type Params = Vec; - type Reply = Result, String>; - } - pub struct PayoutStakers(()); - impl PayoutStakers { - #[allow(dead_code)] - pub fn encode_call(validator_stash: ActorId, era: u32) -> Vec { - ::encode_call(&(validator_stash, era)) - } - } - impl ActionIo for PayoutStakers { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 52, 80, 97, 121, - 111, 117, 116, 83, 116, 97, 107, 101, 114, 115, - ]; - type Params = (ActorId, u32); - type Reply = Result, String>; - } - pub struct Rebond(()); - impl Rebond { - #[allow(dead_code)] - pub fn encode_call(value: u128) -> Vec { - ::encode_call(&value) - } - } - impl ActionIo for Rebond { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 24, 82, 101, 98, - 111, 110, 100, - ]; - type Params = u128; - type Reply = Result, String>; - } - pub struct SetPayee(()); - impl SetPayee { - #[allow(dead_code)] - pub fn encode_call(payee: super::RewardAccount) -> Vec { - ::encode_call(&payee) - } - } - impl ActionIo for SetPayee { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 32, 83, 101, 116, - 80, 97, 121, 101, 101, - ]; - type Params = super::RewardAccount; - type Reply = Result, String>; - } - pub struct Unbond(()); - impl Unbond { - #[allow(dead_code)] - pub fn encode_call(value: u128) -> Vec { - ::encode_call(&value) - } - } - impl ActionIo for Unbond { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 24, 85, 110, 98, - 111, 110, 100, - ]; - type Params = u128; - type Reply = Result, String>; - } - pub struct WithdrawUnbonded(()); - impl WithdrawUnbonded { - #[allow(dead_code)] - pub fn encode_call(num_slashing_spans: u32) -> Vec { - ::encode_call(&num_slashing_spans) - } - } - impl ActionIo for WithdrawUnbonded { - const ROUTE: &'static [u8] = &[ - 52, 83, 116, 97, 107, 105, 110, 103, 66, 114, 111, 107, 101, 114, 64, 87, 105, 116, - 104, 100, 114, 97, 119, 85, 110, 98, 111, 110, 100, 101, 100, - ]; - type Params = u32; - type Reply = Result, String>; - } - } -} -pub struct Bls381Broker { - remoting: R, -} -impl Bls381Broker { - pub fn new(remoting: R) -> Self { - Self { remoting } - } -} -impl traits::Bls381Broker for Bls381Broker { - type Args = R::Args; - fn aggregate_g_1( - &mut self, - points: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::AggregateG1>::new(self.remoting.clone(), points) - } - fn final_exponentiation( - &mut self, - f: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::FinalExponentiation>::new(self.remoting.clone(), f) - } - fn map_to_g_2_affine( - &mut self, - message: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::MapToG2Affine>::new(self.remoting.clone(), message) - } - fn multi_miller_loop( - &mut self, - a: Vec, - b: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::MultiMillerLoop>::new(self.remoting.clone(), (a, b)) - } - fn multi_scalar_multiplication_g_1( - &mut self, - bases: Vec, - scalars: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::MultiScalarMultiplicationG1>::new( - self.remoting.clone(), - (bases, scalars), - ) - } - fn multi_scalar_multiplication_g_2( - &mut self, - bases: Vec, - scalars: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::MultiScalarMultiplicationG2>::new( - self.remoting.clone(), - (bases, scalars), - ) - } - fn projective_multiplication_g_1( - &mut self, - base: Vec, - scalar: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::ProjectiveMultiplicationG1>::new( - self.remoting.clone(), - (base, scalar), - ) - } - fn projective_multiplication_g_2( - &mut self, - base: Vec, - scalar: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, bls_381_broker::io::ProjectiveMultiplicationG2>::new( - self.remoting.clone(), - (base, scalar), - ) - } -} - -pub mod bls_381_broker { - use super::*; - - pub mod io { - use super::*; - use sails_rs::calls::ActionIo; - pub struct AggregateG1(()); - impl AggregateG1 { - #[allow(dead_code)] - pub fn encode_call(points: Vec) -> Vec { - ::encode_call(&points) - } - } - impl ActionIo for AggregateG1 { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 44, 65, 103, 103, 114, - 101, 103, 97, 116, 101, 71, 49, - ]; - type Params = Vec; - type Reply = Result; - } - pub struct FinalExponentiation(()); - impl FinalExponentiation { - #[allow(dead_code)] - pub fn encode_call(f: Vec) -> Vec { - ::encode_call(&f) - } - } - impl ActionIo for FinalExponentiation { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 76, 70, 105, 110, 97, - 108, 69, 120, 112, 111, 110, 101, 110, 116, 105, 97, 116, 105, 111, 110, - ]; - type Params = Vec; - type Reply = Result; - } - pub struct MapToG2Affine(()); - impl MapToG2Affine { - #[allow(dead_code)] - pub fn encode_call(message: Vec) -> Vec { - ::encode_call(&message) - } - } - impl ActionIo for MapToG2Affine { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 52, 77, 97, 112, 84, - 111, 71, 50, 65, 102, 102, 105, 110, 101, - ]; - type Params = Vec; - type Reply = Result; - } - pub struct MultiMillerLoop(()); - impl MultiMillerLoop { - #[allow(dead_code)] - pub fn encode_call(a: Vec, b: Vec) -> Vec { - ::encode_call(&(a, b)) - } - } - impl ActionIo for MultiMillerLoop { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 60, 77, 117, 108, 116, - 105, 77, 105, 108, 108, 101, 114, 76, 111, 111, 112, - ]; - type Params = (Vec, Vec); - type Reply = Result; - } - pub struct MultiScalarMultiplicationG1(()); - impl MultiScalarMultiplicationG1 { - #[allow(dead_code)] - pub fn encode_call(bases: Vec, scalars: Vec) -> Vec { - ::encode_call(&(bases, scalars)) - } - } - impl ActionIo for MultiScalarMultiplicationG1 { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 108, 77, 117, 108, 116, - 105, 83, 99, 97, 108, 97, 114, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, - 105, 111, 110, 71, 49, - ]; - type Params = (Vec, Vec); - type Reply = Result; - } - pub struct MultiScalarMultiplicationG2(()); - impl MultiScalarMultiplicationG2 { - #[allow(dead_code)] - pub fn encode_call(bases: Vec, scalars: Vec) -> Vec { - ::encode_call(&(bases, scalars)) - } - } - impl ActionIo for MultiScalarMultiplicationG2 { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 108, 77, 117, 108, 116, - 105, 83, 99, 97, 108, 97, 114, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, - 105, 111, 110, 71, 50, - ]; - type Params = (Vec, Vec); - type Reply = Result; - } - pub struct ProjectiveMultiplicationG1(()); - impl ProjectiveMultiplicationG1 { - #[allow(dead_code)] - pub fn encode_call(base: Vec, scalar: Vec) -> Vec { - ::encode_call(&(base, scalar)) - } - } - impl ActionIo for ProjectiveMultiplicationG1 { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 104, 80, 114, 111, 106, - 101, 99, 116, 105, 118, 101, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, - 105, 111, 110, 71, 49, - ]; - type Params = (Vec, Vec); - type Reply = Result; - } - pub struct ProjectiveMultiplicationG2(()); - impl ProjectiveMultiplicationG2 { - #[allow(dead_code)] - pub fn encode_call(base: Vec, scalar: Vec) -> Vec { - ::encode_call(&(base, scalar)) - } - } - impl ActionIo for ProjectiveMultiplicationG2 { - const ROUTE: &'static [u8] = &[ - 48, 66, 108, 115, 51, 56, 49, 66, 114, 111, 107, 101, 114, 104, 80, 114, 111, 106, - 101, 99, 116, 105, 118, 101, 77, 117, 108, 116, 105, 112, 108, 105, 99, 97, 116, - 105, 111, 110, 71, 50, - ]; - type Params = (Vec, Vec); - type Reply = Result; - } - } -} -pub struct EthBridgeBroker { - remoting: R, -} -impl EthBridgeBroker { - pub fn new(remoting: R) -> Self { - Self { remoting } - } -} -impl traits::EthBridgeBroker for EthBridgeBroker { - type Args = R::Args; - fn send_eth_message( - &mut self, - destination: H160, - payload: Vec, - ) -> impl Call, Args = R::Args> { - RemotingAction::<_, eth_bridge_broker::io::SendEthMessage>::new( - self.remoting.clone(), - (destination, payload), - ) - } -} - -pub mod eth_bridge_broker { - use super::*; - - pub mod io { - use super::*; - use sails_rs::calls::ActionIo; - pub struct SendEthMessage(()); - impl SendEthMessage { - #[allow(dead_code)] - pub fn encode_call(destination: H160, payload: Vec) -> Vec { - ::encode_call(&(destination, payload)) - } - } - impl ActionIo for SendEthMessage { - const ROUTE: &'static [u8] = &[ - 60, 69, 116, 104, 66, 114, 105, 100, 103, 101, 66, 114, 111, 107, 101, 114, 56, 83, - 101, 110, 100, 69, 116, 104, 77, 101, 115, 115, 97, 103, 101, - ]; - type Params = (H160, Vec); - type Reply = Result; - } - } -} -/// `TypeInfo` implementor copy of `gbuiltin_proxy::ProxyType`. -#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] -#[codec(crate = sails_rs::scale_codec)] -#[scale_info(crate = sails_rs::scale_info)] -pub enum ProxyType { - Any, - NonTransfer, - Governance, - Staking, - IdentityJudgement, - CancelProxy, -} -/// `TypeInfo` implementor copy of `gbuiltin_staking::RewardAccount`. -#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] -#[codec(crate = sails_rs::scale_codec)] -#[scale_info(crate = sails_rs::scale_info)] -pub enum RewardAccount { - /// Pay rewards to the sender's account and increase the amount at stake. - Staked, - /// Pay rewards to the sender's account (usually, the one derived from `program_id`) - /// without increasing the amount at stake. - Program, - /// Pay rewards to a custom account. - Custom(ActorId), - /// Opt for not receiving any rewards at all. - None, -} -/// `TypeInfo` implementor copy of `gbuiltin_bls381::Response`. -#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] -#[codec(crate = sails_rs::scale_codec)] -#[scale_info(crate = sails_rs::scale_info)] -pub enum Bls381Response { - /// Result of the multi Miller loop, encoded: [`ArkScale`]. - MultiMillerLoop(Vec), - /// Result of the final exponentiation, encoded: [`ArkScale`]. - FinalExponentiation(Vec), - /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. - MultiScalarMultiplicationG1(Vec), - /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective`]. - MultiScalarMultiplicationG2(Vec), - /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. - ProjectiveMultiplicationG1(Vec), - /// Result of the projective multiplication, encoded: [`ArkScaleProjective`]. - ProjectiveMultiplicationG2(Vec), - /// Result of the aggregation, encoded: [`ArkScale`]. - AggregateG1(Vec), - /// Result of the mapping, encoded: [`ArkScale`]. - MapToG2Affine(Vec), -} -#[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo)] -#[codec(crate = sails_rs::scale_codec)] -#[scale_info(crate = sails_rs::scale_info)] -pub enum Response { - EthMessageQueued { nonce: U256, hash: H256 }, -} - -pub mod traits { - use super::*; - #[allow(dead_code)] - pub trait BuiltinsExampleClientFactory { - type Args; - #[allow(clippy::new_ret_no_self)] - #[allow(clippy::wrong_self_convention)] - fn new(&self) -> impl Activation; - } - - #[allow(clippy::type_complexity)] - pub trait ProxyBroker { - type Args; - fn add_proxy( - &mut self, - delegate: ActorId, - proxy_type: ProxyType, - ) -> impl Call, String>, Args = Self::Args>; - fn remove_proxy( - &mut self, - delegate: ActorId, - proxy_type: ProxyType, - ) -> impl Call, String>, Args = Self::Args>; - } - - #[allow(clippy::type_complexity)] - pub trait StakingBroker { - type Args; - fn bond( - &mut self, - value: u128, - payee: RewardAccount, - ) -> impl Call, String>, Args = Self::Args>; - fn bond_extra( - &mut self, - value: u128, - ) -> impl Call, String>, Args = Self::Args>; - fn chill(&mut self) -> impl Call, String>, Args = Self::Args>; - fn nominate( - &mut self, - targets: Vec, - ) -> impl Call, String>, Args = Self::Args>; - fn payout_stakers( - &mut self, - validator_stash: ActorId, - era: u32, - ) -> impl Call, String>, Args = Self::Args>; - fn rebond( - &mut self, - value: u128, - ) -> impl Call, String>, Args = Self::Args>; - fn set_payee( - &mut self, - payee: RewardAccount, - ) -> impl Call, String>, Args = Self::Args>; - fn unbond( - &mut self, - value: u128, - ) -> impl Call, String>, Args = Self::Args>; - fn withdraw_unbonded( - &mut self, - num_slashing_spans: u32, - ) -> impl Call, String>, Args = Self::Args>; - } - - #[allow(clippy::type_complexity)] - pub trait Bls381Broker { - type Args; - fn aggregate_g_1( - &mut self, - points: Vec, - ) -> impl Call, Args = Self::Args>; - fn final_exponentiation( - &mut self, - f: Vec, - ) -> impl Call, Args = Self::Args>; - fn map_to_g_2_affine( - &mut self, - message: Vec, - ) -> impl Call, Args = Self::Args>; - fn multi_miller_loop( - &mut self, - a: Vec, - b: Vec, - ) -> impl Call, Args = Self::Args>; - fn multi_scalar_multiplication_g_1( - &mut self, - bases: Vec, - scalars: Vec, - ) -> impl Call, Args = Self::Args>; - fn multi_scalar_multiplication_g_2( - &mut self, - bases: Vec, - scalars: Vec, - ) -> impl Call, Args = Self::Args>; - fn projective_multiplication_g_1( - &mut self, - base: Vec, - scalar: Vec, - ) -> impl Call, Args = Self::Args>; - fn projective_multiplication_g_2( - &mut self, - base: Vec, - scalar: Vec, - ) -> impl Call, Args = Self::Args>; - } - - #[allow(clippy::type_complexity)] - pub trait EthBridgeBroker { - type Args; - fn send_eth_message( - &mut self, - destination: H160, - payload: Vec, - ) -> impl Call, Args = Self::Args>; - } -} diff --git a/examples/builtins/client/src/lib.rs b/examples/builtins/client/src/lib.rs deleted file mode 100644 index 658225503..000000000 --- a/examples/builtins/client/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![no_std] - -// Incorporate code generated based on the IDL file -include!("builtins_example_client.rs"); diff --git a/rs/src/builtins/bls381.rs b/rs/src/builtins/bls381.rs index d1dcbab04..d1400896e 100644 --- a/rs/src/builtins/bls381.rs +++ b/rs/src/builtins/bls381.rs @@ -1,5 +1,4 @@ use crate::{ - ActorId, builtins::{BuiltinsRemoting, builtin_action}, calls::{ActionIo, Call, RemotingAction}, errors::{Error, Result}, @@ -7,12 +6,6 @@ use crate::{ }; use gbuiltin_bls381::{Request as GearBls381Request, Response as GearBls381Response}; -/// Gear protocol BLS381 builtin id is 0x6b6e292c382945e80bf51af2ba7fe9f458dcff81ae6075c46f9095e1bbecdc37 -pub const BLS381_BUILTIN_ID: ActorId = ActorId::new([ - 0x6b, 0x6e, 0x29, 0x2c, 0x38, 0x29, 0x45, 0xe8, 0x0b, 0xf5, 0x1a, 0xf2, 0xba, 0x7f, 0xe9, 0xf4, - 0x58, 0xdc, 0xff, 0x81, 0xae, 0x60, 0x75, 0xc4, 0x6f, 0x90, 0x95, 0xe1, 0xbb, 0xec, 0xdc, 0x37, -]); - builtin_action!( Bls381Request, Bls381Builtin, @@ -208,9 +201,88 @@ impl From for Bls381Response { } } -#[test] -fn test_id() { - let expected = hex::decode("6b6e292c382945e80bf51af2ba7fe9f458dcff81ae6075c46f9095e1bbecdc37") - .expect("Failed to decode hex"); - assert_eq!(BLS381_BUILTIN_ID.into_bytes().to_vec(), expected); +#[cfg(test)] +mod tests { + use super::*; + use crate::{builtins::test_utils::assert_action_codec, prelude::vec}; + + #[test] + fn test_codec() { + assert_action_codec!( + Bls381Request, + MultiMillerLoop { + a: vec![1, 2, 3], + b: vec![4, 5, 6] + }, + Bls381Response, + MultiMillerLoop(vec![7, 8, 9]) + ); + + assert_action_codec!( + Bls381Request, + FinalExponentiation { + f: vec![10, 11, 12] + }, + Bls381Response, + FinalExponentiation(vec![13, 14, 15]) + ); + + assert_action_codec!( + Bls381Request, + MultiScalarMultiplicationG1 { + bases: vec![16, 17, 18], + scalars: vec![19, 20, 21] + }, + Bls381Response, + MultiScalarMultiplicationG1(vec![22, 23, 24]) + ); + + assert_action_codec!( + Bls381Request, + MultiScalarMultiplicationG2 { + bases: vec![25, 26, 27], + scalars: vec![28, 29, 30] + }, + Bls381Response, + MultiScalarMultiplicationG2(vec![31, 32, 33]) + ); + + assert_action_codec!( + Bls381Request, + ProjectiveMultiplicationG1 { + base: vec![34, 35, 36], + scalar: vec![37, 38, 39] + }, + Bls381Response, + ProjectiveMultiplicationG1(vec![40, 41, 42]) + ); + + assert_action_codec!( + Bls381Request, + ProjectiveMultiplicationG2 { + base: vec![43, 44, 45], + scalar: vec![46, 47, 48] + }, + Bls381Response, + ProjectiveMultiplicationG2(vec![49, 50, 51]) + ); + + assert_action_codec!( + Bls381Request, + AggregateG1 { + points: vec![52, 53, 54] + }, + Bls381Response, + AggregateG1(vec![55, 56, 57]) + ); + + assert_action_codec!( + Bls381Request, + MapToG2Affine { + message: vec![58, 59, 60] + }, + Bls381Response, + MapToG2Affine(vec![61, 62, 63]) + ); + } } diff --git a/rs/src/builtins/eth_bridge.rs b/rs/src/builtins/eth_bridge.rs index 358066063..d97dddde4 100644 --- a/rs/src/builtins/eth_bridge.rs +++ b/rs/src/builtins/eth_bridge.rs @@ -30,9 +30,26 @@ impl EthBridgeRemoting { } } -#[test] -fn test_id() { - let expected = hex::decode("f2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf") - .expect("Failed to decode hex"); - assert_eq!(ETH_BRIDGE_BUILTIN_ID.into_bytes().to_vec(), expected); +#[cfg(test)] +mod tests { + use super::*; + use crate::builtins::test_utils::assert_action_codec; + use crate::prelude::vec; + use gprimitives::{H256, U256}; + + #[test] + fn test_codec() { + assert_action_codec!( + EthBridgeRequest, + SendEthMessage { + destination: H160::from([1; 20]), + payload: vec![1, 2, 3, 4] + }, + EthBridgeResponse, + EthMessageQueued { + nonce: U256::one(), + hash: H256::from([2; 32]) + } + ); + } } diff --git a/rs/src/builtins/mod.rs b/rs/src/builtins/mod.rs index 8f21ce411..0feaf3f9e 100644 --- a/rs/src/builtins/mod.rs +++ b/rs/src/builtins/mod.rs @@ -19,6 +19,7 @@ impl BuiltinsRemoting for crate::gstd::calls::GStdRemoting {} #[cfg(not(target_arch = "wasm32"))] impl BuiltinsRemoting for crate::gclient::calls::GClientRemoting {} +// Creates an action for a provided builtin-in request variant and implements the `ActionIo` trait for it. macro_rules! builtin_action { ( $enum_name:ident, @@ -59,7 +60,7 @@ macro_rules! builtin_action { // Helper arm: extract reply type or default (@reply_type $reply_ty:ty) => { $reply_ty }; - (@reply_type) => { Vec }; + (@reply_type) => { () }; // Helper: Match variant with fields (@match_variant $value:ident, $enum_name:ident, $variant:ident, { $($field:ident),* }) => { @@ -94,8 +95,51 @@ macro_rules! builtin_action { $value ); } - Ok(Default::default()) + Ok(()) }}; } pub(crate) use builtin_action; + +#[cfg(test)] +mod test_utils { + macro_rules! assert_action_codec { + // Check that action is encoded/decoded without any routes. + ( + $req_enum_name:ident, + $req_variant:ident $({ $($req_field:ident : $req_value:expr),* $(,)? })?, + $resp_enum_name:ident, + $response_variant:ident $response_body:tt + ) => {{ + let req = $req_enum_name::$req_variant $({ $($req_field: $req_value),* })?; + let resp = $crate::builtins::test_utils::assert_action_codec!(@build_response $resp_enum_name, $response_variant $response_body); + let encoded_action = $req_variant::encode_call(&req); + assert_eq!(req.encode(), encoded_action); + let decoded_resp = $req_variant::decode_reply(resp.encode()).unwrap(); + assert_eq!(resp, decoded_resp); + }}; + + // Check that value is encoded without any routes, and decoded into `()`. + ( + $req_enum_name:ident, + $req_variant:ident $({ $($req_field:ident : $req_value:expr),* $(,)? })? + ) => {{ + let req = $req_enum_name::$req_variant $({ $($req_field: $req_value),* })?; + let encoded_action = $req_variant::encode_call(&req); + assert_eq!(req.encode(), encoded_action); + assert_eq!(<$req_variant as ActionIo>::Reply::type_info(), <()>::type_info()); + }}; + + // Helper: Build response with tuple syntax + (@build_response $resp_enum_name:ident, $response_variant:ident ($response_value:expr)) => { + $resp_enum_name::$response_variant($response_value) + }; + + // Helper: Build response with struct syntax + (@build_response $resp_enum_name:ident, $response_variant:ident { $($resp_field:ident : $resp_value:expr),* $(,)? }) => { + $resp_enum_name::$response_variant { $($resp_field: $resp_value),* } + }; + } + + pub(crate) use assert_action_codec; +} diff --git a/rs/src/builtins/proxy.rs b/rs/src/builtins/proxy.rs index 23fb5eaf5..735e75d88 100644 --- a/rs/src/builtins/proxy.rs +++ b/rs/src/builtins/proxy.rs @@ -8,13 +8,6 @@ use crate::{ use gbuiltin_proxy::{ProxyType as GearProxyType, Request as GearProxyRequest}; // todo [sab] make typeinfo types on gear -// todo [sab] package must provide the address - -/// Gear protocol proxy builtin id is 0x8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299 -pub const PROXY_BUILTIN_ID: ActorId = ActorId::new([ - 0x82, 0x63, 0xcd, 0x9f, 0xc6, 0x48, 0xe1, 0x01, 0xf1, 0xcd, 0x85, 0x85, 0xdc, 0x0b, 0x19, 0x34, - 0x45, 0xc3, 0x75, 0x0a, 0x63, 0xbf, 0x64, 0xa3, 0x9c, 0xdf, 0x58, 0xde, 0x14, 0x82, 0x62, 0x99, -]); builtin_action! { ProxyRequest, @@ -96,9 +89,26 @@ impl From for ProxyType { } } -#[test] -fn test_id() { - let expected = hex::decode("8263cd9fc648e101f1cd8585dc0b193445c3750a63bf64a39cdf58de14826299") - .expect("Failed to decode hex"); - assert_eq!(PROXY_BUILTIN_ID.into_bytes().to_vec(), expected); +#[cfg(test)] +mod tests { + use super::*; + use crate::builtins::test_utils::assert_action_codec; + + #[test] + fn test_codec() { + assert_action_codec!( + ProxyRequest, + AddProxy { + delegate: ActorId::from([1; 32]), + proxy_type: ProxyType::Any + } + ); + assert_action_codec!( + ProxyRequest, + RemoveProxy { + delegate: ActorId::from([2; 32]), + proxy_type: ProxyType::NonTransfer + } + ); + } } diff --git a/rs/src/builtins/staking.rs b/rs/src/builtins/staking.rs index 57197bbff..534183034 100644 --- a/rs/src/builtins/staking.rs +++ b/rs/src/builtins/staking.rs @@ -7,12 +7,6 @@ use crate::{ }; use gbuiltin_staking::{Request as GearStakingRequest, RewardAccount as GearRewardAccount}; -/// Gear protocol staking builtin id is 0x77f65ef190e11bfecb8fc8970fd3749e94bed66a23ec2f7a3623e785d0816761 -pub const STAKING_BUILTIN_ID: ActorId = ActorId::new([ - 0x77, 0xf6, 0x5e, 0xf1, 0x90, 0xe1, 0x1b, 0xfe, 0xcb, 0x8f, 0xc8, 0x97, 0x0f, 0xd3, 0x74, 0x9e, - 0x94, 0xbe, 0xd6, 0x6a, 0x23, 0xec, 0x2f, 0x7a, 0x36, 0x23, 0xe7, 0x85, 0xd0, 0x81, 0x67, 0x61, -]); - builtin_action!( StakingRequest, StakingBuiltin, @@ -149,9 +143,49 @@ impl From for RewardAccount { } } -#[test] -fn test_id() { - let expected = hex::decode("77f65ef190e11bfecb8fc8970fd3749e94bed66a23ec2f7a3623e785d0816761") - .expect("Failed to decode hex"); - assert_eq!(STAKING_BUILTIN_ID.into_bytes().to_vec(), expected); +#[cfg(test)] +mod tests { + use super::*; + use crate::builtins::test_utils; + use crate::{builtins::test_utils::assert_action_codec, prelude::vec}; + + #[test] + fn test_codec() { + assert_action_codec!( + StakingRequest, + Bond { + value: 1000, + payee: RewardAccount::Staked + } + ); + assert_action_codec!(StakingRequest, BondExtra { value: 500 }); + assert_action_codec!(StakingRequest, Unbond { value: 200 }); + assert_action_codec!( + StakingRequest, + WithdrawUnbonded { + num_slashing_spans: 3 + } + ); + assert_action_codec!( + StakingRequest, + Nominate { + targets: vec![ActorId::from([1; 32]), ActorId::from([2; 32])] + } + ); + assert_action_codec!(StakingRequest, Chill); + assert_action_codec!( + StakingRequest, + PayoutStakers { + validator_stash: ActorId::from([3; 32]), + era: 42 + } + ); + assert_action_codec!(StakingRequest, Rebond { value: 300 }); + assert_action_codec!( + StakingRequest, + SetPayee { + payee: RewardAccount::Custom(ActorId::from([4; 32])) + } + ); + } } From e3422ecc175e180830dd9471bf11cc0cfaef26c7 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 23 Jul 2025 12:35:52 +0300 Subject: [PATCH 10/16] remove todo --- rs/src/builtins/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rs/src/builtins/mod.rs b/rs/src/builtins/mod.rs index 0feaf3f9e..71c7958d8 100644 --- a/rs/src/builtins/mod.rs +++ b/rs/src/builtins/mod.rs @@ -89,7 +89,6 @@ macro_rules! builtin_action { }}; (@decode_body $value:ident) => {{ if !$value.is_empty() { - // todo [sab] change to error type panic!( "internal error: expected empty reply for unit variant, received: {:?}", $value From d704e253bc47e057e38628984d3258e96e2b8bf9 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 23 Jul 2025 12:36:56 +0300 Subject: [PATCH 11/16] remove id --- rs/src/builtins/eth_bridge.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/rs/src/builtins/eth_bridge.rs b/rs/src/builtins/eth_bridge.rs index d97dddde4..8a636cb89 100644 --- a/rs/src/builtins/eth_bridge.rs +++ b/rs/src/builtins/eth_bridge.rs @@ -8,12 +8,6 @@ use crate::{ pub use gbuiltin_eth_bridge::{Request as EthBridgeRequest, Response as EthBridgeResponse}; use gprimitives::H160; -/// Gear protocol eth-bridge builtin id is 0xf2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf -pub const ETH_BRIDGE_BUILTIN_ID: ActorId = ActorId::new([ - 0xf2, 0x81, 0x6c, 0xed, 0x0b, 0x15, 0x74, 0x95, 0x95, 0x39, 0x2d, 0x3a, 0x18, 0xb5, 0xa2, 0x36, - 0x3d, 0x6f, 0xef, 0xe5, 0xb3, 0xb6, 0x15, 0x37, 0x39, 0xf2, 0x18, 0x15, 0x1b, 0x7a, 0xcd, 0xbf, -]); - builtin_action!( EthBridgeRequest, EthBridgeRemoting, From 347c3f54171c4b7f54deeb195c72bd52104a489e Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 23 Jul 2025 13:45:37 +0300 Subject: [PATCH 12/16] remove redundant --- rs/src/builtins/eth_bridge.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rs/src/builtins/eth_bridge.rs b/rs/src/builtins/eth_bridge.rs index 8a636cb89..6bcf49201 100644 --- a/rs/src/builtins/eth_bridge.rs +++ b/rs/src/builtins/eth_bridge.rs @@ -1,5 +1,4 @@ use crate::{ - ActorId, builtins::{BuiltinsRemoting, builtin_action}, calls::{ActionIo, Call, RemotingAction}, errors::{Error, Result}, From 61602a417b83d94e34d25e17d4f785b4b86187ca Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 23 Jul 2025 13:46:59 +0300 Subject: [PATCH 13/16] update lock for ethexe --- rs/ethexe/Cargo.lock | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/rs/ethexe/Cargo.lock b/rs/ethexe/Cargo.lock index c964e2ed3..6a04924f3 100644 --- a/rs/ethexe/Cargo.lock +++ b/rs/ethexe/Cargo.lock @@ -317,6 +317,20 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "ark-scale" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "ark-serialize" version = "0.4.2" @@ -1782,6 +1796,51 @@ dependencies = [ "gear-dlmalloc", ] +[[package]] +name = "gbuiltin-bls381" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490015fd6c0b7a2cfd96257a3ee71bd636ad1cc89a73c2f6f62e419a3ecad8f3" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-scale", + "ark-serialize", + "parity-scale-codec", +] + +[[package]] +name = "gbuiltin-eth-bridge" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "370e03a4190a34bbe99ab6736dc162d4c08c6a69cec8deffcd35ac7fc9f8aa82" +dependencies = [ + "gprimitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "gbuiltin-proxy" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2beac2a698e3438d9bc0acd884ea39ef3cd2ee2ed5e07779c1f69812e52cb4c5" +dependencies = [ + "gprimitives", + "parity-scale-codec", +] + +[[package]] +name = "gbuiltin-staking" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa90eb350f6bbaff596fed23833a892f28871c69de0648e59f93616c473c6e64" +dependencies = [ + "gprimitives", + "parity-scale-codec", +] + [[package]] name = "gcore" version = "1.8.1" @@ -4118,6 +4177,10 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "futures", + "gbuiltin-bls381", + "gbuiltin-eth-bridge", + "gbuiltin-proxy", + "gbuiltin-staking", "gcore", "gear-core", "gear-core-errors", From 5b5bb35f65aa1a393c1315de8c7ceb99a157d01b Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 29 Jul 2025 14:06:03 +0300 Subject: [PATCH 14/16] add traits --- rs/src/builtins/bls381.rs | 119 ++++++++++++++++++++++++++++++++++ rs/src/builtins/eth_bridge.rs | 29 ++++++++- rs/src/builtins/proxy.rs | 38 +++++++++++ rs/src/builtins/staking.rs | 85 ++++++++++++++++++++++++ 4 files changed, 268 insertions(+), 3 deletions(-) diff --git a/rs/src/builtins/bls381.rs b/rs/src/builtins/bls381.rs index d1400896e..f5a99e2b1 100644 --- a/rs/src/builtins/bls381.rs +++ b/rs/src/builtins/bls381.rs @@ -64,6 +64,125 @@ impl Bls381Builtin { } } +pub trait Bls381BuiltinTrait { + type Args; + + /// Performs multi Miller loop pairing operation for BLS12-381. + fn multi_miller_loop( + &self, + a: Vec, + b: Vec, + ) -> impl Call; + + /// Performs final exponentiation for BLS12-381. + fn final_exponentiation( + &self, + f: Vec, + ) -> impl Call; + + /// Performs multi scalar multiplication on G1 for BLS12-381. + fn multi_scalar_multiplication_g1( + &self, + bases: Vec, + scalars: Vec, + ) -> impl Call; + + /// Performs multi scalar multiplication on G2 for BLS12-381. + fn multi_scalar_multiplication_g2( + &self, + bases: Vec, + scalars: Vec, + ) -> impl Call; + + /// Performs projective multiplication on G1 for BLS12-381. + fn projective_multiplication_g1( + &self, + base: Vec, + scalar: Vec, + ) -> impl Call; + + /// Performs projective multiplication on G2 for BLS12-381. + fn projective_multiplication_g2( + &self, + base: Vec, + scalar: Vec, + ) -> impl Call; + + /// Aggregates G1 points for BLS12-381. + fn aggregate_g1( + &self, + points: Vec, + ) -> impl Call; + + /// Maps an arbitrary message to a G2Affine point for BLS12-381. + fn map_to_g2_affine( + &self, + message: Vec, + ) -> impl Call; +} + +impl Bls381BuiltinTrait for Bls381Builtin { + type Args = R::Args; + + fn multi_miller_loop( + &self, + a: Vec, + b: Vec, + ) -> impl Call { + self.multi_miller_loop(a, b) + } + + fn final_exponentiation( + &self, + f: Vec, + ) -> impl Call { + self.final_exponentiation(f) + } + + fn multi_scalar_multiplication_g1( + &self, + bases: Vec, + scalars: Vec, + ) -> impl Call { + self.multi_scalar_multiplication_g1(bases, scalars) + } + + fn multi_scalar_multiplication_g2( + &self, + bases: Vec, + scalars: Vec, + ) -> impl Call { + self.multi_scalar_multiplication_g2(bases, scalars) + } + + fn projective_multiplication_g1( + &self, + base: Vec, + scalar: Vec, + ) -> impl Call { + self.projective_multiplication_g1(base, scalar) + } + + fn projective_multiplication_g2( + &self, + base: Vec, + scalar: Vec, + ) -> impl Call { + self.projective_multiplication_g2(base, scalar) + } + + fn aggregate_g1(&self, points: Vec) -> impl Call { + self.aggregate_g1(points) + } + + fn map_to_g2_affine( + &self, + message: Vec, + ) -> impl Call { + self.map_to_g2_affine(message) + } +} + /// `TypeInfo` implementor copy of `gbuiltin_bls381::Request`. #[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] pub enum Bls381Request { diff --git a/rs/src/builtins/eth_bridge.rs b/rs/src/builtins/eth_bridge.rs index 6bcf49201..d0a08788e 100644 --- a/rs/src/builtins/eth_bridge.rs +++ b/rs/src/builtins/eth_bridge.rs @@ -9,20 +9,43 @@ use gprimitives::H160; builtin_action!( EthBridgeRequest, - EthBridgeRemoting, + EthBridgeBuiltin, SendEthMessage { destination: H160, payload: Vec } => EthBridgeResponse ); -pub struct EthBridgeRemoting { +pub struct EthBridgeBuiltin { remoting: R, } -impl EthBridgeRemoting { +impl EthBridgeBuiltin { pub fn new(remoting: R) -> Self { Self { remoting } } } +pub trait EthBridgeBuiltinTrait { + type Args; + + /// Sends an Ethereum message to the specified destination on the Ethereum network with the given payload. + fn send_eth_message( + &self, + destination: H160, + payload: Vec, + ) -> impl Call; +} + +impl EthBridgeBuiltinTrait for EthBridgeBuiltin { + type Args = R::Args; + + fn send_eth_message( + &self, + destination: H160, + payload: Vec, + ) -> impl Call { + self.send_eth_message(destination, payload) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/rs/src/builtins/proxy.rs b/rs/src/builtins/proxy.rs index 735e75d88..886d002be 100644 --- a/rs/src/builtins/proxy.rs +++ b/rs/src/builtins/proxy.rs @@ -31,6 +31,44 @@ impl ProxyBuiltin { } } +pub trait ProxyBuiltinTrait { + type Args; + + /// Adds a proxy for the specified delegate with the given proxy type. + fn add_proxy( + &self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call; + + /// Removes a proxy for the specified delegate with the given proxy type. + fn remove_proxy( + &self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call; +} + +impl ProxyBuiltinTrait for ProxyBuiltin { + type Args = R::Args; + + fn add_proxy( + &self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call { + self.add_proxy(delegate, proxy_type) + } + + fn remove_proxy( + &self, + delegate: ActorId, + proxy_type: ProxyType, + ) -> impl Call { + self.remove_proxy(delegate, proxy_type) + } +} + /// `TypeInfo` implementor copy of `gbuiltin_proxy::Request`. #[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode, TypeInfo)] pub enum ProxyRequest { diff --git a/rs/src/builtins/staking.rs b/rs/src/builtins/staking.rs index 534183034..3f368fe0c 100644 --- a/rs/src/builtins/staking.rs +++ b/rs/src/builtins/staking.rs @@ -65,6 +65,91 @@ impl StakingBuiltin { } } +pub trait StakingBuiltinTrait { + type Args; + + /// Bond up to the `value` from the sender to self as the controller. + fn bond(&self, value: u128, payee: RewardAccount) -> impl Call; + + /// Add up to the `value` to the sender's bonded amount. + fn bond_extra(&self, value: u128) -> impl Call; + + /// Unbond up to the `value` to allow withdrawal after undonding period. + fn unbond(&self, value: u128) -> impl Call; + + /// Withdraw unbonded chunks for which undonding period has elapsed. + fn withdraw_unbonded( + &self, + num_slashing_spans: u32, + ) -> impl Call; + + /// Add sender as a nominator of `targets` or update the existing targets. + fn nominate(&self, targets: Vec) -> impl Call; + + /// Declare intention to [temporarily] stop nominating while still having funds bonded. + fn chill(&self) -> impl Call; + + /// Request stakers payout for the given era. + fn payout_stakers( + &self, + validator_stash: ActorId, + era: u32, + ) -> impl Call; + + /// Rebond a portion of the sender's stash scheduled to be unlocked. + fn rebond(&self, value: u128) -> impl Call; + + /// Set the reward destination. + fn set_payee(&self, payee: RewardAccount) -> impl Call; +} + +impl StakingBuiltinTrait for StakingBuiltin { + type Args = R::Args; + + fn bond(&self, value: u128, payee: RewardAccount) -> impl Call { + self.bond(value, payee) + } + + fn bond_extra(&self, value: u128) -> impl Call { + self.bond_extra(value) + } + + fn unbond(&self, value: u128) -> impl Call { + self.unbond(value) + } + + fn withdraw_unbonded( + &self, + num_slashing_spans: u32, + ) -> impl Call { + self.withdraw_unbonded(num_slashing_spans) + } + + fn nominate(&self, targets: Vec) -> impl Call { + self.nominate(targets) + } + + fn chill(&self) -> impl Call { + self.chill() + } + + fn payout_stakers( + &self, + validator_stash: ActorId, + era: u32, + ) -> impl Call { + self.payout_stakers(validator_stash, era) + } + + fn rebond(&self, value: u128) -> impl Call { + self.rebond(value) + } + + fn set_payee(&self, payee: RewardAccount) -> impl Call { + self.set_payee(payee) + } +} + /// `TypeInfo` implementor copy of `gbuiltin_staking::Request`. #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] pub enum StakingRequest { From a06020cea76b1dc08e0f987cb66f0ca43b217ca7 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 29 Jul 2025 14:07:55 +0300 Subject: [PATCH 15/16] fix clippy warning --- rs/src/builtins/staking.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rs/src/builtins/staking.rs b/rs/src/builtins/staking.rs index 3f368fe0c..d5e16560c 100644 --- a/rs/src/builtins/staking.rs +++ b/rs/src/builtins/staking.rs @@ -231,7 +231,6 @@ impl From for RewardAccount { #[cfg(test)] mod tests { use super::*; - use crate::builtins::test_utils; use crate::{builtins::test_utils::assert_action_codec, prelude::vec}; #[test] From 07683eeb0e6e14cc304657bdbc20b62561cc75bd Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 4 Aug 2025 19:36:00 +0300 Subject: [PATCH 16/16] rebase2 --- Cargo.lock | 19 +++++++++++-------- rs/ethexe/Cargo.lock | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46201850f..25e9d67ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2844,9 +2844,9 @@ dependencies = [ [[package]] name = "gbuiltin-bls381" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490015fd6c0b7a2cfd96257a3ee71bd636ad1cc89a73c2f6f62e419a3ecad8f3" +checksum = "da5c0d4fddca6f05362cda44c30e0775f1ee99a040ac7c7df28d699082aae6be" dependencies = [ "ark-bls12-381", "ark-ec", @@ -2854,13 +2854,14 @@ dependencies = [ "ark-scale", "ark-serialize", "parity-scale-codec", + "scale-info", ] [[package]] name = "gbuiltin-eth-bridge" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370e03a4190a34bbe99ab6736dc162d4c08c6a69cec8deffcd35ac7fc9f8aa82" +checksum = "bd77189c1c742e301656941c8125169d84b12c1deac1ed11acc516aef00002d8" dependencies = [ "gprimitives", "parity-scale-codec", @@ -2869,22 +2870,24 @@ dependencies = [ [[package]] name = "gbuiltin-proxy" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2beac2a698e3438d9bc0acd884ea39ef3cd2ee2ed5e07779c1f69812e52cb4c5" +checksum = "328a23e9eb5831d49ae122d74ce0a49fb1dfd22d6f7fb8cc513f7dadf21d8780" dependencies = [ "gprimitives", "parity-scale-codec", + "scale-info", ] [[package]] name = "gbuiltin-staking" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa90eb350f6bbaff596fed23833a892f28871c69de0648e59f93616c473c6e64" +checksum = "9f38c4cd4469829351cf83b8b89976eb71017f76202e8af2e9ff989e73b5535f" dependencies = [ "gprimitives", "parity-scale-codec", + "scale-info", ] [[package]] diff --git a/rs/ethexe/Cargo.lock b/rs/ethexe/Cargo.lock index c52ad1734..df259a5c2 100644 --- a/rs/ethexe/Cargo.lock +++ b/rs/ethexe/Cargo.lock @@ -1899,9 +1899,9 @@ dependencies = [ [[package]] name = "gbuiltin-bls381" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490015fd6c0b7a2cfd96257a3ee71bd636ad1cc89a73c2f6f62e419a3ecad8f3" +checksum = "da5c0d4fddca6f05362cda44c30e0775f1ee99a040ac7c7df28d699082aae6be" dependencies = [ "ark-bls12-381", "ark-ec", @@ -1909,13 +1909,14 @@ dependencies = [ "ark-scale", "ark-serialize", "parity-scale-codec", + "scale-info", ] [[package]] name = "gbuiltin-eth-bridge" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370e03a4190a34bbe99ab6736dc162d4c08c6a69cec8deffcd35ac7fc9f8aa82" +checksum = "bd77189c1c742e301656941c8125169d84b12c1deac1ed11acc516aef00002d8" dependencies = [ "gprimitives", "parity-scale-codec", @@ -1924,22 +1925,24 @@ dependencies = [ [[package]] name = "gbuiltin-proxy" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2beac2a698e3438d9bc0acd884ea39ef3cd2ee2ed5e07779c1f69812e52cb4c5" +checksum = "328a23e9eb5831d49ae122d74ce0a49fb1dfd22d6f7fb8cc513f7dadf21d8780" dependencies = [ "gprimitives", "parity-scale-codec", + "scale-info", ] [[package]] name = "gbuiltin-staking" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa90eb350f6bbaff596fed23833a892f28871c69de0648e59f93616c473c6e64" +checksum = "9f38c4cd4469829351cf83b8b89976eb71017f76202e8af2e9ff989e73b5535f" dependencies = [ "gprimitives", "parity-scale-codec", + "scale-info", ] [[package]]