Skip to content

Commit

Permalink
change extension bytes data to base58 encoded (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nagaprasadvr authored Jan 14, 2025
1 parent e9fce97 commit dee1c95
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 266 deletions.
201 changes: 43 additions & 158 deletions blockbuster/src/programs/token_extensions/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,12 @@ use spl_token_2022::extension::{
transfer_fee::{TransferFee, TransferFeeAmount, TransferFeeConfig},
transfer_hook::TransferHook,
};
use std::fmt;

use spl_token_group_interface::state::{TokenGroup, TokenGroupMember};
use spl_token_metadata_interface::state::TokenMetadata;

const AE_CIPHERTEXT_LEN: usize = 36;
const UNIT_LEN: usize = 32;
const RISTRETTO_POINT_LEN: usize = UNIT_LEN;
pub(crate) const DECRYPT_HANDLE_LEN: usize = RISTRETTO_POINT_LEN;
pub(crate) const PEDERSEN_COMMITMENT_LEN: usize = RISTRETTO_POINT_LEN;
const ELGAMAL_PUBKEY_LEN: usize = RISTRETTO_POINT_LEN;
const ELGAMAL_CIPHERTEXT_LEN: usize = PEDERSEN_COMMITMENT_LEN + DECRYPT_HANDLE_LEN;
type PodAccountState = u8;
pub type UnixTimestamp = PodI64;
pub type EncryptedBalance = ShadowElGamalCiphertext;
pub type DecryptableBalance = ShadowAeCiphertext;
pub type EncryptedWithheldAmount = ShadowElGamalCiphertext;

use serde::{
de::{self, SeqAccess, Visitor},
Deserializer, Serializer,
};

/// Bs58 encoded public key string. Used for storing Pubkeys in a human readable format.
/// Ideally we'd store them as is in the DB and later convert them to bs58 for display on the API.
Expand All @@ -53,19 +37,6 @@ use serde::{
/// - `Pubkey` doesn't implement something like `schemars::JsonSchema` so we can't convert them back to the rust struct either.
type PublicKeyString = String;

struct ShadowAeCiphertextVisitor;

struct ShadowElGamalCiphertextVisitor;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ShadowAeCiphertext(pub [u8; AE_CIPHERTEXT_LEN]);

#[derive(Clone, Copy, Debug, PartialEq, Zeroable)]
pub struct ShadowElGamalCiphertext(pub [u8; ELGAMAL_CIPHERTEXT_LEN]);

#[derive(Clone, Copy, Debug, Default, Zeroable, PartialEq, Eq, Serialize, Deserialize)]
pub struct ShadowElGamalPubkey(pub [u8; ELGAMAL_PUBKEY_LEN]);

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
pub struct ShadowCpiGuard {
pub lock_cpi: PodBool,
Expand Down Expand Up @@ -164,14 +135,14 @@ pub struct ShadowConfidentialTransferMint {
pub auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ShadowConfidentialTransferAccount {
pub approved: PodBool,
pub elgamal_pubkey: ShadowElGamalPubkey,
pub pending_balance_lo: EncryptedBalance,
pub pending_balance_hi: EncryptedBalance,
pub available_balance: EncryptedBalance,
pub decryptable_available_balance: DecryptableBalance,
pub elgamal_pubkey: String,
pub pending_balance_lo: String,
pub pending_balance_hi: String,
pub available_balance: String,
pub decryptable_available_balance: String,
pub allow_confidential_credits: PodBool,
pub allow_non_confidential_credits: PodBool,
pub pending_balance_credit_counter: PodU64,
Expand All @@ -180,16 +151,16 @@ pub struct ShadowConfidentialTransferAccount {
pub actual_pending_balance_credit_counter: PodU64,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ShadowConfidentialTransferFeeConfig {
pub authority: OptionalNonZeroPubkey,
pub withdraw_withheld_authority_elgamal_pubkey: ShadowElGamalPubkey,
pub withdraw_withheld_authority_elgamal_pubkey: String,
pub harvest_to_mint_enabled: PodBool,
pub withheld_amount: EncryptedWithheldAmount,
pub withheld_amount: String,
}

pub struct ShadowConfidentialTransferFeeAmount {
pub withheld_amount: EncryptedWithheldAmount,
pub withheld_amount: String,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
Expand All @@ -216,114 +187,6 @@ pub struct ShadowMetadata {
pub additional_metadata: Vec<(String, String)>,
}

impl Serialize for ShadowAeCiphertext {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&self.0)
}
}

impl<'de> Visitor<'de> for ShadowElGamalCiphertextVisitor {
type Value = ShadowElGamalCiphertext;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a byte array of length ELGAMAL_CIPHERTEXT_LEN")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
if v.len() == ELGAMAL_CIPHERTEXT_LEN {
let mut arr = [0u8; ELGAMAL_CIPHERTEXT_LEN];
arr.copy_from_slice(v);
Ok(ShadowElGamalCiphertext(arr))
} else {
Err(E::invalid_length(v.len(), &self))
}
}
}

impl<'de> Deserialize<'de> for ShadowElGamalCiphertext {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_bytes(ShadowElGamalCiphertextVisitor)
}
}

impl Default for ShadowElGamalCiphertext {
fn default() -> Self {
ShadowElGamalCiphertext([0u8; ELGAMAL_CIPHERTEXT_LEN])
}
}

impl Default for ShadowAeCiphertext {
fn default() -> Self {
ShadowAeCiphertext([0u8; AE_CIPHERTEXT_LEN])
}
}

impl<'de> Visitor<'de> for ShadowAeCiphertextVisitor {
type Value = ShadowAeCiphertext;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a byte array of length AE_CIPHERTEXT_LEN")
}

fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut arr = [0u8; AE_CIPHERTEXT_LEN];
for (i, item) in arr.iter_mut().enumerate().take(AE_CIPHERTEXT_LEN) {
*item = seq
.next_element()?
.ok_or(de::Error::invalid_length(i, &self))?;
}
Ok(ShadowAeCiphertext(arr))
}
}

impl<'de> Deserialize<'de> for ShadowAeCiphertext {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(AE_CIPHERTEXT_LEN, ShadowAeCiphertextVisitor)
}
}

