Skip to content

Commit f20a3b6

Browse files
committed
feat: write plutus data v1 for permissioned candidates and registerations
1 parent d10cd47 commit f20a3b6

File tree

2 files changed

+138
-30
lines changed

2 files changed

+138
-30
lines changed

toolkit/data-sources/db-sync/testdata/migrations/6_insert_transactions.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,14 +306,14 @@ DO $$
306306
{"constructor": 0, "fields": [] },
307307
{"list": [
308308
{"list": [
309-
{"list":[{"bytes": "63726368"}, {"bytes": "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"}]},
309+
{"bytes": "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"},
310310
{"list":[
311311
{"list":[{"bytes": "61757261"}, {"bytes": "bf20afa1c1a72af3341fa7a447e3f9eada9f3d054a7408fb9e49ad4d6e6559ec"}]},
312312
{"list":[{"bytes": "6772616e"}, {"bytes": "9042a40b0b1baa9adcead024432a923eac706be5e1a89d7f2f2d58bfa8f3c26d"}]}
313313
]}
314314
]},
315315
{"list": [
316-
{"list":[{"bytes": "63726368"}, {"bytes": "79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf"}]},
316+
{"bytes": "79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf"},
317317
{"list":[
318318
{"list":[{"bytes": "61757261"}, {"bytes": "56d1da82e56e4cb35b13de25f69a3e9db917f3e13d6f786321f4b0a9dc153b19"}]},
319319
{"list":[{"bytes": "6772616e"}, {"bytes": "7392f3ea668aa2be7997d82c07bcfbec3ee4a9a4e01e3216d92b8f0d0a086c32"}]}

toolkit/smart-contracts/plutus-data/src/permissioned_candidates.rs

Lines changed: 136 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Plutus data types for permissioned candidates.
22
use cardano_serialization_lib::{BigNum, PlutusData, PlutusList};
33
use sidechain_domain::*;
4+
use sp_core::crypto::key_types::{AURA, GRANDPA};
45

56
use crate::{
67
DataDecodingError, DecodingResult, VersionedDatum, VersionedDatumWithLegacy,
@@ -32,16 +33,15 @@ impl From<PermissionedCandidateDatumV1> for PermissionedCandidateData {
3233
// with T: OpaqueKeys, this function will be re-implemented.
3334
fn from(value: PermissionedCandidateDatumV1) -> Self {
3435
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 }
3737
}
3838
}
3939

4040
#[derive(Clone, Debug, PartialEq)]
4141
/// Datum representing a permissioned candidate with arbitrary set of keys
4242
pub struct PermissionedCandidateDatumV1 {
4343
/// Partner Chains key identifier and bytes
44-
pub partner_chains_key: CandidateKey,
44+
pub partner_chains_key: SidechainPublicKey,
4545
/// Represents arbitrary set of keys with 4 character identifier
4646
pub keys: CandidateKeys,
4747
}
@@ -75,10 +75,11 @@ impl From<PermissionedCandidateDatums> for Vec<PermissionedCandidateData> {
7575
}
7676

7777
/// 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.
7980
/// Encoding:
8081
/// VersionedGenericDatum:
81-
/// - datum: ()
82+
/// - datum: Constr 0 []
8283
/// - appendix:
8384
/// [
8485
/// [ candidates[0].sidechain_public_key
@@ -93,30 +94,94 @@ impl From<PermissionedCandidateDatums> for Vec<PermissionedCandidateData> {
9394
/// // etc.
9495
/// ]
9596
/// - 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+
96131
pub fn permissioned_candidates_to_plutus_data(
97132
candidates: &[PermissionedCandidateData],
98133
) -> 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));
105149
}
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()
107173
}
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)
113179
}
114-
.into()
115180
}
116181

