@@ -109,6 +109,62 @@ impl GovernanceMessage {
109
109
0x50 , 0x75 , 0x72 , 0x70 , 0x6F , 0x73 , 0x65 , 0x47 , 0x6F , 0x76 , 0x65 , 0x72 , 0x6E , 0x61 , 0x6E ,
110
110
0x63 , 0x65 ,
111
111
] ;
112
+
113
+ pub fn read_body < R > ( reader : & mut R , governance_program_id : Pubkey ) -> io:: Result < Self >
114
+ where
115
+ R : io:: Read ,
116
+ {
117
+ let program_id: Pubkey = Pubkey :: new_from_array ( Readable :: read ( reader) ?) ;
118
+ let accounts_len: u16 = Readable :: read ( reader) ?;
119
+ let mut accounts = Vec :: with_capacity ( accounts_len as usize ) ;
120
+ for _ in 0 ..accounts_len {
121
+ let pubkey: [ u8 ; 32 ] = Readable :: read ( reader) ?;
122
+ let is_signer: bool = Readable :: read ( reader) ?;
123
+ let is_writable: bool = Readable :: read ( reader) ?;
124
+ accounts. push ( Acc {
125
+ pubkey : Pubkey :: new_from_array ( pubkey) ,
126
+ is_signer,
127
+ is_writable,
128
+ } ) ;
129
+ }
130
+ let data_len: u16 = Readable :: read ( reader) ?;
131
+ let mut data = vec ! [ 0 ; data_len as usize ] ;
132
+ reader. read_exact ( & mut data) ?;
133
+
134
+ Ok ( GovernanceMessage {
135
+ governance_program_id,
136
+ program_id,
137
+ accounts,
138
+ data,
139
+ } )
140
+ }
141
+
142
+ /// Serialises the governance packet's body. This is the part of the packet
143
+ /// that will be fed into the guardian node (the header part is populated by
144
+ /// the node itself).
145
+ pub fn write_body < W > ( & self , writer : & mut W ) -> io:: Result < ( ) >
146
+ where
147
+ W : io:: Write ,
148
+ {
149
+ let GovernanceMessage {
150
+ governance_program_id : _,
151
+ program_id,
152
+ accounts,
153
+ data,
154
+ } = self ;
155
+
156
+ program_id. to_bytes ( ) . write ( writer) ?;
157
+ u16:: try_from ( accounts. len ( ) )
158
+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: InvalidData , "accounts length overflow" ) ) ?
159
+ . write ( writer) ?;
160
+ for acc in accounts {
161
+ acc. pubkey . to_bytes ( ) . write ( writer) ?;
162
+ acc. is_signer . write ( writer) ?;
163
+ acc. is_writable . write ( writer) ?;
164
+ }
165
+ ( data. len ( ) as u16 ) . write ( writer) ?;
166
+ writer. write_all ( data)
167
+ }
112
168
}
113
169
114
170
#[ test]
@@ -160,31 +216,8 @@ impl Readable for GovernanceMessage {
160
216
"Invalid GovernanceMessage chain" ,
161
217
) ) ;
162
218
}
163
-
164
- let governance_program_id: Pubkey = Pubkey :: new_from_array ( Readable :: read ( reader) ?) ;
165
- let program_id: Pubkey = Pubkey :: new_from_array ( Readable :: read ( reader) ?) ;
166
- let accounts_len: u16 = Readable :: read ( reader) ?;
167
- let mut accounts = Vec :: with_capacity ( accounts_len as usize ) ;
168
- for _ in 0 ..accounts_len {
169
- let pubkey: [ u8 ; 32 ] = Readable :: read ( reader) ?;
170
- let is_signer: bool = Readable :: read ( reader) ?;
171
- let is_writable: bool = Readable :: read ( reader) ?;
172
- accounts. push ( Acc {
173
- pubkey : Pubkey :: new_from_array ( pubkey) ,
174
- is_signer,
175
- is_writable,
176
- } ) ;
177
- }
178
- let data_len: u16 = Readable :: read ( reader) ?;
179
- let mut data = vec ! [ 0 ; data_len as usize ] ;
180
- reader. read_exact ( & mut data) ?;
181
-
182
- Ok ( GovernanceMessage {
183
- governance_program_id,
184
- program_id,
185
- accounts,
186
- data,
187
- } )
219
+ let governance_program_id = Pubkey :: new_from_array ( Readable :: read ( reader) ?) ;
220
+ Self :: read_body ( reader, governance_program_id)
188
221
}
189
222
}
190
223
@@ -205,26 +238,11 @@ impl Writeable for GovernanceMessage {
205
238
where
206
239
W : io:: Write ,
207
240
{
208
- let GovernanceMessage {
209
- governance_program_id,
210
- program_id,
211
- accounts,
212
- data,
213
- } = self ;
214
-
215
241
Self :: MODULE . write ( writer) ?;
216
242
GovernanceAction :: SolanaCall . write ( writer) ?;
217
243
u16:: from ( Chain :: Solana ) . write ( writer) ?;
218
- governance_program_id. to_bytes ( ) . write ( writer) ?;
219
- program_id. to_bytes ( ) . write ( writer) ?;
220
- ( accounts. len ( ) as u16 ) . write ( writer) ?;
221
- for acc in accounts {
222
- acc. pubkey . to_bytes ( ) . write ( writer) ?;
223
- acc. is_signer . write ( writer) ?;
224
- acc. is_writable . write ( writer) ?;
225
- }
226
- ( data. len ( ) as u16 ) . write ( writer) ?;
227
- writer. write_all ( data)
244
+ self . governance_program_id . to_bytes ( ) . write ( writer) ?;
245
+ self . write_body ( writer)
228
246
}
229
247
}
230
248
@@ -258,6 +276,49 @@ fn test_governance_message_serde() {
258
276
assert_eq ! ( msg, msg2) ;
259
277
}
260
278
279
+ #[ test]
280
+ fn test_governance_message_parse_guardian ( ) {
281
+ // hex dumped from guardian node with the following protoxt:
282
+ // ```
283
+ // current_set_index: 4
284
+ // # generic solana call
285
+ // messages: {
286
+ // sequence: 4513077582118919631
287
+ // nonce: 2809988562
288
+ // solana_call: {
289
+ // chain_id: 1
290
+ // governance_contract: "wgvEiKVzX9yyEoh41jZAdC6JqGUTS4CFXbFGBV5TKdZ"
291
+ // encoded_instruction: "00000000000000010000000000000000000000000000000000000000000000000002000000000000000200000000000000000000000000000000000000000000000001010000000000000003000000000000000000000000000000000000000000000000000100050102030405"
292
+ // }
293
+ // }
294
+ // ```
295
+ // TODO: once this program is moved into the monorepo, do an e2e integration test
296
+ let h = hex:: decode ( "000000000000000047656e6572616c507572706f7365476f7665726e616e63650200010e027fbc6b1e61365d4b0680a3179f791b15796f93e24e9b441e3fa04ccda4a000000000000000010000000000000000000000000000000000000000000000000002000000000000000200000000000000000000000000000000000000000000000001010000000000000003000000000000000000000000000000000000000000000000000100050102030405" ) . unwrap ( ) ;
297
+ let actual = GovernanceMessage :: deserialize ( & mut h. as_slice ( ) ) . unwrap ( ) ;
298
+
299
+ let accounts = vec ! [
300
+ Acc {
301
+ pubkey: Pubkey :: try_from( "1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh" ) . unwrap( ) ,
302
+ is_signer: true ,
303
+ is_writable: true ,
304
+ } ,
305
+ Acc {
306
+ pubkey: Pubkey :: try_from( "11111112D1oxKts8YPdTJRG5FzxTNpMtWmq8hkVx3" ) . unwrap( ) ,
307
+ is_signer: false ,
308
+ is_writable: true ,
309
+ } ,
310
+ ] ;
311
+ let data = vec ! [ 1 , 2 , 3 , 4 , 5 ] ;
312
+ let expected = GovernanceMessage {
313
+ governance_program_id : crate :: ID ,
314
+ program_id : Pubkey :: try_from ( "1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM" ) . unwrap ( ) ,
315
+ accounts,
316
+ data,
317
+ } ;
318
+
319
+ assert_eq ! ( actual, expected)
320
+ }
321
+
261
322
#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
262
323
/// The known set of governance actions.
263
324
///
@@ -285,12 +346,12 @@ impl Readable for GovernanceAction {
285
346
R : io:: Read ,
286
347
{
287
348
match Readable :: read ( reader) ? {
288
- 0 => Ok ( GovernanceAction :: Undefined ) ,
349
+ 0u8 => Ok ( GovernanceAction :: Undefined ) ,
289
350
1 => Ok ( GovernanceAction :: EvmCall ) ,
290
351
2 => Ok ( GovernanceAction :: SolanaCall ) ,
291
- _ => Err ( io:: Error :: new (
352
+ n => Err ( io:: Error :: new (
292
353
io:: ErrorKind :: InvalidData ,
293
- "Invalid GovernanceAction" ,
354
+ format ! ( "invalid action {}" , n ) ,
294
355
) ) ,
295
356
}
296
357
}
@@ -307,8 +368,8 @@ impl Writeable for GovernanceAction {
307
368
{
308
369
match self {
309
370
GovernanceAction :: Undefined => Ok ( ( ) ) ,
310
- GovernanceAction :: EvmCall => 1 . write ( writer) ,
311
- GovernanceAction :: SolanaCall => 2 . write ( writer) ,
371
+ GovernanceAction :: EvmCall => 1u8 . write ( writer) ,
372
+ GovernanceAction :: SolanaCall => 2u8 . write ( writer) ,
312
373
}
313
374
}
314
375
}
0 commit comments