1#[cfg(feature = "bls-experimental")]
8use super::ecdsa_bls_crypto;
9use super::{
10 ecdsa_crypto, AuthorityIdBound, Commitment, DoubleVotingProof, ForkVotingProof,
11 FutureBlockVotingProof, Payload, ValidatorSetId, VoteMessage,
12};
13use crate::application_crypto::{AppCrypto, AppPair, RuntimeAppPublic, Wraps};
14use crate::core::{ecdsa, Pair};
15use crate::runtime::traits::{BlockNumber, Header as HeaderT};
16
17use crate::crypto_hashing::keccak_256;
18use codec::Encode;
19use std::{collections::HashMap, marker::PhantomData, sync::LazyLock};
20use strum::IntoEnumIterator;
21
22#[allow(missing_docs)]
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter)]
25pub enum Keyring<AuthorityId> {
26 Alice,
27 Bob,
28 Charlie,
29 Dave,
30 Eve,
31 Ferdie,
32 One,
33 Two,
34 _Marker(PhantomData<AuthorityId>),
35}
36
37pub trait BeefySignerAuthority: AppPair {
42 fn sign(&self, message: &[u8]) -> <Self as AppCrypto>::Signature;
44}
45
46impl BeefySignerAuthority for <ecdsa_crypto::AuthorityId as AppCrypto>::Pair {
47 fn sign(&self, message: &[u8]) -> <Self as AppCrypto>::Signature {
48 let hashed_message = keccak_256(message);
49 self.as_inner_ref().sign_prehashed(&hashed_message).into()
50 }
51}
52
53#[cfg(feature = "bls-experimental")]
54impl BeefySignerAuthority for <ecdsa_bls_crypto::AuthorityId as AppCrypto>::Pair {
55 fn sign(&self, message: &[u8]) -> <Self as AppCrypto>::Signature {
56 self.as_inner_ref().sign(&message).into()
57 }
58}
59
60impl<AuthorityId> Keyring<AuthorityId>
62where
63 AuthorityId: AuthorityIdBound + From<<<AuthorityId as AppCrypto>::Pair as AppCrypto>::Public>,
64 <AuthorityId as AppCrypto>::Pair: BeefySignerAuthority,
65 <AuthorityId as RuntimeAppPublic>::Signature:
66 Send + Sync + From<<<AuthorityId as AppCrypto>::Pair as AppCrypto>::Signature>,
67{
68 pub fn sign(&self, msg: &[u8]) -> <AuthorityId as RuntimeAppPublic>::Signature {
70 let key_pair: <AuthorityId as AppCrypto>::Pair = self.pair();
71 BeefySignerAuthority::sign(&key_pair, msg).into()
72 }
73
74 pub fn pair(&self) -> <AuthorityId as AppCrypto>::Pair {
76 <AuthorityId as AppCrypto>::Pair::from_string(self.to_seed().as_str(), None)
77 .unwrap()
78 .into()
79 }
80
81 pub fn public(&self) -> AuthorityId {
83 self.pair().public().into()
84 }
85
86 pub fn to_seed(&self) -> String {
88 format!("//{}", self)
89 }
90
91 pub fn from_public(who: &AuthorityId) -> Option<Keyring<AuthorityId>> {
93 Self::iter().find(|k| k.public() == *who)
94 }
95}
96
97static PRIVATE_KEYS: LazyLock<HashMap<Keyring<ecdsa_crypto::AuthorityId>, ecdsa_crypto::Pair>> =
98 LazyLock::new(|| Keyring::iter().map(|i| (i.clone(), i.pair())).collect());
99static PUBLIC_KEYS: LazyLock<HashMap<Keyring<ecdsa_crypto::AuthorityId>, ecdsa_crypto::Public>> =
100 LazyLock::new(|| {
101 PRIVATE_KEYS
102 .iter()
103 .map(|(name, pair)| (name.clone(), crate::application_crypto::Pair::public(pair)))
104 .collect()
105 });
106
107impl From<Keyring<ecdsa_crypto::AuthorityId>> for ecdsa_crypto::Pair {
108 fn from(k: Keyring<ecdsa_crypto::AuthorityId>) -> Self {
109 k.pair()
110 }
111}
112
113impl From<Keyring<ecdsa_crypto::AuthorityId>> for ecdsa::Pair {
114 fn from(k: Keyring<ecdsa_crypto::AuthorityId>) -> Self {
115 k.pair().into()
116 }
117}
118
119impl From<Keyring<ecdsa_crypto::AuthorityId>> for ecdsa_crypto::Public {
120 fn from(k: Keyring<ecdsa_crypto::AuthorityId>) -> Self {
121 (*PUBLIC_KEYS).get(&k).cloned().unwrap()
122 }
123}
124
125pub fn signed_vote<Number: BlockNumber>(
127 block_number: Number,
128 payload: Payload,
129 validator_set_id: ValidatorSetId,
130 keyring: &Keyring<ecdsa_crypto::AuthorityId>,
131) -> VoteMessage<Number, ecdsa_crypto::Public, ecdsa_crypto::Signature> {
132 let commitment = Commitment { validator_set_id, block_number, payload };
133 let signature = keyring.sign(&commitment.encode());
134 VoteMessage { commitment, id: keyring.public(), signature }
135}
136
137pub fn generate_double_voting_proof(
139 vote1: (u64, Payload, ValidatorSetId, &Keyring<ecdsa_crypto::AuthorityId>),
140 vote2: (u64, Payload, ValidatorSetId, &Keyring<ecdsa_crypto::AuthorityId>),
141) -> DoubleVotingProof<u64, ecdsa_crypto::Public, ecdsa_crypto::Signature> {
142 let first = signed_vote(vote1.0, vote1.1, vote1.2, vote1.3);
143 let second = signed_vote(vote2.0, vote2.1, vote2.2, vote2.3);
144 DoubleVotingProof { first, second }
145}
146
147pub fn generate_fork_voting_proof<Header: HeaderT<Number = u64>, AncestryProof>(
149 vote: (u64, Payload, ValidatorSetId, &Keyring<ecdsa_crypto::AuthorityId>),
150 ancestry_proof: AncestryProof,
151 header: Header,
152) -> ForkVotingProof<Header, ecdsa_crypto::Public, AncestryProof> {
153 let signed_vote = signed_vote(vote.0, vote.1, vote.2, vote.3);
154 ForkVotingProof { vote: signed_vote, ancestry_proof, header }
155}
156
157pub fn generate_future_block_voting_proof(
159 vote: (u64, Payload, ValidatorSetId, &Keyring<ecdsa_crypto::AuthorityId>),
160) -> FutureBlockVotingProof<u64, ecdsa_crypto::Public> {
161 let signed_vote = signed_vote(vote.0, vote.1, vote.2, vote.3);
162 FutureBlockVotingProof { vote: signed_vote }
163}