Skip to content

Commit

Permalink
[token-2022] Upgrade to zk-sdk (#7148)
Browse files Browse the repository at this point in the history
  • Loading branch information
samkim-crypto authored Aug 16, 2024
1 parent 74efea0 commit 3766c63
Show file tree
Hide file tree
Showing 35 changed files with 1,224 additions and 2,728 deletions.
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions libraries/pod/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ license = "Apache-2.0"
edition = "2021"

[features]
serde-traits = ["dep:serde", "dep:base64"]
serde-traits = ["dep:serde"]
borsh = ["dep:borsh"]

[dependencies]
base64 = { version = "0.22.1", optional = true }
borsh = { version = "1.5.1", optional = true }
bytemuck = { version = "1.16.3" }
bytemuck_derive = { version = "1.7.0" }
serde = { version = "1.0.207", optional = true }
solana-program = "2.0.3"
solana-zk-token-sdk = "2.0.3"
solana-zk-sdk = "2.0.3"
spl-program-error = { version = "0.5.0", path = "../program-error" }

[dev-dependencies]
serde_json = "1.0.124"
base64 = { version = "0.22.1" }

[lib]
crate-type = ["cdylib", "lib"]
Expand Down
96 changes: 53 additions & 43 deletions libraries/pod/src/optional_keys.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
//! Optional pubkeys that can be used a `Pod`s
#[cfg(feature = "borsh")]
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use {
bytemuck_derive::{Pod, Zeroable},
solana_program::{program_error::ProgramError, program_option::COption, pubkey::Pubkey},
solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey,
};
#[cfg(feature = "serde-traits")]
use {
base64::{prelude::BASE64_STANDARD, Engine},
serde::de::{Error, Unexpected, Visitor},
serde::{Deserialize, Deserializer, Serialize, Serializer},
std::{convert::TryFrom, fmt, str::FromStr},
};
use {
bytemuck_derive::{Pod, Zeroable},
solana_program::{program_error::ProgramError, program_option::COption, pubkey::Pubkey},
solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey,
};

/// A Pubkey that encodes `None` as all `0`, meant to be usable as a Pod type,
/// similar to all NonZero* number types from the bytemuck library.
Expand Down Expand Up @@ -131,21 +130,21 @@ impl<'de> Deserialize<'de> for OptionalNonZeroPubkey {
/// type.
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
#[repr(transparent)]
pub struct OptionalNonZeroElGamalPubkey(ElGamalPubkey);
pub struct OptionalNonZeroElGamalPubkey(PodElGamalPubkey);
impl OptionalNonZeroElGamalPubkey {
/// Checks equality between an OptionalNonZeroElGamalPubkey and an
/// ElGamalPubkey when interpreted as bytes.
pub fn equals(&self, other: &ElGamalPubkey) -> bool {
pub fn equals(&self, other: &PodElGamalPubkey) -> bool {
&self.0 == other
}
}
impl TryFrom<Option<ElGamalPubkey>> for OptionalNonZeroElGamalPubkey {
impl TryFrom<Option<PodElGamalPubkey>> for OptionalNonZeroElGamalPubkey {
type Error = ProgramError;
fn try_from(p: Option<ElGamalPubkey>) -> Result<Self, Self::Error> {
fn try_from(p: Option<PodElGamalPubkey>) -> Result<Self, Self::Error> {
match p {
None => Ok(Self(ElGamalPubkey::default())),
None => Ok(Self(PodElGamalPubkey::default())),
Some(elgamal_pubkey) => {
if elgamal_pubkey == ElGamalPubkey::default() {
if elgamal_pubkey == PodElGamalPubkey::default() {
Err(ProgramError::InvalidArgument)
} else {
Ok(Self(elgamal_pubkey))
Expand All @@ -154,26 +153,23 @@ impl TryFrom<Option<ElGamalPubkey>> for OptionalNonZeroElGamalPubkey {
}
}
}
impl From<OptionalNonZeroElGamalPubkey> for Option<ElGamalPubkey> {
impl From<OptionalNonZeroElGamalPubkey> for Option<PodElGamalPubkey> {
fn from(p: OptionalNonZeroElGamalPubkey) -> Self {
if p.0 == ElGamalPubkey::default() {
if p.0 == PodElGamalPubkey::default() {
None
} else {
Some(p.0)
}
}
}

#[cfg(any(feature = "serde-traits", test))]
const OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN: usize = 32;

#[cfg(feature = "serde-traits")]
impl Serialize for OptionalNonZeroElGamalPubkey {
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if self.0 == ElGamalPubkey::default() {
if self.0 == PodElGamalPubkey::default() {
s.serialize_none()
} else {
s.serialize_some(&self.0.to_string())
Expand All @@ -196,18 +192,7 @@ impl<'de> Visitor<'de> for OptionalNonZeroElGamalPubkeyVisitor {
where
E: Error,
{
let bytes = BASE64_STANDARD.decode(v).map_err(Error::custom)?;

if bytes.len() != OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN {
return Err(Error::custom(format!(
"Length of base64 decoded bytes is not {}",
OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN
)));
}

let mut array = [0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN];
array.copy_from_slice(&bytes[0..OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]);
let elgamal_pubkey = ElGamalPubkey(array);
let elgamal_pubkey: PodElGamalPubkey = FromStr::from_str(v).map_err(Error::custom)?;
OptionalNonZeroElGamalPubkey::try_from(Some(elgamal_pubkey)).map_err(Error::custom)
}

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

#[cfg(test)]
mod tests {
use {super::*, crate::bytemuck::pod_from_bytes, solana_program::pubkey::PUBKEY_BYTES};
use {
super::*,
crate::bytemuck::pod_from_bytes,
base64::{prelude::BASE64_STANDARD, Engine},
solana_program::pubkey::PUBKEY_BYTES,
};

#[test]
fn test_pod_non_zero_option() {
Expand Down Expand Up @@ -290,23 +280,41 @@ mod tests {
assert_eq!(optional_non_zero_pubkey_none, deserialized_none);
}

const OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN: usize = 32;

// Unfortunately, the `solana-zk-sdk` does not expose a constructor interface
// to construct `PodRistrettoPoint` from bytes. As a work-around, encode the
// bytes as base64 string and then convert the string to a
// `PodElGamalCiphertext`.
//
// The constructor will be added (and this function removed) with
// `solana-zk-sdk` 2.1.
fn elgamal_pubkey_from_bytes(bytes: &[u8]) -> PodElGamalPubkey {
let string = BASE64_STANDARD.encode(bytes);
std::str::FromStr::from_str(&string).unwrap()
}

#[test]
fn test_pod_non_zero_elgamal_option() {
assert_eq!(
Some(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])),
Option::<ElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(ElGamalPubkey(
[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
)))
Some(elgamal_pubkey_from_bytes(
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
)),
Option::<PodElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(
elgamal_pubkey_from_bytes(&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])
))
);
assert_eq!(
None,
Option::<ElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(ElGamalPubkey(
[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
)))
Option::<PodElGamalPubkey>::from(OptionalNonZeroElGamalPubkey(
elgamal_pubkey_from_bytes(&[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])
))
);

assert_eq!(
OptionalNonZeroElGamalPubkey(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN])),
OptionalNonZeroElGamalPubkey(elgamal_pubkey_from_bytes(
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
)),
*pod_from_bytes::<OptionalNonZeroElGamalPubkey>(
&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]
)
Expand All @@ -318,8 +326,9 @@ mod tests {
#[cfg(feature = "serde-traits")]
#[test]
fn test_pod_non_zero_elgamal_option_serde_some() {
let optional_non_zero_elgamal_pubkey_some =
OptionalNonZeroElGamalPubkey(ElGamalPubkey([1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]));
let optional_non_zero_elgamal_pubkey_some = OptionalNonZeroElGamalPubkey(
elgamal_pubkey_from_bytes(&[1; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]),
);
let serialized_some =
serde_json::to_string(&optional_non_zero_elgamal_pubkey_some).unwrap();
assert_eq!(
Expand All @@ -335,8 +344,9 @@ mod tests {
#[cfg(feature = "serde-traits")]
#[test]
fn test_pod_non_zero_elgamal_option_serde_none() {
let optional_non_zero_elgamal_pubkey_none =
OptionalNonZeroElGamalPubkey(ElGamalPubkey([0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]));
let optional_non_zero_elgamal_pubkey_none = OptionalNonZeroElGamalPubkey(
elgamal_pubkey_from_bytes(&[0; OPTIONAL_NONZERO_ELGAMAL_PUBKEY_LEN]),
);
let serialized_none =
serde_json::to_string(&optional_non_zero_elgamal_pubkey_none).unwrap();
assert_eq!(&serialized_none, "null");
Expand Down
1 change: 1 addition & 0 deletions token/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ spl-token-2022 = { version = "4.0.0", path = "../program-2022", features = [
"no-entrypoint",
] }
spl-token-client = { version = "0.11.0", path = "../client" }
spl-token-confidential-transfer-proof-generation = { version = "0.1.0", path = "../confidential-transfer/proof-generation" }
spl-token-metadata-interface = { version = "0.4.0", path = "../../token-metadata/interface" }
spl-token-group-interface = { version = "0.3.0", path = "../../token-group/interface" }
spl-associated-token-account = { version = "4.0.0", path = "../../associated-token-account/program", features = [
Expand Down
Loading

0 comments on commit 3766c63

Please sign in to comment.