impl Serialize for ShadowElGamalCiphertext {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&self.0)
}
}

impl From<AeCiphertext> for ShadowAeCiphertext {
fn from(original: AeCiphertext) -> Self {
ShadowAeCiphertext(original.0)
}
}

impl From<ElGamalCiphertext> for ShadowElGamalCiphertext {
fn from(original: ElGamalCiphertext) -> Self {
ShadowElGamalCiphertext(original.0)
}
}

impl From<ElGamalPubkey> for ShadowElGamalPubkey {
fn from(original: ElGamalPubkey) -> Self {
ShadowElGamalPubkey(original.0)
}
}

impl From<CpiGuard> for ShadowCpiGuard {
fn from(original: CpiGuard) -> Self {
ShadowCpiGuard {
Expand All @@ -343,7 +206,7 @@ impl From<DefaultAccountState> for ShadowDefaultAccountState {
impl From<ConfidentialTransferFeeAmount> for ShadowConfidentialTransferFeeAmount {
fn from(original: ConfidentialTransferFeeAmount) -> Self {
ShadowConfidentialTransferFeeAmount {
withheld_amount: original.withheld_amount.into(),
withheld_amount: original.withheld_amount.to_base58(),
}
}
}
Expand Down Expand Up @@ -384,7 +247,7 @@ impl From<TokenGroup> for ShadowTokenGroup {
fn from(original: TokenGroup) -> Self {
ShadowTokenGroup {
update_authority: original.update_authority,
mint: bs58::encode(original.mint).into_string(),
mint: original.mint.to_string(),
size: original.size,
max_size: original.max_size,
}
Expand All @@ -394,8 +257,8 @@ impl From<TokenGroup> for ShadowTokenGroup {
impl From<TokenGroupMember> for ShadowTokenGroupMember {
fn from(original: TokenGroupMember) -> Self {
ShadowTokenGroupMember {
mint: bs58::encode(original.mint).into_string(),
group: bs58::encode(original.group).into_string(),
mint: original.mint.to_string(),
group: original.group.to_string(),
member_number: original.member_number,
}
}
Expand Down Expand Up @@ -482,11 +345,11 @@ impl From<ConfidentialTransferAccount> for ShadowConfidentialTransferAccount {
fn from(original: ConfidentialTransferAccount) -> Self {
ShadowConfidentialTransferAccount {
approved: original.approved,
elgamal_pubkey: original.elgamal_pubkey.into(),
pending_balance_lo: original.pending_balance_lo.into(),
pending_balance_hi: original.pending_balance_hi.into(),
available_balance: original.available_balance.into(),
decryptable_available_balance: original.decryptable_available_balance.into(),
elgamal_pubkey: original.elgamal_pubkey.to_base58(),
pending_balance_lo: original.pending_balance_lo.to_base58(),
pending_balance_hi: original.pending_balance_hi.to_base58(),
available_balance: original.available_balance.to_base58(),
decryptable_available_balance: original.decryptable_available_balance.to_base58(),
allow_confidential_credits: original.allow_confidential_credits,
allow_non_confidential_credits: original.allow_non_confidential_credits,
pending_balance_credit_counter: original.pending_balance_credit_counter,
Expand All @@ -504,9 +367,9 @@ impl From<ConfidentialTransferFeeConfig> for ShadowConfidentialTransferFeeConfig
authority: original.authority,
withdraw_withheld_authority_elgamal_pubkey: original
.withdraw_withheld_authority_elgamal_pubkey
.into(),
.to_base58(),
harvest_to_mint_enabled: original.harvest_to_mint_enabled,
withheld_amount: original.withheld_amount.into(),
withheld_amount: original.withheld_amount.to_base58(),
}
}
}
Expand All @@ -523,3 +386,25 @@ impl From<TokenMetadata> for ShadowMetadata {
}
}
}

trait FromBytesToBase58 {
fn to_base58(&self) -> String;
}

impl FromBytesToBase58 for ElGamalPubkey {
fn to_base58(&self) -> String {
bs58::encode(self.0).into_string()
}
}

impl FromBytesToBase58 for ElGamalCiphertext {
fn to_base58(&self) -> String {
bs58::encode(self.0).into_string()
}
}

impl FromBytesToBase58 for AeCiphertext {
fn to_base58(&self) -> String {
bs58::encode(self.0).into_string()
}
}
2 changes: 1 addition & 1 deletion digital_asset_types/src/dao/scopes/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ pub async fn get_nft_editions(
Pagination::Page { page } => (Some(*page as u32), None, None, None),
Pagination::Cursor(_) => {
if let Some(last_asset) = nft_editions.last() {
let cursor_str = bs58::encode(last_asset.edition_address.clone()).into_string();
let cursor_str = last_asset.edition_address.clone();
(None, None, None, Some(cursor_str))
} else {
(None, None, None, None)
Expand Down
4 changes: 2 additions & 2 deletions digital_asset_types/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,12 @@ pub fn create_asset_grouping(
asset_grouping::ActiveModel {
asset_id: Set(asset_id.clone()),
group_key: Set(String::from("collection")),
group_value: Set(Some(bs58::encode(collection).into_string())),
group_value: Set(Some(collection.to_string())),
..Default::default()
},
asset_grouping::Model {
asset_id,
group_value: Some(bs58::encode(collection).into_string()),
group_value: Some(collection.to_string()),
seq: Some(0),
id: row_num,
group_key: "collection".to_string(),
Expand Down
19 changes: 14 additions & 5 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,25 @@ services:
ports:
- "6379:6379"
db:
image: 'postgres:14'
command: [ "postgres", "-c", "log_statement=all", "-c", "log_destination=stderr" ,"-c","max_connections=200" ]
image: "postgres:14"
command:
[
"postgres",
"-c",
"log_statement=all",
"-c",
"log_destination=stderr",
"-c",
"max_connections=200",
]
ports:
- 5432:5432
environment:
POSTGRES_USER: solana # The PostgreSQL user (useful to connect to the database)
POSTGRES_PASSWORD: solana # The PostgreSQL password (useful to connect to the database)
POSTGRES_DB: solana
volumes:
- ./db-data/:/var/lib/postgresql/data/:rw
- ./db-data/:/var/lib/postgresql/data/:z
solana:
image: ghcr.io/metaplex-foundation/plerkle-test-validator:v1.9.0-1.75.0-v1.18.11
volumes:
Expand All @@ -113,5 +122,5 @@ services:
- "8899:8899"
- "9900:9900"
volumes:
grafana_data: { }
graphite_data: { }
grafana_data: {}
graphite_data: {}
Loading

0 comments on commit dee1c95

Please sign in to comment.