@@ -276,7 +276,7 @@ impl ::light_hasher::DataHasher for TruncateOptionStruct {
276
276
#[cfg(debug_assertions)]
277
277
{
278
278
if std::env::var("RUST_BACKTRACE").is_ok() {
279
- let debug_prints: Vec<[u8; 32]> = vec![
279
+ let debug_prints: Vec<[u8;32]> = vec![
280
280
if let Some(a) = & self.a { let result = a.hash_to_field_size() ?; if
281
281
result == [0u8; 32] { return
282
282
Err(::light_hasher::errors::HasherError::OptionHashToFieldSizeZero); }
@@ -560,4 +560,154 @@ impl ::light_hasher::DataHasher for OuterStruct {
560
560
"Should mention SHA256 limitation"
561
561
) ;
562
562
}
563
+
564
+ #[ test]
565
+ fn test_sha256_with_discriminator_integration ( ) {
566
+ // Test that shows LightHasherSha works with LightDiscriminatorSha for large structs
567
+ // This would be impossible with regular Poseidon-based macros
568
+ let input: ItemStruct = parse_quote ! {
569
+ struct LargeIntegratedAccount {
570
+ pub field1: u64 , pub field2: u64 , pub field3: u64 , pub field4: u64 ,
571
+ pub field5: u64 , pub field6: u64 , pub field7: u64 , pub field8: u64 ,
572
+ pub field9: u64 , pub field10: u64 , pub field11: u64 , pub field12: u64 ,
573
+ pub field13: u64 , pub field14: u64 , pub field15: u64 , pub field16: u64 ,
574
+ pub field17: u64 , pub field18: u64 , pub field19: u64 , pub field20: u64 ,
575
+ // Pubkeys without #[hash] attribute
576
+ pub owner: solana_program:: pubkey:: Pubkey ,
577
+ pub authority: solana_program:: pubkey:: Pubkey ,
578
+ pub delegate: solana_program:: pubkey:: Pubkey ,
579
+ }
580
+ } ;
581
+
582
+ // Both SHA256 hasher and discriminator should work
583
+ let sha_hasher_result = derive_light_hasher_sha ( input. clone ( ) ) ;
584
+ assert ! (
585
+ sha_hasher_result. is_ok( ) ,
586
+ "SHA256 hasher should work with large structs"
587
+ ) ;
588
+
589
+ let sha_discriminator_result = crate :: discriminator:: discriminator_sha ( input. clone ( ) ) ;
590
+ assert ! (
591
+ sha_discriminator_result. is_ok( ) ,
592
+ "SHA256 discriminator should work with large structs"
593
+ ) ;
594
+
595
+ // Regular Poseidon variants should fail
596
+ let poseidon_hasher_result = derive_light_hasher ( input) ;
597
+ assert ! (
598
+ poseidon_hasher_result. is_err( ) ,
599
+ "Poseidon hasher should fail with large structs"
600
+ ) ;
601
+
602
+ // Verify the generated code contains expected patterns
603
+ let sha_hasher_code = sha_hasher_result. unwrap ( ) . to_string ( ) ;
604
+ assert ! (
605
+ sha_hasher_code. contains( "try_to_vec" ) ,
606
+ "Should use serialization approach"
607
+ ) ;
608
+ assert ! (
609
+ sha_hasher_code. contains( "BorshSerialize" ) ,
610
+ "Should use Borsh serialization"
611
+ ) ;
612
+
613
+ let sha_discriminator_code = sha_discriminator_result. unwrap ( ) . to_string ( ) ;
614
+ assert ! (
615
+ sha_discriminator_code. contains( "LightDiscriminator" ) ,
616
+ "Should implement LightDiscriminator"
617
+ ) ;
618
+ assert ! (
619
+ sha_discriminator_code. contains( "LIGHT_DISCRIMINATOR" ) ,
620
+ "Should provide discriminator constant"
621
+ ) ;
622
+ }
623
+
624
+ #[ test]
625
+ fn test_complete_sha256_ecosystem_practical_example ( ) {
626
+ // Demonstrates a real-world scenario where SHA256 variants are essential
627
+ // This struct would be impossible with Poseidon due to:
628
+ // 1. >12 fields (23+ fields)
629
+ // 2. Multiple Pubkeys without #[hash] attribute
630
+ // 3. Large data structures
631
+ let input: ItemStruct = parse_quote ! {
632
+ pub struct ComplexGameState {
633
+ // Game metadata (13 fields)
634
+ pub game_id: u64 ,
635
+ pub round: u32 ,
636
+ pub turn: u8 ,
637
+ pub phase: u8 ,
638
+ pub start_time: i64 ,
639
+ pub end_time: i64 ,
640
+ pub max_players: u8 ,
641
+ pub current_players: u8 ,
642
+ pub entry_fee: u64 ,
643
+ pub prize_pool: u64 ,
644
+ pub game_mode: u32 ,
645
+ pub difficulty: u8 ,
646
+ pub status: u8 ,
647
+
648
+ // Player information (6 Pubkey fields - would require #[hash] with Poseidon)
649
+ pub creator: solana_program:: pubkey:: Pubkey ,
650
+ pub winner: solana_program:: pubkey:: Pubkey ,
651
+ pub current_player: solana_program:: pubkey:: Pubkey ,
652
+ pub authority: solana_program:: pubkey:: Pubkey ,
653
+ pub treasury: solana_program:: pubkey:: Pubkey ,
654
+ pub program_id: solana_program:: pubkey:: Pubkey ,
655
+
656
+ // Game state data (4+ more fields)
657
+ pub board_state: [ u8 ; 64 ] , // Large array
658
+ pub player_scores: [ u32 ; 8 ] , // Array of scores
659
+ pub moves_history: [ u16 ; 32 ] , // Move history
660
+ pub special_flags: u32 ,
661
+
662
+ // This gives us 23+ fields total - way beyond Poseidon's 12-field limit
663
+ }
664
+ } ;
665
+
666
+ // SHA256 variants should handle this complex struct effortlessly
667
+ let sha_hasher_result = derive_light_hasher_sha ( input. clone ( ) ) ;
668
+ assert ! (
669
+ sha_hasher_result. is_ok( ) ,
670
+ "SHA256 hasher must handle complex real-world structs"
671
+ ) ;
672
+
673
+ let sha_discriminator_result = crate :: discriminator:: discriminator_sha ( input. clone ( ) ) ;
674
+ assert ! (
675
+ sha_discriminator_result. is_ok( ) ,
676
+ "SHA256 discriminator must handle complex real-world structs"
677
+ ) ;
678
+
679
+ // Poseidon would fail with this struct
680
+ let poseidon_result = derive_light_hasher ( input) ;
681
+ assert ! (
682
+ poseidon_result. is_err( ) ,
683
+ "Poseidon cannot handle structs with >12 fields and unhashed Pubkeys"
684
+ ) ;
685
+
686
+ // Verify SHA256 generates efficient serialization-based code
687
+ let hasher_code = sha_hasher_result. unwrap ( ) . to_string ( ) ;
688
+ assert ! (
689
+ hasher_code. contains( "try_to_vec" ) ,
690
+ "Should serialize entire struct efficiently"
691
+ ) ;
692
+ assert ! (
693
+ hasher_code. contains( "BorshSerialize" ) ,
694
+ "Should use Borsh for serialization"
695
+ ) ;
696
+ assert ! (
697
+ hasher_code. contains( "result [0] = 0" ) || hasher_code. contains( "result[0] = 0" ) ,
698
+ "Should apply field size truncation. Actual code: {}" ,
699
+ hasher_code
700
+ ) ;
701
+
702
+ // Verify discriminator works correctly
703
+ let discriminator_code = sha_discriminator_result. unwrap ( ) . to_string ( ) ;
704
+ assert ! (
705
+ discriminator_code. contains( "ComplexGameState" ) ,
706
+ "Should target correct struct"
707
+ ) ;
708
+ assert ! (
709
+ discriminator_code. contains( "LIGHT_DISCRIMINATOR" ) ,
710
+ "Should provide discriminator constant"
711
+ ) ;
712
+ }
563
713
}
0 commit comments