Skip to content

Commit

Permalink
Add non-inclusion proof support (helius-labs#105)
Browse files Browse the repository at this point in the history
* Bump version

* Add missing test cases

* Add missing files

* Bug fix

* Bump version
  • Loading branch information
pmantica11 authored Jun 12, 2024
1 parent d0f447e commit 8999d7e
Show file tree
Hide file tree
Showing 39 changed files with 1,964 additions and 131 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "photon-indexer"
publish = true
readme = "README.md"
repository = "https://github.com/helius-labs/photon"
version = "0.21.0"
version = "0.23.0"

[[bin]]
name = "photon"
Expand Down
23 changes: 20 additions & 3 deletions src/api/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ use super::method::get_compression_signatures_for_token_owner::{
};
use super::method::get_latest_compression_signatures::get_latest_compression_signatures;
use super::method::get_latest_non_voting_signatures::get_latest_non_voting_signatures;
use super::method::get_multiple_new_address_proofs::{
get_multiple_new_address_proofs, AddressList, GetMultipleNewAddressProofsResponse,
};
use super::method::get_transaction_with_compression_info::{
get_transaction_with_compression_info, GetTransactionRequest, GetTransactionResponse,
};
use super::method::get_validity_proof::{get_validity_proof, CompressedProofWithContext};
use super::method::get_validity_proof::{
get_validity_proof, CompressedProofWithContext, GetValidityProofRequest,
};
use super::method::utils::GetLatestSignaturesRequest;
use super::method::utils::{AccountBalanceResponse, GetPaginatedSignaturesResponse, HashRequest};
use super::{
Expand Down Expand Up @@ -148,6 +153,13 @@ impl PhotonApi {
get_multiple_compressed_account_proofs(self.db_conn.as_ref(), request).await
}

pub async fn get_multiple_new_address_proofs(
&self,
request: AddressList,
) -> Result<GetMultipleNewAddressProofsResponse, PhotonApiError> {
get_multiple_new_address_proofs(self.db_conn.as_ref(), request).await
}

pub async fn get_compressed_token_accounts_by_owner(
&self,
request: GetCompressedTokenAccountsByOwner,
Expand Down Expand Up @@ -254,7 +266,7 @@ impl PhotonApi {

pub async fn get_validity_proof(
&self,
request: HashList,
request: GetValidityProofRequest,
) -> Result<CompressedProofWithContext, PhotonApiError> {
get_validity_proof(self.db_conn.as_ref(), request).await
}
Expand Down Expand Up @@ -290,9 +302,14 @@ impl PhotonApi {
request: Some(HashList::schema().1),
response: GetMultipleCompressedAccountProofsResponse::schema().1,
},
OpenApiSpec {
name: "getMultipleNewAddressProofs".to_string(),
request: Some(AddressList::schema().1),
response: GetMultipleNewAddressProofsResponse::schema().1,
},
OpenApiSpec {
name: "getValidityProof".to_string(),
request: Some(HashList::schema().1),
request: Some(GetValidityProofRequest::schema().1),
response: CompressedProofWithContext::schema().1,
},
OpenApiSpec {
Expand Down
86 changes: 86 additions & 0 deletions src/api/method/get_multiple_new_address_proofs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use sea_orm::DatabaseConnection;
use serde::{Deserialize, Serialize};
use solana_program::pubkey;
use solana_sdk::pubkey::Pubkey;
use utoipa::ToSchema;

use crate::api::error::PhotonApiError;
use crate::common::typedefs::hash::Hash;
use crate::common::typedefs::serializable_pubkey::SerializablePubkey;
use crate::ingester::persist::persisted_indexed_merkle_tree::get_exclusion_range_with_proof;

const ADDRESS_TREE_HEIGHT: u32 = 27;
const ADDRESS_TREE_ADDRESS: Pubkey = pubkey!("C83cpRN6oaafjNgMQJvaYgAz592EP5wunKvbokeTKPLn");

use super::utils::Context;

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct MerkleContextWithNewAddressProof {
pub root: Hash,
pub address: SerializablePubkey,
pub lower_range_address: SerializablePubkey,
pub higher_range_address: SerializablePubkey,
pub leaf_index: u32,
pub proof: Vec<Hash>,
pub merkle_tree: SerializablePubkey,
pub root_seq: u64,
pub low_element_leaf_index: u32,
}

// We do not use generics to simplify documentation generation.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct GetMultipleNewAddressProofsResponse {
pub context: Context,
pub value: Vec<MerkleContextWithNewAddressProof>,
}

pub async fn get_multiple_new_address_proofs_helper(
conn: &DatabaseConnection,
addresses: Vec<SerializablePubkey>,
) -> Result<Vec<MerkleContextWithNewAddressProof>, PhotonApiError> {
if addresses.is_empty() {
return Err(PhotonApiError::ValidationError(
"No addresses provided".to_string(),
));
}
let mut new_address_proofs: Vec<MerkleContextWithNewAddressProof> = Vec::new();

for address in addresses {
let (model, proof) = get_exclusion_range_with_proof(
conn,
ADDRESS_TREE_ADDRESS.to_bytes().to_vec(),
ADDRESS_TREE_HEIGHT,
address.to_bytes_vec(),
)
.await?;
let new_address_proof = MerkleContextWithNewAddressProof {
root: proof.root,
address,
lower_range_address: SerializablePubkey::try_from(model.value)?,
higher_range_address: SerializablePubkey::try_from(model.next_value)?,
leaf_index: model.next_index as u32,
proof: proof.proof,
low_element_leaf_index: model.leaf_index as u32,
merkle_tree: SerializablePubkey::from(ADDRESS_TREE_ADDRESS),
root_seq: proof.root_seq as u64,
};
new_address_proofs.push(new_address_proof);
}
Ok(new_address_proofs)
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
pub struct AddressList(pub Vec<SerializablePubkey>);

pub async fn get_multiple_new_address_proofs(
conn: &DatabaseConnection,
addresses: AddressList,
) -> Result<GetMultipleNewAddressProofsResponse, PhotonApiError> {
let context = Context::extract(conn).await?;
let new_address_proofs = get_multiple_new_address_proofs_helper(conn, addresses.0).await?;

Ok(GetMultipleNewAddressProofsResponse {
value: new_address_proofs,
context,
})
}
Loading

0 comments on commit 8999d7e

Please sign in to comment.