@@ -239,9 +239,40 @@ impl NetworkRunnable for Cmd {
239239}
240240
241241fn parse_changes ( changes : & [ LedgerEntryChange ] ) -> Option < u32 > {
242- match ( & changes[ 0 ] , & changes[ 1 ] ) {
243- (
244- LedgerEntryChange :: State ( _) ,
242+ match changes. len ( ) {
243+ // Handle case with 2 changes (original expected format)
244+ 2 => match ( & changes[ 0 ] , & changes[ 1 ] ) {
245+ (
246+ LedgerEntryChange :: State ( _) ,
247+ LedgerEntryChange :: Restored ( LedgerEntry {
248+ data :
249+ LedgerEntryData :: Ttl ( TtlEntry {
250+ live_until_ledger_seq,
251+ ..
252+ } ) ,
253+ ..
254+ } )
255+ | LedgerEntryChange :: Updated ( LedgerEntry {
256+ data :
257+ LedgerEntryData :: Ttl ( TtlEntry {
258+ live_until_ledger_seq,
259+ ..
260+ } ) ,
261+ ..
262+ } )
263+ | LedgerEntryChange :: Created ( LedgerEntry {
264+ data :
265+ LedgerEntryData :: Ttl ( TtlEntry {
266+ live_until_ledger_seq,
267+ ..
268+ } ) ,
269+ ..
270+ } ) ,
271+ ) => Some ( * live_until_ledger_seq) ,
272+ _ => None ,
273+ } ,
274+ // Handle case with 1 change (single "Restored" type change)
275+ 1 => match & changes[ 0 ] {
245276 LedgerEntryChange :: Restored ( LedgerEntry {
246277 data :
247278 LedgerEntryData :: Ttl ( TtlEntry {
@@ -265,8 +296,259 @@ fn parse_changes(changes: &[LedgerEntryChange]) -> Option<u32> {
265296 ..
266297 } ) ,
267298 ..
268- } ) ,
269- ) => Some ( * live_until_ledger_seq) ,
299+ } ) => Some ( * live_until_ledger_seq) ,
300+ _ => None ,
301+ } ,
270302 _ => None ,
271303 }
272304}
305+
306+ #[ cfg( test) ]
307+ mod tests {
308+ use super :: * ;
309+ use crate :: xdr:: { Hash , LedgerEntry , LedgerEntryChange , LedgerEntryData , TtlEntry } ;
310+
311+ #[ test]
312+ fn test_parse_changes_two_changes_restored ( ) {
313+ // Test the original expected format with 2 changes
314+ let ttl_entry = TtlEntry {
315+ live_until_ledger_seq : 12345 ,
316+ key_hash : Hash ( [ 0 ; 32 ] ) ,
317+ } ;
318+
319+ let changes = vec ! [
320+ LedgerEntryChange :: State ( LedgerEntry {
321+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
322+ last_modified_ledger_seq: 0 ,
323+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
324+ } ) ,
325+ LedgerEntryChange :: Restored ( LedgerEntry {
326+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
327+ last_modified_ledger_seq: 0 ,
328+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
329+ } ) ,
330+ ] ;
331+
332+ let result = parse_changes ( & changes) ;
333+ assert_eq ! ( result, Some ( 12345 ) ) ;
334+ }
335+
336+ #[ test]
337+ fn test_parse_changes_two_changes_updated ( ) {
338+ // Test the original expected format with 2 changes, but second change is Updated
339+ let ttl_entry = TtlEntry {
340+ live_until_ledger_seq : 67890 ,
341+ key_hash : Hash ( [ 0 ; 32 ] ) ,
342+ } ;
343+
344+ let changes = vec ! [
345+ LedgerEntryChange :: State ( LedgerEntry {
346+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
347+ last_modified_ledger_seq: 0 ,
348+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
349+ } ) ,
350+ LedgerEntryChange :: Updated ( LedgerEntry {
351+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
352+ last_modified_ledger_seq: 0 ,
353+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
354+ } ) ,
355+ ] ;
356+
357+ let result = parse_changes ( & changes) ;
358+ assert_eq ! ( result, Some ( 67890 ) ) ;
359+ }
360+
361+ #[ test]
362+ fn test_parse_changes_two_changes_created ( ) {
363+ // Test the original expected format with 2 changes, but second change is Created
364+ let ttl_entry = TtlEntry {
365+ live_until_ledger_seq : 11111 ,
366+ key_hash : Hash ( [ 0 ; 32 ] ) ,
367+ } ;
368+
369+ let changes = vec ! [
370+ LedgerEntryChange :: State ( LedgerEntry {
371+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
372+ last_modified_ledger_seq: 0 ,
373+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
374+ } ) ,
375+ LedgerEntryChange :: Created ( LedgerEntry {
376+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
377+ last_modified_ledger_seq: 0 ,
378+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
379+ } ) ,
380+ ] ;
381+
382+ let result = parse_changes ( & changes) ;
383+ assert_eq ! ( result, Some ( 11111 ) ) ;
384+ }
385+
386+ #[ test]
387+ fn test_parse_changes_single_change_restored ( ) {
388+ // Test the new single change format with Restored type
389+ let ttl_entry = TtlEntry {
390+ live_until_ledger_seq : 22222 ,
391+ key_hash : Hash ( [ 0 ; 32 ] ) ,
392+ } ;
393+
394+ let changes = vec ! [ LedgerEntryChange :: Restored ( LedgerEntry {
395+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
396+ last_modified_ledger_seq: 0 ,
397+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
398+ } ) ] ;
399+
400+ let result = parse_changes ( & changes) ;
401+ assert_eq ! ( result, Some ( 22222 ) ) ;
402+ }
403+
404+ #[ test]
405+ fn test_parse_changes_single_change_updated ( ) {
406+ // Test the new single change format with Updated type
407+ let ttl_entry = TtlEntry {
408+ live_until_ledger_seq : 33333 ,
409+ key_hash : Hash ( [ 0 ; 32 ] ) ,
410+ } ;
411+
412+ let changes = vec ! [ LedgerEntryChange :: Updated ( LedgerEntry {
413+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
414+ last_modified_ledger_seq: 0 ,
415+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
416+ } ) ] ;
417+
418+ let result = parse_changes ( & changes) ;
419+ assert_eq ! ( result, Some ( 33333 ) ) ;
420+ }
421+
422+ #[ test]
423+ fn test_parse_changes_single_change_created ( ) {
424+ // Test the new single change format with Created type
425+ let ttl_entry = TtlEntry {
426+ live_until_ledger_seq : 44444 ,
427+ key_hash : Hash ( [ 0 ; 32 ] ) ,
428+ } ;
429+
430+ let changes = vec ! [ LedgerEntryChange :: Created ( LedgerEntry {
431+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
432+ last_modified_ledger_seq: 0 ,
433+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
434+ } ) ] ;
435+
436+ let result = parse_changes ( & changes) ;
437+ assert_eq ! ( result, Some ( 44444 ) ) ;
438+ }
439+
440+ #[ test]
441+ fn test_parse_changes_invalid_two_changes ( ) {
442+ // Test invalid 2-change format (first change is not State)
443+ let ttl_entry = TtlEntry {
444+ live_until_ledger_seq : 55555 ,
445+ key_hash : Hash ( [ 0 ; 32 ] ) ,
446+ } ;
447+
448+ let changes = vec ! [
449+ LedgerEntryChange :: Restored ( LedgerEntry {
450+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
451+ last_modified_ledger_seq: 0 ,
452+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
453+ } ) ,
454+ LedgerEntryChange :: Restored ( LedgerEntry {
455+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
456+ last_modified_ledger_seq: 0 ,
457+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
458+ } ) ,
459+ ] ;
460+
461+ let result = parse_changes ( & changes) ;
462+ assert_eq ! ( result, None ) ;
463+ }
464+
465+ #[ test]
466+ fn test_parse_changes_invalid_single_change ( ) {
467+ // Test invalid single change format (not TTL data)
468+ let changes = vec ! [ LedgerEntryChange :: Restored ( LedgerEntry {
469+ data: LedgerEntryData :: Account ( crate :: xdr:: AccountEntry {
470+ account_id: crate :: xdr:: AccountId ( crate :: xdr:: PublicKey :: PublicKeyTypeEd25519 (
471+ crate :: xdr:: Uint256 ( [ 0 ; 32 ] ) ,
472+ ) ) ,
473+ balance: 0 ,
474+ seq_num: SequenceNumber ( 0 ) ,
475+ num_sub_entries: 0 ,
476+ inflation_dest: None ,
477+ flags: 0 ,
478+ home_domain: crate :: xdr:: String32 :: default ( ) ,
479+ thresholds: crate :: xdr:: Thresholds :: default ( ) ,
480+ signers: crate :: xdr:: VecM :: default ( ) ,
481+ ext: crate :: xdr:: AccountEntryExt :: V0 ,
482+ } ) ,
483+ last_modified_ledger_seq: 0 ,
484+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
485+ } ) ] ;
486+
487+ let result = parse_changes ( & changes) ;
488+ assert_eq ! ( result, None ) ;
489+ }
490+
491+ #[ test]
492+ fn test_parse_changes_empty_changes ( ) {
493+ // Test empty changes array
494+ let changes = vec ! [ ] ;
495+
496+ let result = parse_changes ( & changes) ;
497+ assert_eq ! ( result, None ) ;
498+ }
499+
500+ #[ test]
501+ fn test_parse_changes_three_changes ( ) {
502+ // Test with 3 changes (should return None)
503+ let ttl_entry = TtlEntry {
504+ live_until_ledger_seq : 66666 ,
505+ key_hash : Hash ( [ 0 ; 32 ] ) ,
506+ } ;
507+
508+ let changes = vec ! [
509+ LedgerEntryChange :: State ( LedgerEntry {
510+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
511+ last_modified_ledger_seq: 0 ,
512+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
513+ } ) ,
514+ LedgerEntryChange :: Restored ( LedgerEntry {
515+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
516+ last_modified_ledger_seq: 0 ,
517+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
518+ } ) ,
519+ LedgerEntryChange :: Updated ( LedgerEntry {
520+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
521+ last_modified_ledger_seq: 0 ,
522+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
523+ } ) ,
524+ ] ;
525+
526+ let result = parse_changes ( & changes) ;
527+ assert_eq ! ( result, None ) ;
528+ }
529+
530+ #[ test]
531+ fn test_parse_changes_mixed_invalid_types ( ) {
532+ // Test with mixed valid and invalid change types
533+ let ttl_entry = TtlEntry {
534+ live_until_ledger_seq : 77777 ,
535+ key_hash : Hash ( [ 0 ; 32 ] ) ,
536+ } ;
537+
538+ let changes = vec ! [
539+ LedgerEntryChange :: State ( LedgerEntry {
540+ data: LedgerEntryData :: Ttl ( ttl_entry. clone( ) ) ,
541+ last_modified_ledger_seq: 0 ,
542+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
543+ } ) ,
544+ LedgerEntryChange :: State ( LedgerEntry {
545+ data: LedgerEntryData :: Ttl ( ttl_entry) ,
546+ last_modified_ledger_seq: 0 ,
547+ ext: crate :: xdr:: LedgerEntryExt :: V0 ,
548+ } ) ,
549+ ] ;
550+
551+ let result = parse_changes ( & changes) ;
552+ assert_eq ! ( result, None ) ;
553+ }
554+ }
0 commit comments