1
1
use {
2
- crate :: stakes:: { Stakes , StakesEnum } ,
3
- serde:: { Deserialize , Serialize } ,
2
+ crate :: {
3
+ stake_account:: StakeAccount ,
4
+ stakes:: { Stakes , StakesEnum } ,
5
+ } ,
6
+ serde:: { Deserialize , Deserializer , Serialize , Serializer } ,
4
7
solana_sdk:: { clock:: Epoch , pubkey:: Pubkey , stake:: state:: Stake } ,
8
+ solana_stake_program:: stake_state:: Delegation ,
5
9
solana_vote:: vote_account:: VoteAccountsHashMap ,
6
10
std:: { collections:: HashMap , sync:: Arc } ,
7
11
} ;
@@ -131,16 +135,78 @@ impl EpochStakes {
131
135
}
132
136
133
137
#[ cfg_attr( feature = "frozen-abi" , derive( AbiExample , AbiEnumVisitor ) ) ]
134
- #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
138
+ #[ cfg_attr( feature = "dev-context-only-utils" , derive( PartialEq ) ) ]
139
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
135
140
pub enum VersionedEpochStakes {
136
141
Current {
137
- stakes : Stakes < Stake > ,
142
+ stakes : StakesSerdeWrapper ,
138
143
total_stake : u64 ,
139
144
node_id_to_vote_accounts : Arc < NodeIdToVoteAccounts > ,
140
145
epoch_authorized_voters : Arc < EpochAuthorizedVoters > ,
141
146
} ,
142
147
}
143
148
149
+ /// Wrapper struct with custom serialization to support serializing
150
+ /// `Stakes<StakeAccount>` as `Stakes<Stake>` without doing a full deep clone of
151
+ /// the stake data. Serialization works by building a `Stakes<&Stake>` map which
152
+ /// borrows `&Stake` from `StakeAccount` entries in `Stakes<StakeAccount>`. Note
153
+ /// that `Stakes<&Stake>` still copies `Pubkey` keys so the `Stakes<&Stake>`
154
+ /// data structure still allocates a fair amount of memory but the memory only
155
+ /// remains allocated during serialization.
156
+ #[ cfg_attr( feature = "frozen-abi" , derive( AbiExample , AbiEnumVisitor ) ) ]
157
+ #[ derive( Debug , Clone ) ]
158
+ pub enum StakesSerdeWrapper {
159
+ Stake ( Stakes < Stake > ) ,
160
+ Account ( Stakes < StakeAccount < Delegation > > ) ,
161
+ }
162
+
163
+ #[ cfg( feature = "dev-context-only-utils" ) ]
164
+ impl PartialEq < Self > for StakesSerdeWrapper {
165
+ fn eq ( & self , other : & Self ) -> bool {
166
+ match ( self , other) {
167
+ ( Self :: Stake ( stakes) , Self :: Stake ( other) ) => stakes == other,
168
+ ( Self :: Account ( stakes) , Self :: Account ( other) ) => stakes == other,
169
+ ( Self :: Stake ( stakes) , Self :: Account ( other) ) => {
170
+ stakes == & Stakes :: < Stake > :: from ( other. clone ( ) )
171
+ }
172
+ ( Self :: Account ( stakes) , Self :: Stake ( other) ) => {
173
+ other == & Stakes :: < Stake > :: from ( stakes. clone ( ) )
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ impl From < StakesSerdeWrapper > for StakesEnum {
180
+ fn from ( stakes : StakesSerdeWrapper ) -> Self {
181
+ match stakes {
182
+ StakesSerdeWrapper :: Stake ( stakes) => Self :: Stakes ( stakes) ,
183
+ StakesSerdeWrapper :: Account ( stakes) => Self :: Accounts ( stakes) ,
184
+ }
185
+ }
186
+ }
187
+
188
+ impl Serialize for StakesSerdeWrapper {
189
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
190
+ where
191
+ S : Serializer ,
192
+ {
193
+ match self {
194
+ Self :: Stake ( stakes) => stakes. serialize ( serializer) ,
195
+ Self :: Account ( stakes) => Stakes :: < & Stake > :: from ( stakes) . serialize ( serializer) ,
196
+ }
197
+ }
198
+ }
199
+
200
+ impl < ' de > Deserialize < ' de > for StakesSerdeWrapper {
201
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
202
+ where
203
+ D : Deserializer < ' de > ,
204
+ {
205
+ let stakes = Stakes :: < Stake > :: deserialize ( deserializer) ?;
206
+ Ok ( Self :: Stake ( stakes) )
207
+ }
208
+ }
209
+
144
210
impl From < VersionedEpochStakes > for EpochStakes {
145
211
fn from ( versioned : VersionedEpochStakes ) -> Self {
146
212
let VersionedEpochStakes :: Current {
@@ -151,7 +217,7 @@ impl From<VersionedEpochStakes> for EpochStakes {
151
217
} = versioned;
152
218
153
219
Self {
154
- stakes : Arc :: new ( StakesEnum :: Stakes ( stakes) ) ,
220
+ stakes : Arc :: new ( stakes. into ( ) ) ,
155
221
total_stake,
156
222
node_id_to_vote_accounts,
157
223
epoch_authorized_voters,
@@ -196,7 +262,7 @@ pub(crate) fn split_epoch_stakes(
196
262
versioned_epoch_stakes. insert (
197
263
epoch,
198
264
VersionedEpochStakes :: Current {
199
- stakes : Stakes :: < Stake > :: from ( stakes. clone ( ) ) ,
265
+ stakes : StakesSerdeWrapper :: Account ( stakes. clone ( ) ) ,
200
266
total_stake,
201
267
node_id_to_vote_accounts,
202
268
epoch_authorized_voters,
@@ -207,7 +273,7 @@ pub(crate) fn split_epoch_stakes(
207
273
versioned_epoch_stakes. insert (
208
274
epoch,
209
275
VersionedEpochStakes :: Current {
210
- stakes : stakes. clone ( ) ,
276
+ stakes : StakesSerdeWrapper :: Stake ( stakes. clone ( ) ) ,
211
277
total_stake,
212
278
node_id_to_vote_accounts,
213
279
epoch_authorized_voters,
@@ -426,7 +492,7 @@ pub(crate) mod tests {
426
492
assert_eq ! (
427
493
versioned. get( & epoch) ,
428
494
Some ( & VersionedEpochStakes :: Current {
429
- stakes: Stakes :: < Stake > :: from ( test_stakes) ,
495
+ stakes: StakesSerdeWrapper :: Account ( test_stakes) ,
430
496
total_stake: epoch_stakes. total_stake,
431
497
node_id_to_vote_accounts: epoch_stakes. node_id_to_vote_accounts,
432
498
epoch_authorized_voters: epoch_stakes. epoch_authorized_voters,
@@ -455,7 +521,7 @@ pub(crate) mod tests {
455
521
assert_eq ! (
456
522
versioned. get( & epoch) ,
457
523
Some ( & VersionedEpochStakes :: Current {
458
- stakes: test_stakes,
524
+ stakes: StakesSerdeWrapper :: Stake ( test_stakes) ,
459
525
total_stake: epoch_stakes. total_stake,
460
526
node_id_to_vote_accounts: epoch_stakes. node_id_to_vote_accounts,
461
527
epoch_authorized_voters: epoch_stakes. epoch_authorized_voters,
@@ -506,8 +572,24 @@ pub(crate) mod tests {
506
572
assert ! ( old. contains_key( & epoch1) ) ;
507
573
508
574
assert_eq ! ( versioned. len( ) , 2 ) ;
509
- assert ! ( versioned. contains_key( & epoch2) ) ;
510
- assert ! ( versioned. contains_key( & epoch3) ) ;
575
+ assert_eq ! (
576
+ versioned. get( & epoch2) ,
577
+ Some ( & VersionedEpochStakes :: Current {
578
+ stakes: StakesSerdeWrapper :: Account ( Stakes :: default ( ) ) ,
579
+ total_stake: 200 ,
580
+ node_id_to_vote_accounts: Arc :: default ( ) ,
581
+ epoch_authorized_voters: Arc :: default ( ) ,
582
+ } )
583
+ ) ;
584
+ assert_eq ! (
585
+ versioned. get( & epoch3) ,
586
+ Some ( & VersionedEpochStakes :: Current {
587
+ stakes: StakesSerdeWrapper :: Stake ( Stakes :: default ( ) ) ,
588
+ total_stake: 300 ,
589
+ node_id_to_vote_accounts: Arc :: default ( ) ,
590
+ epoch_authorized_voters: Arc :: default ( ) ,
591
+ } )
592
+ ) ;
511
593
}
512
594
513
595
#[ test]
0 commit comments