plutus_ledger_api/v1/
crypto.rs

1//! Types for cryptographic primitives, and other lower level building blocks
2
3use std::str::FromStr;
4
5use anyhow::anyhow;
6use cardano_serialization_lib as csl;
7#[cfg(feature = "lbf")]
8use lbr_prelude::json::{Error, Json};
9use nom::combinator::all_consuming;
10use nom::Finish;
11use nom::{combinator::map_res, error::VerboseError, IResult};
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14#[cfg(feature = "serde")]
15use serde_with::{DeserializeFromStr, SerializeDisplay};
16
17use crate as plutus_ledger_api;
18use crate::error::ConversionError;
19use crate::{
20    csl::{
21        csl_to_pla::FromCSL,
22        pla_to_csl::{TryFromPLA, TryFromPLAError},
23    },
24    plutus_data::IsPlutusData,
25};
26
27///////////////////////
28// Ed25519PubKeyHash //
29///////////////////////
30
31/// ED25519 public key hash
32/// This is the standard cryptography in Cardano, commonly referred to as `PubKeyHash` in Plutus
33/// and other libraries
34#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IsPlutusData)]
35#[is_plutus_data_derive_strategy = "Newtype"]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37#[cfg_attr(feature = "lbf", derive(Json))]
38pub struct Ed25519PubKeyHash(pub LedgerBytes);
39
40impl FromCSL<csl::Ed25519KeyHash> for Ed25519PubKeyHash {
41    fn from_csl(value: &csl::Ed25519KeyHash) -> Self {
42        Ed25519PubKeyHash(LedgerBytes(value.to_bytes()))
43    }
44}
45
46impl TryFromPLA<Ed25519PubKeyHash> for csl::Ed25519KeyHash {
47    fn try_from_pla(val: &Ed25519PubKeyHash) -> Result<Self, TryFromPLAError> {
48        csl::Ed25519KeyHash::from_bytes(val.0 .0.to_owned())
49            .map_err(TryFromPLAError::CSLDeserializeError)
50    }
51}
52
53impl FromCSL<csl::RequiredSigners> for Vec<Ed25519PubKeyHash> {
54    fn from_csl(value: &csl::RequiredSigners) -> Self {
55        (0..value.len())
56            .map(|idx| Ed25519PubKeyHash::from_csl(&value.get(idx)))
57            .collect()
58    }
59}
60
61///////////////////////
62// PaymentPubKeyHash //
63///////////////////////
64
65/// Standard public key hash used to verify a transaction witness
66#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IsPlutusData)]
67#[is_plutus_data_derive_strategy = "Newtype"]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69#[cfg_attr(feature = "lbf", derive(Json))]
70pub struct PaymentPubKeyHash(pub Ed25519PubKeyHash);
71
72/////////////////////
73// StakePubKeyHash //
74/////////////////////
75
76/// Standard public key hash used to verify a staking
77#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IsPlutusData)]
78#[is_plutus_data_derive_strategy = "Newtype"]
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80#[cfg_attr(feature = "lbf", derive(Json))]
81pub struct StakePubKeyHash(pub Ed25519PubKeyHash);
82
83/////////////////
84// LedgerBytes //
85/////////////////
86
87/// A bytestring in the Cardano ledger context
88#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, IsPlutusData)]
89#[is_plutus_data_derive_strategy = "Newtype"]
90#[cfg_attr(feature = "serde", derive(SerializeDisplay, DeserializeFromStr))]
91pub struct LedgerBytes(pub Vec<u8>);
92
93impl std::fmt::Debug for LedgerBytes {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        write!(f, "{}", hex::encode(&self.0))
96    }
97}
98
99impl std::fmt::Display for LedgerBytes {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        write!(f, "{}", hex::encode(&self.0))
102    }
103}
104
105impl FromStr for LedgerBytes {
106    type Err = ConversionError;
107
108    fn from_str(s: &str) -> Result<Self, Self::Err> {
109        all_consuming(ledger_bytes)(s)
110            .finish()
111            .map_err(|err| {
112                ConversionError::ParseError(anyhow!(
113                    "Error while parsing CurrencySymbol '{}': {}",
114                    s,
115                    err
116                ))
117            })
118            .map(|(_, cs)| cs)
119    }
120}
121/// Nom parser for LedgerBytes
122/// Expects a hexadecimal string of arbitrary length (0 length is allowed)
123/// E.g.: 00112233445566778899aabbcc
124pub(crate) fn ledger_bytes(input: &str) -> IResult<&str, LedgerBytes, VerboseError<&str>> {
125    map_res(nom::character::complete::hex_digit0, |hex_bytes: &str| {
126        hex::decode(&hex_bytes.to_owned().to_ascii_lowercase().into_bytes()).map(LedgerBytes)
127    })(input)
128}
129
130#[cfg(feature = "lbf")]
131impl Json for LedgerBytes {
132    fn to_json(&self) -> serde_json::Value {
133        String::to_json(&hex::encode(&self.0))
134    }
135
136    fn from_json(value: &serde_json::Value) -> Result<Self, Error> {
137        let bytes = String::from_json(value).and_then(|str| {
138            hex::decode(&str.into_bytes()).map_err(|_| Error::UnexpectedJsonInvariant {
139                wanted: "base16 string".to_owned(),
140                got: "unexpected string".to_owned(),
141                parser: "Plutus.V1.Bytes".to_owned(),
142            })
143        })?;
144
145        Ok(Self(bytes))
146    }
147}