mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 20:27:58 +00:00
sp-api: Make the generated code act based on std in sp-api (#14267)
* sp-api: Make the generated code act based on `std` in `sp-api` Instead of letting the macro generate code that checks if the `std` feature is enabled, it will now generate code that checks if the `std` feature is enabled for the `sp-api` crate. The old implementation basically required that the crate in which the macro was used, had a `std` feature. Now we don't have this requirement anymore and act accordingly the feature in `sp-api` directly. * Missing feature! --------- Co-authored-by: parity-processbot <>
This commit is contained in:
@@ -172,11 +172,12 @@ fn generate_dispatch_function(impls: &[ItemImpl]) -> Result<TokenStream> {
|
||||
});
|
||||
|
||||
Ok(quote!(
|
||||
#[cfg(feature = "std")]
|
||||
pub fn dispatch(method: &str, mut #data: &[u8]) -> Option<Vec<u8>> {
|
||||
match method {
|
||||
#( #impl_calls )*
|
||||
_ => None,
|
||||
#c::std_enabled! {
|
||||
pub fn dispatch(method: &str, mut #data: &[u8]) -> Option<Vec<u8>> {
|
||||
match method {
|
||||
#( #impl_calls )*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
@@ -195,22 +196,23 @@ fn generate_wasm_interface(impls: &[ItemImpl]) -> Result<TokenStream> {
|
||||
Ident::new(&prefix_function_with_trait(&trait_, &fn_name), Span::call_site());
|
||||
|
||||
quote!(
|
||||
#( #attrs )*
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[no_mangle]
|
||||
pub unsafe fn #fn_name(input_data: *mut u8, input_len: usize) -> u64 {
|
||||
let mut #input = if input_len == 0 {
|
||||
&[0u8; 0]
|
||||
} else {
|
||||
unsafe {
|
||||
#c::slice::from_raw_parts(input_data, input_len)
|
||||
}
|
||||
};
|
||||
#c::std_disabled! {
|
||||
#( #attrs )*
|
||||
#[no_mangle]
|
||||
pub unsafe fn #fn_name(input_data: *mut u8, input_len: usize) -> u64 {
|
||||
let mut #input = if input_len == 0 {
|
||||
&[0u8; 0]
|
||||
} else {
|
||||
unsafe {
|
||||
#c::slice::from_raw_parts(input_data, input_len)
|
||||
}
|
||||
};
|
||||
|
||||
#c::init_runtime_logger();
|
||||
#c::init_runtime_logger();
|
||||
|
||||
let output = (move || { #impl_ })();
|
||||
#c::to_substrate_wasm_fn_return_value(&output)
|
||||
let output = (move || { #impl_ })();
|
||||
#c::to_substrate_wasm_fn_return_value(&output)
|
||||
}
|
||||
}
|
||||
)
|
||||
});
|
||||
@@ -224,175 +226,173 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
|
||||
Ok(quote!(
|
||||
pub struct RuntimeApi {}
|
||||
/// Implements all runtime apis for the client side.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub struct RuntimeApiImpl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block> + 'static> {
|
||||
call: &'static C,
|
||||
commit_on_success: std::cell::RefCell<bool>,
|
||||
changes: std::cell::RefCell<#crate_::OverlayedChanges>,
|
||||
storage_transaction_cache: std::cell::RefCell<
|
||||
#crate_::StorageTransactionCache<Block, C::StateBackend>
|
||||
>,
|
||||
recorder: std::option::Option<#crate_::ProofRecorder<Block>>,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiExt<Block> for
|
||||
RuntimeApiImpl<Block, C>
|
||||
{
|
||||
type StateBackend = C::StateBackend;
|
||||
|
||||
fn execute_in_transaction<F: FnOnce(&Self) -> #crate_::TransactionOutcome<R>, R>(
|
||||
&self,
|
||||
call: F,
|
||||
) -> R where Self: Sized {
|
||||
self.start_transaction();
|
||||
|
||||
*std::cell::RefCell::borrow_mut(&self.commit_on_success) = false;
|
||||
let res = call(self);
|
||||
*std::cell::RefCell::borrow_mut(&self.commit_on_success) = true;
|
||||
|
||||
self.commit_or_rollback(std::matches!(res, #crate_::TransactionOutcome::Commit(_)));
|
||||
|
||||
res.into_inner()
|
||||
#crate_::std_enabled! {
|
||||
pub struct RuntimeApiImpl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block> + 'static> {
|
||||
call: &'static C,
|
||||
commit_on_success: std::cell::RefCell<bool>,
|
||||
changes: std::cell::RefCell<#crate_::OverlayedChanges>,
|
||||
storage_transaction_cache: std::cell::RefCell<
|
||||
#crate_::StorageTransactionCache<Block, C::StateBackend>
|
||||
>,
|
||||
recorder: std::option::Option<#crate_::ProofRecorder<Block>>,
|
||||
}
|
||||
|
||||
fn has_api<A: #crate_::RuntimeApiInfo + ?Sized>(
|
||||
&self,
|
||||
at: <Block as #crate_::BlockT>::Hash,
|
||||
) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
|
||||
#crate_::CallApiAt::<Block>::runtime_version_at(self.call, at)
|
||||
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiExt<Block> for
|
||||
RuntimeApiImpl<Block, C>
|
||||
{
|
||||
type StateBackend = C::StateBackend;
|
||||
|
||||
fn execute_in_transaction<F: FnOnce(&Self) -> #crate_::TransactionOutcome<R>, R>(
|
||||
&self,
|
||||
call: F,
|
||||
) -> R where Self: Sized {
|
||||
self.start_transaction();
|
||||
|
||||
*std::cell::RefCell::borrow_mut(&self.commit_on_success) = false;
|
||||
let res = call(self);
|
||||
*std::cell::RefCell::borrow_mut(&self.commit_on_success) = true;
|
||||
|
||||
self.commit_or_rollback(std::matches!(res, #crate_::TransactionOutcome::Commit(_)));
|
||||
|
||||
res.into_inner()
|
||||
}
|
||||
|
||||
fn has_api<A: #crate_::RuntimeApiInfo + ?Sized>(
|
||||
&self,
|
||||
at: <Block as #crate_::BlockT>::Hash,
|
||||
) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
|
||||
#crate_::CallApiAt::<Block>::runtime_version_at(self.call, at)
|
||||
.map(|v| #crate_::RuntimeVersion::has_api_with(&v, &A::ID, |v| v == A::VERSION))
|
||||
}
|
||||
}
|
||||
|
||||
fn has_api_with<A: #crate_::RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>(
|
||||
&self,
|
||||
at: <Block as #crate_::BlockT>::Hash,
|
||||
pred: P,
|
||||
) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
|
||||
#crate_::CallApiAt::<Block>::runtime_version_at(self.call, at)
|
||||
fn has_api_with<A: #crate_::RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>(
|
||||
&self,
|
||||
at: <Block as #crate_::BlockT>::Hash,
|
||||
pred: P,
|
||||
) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
|
||||
#crate_::CallApiAt::<Block>::runtime_version_at(self.call, at)
|
||||
.map(|v| #crate_::RuntimeVersion::has_api_with(&v, &A::ID, pred))
|
||||
}
|
||||
}
|
||||
|
||||
fn api_version<A: #crate_::RuntimeApiInfo + ?Sized>(
|
||||
&self,
|
||||
at: <Block as #crate_::BlockT>::Hash,
|
||||
) -> std::result::Result<Option<u32>, #crate_::ApiError> where Self: Sized {
|
||||
#crate_::CallApiAt::<Block>::runtime_version_at(self.call, at)
|
||||
fn api_version<A: #crate_::RuntimeApiInfo + ?Sized>(
|
||||
&self,
|
||||
at: <Block as #crate_::BlockT>::Hash,
|
||||
) -> std::result::Result<Option<u32>, #crate_::ApiError> where Self: Sized {
|
||||
#crate_::CallApiAt::<Block>::runtime_version_at(self.call, at)
|
||||
.map(|v| #crate_::RuntimeVersion::api_version(&v, &A::ID))
|
||||
}
|
||||
}
|
||||
|
||||
fn record_proof(&mut self) {
|
||||
self.recorder = std::option::Option::Some(std::default::Default::default());
|
||||
}
|
||||
fn record_proof(&mut self) {
|
||||
self.recorder = std::option::Option::Some(std::default::Default::default());
|
||||
}
|
||||
|
||||
fn proof_recorder(&self) -> std::option::Option<#crate_::ProofRecorder<Block>> {
|
||||
std::clone::Clone::clone(&self.recorder)
|
||||
}
|
||||
fn proof_recorder(&self) -> std::option::Option<#crate_::ProofRecorder<Block>> {
|
||||
std::clone::Clone::clone(&self.recorder)
|
||||
}
|
||||
|
||||
fn extract_proof(
|
||||
&mut self,
|
||||
) -> std::option::Option<#crate_::StorageProof> {
|
||||
let recorder = std::option::Option::take(&mut self.recorder);
|
||||
std::option::Option::map(recorder, |recorder| {
|
||||
#crate_::ProofRecorder::<Block>::drain_storage_proof(recorder)
|
||||
})
|
||||
}
|
||||
fn extract_proof(
|
||||
&mut self,
|
||||
) -> std::option::Option<#crate_::StorageProof> {
|
||||
let recorder = std::option::Option::take(&mut self.recorder);
|
||||
std::option::Option::map(recorder, |recorder| {
|
||||
#crate_::ProofRecorder::<Block>::drain_storage_proof(recorder)
|
||||
})
|
||||
}
|
||||
|
||||
fn into_storage_changes(
|
||||
&self,
|
||||
backend: &Self::StateBackend,
|
||||
parent_hash: Block::Hash,
|
||||
) -> core::result::Result<
|
||||
#crate_::StorageChanges<C::StateBackend, Block>,
|
||||
fn into_storage_changes(
|
||||
&self,
|
||||
backend: &Self::StateBackend,
|
||||
parent_hash: Block::Hash,
|
||||
) -> core::result::Result<
|
||||
#crate_::StorageChanges<C::StateBackend, Block>,
|
||||
String
|
||||
> where Self: Sized {
|
||||
let state_version = #crate_::CallApiAt::<Block>::runtime_version_at(self.call, std::clone::Clone::clone(&parent_hash))
|
||||
.map(|v| #crate_::RuntimeVersion::state_version(&v))
|
||||
.map_err(|e| format!("Failed to get state version: {}", e))?;
|
||||
> where Self: Sized {
|
||||
let state_version = #crate_::CallApiAt::<Block>::runtime_version_at(self.call, std::clone::Clone::clone(&parent_hash))
|
||||
.map(|v| #crate_::RuntimeVersion::state_version(&v))
|
||||
.map_err(|e| format!("Failed to get state version: {}", e))?;
|
||||
|
||||
#crate_::OverlayedChanges::into_storage_changes(
|
||||
std::cell::RefCell::take(&self.changes),
|
||||
backend,
|
||||
core::cell::RefCell::take(&self.storage_transaction_cache),
|
||||
state_version,
|
||||
)
|
||||
#crate_::OverlayedChanges::into_storage_changes(
|
||||
std::cell::RefCell::take(&self.changes),
|
||||
backend,
|
||||
core::cell::RefCell::take(&self.storage_transaction_cache),
|
||||
state_version,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl<Block: #crate_::BlockT, C> #crate_::ConstructRuntimeApi<Block, C>
|
||||
for RuntimeApi
|
||||
where
|
||||
C: #crate_::CallApiAt<Block> + 'static,
|
||||
{
|
||||
type RuntimeApi = RuntimeApiImpl<Block, C>;
|
||||
impl<Block: #crate_::BlockT, C> #crate_::ConstructRuntimeApi<Block, C>
|
||||
for RuntimeApi
|
||||
where
|
||||
C: #crate_::CallApiAt<Block> + 'static,
|
||||
{
|
||||
type RuntimeApi = RuntimeApiImpl<Block, C>;
|
||||
|
||||
fn construct_runtime_api<'a>(
|
||||
call: &'a C,
|
||||
) -> #crate_::ApiRef<'a, Self::RuntimeApi> {
|
||||
RuntimeApiImpl {
|
||||
call: unsafe { std::mem::transmute(call) },
|
||||
commit_on_success: true.into(),
|
||||
changes: std::default::Default::default(),
|
||||
recorder: std::default::Default::default(),
|
||||
storage_transaction_cache: std::default::Default::default(),
|
||||
}.into()
|
||||
fn construct_runtime_api<'a>(
|
||||
call: &'a C,
|
||||
) -> #crate_::ApiRef<'a, Self::RuntimeApi> {
|
||||
RuntimeApiImpl {
|
||||
call: unsafe { std::mem::transmute(call) },
|
||||
commit_on_success: true.into(),
|
||||
changes: std::default::Default::default(),
|
||||
recorder: std::default::Default::default(),
|
||||
storage_transaction_cache: std::default::Default::default(),
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> RuntimeApiImpl<Block, C> {
|
||||
fn commit_or_rollback(&self, commit: bool) {
|
||||
let proof = "\
|
||||
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> RuntimeApiImpl<Block, C> {
|
||||
fn commit_or_rollback(&self, commit: bool) {
|
||||
let proof = "\
|
||||
We only close a transaction when we opened one ourself.
|
||||
Other parts of the runtime that make use of transactions (state-machine)
|
||||
also balance their transactions. The runtime cannot close client initiated
|
||||
transactions; qed";
|
||||
if *std::cell::RefCell::borrow(&self.commit_on_success) {
|
||||
let res = if commit {
|
||||
let res = if let Some(recorder) = &self.recorder {
|
||||
#crate_::ProofRecorder::<Block>::commit_transaction(&recorder)
|
||||
if *std::cell::RefCell::borrow(&self.commit_on_success) {
|
||||
let res = if commit {
|
||||
let res = if let Some(recorder) = &self.recorder {
|
||||
#crate_::ProofRecorder::<Block>::commit_transaction(&recorder)
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let res2 = #crate_::OverlayedChanges::commit_transaction(
|
||||
&mut std::cell::RefCell::borrow_mut(&self.changes)
|
||||
);
|
||||
|
||||
// Will panic on an `Err` below, however we should call commit
|
||||
// on the recorder and the changes together.
|
||||
std::result::Result::and(res, std::result::Result::map_err(res2, drop))
|
||||
} else {
|
||||
Ok(())
|
||||
let res = if let Some(recorder) = &self.recorder {
|
||||
#crate_::ProofRecorder::<Block>::rollback_transaction(&recorder)
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let res2 = #crate_::OverlayedChanges::rollback_transaction(
|
||||
&mut std::cell::RefCell::borrow_mut(&self.changes)
|
||||
);
|
||||
|
||||
// Will panic on an `Err` below, however we should call commit
|
||||
// on the recorder and the changes together.
|
||||
std::result::Result::and(res, std::result::Result::map_err(res2, drop))
|
||||
};
|
||||
|
||||
let res2 = #crate_::OverlayedChanges::commit_transaction(
|
||||
&mut std::cell::RefCell::borrow_mut(&self.changes)
|
||||
);
|
||||
|
||||
// Will panic on an `Err` below, however we should call commit
|
||||
// on the recorder and the changes together.
|
||||
std::result::Result::and(res, std::result::Result::map_err(res2, drop))
|
||||
} else {
|
||||
let res = if let Some(recorder) = &self.recorder {
|
||||
#crate_::ProofRecorder::<Block>::rollback_transaction(&recorder)
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let res2 = #crate_::OverlayedChanges::rollback_transaction(
|
||||
&mut std::cell::RefCell::borrow_mut(&self.changes)
|
||||
);
|
||||
|
||||
// Will panic on an `Err` below, however we should call commit
|
||||
// on the recorder and the changes together.
|
||||
std::result::Result::and(res, std::result::Result::map_err(res2, drop))
|
||||
};
|
||||
|
||||
std::result::Result::expect(res, proof);
|
||||
}
|
||||
}
|
||||
|
||||
fn start_transaction(&self) {
|
||||
if !*std::cell::RefCell::borrow(&self.commit_on_success) {
|
||||
return
|
||||
std::result::Result::expect(res, proof);
|
||||
}
|
||||
}
|
||||
|
||||
#crate_::OverlayedChanges::start_transaction(
|
||||
&mut std::cell::RefCell::borrow_mut(&self.changes)
|
||||
);
|
||||
if let Some(recorder) = &self.recorder {
|
||||
#crate_::ProofRecorder::<Block>::start_transaction(&recorder);
|
||||
fn start_transaction(&self) {
|
||||
if !*std::cell::RefCell::borrow(&self.commit_on_success) {
|
||||
return
|
||||
}
|
||||
|
||||
#crate_::OverlayedChanges::start_transaction(
|
||||
&mut std::cell::RefCell::borrow_mut(&self.changes)
|
||||
);
|
||||
if let Some(recorder) = &self.recorder {
|
||||
#crate_::ProofRecorder::<Block>::start_transaction(&recorder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,10 +571,6 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
|
||||
|
||||
input.attrs = filter_cfg_attrs(&input.attrs);
|
||||
|
||||
// The implementation for the `RuntimeApiImpl` is only required when compiling with
|
||||
// the feature `std` or `test`.
|
||||
input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] ));
|
||||
|
||||
fold::fold_item_impl(self, input)
|
||||
}
|
||||
}
|
||||
@@ -595,7 +591,10 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result<TokenStream>
|
||||
|
||||
result.push(processed_impl);
|
||||
}
|
||||
Ok(quote!( #( #result )* ))
|
||||
|
||||
let crate_ = generate_crate_access();
|
||||
|
||||
Ok(quote!( #crate_::std_enabled! { #( #result )* } ))
|
||||
}
|
||||
|
||||
fn populate_runtime_api_versions(
|
||||
@@ -612,13 +611,14 @@ fn populate_runtime_api_versions(
|
||||
));
|
||||
|
||||
sections.push(quote!(
|
||||
#( #attrs )*
|
||||
const _: () = {
|
||||
// All sections with the same name are going to be merged by concatenation.
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[link_section = "runtime_apis"]
|
||||
static SECTION_CONTENTS: [u8; 12] = #crate_access::serialize_runtime_api_info(#id, #version);
|
||||
};
|
||||
#crate_access::std_disabled! {
|
||||
#( #attrs )*
|
||||
const _: () = {
|
||||
// All sections with the same name are going to be merged by concatenation.
|
||||
#[link_section = "runtime_apis"]
|
||||
static SECTION_CONTENTS: [u8; 12] = #crate_access::serialize_runtime_api_info(#id, #version);
|
||||
};
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user