darkfi_sdk/crypto/
blind.rs1use core::str::FromStr;
20
21#[cfg(feature = "async")]
22use darkfi_serial::{async_trait, AsyncDecodable, AsyncEncodable};
23use darkfi_serial::{Decodable, Encodable, SerialDecodable, SerialEncodable};
24
25use pasta_curves::{
26 group::ff::{Field, PrimeField},
27 pallas,
28};
29use rand_core::{CryptoRng, RngCore};
30
31use crate::error::ContractError;
32
33#[cfg(feature = "async")]
34pub trait EncDecode: Encodable + Decodable + AsyncEncodable + AsyncDecodable {}
35#[cfg(not(feature = "async"))]
36pub trait EncDecode: Encodable + Decodable {}
37
38impl EncDecode for pallas::Base {}
39impl EncDecode for pallas::Scalar {}
40
41#[derive(Debug, Copy, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
43pub struct Blind<F: Field + EncDecode>(pub F);
44
45impl<F: Field + EncDecode> Blind<F> {
46 pub const ZERO: Self = Self(F::ZERO);
47
48 pub fn random(rng: &mut (impl CryptoRng + RngCore)) -> Self {
49 Self(F::random(rng))
50 }
51
52 pub fn inner(&self) -> F {
53 self.0
54 }
55}
56
57impl<'a, F: Field + EncDecode> std::ops::Add<&'a Blind<F>> for &Blind<F> {
58 type Output = Blind<F>;
59
60 #[inline]
61 fn add(self, rhs: &'a Blind<F>) -> Blind<F> {
62 Blind(self.0.add(rhs.0))
63 }
64}
65
66impl<F: Field + EncDecode> std::ops::AddAssign for Blind<F> {
67 #[inline]
68 fn add_assign(&mut self, other: Self) {
69 self.0.add_assign(other.0)
70 }
71}
72
73pub type BaseBlind = Blind<pallas::Base>;
74pub type ScalarBlind = Blind<pallas::Scalar>;
75
76impl From<u64> for BaseBlind {
77 fn from(x: u64) -> Self {
78 Self(pallas::Base::from(x))
79 }
80}
81
82impl FromStr for BaseBlind {
83 type Err = ContractError;
84
85 fn from_str(enc: &str) -> Result<Self, Self::Err> {
87 let decoded = bs58::decode(enc).into_vec()?;
88 if decoded.len() != 32 {
89 return Err(Self::Err::IoError(
90 "Failed decoding BaseBlind from bytes, len is not 32".to_string(),
91 ))
92 }
93
94 match pallas::Base::from_repr(decoded.try_into().unwrap()).into() {
95 Some(k) => Ok(Self(k)),
96 None => Err(ContractError::IoError("Could not convert bytes to BaseBlind".to_string())),
97 }
98 }
99}
100
101impl core::fmt::Display for BaseBlind {
102 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
103 let disp: String = bs58::encode(self.0.to_repr()).into_string();
104 write!(f, "{disp}")
105 }
106}
107
108impl From<u64> for ScalarBlind {
109 fn from(x: u64) -> Self {
110 Self(pallas::Scalar::from(x))
111 }
112}
113
114impl FromStr for ScalarBlind {
115 type Err = ContractError;
116
117 fn from_str(enc: &str) -> Result<Self, Self::Err> {
119 let decoded = bs58::decode(enc).into_vec()?;
120 if decoded.len() != 32 {
121 return Err(Self::Err::IoError(
122 "Failed decoding ScalarBlind from bytes, len is not 32".to_string(),
123 ))
124 }
125
126 match pallas::Scalar::from_repr(decoded.try_into().unwrap()).into() {
127 Some(k) => Ok(Self(k)),
128 None => {
129 Err(ContractError::IoError("Could not convert bytes to ScalarBlind".to_string()))
130 }
131 }
132 }
133}
134
135impl core::fmt::Display for ScalarBlind {
136 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
137 let disp: String = bs58::encode(self.0.to_repr()).into_string();
138 write!(f, "{disp}")
139 }
140}