Struct frame_system::limits::BlockWeights
source · pub struct BlockWeights {
pub base_block: Weight,
pub max_block: Weight,
pub per_class: PerDispatchClass<WeightsPerClass>,
}Expand description
Block weight limits & base values configuration.
This object is responsible for defining weight limits and base weight values tracked during extrinsic execution.
Each block starts with base_block weight being consumed right away. Next up the
on_initialize pallet callbacks are invoked and their cost is added before any extrinsic
is executed. This cost is tracked as Mandatory dispatch class.
| | `max_block` | |
| | | |
| | | |
| | | |
| | | #| `on_initialize`
| #| `base_block` | #|
|NOM| |NOM|
||\_ Mandatory
|\__ Operational
\___ Normal
The remaining capacity can be used to dispatch extrinsics. Note that each dispatch class
is being tracked separately, but the sum can’t exceed max_block (except for reserved).
Below you can see a picture representing full block with 3 extrinsics (two Operational and
one Normal). Each class has it’s own limit max_total, but also the sum cannot exceed
max_block value.
-- `Mandatory` limit (unlimited)
| # | | |
| # | `Ext3` | - - `Operational` limit
|# | `Ext2` |- - `Normal` limit
| # | `Ext1` | # |
| #| `on_initialize` | ##|
| #| `base_block` |###|
|NOM| |NOM|
It should be obvious now that it’s possible for one class to reach it’s limit (say Normal),
while the block has still capacity to process more transactions (max_block not reached,
Operational transactions can still go in). Setting max_total to None disables the
per-class limit. This is generally highly recommended for Mandatory dispatch class, while it
can be dangerous for Normal class and should only be done with extra care and consideration.
Often it’s desirable for some class of transactions to be added to the block despite it being
full. For instance one might want to prevent high-priority Normal transactions from pushing
out lower-priority Operational transactions. In such cases you might add a reserved capacity
for given class.
_
# \
# `Ext8` - `reserved`
# _/
| # | `Ext7 | - - `Operational` limit
|# | `Ext6` | |
|# | `Ext5` |-# - `Normal` limit
|# | `Ext4` |## |
| #| `on_initialize` |###|
| #| `base_block` |###|
|NOM| |NOM|
In the above example, Ext4-6 fill up the block almost up to max_block. Ext7 would not fit
if there wasn’t the extra reserved space for Operational transactions. Note that max_total
limit applies to reserved space as well (i.e. the sum of weights of Ext7 & Ext8 mustn’t
exceed it). Setting reserved to None allows the extrinsics to always get into the block up
to their max_total limit. If max_total is set to None as well, all extrinsics witch
dispatchables of given class will always end up in the block (recommended for Mandatory
dispatch class).
As a consequence of reserved space, total consumed block weight might exceed max_block
value, so this parameter should rather be thought of as “target block weight” than a hard limit.
Fields§
§base_block: WeightBase weight of block execution.
max_block: WeightMaximal total weight consumed by all kinds of extrinsics (without reserved space).
per_class: PerDispatchClass<WeightsPerClass>Weight limits for extrinsics of given dispatch class.
Implementations§
source§impl BlockWeights
impl BlockWeights
sourcepub fn get(&self, class: DispatchClass) -> &WeightsPerClass
pub fn get(&self, class: DispatchClass) -> &WeightsPerClass
Get per-class weight settings.
Examples found in repository?
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
fn check_extrinsic_weight(
info: &DispatchInfoOf<T::RuntimeCall>,
) -> Result<(), TransactionValidityError> {
let max = T::BlockWeights::get().get(info.class).max_extrinsic;
match max {
Some(max) if info.weight.any_gt(max) =>
Err(InvalidTransaction::ExhaustsResources.into()),
_ => Ok(()),
}
}
/// Checks if the current extrinsic can fit into the block with respect to block weight limits.
///
/// Upon successes, it returns the new block weight as a `Result`.
fn check_block_weight(
info: &DispatchInfoOf<T::RuntimeCall>,
) -> Result<crate::ConsumedWeight, TransactionValidityError> {
let maximum_weight = T::BlockWeights::get();
let all_weight = Pallet::<T>::block_weight();
calculate_consumed_weight::<T::RuntimeCall>(maximum_weight, all_weight, info)
}
/// Checks if the current extrinsic can fit into the block with respect to block length limits.
///
/// Upon successes, it returns the new block length as a `Result`.
fn check_block_length(
info: &DispatchInfoOf<T::RuntimeCall>,
len: usize,
) -> Result<u32, TransactionValidityError> {
let length_limit = T::BlockLength::get();
let current_len = Pallet::<T>::all_extrinsics_len();
let added_len = len as u32;
let next_len = current_len.saturating_add(added_len);
if next_len > *length_limit.max.get(info.class) {
Err(InvalidTransaction::ExhaustsResources.into())
} else {
Ok(next_len)
}
}
/// Creates new `SignedExtension` to check weight of the extrinsic.
pub fn new() -> Self {
Self(Default::default())
}
/// Do the pre-dispatch checks. This can be applied to both signed and unsigned.
///
/// It checks and notes the new weight and length.
pub fn do_pre_dispatch(
info: &DispatchInfoOf<T::RuntimeCall>,
len: usize,
) -> Result<(), TransactionValidityError> {
let next_len = Self::check_block_length(info, len)?;
let next_weight = Self::check_block_weight(info)?;
Self::check_extrinsic_weight(info)?;
crate::AllExtrinsicsLen::<T>::put(next_len);
crate::BlockWeight::<T>::put(next_weight);
Ok(())
}
/// Do the validate checks. This can be applied to both signed and unsigned.
///
/// It only checks that the block weight and length limit will not exceed.
pub fn do_validate(info: &DispatchInfoOf<T::RuntimeCall>, len: usize) -> TransactionValidity {
// ignore the next length. If they return `Ok`, then it is below the limit.
let _ = Self::check_block_length(info, len)?;
// during validation we skip block limit check. Since the `validate_transaction`
// call runs on an empty block anyway, by this we prevent `on_initialize` weight
// consumption from causing false negatives.
Self::check_extrinsic_weight(info)?;
Ok(Default::default())
}
}
pub fn calculate_consumed_weight<Call>(
maximum_weight: BlockWeights,
mut all_weight: crate::ConsumedWeight,
info: &DispatchInfoOf<Call>,
) -> Result<crate::ConsumedWeight, TransactionValidityError>
where
Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
{
let extrinsic_weight =
info.weight.saturating_add(maximum_weight.get(info.class).base_extrinsic);
let limit_per_class = maximum_weight.get(info.class);
// add the weight. If class is unlimited, use saturating add instead of checked one.
if limit_per_class.max_total.is_none() && limit_per_class.reserved.is_none() {
all_weight.add(extrinsic_weight, info.class)
} else {
all_weight
.checked_add(extrinsic_weight, info.class)
.map_err(|_| InvalidTransaction::ExhaustsResources)?;
}
let per_class = *all_weight.get(info.class);
// Check if we don't exceed per-class allowance
match limit_per_class.max_total {
Some(max) if per_class.any_gt(max) =>
return Err(InvalidTransaction::ExhaustsResources.into()),
// There is no `max_total` limit (`None`),
// or we are below the limit.
_ => {},
}
// In cases total block weight is exceeded, we need to fall back
// to `reserved` pool if there is any.
if all_weight.total().any_gt(maximum_weight.max_block) {
match limit_per_class.reserved {
// We are over the limit in reserved pool.
Some(reserved) if per_class.any_gt(reserved) =>
return Err(InvalidTransaction::ExhaustsResources.into()),
// There is either no limit in reserved pool (`None`),
// or we are below the limit.
_ => {},
}
}
Ok(all_weight)
}More examples
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
pub fn finalize() -> T::Header {
log::debug!(
target: "runtime::system",
"[{:?}] {} extrinsics, length: {} (normal {}%, op: {}%, mandatory {}%) / normal weight:\
{} ({}%) op weight {} ({}%) / mandatory weight {} ({}%)",
Self::block_number(),
Self::extrinsic_index().unwrap_or_default(),
Self::all_extrinsics_len(),
sp_runtime::Percent::from_rational(
Self::all_extrinsics_len(),
*T::BlockLength::get().max.get(DispatchClass::Normal)
).deconstruct(),
sp_runtime::Percent::from_rational(
Self::all_extrinsics_len(),
*T::BlockLength::get().max.get(DispatchClass::Operational)
).deconstruct(),
sp_runtime::Percent::from_rational(
Self::all_extrinsics_len(),
*T::BlockLength::get().max.get(DispatchClass::Mandatory)
).deconstruct(),
Self::block_weight().get(DispatchClass::Normal),
sp_runtime::Percent::from_rational(
Self::block_weight().get(DispatchClass::Normal).ref_time(),
T::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap_or(Bounded::max_value()).ref_time()
).deconstruct(),
Self::block_weight().get(DispatchClass::Operational),
sp_runtime::Percent::from_rational(
Self::block_weight().get(DispatchClass::Operational).ref_time(),
T::BlockWeights::get().get(DispatchClass::Operational).max_total.unwrap_or(Bounded::max_value()).ref_time()
).deconstruct(),
Self::block_weight().get(DispatchClass::Mandatory),
sp_runtime::Percent::from_rational(
Self::block_weight().get(DispatchClass::Mandatory).ref_time(),
T::BlockWeights::get().get(DispatchClass::Mandatory).max_total.unwrap_or(Bounded::max_value()).ref_time()
).deconstruct(),
);
ExecutionPhase::<T>::kill();
AllExtrinsicsLen::<T>::kill();
// The following fields
//
// - <Events<T>>
// - <EventCount<T>>
// - <EventTopics<T>>
// - <Number<T>>
// - <ParentHash<T>>
// - <Digest<T>>
//
// stay to be inspected by the client and will be cleared by `Self::initialize`.
let number = <Number<T>>::get();
let parent_hash = <ParentHash<T>>::get();
let digest = <Digest<T>>::get();
let extrinsics = (0..ExtrinsicCount::<T>::take().unwrap_or_default())
.map(ExtrinsicData::<T>::take)
.collect();
let extrinsics_root = extrinsics_data_root::<T::Hashing>(extrinsics);
// move block hash pruning window by one block
let block_hash_count = T::BlockHashCount::get();
let to_remove = number.saturating_sub(block_hash_count).saturating_sub(One::one());
// keep genesis hash
if !to_remove.is_zero() {
<BlockHash<T>>::remove(to_remove);
}
let version = T::Version::get().state_version();
let storage_root = T::Hash::decode(&mut &sp_io::storage::root(version)[..])
.expect("Node is configured to use the same hash; qed");
<T::Header as traits::Header>::new(
number,
extrinsics_root,
storage_root,
parent_hash,
digest,
)
}
/// Deposits a log and ensures it matches the block's log data.
///
/// # <weight>
/// - `O(1)`
/// - 1 storage write (codec `O(1)`)
/// # </weight>
pub fn deposit_log(item: generic::DigestItem) {
<Digest<T>>::append(item);
}
/// Get the basic externalities for this pallet, useful for tests.
#[cfg(any(feature = "std", test))]
pub fn externalities() -> TestExternalities {
TestExternalities::new(sp_core::storage::Storage {
top: map![
<BlockHash<T>>::hashed_key_for(T::BlockNumber::zero()) => [69u8; 32].encode(),
<Number<T>>::hashed_key().to_vec() => T::BlockNumber::one().encode(),
<ParentHash<T>>::hashed_key().to_vec() => [69u8; 32].encode()
],
children_default: map![],
})
}
/// Get the current events deposited by the runtime.
///
/// NOTE: This should only be used in tests. Reading events from the runtime can have a large
/// impact on the PoV size of a block. Users should use alternative and well bounded storage
/// items for any behavior like this.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn events() -> Vec<EventRecord<T::RuntimeEvent, T::Hash>> {
// Dereferencing the events here is fine since we are not in the
// memory-restricted runtime.
Self::read_events_no_consensus().map(|e| *e).collect()
}
/// Get the current events deposited by the runtime.
///
/// Should only be called if you know what you are doing and outside of the runtime block
/// execution else it can have a large impact on the PoV size of a block.
pub fn read_events_no_consensus(
) -> impl sp_std::iter::Iterator<Item = Box<EventRecord<T::RuntimeEvent, T::Hash>>> {
Events::<T>::stream_iter()
}
/// Set the block number to something in particular. Can be used as an alternative to
/// `initialize` for tests that don't need to bother with the other environment entries.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn set_block_number(n: T::BlockNumber) {
<Number<T>>::put(n);
}
/// Sets the index of extrinsic that is currently executing.
#[cfg(any(feature = "std", test))]
pub fn set_extrinsic_index(extrinsic_index: u32) {
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &extrinsic_index)
}
/// Set the parent hash number to something in particular. Can be used as an alternative to
/// `initialize` for tests that don't need to bother with the other environment entries.
#[cfg(any(feature = "std", test))]
pub fn set_parent_hash(n: T::Hash) {
<ParentHash<T>>::put(n);
}
/// Set the current block weight. This should only be used in some integration tests.
#[cfg(any(feature = "std", test))]
pub fn set_block_consumed_resources(weight: Weight, len: usize) {
BlockWeight::<T>::mutate(|current_weight| {
current_weight.set(weight, DispatchClass::Normal)
});
AllExtrinsicsLen::<T>::put(len as u32);
}
/// Reset events.
///
/// This needs to be used in prior calling [`initialize`](Self::initialize) for each new block
/// to clear events from previous block.
pub fn reset_events() {
<Events<T>>::kill();
EventCount::<T>::kill();
let _ = <EventTopics<T>>::clear(u32::max_value(), None);
}
/// Assert the given `event` exists.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn assert_has_event(event: T::RuntimeEvent) {
assert!(Self::events().iter().any(|record| record.event == event))
}
/// Assert the last event equal to the given `event`.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn assert_last_event(event: T::RuntimeEvent) {
assert_eq!(Self::events().last().expect("events expected").event, event);
}
/// Return the chain's current runtime version.
pub fn runtime_version() -> RuntimeVersion {
T::Version::get()
}
/// Retrieve the account transaction counter from storage.
pub fn account_nonce(who: impl EncodeLike<T::AccountId>) -> T::Index {
Account::<T>::get(who).nonce
}
/// Increment a particular account's nonce by 1.
pub fn inc_account_nonce(who: impl EncodeLike<T::AccountId>) {
Account::<T>::mutate(who, |a| a.nonce += T::Index::one());
}
/// Note what the extrinsic data of the current extrinsic index is.
///
/// This is required to be called before applying an extrinsic. The data will used
/// in [`Self::finalize`] to calculate the correct extrinsics root.
pub fn note_extrinsic(encoded_xt: Vec<u8>) {
ExtrinsicData::<T>::insert(Self::extrinsic_index().unwrap_or_default(), encoded_xt);
}
/// To be called immediately after an extrinsic has been applied.
///
/// Emits an `ExtrinsicSuccess` or `ExtrinsicFailed` event depending on the outcome.
/// The emitted event contains the post-dispatch corrected weight including
/// the base-weight for its dispatch class.
pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, mut info: DispatchInfo) {
info.weight = extract_actual_weight(r, &info)
.saturating_add(T::BlockWeights::get().get(info.class).base_extrinsic);
info.pays_fee = extract_actual_pays_fee(r, &info);
Self::deposit_event(match r {
Ok(_) => Event::ExtrinsicSuccess { dispatch_info: info },
Err(err) => {
log::trace!(
target: "runtime::system",
"Extrinsic failed at block({:?}): {:?}",
Self::block_number(),
err,
);
Event::ExtrinsicFailed { dispatch_error: err.error, dispatch_info: info }
},
});
let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32;
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index);
ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(next_extrinsic_index));
}sourcepub fn validate(self) -> ValidationResult
pub fn validate(self) -> ValidationResult
Verifies correctness of this BlockWeights object.
Examples found in repository?
More examples
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
pub fn build(self) -> ValidationResult {
// compute max extrinsic size
let Self { mut weights, init_cost } = self;
// compute max block size.
for class in DispatchClass::all() {
weights.max_block = match weights.per_class.get(*class).max_total {
Some(max) => max.max(weights.max_block),
_ => weights.max_block,
};
}
// compute max size of single extrinsic
if let Some(init_weight) = init_cost.map(|rate| rate * weights.max_block) {
for class in DispatchClass::all() {
let per_class = weights.per_class.get_mut(*class);
if per_class.max_extrinsic.is_none() && init_cost.is_some() {
per_class.max_extrinsic = per_class
.max_total
.map(|x| x.saturating_sub(init_weight))
.map(|x| x.saturating_sub(per_class.base_extrinsic));
}
}
}
// Validate the result
weights.validate()
}sourcepub fn simple_max(block_weight: Weight) -> Self
pub fn simple_max(block_weight: Weight) -> Self
Create new weights definition, with both Normal and Operational
classes limited to given weight.
Note there is no reservation for Operational class, so this constructor
is not suitable for production deployments.
sourcepub fn with_sensible_defaults(
expected_block_weight: Weight,
normal_ratio: Perbill
) -> Self
pub fn with_sensible_defaults(
expected_block_weight: Weight,
normal_ratio: Perbill
) -> Self
Create a sensible default weights system given only expected maximal block weight and the
ratio that Normal extrinsics should occupy.
Assumptions:
- Average block initialization is assumed to be
10%. Operationaltransactions have reserved allowance (1.0 - normal_ratio)
sourcepub fn builder() -> BlockWeightsBuilder
pub fn builder() -> BlockWeightsBuilder
Start constructing new BlockWeights object.
By default all kinds except of Mandatory extrinsics are disallowed.
Examples found in repository?
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
pub fn simple_max(block_weight: Weight) -> Self {
Self::builder()
.base_block(Weight::zero())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = Weight::zero();
})
.for_class(DispatchClass::non_mandatory(), |weights| {
weights.max_total = block_weight.into();
})
.build()
.expect("We only specify max_total and leave base values as defaults; qed")
}
/// Create a sensible default weights system given only expected maximal block weight and the
/// ratio that `Normal` extrinsics should occupy.
///
/// Assumptions:
/// - Average block initialization is assumed to be `10%`.
/// - `Operational` transactions have reserved allowance (`1.0 - normal_ratio`)
pub fn with_sensible_defaults(expected_block_weight: Weight, normal_ratio: Perbill) -> Self {
let normal_weight = normal_ratio * expected_block_weight;
Self::builder()
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = normal_weight.into();
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = expected_block_weight.into();
weights.reserved = (expected_block_weight - normal_weight).into();
})
.avg_block_initialization(Perbill::from_percent(10))
.build()
.expect("Sensible defaults are tested to be valid; qed")
}Trait Implementations§
source§impl Clone for BlockWeights
impl Clone for BlockWeights
source§fn clone(&self) -> BlockWeights
fn clone(&self) -> BlockWeights
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moresource§impl Debug for BlockWeights
impl Debug for BlockWeights
source§impl Decode for BlockWeights
impl Decode for BlockWeights
source§impl Default for BlockWeights
impl Default for BlockWeights
source§impl Encode for BlockWeights
impl Encode for BlockWeights
source§fn encode_to<__CodecOutputEdqy: Output + ?Sized>(
&self,
__codec_dest_edqy: &mut __CodecOutputEdqy
)
fn encode_to<__CodecOutputEdqy: Output + ?Sized>(
&self,
__codec_dest_edqy: &mut __CodecOutputEdqy
)
source§fn size_hint(&self) -> usize
fn size_hint(&self) -> usize
source§fn using_encoded<R, F>(&self, f: F) -> Rwhere
F: FnOnce(&[u8]) -> R,
fn using_encoded<R, F>(&self, f: F) -> Rwhere
F: FnOnce(&[u8]) -> R,
source§fn encoded_size(&self) -> usize
fn encoded_size(&self) -> usize
source§impl TypeInfo for BlockWeights
impl TypeInfo for BlockWeights
impl EncodeLike<BlockWeights> for BlockWeights
Auto Trait Implementations§
impl RefUnwindSafe for BlockWeights
impl Send for BlockWeights
impl Sync for BlockWeights
impl Unpin for BlockWeights
impl UnwindSafe for BlockWeights
Blanket Implementations§
source§impl<T> CheckedConversion for T
impl<T> CheckedConversion for T
source§impl<T> DecodeLimit for Twhere
T: Decode,
impl<T> DecodeLimit for Twhere
T: Decode,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.source§impl<T> Hashable for Twhere
T: Codec,
impl<T> Hashable for Twhere
T: Codec,
fn blake2_128(&self) -> [u8; 16]
fn blake2_256(&self) -> [u8; 32]
fn blake2_128_concat(&self) -> Vec<u8, Global> ⓘ
fn twox_128(&self) -> [u8; 16]
fn twox_256(&self) -> [u8; 32]
fn twox_64_concat(&self) -> Vec<u8, Global> ⓘ
fn identity(&self) -> Vec<u8, Global> ⓘ
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T, Outer> IsWrappedBy<Outer> for Twhere
Outer: AsRef<T> + AsMut<T> + From<T>,
T: From<Outer>,
impl<T, Outer> IsWrappedBy<Outer> for Twhere
Outer: AsRef<T> + AsMut<T> + From<T>,
T: From<Outer>,
§impl<T> SaturatedConversion for T
impl<T> SaturatedConversion for T
§fn saturated_from<T>(t: T) -> Selfwhere
Self: UniqueSaturatedFrom<T>,
fn saturated_from<T>(t: T) -> Selfwhere
Self: UniqueSaturatedFrom<T>,
§fn saturated_into<T>(self) -> Twhere
Self: UniqueSaturatedInto<T>,
fn saturated_into<T>(self) -> Twhere
Self: UniqueSaturatedInto<T>,
T. Read moresource§impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
source§fn unchecked_into(self) -> T
fn unchecked_into(self) -> T
unchecked_from.§impl<T, S> UniqueSaturatedInto<T> for Swhere
T: Bounded,
S: TryInto<T>,
impl<T, S> UniqueSaturatedInto<T> for Swhere
T: Bounded,
S: TryInto<T>,
§fn unique_saturated_into(self) -> T
fn unique_saturated_into(self) -> T
T.