@@ -265,21 +265,21 @@ private void handleSaltSimulate(RoutingContext rc) {
265265 saltRotation .setEnableV4RawUid (false );
266266 for (int i = 0 ; i < preMigrationIterations ; i ++) {
267267 LOGGER .info ("Step 1 - Pre-migration Iteration {}/{}" , i + 1 , preMigrationIterations );
268- simulationIteration (rc , fraction , targetDate , i , emails , emailToUidMapping );
268+ simulationIteration (rc , fraction , targetDate , i , false , emails , emailToUidMapping );
269269 targetDate = targetDate .plusDays (1 );
270270 }
271271
272272 saltRotation .setEnableV4RawUid (true );
273273 for (int i = 0 ; i < migrationV4Iterations ; i ++) {
274274 LOGGER .info ("Step 2 - Migration V4 Iteration {}/{}" , i + 1 , migrationV4Iterations );
275- simulationIteration (rc , fraction , targetDate , i , emails , emailToUidMapping );
275+ simulationIteration (rc , fraction , targetDate , i , true , emails , emailToUidMapping );
276276 targetDate = targetDate .plusDays (1 );
277277 }
278278
279279 saltRotation .setEnableV4RawUid (false );
280280 for (int i = 0 ; i < migrationV2V3Iterations ; i ++) {
281281 LOGGER .info ("Step 3 - Migration V2/V3 Iteration {}/{}" , i + 1 , migrationV2V3Iterations );
282- simulationIteration (rc , fraction , targetDate , i , emails , emailToUidMapping );
282+ simulationIteration (rc , fraction , targetDate , i , false , emails , emailToUidMapping );
283283 targetDate = targetDate .plusDays (1 );
284284 }
285285
@@ -293,7 +293,7 @@ private void handleSaltSimulate(RoutingContext rc) {
293293 }
294294
295295 private void simulationIteration (
296- RoutingContext rc , double fraction , TargetDate targetDate , int iteration ,
296+ RoutingContext rc , double fraction , TargetDate targetDate , int iteration , boolean enabledV4Uid ,
297297 List <String > emails , Map <String , Map <SaltEntry , String >> emailToUidMapping
298298 ) throws Exception {
299299 // Rotate salts
@@ -312,38 +312,45 @@ private void simulationIteration(
312312 Map <SaltEntry , Integer > invalidSaltCount = new HashMap <>();
313313 int skippedUidCount = 0 ;
314314 int inconsistentUidCount = 0 ;
315- int validUidV2Count = 0 ;
316315 int validUidV4Count = 0 ;
317- int validPrevUidV2Count = 0 ;
316+ int validUidV2Count = 0 ;
318317 int validPrevUidV4Count = 0 ;
318+ int validPrevUidV2Count = 0 ;
319319 int validNoPrevUidCount = 0 ;
320320 int invalidUidCount = 0 ;
321321 int invalidPrevUidCount = 0 ;
322322 for (int j = 0 ; j < IDENTITY_COUNT ; j ++) {
323323 String email = emails .get (j );
324324 SaltEntry salt = emailToSaltMap .get (email );
325325
326- // Assert salt state
326+ // Prepare salt state booleans
327327 boolean missingSalt = salt .currentSalt () == null ;
328328 boolean missingKey = salt .currentKeySalt () == null || salt .currentKeySalt ().key () == null || salt .currentKeySalt ().salt () == null ;
329329 boolean missingPrevSalt = salt .previousSalt () == null ;
330330 boolean missingPrevKey = salt .previousKeySalt () == null || salt .previousKeySalt ().key () == null || salt .previousKeySalt ().salt () == null ;
331- if (!assertSaltState (missingSalt , missingKey , missingPrevSalt , missingPrevKey )) {
332- invalidSaltCount .put (salt , invalidSaltCount .getOrDefault (salt , 0 ) + 1 );
333- skippedUidCount ++;
334- continue ;
335- }
336- validSaltCount .put (salt , validSaltCount .getOrDefault (salt , 0 ) + 1 );
337331
338- // Assert current UID
332+ // Prepare current UID booleans
339333 JsonNode mapping = emailMappings .get (j );
340334 String uid = mapping .at ("/u" ).asText (null );
341335 byte [] uidBytes = uid == null ? null : Base64 .getDecoder ().decode (uid );
342336 boolean isV4Uid = uidBytes != null && uidBytes .length == 33 ;
343337 boolean isV2Uid = uidBytes != null && uidBytes .length == 32 ;
338+ boolean rotated = emailToUidMapping .get (email ).containsKey (salt );
339+
340+ // Assert salt state + additional assertions on freshly rotated salts with enabledV4Uid flag
341+ if (!assertSaltState (missingSalt , missingKey , missingPrevSalt , missingPrevKey , rotated , enabledV4Uid )) {
342+ invalidSaltCount .put (salt , invalidSaltCount .getOrDefault (salt , 0 ) + 1 );
343+ skippedUidCount ++;
344+ continue ;
345+ }
346+ validSaltCount .put (salt , validSaltCount .getOrDefault (salt , 0 ) + 1 );
347+
348+ // Assert UID consistency
344349 if (!assertUidConsistency (uid , email , salt , emailToUidMapping )) {
345350 inconsistentUidCount ++;
346351 }
352+
353+ // Assert that current UID is valid based on salt state
347354 boolean validCurrentUid = assertCurrentUid (uidBytes , isV4Uid , isV2Uid , missingKey , missingSalt , email , salt , result .getSnapshot ());
348355 if (validCurrentUid ) {
349356 if (isV4Uid ) {
@@ -360,7 +367,10 @@ private void simulationIteration(
360367 byte [] prevUidBytes = prevUid == null ? null : Base64 .getDecoder ().decode (prevUid );
361368 boolean isPrevV4Uid = prevUidBytes != null && prevUidBytes .length == 33 ;
362369 boolean isPrevV2Uid = prevUidBytes != null && prevUidBytes .length == 32 ;
363- boolean validPrevUid = assertPrevUid (prevUidBytes , isPrevV4Uid , isPrevV2Uid , missingPrevKey , missingPrevSalt , isV4Uid , isV2Uid , email , salt , result .getSnapshot ());
370+
371+ boolean validPrevUid = assertPrevUid (
372+ prevUidBytes , isPrevV4Uid , isPrevV2Uid , missingPrevKey , missingPrevSalt ,
373+ email , salt , result .getSnapshot ());
364374 if (validPrevUid ) {
365375 if (prevUidBytes != null ) {
366376 if (isPrevV4Uid ) {
@@ -413,7 +423,9 @@ private SaltRotation.Result rotateSalts(RoutingContext rc, double fraction, Targ
413423 return result ;
414424 }
415425
416- private boolean assertSaltState (boolean missingSalt , boolean missingKey , boolean missingPrevSalt , boolean missingPrevKey ) {
426+ private boolean assertSaltState (
427+ boolean missingSalt , boolean missingKey , boolean missingPrevSalt , boolean missingPrevKey ,
428+ boolean rotated , boolean enabledV4Uid ) {
417429 if (missingSalt && missingKey ) {
418430 LOGGER .error ("Invalid salt state - salt and key are both missing" );
419431 return false ;
@@ -423,6 +435,12 @@ private boolean assertSaltState(boolean missingSalt, boolean missingKey, boolean
423435 } else if (!missingPrevSalt && !missingPrevKey ) {
424436 LOGGER .error ("Invalid salt state - previous salt and previous key are both present" );
425437 return false ;
438+ } else if (rotated && enabledV4Uid && missingKey ) {
439+ LOGGER .error ("Invalid salt state - V4 UID enabled but missing key on rotated salt" );
440+ return false ;
441+ } else if (rotated && !enabledV4Uid && missingSalt ) {
442+ LOGGER .error ("Invalid salt state - V4 UID enabled but missing salt on rotated salt" );
443+ return false ;
426444 }
427445
428446 return true ;
@@ -479,23 +497,15 @@ private boolean assertCurrentUid(
479497
480498 private boolean assertPrevUid (
481499 byte [] prevUidBytes , boolean isPrevV4Uid , boolean isPrevV2Uid , boolean missingPrevKey , boolean missingPrevSalt ,
482- boolean isV4Uid , boolean isV2Uid ,
483500 String email , SaltEntry salt , RotatingSaltProvider .SaltSnapshot snapshot
484501 ) {
485502 if (prevUidBytes != null ) {
486503 if (isPrevV4Uid ) {
487- if (isV2Uid ) {
488- LOGGER .error ("Invalid previous UID state - v2 UID with v4 prev UID" );
489- return false ;
490- } else if (isV4Uid ) {
491- if (assertV4Uid (prevUidBytes , email , salt .previousKeySalt (), snapshot )) {
492- if (!missingPrevKey ) {
493- return true ;
494- } else {
495- LOGGER .error ("Invalid previous UID state - v4 UID generated with null key" );
496- return false ;
497- }
504+ if (assertV4Uid (prevUidBytes , email , salt .previousKeySalt (), snapshot )) {
505+ if (!missingPrevKey ) {
506+ return true ;
498507 } else {
508+ LOGGER .error ("Invalid previous UID state - v4 UID generated with null key" );
499509 return false ;
500510 }
501511 } else {
@@ -514,14 +524,8 @@ private boolean assertPrevUid(
514524 return false ;
515525 }
516526 } else {
517- if (!missingPrevKey && !missingPrevSalt ) {
518- LOGGER .error ("Invalid previous UID state - both previous salt and previous key found" );
519- return false ;
520- } else if (!missingPrevKey ) { // Add rollback assertions
521- LOGGER .error ("Expected: v4 prev UID | Actual: null prev UID" );
522- return false ;
523- } else if (!missingPrevSalt ) { // Add rollback assertions
524- LOGGER .error ("Expected: v2 prev UID | Actual: null prev UID" );
527+ if (!missingPrevKey || !missingPrevSalt ) {
528+ LOGGER .error ("Invalid previous UID state - previous salt or previous key found" );
525529 return false ;
526530 } else {
527531 return true ;
0 commit comments