Skip to content

Commit 0aa1f33

Browse files
committed
fix outside execution mistake
1 parent 392df8c commit 0aa1f33

File tree

8 files changed

+400
-183
lines changed

8 files changed

+400
-183
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cartridge/src/paymaster/layer.rs

Lines changed: 212 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,34 @@ use katana_primitives::{ContractAddress, Felt};
1212
use katana_provider::ProviderFactory;
1313
use katana_rpc_server::starknet::PendingBlockProvider;
1414
use katana_rpc_types::broadcasted::BroadcastedTx;
15+
use katana_rpc_types::FeeEstimate;
1516
use serde::Deserialize;
1617
use starknet::core::types::SimulationFlagForEstimateFee;
18+
use starknet::providers::jsonrpc::JsonRpcResponse;
19+
use tracing::{debug, trace};
1720

1821
use super::Paymaster;
1922
use crate::rpc::types::OutsideExecution;
2023

24+
#[derive(Deserialize)]
25+
struct EstimateFeeParams {
26+
#[serde(alias = "request")]
27+
txs: Vec<BroadcastedTx>,
28+
#[serde(alias = "simulationFlags")]
29+
simulation_flags: Vec<SimulationFlagForEstimateFee>,
30+
#[serde(alias = "blockId")]
31+
block_id: BlockIdOrTag,
32+
}
33+
34+
#[derive(Deserialize)]
35+
struct OutsideExecutionParams {
36+
#[serde(alias = "address")]
37+
controller_address: ContractAddress,
38+
#[serde(alias = "outsideExecution")]
39+
outside_execution: OutsideExecution,
40+
signature: Vec<Felt>,
41+
}
42+
2143
#[derive(Debug)]
2244
pub struct PaymasterLayer<Pool: TransactionPool, PP: PendingBlockProvider, PF: ProviderFactory>
2345
where
@@ -60,28 +82,21 @@ where
6082
impl<S, Pool: TransactionPool + 'static, PP: PendingBlockProvider, PF: ProviderFactory>
6183
PaymasterService<S, Pool, PP, PF>
6284
where
63-
S: RpcServiceT + Send + Sync + Clone + 'static,
85+
S: RpcServiceT<MethodResponse = MethodResponse> + Send + Sync + Clone + 'static,
6486
<PF as ProviderFactory>::Provider: ProviderRO,
6587
{
66-
async fn intercept_estimate_fee(paymaster: Paymaster<Pool, PP, PF>, request: &mut Request<'_>) {
88+
/// Extract estimate_fee parameters from the request.
89+
fn parse_estimate_fee_params(request: &Request<'_>) -> Option<EstimateFeeParams> {
6790
let params = request.params();
6891

69-
let (txs, simulation_flags, block_id) = if params.is_object() {
70-
#[derive(Deserialize)]
71-
struct ParamsObject {
72-
request: Vec<BroadcastedTx>,
73-
#[serde(alias = "simulationFlags")]
74-
simulation_flags: Vec<SimulationFlagForEstimateFee>,
75-
#[serde(alias = "blockId")]
76-
block_id: BlockIdOrTag,
92+
if params.is_object() {
93+
match params.parse() {
94+
Ok(p) => Some(p),
95+
Err(..) => {
96+
debug!(target: "cartridge", "Failed to parse estimate fee params.");
97+
None
98+
}
7799
}
78-
79-
let parsed: ParamsObject = match params.parse() {
80-
Ok(p) => p,
81-
Err(..) => return,
82-
};
83-
84-
(parsed.request, parsed.simulation_flags, parsed.block_id)
85100
} else {
86101
let mut seq = params.sequence();
87102

@@ -90,81 +105,201 @@ where
90105
let block_id_result: Result<BlockIdOrTag, _> = seq.next();
91106

92107
match (txs_result, simulation_flags_result, block_id_result) {
93-
(Ok(txs), Ok(simulation_flags), Ok(block_id)) => (txs, simulation_flags, block_id),
94-
_ => return,
108+
(Ok(txs), Ok(simulation_flags), Ok(block_id)) => {
109+
Some(EstimateFeeParams { txs, simulation_flags, block_id })
110+
}
111+
_ => {
112+
debug!(target: "cartridge", "Failed to parse estimate fee params.");
113+
None
114+
}
95115
}
96-
};
97-
98-
if let Ok(Some(updated_txs)) = paymaster.handle_estimate_fees(block_id, txs).await {
99-
let new_params = {
100-
let mut params = jsonrpsee::core::params::ArrayParams::new();
101-
params.insert(&updated_txs).unwrap();
102-
params.insert(simulation_flags).unwrap();
103-
params.insert(block_id).unwrap();
104-
params
105-
};
106-
107-
let params = new_params.to_rpc_params().unwrap();
108-
let params = params.map(Cow::Owned);
109-
request.params = params;
110116
}
111117
}
112118

113-
async fn intercept_add_outside_execution(
114-
paymaster: Paymaster<Pool, PP, PF>,
115-
request: &mut Request<'_>,
116-
) {
119+
/// Extract add_outside_execution parameters from the request.
120+
fn parse_add_outside_execution_params(request: &Request<'_>) -> Option<OutsideExecutionParams> {
117121
let params = request.params();
118122

119-
let (controller_address, outside_execution, signature) = if params.is_object() {
120-
#[derive(Deserialize)]
121-
struct ParamsObject {
122-
address: ContractAddress,
123-
#[serde(alias = "outsideExecution")]
124-
outside_execution: OutsideExecution,
125-
signature: Vec<Felt>,
123+
if params.is_object() {
124+
println!("params is object: {:?}", params);
125+
match params.parse() {
126+
Ok(p) => Some(p),
127+
Err(..) => {
128+
debug!(target: "cartridge", "Failed to parse outside execution params.");
129+
None
130+
}
126131
}
127-
128-
let parsed: ParamsObject = match params.parse() {
129-
Ok(p) => p,
130-
Err(..) => return,
131-
};
132-
133-
(parsed.address, parsed.outside_execution, parsed.signature)
134132
} else {
133+
println!("params is sequence: {:?}", params);
135134
let mut seq = params.sequence();
136135

137136
let address_result: Result<ContractAddress, _> = seq.next();
138137
let outside_execution_result: Result<OutsideExecution, _> = seq.next();
139138
let signature_result: Result<Vec<Felt>, _> = seq.next();
140139

141140
match (address_result, outside_execution_result, signature_result) {
142-
(Ok(address), Ok(outside_execution), Ok(signature)) => {
143-
(address, outside_execution, signature)
141+
(Ok(controller_address), Ok(outside_execution), Ok(signature)) => {
142+
Some(OutsideExecutionParams {
143+
controller_address,
144+
outside_execution,
145+
signature,
146+
})
147+
}
148+
_ => {
149+
debug!(target: "cartridge", "Failed to parse outside execution params.");
150+
None
144151
}
145-
_ => return,
146152
}
147-
};
148-
149-
match paymaster
150-
.handle_add_outside_execution(controller_address, outside_execution, signature)
151-
.await
152-
{
153-
Ok(Some((outside_execution, signature))) => {
154-
let new_params = {
155-
let mut params = jsonrpsee::core::params::ArrayParams::new();
156-
params.insert(controller_address).unwrap();
157-
params.insert(outside_execution).unwrap();
158-
params.insert(signature).unwrap();
159-
params
153+
}
154+
}
155+
156+
/// Build a new estimate fee request with the updated transactions.
157+
fn build_new_estimate_fee_request<'a>(
158+
request: &Request<'a>,
159+
params: &EstimateFeeParams,
160+
updated_txs: &Vec<BroadcastedTx>,
161+
) -> Request<'a> {
162+
let mut new_request = request.clone();
163+
164+
let mut new_params = jsonrpsee::core::params::ArrayParams::new();
165+
new_params.insert(updated_txs).unwrap();
166+
new_params.insert(params.simulation_flags.clone()).unwrap();
167+
new_params.insert(params.block_id).unwrap();
168+
169+
let new_params = new_params.to_rpc_params().unwrap();
170+
new_request.params = new_params.map(Cow::Owned);
171+
new_request
172+
}
173+
174+
/// <----
175+
fn build_no_fee_response(request: &Request<'_>, count: usize) -> MethodResponse {
176+
let estimate_fees = vec![
177+
FeeEstimate {
178+
l1_gas_consumed: 0,
179+
l1_gas_price: 0,
180+
l2_gas_consumed: 0,
181+
l2_gas_price: 0,
182+
l1_data_gas_consumed: 0,
183+
l1_data_gas_price: 0,
184+
overall_fee: 0
185+
};
186+
count
187+
];
188+
189+
MethodResponse::response(
190+
request.id().clone(),
191+
jsonrpsee::ResponsePayload::success(estimate_fees),
192+
usize::MAX,
193+
)
194+
}
195+
/// ---->
196+
197+
fn intercept_estimate_fee<'a>(
198+
service: S,
199+
paymaster: Paymaster<Pool, PP, PF>,
200+
request: Request<'a>,
201+
) -> impl Future<Output = S::MethodResponse> + Send + 'a {
202+
async move {
203+
if let Some(params) = Self::parse_estimate_fee_params(&request) {
204+
let updated_txs = paymaster
205+
.handle_estimate_fees(params.block_id, &params.txs)
206+
.await
207+
.unwrap_or_default();
208+
209+
if let Some(updated_txs) = updated_txs {
210+
let new_request =
211+
Self::build_new_estimate_fee_request(&request, &params, &updated_txs);
212+
213+
let response = service.call(new_request).await;
214+
215+
// if `handle_estimate_fees` has added some new transactions at the
216+
// beginning of updated_txs, we have to remove
217+
// extras results from estimate_fees to be
218+
// sure to return the same number of result than the number
219+
// of transactions in the request.
220+
let nb_of_txs = params.txs.len();
221+
let nb_of_extra_txs = updated_txs.len() - nb_of_txs;
222+
223+
if response.is_success() && nb_of_extra_txs > 0 {
224+
if let Ok(JsonRpcResponse::Success { result: mut estimate_fees, .. }) =
225+
serde_json::from_str::<JsonRpcResponse<Vec<FeeEstimate>>>(
226+
response.to_json().get(),
227+
)
228+
{
229+
if estimate_fees.len() >= nb_of_extra_txs {
230+
estimate_fees.drain(0..nb_of_extra_txs);
231+
}
232+
233+
trace!(
234+
target: "cartridge",
235+
nb_of_extra_txs = nb_of_extra_txs,
236+
nb_of_estimate_fees = estimate_fees.len(),
237+
"Removing extra transactions from estimate fees response",
238+
);
239+
240+
// TODO: restore the real response
241+
242+
return Self::build_no_fee_response(&request, nb_of_txs);
243+
// return MethodResponse::response(
244+
// request.id().clone(),
245+
// jsonrpsee::ResponsePayload::success(estimate_fees),
246+
// usize::MAX,
247+
// );
248+
}
249+
}
250+
251+
trace!(target: "cartridge", "Estimate fee endpoint original response returned");
252+
return Self::build_no_fee_response(&request, nb_of_txs);
253+
// return response;
254+
}
255+
}
256+
257+
trace!(target: "cartridge", "Estimate fee endpoint called with the original transaction");
258+
service.call(request).await
259+
}
260+
}
261+
262+
fn intercept_add_outside_execution<'a>(
263+
service: S,
264+
paymaster: Paymaster<Pool, PP, PF>,
265+
request: Request<'a>,
266+
) -> impl Future<Output = S::MethodResponse> + Send + 'a {
267+
async move {
268+
if let Some(OutsideExecutionParams {
269+
controller_address,
270+
outside_execution,
271+
signature,
272+
}) = Self::parse_add_outside_execution_params(&request)
273+
{
274+
let updated_tx = match paymaster
275+
.handle_add_outside_execution(controller_address, outside_execution, signature)
276+
.await
277+
{
278+
Ok(Some(tx)) => Some(tx),
279+
Ok(None) => None,
280+
Err(error) => panic!("{error}"),
160281
};
161282

162-
let params = new_params.to_rpc_params().unwrap();
163-
let params = params.map(Cow::Owned);
164-
request.params = params;
283+
if let Some((outside_execution, signature)) = updated_tx {
284+
let mut new_request = request.clone();
285+
let new_params = {
286+
let mut params = jsonrpsee::core::params::ArrayParams::new();
287+
params.insert(controller_address).unwrap();
288+
params.insert(outside_execution).unwrap();
289+
params.insert(signature).unwrap();
290+
params
291+
};
292+
293+
let params = new_params.to_rpc_params().unwrap();
294+
new_request.params = params.map(Cow::Owned);
295+
296+
trace!(target: "cartridge", "Call outside_execution endpoint with the updated transaction");
297+
return service.call(new_request).await;
298+
}
165299
}
166-
Ok(None) => {}
167-
Err(error) => panic!("{error}"),
300+
301+
trace!(target: "cartridge", "Call outside_execution endpoint with the original transaction");
302+
service.call(request).await
168303
}
169304
}
170305
}
@@ -199,19 +334,19 @@ where
199334

200335
fn call<'a>(
201336
&self,
202-
mut request: Request<'a>,
337+
request: Request<'a>,
203338
) -> impl Future<Output = Self::MethodResponse> + Send + 'a {
204339
let service = self.service.clone();
205340
let paymaster = self.paymaster.clone();
206341

207342
async move {
208343
if request.method_name() == "starknet_estimateFee" {
209-
Self::intercept_estimate_fee(paymaster, &mut request).await;
344+
Self::intercept_estimate_fee(service, paymaster, request).await
210345
} else if request.method_name() == "cartridge_addExecuteOutsideTransaction" {
211-
Self::intercept_add_outside_execution(paymaster, &mut request).await;
346+
Self::intercept_add_outside_execution(service, paymaster, request).await
347+
} else {
348+
service.call(request).await
212349
}
213-
214-
service.call(request).await
215350
}
216351
}
217352

0 commit comments

Comments
 (0)