Skip to content

Commit 1408efd

Browse files
authored
Make AuRa generic over cryptography (paritytech#2062)
As is so often the case in Rust, most of the work was fixing compiler errors and removing spurious type annotations.
1 parent 964e909 commit 1408efd

File tree

7 files changed

+88
-62
lines changed

7 files changed

+88
-62
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ node/runtime/wasm/target/
1616
polkadot.*
1717
.DS_Store
1818
.idea/
19+
nohup.out
20+
rls*.log

core/consensus/aura/src/lib.rs

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
//! Blocks from future steps will be either deferred or rejected depending on how
2727
//! far in the future they are.
2828
29-
use std::{sync::Arc, time::Duration, thread};
29+
use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug};
3030

31-
use parity_codec::Encode;
31+
use parity_codec::{Encode, Decode};
3232
use consensus_common::{
3333
Authorities, BlockImport, Environment, Proposer, ForkChoiceStrategy
3434
};
@@ -41,7 +41,7 @@ use runtime_primitives::{generic, generic::BlockId, Justification};
4141
use runtime_primitives::traits::{
4242
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi
4343
};
44-
use primitives::{ed25519, Pair};
44+
use primitives::Pair;
4545
use inherents::{InherentDataProviders, InherentData, RuntimeString};
4646

4747
use futures::{Stream, Future, IntoFuture, future};
@@ -60,8 +60,8 @@ pub use aura_slots::SlotDuration;
6060
pub use aura_primitives::*;
6161
pub use consensus_common::SyncOracle;
6262

63-
type AuthorityId = ed25519::Public;
64-
type Signature = ed25519::Signature;
63+
type AuthorityId<P> = <P as Pair>::Public;
64+
type Signature<P> = <P as Pair>::Signature;
6565

6666
/// A handle to the network. This is generally implemented by providing some
6767
/// handle to a gossip service or similar.
@@ -76,7 +76,9 @@ pub trait Network: Clone {
7676
}
7777

