@@ -215,6 +215,7 @@ func (proc *Processor) decodeMutations(
215215 out .AddMAC (indexMAC , valueMAC )
216216 }
217217 out .Mutations = append (out .Mutations , Mutation {
218+ KeyID : mutation .GetRecord ().GetKeyID ().GetID (),
218219 Operation : mutation .GetOperation (),
219220 Action : syncAction .GetValue (),
220221 Version : syncAction .GetVersion (),
@@ -257,7 +258,14 @@ func (proc *Processor) validateSnapshotMAC(ctx context.Context, name WAPatchName
257258 return
258259}
259260
260- func (proc * Processor ) decodeSnapshot (ctx context.Context , name WAPatchName , ss * waServerSync.SyncdSnapshot , initialState HashState , validateMACs bool , newMutationsInput []Mutation ) (newMutations []Mutation , currentState HashState , err error ) {
261+ func (proc * Processor ) decodeSnapshot (
262+ ctx context.Context ,
263+ name WAPatchName ,
264+ ss * waServerSync.SyncdSnapshot ,
265+ initialState HashState ,
266+ validateMACs bool ,
267+ newMutationsInput []Mutation ,
268+ ) (newMutations []Mutation , currentState HashState , err error ) {
261269 currentState = initialState
262270 currentState .Version = ss .GetVersion ().GetVersion ()
263271
@@ -269,9 +277,17 @@ func (proc *Processor) decodeSnapshot(ctx context.Context, name WAPatchName, ss
269277 }
270278 }
271279
280+ var fakeIndexesToRemove map [[32 ]byte ][]byte
272281 var warn []error
273282 warn , err = currentState .updateHash (encryptedMutations , func (indexMAC []byte , maxIndex int ) ([]byte , error ) {
274- return nil , nil
283+ vm , newIndexMAC , err := proc .evilHackForLIDMutation (ctx , name , indexMAC , encryptedMutations [maxIndex ], maxIndex , encryptedMutations , false )
284+ if vm != nil && newIndexMAC != nil && len (indexMAC ) == 32 {
285+ if fakeIndexesToRemove == nil {
286+ fakeIndexesToRemove = make (map [[32 ]byte ][]byte )
287+ }
288+ fakeIndexesToRemove [indexMACToArray (indexMAC )] = newIndexMAC
289+ }
290+ return vm , err
275291 })
276292 if len (warn ) > 0 {
277293 proc .Log .Warnf ("Warnings while updating hash for %s: %+v" , name , warn )
@@ -291,7 +307,7 @@ func (proc *Processor) decodeSnapshot(ctx context.Context, name WAPatchName, ss
291307
292308 var out patchOutput
293309 out .Mutations = newMutationsInput
294- err = proc .decodeMutations (ctx , encryptedMutations , & out , validateMACs , currentState .Version , nil )
310+ err = proc .decodeMutations (ctx , encryptedMutations , & out , validateMACs , currentState .Version , fakeIndexesToRemove )
295311 if err != nil {
296312 err = fmt .Errorf ("failed to decode snapshot of v%d: %w" , currentState .Version , err )
297313 return
@@ -313,6 +329,8 @@ func (proc *Processor) evilHackForLIDMutation(
313329 oldIndexMAC []byte ,
314330 mutation * waServerSync.SyncdMutation ,
315331 mutationNum int ,
332+ prevMutations []* waServerSync.SyncdMutation ,
333+ checkDatabase bool ,
316334) (newValueMAC , newIndexMAC []byte , err error ) {
317335 _ , _ , index , _ , keys , err := proc .decodeMutation (ctx , mutation , mutationNum , true )
318336 if err != nil {
@@ -351,7 +369,44 @@ func (proc *Processor) evilHackForLIDMutation(
351369 return nil , nil , fmt .Errorf ("failed to marshal modified index for LID hack: %w" , err )
352370 }
353371 newIndexMAC = concatAndHMAC (sha256 .New , keys .Index , indexBytes )
354- newValueMAC , err = proc .Store .AppState .GetAppStateMutationMAC (ctx , string (patchName ), newIndexMAC )
372+ currentKeyID := mutation .GetRecord ().GetKeyID ().GetID ()
373+ for i := mutationNum - 1 ; i >= 0 ; i -- {
374+ newKeyID := prevMutations [i ].GetRecord ().GetKeyID ().GetID ()
375+ if ! bytes .Equal (currentKeyID , newKeyID ) {
376+ keys , err = proc .getAppStateKey (ctx , newKeyID )
377+ if err != nil {
378+ return nil , nil , fmt .Errorf ("failed to get key %X to decode mutation for LID hack: %w" , newKeyID , err )
379+ }
380+ currentKeyID = newKeyID
381+ newIndexMAC = concatAndHMAC (sha256 .New , keys .Index , indexBytes )
382+ }
383+ if bytes .Equal (prevMutations [i ].GetRecord ().GetIndex ().GetBlob (), newIndexMAC ) {
384+ if prevMutations [i ].GetOperation () == waServerSync .SyncdMutation_SET {
385+ value := prevMutations [i ].GetRecord ().GetValue ().GetBlob ()
386+ newValueMAC = value [len (value )- 32 :]
387+ } else {
388+ // Found a REMOVE operation, no previous value
389+ return nil , nil , nil
390+ }
391+ }
392+ }
393+ if newValueMAC == nil && checkDatabase {
394+ newValueMAC , err = proc .Store .AppState .GetAppStateMutationMAC (ctx , string (patchName ), newIndexMAC )
395+ if err == nil && newValueMAC == nil {
396+ var allKeys []* store.AppStateSyncKey
397+ allKeys , err = proc .Store .AppStateKeys .GetAllAppStateSyncKeys (ctx )
398+ for _ , key := range allKeys {
399+ altIndexMAC := concatAndHMAC (sha256 .New , expandAppStateKeys (key .Data ).Index , indexBytes )
400+ newValueMAC , err = proc .Store .AppState .GetAppStateMutationMAC (ctx , string (patchName ), altIndexMAC )
401+ if newValueMAC != nil {
402+ newIndexMAC = altIndexMAC
403+ }
404+ if err != nil || newValueMAC != nil {
405+ break
406+ }
407+ }
408+ }
409+ }
355410 if err != nil {
356411 // explosions (return is below)
357412 } else if newValueMAC == nil {
@@ -402,7 +457,7 @@ func (proc *Processor) validatePatch(
402457 if vm != nil || err != nil || ! allowEvilLIDHack {
403458 return vm , err
404459 }
405- vm , newIndexMAC , err := proc .evilHackForLIDMutation (ctx , patchName , indexMAC , patch .Mutations [maxIndex ], maxIndex )
460+ vm , newIndexMAC , err := proc .evilHackForLIDMutation (ctx , patchName , indexMAC , patch .Mutations [maxIndex ], maxIndex , patch . Mutations , true )
406461 if vm != nil && newIndexMAC != nil && len (indexMAC ) == 32 {
407462 if fakeIndexesToRemove == nil {
408463 fakeIndexesToRemove = make (map [[32 ]byte ][]byte )
0 commit comments