plutus_ledger_api/v1/
crypto.rs

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