Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions Cargo.lock

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

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

[features]
serde-traits = ["dep:serde"]
borsh = ["dep:borsh", "solana-pubkey/borsh"]
serde-traits = ["dep:serde", "solana-address/decode"]
borsh = ["dep:borsh", "solana-address/borsh"]
wincode = ["dep:wincode"]

[dependencies]
Expand All @@ -20,16 +20,17 @@ num-derive = "0.4"
num_enum = "0.7"
num-traits = "0.2"
serde = { version = "1.0.228", optional = true }
wincode = { version = "0.4.4", features = ["derive"], optional = true }
solana-address = { version = "2.2.0", features = ["bytemuck"] }
solana-program-error = "3.0.0"
solana-program-option = "3.0.0"
solana-pubkey = "3.0.0"
solana-zk-sdk = "4.0.0"
thiserror = "2.0"
wincode = { version = "0.4.4", features = ["derive"], optional = true }

[dev-dependencies]
base64 = { version = "0.22.1" }
serde_json = "1.0.145"
solana-address = { version = "2.2.0", features = ["decode"] }
spl-pod = { path = ".", features = ["wincode"] }
test-case = "3.3.1"

Expand Down
2 changes: 1 addition & 1 deletion pod/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ pub mod slice;

// Export current sdk types for downstream users building with a different sdk
// version
pub use {solana_program_error, solana_program_option, solana_pubkey};
pub use {solana_address, solana_program_error, solana_program_option};
34 changes: 17 additions & 17 deletions pod/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

use {
bytemuck::{Pod, Zeroable},
solana_address::{Address, ADDRESS_BYTES},
solana_program_error::ProgramError,
solana_program_option::COption,
solana_pubkey::{Pubkey, PUBKEY_BYTES},
};

/// Trait for types that can be `None`.
Expand Down Expand Up @@ -121,42 +121,42 @@ impl<T: Nullable> TryFrom<COption<T>> for PodOption<T> {
}
}

