Skip to content

Commit 586f098

Browse files
bkchrandresilva
authored andcommitted
ed25519_verify: Support using dalek for historical blocks (paritytech#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 <[email protected]> * Fix merge and warning * Fix docs Co-authored-by: André Silva <[email protected]>
1 parent d0d67de commit 586f098

File tree

18 files changed

+325
-100
lines changed

18 files changed

+325
-100
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/api/src/call_executor.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@
1919
//! A method call executor interface.
2020
2121
use sc_executor::{RuntimeVersion, RuntimeVersionOf};
22-
use sp_externalities::Extensions;
2322
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
24-
use sp_state_machine::{ExecutionManager, ExecutionStrategy, OverlayedChanges, StorageProof};
23+
use sp_state_machine::{ExecutionStrategy, OverlayedChanges, StorageProof};
2524
use std::cell::RefCell;
2625

2726
use crate::execution_extensions::ExecutionExtensions;
28-
use sp_api::{ProofRecorder, StorageTransactionCache};
27+
use sp_api::{ExecutionContext, ProofRecorder, StorageTransactionCache};
2928

3029
/// Executor Provider
3130
pub trait ExecutorProvider<Block: BlockT> {
@@ -47,6 +46,9 @@ pub trait CallExecutor<B: BlockT>: RuntimeVersionOf {
4746
/// The backend used by the node.
4847
type Backend: crate::backend::Backend<B>;
4948

49+
/// Returns the [`ExecutionExtensions`].
50+
fn execution_extensions(&self) -> &ExecutionExtensions<B>;
51+
5052
/// Execute a call to a contract on top of state in a block of given hash.
5153
///
5254
/// No changes are made.
@@ -56,20 +58,14 @@ pub trait CallExecutor<B: BlockT>: RuntimeVersionOf {
5658
method: &str,
5759
call_data: &[u8],
5860
strategy: ExecutionStrategy,
59-
extensions: Option<Extensions>,
6061
) -> Result<Vec<u8>, sp_blockchain::Error>;
6162

6263
/// Execute a contextual call on top of state in a block of a given hash.
6364
///
6465
/// No changes are made.
6566
/// Before executing the method, passed header is installed as the current header
6667
/// of the execution context.
67-
fn contextual_call<
68-
EM: Fn(
69-
Result<Vec<u8>, Self::Error>,
70-
Result<Vec<u8>, Self::Error>,
71-
) -> Result<Vec<u8>, Self::Error>,
72-
>(
68+
fn contextual_call(
7369
&self,
7470
at: &BlockId<B>,
7571
method: &str,
@@ -80,12 +76,9 @@ pub trait CallExecutor<B: BlockT>: RuntimeVersionOf {
8076
StorageTransactionCache<B, <Self::Backend as crate::backend::Backend<B>>::State>,
8177
>,
8278
>,
83-
execution_manager: ExecutionManager<EM>,
8479
proof_recorder: &Option<ProofRecorder<B>>,
85-
extensions: Option<Extensions>,
86-
) -> sp_blockchain::Result<Vec<u8>>
87-
where
88-
ExecutionManager<EM>: Clone;
80+
context: ExecutionContext,
81+
) -> sp_blockchain::Result<Vec<u8>>;
8982

9083
/// Extract RuntimeVersion of given block
9184
///

client/api/src/execution_extensions.rs

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ use sp_core::{
2929
offchain::{self, OffchainDbExt, OffchainWorkerExt, TransactionPoolExt},
3030
ExecutionContext,
3131
};
32-
use sp_externalities::Extensions;
32+
use sp_externalities::{Extension, Extensions};
3333
use sp_keystore::{KeystoreExt, SyncCryptoStorePtr};
34-
use sp_runtime::{generic::BlockId, traits};
34+
use sp_runtime::{
35+
generic::BlockId,
36+
traits::{Block as BlockT, NumberFor},
37+
};
3538
pub use sp_state_machine::ExecutionStrategy;
3639
use sp_state_machine::{DefaultHandler, ExecutionManager};
37-
use std::sync::{Arc, Weak};
40+
use std::{
41+
marker::PhantomData,
42+
sync::{Arc, Weak},
43+
};
3844

3945
/// Execution strategies settings.
4046
#[derive(Debug, Clone)]
@@ -63,18 +69,81 @@ impl Default for ExecutionStrategies {
6369
}
6470
}
6571

66-
/// Generate the starting set of ExternalitiesExtensions based upon the given capabilities
67-
pub trait ExtensionsFactory: Send + Sync {
68-
/// Make `Extensions` for given `Capabilities`.
69-
fn extensions_for(&self, capabilities: offchain::Capabilities) -> Extensions;
72+
/// Generate the starting set of [`Extensions`].
73+
///
74+
/// These [`Extensions`] are passed to the environment a runtime is executed in.
75+
pub trait ExtensionsFactory<Block: BlockT>: Send + Sync {
76+
/// Create [`Extensions`] for the given input.
77+
///
78+
/// - `block_hash`: The hash of the block in the context that extensions will be used.
79+
/// - `block_number`: The number of the block in the context that extensions will be used.
80+
/// - `capabilities`: The capabilities
81+
fn extensions_for(
82+
&self,
83+
block_hash: Block::Hash,
84+
block_number: NumberFor<Block>,
85+
capabilities: offchain::Capabilities,
86+
) -> Extensions;
7087
}
7188

72-
impl ExtensionsFactory for () {
73-
fn extensions_for(&self, _capabilities: offchain::Capabilities) -> Extensions {
89+
impl<Block: BlockT> ExtensionsFactory<Block> for () {
90+
fn extensions_for(
91+
&self,
92+
_: Block::Hash,
93+
_: NumberFor<Block>,
94+
_capabilities: offchain::Capabilities,
95+
) -> Extensions {
7496
Extensions::new()
7597
}
7698
}
7799

100+
impl<Block: BlockT, T: ExtensionsFactory<Block>> ExtensionsFactory<Block> for Vec<T> {
101+
fn extensions_for(
102+
&self,
103+
block_hash: Block::Hash,
104+
block_number: NumberFor<Block>,
105+
capabilities: offchain::Capabilities,
106+
) -> Extensions {
107+
let mut exts = Extensions::new();
108+
exts.extend(self.iter().map(|e| e.extensions_for(block_hash, block_number, capabilities)));
109+
exts
110+
}
111+
}
112+
113+
/// An [`ExtensionsFactory`] that registers an [`Extension`] before a certain block.
114+
pub struct ExtensionBeforeBlock<Block: BlockT, Ext> {
115+
before: NumberFor<Block>,
116+
_marker: PhantomData<fn(Ext) -> Ext>,
117+
}
118+
119+
impl<Block: BlockT, Ext> ExtensionBeforeBlock<Block, Ext> {
120+
/// Create the extension factory.
121+
///
122+
/// - `before`: The block number until the extension should be registered.
123+
pub fn new(before: NumberFor<Block>) -> Self {
124+
Self { before, _marker: PhantomData }
125+
}
126+
}
127+
128+
impl<Block: BlockT, Ext: Default + Extension> ExtensionsFactory<Block>
129+
for ExtensionBeforeBlock<Block, Ext>
130+
{
131+
fn extensions_for(
132+
&self,
133+
_: Block::Hash,
134+
block_number: NumberFor<Block>,
135+
_: offchain::Capabilities,
136+
) -> Extensions {
137+
let mut exts = Extensions::new();
138+
139+
if block_number < self.before {
140+
exts.register(Ext::default());
141+
}
142+
143+
exts
144+
}
145+
}
146+
78147
/// Create a Offchain DB accessor object.
79148
pub trait DbExternalitiesFactory: Send + Sync {
80149
/// Create [`offchain::DbExternalities`] instance.
@@ -92,7 +161,7 @@ impl<T: offchain::DbExternalities + Clone + Sync + Send + 'static> DbExternaliti
92161
/// This crate aggregates extensions available for the offchain calls
93162
/// and is responsible for producing a correct `Extensions` object.
94163
/// for each call, based on required `Capabilities`.
95-
pub struct ExecutionExtensions<Block: traits::Block> {
164+
pub struct ExecutionExtensions<Block: BlockT> {
96165
strategies: ExecutionStrategies,
97166
keystore: Option<SyncCryptoStorePtr>,
98167
offchain_db: Option<Box<dyn DbExternalitiesFactory>>,
@@ -103,10 +172,10 @@ pub struct ExecutionExtensions<Block: traits::Block> {
103172
// That's also the reason why it's being registered lazily instead of
104173
// during initialization.
105174
transaction_pool: RwLock<Option<Weak<dyn OffchainSubmitTransaction<Block>>>>,
106-
extensions_factory: RwLock<Box<dyn ExtensionsFactory>>,
175+
extensions_factory: RwLock<Box<dyn ExtensionsFactory<Block>>>,
107176
}
108177

109-
impl<Block: traits::Block> Default for ExecutionExtensions<Block> {
178+
impl<Block: BlockT> Default for ExecutionExtensions<Block> {
110179
fn default() -> Self {
111180
Self {
112181
strategies: Default::default(),
@@ -118,7 +187,7 @@ impl<Block: traits::Block> Default for ExecutionExtensions<Block> {
118187
}
119188
}
120189

121-
impl<Block: traits::Block> ExecutionExtensions<Block> {
190+
impl<Block: BlockT> ExecutionExtensions<Block> {
122191
/// Create new `ExecutionExtensions` given a `keystore` and `ExecutionStrategies`.
123192
pub fn new(
124193
strategies: ExecutionStrategies,
@@ -142,8 +211,8 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
142211
}
143212

144213
/// Set the new extensions_factory
145-
pub fn set_extensions_factory(&self, maker: Box<dyn ExtensionsFactory>) {
146-
*self.extensions_factory.write() = maker;
214+
pub fn set_extensions_factory(&self, maker: impl ExtensionsFactory<Block> + 'static) {
215+
*self.extensions_factory.write() = Box::new(maker);
147216
}
148217

149218
/// Register transaction pool extension.
@@ -156,10 +225,18 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
156225

157226
/// Based on the execution context and capabilities it produces
158227
/// the extensions object to support desired set of APIs.
159-
pub fn extensions(&self, at: &BlockId<Block>, context: ExecutionContext) -> Extensions {
228+
pub fn extensions(
229+
&self,
230+
block_hash: Block::Hash,
231+
block_number: NumberFor<Block>,
232+
context: ExecutionContext,
233+
) -> Extensions {
160234
let capabilities = context.capabilities();
161235

162-
let mut extensions = self.extensions_factory.read().extensions_for(capabilities);
236+
let mut extensions =
237+
self.extensions_factory
238+
.read()
239+
.extensions_for(block_hash, block_number, capabilities);
163240

164241
if capabilities.contains(offchain::Capabilities::KEYSTORE) {
165242
if let Some(ref keystore) = self.keystore {
@@ -169,10 +246,10 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
169246

170247
if capabilities.contains(offchain::Capabilities::TRANSACTION_POOL) {
171248
if let Some(pool) = self.transaction_pool.read().as_ref().and_then(|x| x.upgrade()) {
172-
extensions
173-
.register(TransactionPoolExt(
174-
Box::new(TransactionPoolAdapter { at: *at, pool }) as _,
175-
));
249+
extensions.register(TransactionPoolExt(Box::new(TransactionPoolAdapter {
250+
at: BlockId::Hash(block_hash),
251+
pool,
252+
}) as _));
176253
}
177254
}
178255

@@ -203,7 +280,8 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
203280
/// the right manager and extensions object to support desired set of APIs.
204281
pub fn manager_and_extensions<E: std::fmt::Debug>(
205282
&self,
206-
at: &BlockId<Block>,
283+
block_hash: Block::Hash,
284+
block_number: NumberFor<Block>,
207285
context: ExecutionContext,
208286
) -> (ExecutionManager<DefaultHandler<E>>, Extensions) {
209287
let manager = match context {
@@ -215,17 +293,17 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
215293
ExecutionContext::OffchainCall(_) => self.strategies.other.get_manager(),
216294
};
217295

218-
(manager, self.extensions(at, context))
296+
(manager, self.extensions(block_hash, block_number, context))
219297
}
220298
}
221299

222300
/// A wrapper type to pass `BlockId` to the actual transaction pool.
223-
struct TransactionPoolAdapter<Block: traits::Block> {
301+
struct TransactionPoolAdapter<Block: BlockT> {
224302
at: BlockId<Block>,
225303
pool: Arc<dyn OffchainSubmitTransaction<Block>>,
226304
}
227305

228-
impl<Block: traits::Block> offchain::TransactionPool for TransactionPoolAdapter<Block> {
306+
impl<Block: BlockT> offchain::TransactionPool for TransactionPoolAdapter<Block> {
229307
fn submit_transaction(&mut self, data: Vec<u8>) -> Result<(), ()> {
230308
let xt = match Block::Extrinsic::decode(&mut &*data) {
231309
Ok(xt) => xt,

client/finality-grandpa/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,6 @@ where
477477
"GrandpaApi_grandpa_authorities",
478478
&[],
479479
ExecutionStrategy::NativeElseWasm,
480-
None,
481480
)
482481
.and_then(|call_result| {
483482
Decode::decode(&mut &call_result[..]).map_err(|err| {

client/rpc/src/state/state_full.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ where
200200
&method,
201201
&call_data,
202202
self.client.execution_extensions().strategies().other,
203-
None,
204203
)
205204
.map(Into::into)
206205
})

client/service/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,14 @@ where
311311
executor,
312312
spawn_handle,
313313
config.clone(),
314+
execution_extensions,
314315
)?;
315316
crate::client::Client::new(
316317
backend,
317318
executor,
318319
genesis_storage,
319320
fork_blocks,
320321
bad_blocks,
321-
execution_extensions,
322322
prometheus_registry,
323323
telemetry,
324324
config,

0 commit comments

Comments
 (0)