|
1 | 1 | use crate::errors::BeaconChainError; |
2 | 2 | use crate::{BeaconChainTypes, BeaconStore}; |
| 3 | +use bls::PUBLIC_KEY_UNCOMPRESSED_BYTES_LEN; |
| 4 | +use smallvec::SmallVec; |
3 | 5 | use ssz::{Decode, Encode}; |
| 6 | +use ssz_derive::{Decode, Encode}; |
4 | 7 | use std::collections::HashMap; |
5 | 8 | use std::marker::PhantomData; |
6 | 9 | use store::{DBColumn, Error as StoreError, StoreItem, StoreOp}; |
@@ -49,14 +52,13 @@ impl<T: BeaconChainTypes> ValidatorPubkeyCache<T> { |
49 | 52 | let mut pubkey_bytes = vec![]; |
50 | 53 |
|
51 | 54 | for validator_index in 0.. { |
52 | | - if let Some(DatabasePubkey(pubkey)) = |
| 55 | + if let Some(db_pubkey) = |
53 | 56 | store.get_item(&DatabasePubkey::key_for_index(validator_index))? |
54 | 57 | { |
55 | | - pubkeys.push((&pubkey).try_into().map_err(|e| { |
56 | | - BeaconChainError::ValidatorPubkeyCacheError(format!("{:?}", e)) |
57 | | - })?); |
58 | | - pubkey_bytes.push(pubkey); |
59 | | - indices.insert(pubkey, validator_index); |
| 58 | + let (pk, pk_bytes) = DatabasePubkey::as_pubkey(&db_pubkey)?; |
| 59 | + pubkeys.push(pk); |
| 60 | + indices.insert(pk_bytes, validator_index); |
| 61 | + pubkey_bytes.push(pk_bytes); |
60 | 62 | } else { |
61 | 63 | break; |
62 | 64 | } |
@@ -104,29 +106,29 @@ impl<T: BeaconChainTypes> ValidatorPubkeyCache<T> { |
104 | 106 | self.indices.reserve(validator_keys.len()); |
105 | 107 |
|
106 | 108 | let mut store_ops = Vec::with_capacity(validator_keys.len()); |
107 | | - for pubkey in validator_keys { |
| 109 | + for pubkey_bytes in validator_keys { |
108 | 110 | let i = self.pubkeys.len(); |
109 | 111 |
|
110 | | - if self.indices.contains_key(&pubkey) { |
| 112 | + if self.indices.contains_key(&pubkey_bytes) { |
111 | 113 | return Err(BeaconChainError::DuplicateValidatorPublicKey); |
112 | 114 | } |
113 | 115 |
|
| 116 | + let pubkey = (&pubkey_bytes) |
| 117 | + .try_into() |
| 118 | + .map_err(BeaconChainError::InvalidValidatorPubkeyBytes)?; |
| 119 | + |
114 | 120 | // Stage the new validator key for writing to disk. |
115 | 121 | // It will be committed atomically when the block that introduced it is written to disk. |
116 | 122 | // Notably it is NOT written while the write lock on the cache is held. |
117 | 123 | // See: https://github.com/sigp/lighthouse/issues/2327 |
118 | 124 | store_ops.push(StoreOp::KeyValueOp( |
119 | | - DatabasePubkey(pubkey).as_kv_store_op(DatabasePubkey::key_for_index(i)), |
| 125 | + DatabasePubkey::from_pubkey(&pubkey) |
| 126 | + .as_kv_store_op(DatabasePubkey::key_for_index(i)), |
120 | 127 | )); |
121 | 128 |
|
122 | | - self.pubkeys.push( |
123 | | - (&pubkey) |
124 | | - .try_into() |
125 | | - .map_err(BeaconChainError::InvalidValidatorPubkeyBytes)?, |
126 | | - ); |
127 | | - self.pubkey_bytes.push(pubkey); |
128 | | - |
129 | | - self.indices.insert(pubkey, i); |
| 129 | + self.pubkeys.push(pubkey); |
| 130 | + self.pubkey_bytes.push(pubkey_bytes); |
| 131 | + self.indices.insert(pubkey_bytes, i); |
130 | 132 | } |
131 | 133 |
|
132 | 134 | Ok(store_ops) |
@@ -166,26 +168,42 @@ impl<T: BeaconChainTypes> ValidatorPubkeyCache<T> { |
166 | 168 | /// Wrapper for a public key stored in the database. |
167 | 169 | /// |
168 | 170 | /// Keyed by the validator index as `Hash256::from_low_u64_be(index)`. |
169 | | -struct DatabasePubkey(PublicKeyBytes); |
| 171 | +#[derive(Encode, Decode)] |
| 172 | +pub struct DatabasePubkey { |
| 173 | + pubkey: SmallVec<[u8; PUBLIC_KEY_UNCOMPRESSED_BYTES_LEN]>, |
| 174 | +} |
170 | 175 |
|
171 | 176 | impl StoreItem for DatabasePubkey { |
172 | 177 | fn db_column() -> DBColumn { |
173 | 178 | DBColumn::PubkeyCache |
174 | 179 | } |
175 | 180 |
|
176 | 181 | fn as_store_bytes(&self) -> Vec<u8> { |
177 | | - self.0.as_ssz_bytes() |
| 182 | + self.as_ssz_bytes() |
178 | 183 | } |
179 | 184 |
|
180 | 185 | fn from_store_bytes(bytes: &[u8]) -> Result<Self, StoreError> { |
181 | | - Ok(Self(PublicKeyBytes::from_ssz_bytes(bytes)?)) |
| 186 | + Ok(Self::from_ssz_bytes(bytes)?) |
182 | 187 | } |
183 | 188 | } |
184 | 189 |
|
185 | 190 | impl DatabasePubkey { |
186 | 191 | fn key_for_index(index: usize) -> Hash256 { |
187 | 192 | Hash256::from_low_u64_be(index as u64) |
188 | 193 | } |
| 194 | + |
| 195 | + pub fn from_pubkey(pubkey: &PublicKey) -> Self { |
| 196 | + Self { |
| 197 | + pubkey: pubkey.serialize_uncompressed().into(), |
| 198 | + } |
| 199 | + } |
| 200 | + |
| 201 | + pub fn as_pubkey(&self) -> Result<(PublicKey, PublicKeyBytes), BeaconChainError> { |
| 202 | + let pubkey = PublicKey::deserialize_uncompressed(&self.pubkey) |
| 203 | + .map_err(BeaconChainError::InvalidValidatorPubkeyBytes)?; |
| 204 | + let pubkey_bytes = pubkey.compress(); |
| 205 | + Ok((pubkey, pubkey_bytes)) |
| 206 | + } |
189 | 207 | } |
190 | 208 |
|
191 | 209 | #[cfg(test)] |
|
0 commit comments