Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 1ec4dc8

Browse files
committed
update spl-pod to use zk-sdk
1 parent 48b8381 commit 1ec4dc8

File tree

3 files changed

+54
-47
lines changed

3 files changed

+54
-47
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libraries/pod/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@ license = "Apache-2.0"
88
edition = "2021"
99

1010
[features]
11-
serde-traits = ["dep:serde", "dep:base64"]
11+
serde-traits = ["dep:serde"]
1212
borsh = ["dep:borsh"]
1313

1414
[dependencies]
15-
base64 = { version = "0.22.1", optional = true }
1615
borsh = { version = "1.5.1", optional = true }
1716
bytemuck = { version = "1.16.3" }
1817
bytemuck_derive = { version = "1.7.0" }
1918
serde = { version = "1.0.207", optional = true }
2019
solana-program = "2.0.3"
21-
solana-zk-token-sdk = "2.0.3"
20+
solana-zk-sdk = "2.0.3"
2221
spl-program-error = { version = "0.5.0", path = "../program-error" }
2322

2423
[dev-dependencies]
2524
serde_json = "1.0.124"
25+
base64 = { version = "0.22.1" }
2626

2727
[lib]
2828
crate-type = ["cdylib", "lib"]

libraries/pod/src/optional_keys.rs

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
//! Optional pubkeys that can be used a `Pod`s
22
#[cfg(feature = "borsh")]
33
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
4+
use {
5+
bytemuck_derive::{Pod, Zeroable},
6+
solana_program::{program_error::ProgramError, program_option::COption, pubkey::Pubkey},
7+
solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey,
8+
};
49
#[cfg(feature = "serde-traits")]
510
use {
6-
base64::{prelude::BASE64_STANDARD, Engine},
711
serde::de::{Error, Unexpected, Visitor},
812
serde::{Deserialize, Deserializer, Serialize, Serializer},
913
std::{convert::TryFrom, fmt, str::FromStr},
1014
};
11-
use {
12-
bytemuck_derive::{Pod, Zeroable},
13-
solana_program::{program_error::ProgramError, program_option::COption, pubkey::Pubkey},
14-
solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey,
15-
};
1615

