mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 22:41:06 +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:
@@ -311,6 +311,7 @@ where
|
||||
executor,
|
||||
spawn_handle,
|
||||
config.clone(),
|
||||
execution_extensions,
|
||||
)?;
|
||||
crate::client::Client::new(
|
||||
backend,
|
||||
@@ -318,7 +319,6 @@ where
|
||||
genesis_storage,
|
||||
fork_blocks,
|
||||
bad_blocks,
|
||||
execution_extensions,
|
||||
prometheus_registry,
|
||||
telemetry,
|
||||
config,
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{client::ClientConfig, wasm_override::WasmOverride, wasm_substitutes::WasmSubstitutes};
|
||||
use sc_client_api::{backend, call_executor::CallExecutor, HeaderBackend};
|
||||
use sc_client_api::{
|
||||
backend, call_executor::CallExecutor, execution_extensions::ExecutionExtensions, HeaderBackend,
|
||||
};
|
||||
use sc_executor::{RuntimeVersion, RuntimeVersionOf};
|
||||
use sp_api::{ProofRecorder, StorageTransactionCache};
|
||||
use sp_api::{ExecutionContext, ProofRecorder, StorageTransactionCache};
|
||||
use sp_core::traits::{CodeExecutor, RuntimeCode, SpawnNamed};
|
||||
use sp_externalities::Extensions;
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
||||
use sp_state_machine::{
|
||||
backend::AsTrieBackend, ExecutionManager, ExecutionStrategy, Ext, OverlayedChanges,
|
||||
StateMachine, StorageProof,
|
||||
backend::AsTrieBackend, ExecutionStrategy, Ext, OverlayedChanges, StateMachine, StorageProof,
|
||||
};
|
||||
use std::{cell::RefCell, sync::Arc};
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct LocalCallExecutor<Block: BlockT, B, E> {
|
||||
wasm_substitutes: WasmSubstitutes<Block, E, B>,
|
||||
spawn_handle: Box<dyn SpawnNamed>,
|
||||
client_config: ClientConfig<Block>,
|
||||
execution_extensions: Arc<ExecutionExtensions<Block>>,
|
||||
}
|
||||
|
||||
impl<Block: BlockT, B, E> LocalCallExecutor<Block, B, E>
|
||||
@@ -51,6 +52,7 @@ where
|
||||
executor: E,
|
||||
spawn_handle: Box<dyn SpawnNamed>,
|
||||
client_config: ClientConfig<Block>,
|
||||
execution_extensions: ExecutionExtensions<Block>,
|
||||
) -> sp_blockchain::Result<Self> {
|
||||
let wasm_override = client_config
|
||||
.wasm_runtime_overrides
|
||||
@@ -71,6 +73,7 @@ where
|
||||
spawn_handle,
|
||||
client_config,
|
||||
wasm_substitutes,
|
||||
execution_extensions: Arc::new(execution_extensions),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -124,6 +127,7 @@ where
|
||||
spawn_handle: self.spawn_handle.clone(),
|
||||
client_config: self.client_config.clone(),
|
||||
wasm_substitutes: self.wasm_substitutes.clone(),
|
||||
execution_extensions: self.execution_extensions.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,30 +142,41 @@ where
|
||||
|
||||
type Backend = B;
|
||||
|
||||
fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
|
||||
&self.execution_extensions
|
||||
}
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
method: &str,
|
||||
call_data: &[u8],
|
||||
strategy: ExecutionStrategy,
|
||||
extensions: Option<Extensions>,
|
||||
) -> sp_blockchain::Result<Vec<u8>> {
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let at_hash = self.backend.blockchain().expect_block_hash_from_id(at)?;
|
||||
let at_number = self.backend.blockchain().expect_block_number_from_id(at)?;
|
||||
let state = self.backend.state_at(at_hash)?;
|
||||
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
|
||||
let runtime_code = self.check_override(runtime_code, at)?;
|
||||
|
||||
let extensions = self.execution_extensions.extensions(
|
||||
at_hash,
|
||||
at_number,
|
||||
ExecutionContext::OffchainCall(None),
|
||||
);
|
||||
|
||||
let mut sm = StateMachine::new(
|
||||
&state,
|
||||
&mut changes,
|
||||
&self.executor,
|
||||
method,
|
||||
call_data,
|
||||
extensions.unwrap_or_default(),
|
||||
extensions,
|
||||
&runtime_code,
|
||||
self.spawn_handle.clone(),
|
||||
)
|
||||
@@ -171,30 +186,25 @@ where
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn contextual_call<
|
||||
EM: Fn(
|
||||
Result<Vec<u8>, Self::Error>,
|
||||
Result<Vec<u8>, Self::Error>,
|
||||
) -> Result<Vec<u8>, Self::Error>,
|
||||
>(
|
||||
fn contextual_call(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
method: &str,
|
||||
call_data: &[u8],
|
||||
changes: &RefCell<OverlayedChanges>,
|
||||
storage_transaction_cache: Option<&RefCell<StorageTransactionCache<Block, B::State>>>,
|
||||
execution_manager: ExecutionManager<EM>,
|
||||
recorder: &Option<ProofRecorder<Block>>,
|
||||
extensions: Option<Extensions>,
|
||||
) -> Result<Vec<u8>, sp_blockchain::Error>
|
||||
where
|
||||
ExecutionManager<EM>: Clone,
|
||||
{
|
||||
context: ExecutionContext,
|
||||
) -> Result<Vec<u8>, sp_blockchain::Error> {
|
||||
let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut());
|
||||
|
||||
let at_hash = self.backend.blockchain().expect_block_hash_from_id(at)?;
|
||||
let at_number = self.backend.blockchain().expect_block_number_from_id(at)?;
|
||||
let state = self.backend.state_at(at_hash)?;
|
||||
|
||||
let (execution_manager, extensions) =
|
||||
self.execution_extensions.manager_and_extensions(at_hash, at_number, context);
|
||||
|
||||
let changes = &mut *changes.borrow_mut();
|
||||
|
||||
// It is important to extract the runtime code here before we create the proof
|
||||
@@ -220,7 +230,7 @@ where
|
||||
&self.executor,
|
||||
method,
|
||||
call_data,
|
||||
extensions.unwrap_or_default(),
|
||||
extensions,
|
||||
&runtime_code,
|
||||
self.spawn_handle.clone(),
|
||||
)
|
||||
@@ -235,7 +245,7 @@ where
|
||||
&self.executor,
|
||||
method,
|
||||
call_data,
|
||||
extensions.unwrap_or_default(),
|
||||
extensions,
|
||||
&runtime_code,
|
||||
self.spawn_handle.clone(),
|
||||
)
|
||||
@@ -269,6 +279,7 @@ where
|
||||
call_data: &[u8],
|
||||
) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
|
||||
let at_hash = self.backend.blockchain().expect_block_hash_from_id(at)?;
|
||||
let at_number = self.backend.blockchain().expect_block_number_from_id(at)?;
|
||||
let state = self.backend.state_at(at_hash)?;
|
||||
|
||||
let trie_backend = state.as_trie_backend();
|
||||
@@ -286,6 +297,11 @@ where
|
||||
method,
|
||||
call_data,
|
||||
&runtime_code,
|
||||
self.execution_extensions.extensions(
|
||||
at_hash,
|
||||
at_number,
|
||||
ExecutionContext::OffchainCall(None),
|
||||
),
|
||||
)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
@@ -392,6 +408,11 @@ mod tests {
|
||||
backend.clone(),
|
||||
)
|
||||
.unwrap(),
|
||||
execution_extensions: Arc::new(ExecutionExtensions::new(
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
)),
|
||||
};
|
||||
|
||||
let check = call_executor
|
||||
|
||||
@@ -67,7 +67,8 @@ use sp_keystore::SyncCryptoStorePtr;
|
||||
use sp_runtime::{
|
||||
generic::{BlockId, SignedBlock},
|
||||
traits::{
|
||||
Block as BlockT, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero,
|
||||
Block as BlockT, BlockIdTo, HashFor, Header as HeaderT, NumberFor, One,
|
||||
SaturatedConversion, Zero,
|
||||
},
|
||||
BuildStorage, Digest, Justification, Justifications, StateVersion,
|
||||
};
|
||||
@@ -113,7 +114,6 @@ where
|
||||
// Holds the block hash currently being imported. TODO: replace this with block queue.
|
||||
importing_block: RwLock<Option<Block::Hash>>,
|
||||
block_rules: BlockRules<Block>,
|
||||
execution_extensions: ExecutionExtensions<Block>,
|
||||
config: ClientConfig<Block>,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
_phantom: PhantomData<RA>,
|
||||
@@ -230,20 +230,26 @@ where
|
||||
Block: BlockT,
|
||||
B: backend::LocalBackend<Block> + 'static,
|
||||
{
|
||||
let call_executor =
|
||||
LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone())?;
|
||||
let extensions = ExecutionExtensions::new(
|
||||
Default::default(),
|
||||
keystore,
|
||||
sc_offchain::OffchainDb::factory_from_backend(&*backend),
|
||||
);
|
||||
|
||||
let call_executor = LocalCallExecutor::new(
|
||||
backend.clone(),
|
||||
executor,
|
||||
spawn_handle,
|
||||
config.clone(),
|
||||
extensions,
|
||||
)?;
|
||||
|
||||
Client::new(
|
||||
backend,
|
||||
call_executor,
|
||||
build_genesis_storage,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
extensions,
|
||||
prometheus_registry,
|
||||
telemetry,
|
||||
config,
|
||||
@@ -347,7 +353,6 @@ where
|
||||
build_genesis_storage: &dyn BuildStorage,
|
||||
fork_blocks: ForkBlocks<Block>,
|
||||
bad_blocks: BadBlocks<Block>,
|
||||
execution_extensions: ExecutionExtensions<Block>,
|
||||
prometheus_registry: Option<Registry>,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
config: ClientConfig<Block>,
|
||||
@@ -394,7 +399,6 @@ where
|
||||
finality_actions: Default::default(),
|
||||
importing_block: Default::default(),
|
||||
block_rules: BlockRules::new(fork_blocks, bad_blocks),
|
||||
execution_extensions,
|
||||
config,
|
||||
telemetry,
|
||||
_phantom: Default::default(),
|
||||
@@ -1386,7 +1390,7 @@ where
|
||||
}
|
||||
|
||||
fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
|
||||
&self.execution_extensions
|
||||
self.executor.execution_extensions()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1580,7 +1584,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E, Block, RA> sp_runtime::traits::BlockIdTo<Block> for Client<B, E, Block, RA>
|
||||
impl<B, E, Block, RA> BlockIdTo<Block> for Client<B, E, Block, RA>
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block> + Send + Sync,
|
||||
@@ -1637,7 +1641,7 @@ where
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block, Backend = B> + Send + Sync,
|
||||
Block: BlockT,
|
||||
RA: ConstructRuntimeApi<Block, Self>,
|
||||
RA: ConstructRuntimeApi<Block, Self> + Send + Sync,
|
||||
{
|
||||
type Api = <RA as ConstructRuntimeApi<Block, Self>>::RuntimeApi;
|
||||
|
||||
@@ -1651,6 +1655,7 @@ where
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block, Backend = B> + Send + Sync,
|
||||
Block: BlockT,
|
||||
RA: Send + Sync,
|
||||
{
|
||||
type StateBackend = B::State;
|
||||
|
||||
@@ -1658,21 +1663,15 @@ where
|
||||
&self,
|
||||
params: CallApiAtParams<Block, B::State>,
|
||||
) -> Result<Vec<u8>, sp_api::ApiError> {
|
||||
let at = params.at;
|
||||
|
||||
let (manager, extensions) =
|
||||
self.execution_extensions.manager_and_extensions(at, params.context);
|
||||
|
||||
self.executor
|
||||
.contextual_call(
|
||||
at,
|
||||
params.at,
|
||||
params.function,
|
||||
¶ms.arguments,
|
||||
params.overlayed_changes,
|
||||
Some(params.storage_transaction_cache),
|
||||
manager,
|
||||
params.recorder,
|
||||
Some(extensions),
|
||||
params.context,
|
||||
)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user