sp-api: Don't be dirty (#11015)

Ensure that the sp api macros don't use functions without providing the full path to the function.
This hygiene ensures that we don't actually try to call a method of an imported trait for example.
This commit is contained in:
Bastian Köcher
2022-03-11 23:20:18 +01:00
committed by GitHub
parent 47f96b6584
commit d9d05969a1
2 changed files with 59 additions and 55 deletions
@@ -378,21 +378,21 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
#[cfg(any(feature = "std", test))]
#[allow(clippy::too_many_arguments)]
pub fn #fn_name<
R: #crate_::Encode + #crate_::Decode + PartialEq,
R: #crate_::Encode + #crate_::Decode + std::cmp::PartialEq,
NC: FnOnce() -> std::result::Result<R, #crate_::ApiError> + std::panic::UnwindSafe,
Block: #crate_::BlockT,
T: #crate_::CallApiAt<Block>,
>(
call_runtime_at: &T,
at: &#crate_::BlockId<Block>,
args: Vec<u8>,
args: std::vec::Vec<u8>,
changes: &std::cell::RefCell<#crate_::OverlayedChanges>,
storage_transaction_cache: &std::cell::RefCell<
#crate_::StorageTransactionCache<Block, T::StateBackend>
>,
native_call: Option<NC>,
native_call: std::option::Option<NC>,
context: #crate_::ExecutionContext,
recorder: &Option<#crate_::ProofRecorder<Block>>,
recorder: &std::option::Option<#crate_::ProofRecorder<Block>>,
) -> std::result::Result<#crate_::NativeOrEncoded<R>, #crate_::ApiError> {
let version = call_runtime_at.runtime_version_at(at)?;
@@ -412,7 +412,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
recorder,
};
let ret = call_runtime_at.call_api_at(params)?;
let ret = #crate_::CallApiAt::<Block>::call_api_at(call_runtime_at, params)?;
return Ok(ret)
}
@@ -429,7 +429,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
recorder,
};
call_runtime_at.call_api_at(params)
#crate_::CallApiAt::<Block>::call_api_at(call_runtime_at, params)
}
));
}
@@ -677,13 +677,13 @@ impl<'a> ToClientSideDecl<'a> {
#native_handling
},
#crate_::NativeOrEncoded::Encoded(r) => {
<#ret_type as #crate_::Decode>::decode(&mut &r[..])
.map_err(|err|
#crate_::ApiError::FailedToDecodeReturnValue {
function: #function_name,
error: err,
}
)
std::result::Result::map_err(
<#ret_type as #crate_::Decode>::decode(&mut &r[..]),
|err| #crate_::ApiError::FailedToDecodeReturnValue {
function: #function_name,
error: err,
}
)
}
}
)
@@ -207,7 +207,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
storage_transaction_cache: std::cell::RefCell<
#crate_::StorageTransactionCache<Block, C::StateBackend>
>,
recorder: Option<#crate_::ProofRecorder<Block>>,
recorder: std::option::Option<#crate_::ProofRecorder<Block>>,
}
// `RuntimeApi` itself is not threadsafe. However, an instance is only available in a
@@ -233,12 +233,12 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
&self,
call: F,
) -> R where Self: Sized {
self.changes.borrow_mut().start_transaction();
*self.commit_on_success.borrow_mut() = false;
#crate_::OverlayedChanges::start_transaction(&mut std::cell::RefCell::borrow_mut(&self.changes));
*std::cell::RefCell::borrow_mut(&self.commit_on_success) = false;
let res = call(self);
*self.commit_on_success.borrow_mut() = true;
*std::cell::RefCell::borrow_mut(&self.commit_on_success) = true;
self.commit_or_rollback(matches!(res, #crate_::TransactionOutcome::Commit(_)));
self.commit_or_rollback(std::matches!(res, #crate_::TransactionOutcome::Commit(_)));
res.into_inner()
}
@@ -247,9 +247,8 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
&self,
at: &#crate_::BlockId<Block>,
) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
self.call
.runtime_version_at(at)
.map(|v| v.has_api_with(&A::ID, |v| v == A::VERSION))
#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>(
@@ -257,51 +256,48 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
at: &#crate_::BlockId<Block>,
pred: P,
) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
self.call
.runtime_version_at(at)
.map(|v| v.has_api_with(&A::ID, pred))
#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: &#crate_::BlockId<Block>,
) -> std::result::Result<Option<u32>, #crate_::ApiError> where Self: Sized {
self.call
.runtime_version_at(at)
.map(|v| v.api_version(&A::ID))
#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 = Some(Default::default());
self.recorder = std::option::Option::Some(std::default::Default::default());
}
fn proof_recorder(&self) -> Option<#crate_::ProofRecorder<Block>> {
self.recorder.clone()
fn proof_recorder(&self) -> std::option::Option<#crate_::ProofRecorder<Block>> {
std::clone::Clone::clone(&self.recorder)
}
fn extract_proof(&mut self) -> Option<#crate_::StorageProof> {
self.recorder
.take()
.map(|recorder| recorder.to_storage_proof())
fn extract_proof(&mut self) -> std::option::Option<#crate_::StorageProof> {
std::option::Option::take(&mut self.recorder)
.map(|recorder| #crate_::ProofRecorder::<Block>::to_storage_proof(&recorder))
}
fn into_storage_changes(
&self,
backend: &Self::StateBackend,
parent_hash: Block::Hash,
) -> std::result::Result<
) -> core::result::Result<
#crate_::StorageChanges<C::StateBackend, Block>,
String
> where Self: Sized {
let at = #crate_::BlockId::Hash(parent_hash.clone());
let state_version = self.call
.runtime_version_at(&at)
.map(|v| v.state_version())
let at = #crate_::BlockId::Hash(std::clone::Clone::clone(&parent_hash));
let state_version = #crate_::CallApiAt::<Block>::runtime_version_at(self.call, &at)
.map(|v| #crate_::RuntimeVersion::state_version(&v))
.map_err(|e| format!("Failed to get state version: {}", e))?;
self.changes.replace(Default::default()).into_storage_changes(
#crate_::OverlayedChanges::into_storage_changes(
std::cell::RefCell::take(&self.changes),
backend,
self.storage_transaction_cache.replace(Default::default()),
core::cell::RefCell::take(&self.storage_transaction_cache),
state_version,
)
}
@@ -321,9 +317,9 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
RuntimeApiImpl {
call: unsafe { std::mem::transmute(call) },
commit_on_success: true.into(),
changes: Default::default(),
recorder: Default::default(),
storage_transaction_cache: Default::default(),
changes: std::default::Default::default(),
recorder: std::default::Default::default(),
storage_transaction_cache: std::default::Default::default(),
}.into()
}
}
@@ -331,20 +327,22 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
#[cfg(any(feature = "std", test))]
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> RuntimeApiImpl<Block, C> {
fn call_api_at<
R: #crate_::Encode + #crate_::Decode + PartialEq,
R: #crate_::Encode + #crate_::Decode + std::cmp::PartialEq,
F: FnOnce(
&C,
&std::cell::RefCell<#crate_::OverlayedChanges>,
&std::cell::RefCell<#crate_::StorageTransactionCache<Block, C::StateBackend>>,
&Option<#crate_::ProofRecorder<Block>>,
&std::option::Option<#crate_::ProofRecorder<Block>>,
) -> std::result::Result<#crate_::NativeOrEncoded<R>, E>,
E,
>(
&self,
call_api_at: F,
) -> std::result::Result<#crate_::NativeOrEncoded<R>, E> {
if *self.commit_on_success.borrow() {
self.changes.borrow_mut().start_transaction();
if *std::cell::RefCell::borrow(&self.commit_on_success) {
#crate_::OverlayedChanges::start_transaction(
&mut std::cell::RefCell::borrow_mut(&self.changes)
);
}
let res = call_api_at(
&self.call,
@@ -353,7 +351,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
&self.recorder,
);
self.commit_or_rollback(res.is_ok());
self.commit_or_rollback(std::result::Result::is_ok(&res));
res
}
@@ -362,13 +360,19 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
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 *self.commit_on_success.borrow() {
if commit {
self.changes.borrow_mut().commit_transaction().expect(proof);
transactions; qed";
if *std::cell::RefCell::borrow(&self.commit_on_success) {
let res = if commit {
#crate_::OverlayedChanges::commit_transaction(
&mut std::cell::RefCell::borrow_mut(&self.changes)
)
} else {
self.changes.borrow_mut().rollback_transaction().expect(proof);
}
#crate_::OverlayedChanges::rollback_transaction(
&mut std::cell::RefCell::borrow_mut(&self.changes)
)
};
std::result::Result::expect(res, proof);
}
}
}