1716
/// A Pubkey that encodes `None` as all `0`, meant to be usable as a Pod type,
1817
/// similar to all NonZero* number types from the bytemuck library.
@@ -131,21 +130,21 @@ impl<'de> Deserialize<'de> for OptionalNonZeroPubkey {
131130
/// type.
132131
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
133132
#[repr(transparent)]
134-
pub struct OptionalNonZeroElGamalPubkey(ElGamalPubkey);
133+
pub struct OptionalNonZeroElGamalPubkey(PodElGamalPubkey);
135134
impl OptionalNonZeroElGamalPubkey {
136135
/// Checks equality between an OptionalNonZeroElGamalPubkey and an
137136
/// ElGamalPubkey when interpreted as bytes.
138-
pub fn equals(&self, other: &ElGamalPubkey) -> bool {
137+
pub fn equals(&self, other: &PodElGamalPubkey) -> bool {
139138
&self.0 == other
140139
}
141140
}
142-
impl TryFrom<Option<ElGamalPubkey>> for OptionalNonZeroElGamalPubkey {
141+
impl TryFrom<Option<PodElGamalPubkey>> for OptionalNonZeroElGamalPubkey {
143142
type Error = ProgramError;
144-
fn try_from(p: Option<ElGamalPubkey>) -> Result<Self, Self::Error> {
143+
fn try_from(p: Option<PodElGamalPubkey>) -> Result<Self, Self::Error> {
145144
match p {
146-
None => Ok(Self(ElGamalPubkey::default())),
145+
None => Ok(Self(PodElGamalPubkey::default())),
147146
Some(elgamal_pubkey) => {
148-
if elgamal_pubkey == ElGamalPubkey::default() {
147+
if elgamal_pubkey == PodElGamalPubkey::default() {
149148
Err(ProgramError::InvalidArgument)
150149
} else {
151150
Ok(Self(elgamal_pubkey))
@@ -154,26 +153,23 @@ impl TryFrom<Option<ElGamalPubkey>> for OptionalNonZeroElGamalPubkey {
154153
}
155154
}
156155
}
157-
impl From<OptionalNonZeroElGamalPubkey> for Option<ElGamalPubkey> {
156+
impl From<OptionalNonZeroElGamalPubkey> for Option<PodElGamalPubkey> {
158157
fn from(p: OptionalNonZeroElGamalPubkey) -> Self {
159-
if p.0 == ElGamalPubkey::default() {
158+
if p.0 == PodElGamalPubkey::default() {
160159
None
161160
} else {
162161
Some(p.0)
163162
}
164163
}
165164
}
166165

167-
#[cfg(any(feature = "serde-traits", test))]
168-
const OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN: usize = 32;
169-
170166
#[cfg(feature = "serde-traits")]
171167
impl Serialize for OptionalNonZeroElGamalPubkey {
172168
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
173169
where
174170
S: Serializer,
175171
{
176-
if self.0 == ElGamalPubkey::default() {
172+
if self.0 == PodElGamalPubkey::default() {
177173
s.serialize_none()
178174
} else {
179175
s.serialize_some(&self.0.to_string())
@@ -196,18 +192,7 @@ impl<'de> Visitor<'de> for OptionalNonZeroElGamalPubkeyVisitor {
196192
where
197193
E: Error,
198194
{
199-
let bytes = BASE64_STANDARD.decode(v).map_err(Error::custom)?;
200-
201-
if bytes.len() != OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN {
202-
return Err(Error::custom(format!(
203-
"Length of base64 decoded bytes is not {}",
204-
OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN
205-
)));
206-
}
207-
208-
let mut array = [0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN];
209-
array.copy_from_slice(&bytes[0..OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]);
210-
let elgamal_pubkey = ElGamalPubkey(array);
195+
let elgamal_pubkey: PodElGamalPubkey = FromStr::from_str(v).map_err(Error::custom)?;
211196
OptionalNonZeroElGamalPubkey::try_from(Some(elgamal_pubkey)).map_err(Error::custom)
212197
}
213198

@@ -231,7 +216,12 @@ impl<'de> Deserialize<'de> for OptionalNonZeroElGamalPubkey {
231216

232217
#[cfg(test)]
233218
mod tests {
234-
use {super::*, crate::bytemuck::pod_from_bytes, solana_program::pubkey::PUBKEY_BYTES};
219+
use {
220+
super::*,
221+
crate::bytemuck::pod_from_bytes,
222+
base64::{prelude::BASE64_STANDARD, Engine},
223+
solana_program::pubkey::PUBKEY_BYTES,
224+
};
235225

236226
#[test]
237227
fn test_pod_non_zero_option() {
@@ -290,23 +280,38 @@ mod tests {
290280
assert_eq!(optional_non_zero_pubkey_none, deserialized_none);
291281
}
292282

283+
const OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN: usize = 32;
284+
285+
// Unfortunately, the `solana-zk-sdk` does not exporse a constructor interface
286+
// to construct `PodRistrettoPoint` from bytes. As a work-around, encode the
287+
// bytes as base64 string and then convert the string to a
288+
// `PodElGamalCiphertext`.
289+
fn elgamal_pubkey_from_bytes(bytes: &[u8]) -> PodElGamalPubkey {
290+
let string = BASE64_STANDARD.encode(bytes);
291+
std::str::FromStr::from_str(&string).unwrap()
292+
}
293+
293294
#[test]
294295
fn test_pod_non_zero_elgamal_option() {
295296
assert_eq!(
296-
Some(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])),
297-
Option::<ElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(ElGamalPubkey(
298-
[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
299-
)))
297+
Some(elgamal_pubkey_from_bytes(
298+
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
299+
)),
300+
Option::<PodElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(
301+
elgamal_pubkey_from_bytes(&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])
302+
))
300303
);
301304
assert_eq!(
302305
None,
303-
Option::<ElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(ElGamalPubkey(
304-
[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
305-
)))
306+
Option::<PodElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(
307+
elgamal_pubkey_from_bytes(&[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])
308+
))
306309
);
307310

308311
assert_eq!(
309-
OptionalNonZeroElGamalPubkey(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])),
312+
OptionalNonZeroElGamalPubkey(elgamal_pubkey_from_bytes(
313+
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
314+
)),
310315
*pod_from_bytes::<OptionalNonZeroElGamalPubkey>(
311316
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
312317
)
@@ -318,8 +323,9 @@ mod tests {
318323
#[cfg(feature = "serde-traits")]
319324
#[test]
320325
fn test_pod_non_zero_elgamal_option_serde_some() {
321-
let optional_non_zero_elgamal_pubkey_some =
322-
OptionalNonZeroElGamalPubkey(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]));
326+
let optional_non_zero_elgamal_pubkey_some = OptionalNonZeroElGamalPubkey(
327+
elgamal_pubkey_from_bytes(&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]),
328+
);
323329
let serialized_some =
324330
serde_json::to_string(&optional_non_zero_elgamal_pubkey_some).unwrap();
325331
assert_eq!(
@@ -335,8 +341,9 @@ mod tests {
335341
#[cfg(feature = "serde-traits")]
336342
#[test]
337343
fn test_pod_non_zero_elgamal_option_serde_none() {
338-
let optional_non_zero_elgamal_pubkey_none =
339-
OptionalNonZeroElGamalPubkey(ElGamalPubkey([0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]));
344+
let optional_non_zero_elgamal_pubkey_none = OptionalNonZeroElGamalPubkey(
345+
elgamal_pubkey_from_bytes(&[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]),
346+
);
340347
let serialized_none =
341348
serde_json::to_string(&optional_non_zero_elgamal_pubkey_none).unwrap();
342349
assert_eq!(&serialized_none, "null");

0 commit comments

Comments
 (0)