mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 13:37:57 +00:00
ed25519_verify: Support using dalek for historical blocks (#12661)
* ed25519_verify: Support using dalek for historical blocks The switch from `ed25519-dalek` to `ed25519-zebra` was actually a breaking change. `ed25519-zebra` is more permissive. To support historical blocks when syncing a chain this pull request introduces an externalities extension `UseDalekExt`. This extension is just used as a signaling mechanism to `ed25519_verify` to use `ed25519-dalek` when it is present. Together with `ExtensionBeforeBlock` it can be used to setup a node in way to sync historical blocks that require `ed25519-dalek`, because they included a transaction that verified differently as when using `ed25519-zebra`. This feature can be enabled in the following way. In the chain service file, directly after the client is created, the following code should be added: ``` use sc_client_api::ExecutorProvider; client.execution_extensions().set_extensions_factory( sc_client_api::execution_extensions::ExtensionBeforeBlock::<Block, sp_io::UseDalekExt>::new(BLOCK_NUMBER_UNTIL_DALEK_SHOULD_BE_USED) ); ``` * Fix doc * More fixes * Update client/api/src/execution_extensions.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Fix merge and warning * Fix docs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
@@ -29,12 +29,18 @@ use sp_core::{
|
||||
offchain::{self, OffchainDbExt, OffchainWorkerExt, TransactionPoolExt},
|
||||
ExecutionContext,
|
||||
};
|
||||
use sp_externalities::Extensions;
|
||||
use sp_externalities::{Extension, Extensions};
|
||||
use sp_keystore::{KeystoreExt, SyncCryptoStorePtr};
|
||||
use sp_runtime::{generic::BlockId, traits};
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, NumberFor},
|
||||
};
|
||||
pub use sp_state_machine::ExecutionStrategy;
|
||||
use sp_state_machine::{DefaultHandler, ExecutionManager};
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
/// Execution strategies settings.
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -63,18 +69,81 @@ impl Default for ExecutionStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate the starting set of ExternalitiesExtensions based upon the given capabilities
|
||||
pub trait ExtensionsFactory: Send + Sync {
|
||||
/// Make `Extensions` for given `Capabilities`.
|
||||
fn extensions_for(&self, capabilities: offchain::Capabilities) -> Extensions;
|
||||
/// Generate the starting set of [`Extensions`].
|
||||
///
|
||||
/// These [`Extensions`] are passed to the environment a runtime is executed in.
|
||||
pub trait ExtensionsFactory<Block: BlockT>: Send + Sync {
|
||||
/// Create [`Extensions`] for the given input.
|
||||
///
|
||||
/// - `block_hash`: The hash of the block in the context that extensions will be used.
|
||||
/// - `block_number`: The number of the block in the context that extensions will be used.
|
||||
/// - `capabilities`: The capabilities
|
||||
fn extensions_for(
|
||||
&self,
|
||||
block_hash: Block::Hash,
|
||||
block_number: NumberFor<Block>,
|
||||
capabilities: offchain::Capabilities,
|
||||
) -> Extensions;
|
||||
}
|
||||
|
||||
impl ExtensionsFactory for () {
|
||||
fn extensions_for(&self, _capabilities: offchain::Capabilities) -> Extensions {
|
||||
impl<Block: BlockT> ExtensionsFactory<Block> for () {
|
||||
fn extensions_for(
|
||||
&self,
|
||||
_: Block::Hash,
|
||||
_: NumberFor<Block>,
|
||||
_capabilities: offchain::Capabilities,
|
||||
) -> Extensions {
|
||||
Extensions::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT, T: ExtensionsFactory<Block>> ExtensionsFactory<Block> for Vec<T> {
|
||||
fn extensions_for(
|
||||
&self,
|
||||
block_hash: Block::Hash,
|
||||
block_number: NumberFor<Block>,
|
||||
capabilities: offchain::Capabilities,
|
||||
) -> Extensions {
|
||||
let mut exts = Extensions::new();
|
||||
exts.extend(self.iter().map(|e| e.extensions_for(block_hash, block_number, capabilities)));
|
||||
exts
|
||||
}
|
||||
}
|
||||
|
||||
/// An [`ExtensionsFactory`] that registers an [`Extension`] before a certain block.
|
||||
pub struct ExtensionBeforeBlock<Block: BlockT, Ext> {
|
||||
before: NumberFor<Block>,
|
||||
_marker: PhantomData<fn(Ext) -> Ext>,
|
||||
}
|
||||
|
||||
impl<Block: BlockT, Ext> ExtensionBeforeBlock<Block, Ext> {
|
||||
/// Create the extension factory.
|
||||
///
|
||||
/// - `before`: The block number until the extension should be registered.
|
||||
pub fn new(before: NumberFor<Block>) -> Self {
|
||||
Self { before, _marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT, Ext: Default + Extension> ExtensionsFactory<Block>
|
||||
for ExtensionBeforeBlock<Block, Ext>
|
||||
{
|
||||
fn extensions_for(
|
||||
&self,
|
||||
_: Block::Hash,
|
||||
block_number: NumberFor<Block>,
|
||||
_: offchain::Capabilities,
|
||||
) -> Extensions {
|
||||
let mut exts = Extensions::new();
|
||||
|
||||
if block_number < self.before {
|
||||
exts.register(Ext::default());
|
||||
}
|
||||
|
||||
exts
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a Offchain DB accessor object.
|
||||
pub trait DbExternalitiesFactory: Send + Sync {
|
||||
/// Create [`offchain::DbExternalities`] instance.
|
||||
@@ -92,7 +161,7 @@ impl<T: offchain::DbExternalities + Clone + Sync + Send + 'static> DbExternaliti
|
||||
/// This crate aggregates extensions available for the offchain calls
|
||||
/// and is responsible for producing a correct `Extensions` object.
|
||||
/// for each call, based on required `Capabilities`.
|
||||
pub struct ExecutionExtensions<Block: traits::Block> {
|
||||
pub struct ExecutionExtensions<Block: BlockT> {
|
||||
strategies: ExecutionStrategies,
|
||||
keystore: Option<SyncCryptoStorePtr>,
|
||||
offchain_db: Option<Box<dyn DbExternalitiesFactory>>,
|
||||
@@ -103,10 +172,10 @@ pub struct ExecutionExtensions<Block: traits::Block> {
|
||||
// That's also the reason why it's being registered lazily instead of
|
||||
// during initialization.
|
||||
transaction_pool: RwLock<Option<Weak<dyn OffchainSubmitTransaction<Block>>>>,
|
||||
extensions_factory: RwLock<Box<dyn ExtensionsFactory>>,
|
||||
extensions_factory: RwLock<Box<dyn ExtensionsFactory<Block>>>,
|
||||
}
|
||||
|
||||
impl<Block: traits::Block> Default for ExecutionExtensions<Block> {
|
||||
impl<Block: BlockT> Default for ExecutionExtensions<Block> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
strategies: Default::default(),
|
||||
@@ -118,7 +187,7 @@ impl<Block: traits::Block> Default for ExecutionExtensions<Block> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: traits::Block> ExecutionExtensions<Block> {
|
||||
impl<Block: BlockT> ExecutionExtensions<Block> {
|
||||
/// Create new `ExecutionExtensions` given a `keystore` and `ExecutionStrategies`.
|
||||
pub fn new(
|
||||
strategies: ExecutionStrategies,
|
||||
@@ -142,8 +211,8 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
|
||||
}
|
||||
|
||||
/// Set the new extensions_factory
|
||||
pub fn set_extensions_factory(&self, maker: Box<dyn ExtensionsFactory>) {
|
||||
*self.extensions_factory.write() = maker;
|
||||
pub fn set_extensions_factory(&self, maker: impl ExtensionsFactory<Block> + 'static) {
|
||||
*self.extensions_factory.write() = Box::new(maker);
|
||||
}
|
||||
|
||||
/// Register transaction pool extension.
|
||||
@@ -156,10 +225,18 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
|
||||
|
||||
/// Based on the execution context and capabilities it produces
|
||||
/// the extensions object to support desired set of APIs.
|
||||
pub fn extensions(&self, at: &BlockId<Block>, context: ExecutionContext) -> Extensions {
|
||||
pub fn extensions(
|
||||
&self,
|
||||
block_hash: Block::Hash,
|
||||
block_number: NumberFor<Block>,
|
||||
context: ExecutionContext,
|
||||
) -> Extensions {
|
||||
let capabilities = context.capabilities();
|
||||
|
||||
let mut extensions = self.extensions_factory.read().extensions_for(capabilities);
|
||||
let mut extensions =
|
||||
self.extensions_factory
|
||||
.read()
|
||||
.extensions_for(block_hash, block_number, capabilities);
|
||||
|
||||
if capabilities.contains(offchain::Capabilities::KEYSTORE) {
|
||||
if let Some(ref keystore) = self.keystore {
|
||||
@@ -169,10 +246,10 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
|
||||
|
||||
if capabilities.contains(offchain::Capabilities::TRANSACTION_POOL) {
|
||||
if let Some(pool) = self.transaction_pool.read().as_ref().and_then(|x| x.upgrade()) {
|
||||
extensions
|
||||
.register(TransactionPoolExt(
|
||||
Box::new(TransactionPoolAdapter { at: *at, pool }) as _,
|
||||
));
|
||||
extensions.register(TransactionPoolExt(Box::new(TransactionPoolAdapter {
|
||||
at: BlockId::Hash(block_hash),
|
||||
pool,
|
||||
}) as _));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +280,8 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
|
||||
/// the right manager and extensions object to support desired set of APIs.
|
||||
pub fn manager_and_extensions<E: std::fmt::Debug>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
block_hash: Block::Hash,
|
||||
block_number: NumberFor<Block>,
|
||||
context: ExecutionContext,
|
||||
) -> (ExecutionManager<DefaultHandler<E>>, Extensions) {
|
||||
let manager = match context {
|
||||
@@ -215,17 +293,17 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
|
||||
ExecutionContext::OffchainCall(_) => self.strategies.other.get_manager(),
|
||||
};
|
||||
|
||||
(manager, self.extensions(at, context))
|
||||
(manager, self.extensions(block_hash, block_number, context))
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper type to pass `BlockId` to the actual transaction pool.
|
||||
struct TransactionPoolAdapter<Block: traits::Block> {
|
||||
struct TransactionPoolAdapter<Block: BlockT> {
|
||||
at: BlockId<Block>,
|
||||
pool: Arc<dyn OffchainSubmitTransaction<Block>>,
|
||||
}
|
||||
|
||||
impl<Block: traits::Block> offchain::TransactionPool for TransactionPoolAdapter<Block> {
|
||||
impl<Block: BlockT> offchain::TransactionPool for TransactionPoolAdapter<Block> {
|
||||
fn submit_transaction(&mut self, data: Vec<u8>) -> Result<(), ()> {
|
||||
let xt = match Block::Extrinsic::decode(&mut &*data) {
|
||||
Ok(xt) => xt,
|
||||
|
||||
Reference in New Issue
Block a user