Skip to content

Commit

Permalink
fix(gateway): use compressed sierra for declare
Browse files Browse the repository at this point in the history
  • Loading branch information
jbcaron committed Jan 9, 2025
1 parent 73d8079 commit 539063c
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 46 deletions.
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Next release

- refactor(gateway): remove query-only support from user transactions
- fix(gateway): serialize tip as hex in UserTransaction
- fix(gateway): serialize `tip` as hex in UserTransaction
- fix(block_production): dynamic block closing now adds special address with prev block hash
- fix(rpc): call, simulate, estimate rpcs executed on top of the block, not at the start of it
- fix(compilation): crate-level compilation
Expand Down Expand Up @@ -503,7 +503,6 @@

## v0.4.0

- fix(gateway): serialize `tip` as hex in UserTransaction
- chore: release v0.4.0
- feat: better management of custom configurations for genesis assets
- feat: use actual vm resource costs
Expand Down
6 changes: 4 additions & 2 deletions crates/madara/client/gateway/server/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use mp_utils::service::ServiceContext;
use serde::Serialize;
use serde_json::json;
use starknet_types_core::felt::Felt;
use starknet_types_rpc::TraceBlockTransactionsResult;
use starknet_types_rpc::{BroadcastedDeclareTxn, TraceBlockTransactionsResult};

