1
1
//! Plutus data types for permissioned candidates.
2
2
use cardano_serialization_lib:: { BigNum , PlutusData , PlutusList } ;
3
3
use sidechain_domain:: * ;
4
+ use sp_core:: crypto:: key_types:: { AURA , GRANDPA } ;
4
5
5
6
use crate :: {
6
7
DataDecodingError , DecodingResult , VersionedDatum , VersionedDatumWithLegacy ,
@@ -32,16 +33,15 @@ impl From<PermissionedCandidateDatumV1> for PermissionedCandidateData {
32
33
// with T: OpaqueKeys, this function will be re-implemented.
33
34
fn from ( value : PermissionedCandidateDatumV1 ) -> Self {
34
35
let PermissionedCandidateDatumV1 { partner_chains_key, keys } = value;
35
- let sidechain_public_key = SidechainPublicKey ( partner_chains_key. bytes ) ;
36
- PermissionedCandidateData { sidechain_public_key, keys }
36
+ PermissionedCandidateData { sidechain_public_key : partner_chains_key, keys }
37
37
}
38
38
}
39
39
40
40
#[ derive( Clone , Debug , PartialEq ) ]
41
41
/// Datum representing a permissioned candidate with arbitrary set of keys
42
42
pub struct PermissionedCandidateDatumV1 {
43
43
/// Partner Chains key identifier and bytes
44
- pub partner_chains_key : CandidateKey ,
44
+ pub partner_chains_key : SidechainPublicKey ,
45
45
/// Represents arbitrary set of keys with 4 character identifier
46
46
pub keys : CandidateKeys ,
47
47
}
@@ -75,10 +75,11 @@ impl From<PermissionedCandidateDatums> for Vec<PermissionedCandidateData> {
75
75
}
76
76
77
77
/// Converts a list of [PermissionedCandidateData] values to [VersionedGenericDatum] encoded as [PlutusData].
78
- ///
78
+ /// Version 0 is used for specific set of Partner Chains Key: partner chains key, AURA, Grandpa
79
+ /// If other set of key is used, then version 1 is used.
79
80
/// Encoding:
80
81
/// VersionedGenericDatum:
81
- /// - datum: ()
82
+ /// - datum: Constr 0 []
82
83
/// - appendix:
83
84
/// [
84
85
/// [ candidates[0].sidechain_public_key
@@ -93,30 +94,94 @@ impl From<PermissionedCandidateDatums> for Vec<PermissionedCandidateData> {
93
94
/// // etc.
94
95
/// ]
95
96
/// - version: 0
97
+ /// or:
98
+ /// VersionedGenericDatum:
99
+ /// - datum: Constr 0 []
100
+ /// - appendix:
101
+ /// [
102
+ /// [ candidates[0].sidechain_public_key
103
+ /// ,
104
+ /// [
105
+ /// [ candidates[0].keys[0].id,
106
+ /// , candidates[0].keys[0].bytes
107
+ /// ]
108
+ /// , [ candidates[0].keys[1].id,
109
+ /// , candidates[0].keys[1].bytes
110
+ /// ]
111
+ /// // etc.
112
+ /// ]
113
+ /// ]
114
+ /// ,
115
+ /// [ candidates[1].sidechain_public_key
116
+ /// ,
117
+ /// [
118
+ /// [ candidates[1].keys[0].id,
119
+ /// , candidates[1].keys[0].bytes
120
+ /// ]
121
+ /// , [ candidates[1].keys[1].id,
122
+ /// , candidates[1].keys[1].bytes
123
+ /// ]
124
+ /// // etc.
125
+ /// ]
126
+ /// ]
127
+ /// // etc.
128
+ /// ]
129
+ /// - version: 1
130
+
96
131
pub fn permissioned_candidates_to_plutus_data (
97
132
candidates : & [ PermissionedCandidateData ] ,
98
133
) -> PlutusData {
99
- let mut list = PlutusList :: new ( ) ;
100
- for candidate in candidates {
101
- let mut candidate_datum = PlutusList :: new ( ) ;
102
- candidate_datum. add ( & PlutusData :: new_bytes ( candidate. sidechain_public_key . 0 . clone ( ) ) ) ;
103
- for key in candidate. keys . 0 . iter ( ) {
104
- candidate_datum. add ( & PlutusData :: new_bytes ( key. bytes . clone ( ) ) ) ;
134
+ fn has_only_aura_and_grandpa_keys ( data : & PermissionedCandidateData ) -> bool {
135
+ data. keys . 0 . len ( ) == 2
136
+ && data. keys . find ( AURA ) . is_some ( )
137
+ && data. keys . find ( GRANDPA ) . is_some ( )
138
+ }
139
+
140
+ fn candidates_to_plutus_data_v0 ( candidates : & [ PermissionedCandidateData ] ) -> PlutusData {
141
+ let mut list = PlutusList :: new ( ) ;
142
+ for candidate in candidates {
143
+ let mut candidate_datum = PlutusList :: new ( ) ;
144
+ candidate_datum. add ( & PlutusData :: new_bytes ( candidate. sidechain_public_key . 0 . clone ( ) ) ) ;
145
+ for key in candidate. keys . 0 . iter ( ) {
146
+ candidate_datum. add ( & PlutusData :: new_bytes ( key. bytes . clone ( ) ) ) ;
147
+ }
148
+ list. add ( & PlutusData :: new_list ( & candidate_datum) ) ;
105
149
}
106
- list. add ( & PlutusData :: new_list ( & candidate_datum) ) ;
150
+ let appendix = PlutusData :: new_list ( & list) ;
151
+ VersionedGenericDatum {
152
+ datum : PlutusData :: new_empty_constr_plutus_data ( & BigNum :: zero ( ) ) ,
153
+ appendix,
154
+ version : 0 ,
155
+ }
156
+ . into ( )
157
+ }
158
+
159
+ fn candidates_to_plutus_data_v1 ( candidates : & [ PermissionedCandidateData ] ) -> PlutusData {
160
+ let mut list = PlutusList :: new ( ) ;
161
+ for candidate in candidates {
162
+ let mut candidate_datum = PlutusList :: new ( ) ;
163
+ candidate_datum. add ( & PlutusData :: new_bytes ( candidate. sidechain_public_key . 0 . clone ( ) ) ) ;
164
+ candidate_datum. add ( & candidate_keys_to_plutus ( & candidate. keys ) ) ;
165
+ list. add ( & PlutusData :: new_list ( & candidate_datum) ) ;
166
+ }
167
+ VersionedGenericDatum {
168
+ datum : PlutusData :: new_empty_constr_plutus_data ( & BigNum :: zero ( ) ) ,
169
+ appendix : PlutusData :: new_list ( & list) ,
170
+ version : 1 ,
171
+ }
172
+ . into ( )
107
173
}
108
- let appendix = PlutusData :: new_list ( & list ) ;
109
- VersionedGenericDatum {
110
- datum : PlutusData :: new_empty_constr_plutus_data ( & BigNum :: zero ( ) ) ,
111
- appendix ,
112
- version : 0 ,
174
+
175
+ if candidates . iter ( ) . all ( has_only_aura_and_grandpa_keys ) {
176
+ candidates_to_plutus_data_v0 ( candidates )
177
+ } else {
178
+ candidates_to_plutus_data_v1 ( candidates )
113
179
}
114
- . into ( )
115
180
}
116
181
117
182
impl PermissionedCandidateDatums {
118
183
/// Parses plutus data schema in accordance with V1 schema
119
- fn decode_v1 ( data : & PlutusData ) -> Result < Self , String > {
184
+ fn decode_v1_appendix ( data : & PlutusData ) -> Result < Self , String > {
120
185
let permissioned_candidates = data
121
186
. as_list ( )
122
187
. and_then ( |list_datums| {
@@ -154,9 +219,10 @@ impl VersionedDatumWithLegacy for PermissionedCandidateDatums {
154
219
appendix : & PlutusData ,
155
220
) -> Result < Self , String > {
156
221
match version {
222
+ // v0 appendix is the same as legacy format of whole plutus data
157
223
0 => PermissionedCandidateDatums :: decode_legacy ( appendix)
158
224
. map_err ( |msg| format ! ( "Cannot parse appendix: {msg}" ) ) ,
159
- 1 => PermissionedCandidateDatums :: decode_v1 ( appendix)
225
+ 1 => PermissionedCandidateDatums :: decode_v1_appendix ( appendix)
160
226
. map_err ( |msg| format ! ( "Cannot parse appendix: {msg}" ) ) ,
161
227
_ => Err ( format ! ( "Unknown version: {version}" ) ) ,
162
228
}
@@ -182,7 +248,7 @@ fn decode_legacy_candidate_datum(datum: &PlutusData) -> Option<PermissionedCandi
182
248
fn decode_v1_candidate_datum ( datum : & PlutusData ) -> Option < PermissionedCandidateDatumV1 > {
183
249
// The first element has Partner Chains key, second contains all other keys
184
250
let outer_list = datum. as_list ( ) . filter ( |l| l. len ( ) == 2 ) ?;
185
- let partner_chains_key = decode_candidate_key ( & outer_list. get ( 0 ) ) ? ;
251
+ let partner_chains_key = SidechainPublicKey ( outer_list. get ( 0 ) . as_bytes ( ) ? ) ;
186
252
let keys = decode_candidate_keys ( & outer_list. get ( 1 ) ) ?;
187
253
Some ( PermissionedCandidateDatumV1 { partner_chains_key, keys } )
188
254
}
@@ -265,14 +331,14 @@ mod tests {
265
331
{ "constructor" : 0 , "fields" : [ ] } ,
266
332
{ "list" : [
267
333
{ "list" : [
268
- { "list" : [ { " bytes": hex :: encode ( b"crch" ) } , { "bytes" : " cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"} ] } ,
334
+ { "bytes" : " cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"} ,
269
335
{ "list" : [
270
336
{ "list" : [ { "bytes" : hex:: encode( b"aura" ) } , { "bytes" : "bf20afa1c1a72af3341fa7a447e3f9eada9f3d054a7408fb9e49ad4d6e6559ec" } ] } ,
271
337
{ "list" : [ { "bytes" : hex:: encode( b"gran" ) } , { "bytes" : "9042a40b0b1baa9adcead024432a923eac706be5e1a89d7f2f2d58bfa8f3c26d" } ] }
272
338
] }
273
339
] } ,
274
340
{ "list" : [
275
- { "list" : [ { " bytes": hex :: encode ( b"crch" ) } , { "bytes" : " 79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf"} ] } ,
341
+ { "bytes" : " 79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf"} ,
276
342
{ "list" : [
277
343
{ "list" : [ { "bytes" : hex:: encode( b"aura" ) } , { "bytes" : "56d1da82e56e4cb35b13de25f69a3e9db917f3e13d6f786321f4b0a9dc153b19" } ] } ,
278
344
{ "list" : [ { "bytes" : hex:: encode( b"gran" ) } , { "bytes" : "7392f3ea668aa2be7997d82c07bcfbec3ee4a9a4e01e3216d92b8f0d0a086c32" } ] }
@@ -285,7 +351,7 @@ mod tests {
285
351
}
286
352
287
353
#[ test]
288
- fn test_permissioned_candidates_to_plutus_data ( ) {
354
+ fn permissioned_candidates_to_plutus_data_outputs_v0_for_aura_and_grandpa_keys ( ) {
289
355
let expected_plutus_data = json_to_plutus_data ( v0_datum_json ( ) ) ;
290
356
291
357
let domain_data = vec ! [
@@ -329,6 +395,50 @@ mod tests {
329
395
assert_eq ! ( permissioned_candidates_to_plutus_data( & domain_data) , expected_plutus_data)
330
396
}
331
397
398
+ #[ test]
399
+ fn permissioned_candidates_to_plutus_data_outputs_v1 ( ) {
400
+ let domain_data = vec ! [
401
+ PermissionedCandidateData {
402
+ sidechain_public_key: SidechainPublicKey ( [ 1 ; 33 ] . to_vec( ) ) ,
403
+ keys: CandidateKeys ( vec![
404
+ CandidateKey { id: [ 2 ; 4 ] , bytes: [ 3 ; 32 ] . to_vec( ) } ,
405
+ CandidateKey { id: [ 4 ; 4 ] , bytes: [ 5 ; 32 ] . to_vec( ) } ,
406
+ ] ) ,
407
+ } ,
408
+ PermissionedCandidateData {
409
+ sidechain_public_key: SidechainPublicKey ( [ 6 ; 33 ] . to_vec( ) ) ,
410
+ keys: CandidateKeys ( vec![
411
+ CandidateKey { id: [ 7 ; 4 ] , bytes: [ 8 ; 32 ] . to_vec( ) } ,
412
+ CandidateKey { id: [ 9 ; 4 ] , bytes: [ 10u8 ; 32 ] . to_vec( ) } ,
413
+ ] ) ,
414
+ } ,
415
+ ] ;
416
+ let json = serde_json:: json!( {
417
+ "list" : [
418
+ { "constructor" : 0 , "fields" : [ ] } ,
419
+ { "list" : [
420
+ { "list" : [
421
+ { "bytes" : "010101010101010101010101010101010101010101010101010101010101010101" } ,
422
+ { "list" : [
423
+ { "list" : [ { "bytes" : "02020202" } , { "bytes" : "0303030303030303030303030303030303030303030303030303030303030303" } ] } ,
424
+ { "list" : [ { "bytes" : "04040404" } , { "bytes" : "0505050505050505050505050505050505050505050505050505050505050505" } ] }
425
+ ] }
426
+ ] } ,
427
+ { "list" : [
428
+ { "bytes" : "060606060606060606060606060606060606060606060606060606060606060606" } ,
429
+ { "list" : [
430
+ { "list" : [ { "bytes" : "07070707" } , { "bytes" : "0808080808080808080808080808080808080808080808080808080808080808" } ] } ,
431
+ { "list" : [ { "bytes" : "09090909" } , { "bytes" : "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a" } ] }
432
+ ] }
433
+ ] }
434
+ ] } ,
435
+ { "int" : 1 }
436
+ ]
437
+ } ) ;
438
+ let expected_plutus_data = json_to_plutus_data ( json) ;
439
+ assert_eq ! ( permissioned_candidates_to_plutus_data( & domain_data) , expected_plutus_data)
440
+ }
441
+
332
442
#[ test]
333
443
fn valid_v0_permissioned_candidates ( ) {
334
444
let plutus_data = json_to_plutus_data ( v0_datum_json ( ) ) ;
@@ -367,8 +477,7 @@ mod tests {
367
477
368
478
let expected_datum = PermissionedCandidateDatums :: V1 ( vec ! [
369
479
PermissionedCandidateDatumV1 {
370
- partner_chains_key: CandidateKey :: new(
371
- CROSS_CHAIN_KEY_TYPE_ID ,
480
+ partner_chains_key: SidechainPublicKey (
372
481
hex!( "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854" ) . into( ) ,
373
482
) ,
374
483
keys: CandidateKeys ( vec![
@@ -385,8 +494,7 @@ mod tests {
385
494
] ) ,
386
495
} ,
387
496
PermissionedCandidateDatumV1 {
388
- partner_chains_key: CandidateKey :: new(
389
- CROSS_CHAIN_KEY_TYPE_ID ,
497
+ partner_chains_key: SidechainPublicKey (
390
498
hex!( "79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf" ) . into( ) ,
391
499
) ,
392
500
keys: CandidateKeys ( vec![
0 commit comments