7878
/// Get slot author for given block along with authorities.
79-
fn slot_author(slot_num: u64, authorities: &[AuthorityId]) -> Option<AuthorityId> {
79+
fn slot_author<P: Pair>(slot_num: u64, authorities: &[AuthorityId<P>]) -> Option<AuthorityId<P>>
80+
where P::Public: Clone,
81+
{
8082
if authorities.is_empty() { return None }
8183

8284
let idx = slot_num % (authorities.len() as u64);
@@ -88,7 +90,7 @@ fn slot_author(slot_num: u64, authorities: &[AuthorityId]) -> Option<AuthorityId
8890
this is a valid index; qed")
8991
.clone();
9092

91-
Some(current_author)
93+
Some(current_author.clone())
9294
}
9395

9496
fn duration_now() -> Option<Duration> {
@@ -110,25 +112,27 @@ fn inherent_to_common_error(err: RuntimeString) -> consensus_common::Error {
110112
}
111113

112114
/// A digest item which is usable with aura consensus.
113-
pub trait CompatibleDigestItem: Sized {
115+
pub trait CompatibleDigestItem<T: Pair>: Sized {
114116
/// Construct a digest item which is a slot number and a signature on the
115117
/// hash.
116-
fn aura_seal(slot_number: u64, signature: Signature) -> Self;
118+
fn aura_seal(slot_number: u64, signature: Signature<T>) -> Self;
117119

118120
/// If this item is an Aura seal, return the slot number and signature.
119-
fn as_aura_seal(&self) -> Option<(u64, Signature)>;
121+
fn as_aura_seal(&self) -> Option<(u64, Signature<T>)>;
120122
}
121123

122-
impl<Hash, AuthorityId> CompatibleDigestItem for generic::DigestItem<Hash, AuthorityId, Signature> {
124+
impl<T: Pair, Hash, AuthorityId> CompatibleDigestItem<T> for generic::DigestItem<Hash, AuthorityId, Signature<T>>
125+
where T::Signature: Clone
126+
{
123127
/// Construct a digest item which is a slot number and a signature on the
124128
/// hash.
125-
fn aura_seal(slot_number: u64, signature: Signature) -> Self {
129+
fn aura_seal(slot_number: u64, signature: Signature<T>) -> Self {
126130
generic::DigestItem::Seal(slot_number, signature)
127131
}
128132
/// If this item is an Aura seal, return the slot number and signature.
129-
fn as_aura_seal(&self) -> Option<(u64, Signature)> {
133+
fn as_aura_seal(&self) -> Option<(u64, Signature<T>)> {
130134
match self {
131-
generic::DigestItem::Seal(slot, ref sig) => Some((*slot, sig.clone().into())),
135+
generic::DigestItem::Seal(slot, ref sig) => Some((*slot, (*sig).clone())),
132136
_ => None
133137
}
134138
}
@@ -147,9 +151,9 @@ impl SlotCompatible for AuraSlotCompatible {
147151
}
148152

149153
/// Start the aura worker in a separate thread.
150-
pub fn start_aura_thread<B, C, E, I, SO, Error, OnExit>(
154+
pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>(
151155
slot_duration: SlotDuration,
152-
local_key: Arc<ed25519::Pair>,
156+
local_key: Arc<P>,
153157
client: Arc<C>,
154158
block_import: Arc<I>,
155159
env: Arc<E>,
@@ -164,9 +168,11 @@ pub fn start_aura_thread<B, C, E, I, SO, Error, OnExit>(
164168
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
165169
I: BlockImport<B> + Send + Sync + 'static,
166170
Error: From<C::Error> + From<I::Error> + 'static,
171+
P: Pair + Send + Sync + 'static,
172+
P::Public: Encode + Decode + Eq + Clone + Debug + Hash + Send + Sync + 'static,
167173
SO: SyncOracle + Send + Sync + Clone + 'static,
168174
OnExit: Future<Item=(), Error=()> + Send + 'static,
169-
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=AuthorityId> + 'static,
175+
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>> + 'static,
170176
Error: ::std::error::Error + Send + From<::consensus_common::Error> + 'static,
171177
{
172178
let worker = AuraWorker {
@@ -184,9 +190,9 @@ pub fn start_aura_thread<B, C, E, I, SO, Error, OnExit>(
184190
}
185191

186192
/// Start the aura worker. The returned future should be run in a tokio runtime.
187-
pub fn start_aura<B, C, E, I, SO, Error, OnExit>(
193+
pub fn start_aura<B, C, E, I, P, SO, Error, OnExit>(
188194
slot_duration: SlotDuration,
189-
local_key: Arc<ed25519::Pair>,
195+
local_key: Arc<P>,
190196
client: Arc<C>,
191197
block_import: Arc<I>,
192198
env: Arc<E>,
@@ -201,8 +207,10 @@ pub fn start_aura<B, C, E, I, SO, Error, OnExit>(
201207
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
202208
I: BlockImport<B> + Send + Sync + 'static,
203209
Error: From<C::Error> + From<I::Error>,
210+
P: Pair + Send + Sync + 'static,
211+
P::Public: Hash + Eq + Send + Sync + Clone + Debug + Encode + Decode + 'static,
204212
SO: SyncOracle + Send + Sync + Clone,
205-
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=AuthorityId>,
213+
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
206214
Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>,
207215
OnExit: Future<Item=(), Error=()>,
208216
{
@@ -219,24 +227,26 @@ pub fn start_aura<B, C, E, I, SO, Error, OnExit>(
219227
)
220228
}
221229

222-
struct AuraWorker<C, E, I, SO> {
230+
struct AuraWorker<C, E, I, P, SO> {
223231
client: Arc<C>,
224232
block_import: Arc<I>,
225233
env: Arc<E>,
226-
local_key: Arc<ed25519::Pair>,
234+
local_key: Arc<P>,
227235
sync_oracle: SO,
228236
inherent_data_providers: InherentDataProviders,
229237
}
230238

231-
impl<B: Block, C, E, I, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, SO> where
239+
impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
232240
C: Authorities<B>,
233241
E: Environment<B, Error=Error>,
234242
E::Proposer: Proposer<B, Error=Error>,
235243
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
236244
I: BlockImport<B> + Send + Sync + 'static,
245+
P: Pair + Send + Sync + 'static,
246+
P::Public: Hash + Eq + Send + Sync + Clone + Debug + Encode + Decode + 'static,
237247
Error: From<C::Error> + From<I::Error>,
238248
SO: SyncOracle + Send + Clone,
239-
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=AuthorityId>,
249+
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
240250
Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>,
241251
{
242252
type OnSlot = Box<Future<Item=(), Error=consensus_common::Error> + Send>;
@@ -284,10 +294,10 @@ impl<B: Block, C, E, I, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, SO> whe
284294
);
285295
return Box::new(future::ok(()));
286296
}
287-
288-
let proposal_work = match slot_author(slot_num, &authorities) {
297+
let maybe_author = slot_author::<P>(slot_num, &authorities);
298+
let proposal_work = match maybe_author {
289299
None => return Box::new(future::ok(())),
290-
Some(author) => if author.0 == public_key.0 {
300+
Some(author) => if author == public_key {
291301
debug!(
292302
target: "aura", "Starting authorship at slot {}; timestamp = {}",
293303
slot_num,
@@ -347,7 +357,7 @@ impl<B: Block, C, E, I, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, SO> whe
347357
// add it to a digest item.
348358
let to_sign = (slot_num, pre_hash).encode();
349359
let signature = pair.sign(&to_sign[..]);
350-
let item = <DigestItemFor<B> as CompatibleDigestItem>::aura_seal(
360+
let item = <DigestItemFor<B> as CompatibleDigestItem<P>>::aura_seal(
351361
slot_num,
352362
signature,
353363
);
@@ -391,9 +401,10 @@ impl<B: Block, C, E, I, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, SO> whe
391401
/// if it's successful, returns the pre-header, the slot number, and the signat.
392402
//
393403
// FIXME #1018 needs misbehavior types
394-
fn check_header<B: Block>(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[AuthorityId])
395-
-> Result<CheckedHeader<B::Header, ed25519::Signature>, String>
396-
where DigestItemFor<B>: CompatibleDigestItem
404+
fn check_header<B: Block, P: Pair>(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[AuthorityId<P>])
405+
-> Result<CheckedHeader<B::Header, P::Signature>, String>
406+
where DigestItemFor<B>: CompatibleDigestItem<P>,
407+
P::Public: Clone + AsRef<P::Public>,
397408
{
398409
let digest_item = match header.digest_mut().pop() {
399410
Some(x) => x,
@@ -411,16 +422,16 @@ fn check_header<B: Block>(slot_now: u64, mut header: B::Header, hash: B::Hash, a
411422
// check the signature is valid under the expected authority and
412423
// chain state.
413424

414-
let expected_author = match slot_author(slot_num, &authorities) {
425+
let expected_author = match slot_author::<P>(slot_num, &authorities) {
415426
None => return Err("Slot Author not found".to_string()),
416427
Some(author) => author
417428
};
418429

419430
let pre_hash = header.hash();
420431
let to_sign = (slot_num, pre_hash).encode();
421-
let public = ed25519::Public(expected_author.0);
432+
let public = expected_author;
422433

423-
if ed25519::Pair::verify(&sig, &to_sign[..], public) {
434+
if P::verify(&sig, &to_sign[..], public) {
424435
Ok(CheckedHeader::Checked(header, slot_num, sig))
425436
} else {
426437
Err(format!("Bad signature on {:?}", hash))
@@ -442,13 +453,15 @@ pub trait ExtraVerification<B: Block>: Send + Sync {
442453
}
443454

444455
/// A verifier for Aura blocks.
445-
pub struct AuraVerifier<C, E> {
456+
pub struct AuraVerifier<C, E, P> {
446457
client: Arc<C>,
447458
extra: E,
459+
phantom: PhantomData<P>,
448460
inherent_data_providers: inherents::InherentDataProviders,
449461
}
450462

451-
impl<C, E> AuraVerifier<C, E>
463+
impl<C, E, P> AuraVerifier<C, E, P>
464+
where P: Send + Sync + 'static
452465
{
453466
fn check_inherents<B: Block>(
454467
&self,
@@ -511,19 +524,21 @@ impl<B: Block> ExtraVerification<B> for NothingExtra {
511524
}
512525
}
513526

514-
impl<B: Block, C, E> Verifier<B> for AuraVerifier<C, E> where
527+
impl<B: Block, C, E, P> Verifier<B> for AuraVerifier<C, E, P> where
515528
C: Authorities<B> + ProvideRuntimeApi + Send + Sync,
516529
C::Api: BlockBuilderApi<B>,
517-
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=AuthorityId>,
530+
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
518531
E: ExtraVerification<B>,
532+
P: Pair + Send + Sync + 'static,
533+
P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + AsRef<P::Public> + 'static,
519534
{
520535
fn verify(
521536
&self,
522537
origin: BlockOrigin,
523538
header: B::Header,
524539
justification: Option<Justification>,
525540
mut body: Option<Vec<B::Extrinsic>>,
526-
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityId>>), String> {
541+
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityId<P>>>), String> {
527542
let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?;
528543
let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data)
529544
.map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?;
@@ -539,7 +554,7 @@ impl<B: Block, C, E> Verifier<B> for AuraVerifier<C, E> where
539554

540555
// we add one to allow for some small drift.
541556
// FIXME #1019 in the future, alter this queue to allow deferring of headers
542-
let checked_header = check_header::<B>(slot_now + 1, header, hash, &authorities[..])?;
557+
let checked_header = check_header::<B, P>(slot_now + 1, header, hash, &authorities[..])?;
543558
match checked_header {
544559
CheckedHeader::Checked(pre_header, slot_num, sig) => {
545560
let item = <DigestItemFor<B>>::aura_seal(slot_num, sig);
@@ -617,7 +632,7 @@ fn register_aura_inherent_data_provider(
617632
}
618633

619634
/// Start an import queue for the Aura consensus algorithm.
620-
pub fn import_queue<B, C, E>(
635+
pub fn import_queue<B, C, E, P>(
621636
slot_duration: SlotDuration,
622637
block_import: SharedBlockImport<B>,
623638
justification_import: Option<SharedJustificationImport<B>>,
@@ -628,13 +643,20 @@ pub fn import_queue<B, C, E>(
628643
B: Block,
629644
C: 'static + Authorities<B> + ProvideRuntimeApi + Send + Sync,
630645
C::Api: BlockBuilderApi<B>,
631-
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=AuthorityId>,
646+
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
632647
E: 'static + ExtraVerification<B>,
648+
P: Pair + Send + Sync + 'static,
649+
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef<P::Public>,
633650
{
634651
register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?;
635652

636653
let verifier = Arc::new(
637-
AuraVerifier { client: client.clone(), extra, inherent_data_providers }
654+
AuraVerifier {
655+
client: client.clone(),
656+
extra,
657+
inherent_data_providers,
658+
phantom: PhantomData,
659+
}
638660
);
639661
Ok(BasicQueue::new(verifier, block_import, justification_import))
640662
}
@@ -650,6 +672,7 @@ mod tests {
650672
use parking_lot::Mutex;
651673
use tokio::runtime::current_thread;
652674
use keyring::ed25519::Keyring;
675+
use primitives::ed25519;
653676
use client::BlockchainEvents;
654677
use test_client;
655678

@@ -664,7 +687,7 @@ mod tests {
664687
type Proposer = DummyProposer;
665688
type Error = Error;
666689

667-
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId])
690+
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId<ed25519::Pair>])
668691
-> Result<DummyProposer, Error>
669692
{
670693
Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
@@ -690,7 +713,7 @@ mod tests {
690713

691714
impl TestNetFactory for AuraTestNet {
692715
type Specialization = DummySpecialization;
693-
type Verifier = AuraVerifier<PeersClient, NothingExtra>;
716+
type Verifier = AuraVerifier<PeersClient, NothingExtra, ed25519::Pair>;
694717
type PeerData = ();
695718

696719
/// Create new test network with peers and given config.
@@ -717,6 +740,7 @@ mod tests {
717740
client,
718741
extra: NothingExtra,
719742
inherent_data_providers,
743+
phantom: Default::default(),
720744
})
721745
}
722746

@@ -775,7 +799,7 @@ mod tests {
775799
&inherent_data_providers, slot_duration.get()
776800
).expect("Registers aura inherent data provider");
777801

778-
let aura = start_aura(
802+
let aura = start_aura::<_, _, _, _, ed25519::Pair, _, _, _>(
779803
slot_duration,
780804
Arc::new(key.clone().into()),
781805
client.clone(),

core/primitives/src/sr25519.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ impl Pair {
501501
#[cfg(test)]
502502
mod test {
503503
use super::*;
504-
use crate::{Pair as PairT, crypto::{Ss58Codec, DEV_PHRASE, DEV_ADDRESS}};
504+
use crate::crypto::{Ss58Codec, DEV_PHRASE, DEV_ADDRESS};
505505
use hex_literal::{hex, hex_impl};
506506

507507
#[test]

node-template/src/service.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ construct_service_factory! {
8585
Self::Block,
8686
>
8787
{ |config: &mut FactoryFullConfiguration<Self> , client: Arc<FullClient<Self>>|
88-
import_queue(
88+
import_queue::<_, _, _, Pair>(
8989
SlotDuration::get_or_compute(&*client)?,
9090
client.clone(),
9191
None,
@@ -98,7 +98,7 @@ construct_service_factory! {
9898
Self::Block,
9999
>
100100
{ |config: &mut FactoryFullConfiguration<Self>, client: Arc<LightClient<Self>>|
101-
import_queue(
101+
import_queue::<_, _, _, Pair>(
102102
SlotDuration::get_or_compute(&*client)?,
103103
client.clone(),
104104
None,

0 commit comments

Comments
 (0)