Skip to content
Open
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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/apollo_class_manager_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ tokio.workspace = true
apollo_proof_manager_types = { workspace = true, features = ["testing"] }
assert_matches.workspace = true
blockifier = { workspace = true, features = ["testing"] }
blockifier_test_utils.workspace = true
mempool_test_utils.workspace = true
mockall.workspace = true
rstest.workspace = true
Expand Down
28 changes: 26 additions & 2 deletions crates/apollo_class_manager_types/src/transaction_converter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use apollo_proof_manager_types::SharedProofManagerClient;
use apollo_proof_manager_types::{ProofManagerClientError, SharedProofManagerClient};
use async_trait::async_trait;
#[cfg(any(feature = "testing", test))]
use mockall::automock;
Expand Down Expand Up @@ -41,6 +41,8 @@ pub enum TransactionConverterError {
#[error("Class of hash: {class_hash} not found")]
ClassNotFound { class_hash: ClassHash },
#[error(transparent)]
ProofManagerClientError(#[from] ProofManagerClientError),
#[error(transparent)]
StarknetApiError(#[from] StarknetApiError),
#[error(transparent)]
ValidateCompiledClassHashError(#[from] ValidateCompiledClassHashError),
Expand Down Expand Up @@ -200,7 +202,10 @@ impl TransactionConverterTrait for TransactionConverter {
tx: RpcTransaction,
) -> TransactionConverterResult<InternalRpcTransaction> {
let tx_without_hash = match tx {
RpcTransaction::Invoke(tx) => InternalRpcTransactionWithoutTxHash::Invoke(tx.into()),
RpcTransaction::Invoke(RpcInvokeTransaction::V3(tx)) => {
self._handle_proof_verification(&tx.proof_facts, &tx.proof).await?;
InternalRpcTransactionWithoutTxHash::Invoke(tx.into())
}
RpcTransaction::Declare(RpcDeclareTransaction::V3(tx)) => {
let ClassHashes { class_hash, executable_class_hash_v2 } =
self.class_manager_client.add_class(tx.contract_class).await?;
Expand Down Expand Up @@ -310,6 +315,25 @@ impl TransactionConverter {
)?)
}

async fn _handle_proof_verification(
&self,
proof_facts: &ProofFacts,
proof: &Proof,
) -> TransactionConverterResult<()> {
if proof_facts.is_empty() {
return Ok(());
}

let contains_proof = self.proof_manager_client.contains_proof(proof_facts.clone()).await?;
if contains_proof {
return Ok(());
}

self._verify_proof(proof_facts.clone(), proof.clone())?;
self.proof_manager_client.set_proof(proof_facts.clone(), proof.clone()).await?;
Ok(())
}

fn _verify_proof(
&self,
_proof_facts: ProofFacts,
Expand Down
101 changes: 99 additions & 2 deletions crates/apollo_class_manager_types/src/transaction_converter_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ use std::sync::Arc;
use apollo_proof_manager_types::MockProofManagerClient;
use assert_matches::assert_matches;
use blockifier::context::ChainInfo;
use mempool_test_utils::starknet_api_test_utils::declare_tx;
use blockifier_test_utils::cairo_versions::{CairoVersion, RunnableCairo1};
use mempool_test_utils::starknet_api_test_utils::{
declare_tx,
invoke_tx,
invoke_tx_client_side_proving,
};
use mockall::predicate::eq;
use rstest::rstest;
use starknet_api::compiled_class_hash;
use starknet_api::executable_transaction::ValidateCompiledClassHashError;
use starknet_api::rpc_transaction::{RpcDeclareTransaction, RpcTransaction};
use starknet_api::transaction::fields::Proof;
use starknet_api::{compiled_class_hash, felt, proof_facts};

use crate::transaction_converter::{
TransactionConverter,
Expand Down Expand Up @@ -56,3 +62,94 @@ async fn test_compiled_class_hash_mismatch() {
);
assert_eq!(err, expected_code);
}

#[rstest]
#[tokio::test]
async fn test_proof_verification_called_for_invoke_v3_with_proof_facts() {
// Create an invoke transaction with proof_facts and proof.
let proof_facts = proof_facts![felt!("0x1"), felt!("0x2"), felt!("0x3")];
let proof = Proof::from(vec![1u32, 2u32, 3u32]);
let invoke_tx = invoke_tx_client_side_proving(
CairoVersion::Cairo1(RunnableCairo1::Casm),
proof_facts.clone(),
proof.clone(),
);

let mut mock_proof_manager_client = MockProofManagerClient::new();
mock_proof_manager_client
.expect_contains_proof()
.once()
.with(eq(proof_facts.clone()))
.return_once(|_| Ok(false));
mock_proof_manager_client
.expect_set_proof()
.once()
.with(eq(proof_facts), eq(proof))
.return_once(|_, _| Ok(()));

let mock_class_manager_client = MockClassManagerClient::new();

let transaction_converter = TransactionConverter::new(
Arc::new(mock_class_manager_client),
Arc::new(mock_proof_manager_client),
ChainInfo::create_for_testing().chain_id,
);

// Convert the RPC transaction to an internal RPC transaction.
transaction_converter.convert_rpc_tx_to_internal_rpc_tx(invoke_tx).await.unwrap();
}

#[rstest]
#[tokio::test]
async fn test_proof_verification_skipped_for_invoke_v3_without_proof_facts() {
// Create an invoke transaction without proof_facts.
let invoke_tx = invoke_tx(CairoVersion::Cairo1(RunnableCairo1::Casm));

// Mock proof manager client expects NO calls to contains_proof or set_proof.
let mock_proof_manager_client = MockProofManagerClient::new();
let mock_class_manager_client = MockClassManagerClient::new();

let transaction_converter = TransactionConverter::new(
Arc::new(mock_class_manager_client),
Arc::new(mock_proof_manager_client),
ChainInfo::create_for_testing().chain_id,
);

// Convert the RPC transaction to an internal RPC transaction.
// This should succeed without calling contains_proof or set_proof.
transaction_converter.convert_rpc_tx_to_internal_rpc_tx(invoke_tx).await.unwrap();
}

#[rstest]
#[tokio::test]
async fn test_proof_verification_skipped_when_proof_already_exists() {
// Create an invoke transaction with proof_facts and proof.
let proof_facts = proof_facts![felt!("0x1"), felt!("0x2"), felt!("0x3")];
let proof = Proof::from(vec![1u32, 2u32, 3u32]);
let invoke_tx = invoke_tx_client_side_proving(
CairoVersion::Cairo1(RunnableCairo1::Casm),
proof_facts.clone(),
proof.clone(),
);

let mut mock_proof_manager_client = MockProofManagerClient::new();
// Expect contains_proof to be called and return true (proof already exists).
mock_proof_manager_client
.expect_contains_proof()
.once()
.with(eq(proof_facts))
.return_once(|_| Ok(true));
// Since proof already exists, expect set_proof to NOT be called.

let mock_class_manager_client = MockClassManagerClient::new();

let transaction_converter = TransactionConverter::new(
Arc::new(mock_class_manager_client),
Arc::new(mock_proof_manager_client),
ChainInfo::create_for_testing().chain_id,
);

// Convert the RPC transaction to an internal RPC transaction.
// This should succeed and only call contains_proof, not set_proof.
transaction_converter.convert_rpc_tx_to_internal_rpc_tx(invoke_tx).await.unwrap();
}
3 changes: 3 additions & 0 deletions crates/apollo_gateway/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ pub fn transaction_converter_err_to_deprecated_gw_err(
err: TransactionConverterError,
) -> StarknetError {
match err {
TransactionConverterError::ProofManagerClientError(err) => {
StarknetError::internal_with_logging("Proof manager client error", err)
}
TransactionConverterError::ValidateCompiledClassHashError(err) => {
convert_compiled_class_hash_error(err)
}
Expand Down
6 changes: 0 additions & 6 deletions crates/apollo_gateway/src/stateless_transaction_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ impl StatelessTransactionValidator {
self.validate_tx_size(tx)?;
self.validate_nonce_data_availability_mode(tx)?;
self.validate_fee_data_availability_mode(tx)?;
self.validate_proof(tx)?;

if let RpcTransaction::Declare(declare_tx) = tx {
self.validate_declare_tx(declare_tx)?;
Expand Down Expand Up @@ -219,11 +218,6 @@ impl StatelessTransactionValidator {
Ok(())
}

fn validate_proof(&self, _: &RpcTransaction) -> StatelessTransactionValidatorResult<()> {
// TODO(Einat): Implement proof validation.
Ok(())
}

fn validate_declare_tx(
&self,
declare_tx: &RpcDeclareTransaction,
Expand Down
2 changes: 1 addition & 1 deletion crates/apollo_proof_manager_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub enum ProofManagerError {
Io(String),
}

#[derive(Clone, Debug, Error)]
#[derive(Clone, Debug, Error, PartialEq)]
pub enum ProofManagerClientError {
#[error(transparent)]
ClientError(#[from] ClientError),
Expand Down
Loading