/// Implementation of `Nullable` for `Pubkey`.
impl Nullable for Pubkey {
const NONE: Self = Pubkey::new_from_array([0u8; PUBKEY_BYTES]);
/// Implementation of `Nullable` for `Address`.
impl Nullable for Address {
const NONE: Self = Address::new_from_array([0u8; ADDRESS_BYTES]);
}

#[cfg(test)]
mod tests {
use {super::*, crate::bytemuck::pod_slice_from_bytes};
const ID: Pubkey = Pubkey::from_str_const("TestSysvar111111111111111111111111111111111");
const ID: Address = Address::from_str_const("TestSysvar111111111111111111111111111111111");

#[test]
fn test_pod_option_pubkey() {
let some_pubkey = PodOption::from(ID);
assert_eq!(some_pubkey.get(), Some(ID));
fn test_pod_option_address() {
let some_address = PodOption::from(ID);
assert_eq!(some_address.get(), Some(ID));

let none_pubkey = PodOption::from(Pubkey::default());
assert_eq!(none_pubkey.get(), None);
let none_address = PodOption::from(Address::default());
assert_eq!(none_address.get(), None);

let mut data = Vec::with_capacity(64);
data.extend_from_slice(ID.as_ref());
data.extend_from_slice(&[0u8; 32]);

let values = pod_slice_from_bytes::<PodOption<Pubkey>>(&data).unwrap();
let values = pod_slice_from_bytes::<PodOption<Address>>(&data).unwrap();
assert_eq!(values[0], PodOption::from(ID));
assert_eq!(values[1], PodOption::from(Pubkey::default()));
assert_eq!(values[1], PodOption::from(Address::default()));

let option_pubkey = Some(ID);
let pod_option_pubkey: PodOption<Pubkey> = option_pubkey.try_into().unwrap();
let pod_option_pubkey: PodOption<Address> = option_pubkey.try_into().unwrap();
assert_eq!(pod_option_pubkey, PodOption::from(ID));
assert_eq!(
pod_option_pubkey,
PodOption::try_from(option_pubkey).unwrap()
);

let coption_pubkey = COption::Some(ID);
let pod_option_pubkey: PodOption<Pubkey> = coption_pubkey.try_into().unwrap();
let pod_option_pubkey: PodOption<Address> = coption_pubkey.try_into().unwrap();
assert_eq!(pod_option_pubkey, PodOption::from(ID));
assert_eq!(
pod_option_pubkey,
Expand All @@ -172,17 +172,17 @@ mod tests {
let none_pubkey = None;
assert_eq!(
PodOption::try_from(none_pubkey).unwrap(),
PodOption::from(Pubkey::NONE)
PodOption::from(Address::NONE)
);

let invalid_option = Some(Pubkey::NONE);
let invalid_option = Some(Address::NONE);
let err = PodOption::try_from(invalid_option).unwrap_err();
assert_eq!(err, ProgramError::InvalidArgument);
}

#[test]
fn test_default() {
let def = PodOption::<Pubkey>::default();
let def = PodOption::<Address>::default();
assert_eq!(def, None.try_into().unwrap());
}
}
50 changes: 25 additions & 25 deletions pod/src/optional_keys.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Optional pubkeys that can be used a `Pod`s
//! Optional addresses that can be used a `Pod`s
#[cfg(feature = "borsh")]
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use {
bytemuck_derive::{Pod, Zeroable},
solana_address::Address,
solana_program_error::ProgramError,
solana_program_option::COption,
solana_pubkey::Pubkey,
solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey,
};
#[cfg(feature = "serde-traits")]
Expand All @@ -23,14 +23,14 @@ use {
)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
#[repr(transparent)]
pub struct OptionalNonZeroPubkey(pub Pubkey);
impl TryFrom<Option<Pubkey>> for OptionalNonZeroPubkey {
pub struct OptionalNonZeroPubkey(pub Address);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not going to rename OptionalNonZeroPubkey as we have an upcoming update to migrate this functionality to PodOption

impl TryFrom<Option<Address>> for OptionalNonZeroPubkey {
type Error = ProgramError;
fn try_from(p: Option<Pubkey>) -> Result<Self, Self::Error> {
fn try_from(p: Option<Address>) -> Result<Self, Self::Error> {
match p {
None => Ok(Self(Pubkey::default())),
None => Ok(Self(Address::default())),
Some(pubkey) => {
if pubkey == Pubkey::default() {
if pubkey == Address::default() {
Err(ProgramError::InvalidArgument)
} else {
Ok(Self(pubkey))
Expand All @@ -39,13 +39,13 @@ impl TryFrom<Option<Pubkey>> for OptionalNonZeroPubkey {
}
}
}
impl TryFrom<COption<Pubkey>> for OptionalNonZeroPubkey {
impl TryFrom<COption<Address>> for OptionalNonZeroPubkey {
type Error = ProgramError;
fn try_from(p: COption<Pubkey>) -> Result<Self, Self::Error> {
fn try_from(p: COption<Address>) -> Result<Self, Self::Error> {
match p {
COption::None => Ok(Self(Pubkey::default())),
COption::None => Ok(Self(Address::default())),
COption::Some(pubkey) => {
if pubkey == Pubkey::default() {
if pubkey == Address::default() {
Err(ProgramError::InvalidArgument)
} else {
Ok(Self(pubkey))
Expand All @@ -54,18 +54,18 @@ impl TryFrom<COption<Pubkey>> for OptionalNonZeroPubkey {
}
}
}
impl From<OptionalNonZeroPubkey> for Option<Pubkey> {
impl From<OptionalNonZeroPubkey> for Option<Address> {
fn from(p: OptionalNonZeroPubkey) -> Self {
if p.0 == Pubkey::default() {
if p.0 == Address::default() {
None
} else {
Some(p.0)
}
}
}
impl From<OptionalNonZeroPubkey> for COption<Pubkey> {
impl From<OptionalNonZeroPubkey> for COption<Address> {
fn from(p: OptionalNonZeroPubkey) -> Self {
if p.0 == Pubkey::default() {
if p.0 == Address::default() {
COption::None
} else {
COption::Some(p.0)
Expand All @@ -79,7 +79,7 @@ impl Serialize for OptionalNonZeroPubkey {
where
S: Serializer,
{
if self.0 == Pubkey::default() {
if self.0 == Address::default() {
s.serialize_none()
} else {
s.serialize_some(&self.0.to_string())
Expand All @@ -103,7 +103,7 @@ impl Visitor<'_> for OptionalNonZeroPubkeyVisitor {
where
E: Error,
{
let pkey = Pubkey::from_str(v)
let pkey = Address::from_str(v)
.map_err(|_| Error::invalid_value(Unexpected::Str(v), &"value string"))?;

OptionalNonZeroPubkey::try_from(Some(pkey))
Expand Down Expand Up @@ -222,21 +222,21 @@ mod tests {
super::*,
crate::bytemuck::pod_from_bytes,
base64::{prelude::BASE64_STANDARD, Engine},
solana_pubkey::PUBKEY_BYTES,
solana_address::ADDRESS_BYTES,
};

#[test]
fn test_pod_non_zero_option() {
assert_eq!(
Some(Pubkey::new_from_array([1; PUBKEY_BYTES])),
Option::<Pubkey>::from(
*pod_from_bytes::<OptionalNonZeroPubkey>(&[1; PUBKEY_BYTES]).unwrap()
Some(Address::new_from_array([1; ADDRESS_BYTES])),
Option::<Address>::from(
*pod_from_bytes::<OptionalNonZeroPubkey>(&[1; ADDRESS_BYTES]).unwrap()
)
);
assert_eq!(
None,
Option::<Pubkey>::from(
*pod_from_bytes::<OptionalNonZeroPubkey>(&[0; PUBKEY_BYTES]).unwrap()
Option::<Address>::from(
*pod_from_bytes::<OptionalNonZeroPubkey>(&[0; ADDRESS_BYTES]).unwrap()
)
);
assert_eq!(
Expand All @@ -257,7 +257,7 @@ mod tests {
#[test]
fn test_pod_non_zero_option_serde_some() {
let optional_non_zero_pubkey_some =
OptionalNonZeroPubkey(Pubkey::new_from_array([1; PUBKEY_BYTES]));
OptionalNonZeroPubkey(Address::new_from_array([1; ADDRESS_BYTES]));
let serialized_some = serde_json::to_string(&optional_non_zero_pubkey_some).unwrap();
assert_eq!(
&serialized_some,
Expand All @@ -273,7 +273,7 @@ mod tests {
#[test]
fn test_pod_non_zero_option_serde_none() {
let optional_non_zero_pubkey_none =
OptionalNonZeroPubkey(Pubkey::new_from_array([0; PUBKEY_BYTES]));
OptionalNonZeroPubkey(Address::new_from_array([0; ADDRESS_BYTES]));
let serialized_none = serde_json::to_string(&optional_non_zero_pubkey_none).unwrap();
assert_eq!(&serialized_none, "null");

Expand Down
Loading