use super::{
error::{GatewayError, OptionExt, ResultExt},
Expand Down Expand Up @@ -349,7 +349,9 @@ async fn declare_transaction(
tx: UserDeclareTransaction,
add_transaction_provider: Arc<dyn AddTransactionProvider>,
) -> Response<String> {
match add_transaction_provider.add_declare_transaction(tx.into()).await {
let tx: BroadcastedDeclareTxn<Felt> = tx.try_into().unwrap();

match add_transaction_provider.add_declare_transaction(tx).await {
Ok(result) => create_json_response(hyper::StatusCode::OK, &result),
Err(e) => create_json_response(hyper::StatusCode::OK, &e),
}
Expand Down
9 changes: 5 additions & 4 deletions crates/madara/primitives/class/src/into_starknet_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
};

impl TryFrom<starknet_types_rpc::MaybeDeprecatedContractClass<Felt>> for ContractClass {
type Error = base64::DecodeError;
type Error = std::io::Error;

fn try_from(contract_class: starknet_types_rpc::MaybeDeprecatedContractClass<Felt>) -> Result<Self, Self::Error> {
match contract_class {
Expand Down Expand Up @@ -123,15 +123,16 @@ impl From<SierraEntryPoint> for starknet_types_rpc::SierraEntryPoint<Felt> {
}

impl TryFrom<starknet_types_rpc::DeprecatedContractClass<Felt>> for CompressedLegacyContractClass {
type Error = base64::DecodeError;
type Error = std::io::Error;

fn try_from(
compressed_legacy_contract_class: starknet_types_rpc::DeprecatedContractClass<Felt>,
) -> Result<Self, Self::Error> {
use base64::Engine;

let decoded_program =
base64::engine::general_purpose::STANDARD.decode(&compressed_legacy_contract_class.program)?;
let decoded_program = base64::engine::general_purpose::STANDARD
.decode(&compressed_legacy_contract_class.program)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;

Ok(CompressedLegacyContractClass {
program: decoded_program,
Expand Down
50 changes: 50 additions & 0 deletions crates/madara/primitives/class/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,56 @@ impl FlattenedSierraClass {
}
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct CompressedSierraClass {
/// The gzipped compressed program as a base64 string.
pub sierra_program: String,
pub contract_class_version: String,
pub entry_points_by_type: EntryPointsByType,
pub abi: String,
}

impl TryFrom<FlattenedSierraClass> for CompressedSierraClass {
type Error = std::io::Error;

fn try_from(flattened_sierra_class: FlattenedSierraClass) -> Result<Self, Self::Error> {
let mut base64_encoder =
base64::write::EncoderWriter::new(Vec::new(), &base64::engine::general_purpose::STANDARD);
let mut gzip_encoder = flate2::write::GzEncoder::new(&mut base64_encoder, flate2::Compression::default());
serde_json::to_writer(&mut gzip_encoder, &flattened_sierra_class.sierra_program)?;
gzip_encoder.try_finish()?;
drop(gzip_encoder);
base64_encoder.finish().map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "base64 encoding error"))?;
let sierra_program = String::from_utf8(base64_encoder.into_inner()).unwrap();

Ok(Self {
sierra_program,
contract_class_version: flattened_sierra_class.contract_class_version,
entry_points_by_type: flattened_sierra_class.entry_points_by_type,
abi: flattened_sierra_class.abi,
})
}
}

impl TryFrom<CompressedSierraClass> for FlattenedSierraClass {
type Error = std::io::Error;

fn try_from(compressed_sierra_class: CompressedSierraClass) -> Result<Self, Self::Error> {
let string_reader = std::io::Cursor::new(compressed_sierra_class.sierra_program);
let base64_decoder =
base64::read::DecoderReader::new(string_reader, &base64::engine::general_purpose::STANDARD);
let gzip_decoder = flate2::read::GzDecoder::new(base64_decoder);
let sierra_program = serde_json::from_reader(gzip_decoder)?;

Ok(Self {
sierra_program,
contract_class_version: compressed_sierra_class.contract_class_version,
entry_points_by_type: compressed_sierra_class.entry_points_by_type,
abi: compressed_sierra_class.abi,
})
}
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub struct EntryPointsByType {
Expand Down
94 changes: 57 additions & 37 deletions crates/madara/primitives/gateway/src/user_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
//! - `ContractClassDecodeError`: When contract class decoding fails
//!
use mp_class::{CompressedLegacyContractClass, FlattenedSierraClass};
use mp_class::{CompressedLegacyContractClass, CompressedSierraClass, FlattenedSierraClass};
use mp_convert::hex_serde::U64AsHex;
use mp_transactions::{DataAvailabilityMode, ResourceBoundsMapping};
use serde::{Deserialize, Serialize};
Expand All @@ -48,7 +48,7 @@ pub enum UserTransactionConversionError {
#[error("User transaction can't be a query only transaction")]
UnsupportedQueryTransaction,
#[error("Error while decoding the contract class: {0}")]
ContractClassDecodeError(#[from] base64::DecodeError),
ContractClassDecodeError(#[from] std::io::Error),
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand All @@ -60,12 +60,14 @@ pub enum UserTransaction {
DeployAccount(UserDeployAccountTransaction),
}

impl From<UserTransaction> for BroadcastedTxn<Felt> {
fn from(transaction: UserTransaction) -> Self {
impl TryFrom<UserTransaction> for BroadcastedTxn<Felt> {
type Error = UserTransactionConversionError;

fn try_from(transaction: UserTransaction) -> Result<Self, Self::Error> {
match transaction {
UserTransaction::Declare(tx) => BroadcastedTxn::Declare(tx.into()),
UserTransaction::InvokeFunction(tx) => BroadcastedTxn::Invoke(tx.into()),
UserTransaction::DeployAccount(tx) => BroadcastedTxn::DeployAccount(tx.into()),
UserTransaction::Declare(tx) => Ok(BroadcastedTxn::Declare(tx.try_into()?)),
UserTransaction::InvokeFunction(tx) => Ok(BroadcastedTxn::Invoke(tx.into())),
UserTransaction::DeployAccount(tx) => Ok(BroadcastedTxn::DeployAccount(tx.into())),
}
}
}
Expand Down Expand Up @@ -93,12 +95,14 @@ pub enum UserDeclareTransaction {
V3(UserDeclareV3Transaction),
}

impl From<UserDeclareTransaction> for BroadcastedDeclareTxn<Felt> {
fn from(transaction: UserDeclareTransaction) -> Self {
impl TryFrom<UserDeclareTransaction> for BroadcastedDeclareTxn<Felt> {
type Error = UserTransactionConversionError;

fn try_from(transaction: UserDeclareTransaction) -> Result<Self, Self::Error> {
match transaction {
UserDeclareTransaction::V1(tx) => BroadcastedDeclareTxn::V1(tx.into()),
UserDeclareTransaction::V2(tx) => BroadcastedDeclareTxn::V2(tx.into()),
UserDeclareTransaction::V3(tx) => BroadcastedDeclareTxn::V3(tx.into()),
UserDeclareTransaction::V1(tx) => Ok(BroadcastedDeclareTxn::V1(tx.into())),
UserDeclareTransaction::V2(tx) => Ok(BroadcastedDeclareTxn::V2(tx.try_into()?)),
UserDeclareTransaction::V3(tx) => Ok(BroadcastedDeclareTxn::V3(tx.try_into()?)),
}
}
}
Expand All @@ -109,8 +113,8 @@ impl TryFrom<BroadcastedDeclareTxn<Felt>> for UserDeclareTransaction {
fn try_from(transaction: BroadcastedDeclareTxn<Felt>) -> Result<Self, Self::Error> {
match transaction {
BroadcastedDeclareTxn::V1(tx) => Ok(UserDeclareTransaction::V1(tx.try_into()?)),
BroadcastedDeclareTxn::V2(tx) => Ok(UserDeclareTransaction::V2(tx.into())),
BroadcastedDeclareTxn::V3(tx) => Ok(UserDeclareTransaction::V3(tx.into())),
BroadcastedDeclareTxn::V2(tx) => Ok(UserDeclareTransaction::V2(tx.try_into()?)),
BroadcastedDeclareTxn::V3(tx) => Ok(UserDeclareTransaction::V3(tx.try_into()?)),
BroadcastedDeclareTxn::QueryV1(_)
| BroadcastedDeclareTxn::QueryV2(_)
| BroadcastedDeclareTxn::QueryV3(_) => Err(UserTransactionConversionError::UnsupportedQueryTransaction),
Expand Down Expand Up @@ -140,7 +144,7 @@ impl From<UserDeclareV1Transaction> for BroadcastedDeclareTxnV1<Felt> {
}

impl TryFrom<BroadcastedDeclareTxnV1<Felt>> for UserDeclareV1Transaction {
type Error = base64::DecodeError;
type Error = std::io::Error;

fn try_from(transaction: BroadcastedDeclareTxnV1<Felt>) -> Result<Self, Self::Error> {
Ok(Self {
Expand All @@ -155,44 +159,52 @@ impl TryFrom<BroadcastedDeclareTxnV1<Felt>> for UserDeclareV1Transaction {

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UserDeclareV2Transaction {
pub contract_class: FlattenedSierraClass,
pub contract_class: CompressedSierraClass,
pub compiled_class_hash: Felt,
pub sender_address: Felt,
pub max_fee: Felt,
pub signature: Vec<Felt>,
pub nonce: Felt,
}

impl From<UserDeclareV2Transaction> for BroadcastedDeclareTxnV2<Felt> {
fn from(transaction: UserDeclareV2Transaction) -> Self {
Self {
impl TryFrom<UserDeclareV2Transaction> for BroadcastedDeclareTxnV2<Felt> {
type Error = std::io::Error;

fn try_from(transaction: UserDeclareV2Transaction) -> Result<Self, Self::Error> {
let flattened_sierra_class: FlattenedSierraClass = transaction.contract_class.try_into()?;

Ok(Self {
sender_address: transaction.sender_address,
compiled_class_hash: transaction.compiled_class_hash,
max_fee: transaction.max_fee,
signature: transaction.signature,
nonce: transaction.nonce,
contract_class: transaction.contract_class.into(),
}
contract_class: flattened_sierra_class.into(),
})
}
}

impl From<BroadcastedDeclareTxnV2<Felt>> for UserDeclareV2Transaction {
fn from(transaction: BroadcastedDeclareTxnV2<Felt>) -> Self {
Self {
impl TryFrom<BroadcastedDeclareTxnV2<Felt>> for UserDeclareV2Transaction {
type Error = std::io::Error;

fn try_from(transaction: BroadcastedDeclareTxnV2<Felt>) -> Result<Self, Self::Error> {
let flattened_sierra_class: FlattenedSierraClass = transaction.contract_class.into();

Ok(Self {
sender_address: transaction.sender_address,
compiled_class_hash: transaction.compiled_class_hash,
max_fee: transaction.max_fee,
signature: transaction.signature,
nonce: transaction.nonce,
contract_class: transaction.contract_class.into(),
}
contract_class: flattened_sierra_class.try_into()?,
})
}
}

#[serde_as]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UserDeclareV3Transaction {
pub contract_class: FlattenedSierraClass,
pub contract_class: CompressedSierraClass,
pub compiled_class_hash: Felt,
pub sender_address: Felt,
pub signature: Vec<Felt>,
Expand All @@ -206,9 +218,13 @@ pub struct UserDeclareV3Transaction {
pub account_deployment_data: Vec<Felt>,
}

impl From<UserDeclareV3Transaction> for BroadcastedDeclareTxnV3<Felt> {
fn from(transaction: UserDeclareV3Transaction) -> Self {
Self {
impl TryFrom<UserDeclareV3Transaction> for BroadcastedDeclareTxnV3<Felt> {
type Error = std::io::Error;

fn try_from(transaction: UserDeclareV3Transaction) -> Result<Self, Self::Error> {
let flattened_sierra_class: FlattenedSierraClass = transaction.contract_class.try_into()?;

Ok(Self {
sender_address: transaction.sender_address,
compiled_class_hash: transaction.compiled_class_hash,
signature: transaction.signature,
Expand All @@ -217,16 +233,20 @@ impl From<UserDeclareV3Transaction> for BroadcastedDeclareTxnV3<Felt> {
fee_data_availability_mode: transaction.fee_data_availability_mode.into(),
resource_bounds: transaction.resource_bounds.into(),
tip: transaction.tip,
contract_class: transaction.contract_class.into(),
contract_class: flattened_sierra_class.into(),
paymaster_data: transaction.paymaster_data,
account_deployment_data: transaction.account_deployment_data,
}
})
}
}

impl From<BroadcastedDeclareTxnV3<Felt>> for UserDeclareV3Transaction {
fn from(transaction: BroadcastedDeclareTxnV3<Felt>) -> Self {
Self {
impl TryFrom<BroadcastedDeclareTxnV3<Felt>> for UserDeclareV3Transaction {
type Error = std::io::Error;

fn try_from(transaction: BroadcastedDeclareTxnV3<Felt>) -> Result<Self, Self::Error> {
let flattened_sierra_class: FlattenedSierraClass = transaction.contract_class.into();

Ok(Self {
sender_address: transaction.sender_address,
compiled_class_hash: transaction.compiled_class_hash,
signature: transaction.signature,
Expand All @@ -235,10 +255,10 @@ impl From<BroadcastedDeclareTxnV3<Felt>> for UserDeclareV3Transaction {
fee_data_availability_mode: transaction.fee_data_availability_mode.into(),
resource_bounds: transaction.resource_bounds.into(),
tip: transaction.tip,
contract_class: transaction.contract_class.into(),
contract_class: flattened_sierra_class.try_into()?,
paymaster_data: transaction.paymaster_data,
account_deployment_data: transaction.account_deployment_data,
}
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/madara/primitives/transactions/src/to_blockifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ pub enum ToBlockifierError {
#[error("Compiled class hash mismatch: expected {expected}, actual {compilation}")]
CompiledClassHashMismatch { expected: Felt, compilation: Felt },
#[error("Failed to convert base64 program to cairo program: {0}")]
Base64ToCairoError(#[from] base64::DecodeError),
Base64ToCairoError(#[from] std::io::Error),
#[error("Missing class")]
MissingClass,
}
Expand Down

0 comments on commit 539063c

Please sign in to comment.