117182
impl PermissionedCandidateDatums {
118183
/// 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> {
120185
let permissioned_candidates = data
121186
.as_list()
122187
.and_then(|list_datums| {
@@ -154,9 +219,10 @@ impl VersionedDatumWithLegacy for PermissionedCandidateDatums {
154219
appendix: &PlutusData,
155220
) -> Result<Self, String> {
156221
match version {
222+
// v0 appendix is the same as legacy format of whole plutus data
157223
0 => PermissionedCandidateDatums::decode_legacy(appendix)
158224
.map_err(|msg| format!("Cannot parse appendix: {msg}")),
159-
1 => PermissionedCandidateDatums::decode_v1(appendix)
225+
1 => PermissionedCandidateDatums::decode_v1_appendix(appendix)
160226
.map_err(|msg| format!("Cannot parse appendix: {msg}")),
161227
_ => Err(format!("Unknown version: {version}")),
162228
}
@@ -182,7 +248,7 @@ fn decode_legacy_candidate_datum(datum: &PlutusData) -> Option<PermissionedCandi
182248
fn decode_v1_candidate_datum(datum: &PlutusData) -> Option<PermissionedCandidateDatumV1> {
183249
// The first element has Partner Chains key, second contains all other keys
184250
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()?);
186252
let keys = decode_candidate_keys(&outer_list.get(1))?;
187253
Some(PermissionedCandidateDatumV1 { partner_chains_key, keys })
188254
}
@@ -265,14 +331,14 @@ mod tests {
265331
{ "constructor": 0, "fields": [] },
266332
{"list": [
267333
{"list":[
268-
{"list": [{"bytes": hex::encode(b"crch")}, {"bytes": "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"}]},
334+
{"bytes": "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"},
269335
{"list": [
270336
{"list": [{"bytes": hex::encode(b"aura")}, {"bytes": "bf20afa1c1a72af3341fa7a447e3f9eada9f3d054a7408fb9e49ad4d6e6559ec"}]},
271337
{"list": [{"bytes": hex::encode(b"gran")}, {"bytes": "9042a40b0b1baa9adcead024432a923eac706be5e1a89d7f2f2d58bfa8f3c26d"}]}
272338
]}
273339
]},
274340
{"list":[
275-
{"list": [{"bytes": hex::encode(b"crch")}, {"bytes": "79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf"}]},
341+
{"bytes": "79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf"},
276342
{"list": [
277343
{"list": [{"bytes": hex::encode(b"aura")}, {"bytes": "56d1da82e56e4cb35b13de25f69a3e9db917f3e13d6f786321f4b0a9dc153b19"}]},
278344
{"list": [{"bytes": hex::encode(b"gran")}, {"bytes": "7392f3ea668aa2be7997d82c07bcfbec3ee4a9a4e01e3216d92b8f0d0a086c32"}]}
@@ -285,7 +351,7 @@ mod tests {
285351
}
286352

287353
#[test]
288-
fn test_permissioned_candidates_to_plutus_data() {
354+
fn permissioned_candidates_to_plutus_data_outputs_v0_for_aura_and_grandpa_keys() {
289355
let expected_plutus_data = json_to_plutus_data(v0_datum_json());
290356

291357
let domain_data = vec![
@@ -329,6 +395,50 @@ mod tests {
329395
assert_eq!(permissioned_candidates_to_plutus_data(&domain_data), expected_plutus_data)
330396
}
331397

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+
332442
#[test]
333443
fn valid_v0_permissioned_candidates() {
334444
let plutus_data = json_to_plutus_data(v0_datum_json());
@@ -367,8 +477,7 @@ mod tests {
367477

368478
let expected_datum = PermissionedCandidateDatums::V1(vec![
369479
PermissionedCandidateDatumV1 {
370-
partner_chains_key: CandidateKey::new(
371-
CROSS_CHAIN_KEY_TYPE_ID,
480+
partner_chains_key: SidechainPublicKey(
372481
hex!("cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854").into(),
373482
),
374483
keys: CandidateKeys(vec![
@@ -385,8 +494,7 @@ mod tests {
385494
]),
386495
},
387496
PermissionedCandidateDatumV1 {
388-
partner_chains_key: CandidateKey::new(
389-
CROSS_CHAIN_KEY_TYPE_ID,
497+
partner_chains_key: SidechainPublicKey(
390498
hex!("79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf").into(),
391499
),
392500
keys: CandidateKeys(vec![

0 commit comments

Comments
 (0)