@@ -18,7 +18,7 @@ type PersistedSyncContributions<T> = Vec<(SyncAggregateId, Vec<SyncCommitteeCont
1818/// Operations are stored in arbitrary order, so it's not a good idea to compare instances
1919/// of this type (or its encoded form) for equality. Convert back to an `OperationPool` first.
2020#[ superstruct(
21- variants( V5 , V12 ) ,
21+ variants( V5 , V12 , V14 ) ,
2222 variant_attributes(
2323 derive( Derivative , PartialEq , Debug , Encode , Decode ) ,
2424 derivative( Clone ) ,
@@ -32,28 +32,31 @@ pub struct PersistedOperationPool<T: EthSpec> {
3232 #[ superstruct( only( V5 ) ) ]
3333 pub attestations_v5 : Vec < ( AttestationId , Vec < Attestation < T > > ) > ,
3434 /// Attestations and their attesting indices.
35- #[ superstruct( only( V12 ) ) ]
35+ #[ superstruct( only( V12 , V14 ) ) ]
3636 pub attestations : Vec < ( Attestation < T > , Vec < u64 > ) > ,
3737 /// Mapping from sync contribution ID to sync contributions and aggregate.
3838 pub sync_contributions : PersistedSyncContributions < T > ,
3939 /// [DEPRECATED] Attester slashings.
4040 #[ superstruct( only( V5 ) ) ]
4141 pub attester_slashings_v5 : Vec < ( AttesterSlashing < T > , ForkVersion ) > ,
4242 /// Attester slashings.
43- #[ superstruct( only( V12 ) ) ]
43+ #[ superstruct( only( V12 , V14 ) ) ]
4444 pub attester_slashings : Vec < SigVerifiedOp < AttesterSlashing < T > , T > > ,
4545 /// [DEPRECATED] Proposer slashings.
4646 #[ superstruct( only( V5 ) ) ]
4747 pub proposer_slashings_v5 : Vec < ProposerSlashing > ,
4848 /// Proposer slashings with fork information.
49- #[ superstruct( only( V12 ) ) ]
49+ #[ superstruct( only( V12 , V14 ) ) ]
5050 pub proposer_slashings : Vec < SigVerifiedOp < ProposerSlashing , T > > ,
5151 /// [DEPRECATED] Voluntary exits.
5252 #[ superstruct( only( V5 ) ) ]
5353 pub voluntary_exits_v5 : Vec < SignedVoluntaryExit > ,
5454 /// Voluntary exits with fork information.
55- #[ superstruct( only( V12 ) ) ]
55+ #[ superstruct( only( V12 , V14 ) ) ]
5656 pub voluntary_exits : Vec < SigVerifiedOp < SignedVoluntaryExit , T > > ,
57+ /// BLS to Execution Changes
58+ #[ superstruct( only( V14 ) ) ]
59+ pub bls_to_execution_changes : Vec < SigVerifiedOp < SignedBlsToExecutionChange , T > > ,
5760}
5861
5962impl < T : EthSpec > PersistedOperationPool < T > {
@@ -99,12 +102,20 @@ impl<T: EthSpec> PersistedOperationPool<T> {
99102 . map ( |( _, exit) | exit. clone ( ) )
100103 . collect ( ) ;
101104
102- PersistedOperationPool :: V12 ( PersistedOperationPoolV12 {
105+ let bls_to_execution_changes = operation_pool
106+ . bls_to_execution_changes
107+ . read ( )
108+ . iter ( )
109+ . map ( |( _, bls_to_execution_change) | bls_to_execution_change. clone ( ) )
110+ . collect ( ) ;
111+
112+ PersistedOperationPool :: V14 ( PersistedOperationPoolV14 {
103113 attestations,
104114 sync_contributions,
105115 attester_slashings,
106116 proposer_slashings,
107117 voluntary_exits,
118+ bls_to_execution_changes,
108119 } )
109120 }
110121
@@ -127,23 +138,41 @@ impl<T: EthSpec> PersistedOperationPool<T> {
127138 ) ;
128139 let sync_contributions = RwLock :: new ( self . sync_contributions ( ) . iter ( ) . cloned ( ) . collect ( ) ) ;
129140 let attestations = match self {
130- PersistedOperationPool :: V5 ( _) => return Err ( OpPoolError :: IncorrectOpPoolVariant ) ,
131- PersistedOperationPool :: V12 ( pool) => {
141+ PersistedOperationPool :: V5 ( _) | PersistedOperationPool :: V12 ( _) => {
142+ return Err ( OpPoolError :: IncorrectOpPoolVariant )
143+ }
144+ PersistedOperationPool :: V14 ( ref pool) => {
132145 let mut map = AttestationMap :: default ( ) ;
133- for ( att, attesting_indices) in pool. attestations {
146+ for ( att, attesting_indices) in pool. attestations . clone ( ) {
134147 map. insert ( att, attesting_indices) ;
135148 }
136149 RwLock :: new ( map)
137150 }
138151 } ;
152+ let bls_to_execution_changes = match self {
153+ PersistedOperationPool :: V5 ( _) | PersistedOperationPool :: V12 ( _) => {
154+ return Err ( OpPoolError :: IncorrectOpPoolVariant )
155+ }
156+ PersistedOperationPool :: V14 ( pool) => RwLock :: new (
157+ pool. bls_to_execution_changes
158+ . iter ( )
159+ . cloned ( )
160+ . map ( |bls_to_execution_change| {
161+ (
162+ bls_to_execution_change. as_inner ( ) . message . validator_index ,
163+ bls_to_execution_change,
164+ )
165+ } )
166+ . collect ( ) ,
167+ ) ,
168+ } ;
139169 let op_pool = OperationPool {
140170 attestations,
141171 sync_contributions,
142172 attester_slashings,
143173 proposer_slashings,
144174 voluntary_exits,
145- // FIXME(capella): implement schema migration for address changes in op pool
146- bls_to_execution_changes : Default :: default ( ) ,
175+ bls_to_execution_changes,
147176 reward_cache : Default :: default ( ) ,
148177 _phantom : Default :: default ( ) ,
149178 } ;
@@ -165,6 +194,20 @@ impl<T: EthSpec> StoreItem for PersistedOperationPoolV5<T> {
165194 }
166195}
167196
197+ impl < T : EthSpec > StoreItem for PersistedOperationPoolV12 < T > {
198+ fn db_column ( ) -> DBColumn {
199+ DBColumn :: OpPool
200+ }
201+
202+ fn as_store_bytes ( & self ) -> Vec < u8 > {
203+ self . as_ssz_bytes ( )
204+ }
205+
206+ fn from_store_bytes ( bytes : & [ u8 ] ) -> Result < Self , StoreError > {
207+ PersistedOperationPoolV12 :: from_ssz_bytes ( bytes) . map_err ( Into :: into)
208+ }
209+ }
210+
168211/// Deserialization for `PersistedOperationPool` defaults to `PersistedOperationPool::V12`.
169212impl < T : EthSpec > StoreItem for PersistedOperationPool < T > {
170213 fn db_column ( ) -> DBColumn {
@@ -177,8 +220,8 @@ impl<T: EthSpec> StoreItem for PersistedOperationPool<T> {
177220
178221 fn from_store_bytes ( bytes : & [ u8 ] ) -> Result < Self , StoreError > {
179222 // Default deserialization to the latest variant.
180- PersistedOperationPoolV12 :: from_ssz_bytes ( bytes)
181- . map ( Self :: V12 )
223+ PersistedOperationPoolV14 :: from_ssz_bytes ( bytes)
224+ . map ( Self :: V14 )
182225 . map_err ( Into :: into)
183226 }
184227}
0 commit comments