@@ -48,8 +48,8 @@ const PROOF_ON_CHAIN: u8 = 3;
4848pub use super :: affinity:: AffinityFilter ;
4949
5050#[ derive( Debug , Clone ) ]
51- pub enum StatementMessage < ' a > {
52- Statements ( Vec < & ' a [ u8 ] > ) ,
51+ pub enum StatementMessage {
52+ Statements ( Vec < ( [ u8 ; 32 ] , Statement ) > ) ,
5353 ExplicitTopicAffinity ( AffinityFilter ) ,
5454}
5555
@@ -210,14 +210,15 @@ const V2_TAG_AFFINITY: u8 = 0x01;
210210
211211pub fn decode_statement_message (
212212 bytes : & [ u8 ] ,
213- ) -> Result < StatementMessage < ' _ > , DecodeStatementMessageError > {
213+ ) -> Result < StatementMessage , DecodeStatementMessageError > {
214214 if bytes. is_empty ( ) {
215215 return Err ( DecodeStatementMessageError :: Empty ) ;
216216 }
217217
218218 match bytes[ 0 ] {
219219 V2_TAG_STATEMENTS => {
220- let stmts = extract_statement_bytes ( & bytes[ 1 ..] ) ?;
220+ let stmts = decode_statement_notification ( & bytes[ 1 ..] )
221+ . map_err ( DecodeStatementMessageError :: InvalidStatements ) ?;
221222 Ok ( StatementMessage :: Statements ( stmts) )
222223 }
223224 V2_TAG_AFFINITY => {
@@ -230,67 +231,27 @@ pub fn decode_statement_message(
230231}
231232
232233pub fn encode_statements_message ( statements : & [ & [ u8 ] ] ) -> Vec < u8 > {
234+ let tag_len = 1 ;
235+ let max_compact_len = 5 ;
233236 let total_len: usize = statements. iter ( ) . map ( |s| s. len ( ) ) . sum ( ) ;
234- let mut out = Vec :: with_capacity ( 1 + 5 + total_len) ;
237+ let mut out = Vec :: with_capacity ( tag_len + max_compact_len + total_len) ;
235238 out. push ( V2_TAG_STATEMENTS ) ;
236239 out. extend_from_slice ( crate :: util:: encode_scale_compact_usize ( statements. len ( ) ) . as_ref ( ) ) ;
237240 for stmt in statements {
238- out. extend_from_slice ( crate :: util:: encode_scale_compact_usize ( stmt. len ( ) ) . as_ref ( ) ) ;
239241 out. extend_from_slice ( stmt) ;
240242 }
241243 out
242244}
243245
244246pub fn encode_topic_affinity_message ( filter : & AffinityFilter ) -> Vec < u8 > {
247+ let tag_len = 1 ;
245248 let encoded = filter. encode_to_vec ( ) ;
246- let mut out = Vec :: with_capacity ( 1 + encoded. len ( ) ) ;
249+ let mut out = Vec :: with_capacity ( tag_len + encoded. len ( ) ) ;
247250 out. push ( V2_TAG_AFFINITY ) ;
248251 out. extend_from_slice ( & encoded) ;
249252 out
250253}
251254
252- fn extract_statement_bytes ( data : & [ u8 ] ) -> Result < Vec < & [ u8 ] > , DecodeStatementMessageError > {
253- let ( mut remaining, count) =
254- crate :: util:: nom_scale_compact_usize :: < nom:: error:: Error < & [ u8 ] > > ( data) . map_err ( |_| {
255- DecodeStatementMessageError :: InvalidStatements ( DecodeStatementNotificationError (
256- nom:: error:: ErrorKind :: Fail ,
257- ) )
258- } ) ?;
259-
260- if count > MAX_STATEMENTS_PER_NOTIFICATION {
261- return Err ( DecodeStatementMessageError :: InvalidStatements (
262- DecodeStatementNotificationError ( nom:: error:: ErrorKind :: TooLarge ) ,
263- ) ) ;
264- }
265-
266- let mut statements = Vec :: with_capacity ( count) ;
267- for _ in 0 ..count {
268- let ( rest, len) = crate :: util:: nom_scale_compact_usize :: < nom:: error:: Error < & [ u8 ] > > (
269- remaining,
270- )
271- . map_err ( |_| {
272- DecodeStatementMessageError :: InvalidStatements ( DecodeStatementNotificationError (
273- nom:: error:: ErrorKind :: Fail ,
274- ) )
275- } ) ?;
276- if rest. len ( ) < len {
277- return Err ( DecodeStatementMessageError :: InvalidStatements (
278- DecodeStatementNotificationError ( nom:: error:: ErrorKind :: Eof ) ,
279- ) ) ;
280- }
281- statements. push ( & rest[ ..len] ) ;
282- remaining = & rest[ len..] ;
283- }
284-
285- if !remaining. is_empty ( ) {
286- return Err ( DecodeStatementMessageError :: InvalidStatements (
287- DecodeStatementNotificationError ( nom:: error:: ErrorKind :: NonEmpty ) ,
288- ) ) ;
289- }
290-
291- Ok ( statements)
292- }
293-
294255#[ derive( Debug , derive_more:: Display , derive_more:: Error , Clone ) ]
295256pub enum DecodeStatementMessageError {
296257 #[ display( "Empty V2 statement message" ) ]
@@ -751,15 +712,56 @@ mod tests {
751712 match decoded {
752713 StatementMessage :: Statements ( stmts) => {
753714 assert_eq ! ( stmts. len( ) , 2 ) ;
754- assert_eq ! ( stmts[ 0 ] , encoded1 . as_slice ( ) ) ;
755- assert_eq ! ( stmts[ 1 ] , encoded2 . as_slice ( ) ) ;
715+ assert_eq ! ( stmts[ 0 ] . 1 , statement1 ) ;
716+ assert_eq ! ( stmts[ 1 ] . 1 , statement2 ) ;
756717 }
757718 _ => panic ! ( "Expected Statements variant" ) ,
758719 }
759720 }
760721
761722 #[ test]
762- fn v2_affinity_roundtrip ( ) {
723+ fn v2_statements_encoding_snapshot ( ) {
724+ let statement = Statement {
725+ proof : Some ( Proof :: OnChain {
726+ who : [ 42u8 ; 32 ] ,
727+ block_hash : [ 24u8 ; 32 ] ,
728+ event_index : 66 ,
729+ } ) ,
730+ decryption_key : Some ( [ 0xde ; 32 ] ) ,
731+ expiry : 999 ,
732+ channel : Some ( [ 0xcc ; 32 ] ) ,
733+ topics : vec ! [ [ 0x01 ; 32 ] , [ 0x02 ; 32 ] ] ,
734+ data : Some ( vec ! [ 55 , 99 ] ) ,
735+ } ;
736+
737+ let stmt_bytes = encode_statement ( & statement) . unwrap ( ) ;
738+ let v2_encoded = encode_statements_message ( & [ & stmt_bytes] ) ;
739+
740+ let digest: [ u8 ; 32 ] = blake2_rfc:: blake2b:: blake2b ( 32 , & [ ] , & v2_encoded)
741+ . as_bytes ( )
742+ . try_into ( )
743+ . unwrap ( ) ;
744+ assert_eq ! (
745+ digest,
746+ [
747+ 44 , 71 , 235 , 73 , 238 , 115 , 6 , 15 , 128 , 174 , 159 , 216 , 166 , 76 , 26 , 101 , 28 , 143 ,
748+ 88 , 21 , 22 , 128 , 169 , 62 , 180 , 19 , 164 , 234 , 174 , 210 , 81 , 105
749+ ] ,
750+ "blake2_256 digest must match polkadot-sdk snapshot"
751+ ) ;
752+
753+ let decoded = decode_statement_message ( & v2_encoded) . unwrap ( ) ;
754+ match decoded {
755+ StatementMessage :: Statements ( stmts) => {
756+ assert_eq ! ( stmts. len( ) , 1 ) ;
757+ assert_eq ! ( stmts[ 0 ] . 1 , statement) ;
758+ }
759+ _ => panic ! ( "Expected Statements variant" ) ,
760+ }
761+ }
762+
763+ #[ test]
764+ fn v2_affinity_encoding_snapshot ( ) {
763765 let topic1 = [ 0x01u8 ; 32 ] ;
764766 let topic2 = [ 0x02u8 ; 32 ] ;
765767 let topic3 = [ 0x03u8 ; 32 ] ;
@@ -769,8 +771,21 @@ mod tests {
769771 filter. insert ( & topic2) ;
770772
771773 let encoded = encode_topic_affinity_message ( & filter) ;
772- let decoded = decode_statement_message ( & encoded) . unwrap ( ) ;
773774
775+ let digest: [ u8 ; 32 ] = blake2_rfc:: blake2b:: blake2b ( 32 , & [ ] , & encoded)
776+ . as_bytes ( )
777+ . try_into ( )
778+ . unwrap ( ) ;
779+ assert_eq ! (
780+ digest,
781+ [
782+ 82 , 59 , 251 , 163 , 43 , 156 , 130 , 249 , 35 , 214 , 187 , 99 , 4 , 105 , 179 , 131 , 42 , 117 ,
783+ 191 , 57 , 160 , 243 , 233 , 20 , 204 , 239 , 62 , 120 , 55 , 5 , 234 , 62
784+ ] ,
785+ "blake2_256 digest must match polkadot-sdk snapshot"
786+ ) ;
787+
788+ let decoded = decode_statement_message ( & encoded) . unwrap ( ) ;
774789 let StatementMessage :: ExplicitTopicAffinity ( af) = decoded else {
775790 panic ! ( "Expected ExplicitTopicAffinity variant" ) ;
776791 } ;
0 commit comments