mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 19:51:05 +00:00
Metadata V16: Be more dynamic over which hasher is used. (#1974)
* Use DynamicHasher256 to support Blake2 or Keccack depending on chain * remove Config::Hash associated type, replace with HashFor<Config> alias * Fix doc links * fix wasm tests * Don't strip system pallet associated types. check System.Hashing, not Hash. Rename BlockHash trait to Hash * Tweak comment * fmt * fix merge * Fix typo
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
use super::BlockError;
|
||||
use crate::blocks::extrinsic_transaction_extensions::ExtrinsicTransactionExtensions;
|
||||
use crate::{
|
||||
config::{Config, Hasher},
|
||||
config::{Config, HashFor, Hasher},
|
||||
error::{Error, MetadataError},
|
||||
Metadata,
|
||||
};
|
||||
@@ -22,6 +22,7 @@ pub use crate::blocks::StaticExtrinsic;
|
||||
pub struct Extrinsics<T: Config> {
|
||||
extrinsics: Vec<Arc<(Extrinsic<'static, u32>, Vec<u8>)>>,
|
||||
metadata: Metadata,
|
||||
hasher: T::Hasher,
|
||||
_marker: core::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -30,6 +31,7 @@ impl<T: Config> Extrinsics<T> {
|
||||
/// each extrinsic hash (in the form of bytes) and some metadata that
|
||||
/// we'll use to decode them.
|
||||
pub fn decode_from(extrinsics: Vec<Vec<u8>>, metadata: Metadata) -> Result<Self, Error> {
|
||||
let hasher = T::Hasher::new(&metadata);
|
||||
let extrinsics = extrinsics
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
@@ -63,6 +65,7 @@ impl<T: Config> Extrinsics<T> {
|
||||
|
||||
Ok(Self {
|
||||
extrinsics,
|
||||
hasher,
|
||||
metadata,
|
||||
_marker: core::marker::PhantomData,
|
||||
})
|
||||
@@ -85,10 +88,16 @@ impl<T: Config> Extrinsics<T> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = ExtrinsicDetails<T>> + Send + Sync + 'static {
|
||||
let extrinsics = self.extrinsics.clone();
|
||||
let num_extrinsics = self.extrinsics.len();
|
||||
let hasher = self.hasher;
|
||||
let metadata = self.metadata.clone();
|
||||
|
||||
(0..num_extrinsics).map(move |index| {
|
||||
ExtrinsicDetails::new(index as u32, extrinsics[index].clone(), metadata.clone())
|
||||
ExtrinsicDetails::new(
|
||||
index as u32,
|
||||
extrinsics[index].clone(),
|
||||
hasher,
|
||||
metadata.clone(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -133,6 +142,8 @@ pub struct ExtrinsicDetails<T: Config> {
|
||||
index: u32,
|
||||
/// Extrinsic bytes and decode info.
|
||||
ext: Arc<(Extrinsic<'static, u32>, Vec<u8>)>,
|
||||
/// Hash the extrinsic if we want.
|
||||
hasher: T::Hasher,
|
||||
/// Subxt metadata to fetch the extrinsic metadata.
|
||||
metadata: Metadata,
|
||||
_marker: core::marker::PhantomData<T>,
|
||||
@@ -147,20 +158,22 @@ where
|
||||
pub fn new(
|
||||
index: u32,
|
||||
ext: Arc<(Extrinsic<'static, u32>, Vec<u8>)>,
|
||||
hasher: T::Hasher,
|
||||
metadata: Metadata,
|
||||
) -> ExtrinsicDetails<T> {
|
||||
ExtrinsicDetails {
|
||||
index,
|
||||
ext,
|
||||
hasher,
|
||||
metadata,
|
||||
_marker: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate and return the hash of the extrinsic, based on the configured hasher.
|
||||
pub fn hash(&self) -> T::Hash {
|
||||
pub fn hash(&self) -> HashFor<T> {
|
||||
// Use hash(), not hash_of(), because we don't want to double encode the bytes.
|
||||
T::Hasher::hash(self.bytes())
|
||||
self.hasher.hash(self.bytes())
|
||||
}
|
||||
|
||||
/// Is the extrinsic signed?
|
||||
@@ -532,6 +545,7 @@ mod tests {
|
||||
#[test]
|
||||
fn tx_hashes_line_up() {
|
||||
let metadata = metadata();
|
||||
let hasher = <SubstrateConfig as Config>::Hasher::new(&metadata);
|
||||
|
||||
let tx = crate::dynamic::tx(
|
||||
"Test",
|
||||
@@ -559,7 +573,11 @@ mod tests {
|
||||
// Both of these types should produce the same bytes.
|
||||
assert_eq!(tx_encoded.encoded(), extrinsic.bytes(), "bytes should eq");
|
||||
// Both of these types should produce the same hash.
|
||||
assert_eq!(tx_encoded.hash(), extrinsic.hash(), "hashes should eq");
|
||||
assert_eq!(
|
||||
tx_encoded.hash_with(hasher),
|
||||
extrinsic.hash(),
|
||||
"hashes should eq"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+5
-2
@@ -4,7 +4,10 @@
|
||||
|
||||
//! A couple of client types that we use elsewhere.
|
||||
|
||||
use crate::{config::Config, metadata::Metadata};
|
||||
use crate::{
|
||||
config::{Config, HashFor},
|
||||
metadata::Metadata,
|
||||
};
|
||||
use derive_where::derive_where;
|
||||
|
||||
/// This provides access to some relevant client state in transaction extensions,
|
||||
@@ -12,7 +15,7 @@ use derive_where::derive_where;
|
||||
#[derive_where(Clone, Debug)]
|
||||
pub struct ClientState<C: Config> {
|
||||
/// Genesis hash.
|
||||
pub genesis_hash: C::Hash,
|
||||
pub genesis_hash: HashFor<C>,
|
||||
/// Runtime version.
|
||||
pub runtime_version: RuntimeVersion,
|
||||
/// Metadata.
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
//! [`crate::config::DefaultExtrinsicParams`] provides a general-purpose
|
||||
//! implementation of this that will work in many cases.
|
||||
|
||||
use crate::{client::ClientState, error::ExtrinsicParamsError, Config};
|
||||
use crate::{
|
||||
client::ClientState,
|
||||
config::{Config, HashFor},
|
||||
error::ExtrinsicParamsError,
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use core::any::Any;
|
||||
|
||||
@@ -74,7 +78,7 @@ pub trait Params<T: Config> {
|
||||
/// Set the account nonce.
|
||||
fn inject_account_nonce(&mut self, _nonce: u64) {}
|
||||
/// Set the current block.
|
||||
fn inject_block(&mut self, _number: u64, _hash: T::Hash) {}
|
||||
fn inject_block(&mut self, _number: u64, _hash: HashFor<T>) {}
|
||||
}
|
||||
|
||||
impl<T: Config> Params<T> for () {}
|
||||
@@ -85,7 +89,8 @@ macro_rules! impl_tuples {
|
||||
fn inject_account_nonce(&mut self, nonce: u64) {
|
||||
$(self.$index.inject_account_nonce(nonce);)+
|
||||
}
|
||||
fn inject_block(&mut self, number: u64, hash: Conf::Hash) {
|
||||
|
||||
fn inject_block(&mut self, number: u64, hash: HashFor<Conf>) {
|
||||
$(self.$index.inject_block(number, hash);)+
|
||||
}
|
||||
}
|
||||
|
||||
+16
-12
@@ -20,6 +20,7 @@ use core::fmt::Debug;
|
||||
use scale_decode::DecodeAsType;
|
||||
use scale_encode::EncodeAsType;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use subxt_metadata::Metadata;
|
||||
|
||||
pub use default_extrinsic_params::{DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder};
|
||||
pub use extrinsic_params::{ExtrinsicParams, ExtrinsicParamsEncoder};
|
||||
@@ -33,9 +34,6 @@ pub use transaction_extensions::TransactionExtension;
|
||||
// And we want the compiler to infer `Send` and `Sync` OK for things which have `T: Config`
|
||||
// rather than having to `unsafe impl` them ourselves.
|
||||
pub trait Config: Sized + Send + Sync + 'static {
|
||||
/// The output of the `Hasher` function.
|
||||
type Hash: BlockHash;
|
||||
|
||||
/// The account ID type.
|
||||
type AccountId: Debug + Clone + Encode + Decode + Serialize + Send;
|
||||
|
||||
@@ -46,7 +44,7 @@ pub trait Config: Sized + Send + Sync + 'static {
|
||||
type Signature: Debug + Clone + Encode + Decode + Send;
|
||||
|
||||
/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
|
||||
type Hasher: Debug + Hasher<Output = Self::Hash>;
|
||||
type Hasher: Debug + Clone + Copy + Hasher + Send + Sync;
|
||||
|
||||
/// The block header.
|
||||
type Header: Debug + Header<Hasher = Self::Hasher> + Sync + Send + DeserializeOwned;
|
||||
@@ -58,11 +56,14 @@ pub trait Config: Sized + Send + Sync + 'static {
|
||||
type AssetId: Debug + Clone + Encode + DecodeAsType + EncodeAsType + Send;
|
||||
}
|
||||
|
||||
/// Given some [`Config`], this returns the type of hash used.
|
||||
pub type HashFor<T> = <<T as Config>::Hasher as Hasher>::Output;
|
||||
|
||||
/// given some [`Config`], this return the other params needed for its `ExtrinsicParams`.
|
||||
pub type ParamsFor<T> = <<T as Config>::ExtrinsicParams as ExtrinsicParams<T>>::Params;
|
||||
|
||||
/// Block hashes must conform to a bunch of things to be used in Subxt.
|
||||
pub trait BlockHash:
|
||||
pub trait Hash:
|
||||
Debug
|
||||
+ Copy
|
||||
+ Send
|
||||
@@ -77,7 +78,7 @@ pub trait BlockHash:
|
||||
+ core::hash::Hash
|
||||
{
|
||||
}
|
||||
impl<T> BlockHash for T where
|
||||
impl<T> Hash for T where
|
||||
T: Debug
|
||||
+ Copy
|
||||
+ Send
|
||||
@@ -97,15 +98,18 @@ impl<T> BlockHash for T where
|
||||
/// and extrinsics.
|
||||
pub trait Hasher {
|
||||
/// The type given back from the hash operation
|
||||
type Output;
|
||||
type Output: Hash;
|
||||
|
||||
/// Construct a new hasher.
|
||||
fn new(metadata: &Metadata) -> Self;
|
||||
|
||||
/// Hash some bytes to the given output type.
|
||||
fn hash(s: &[u8]) -> Self::Output;
|
||||
fn hash(&self, s: &[u8]) -> Self::Output;
|
||||
|
||||
/// Hash some SCALE encodable type to the given output type.
|
||||
fn hash_of<S: Encode>(s: &S) -> Self::Output {
|
||||
fn hash_of<S: Encode>(&self, s: &S) -> Self::Output {
|
||||
let out = s.encode();
|
||||
Self::hash(&out)
|
||||
self.hash(&out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +124,7 @@ pub trait Header: Sized + Encode + Decode {
|
||||
fn number(&self) -> Self::Number;
|
||||
|
||||
/// Hash this header.
|
||||
fn hash(&self) -> <Self::Hasher as Hasher>::Output {
|
||||
Self::Hasher::hash_of(self)
|
||||
fn hash_with(&self, hasher: Self::Hasher) -> <Self::Hasher as Hasher>::Output {
|
||||
hasher.hash_of(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ pub use primitive_types::{H256, U256};
|
||||
pub enum PolkadotConfig {}
|
||||
|
||||
impl Config for PolkadotConfig {
|
||||
type Hash = <SubstrateConfig as Config>::Hash;
|
||||
type AccountId = <SubstrateConfig as Config>::AccountId;
|
||||
type Signature = <SubstrateConfig as Config>::Signature;
|
||||
type Hasher = <SubstrateConfig as Config>::Hasher;
|
||||
|
||||
@@ -11,6 +11,7 @@ use alloc::vec::Vec;
|
||||
use codec::{Decode, Encode};
|
||||
pub use primitive_types::{H256, U256};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use subxt_metadata::Metadata;
|
||||
|
||||
/// Default set of commonly used types by Substrate runtimes.
|
||||
// Note: We only use this at the type level, so it should be impossible to
|
||||
@@ -21,12 +22,11 @@ use serde::{Deserialize, Serialize};
|
||||
pub enum SubstrateConfig {}
|
||||
|
||||
impl Config for SubstrateConfig {
|
||||
type Hash = H256;
|
||||
type AccountId = AccountId32;
|
||||
type Address = MultiAddress<Self::AccountId, u32>;
|
||||
type Signature = MultiSignature;
|
||||
type Hasher = BlakeTwo256;
|
||||
type Header = SubstrateHeader<u32, BlakeTwo256>;
|
||||
type Hasher = DynamicHasher256;
|
||||
type Header = SubstrateHeader<u32, DynamicHasher256>;
|
||||
type ExtrinsicParams = SubstrateExtrinsicParams<Self>;
|
||||
type AssetId = u32;
|
||||
}
|
||||
@@ -39,17 +39,73 @@ pub type SubstrateExtrinsicParams<T> = DefaultExtrinsicParams<T>;
|
||||
/// This is what you provide to methods like `sign_and_submit()`.
|
||||
pub type SubstrateExtrinsicParamsBuilder<T> = DefaultExtrinsicParamsBuilder<T>;
|
||||
|
||||
/// A type that can hash values using the blaks2_256 algorithm.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode)]
|
||||
/// A hasher (ie implements [`Hasher`]) which hashes values using the blaks2_256 algorithm.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct BlakeTwo256;
|
||||
|
||||
impl Hasher for BlakeTwo256 {
|
||||
type Output = H256;
|
||||
fn hash(s: &[u8]) -> Self::Output {
|
||||
|
||||
fn new(_metadata: &Metadata) -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn hash(&self, s: &[u8]) -> Self::Output {
|
||||
sp_crypto_hashing::blake2_256(s).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// A hasher (ie implements [`Hasher`]) which inspects the runtime metadata to decide how to
|
||||
/// hash types, falling back to blake2_256 if the hasher information is not available.
|
||||
///
|
||||
/// Currently this hasher supports only `BlakeTwo256` and `Keccak256` hashing methods.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DynamicHasher256(HashType);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum HashType {
|
||||
// Most chains use this:
|
||||
BlakeTwo256,
|
||||
// Chains like Hyperbridge use this (tends to be eth compatible chains)
|
||||
Keccak256,
|
||||
// If we don't have V16 metadata, we'll emit this and default to BlakeTwo256.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Hasher for DynamicHasher256 {
|
||||
type Output = H256;
|
||||
|
||||
fn new(metadata: &Metadata) -> Self {
|
||||
// Determine the Hash associated type used for the current chain, if possible.
|
||||
let Some(system_pallet) = metadata.pallet_by_name("System") else {
|
||||
return Self(HashType::Unknown);
|
||||
};
|
||||
let Some(hash_ty_id) = system_pallet.associated_type_id("Hashing") else {
|
||||
return Self(HashType::Unknown);
|
||||
};
|
||||
|
||||
let ty = metadata
|
||||
.types()
|
||||
.resolve(hash_ty_id)
|
||||
.expect("Type information for 'Hashing' associated type should be in metadata");
|
||||
|
||||
let hash_type = match ty.path.ident().as_deref().unwrap_or("") {
|
||||
"BlakeTwo256" => HashType::BlakeTwo256,
|
||||
"Keccak256" => HashType::Keccak256,
|
||||
_ => HashType::Unknown,
|
||||
};
|
||||
|
||||
Self(hash_type)
|
||||
}
|
||||
|
||||
fn hash(&self, s: &[u8]) -> Self::Output {
|
||||
match self.0 {
|
||||
HashType::BlakeTwo256 | HashType::Unknown => sp_crypto_hashing::blake2_256(s).into(),
|
||||
HashType::Keccak256 => sp_crypto_hashing::keccak_256(s).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic Substrate header type, adapted from `sp_runtime::generic::Header`.
|
||||
/// The block number and hasher can be configured to adapt this for other nodes.
|
||||
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
@@ -75,11 +131,12 @@ pub struct SubstrateHeader<N: Copy + Into<U256> + TryFrom<U256>, H: Hasher> {
|
||||
impl<N, H> Header for SubstrateHeader<N, H>
|
||||
where
|
||||
N: Copy + Into<u64> + Into<U256> + TryFrom<U256> + Encode,
|
||||
H: Hasher + Encode,
|
||||
H: Hasher,
|
||||
SubstrateHeader<N, H>: Encode + Decode,
|
||||
{
|
||||
type Number = N;
|
||||
type Hasher = H;
|
||||
|
||||
fn number(&self) -> Self::Number {
|
||||
self.number
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
use super::extrinsic_params::ExtrinsicParams;
|
||||
use crate::client::ClientState;
|
||||
use crate::config::{ExtrinsicParamsEncoder, Header};
|
||||
use crate::config::ExtrinsicParamsEncoder;
|
||||
use crate::config::{Config, HashFor};
|
||||
use crate::error::ExtrinsicParamsError;
|
||||
use crate::utils::{Era, Static};
|
||||
use crate::Config;
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
@@ -262,7 +262,7 @@ impl<T: Config> TransactionExtension<T> for CheckTxVersion {
|
||||
}
|
||||
|
||||
/// The [`CheckGenesis`] transaction extension.
|
||||
pub struct CheckGenesis<T: Config>(T::Hash);
|
||||
pub struct CheckGenesis<T: Config>(HashFor<T>);
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckGenesis<T> {
|
||||
type Params = ();
|
||||
@@ -288,7 +288,7 @@ impl<T: Config> TransactionExtension<T> for CheckGenesis<T> {
|
||||
/// The [`CheckMortality`] transaction extension.
|
||||
pub struct CheckMortality<T: Config> {
|
||||
params: CheckMortalityParamsInner<T>,
|
||||
genesis_hash: T::Hash,
|
||||
genesis_hash: HashFor<T>,
|
||||
}
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckMortality<T> {
|
||||
@@ -352,7 +352,7 @@ enum CheckMortalityParamsInner<T: Config> {
|
||||
MortalFromBlock {
|
||||
for_n_blocks: u64,
|
||||
from_block_n: u64,
|
||||
from_block_hash: T::Hash,
|
||||
from_block_hash: HashFor<T>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -368,23 +368,14 @@ impl<T: Config> CheckMortalityParams<T> {
|
||||
pub fn mortal(for_n_blocks: u64) -> Self {
|
||||
Self(CheckMortalityParamsInner::MortalForBlocks(for_n_blocks))
|
||||
}
|
||||
/// Configure a transaction that will be mortal for the number of blocks given,
|
||||
/// and from the block header provided.
|
||||
pub fn mortal_from(for_n_blocks: u64, from_block: T::Header) -> Self {
|
||||
Self(CheckMortalityParamsInner::MortalFromBlock {
|
||||
for_n_blocks,
|
||||
from_block_n: from_block.number().into(),
|
||||
from_block_hash: from_block.hash(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Configure a transaction that will be mortal for the number of blocks given,
|
||||
/// and from the block details provided. Prefer to use [`CheckMortalityParams::mortal()`]
|
||||
/// or [`CheckMortalityParams::mortal_from()`] which both avoid the block number and hash
|
||||
/// from being misaligned.
|
||||
/// where possible, which prevents the block number and hash from being misaligned.
|
||||
pub fn mortal_from_unchecked(
|
||||
for_n_blocks: u64,
|
||||
from_block_n: u64,
|
||||
from_block_hash: T::Hash,
|
||||
from_block_hash: HashFor<T>,
|
||||
) -> Self {
|
||||
Self(CheckMortalityParamsInner::MortalFromBlock {
|
||||
for_n_blocks,
|
||||
@@ -399,7 +390,7 @@ impl<T: Config> CheckMortalityParams<T> {
|
||||
}
|
||||
|
||||
impl<T: Config> Params<T> for CheckMortalityParams<T> {
|
||||
fn inject_block(&mut self, from_block_n: u64, from_block_hash: <T as Config>::Hash) {
|
||||
fn inject_block(&mut self, from_block_n: u64, from_block_hash: HashFor<T>) {
|
||||
match &self.0 {
|
||||
CheckMortalityParamsInner::MortalForBlocks(n) => {
|
||||
self.0 = CheckMortalityParamsInner::MortalFromBlock {
|
||||
|
||||
+11
-7
@@ -45,7 +45,11 @@ use derive_where::derive_where;
|
||||
use scale_decode::{DecodeAsFields, DecodeAsType};
|
||||
use subxt_metadata::PalletMetadata;
|
||||
|
||||
use crate::{error::MetadataError, Config, Error, Metadata};
|
||||
use crate::{
|
||||
config::{Config, HashFor},
|
||||
error::MetadataError,
|
||||
Error, Metadata,
|
||||
};
|
||||
|
||||
/// Create a new [`Events`] instance from the given bytes.
|
||||
///
|
||||
@@ -232,7 +236,7 @@ pub struct EventDetails<T: Config> {
|
||||
// end of everything (fields + topics)
|
||||
end_idx: usize,
|
||||
metadata: Metadata,
|
||||
topics: Vec<T::Hash>,
|
||||
topics: Vec<HashFor<T>>,
|
||||
}
|
||||
|
||||
impl<T: Config> EventDetails<T> {
|
||||
@@ -281,7 +285,7 @@ impl<T: Config> EventDetails<T> {
|
||||
let event_fields_end_idx = all_bytes.len() - input.len();
|
||||
|
||||
// topics come after the event data in EventRecord.
|
||||
let topics = Vec::<T::Hash>::decode(input)?;
|
||||
let topics = Vec::<HashFor<T>>::decode(input)?;
|
||||
|
||||
// what bytes did we skip over in total, including topics.
|
||||
let end_idx = all_bytes.len() - input.len();
|
||||
@@ -413,7 +417,7 @@ impl<T: Config> EventDetails<T> {
|
||||
}
|
||||
|
||||
/// Return the topics associated with this event.
|
||||
pub fn topics(&self) -> &[T::Hash] {
|
||||
pub fn topics(&self) -> &[HashFor<T>] {
|
||||
&self.topics
|
||||
}
|
||||
}
|
||||
@@ -430,7 +434,7 @@ pub struct EventMetadataDetails<'a> {
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test_utils {
|
||||
use super::*;
|
||||
use crate::config::{Config, SubstrateConfig};
|
||||
use crate::config::{HashFor, SubstrateConfig};
|
||||
use codec::Encode;
|
||||
use frame_metadata::{
|
||||
v15::{
|
||||
@@ -463,12 +467,12 @@ pub(crate) mod test_utils {
|
||||
pub struct EventRecord<E: Encode> {
|
||||
phase: Phase,
|
||||
event: AllEvents<E>,
|
||||
topics: Vec<<SubstrateConfig as Config>::Hash>,
|
||||
topics: Vec<HashFor<SubstrateConfig>>,
|
||||
}
|
||||
|
||||
impl<E: Encode> EventRecord<E> {
|
||||
/// Create a new event record with the given phase, event, and topics.
|
||||
pub fn new(phase: Phase, event: E, topics: Vec<<SubstrateConfig as Config>::Hash>) -> Self {
|
||||
pub fn new(phase: Phase, event: E, topics: Vec<HashFor<SubstrateConfig>>) -> Self {
|
||||
Self {
|
||||
phase,
|
||||
event: AllEvents::Test(event),
|
||||
|
||||
+10
-6
@@ -9,7 +9,7 @@
|
||||
//! ```rust
|
||||
//! use subxt_signer::sr25519::dev;
|
||||
//! use subxt_macro::subxt;
|
||||
//! use subxt_core::config::PolkadotConfig;
|
||||
//! use subxt_core::config::{PolkadotConfig, HashFor};
|
||||
//! use subxt_core::config::DefaultExtrinsicParamsBuilder as Params;
|
||||
//! use subxt_core::tx;
|
||||
//! use subxt_core::utils::H256;
|
||||
@@ -59,7 +59,7 @@
|
||||
pub mod payload;
|
||||
pub mod signer;
|
||||
|
||||
use crate::config::{Config, ExtrinsicParams, ExtrinsicParamsEncoder, Hasher};
|
||||
use crate::config::{Config, ExtrinsicParams, ExtrinsicParamsEncoder, HashFor, Hasher};
|
||||
use crate::error::{Error, ExtrinsicError, MetadataError};
|
||||
use crate::metadata::Metadata;
|
||||
use crate::utils::Encoded;
|
||||
@@ -406,7 +406,8 @@ impl<T: Config> PartialTransactionV5<T> {
|
||||
|
||||
/// This represents a signed transaction that's ready to be submitted.
|
||||
/// Use [`Transaction::encoded()`] or [`Transaction::into_encoded()`] to
|
||||
/// get the bytes for it, or [`Transaction::hash()`] to get the hash.
|
||||
/// get the bytes for it, or [`Transaction::hash_with()`] to hash the transaction
|
||||
/// given an instance of [`Config::Hasher`].
|
||||
pub struct Transaction<T> {
|
||||
encoded: Encoded,
|
||||
marker: core::marker::PhantomData<T>,
|
||||
@@ -422,9 +423,12 @@ impl<T: Config> Transaction<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate and return the hash of the extrinsic, based on the configured hasher.
|
||||
pub fn hash(&self) -> T::Hash {
|
||||
T::Hasher::hash_of(&self.encoded)
|
||||
/// Calculate and return the hash of the extrinsic, based on the provided hasher.
|
||||
/// If you don't have a hasher to hand, you can construct one using the metadata
|
||||
/// with `T::Hasher::new(&metadata)`. This will create a hasher suitable for the
|
||||
/// current chain where possible.
|
||||
pub fn hash_with(&self, hasher: T::Hasher) -> HashFor<T> {
|
||||
hasher.hash_of(&self.encoded)
|
||||
}
|
||||
|
||||
/// Returns the SCALE encoded extrinsic bytes.
|
||||
|
||||
Reference in New Issue
Block a user