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

Commit 3766c63

Browse files
[token-2022] Upgrade to zk-sdk (#7148)
1 parent 74efea0 commit 3766c63

35 files changed

+1224
-2728
lines changed

Cargo.lock

Lines changed: 9 additions & 2 deletions
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: 53 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,41 @@ 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 expose 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+
//
290+
// The constructor will be added (and this function removed) with
291+
// `solana-zk-sdk` 2.1.
292+
fn elgamal_pubkey_from_bytes(bytes: &[u8]) -> PodElGamalPubkey {
293+
let string = BASE64_STANDARD.encode(bytes);
294+
std::str::FromStr::from_str(&string).unwrap()
295+
}
296+
293297
#[test]
294298
fn test_pod_non_zero_elgamal_option() {
295299
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-
)))
300+
Some(elgamal_pubkey_from_bytes(
301+
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
302+
)),
303+
Option::<PodElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(
304+
elgamal_pubkey_from_bytes(&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])
305+
))
300306
);
301307
assert_eq!(
302308
None,
303-
Option::<ElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(ElGamalPubkey(
304-
[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
305-
)))
309+
Option::<PodElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(
310+
elgamal_pubkey_from_bytes(&[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])
311+
))
306312
);
307313

308314
assert_eq!(
309-
OptionalNonZeroElGamalPubkey(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])),
315+
OptionalNonZeroElGamalPubkey(elgamal_pubkey_from_bytes(
316+
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
317+
)),
310318
*pod_from_bytes::<OptionalNonZeroElGamalPubkey>(
311319
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
312320
)
@@ -318,8 +326,9 @@ mod tests {
318326
#[cfg(feature = "serde-traits")]
319327
#[test]
320328
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]));
329+
let optional_non_zero_elgamal_pubkey_some = OptionalNonZeroElGamalPubkey(
330+
elgamal_pubkey_from_bytes(&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]),
331+
);
323332
let serialized_some =
324333
serde_json::to_string(&optional_non_zero_elgamal_pubkey_some).unwrap();
325334
assert_eq!(
@@ -335,8 +344,9 @@ mod tests {
335344
#[cfg(feature = "serde-traits")]
336345
#[test]
337346
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]));
347+
let optional_non_zero_elgamal_pubkey_none = OptionalNonZeroElGamalPubkey(
348+
elgamal_pubkey_from_bytes(&[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]),
349+
);
340350
let serialized_none =
341351
serde_json::to_string(&optional_non_zero_elgamal_pubkey_none).unwrap();
342352
assert_eq!(&serialized_none, "null");

token/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ spl-token-2022 = { version = "4.0.0", path = "../program-2022", features = [
3535
"no-entrypoint",
3636
] }
3737
spl-token-client = { version = "0.11.0", path = "../client" }
38+
spl-token-confidential-transfer-proof-generation = { version = "0.1.0", path = "../confidential-transfer/proof-generation" }
3839
spl-token-metadata-interface = { version = "0.4.0", path = "../../token-metadata/interface" }
3940
spl-token-group-interface = { version = "0.3.0", path = "../../token-group/interface" }
4041
spl-associated-token-account = { version = "4.0.0", path = "../../associated-token-account/program", features = [

0 commit comments

Comments
 (0)