whisky_csl/utils/
certificates.rs

1use std::net::{Ipv4Addr, Ipv6Addr};
2
3use cardano_serialization_lib as csl;
4
5use whisky_common::*;
6
7use super::to_bignum;
8
9pub fn to_csl_drep(drep: &DRep) -> Result<csl::DRep, WError> {
10    match drep {
11        DRep::DRepId(drep_id) => {
12            Ok(csl::DRep::from_bech32(drep_id)
13                .map_err(WError::from_err("to_csl_drep - drep_id"))?)
14        }
15        DRep::AlwaysAbstain => Ok(csl::DRep::new_always_abstain()),
16        DRep::AlwaysNoConfidence => Ok(csl::DRep::new_always_no_confidence()),
17    }
18}
19
20pub fn to_csl_anchor(anchor: &Anchor) -> Result<csl::Anchor, WError> {
21    Ok(csl::Anchor::new(
22        &csl::URL::new(anchor.anchor_url.clone())
23            .map_err(WError::from_err("to_csl_anchor - invalid anchor url"))?,
24        &csl::AnchorDataHash::from_hex(&anchor.anchor_data_hash)
25            .map_err(WError::from_err("to_csl_anchor - invalid anchor data hash"))?,
26    ))
27}
28
29pub fn to_csl_cert(cert: CertificateType) -> Result<csl::Certificate, WError> {
30    match cert {
31        CertificateType::RegisterPool(reg_pool_cert) => to_register_pool_cert(reg_pool_cert),
32        CertificateType::RegisterStake(reg_stake_cert) => to_register_stake_cert(reg_stake_cert),
33        CertificateType::DeregisterStake(dereg_stake_cert) => {
34            to_deregister_stake_cert(dereg_stake_cert)
35        }
36        CertificateType::DelegateStake(deleg_stake_cert) => {
37            to_delegate_stake_cert(deleg_stake_cert)
38        }
39        CertificateType::RetirePool(retire_pool_cert) => to_retire_pool_cert(retire_pool_cert),
40        CertificateType::VoteDelegation(vote_deleg_cert) => {
41            to_vote_delegation_cert(vote_deleg_cert)
42        }
43        CertificateType::StakeAndVoteDelegation(stake_and_vote_deleg_cert) => {
44            to_stake_and_vote_delegation_cert(stake_and_vote_deleg_cert)
45        }
46        CertificateType::StakeRegistrationAndDelegation(stake_reg_and_deleg_cert) => {
47            to_stake_registration_and_delegation_cert(stake_reg_and_deleg_cert)
48        }
49        CertificateType::VoteRegistrationAndDelegation(vote_reg_and_deleg_cert) => {
50            to_vote_registration_and_delgation_cert(vote_reg_and_deleg_cert)
51        }
52        CertificateType::StakeVoteRegistrationAndDelegation(stake_vote_reg_and_deleg_cert) => {
53            to_stake_vote_registration_and_delegation_cert(stake_vote_reg_and_deleg_cert)
54        }
55        CertificateType::CommitteeHotAuth(committee_hot_auth_cert) => {
56            to_committee_hot_auth_cert(committee_hot_auth_cert)
57        }
58        CertificateType::CommitteeColdResign(committee_cold_resign_cert) => {
59            to_commitee_cold_resign_cert(committee_cold_resign_cert)
60        }
61        CertificateType::DRepRegistration(drep_registration_cert) => {
62            to_drep_registration_cert(drep_registration_cert)
63        }
64        CertificateType::DRepDeregistration(drep_deregistration_cert) => {
65            to_drep_deregistration_cert(drep_deregistration_cert)
66        }
67        CertificateType::DRepUpdate(drep_update_cert) => to_drep_update_cert(drep_update_cert),
68    }
69}
70
71fn to_register_pool_cert(register_pool: RegisterPool) -> Result<csl::Certificate, WError> {
72    let mut relays = csl::Relays::new();
73    for relay in register_pool.pool_params.relays {
74        match relay {
75            Relay::SingleHostAddr(single_host_address_relay) => {
76                let ipv4_bytes: Option<csl::Ipv4> =
77                    single_host_address_relay.ipv4.map(|ipv4_str| {
78                        let addr: Ipv4Addr = ipv4_str.parse().expect("ipv4 address parse failed");
79                        csl::Ipv4::new(addr.octets().to_vec()).unwrap()
80                    });
81
82                let ipv6_bytes: Option<csl::Ipv6> =
83                    single_host_address_relay.ipv6.map(|ipv6_str| {
84                        let addr: Ipv6Addr = ipv6_str.parse().expect("ipv6 address parse failed");
85                        csl::Ipv6::new(addr.octets().to_vec()).unwrap()
86                    });
87                relays.add(&csl::Relay::new_single_host_addr(
88                    &csl::SingleHostAddr::new(
89                        single_host_address_relay.port,
90                        ipv4_bytes,
91                        ipv6_bytes,
92                    ),
93                ));
94            }
95            Relay::SingleHostName(single_host_name_relay) => relays.add(
96                &csl::Relay::new_single_host_name(&csl::SingleHostName::new(
97                    single_host_name_relay.port,
98                    &csl::DNSRecordAorAAAA::new(single_host_name_relay.domain_name).map_err(
99                        WError::from_err("to_register_pool_cert - invalid domain name - single"),
100                    )?,
101                )),
102            ),
103            Relay::MultiHostName(multi_host_name_relay) => {
104                relays.add(&csl::Relay::new_multi_host_name(&csl::MultiHostName::new(
105                    &csl::DNSRecordSRV::new(multi_host_name_relay.domain_name).map_err(
106                        WError::from_err("to_register_pool_cert - invalid domain name - multi"),
107                    )?,
108                )))
109            }
110        }
111    }
112
113    let mut pool_owners = csl::Ed25519KeyHashes::new();
114    for owner in register_pool.pool_params.owners {
115        pool_owners.add(
116            &csl::Ed25519KeyHash::from_hex(&owner).map_err(WError::from_err(
117                "to_register_pool_cert - invalid pool owner",
118            ))?,
119        );
120    }
121    Ok(csl::Certificate::new_pool_registration(
122        &csl::PoolRegistration::new(&csl::PoolParams::new(
123            &csl::Ed25519KeyHash::from_hex(&register_pool.pool_params.operator).map_err(
124                WError::from_err("to_register_pool_cert - invalid pool operator"),
125            )?,
126            &csl::VRFKeyHash::from_hex(&register_pool.pool_params.vrf_key_hash).map_err(
127                WError::from_err("to_register_pool_cert - invalid pool vrf key hash"),
128            )?,
129            &csl::BigNum::from_str(&register_pool.pool_params.pledge).map_err(WError::from_err(
130                "to_register_pool_cert - invalid pool pledge",
131            ))?,
132            &csl::BigNum::from_str(&register_pool.pool_params.cost).map_err(WError::from_err(
133                "to_register_pool_cert - invalid pool cost",
134            ))?,
135            &csl::UnitInterval::new(
136                &csl::BigNum::from_str(&register_pool.pool_params.margin.0.to_string()).map_err(
137                    WError::from_err("to_register_pool_cert - invalid pool margin - 0"),
138                )?,
139                &csl::BigNum::from_str(&register_pool.pool_params.margin.1.to_string()).map_err(
140                    WError::from_err("to_register_pool_cert - invalid pool margin - 1"),
141                )?,
142            ),
143            &csl::RewardAddress::from_address(
144                &csl::Address::from_bech32(&register_pool.pool_params.reward_address).map_err(
145                    WError::from_err("to_register_pool_cert - invalid pool reward address"),
146                )?,
147            )
148            .ok_or_else(WError::from_opt(
149                "to_register_pool_cert - invalid pool reward address",
150                "Invalid reward address",
151            ))?,
152            &pool_owners,
153            &relays,
154            register_pool.pool_params.metadata.map(|data| {
155                csl::PoolMetadata::new(
156                    &csl::URL::new(data.url).unwrap(),
157                    &csl::PoolMetadataHash::from_hex(&data.hash).unwrap(),
158                )
159            }),
160        )),
161    ))
162}
163
164fn to_register_stake_cert(register_stake: RegisterStake) -> Result<csl::Certificate, WError> {
165    Ok(csl::Certificate::new_stake_registration(
166        &csl::StakeRegistration::new(
167            &csl::Address::from_bech32(&register_stake.stake_key_address)
168                .map_err(WError::from_err(
169                    "to_register_stake_cert - invalid stake key address",
170                ))?
171                .payment_cred()
172                .unwrap(),
173        ),
174    ))
175}
176
177fn to_delegate_stake_cert(delegate_stake: DelegateStake) -> Result<csl::Certificate, WError> {
178    Ok(csl::Certificate::new_stake_delegation(
179        &csl::StakeDelegation::new(
180            &csl::Address::from_bech32(&delegate_stake.stake_key_address)
181                .map_err(WError::from_err(
182                    "to_delegate_stake_cert - invalid stake key address",
183                ))?
184                .payment_cred()
185                .unwrap(),
186            &csl::Ed25519KeyHash::from_hex(&delegate_stake.pool_id)
187                .map_err(WError::from_err("to_delegate_stake_cert - invalid pool id"))?,
188        ),
189    ))
190}
191
192fn to_deregister_stake_cert(deregister_stake: DeregisterStake) -> Result<csl::Certificate, WError> {
193    Ok(csl::Certificate::new_stake_deregistration(
194        &csl::StakeDeregistration::new(
195            &csl::Address::from_bech32(&deregister_stake.stake_key_address)
196                .map_err(WError::from_err(
197                    "to_deregister_stake_cert - invalid stake key address",
198                ))?
199                .payment_cred()
200                .unwrap(),
201        ),
202    ))
203}
204
205fn to_retire_pool_cert(retire_pool: RetirePool) -> Result<csl::Certificate, WError> {
206    Ok(csl::Certificate::new_pool_retirement(
207        &csl::PoolRetirement::new(
208            &csl::Ed25519KeyHash::from_hex(&retire_pool.pool_id)
209                .map_err(WError::from_err("to_retire_pool_cert - invalid pool id"))?,
210            retire_pool.epoch,
211        ),
212    ))
213}
214
215fn to_vote_delegation_cert(vote_delegation: VoteDelegation) -> Result<csl::Certificate, WError> {
216    Ok(csl::Certificate::new_vote_delegation(
217        &csl::VoteDelegation::new(
218            &csl::Address::from_bech32(&vote_delegation.stake_key_address)
219                .map_err(WError::from_err(
220                    "to_vote_delegation_cert - invalid stake key address",
221                ))?
222                .payment_cred()
223                .unwrap(),
224            &to_csl_drep(&vote_delegation.drep)?,
225        ),
226    ))
227}
228
229fn to_stake_and_vote_delegation_cert(
230    stake_and_vote_delegation: StakeAndVoteDelegation,
231) -> Result<csl::Certificate, WError> {
232    Ok(csl::Certificate::new_stake_and_vote_delegation(
233        &csl::StakeAndVoteDelegation::new(
234            &csl::Address::from_bech32(&stake_and_vote_delegation.stake_key_address)
235                .map_err(WError::from_err(
236                    "to_stake_and_vote_delegation_cert - invalid stake key address",
237                ))?
238                .payment_cred()
239                .unwrap(),
240            &csl::Ed25519KeyHash::from_hex(&stake_and_vote_delegation.pool_key_hash).map_err(
241                WError::from_err("to_stake_and_vote_delegation_cert - invalid pool key hash"),
242            )?,
243            &to_csl_drep(&stake_and_vote_delegation.drep)?,
244        ),
245    ))
246}
247
248fn to_stake_registration_and_delegation_cert(
249    stake_registration_and_delegation: StakeRegistrationAndDelegation,
250) -> Result<csl::Certificate, WError> {
251    Ok(csl::Certificate::new_stake_registration_and_delegation(
252        &csl::StakeRegistrationAndDelegation::new(
253            &csl::Address::from_bech32(&stake_registration_and_delegation.stake_key_address)
254                .map_err(WError::from_err(
255                    "to_stake_registration_and_delegation_cert - invalid stake key address",
256                ))?
257                .payment_cred()
258                .ok_or_else(WError::from_opt(
259                    "to_stake_registration_and_delegation_cert - invalid stake key address",
260                    "Invalid stake key address",
261                ))?,
262            &csl::Ed25519KeyHash::from_hex(&stake_registration_and_delegation.pool_key_hash)
263                .map_err(WError::from_err(
264                    "to_stake_registration_and_delegation_cert - invalid pool key hash",
265                ))?,
266            &to_bignum(stake_registration_and_delegation.coin).map_err(WError::add_err_trace(
267                "to_stake_registration_and_delegation_cert",
268            ))?,
269        ),
270    ))
271}
272
273fn to_vote_registration_and_delgation_cert(
274    vote_registration_and_delgation: VoteRegistrationAndDelegation,
275) -> Result<csl::Certificate, WError> {
276    Ok(csl::Certificate::new_vote_registration_and_delegation(
277        &csl::VoteRegistrationAndDelegation::new(
278            &csl::Address::from_bech32(&vote_registration_and_delgation.stake_key_address)
279                .map_err(WError::from_err(
280                    "to_vote_registration_and_delgation_cert - invalid stake key address",
281                ))?
282                .payment_cred()
283                .ok_or_else(WError::from_opt(
284                    "to_vote_registration_and_delgation_cert - invalid stake key address",
285                    "Invalid stake key address",
286                ))?,
287            &to_csl_drep(&vote_registration_and_delgation.drep).map_err(WError::add_err_trace(
288                "to_vote_registration_and_delgation_cert - invalid drep",
289            ))?,
290            &to_bignum(vote_registration_and_delgation.coin).map_err(WError::add_err_trace(
291                "to_vote_registration_and_delgation_cert - invalid coin",
292            ))?,
293        ),
294    ))
295}
296
297fn to_stake_vote_registration_and_delegation_cert(
298    stake_vote_registration_and_delegation: StakeVoteRegistrationAndDelegation,
299) -> Result<csl::Certificate, WError> {
300    Ok(
301        csl::Certificate::new_stake_vote_registration_and_delegation(
302            &csl::StakeVoteRegistrationAndDelegation::new(
303                &csl::Address::from_bech32(
304                    &stake_vote_registration_and_delegation.stake_key_address,
305                )
306                .map_err(WError::from_err(
307                    "to_stake_vote_registration_and_delegation_cert - invalid stake key address",
308                ))?
309                .payment_cred()
310                .ok_or_else(WError::from_opt(
311                    "to_stake_vote_registration_and_delegation_cert - invalid stake key address",
312                    "Invalid stake key address",
313                ))?,
314                &csl::Ed25519KeyHash::from_hex(
315                    &stake_vote_registration_and_delegation.pool_key_hash,
316                )
317                .map_err(WError::from_err(
318                    "to_stake_vote_registration_and_delegation_cert - invalid pool key hash",
319                ))?,
320                &to_csl_drep(&stake_vote_registration_and_delegation.drep).map_err(
321                    WError::add_err_trace(
322                        "to_stake_vote_registration_and_delegation_cert - invalid drep",
323                    ),
324                )?,
325                &to_bignum(stake_vote_registration_and_delegation.coin).map_err(
326                    WError::add_err_trace(
327                        "to_stake_vote_registration_and_delegation_cert - invalid coin",
328                    ),
329                )?,
330            ),
331        ),
332    )
333}
334
335fn to_committee_hot_auth_cert(
336    committee_hot_auth: CommitteeHotAuth,
337) -> Result<csl::Certificate, WError> {
338    Ok(csl::Certificate::new_committee_hot_auth(
339        &csl::CommitteeHotAuth::new(
340            &csl::Address::from_bech32(&committee_hot_auth.committee_cold_key_address)
341                .map_err(WError::from_err(
342                    "to_committee_hot_auth_cert - invalid committee cold key address",
343                ))?
344                .payment_cred()
345                .ok_or_else(WError::from_opt(
346                    "to_committee_hot_auth_cert - invalid committee cold key address",
347                    "Invalid committee cold key address",
348                ))?,
349            &csl::Address::from_bech32(&committee_hot_auth.committee_hot_key_address)
350                .map_err(WError::from_err(
351                    "to_committee_hot_auth_cert - invalid committee hot key address",
352                ))?
353                .payment_cred()
354                .ok_or_else(WError::from_opt(
355                    "to_committee_hot_auth_cert - invalid committee hot key address",
356                    "Invalid committee hot key address",
357                ))?,
358        ),
359    ))
360}
361
362fn to_commitee_cold_resign_cert(
363    committee_cold_resign: CommitteeColdResign,
364) -> Result<csl::Certificate, WError> {
365    let committee_cold_key =
366        &csl::Address::from_bech32(&committee_cold_resign.committee_cold_key_address)
367            .map_err(WError::from_err(
368                "to_commitee_cold_resign_cert - invalid committee cold key address",
369            ))?
370            .payment_cred()
371            .ok_or_else(WError::from_opt(
372                "to_commitee_cold_resign_cert - invalid committee cold key address",
373                "Invalid committee cold key address",
374            ))?;
375    match committee_cold_resign.anchor {
376        Some(anchor) => Ok(csl::Certificate::new_committee_cold_resign(
377            &csl::CommitteeColdResign::new_with_anchor(
378                committee_cold_key,
379                &to_csl_anchor(&anchor).map_err(WError::add_err_trace(
380                    "to_commitee_cold_resign_cert - invalid anchor",
381                ))?,
382            ),
383        )),
384        None => Ok(csl::Certificate::new_committee_cold_resign(
385            &csl::CommitteeColdResign::new(committee_cold_key),
386        )),
387    }
388}
389
390fn to_drep_registration_cert(
391    drep_registration: DRepRegistration,
392) -> Result<csl::Certificate, WError> {
393    let drep = csl::DRep::from_bech32(&drep_registration.drep_id).map_err(WError::from_err(
394        "to_drep_registration_cert - invalid drep id",
395    ))?;
396    let drep_credential = if drep.to_script_hash().is_some() {
397        csl::Credential::from_scripthash(&drep.to_script_hash().unwrap())
398    } else if drep.to_key_hash().is_some() {
399        csl::Credential::from_keyhash(&drep.to_key_hash().unwrap())
400    } else {
401        return Err(WError::new(
402            "to_drep_registration_cert - invalid drep id",
403            "Error occured when deserializing DrepId to either script hash or key hash",
404        ));
405    };
406
407    match drep_registration.anchor {
408        Some(anchor) => Ok(csl::Certificate::new_drep_registration(
409            &csl::DRepRegistration::new_with_anchor(
410                &drep_credential,
411                &to_bignum(drep_registration.coin).map_err(WError::add_err_trace(
412                    "to_drep_registration_cert - invalid coin",
413                ))?,
414                &to_csl_anchor(&anchor).map_err(WError::add_err_trace(
415                    "to_drep_registration_cert - invalid anchor",
416                ))?,
417            ),
418        )),
419        None => Ok(csl::Certificate::new_drep_registration(
420            &csl::DRepRegistration::new(
421                &drep_credential,
422                &to_bignum(drep_registration.coin).map_err(WError::add_err_trace(
423                    "to_drep_registration_cert - invalid coin",
424                ))?,
425            ),
426        )),
427    }
428}
429
430fn to_drep_deregistration_cert(
431    drep_deregistration: DRepDeregistration,
432) -> Result<csl::Certificate, WError> {
433    let drep = csl::DRep::from_bech32(&drep_deregistration.drep_id).map_err(WError::from_err(
434        "to_drep_deregistration_cert - invalid drep id",
435    ))?;
436    let drep_credential = if drep.to_script_hash().is_some() {
437        csl::Credential::from_scripthash(&drep.to_script_hash().unwrap())
438    } else if drep.to_key_hash().is_some() {
439        csl::Credential::from_keyhash(&drep.to_key_hash().unwrap())
440    } else {
441        return Err(WError::new(
442            "to_drep_deregistration_cert - invalid drep id",
443            "Error occured when deserializing DrepId to either script hash or key hash",
444        ));
445    };
446
447    Ok(csl::Certificate::new_drep_deregistration(
448        &csl::DRepDeregistration::new(
449            &drep_credential,
450            &to_bignum(drep_deregistration.coin).map_err(WError::add_err_trace(
451                "to_drep_deregistration_cert - invalid coin",
452            ))?,
453        ),
454    ))
455}
456
457fn to_drep_update_cert(drep_update: DRepUpdate) -> Result<csl::Certificate, WError> {
458    let drep = csl::DRep::from_bech32(&drep_update.drep_id)
459        .map_err(WError::from_err("to_drep_update_cert - invalid drep id"))?;
460    let drep_credential = if drep.to_script_hash().is_some() {
461        csl::Credential::from_scripthash(&drep.to_script_hash().unwrap())
462    } else if drep.to_key_hash().is_some() {
463        csl::Credential::from_keyhash(&drep.to_key_hash().unwrap())
464    } else {
465        return Err(WError::new(
466            "to_drep_update_cert - invalid drep id",
467            "Error occured when deserializing DrepId to either script hash or key hash",
468        ));
469    };
470    match drep_update.anchor {
471        Some(anchor) => Ok(csl::Certificate::new_drep_update(
472            &csl::DRepUpdate::new_with_anchor(&drep_credential, &to_csl_anchor(&anchor)?),
473        )),
474        None => Ok(csl::Certificate::new_drep_update(&csl::DRepUpdate::new(
475            &drep_credential,
476        ))),
477    }
478}