Remove bounds on Config trait that aren't strictly necessary (#389)

* Use Derivative to skip bounds on T when they aren't necessary, and remove unnecessary bounds on Config

* loosen a couple more derive bounds

* Use PhantomDataSendSync to avoid accidentally removing Send+Sync bounds
This commit is contained in:
James Wilson
2022-01-13 16:07:27 +00:00
committed by GitHub
parent d1e2985ce8
commit 96fe1d61a9
8 changed files with 179 additions and 99 deletions
+1
View File
@@ -39,6 +39,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate/", branch = "maste
sp-version = { package = "sp-version", git = "https://github.com/paritytech/substrate/", branch = "master" }
frame-metadata = "14.0.0"
derivative = "2.2.0"
[dev-dependencies]
sp-arithmetic = { git = "https://github.com/paritytech/substrate/", branch = "master", default-features = false }
+3 -1
View File
@@ -40,6 +40,7 @@ use crate::{
Config,
Metadata,
};
use derivative::Derivative;
use std::sync::Arc;
/// ClientBuilder for constructing a Client.
@@ -111,7 +112,8 @@ impl ClientBuilder {
}
/// Client to interface with a substrate node.
#[derive(Clone)]
#[derive(Derivative)]
#[derivative(Clone(bound = ""))]
pub struct Client<T: Config> {
rpc: Rpc<T>,
genesis_hash: T::Hash,
+7 -3
View File
@@ -32,7 +32,10 @@ use sp_runtime::traits::{
};
/// Runtime types.
pub trait Config: Clone + Default + Sized + Send + Sync + 'static {
// Note: the 'static bound isn't strictly required, but currently deriving TypeInfo
// automatically applies a 'static bound to all generic types (including this one),
// and so until that is resolved, we'll keep the (easy to satisfy) constraint here.
pub trait Config: 'static {
/// Account index (aka nonce) type. This stores the number of previous
/// transactions associated with a sender account.
type Index: Parameter + Member + Default + AtLeast32Bit + Copy + scale_info::TypeInfo;
@@ -83,8 +86,9 @@ pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug {}
impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug {}
/// Default set of commonly used types by Substrate runtimes.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DefaultConfig;
// Note: We only use this at the type level, so it should be impossible to
// create an instance of it.
pub enum DefaultConfig {}
impl Config for DefaultConfig {
type Index = u32;
+15 -17
View File
@@ -14,16 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
use codec::{
Codec,
Compact,
Decode,
Encode,
Error as CodecError,
Input,
};
use std::marker::PhantomData;
use crate::{
metadata::{
EventMetadata,
@@ -33,8 +23,18 @@ use crate::{
Error,
Event,
Metadata,
PhantomDataSendSync,
Phase,
};
use codec::{
Codec,
Compact,
Decode,
Encode,
Error as CodecError,
Input,
};
use derivative::Derivative;
use scale_info::{
TypeDef,
TypeDefPrimitive,
@@ -69,16 +69,14 @@ impl RawEvent {
}
/// Events decoder.
#[derive(Debug, Clone)]
pub struct EventsDecoder<T> {
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Debug(bound = ""))]
pub struct EventsDecoder<T: Config> {
metadata: Metadata,
marker: PhantomData<T>,
marker: PhantomDataSendSync<T>,
}
impl<T> EventsDecoder<T>
where
T: Config,
{
impl<T: Config> EventsDecoder<T> {
/// Creates a new `EventsDecoder`.
pub fn new(metadata: Metadata) -> Self {
Self {
+94 -61
View File
@@ -14,14 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
use crate::PhantomDataSendSync;
use codec::{
Decode,
Encode,
};
use core::{
fmt::Debug,
marker::PhantomData,
};
use derivative::Derivative;
use scale_info::TypeInfo;
use sp_runtime::{
generic::Era,
@@ -48,19 +46,22 @@ use crate::Config;
/// returned via `additional_signed()`.
/// Ensure the runtime version registered in the transaction is the same as at present.
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct CheckSpecVersion<T: Config>(
pub PhantomData<T>,
pub PhantomDataSendSync<T>,
/// Local version to be used for `AdditionalSigned`
#[codec(skip)]
pub u32,
);
impl<T> SignedExtension for CheckSpecVersion<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for CheckSpecVersion<T> {
const IDENTIFIER: &'static str = "CheckSpecVersion";
type AccountId = T::AccountId;
type Call = ();
@@ -88,19 +89,22 @@ where
///
/// This is modified from the substrate version to allow passing in of the version, which is
/// returned via `additional_signed()`.
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct CheckTxVersion<T: Config>(
pub PhantomData<T>,
pub PhantomDataSendSync<T>,
/// Local version to be used for `AdditionalSigned`
#[codec(skip)]
pub u32,
);
impl<T> SignedExtension for CheckTxVersion<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for CheckTxVersion<T> {
const IDENTIFIER: &'static str = "CheckTxVersion";
type AccountId = T::AccountId;
type Call = ();
@@ -128,19 +132,22 @@ where
///
/// This is modified from the substrate version to allow passing in of the genesis hash, which is
/// returned via `additional_signed()`.
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct CheckGenesis<T: Config>(
pub PhantomData<T>,
pub PhantomDataSendSync<T>,
/// Local genesis hash to be used for `AdditionalSigned`
#[codec(skip)]
pub T::Hash,
);
impl<T> SignedExtension for CheckGenesis<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for CheckGenesis<T> {
const IDENTIFIER: &'static str = "CheckGenesis";
type AccountId = T::AccountId;
type Call = ();
@@ -169,20 +176,23 @@ where
/// This is modified from the substrate version to allow passing in of the genesis hash, which is
/// returned via `additional_signed()`. It assumes therefore `Era::Immortal` (The transaction is
/// valid forever)
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct CheckMortality<T: Config>(
/// The default structure for the Extra encoding
pub (Era, PhantomData<T>),
pub (Era, PhantomDataSendSync<T>),
/// Local genesis hash to be used for `AdditionalSigned`
#[codec(skip)]
pub T::Hash,
);
impl<T> SignedExtension for CheckMortality<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for CheckMortality<T> {
const IDENTIFIER: &'static str = "CheckMortality";
type AccountId = T::AccountId;
type Call = ();
@@ -205,14 +215,17 @@ where
}
/// Nonce check and increment to give replay protection for transactions.
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct CheckNonce<T: Config>(#[codec(compact)] pub T::Index);
impl<T> SignedExtension for CheckNonce<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for CheckNonce<T> {
const IDENTIFIER: &'static str = "CheckNonce";
type AccountId = T::AccountId;
type Call = ();
@@ -235,14 +248,17 @@ where
}
/// Resource limit check.
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct CheckWeight<T: Config>(pub PhantomData<T>);
pub struct CheckWeight<T: Config>(pub PhantomDataSendSync<T>);
impl<T> SignedExtension for CheckWeight<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for CheckWeight<T> {
const IDENTIFIER: &'static str = "CheckWeight";
type AccountId = T::AccountId;
type Call = ();
@@ -266,17 +282,21 @@ where
/// Require the transactor pay for themselves and maybe include a tip to gain additional priority
/// in the queue.
#[derive(Encode, Decode, Clone, Debug, Default, Eq, PartialEq, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = ""),
Default(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct ChargeTransactionPayment<T: Config>(
#[codec(compact)] u128,
pub PhantomData<T>,
pub PhantomDataSendSync<T>,
);
impl<T> SignedExtension for ChargeTransactionPayment<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for ChargeTransactionPayment<T> {
const IDENTIFIER: &'static str = "ChargeTransactionPayment";
type AccountId = T::AccountId;
type Call = ();
@@ -300,7 +320,14 @@ where
/// Require the transactor pay for themselves and maybe include a tip to gain additional priority
/// in the queue.
#[derive(Encode, Decode, Clone, Default, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = ""),
Default(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct ChargeAssetTxPayment<T: Config> {
/// The tip for the block author.
@@ -309,13 +336,10 @@ pub struct ChargeAssetTxPayment<T: Config> {
/// The asset with which to pay the tip.
pub asset_id: Option<u32>,
/// Marker for unused type parameter.
pub marker: PhantomData<T>,
pub marker: PhantomDataSendSync<T>,
}
impl<T> SignedExtension for ChargeAssetTxPayment<T>
where
T: Config + Clone + Debug + Eq + Send + Sync,
{
impl<T: Config> SignedExtension for ChargeAssetTxPayment<T> {
const IDENTIFIER: &'static str = "ChargeAssetTxPayment";
type AccountId = T::AccountId;
type Call = ();
@@ -358,19 +382,25 @@ pub trait SignedExtra<T: Config>: SignedExtension {
}
/// Default `SignedExtra` for substrate runtimes.
#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, TypeInfo)]
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = "")
)]
#[scale_info(skip_type_params(T))]
pub struct DefaultExtraWithTxPayment<T: Config, X> {
spec_version: u32,
tx_version: u32,
nonce: T::Index,
genesis_hash: T::Hash,
marker: PhantomData<X>,
marker: PhantomDataSendSync<X>,
}
impl<T, X> SignedExtra<T> for DefaultExtraWithTxPayment<T, X>
where
T: Config + Clone + Debug + Eq + Send + Sync,
T: Config,
X: SignedExtension<AccountId = T::AccountId, Call = ()> + Default,
{
type Extra = (
@@ -396,18 +426,21 @@ where
tx_version,
nonce,
genesis_hash,
marker: PhantomData,
marker: PhantomDataSendSync::new(),
}
}
fn extra(&self) -> Self::Extra {
(
CheckSpecVersion(PhantomData, self.spec_version),
CheckTxVersion(PhantomData, self.tx_version),
CheckGenesis(PhantomData, self.genesis_hash),
CheckMortality((Era::Immortal, PhantomData), self.genesis_hash),
CheckSpecVersion(PhantomDataSendSync::new(), self.spec_version),
CheckTxVersion(PhantomDataSendSync::new(), self.tx_version),
CheckGenesis(PhantomDataSendSync::new(), self.genesis_hash),
CheckMortality(
(Era::Immortal, PhantomDataSendSync::new()),
self.genesis_hash,
),
CheckNonce(self.nonce),
CheckWeight(PhantomData),
CheckWeight(PhantomDataSendSync::new()),
X::default(),
)
}
@@ -416,7 +449,7 @@ where
impl<T, X: SignedExtension<AccountId = T::AccountId, Call = ()> + Default> SignedExtension
for DefaultExtraWithTxPayment<T, X>
where
T: Config + Clone + Debug + Eq + Send + Sync,
T: Config,
X: SignedExtension,
{
const IDENTIFIER: &'static str = "DefaultExtra";
+36 -7
View File
@@ -53,10 +53,8 @@ use codec::{
DecodeAll,
Encode,
};
use core::{
fmt::Debug,
marker::PhantomData,
};
use core::fmt::Debug;
use derivative::Derivative;
mod client;
mod config;
@@ -180,10 +178,17 @@ pub enum Phase {
///
/// [`WrapperKeepOpaque`] stores the type only in its opaque format, aka as a `Vec<u8>`. To
/// access the real type `T` [`Self::try_decode`] needs to be used.
#[derive(Debug, Eq, PartialEq, Default, Clone, Decode, Encode)]
#[derive(Derivative, Encode, Decode)]
#[derivative(
Debug(bound = ""),
Clone(bound = ""),
PartialEq(bound = ""),
Eq(bound = ""),
Default(bound = "")
)]
pub struct WrapperKeepOpaque<T> {
data: Vec<u8>,
_phantom: PhantomData<T>,
_phantom: PhantomDataSendSync<T>,
}
impl<T: Decode> WrapperKeepOpaque<T> {
@@ -208,7 +213,31 @@ impl<T: Decode> WrapperKeepOpaque<T> {
pub fn from_encoded(data: Vec<u8>) -> Self {
Self {
data,
_phantom: PhantomData,
_phantom: PhantomDataSendSync::new(),
}
}
}
/// A version of [`std::marker::PhantomData`] that is also Send and Sync (which is fine
/// because regardless of the generic param, it is always possible to Send + Sync this
/// 0 size type).
#[derive(Derivative, Encode, Decode, scale_info::TypeInfo)]
#[derivative(
Clone(bound = ""),
PartialEq(bound = ""),
Debug(bound = ""),
Eq(bound = ""),
Default(bound = "")
)]
#[scale_info(skip_type_params(T))]
#[doc(hidden)]
pub struct PhantomDataSendSync<T>(core::marker::PhantomData<T>);
impl<T> PhantomDataSendSync<T> {
pub(crate) fn new() -> Self {
Self(core::marker::PhantomData)
}
}
unsafe impl<T> Send for PhantomDataSendSync<T> {}
unsafe impl<T> Sync for PhantomDataSendSync<T> {}
+10 -1
View File
@@ -132,13 +132,22 @@ impl StorageMapKey {
}
/// Client for querying runtime storage.
#[derive(Clone)]
pub struct StorageClient<'a, T: Config> {
rpc: &'a Rpc<T>,
metadata: &'a Metadata,
iter_page_size: u32,
}
impl<'a, T: Config> Clone for StorageClient<'a, T> {
fn clone(&self) -> Self {
Self {
rpc: self.rpc,
metadata: self.metadata,
iter_page_size: self.iter_page_size,
}
}
}
impl<'a, T: Config> StorageClient<'a, T> {
/// Create a new [`StorageClient`]
pub fn new(rpc: &'a Rpc<T>, metadata: &'a Metadata, iter_page_size: u32) -> Self {
+13 -9
View File
@@ -16,11 +16,6 @@
use std::task::Poll;
use sp_core::storage::StorageKey;
use sp_runtime::traits::Hash;
pub use sp_runtime::traits::SignedExtension;
pub use sp_version::RuntimeVersion;
use crate::{
client::Client,
error::{
@@ -32,6 +27,7 @@ use crate::{
Config,
Phase,
};
use derivative::Derivative;
use futures::{
Stream,
StreamExt,
@@ -40,10 +36,15 @@ use jsonrpsee::core::{
client::Subscription as RpcSubscription,
Error as RpcError,
};
use sp_core::storage::StorageKey;
use sp_runtime::traits::Hash;
pub use sp_runtime::traits::SignedExtension;
pub use sp_version::RuntimeVersion;
/// This struct represents a subscription to the progress of some transaction, and is
/// returned from [`crate::SubmittableExtrinsic::sign_and_submit_then_watch()`].
#[derive(Debug)]
#[derive(Derivative)]
#[derivative(Debug(bound = ""))]
pub struct TransactionProgress<'client, T: Config> {
sub: Option<RpcSubscription<SubstrateTransactionStatus<T::Hash, T::Hash>>>,
ext_hash: T::Hash,
@@ -261,7 +262,8 @@ impl<'client, T: Config> Stream for TransactionProgress<'client, T> {
/// finalized. The `FinalityTimeout` event will be emitted when the block did not reach finality
/// within 512 blocks. This either indicates that finality is not available for your chain,
/// or that finality gadget is lagging behind.
#[derive(Debug)]
#[derive(Derivative)]
#[derivative(Debug(bound = ""))]
pub enum TransactionStatus<'client, T: Config> {
/// The transaction is part of the "future" queue.
Future,
@@ -310,7 +312,8 @@ impl<'client, T: Config> TransactionStatus<'client, T> {
}
/// This struct represents a transaction that has made it into a block.
#[derive(Debug)]
#[derive(Derivative)]
#[derivative(Debug(bound = ""))]
pub struct TransactionInBlock<'client, T: Config> {
block_hash: T::Hash,
ext_hash: T::Hash,
@@ -416,7 +419,8 @@ impl<'client, T: Config> TransactionInBlock<'client, T> {
/// This represents the events related to our transaction.
/// We can iterate over the events, or look for a specific one.
#[derive(Debug)]
#[derive(Derivative)]
#[derivative(Debug(bound = ""))]
pub struct TransactionEvents<T: Config> {
block_hash: T::Hash,
ext_hash: T::Hash,