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:
Bastian Köcher
2022-11-27 16:34:07 +01:00
committed by GitHub
parent 0068716b5a
commit 0c934a9352
18 changed files with 325 additions and 100 deletions
@@ -20,7 +20,8 @@ use futures::executor::block_on;
use parity_scale_codec::{Decode, Encode, Joiner};
use sc_block_builder::BlockBuilderProvider;
use sc_client_api::{
in_mem, BlockBackend, BlockchainEvents, FinalityNotifications, HeaderBackend, StorageProvider,
in_mem, BlockBackend, BlockchainEvents, ExecutorProvider, FinalityNotifications, HeaderBackend,
StorageProvider,
};
use sc_client_db::{Backend, BlocksPruning, DatabaseSettings, DatabaseSource, PruningMode};
use sc_consensus::{
@@ -1875,3 +1876,40 @@ fn reorg_triggers_a_notification_even_for_sources_that_should_not_trigger_notifi
let tree_route = notification.tree_route.unwrap();
assert_eq!(tree_route.enacted()[0].hash, b1.hash());
}
#[test]
fn use_dalek_ext_works() {
fn zero_ed_pub() -> sp_core::ed25519::Public {
sp_core::ed25519::Public([0u8; 32])
}
fn zero_ed_sig() -> sp_core::ed25519::Signature {
sp_core::ed25519::Signature::from_raw([0u8; 64])
}
let mut client = TestClientBuilder::new().build();
client.execution_extensions().set_extensions_factory(
sc_client_api::execution_extensions::ExtensionBeforeBlock::<Block, sp_io::UseDalekExt>::new(
1,
),
);
let a1 = client
.new_block_at(&BlockId::Number(0), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::NetworkInitialSync, a1.clone())).unwrap();
// On block zero it will use dalek and then on block 1 it will use zebra
assert!(!client
.runtime_api()
.verify_ed25519(&BlockId::Number(0), zero_ed_sig(), zero_ed_pub(), vec![])
.unwrap());
assert!(client
.runtime_api()
.verify_ed25519(&BlockId::Number(1), zero_ed_sig(), zero_ed_pub(), vec![])
.unwrap());
}