11use serde:: { Deserialize , Serialize } ;
22use sha2:: { Digest , Sha256 } ;
33use std:: { collections:: BTreeMap , fmt:: Display } ;
4+
5+ #[ cfg( feature = "future_snark" ) ]
46use thiserror:: Error ;
57
68#[ cfg( test) ]
79use crate :: entities:: Epoch ;
810
911/// Error returned by [ProtocolMessage::check_rigid_integrity] when a rigid-segment value
1012/// in a [ProtocolMessage] does not match the fixed-size SNARK-friendly slot it must fill.
13+ #[ cfg( feature = "future_snark" ) ]
1114#[ derive( Debug , Error , PartialEq , Eq ) ]
1215pub enum RigidProtocolMessageIntegrityError {
1316 /// The decoded value of a fixed-size rigid field does not match the expected byte length.
@@ -87,42 +90,52 @@ fn decode_protocol_parameters_to_rigid_slot_bytes(
8790
8891/// [ProtocolMessagePartKey] entries projected into a fixed-size segment of the rigid preimage,
8992/// and therefore stripped from the dynamic-parts digest segment.
93+ #[ cfg( feature = "future_snark" ) ]
9094const RIGID_SEGMENT_KEYS : & [ ProtocolMessagePartKey ] = & [
9195 ProtocolMessagePartKey :: NextSnarkAggregateVerificationKey ,
9296 ProtocolMessagePartKey :: NextProtocolParameters ,
9397 ProtocolMessagePartKey :: CurrentEpoch ,
9498] ;
9599
96- /// Byte length of the `digest` value segment in the rigid preimage.
100+ /// Byte length of the `digest` value segment in the rigid preimage. Kept ungated because the
101+ /// legacy hash path also uses it as the SHA-256 output buffer width.
97102pub const RIGID_DIGEST_BYTES : usize = 32 ;
98103
99104/// Byte length of the `next_aggregate_verification_key` value segment in the rigid preimage.
100105///
101106/// The slot holds the SNARK-friendly aggregate verification key bytes (the value sourced from
102107/// [ProtocolMessagePartKey::NextSnarkAggregateVerificationKey]).
108+ #[ cfg( feature = "future_snark" ) ]
103109pub const RIGID_NEXT_AGGREGATE_VERIFICATION_KEY_BYTES : usize = 44 ;
104110
105111/// Byte length of the `next_protocol_parameters` value segment in the rigid preimage.
112+ #[ cfg( feature = "future_snark" ) ]
106113pub const RIGID_NEXT_PROTOCOL_PARAMETERS_BYTES : usize = 32 ;
107114
108115/// Byte length of the `current_epoch` value segment in the rigid preimage.
116+ #[ cfg( feature = "future_snark" ) ]
109117pub const RIGID_CURRENT_EPOCH_BYTES : usize = 8 ;
110118
111119/// ASCII label written immediately before the `digest` value segment in the rigid preimage.
120+ #[ cfg( feature = "future_snark" ) ]
112121const RIGID_DIGEST_LABEL : & [ u8 ] = b"digest" ;
113122
114123/// ASCII label written immediately before the `next_aggregate_verification_key` value segment in the rigid preimage.
124+ #[ cfg( feature = "future_snark" ) ]
115125const RIGID_NEXT_AGGREGATE_VERIFICATION_KEY_LABEL : & [ u8 ] = b"next_aggregate_verification_key" ;
116126
117127/// ASCII label written immediately before the `next_protocol_parameters` value segment in the rigid preimage.
128+ #[ cfg( feature = "future_snark" ) ]
118129const RIGID_NEXT_PROTOCOL_PARAMETERS_LABEL : & [ u8 ] = b"next_protocol_parameters" ;
119130
120131/// ASCII label written immediately before the `current_epoch` value segment in the rigid preimage.
132+ #[ cfg( feature = "future_snark" ) ]
121133const RIGID_CURRENT_EPOCH_LABEL : & [ u8 ] = b"current_epoch" ;
122134
123135/// Byte length of the full rigid preimage that [ProtocolMessage::rigid_preimage] assembles when
124136/// the hash scheme is [ProtocolMessageHashScheme::Rigid]. Each named segment is prefixed by its ASCII
125137/// label, mirroring the layout consumed by the IVC SNARK gadget.
138+ #[ cfg( feature = "future_snark" ) ]
126139const RIGID_PROTOCOL_MESSAGE_PREIMAGE_BYTES : usize = RIGID_DIGEST_LABEL . len ( )
127140 + RIGID_DIGEST_BYTES
128141 + RIGID_NEXT_AGGREGATE_VERIFICATION_KEY_LABEL . len ( )
@@ -143,6 +156,7 @@ pub enum ProtocolMessageHashScheme {
143156 Legacy ,
144157
145158 /// Lagrange SNARK-friendly hash scheme.
159+ #[ cfg( feature = "future_snark" ) ]
146160 #[ serde( rename = "rigid" ) ]
147161 Rigid ,
148162}
@@ -267,6 +281,7 @@ impl ProtocolMessage {
267281
268282 /// [ProtocolMessage] factory returning the rigid (Lagrange) [ProtocolMessageHashScheme::Rigid]
269283 /// variant.
284+ #[ cfg( feature = "future_snark" ) ]
270285 pub fn new_rigid ( ) -> ProtocolMessage {
271286 ProtocolMessage {
272287 message_parts : BTreeMap :: new ( ) ,
@@ -293,20 +308,17 @@ impl ProtocolMessage {
293308 self . message_parts . get ( key)
294309 }
295310
296- /// Return `true` if the protocol message uses the [ProtocolMessageHashScheme::Rigid] hash
297- /// scheme.
311+ /// Return `true` if the protocol message uses the rigid hash scheme.
298312 pub fn is_rigid ( & self ) -> bool {
299- matches ! ( self . hash_scheme, ProtocolMessageHashScheme :: Rigid )
313+ ! matches ! ( self . hash_scheme, ProtocolMessageHashScheme :: Legacy )
300314 }
301315
302- /// Compute the hex-encoded SHA-256 hash of the protocol message.
303- ///
304- /// Dispatches over [ProtocolMessage::hash_scheme]: the legacy scheme keeps the pre-Lagrange
305- /// byte-identical output, the rigid scheme hashes the SNARK-friendly
306- /// [rigid_preimage](ProtocolMessage::rigid_preimage).
316+ /// Compute the hex-encoded SHA-256 hash of the protocol message, dispatching over
317+ /// [ProtocolMessage::hash_scheme].
307318 pub fn compute_hash ( & self ) -> String {
308319 match self . hash_scheme {
309320 ProtocolMessageHashScheme :: Legacy => self . compute_legacy_hash ( ) ,
321+ #[ cfg( feature = "future_snark" ) ]
310322 ProtocolMessageHashScheme :: Rigid => self . compute_rigid_hash ( ) ,
311323 }
312324 }
@@ -324,6 +336,7 @@ impl ProtocolMessage {
324336 hex:: encode ( self . compute_legacy_digest_bytes ( ) )
325337 }
326338
339+ #[ cfg( feature = "future_snark" ) ]
327340 fn compute_rigid_hash ( & self ) -> String {
328341 hex:: encode ( Sha256 :: digest ( self . rigid_preimage ( ) ) )
329342 }
@@ -332,6 +345,7 @@ impl ProtocolMessage {
332345 /// `"digest" || digest_value || "next_aggregate_verification_key" || avk_value
333346 /// || "next_protocol_parameters" || protocol_parameters_value
334347 /// || "current_epoch" || current_epoch_value`.
348+ #[ cfg( feature = "future_snark" ) ]
335349 pub fn rigid_preimage ( & self ) -> Vec < u8 > {
336350 let mut preimage = Vec :: with_capacity ( RIGID_PROTOCOL_MESSAGE_PREIMAGE_BYTES ) ;
337351 preimage. extend_from_slice ( RIGID_DIGEST_LABEL ) ;
@@ -421,6 +435,7 @@ impl ProtocolMessage {
421435 /// strict check is bypassed, the verifier recomputes a preimage that does not match the
422436 /// signed bytes and the signature-vs-message check fails as a `match_message` mismatch
423437 /// instead of a typed error.
438+ #[ cfg( feature = "future_snark" ) ]
424439 fn rigid_next_aggregate_verification_key_field (
425440 & self ,
426441 ) -> [ u8 ; RIGID_NEXT_AGGREGATE_VERIFICATION_KEY_BYTES ] {
@@ -702,6 +717,7 @@ mod tests {
702717 protocol_message
703718 }
704719
720+ #[ cfg( feature = "future_snark" ) ]
705721 fn build_rigid_protocol_message_reference ( ) -> ProtocolMessage {
706722 let mut message = ProtocolMessage :: new_rigid ( ) ;
707723 message. set_message_part (
@@ -735,6 +751,7 @@ mod tests {
735751 ) ;
736752 }
737753
754+ #[ cfg( feature = "future_snark" ) ]
738755 #[ test]
739756 fn new_rigid_returns_a_message_with_rigid_hash_scheme ( ) {
740757 let protocol_message = ProtocolMessage :: new_rigid ( ) ;
@@ -746,6 +763,7 @@ mod tests {
746763 ) ;
747764 }
748765
766+ #[ cfg( feature = "future_snark" ) ]
749767 #[ test]
750768 fn set_message_part_works_same_on_every_hash_scheme ( ) {
751769 let mut legacy = ProtocolMessage :: new ( ) ;
@@ -764,6 +782,7 @@ mod tests {
764782 ) ;
765783 }
766784
785+ #[ cfg( feature = "future_snark" ) ]
767786 #[ test]
768787 fn legacy_and_rigid_compute_hash_outputs_do_not_collide_on_same_map ( ) {
769788 let mut legacy = build_protocol_message_reference ( ) ;
@@ -775,6 +794,7 @@ mod tests {
775794 assert_eq ! ( legacy. compute_hash( ) , rigid. compute_hash( ) ) ;
776795 }
777796
797+ #[ cfg( feature = "future_snark" ) ]
778798 #[ test]
779799 fn rigid_compute_hash_produces_a_hex_encoded_32_bytes_digest ( ) {
780800 let rigid = build_rigid_protocol_message_reference ( ) ;
@@ -786,6 +806,7 @@ mod tests {
786806 assert_eq ! ( decoded. len( ) , 32 ) ;
787807 }
788808
809+ #[ cfg( feature = "future_snark" ) ]
789810 #[ test]
790811 fn rigid_preimage_has_expected_fixed_byte_length ( ) {
791812 let rigid = ProtocolMessage :: new_rigid ( ) ;
@@ -795,6 +816,7 @@ mod tests {
795816 assert_eq ! ( preimage. len( ) , RIGID_PROTOCOL_MESSAGE_PREIMAGE_BYTES ) ;
796817 }
797818
819+ #[ cfg( feature = "future_snark" ) ]
798820 #[ test]
799821 fn rigid_preimage_concatenates_labeled_segments_in_a_fixed_order ( ) {
800822 let rigid = build_rigid_protocol_message_reference ( ) ;
@@ -812,6 +834,7 @@ mod tests {
812834 assert_eq ! ( rigid. rigid_preimage( ) , expected) ;
813835 }
814836
837+ #[ cfg( feature = "future_snark" ) ]
815838 #[ test]
816839 fn rigid_preimage_layout_pins_label_offsets_and_segment_lengths ( ) {
817840 let rigid = build_rigid_protocol_message_reference ( ) ;
@@ -884,6 +907,7 @@ mod tests {
884907 ) ;
885908 }
886909
910+ #[ cfg( feature = "future_snark" ) ]
887911 #[ test]
888912 fn rigid_preimage_total_byte_length_is_pinned_to_one_hundred_ninety ( ) {
889913 let rigid = build_rigid_protocol_message_reference ( ) ;
@@ -895,6 +919,7 @@ mod tests {
895919 ) ;
896920 }
897921
922+ #[ cfg( feature = "future_snark" ) ]
898923 #[ test]
899924 fn rigid_preimage_sources_aggregate_verification_key_segment_from_snark_avk_value ( ) {
900925 let mut message = ProtocolMessage :: new_rigid ( ) ;
@@ -922,6 +947,7 @@ mod tests {
922947 assert_eq ! ( restored. hash_scheme, ProtocolMessageHashScheme :: Legacy ) ;
923948 }
924949
950+ #[ cfg( feature = "future_snark" ) ]
925951 #[ test]
926952 fn serde_round_trips_rigid_shape ( ) {
927953 let protocol_message = build_rigid_protocol_message_reference ( ) ;
@@ -952,6 +978,7 @@ mod tests {
952978 ) ;
953979 }
954980
981+ #[ cfg( feature = "future_snark" ) ]
955982 #[ test]
956983 fn rigid_wire_shape_exposes_hash_scheme_discriminator ( ) {
957984 let protocol_message = build_rigid_protocol_message_reference ( ) ;
@@ -1012,6 +1039,7 @@ mod tests {
10121039 ) ;
10131040 }
10141041
1042+ #[ cfg( feature = "future_snark" ) ]
10151043 #[ test]
10161044 fn rigid_next_protocol_parameters_field_holds_raw_hex_decoded_bytes ( ) {
10171045 let mut message = ProtocolMessage :: new_rigid ( ) ;
@@ -1024,6 +1052,7 @@ mod tests {
10241052 assert_eq ! ( message. rigid_next_protocol_parameters_field( ) , raw) ;
10251053 }
10261054
1055+ #[ cfg( feature = "future_snark" ) ]
10271056 #[ test]
10281057 fn rigid_current_epoch_field_is_little_endian_encoded_parsed_integer ( ) {
10291058 let mut message = ProtocolMessage :: new_rigid ( ) ;
@@ -1032,6 +1061,7 @@ mod tests {
10321061 assert_eq ! ( message. rigid_current_epoch_field( ) , 7u64 . to_le_bytes( ) ) ;
10331062 }
10341063
1064+ #[ cfg( feature = "future_snark" ) ]
10351065 #[ test]
10361066 fn stripped_for_rigid_digest_drops_only_rigid_segment_keys_and_forces_legacy_hash_scheme ( ) {
10371067 let mut rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1056,6 +1086,7 @@ mod tests {
10561086 ) ;
10571087 }
10581088
1089+ #[ cfg( feature = "future_snark" ) ]
10591090 #[ test]
10601091 fn rigid_digest_field_is_invariant_under_changes_of_rigid_segment_keys ( ) {
10611092 let mut base = build_rigid_protocol_message_reference ( ) ;
@@ -1072,6 +1103,7 @@ mod tests {
10721103 ) ;
10731104 }
10741105
1106+ #[ cfg( feature = "future_snark" ) ]
10751107 #[ test]
10761108 fn rigid_compute_hash_changes_when_digest_related_parts_change ( ) {
10771109 let mut base = build_rigid_protocol_message_reference ( ) ;
@@ -1109,6 +1141,7 @@ mod tests {
11091141 assert_eq ! ( message. get_current_epoch( ) , None ) ;
11101142 }
11111143
1144+ #[ cfg( feature = "future_snark" ) ]
11121145 #[ test]
11131146 fn rigid_preimage_is_byte_identical_to_a_hand_built_labeled_concatenation ( ) {
11141147 let snark_avk_bytes = [ 5u8 ; RIGID_NEXT_AGGREGATE_VERIFICATION_KEY_BYTES ] ;
@@ -1150,6 +1183,7 @@ mod tests {
11501183 ) ;
11511184 }
11521185
1186+ #[ cfg( feature = "future_snark" ) ]
11531187 #[ test]
11541188 fn check_rigid_integrity_is_a_no_op_for_legacy_protocol_messages ( ) {
11551189 let legacy = build_protocol_message_reference ( ) ;
@@ -1159,6 +1193,7 @@ mod tests {
11591193 . expect ( "legacy protocol message must skip the rigid layout check" ) ;
11601194 }
11611195
1196+ #[ cfg( feature = "future_snark" ) ]
11621197 #[ test]
11631198 fn check_rigid_integrity_succeeds_on_a_well_formed_rigid_protocol_message ( ) {
11641199 let rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1168,6 +1203,7 @@ mod tests {
11681203 . expect ( "a well-formed rigid protocol message must pass the integrity check" ) ;
11691204 }
11701205
1206+ #[ cfg( feature = "future_snark" ) ]
11711207 #[ test]
11721208 fn check_rigid_integrity_allows_an_empty_dynamic_digest_projection ( ) {
11731209 let mut rigid = ProtocolMessage :: new_rigid ( ) ;
@@ -1186,6 +1222,7 @@ mod tests {
11861222 . expect ( "an empty dynamic-parts projection must be accepted" ) ;
11871223 }
11881224
1225+ #[ cfg( feature = "future_snark" ) ]
11891226 #[ test]
11901227 fn check_rigid_integrity_fails_when_next_snark_avk_entry_is_missing ( ) {
11911228 let mut rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1203,6 +1240,7 @@ mod tests {
12031240 ) ;
12041241 }
12051242
1243+ #[ cfg( feature = "future_snark" ) ]
12061244 #[ test]
12071245 fn check_rigid_integrity_fails_when_next_snark_avk_decodes_to_unexpected_length ( ) {
12081246 let mut rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1225,6 +1263,7 @@ mod tests {
12251263 ) ;
12261264 }
12271265
1266+ #[ cfg( feature = "future_snark" ) ]
12281267 #[ test]
12291268 fn check_rigid_integrity_fails_when_next_protocol_parameters_entry_is_missing ( ) {
12301269 let mut rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1242,6 +1281,7 @@ mod tests {
12421281 ) ;
12431282 }
12441283
1284+ #[ cfg( feature = "future_snark" ) ]
12451285 #[ test]
12461286 fn check_rigid_integrity_fails_when_next_protocol_parameters_decodes_to_unexpected_length ( ) {
12471287 let mut rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1264,6 +1304,7 @@ mod tests {
12641304 ) ;
12651305 }
12661306
1307+ #[ cfg( feature = "future_snark" ) ]
12671308 #[ test]
12681309 fn check_rigid_integrity_fails_when_current_epoch_entry_is_missing ( ) {
12691310 let mut rigid = build_rigid_protocol_message_reference ( ) ;
@@ -1279,6 +1320,7 @@ mod tests {
12791320 ) ;
12801321 }
12811322
1323+ #[ cfg( feature = "future_snark" ) ]
12821324 #[ test]
12831325 fn check_rigid_integrity_fails_when_current_epoch_is_not_a_decimal_unsigned_integer ( ) {
12841326 let mut rigid = build_rigid_protocol_message_reference ( ) ;
0 commit comments