diem_types/
validator_signer.rs1use crate::{
9 account_address::AccountAddress,
10 validator_config::{
11 ConsensusPrivateKey, ConsensusPublicKey, ConsensusSignature,
12 ConsensusVRFPrivateKey, ConsensusVRFPublicKey,
13 },
14};
15use diem_crypto::{
16 hash::CryptoHash, test_utils::TEST_SEED, PrivateKey, SigningKey, Uniform,
17};
18use rand::{rngs::StdRng, SeedableRng};
19use serde::ser::Serialize;
20use std::convert::TryFrom;
21
22#[cfg_attr(any(test, feature = "fuzzing"), derive(Clone, Debug))]
26pub struct ValidatorSigner {
27 author: AccountAddress,
28 private_key: ConsensusPrivateKey,
29 vrf_private_key: Option<ConsensusVRFPrivateKey>,
31}
32
33impl ValidatorSigner {
34 pub fn new(
35 author: AccountAddress, private_key: ConsensusPrivateKey,
36 vrf_private_key: Option<ConsensusVRFPrivateKey>,
37 ) -> Self {
38 ValidatorSigner {
39 author,
40 private_key,
41 vrf_private_key,
42 }
43 }
44
45 pub fn sign<T: Serialize + CryptoHash>(
47 &self, message: &T,
48 ) -> ConsensusSignature {
49 self.private_key.sign(message)
50 }
51
52 pub fn author(&self) -> AccountAddress { self.author }
54
55 pub fn public_key(&self) -> ConsensusPublicKey {
57 self.private_key.public_key()
58 }
59
60 pub fn vrf_public_key(&self) -> Option<ConsensusVRFPublicKey> {
61 self.vrf_private_key.as_ref().map(|sk| sk.public_key())
62 }
63
64 #[cfg(any(test, feature = "fuzzing"))]
67 pub fn private_key(&self) -> &ConsensusPrivateKey { &self.private_key }
68}
69
70impl ValidatorSigner {
71 pub fn random(opt_rng_seed: impl for<'a> Into<Option<[u8; 32]>>) -> Self {
76 let mut rng =
77 StdRng::from_seed(opt_rng_seed.into().unwrap_or(TEST_SEED));
78 Self::new(
79 AccountAddress::random(),
80 ConsensusPrivateKey::generate(&mut rng),
81 Some(ConsensusVRFPrivateKey::generate(&mut rng)),
82 )
83 }
84
85 pub fn from_int(num: u8) -> Self {
88 let mut address = [0; AccountAddress::LENGTH];
89 address[0] = num;
90 let private_key = ConsensusPrivateKey::generate_for_testing();
91 let vrf_private_key = ConsensusVRFPrivateKey::generate_for_testing();
92 Self::new(
93 AccountAddress::try_from(&address[..]).unwrap(),
94 private_key,
95 Some(vrf_private_key),
96 )
97 }
98}
99
100#[cfg(any(test, feature = "fuzzing"))]
101pub mod proptests {
102 use super::*;
103 use diem_crypto::Genesis;
104 use proptest::{prelude::*, sample, strategy::LazyJust};
105
106 #[allow(clippy::redundant_closure)]
107 pub fn arb_signing_key() -> impl Strategy<Value = ConsensusPrivateKey> {
108 prop_oneof![
109 LazyJust::new(|| ConsensusPrivateKey::generate_for_testing()),
112 LazyJust::new(|| ConsensusPrivateKey::genesis()),
113 ]
114 }
115
116 pub fn signer_strategy(
117 signing_key_strategy: impl Strategy<Value = ConsensusPrivateKey>,
118 ) -> impl Strategy<Value = ValidatorSigner> {
119 signing_key_strategy.prop_map(|signing_key| {
120 ValidatorSigner::new(AccountAddress::random(), signing_key, None)
121 })
122 }
123
124 #[allow(clippy::redundant_closure)]
125 pub fn rand_signer() -> impl Strategy<Value = ValidatorSigner> {
126 signer_strategy(arb_signing_key())
127 }
128
129 #[allow(clippy::redundant_closure)]
130 pub fn arb_signer() -> impl Strategy<Value = ValidatorSigner> {
131 prop_oneof![
132 rand_signer(),
133 LazyJust::new(|| {
134 let genesis_key = ConsensusPrivateKey::genesis();
135 ValidatorSigner::new(
136 AccountAddress::random(),
137 genesis_key,
138 None,
139 )
140 })
141 ]
142 }
143
144 fn select_keypair(
145 keys: Vec<ConsensusPrivateKey>,
146 ) -> impl Strategy<Value = ConsensusPrivateKey> {
147 sample::select(keys)
148 }
149
150 pub fn mostly_in_keypair_pool(
151 keys: Vec<ConsensusPrivateKey>,
152 ) -> impl Strategy<Value = ValidatorSigner> {
153 prop::strategy::Union::new_weighted(vec![
154 (9, signer_strategy(select_keypair(keys)).boxed()),
155 (1, arb_signer().boxed()),
156 ])
157 }
158
159 proptest! {
160 #[test]
161 fn test_new_signer(signing_key in arb_signing_key()){
162 let public_key = signing_key.public_key();
163 let signer = ValidatorSigner::new(AccountAddress::random(), signing_key, None);
164 prop_assert_eq!(public_key, signer.public_key());
165 }
166
167 }
168}