Skip to content

Commit f1846ba

Browse files
committed
added fast-call-read-only endpoint
1 parent 31dd1b0 commit f1846ba

File tree

6 files changed

+712
-206
lines changed

6 files changed

+712
-206
lines changed

stackslib/src/net/api/callreadonly.rs

Lines changed: 17 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use clarity::vm::analysis::CheckErrors;
2020
use clarity::vm::ast::parser::v1::CLARITY_NAME_REGEX;
2121
use clarity::vm::clarity::ClarityConnection;
2222
use clarity::vm::costs::{CostErrors, ExecutionCost, LimitedCostTracker};
23-
use clarity::vm::errors::Error as ClarityRuntimeError;
2423
use clarity::vm::errors::Error::Unchecked;
24+
use clarity::vm::errors::{Error as ClarityRuntimeError, InterpreterError};
2525
use clarity::vm::representations::{CONTRACT_NAME_REGEX_STRING, STANDARD_PRINCIPAL_REGEX_STRING};
2626
use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier};
2727
use clarity::vm::{ClarityName, ContractName, SymbolicExpression, Value};
@@ -61,7 +61,7 @@ pub struct CallReadOnlyResponse {
6161

6262
#[derive(Clone)]
6363
pub struct RPCCallReadOnlyRequestHandler {
64-
maximum_call_argument_size: u32,
64+
pub maximum_call_argument_size: u32,
6565
read_only_call_limit: ExecutionCost,
6666

6767
/// Runtime fields
@@ -70,16 +70,10 @@ pub struct RPCCallReadOnlyRequestHandler {
7070
pub sender: Option<PrincipalData>,
7171
pub sponsor: Option<PrincipalData>,
7272
pub arguments: Option<Vec<Value>>,
73-
74-
read_only_max_execution_time: Duration,
7573
}
7674

7775
impl RPCCallReadOnlyRequestHandler {
78-
pub fn new(
79-
maximum_call_argument_size: u32,
80-
read_only_call_limit: ExecutionCost,
81-
read_only_max_execution_time: Duration,
82-
) -> Self {
76+
pub fn new(maximum_call_argument_size: u32, read_only_call_limit: ExecutionCost) -> Self {
8377
Self {
8478
maximum_call_argument_size,
8579
read_only_call_limit,
@@ -88,7 +82,6 @@ impl RPCCallReadOnlyRequestHandler {
8882
sender: None,
8983
sponsor: None,
9084
arguments: None,
91-
read_only_max_execution_time,
9285
}
9386
}
9487
}
@@ -193,12 +186,6 @@ impl RPCRequestHandler for RPCCallReadOnlyRequestHandler {
193186
}
194187
};
195188

196-
let cost_tracker = contents
197-
.get_query_args()
198-
.get("cost_tracker")
199-
.map(|cost_tracker| cost_tracker.as_str().into())
200-
.unwrap_or(CostTrackerRequest::Limited);
201-
202189
let contract_identifier = self
203190
.contract_identifier
204191
.take()
@@ -239,19 +226,14 @@ impl RPCRequestHandler for RPCCallReadOnlyRequestHandler {
239226
|clarity_tx| {
240227
let epoch = clarity_tx.get_epoch();
241228
let cost_track = clarity_tx
242-
.with_clarity_db_readonly(|clarity_db| match cost_tracker {
243-
CostTrackerRequest::Limited => LimitedCostTracker::new_mid_block(
229+
.with_clarity_db_readonly(|clarity_db| {
230+
LimitedCostTracker::new_mid_block(
244231
mainnet, chain_id, cost_limit, clarity_db, epoch,
245-
),
246-
CostTrackerRequest::Free => {
247-
enforce_max_execution_time = true;
248-
Ok(LimitedCostTracker::new_free())
249-
}
250-
CostTrackerRequest::Invalid => {
251-
Err(CostErrors::Expect("Invalid cost tracker".into()))
252-
}
232+
)
253233
})
254-
.map_err(|e| ClarityRuntimeError::from(e))?;
234+
.map_err(|_| {
235+
ClarityRuntimeError::from(InterpreterError::CostContractLoadFailure)
236+
})?;
255237

256238
let clarity_version = clarity_tx
257239
.with_analysis_db_readonly(|analysis_db| {
@@ -272,13 +254,6 @@ impl RPCRequestHandler for RPCCallReadOnlyRequestHandler {
272254
sponsor,
273255
cost_track,
274256
|env| {
275-
// cost tracking in read only calls is meamingful mainly from a security point of view
276-
// for this reason we enforce max_execution_time when cost tracking is disabled/free
277-
if enforce_max_execution_time {
278-
env.global_context
279-
.set_max_execution_time(self.read_only_max_execution_time);
280-
}
281-
282257
// we want to execute any function as long as no actual writes are made as
283258
// opposed to be limited to purely calling `define-read-only` functions,
284259
// so use `read_only = false`. This broadens the number of functions that
@@ -355,38 +330,6 @@ impl HttpResponse for RPCCallReadOnlyRequestHandler {
355330
}
356331
}
357332

358-
/// All representations of the `cost_tracker=` query parameter value
359-
#[derive(Debug, Clone, PartialEq)]
360-
pub enum CostTrackerRequest {
361-
Limited,
362-
Free,
363-
Invalid,
364-
}
365-
366-
impl CostTrackerRequest {}
367-
368-
impl std::fmt::Display for CostTrackerRequest {
369-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
370-
match self {
371-
Self::Limited => write!(f, "limited"),
372-
Self::Free => write!(f, "free"),
373-
Self::Invalid => write!(f, "invalid"),
374-
}
375-
}
376-
}
377-
378-
impl From<&str> for CostTrackerRequest {
379-
fn from(s: &str) -> CostTrackerRequest {
380-
if s == "limited" || s == "" {
381-
CostTrackerRequest::Limited
382-
} else if s == "free" {
383-
CostTrackerRequest::Free
384-
} else {
385-
CostTrackerRequest::Invalid
386-
}
387-
}
388-
}
389-
390333
impl StacksHttpRequest {
391334
/// Make a new request to run a read-only function
392335
pub fn new_callreadonlyfunction(
@@ -398,7 +341,6 @@ impl StacksHttpRequest {
398341
function_name: ClarityName,
399342
function_args: Vec<Value>,
400343
tip_req: TipRequest,
401-
cost_tracker: CostTrackerRequest,
402344
) -> StacksHttpRequest {
403345
StacksHttpRequest::new_for_peer(
404346
host,
@@ -407,17 +349,14 @@ impl StacksHttpRequest {
407349
"/v2/contracts/call-read/{}/{}/{}",
408350
&contract_addr, &contract_name, &function_name
409351
),
410-
HttpRequestContents::new()
411-
.for_tip(tip_req)
412-
.query_arg("cost_tracker".to_string(), cost_tracker.to_string())
413-
.payload_json(
414-
serde_json::to_value(CallReadOnlyRequestBody {
415-
sender: sender.to_string(),
416-
sponsor: sponsor.map(|s| s.to_string()),
417-
arguments: function_args.into_iter().map(|v| v.to_string()).collect(),
418-
})
419-
.expect("FATAL: failed to encode infallible data"),
420-
),
352+
HttpRequestContents::new().for_tip(tip_req).payload_json(
353+
serde_json::to_value(CallReadOnlyRequestBody {
354+
sender: sender.to_string(),
355+
sponsor: sponsor.map(|s| s.to_string()),
356+
arguments: function_args.into_iter().map(|v| v.to_string()).collect(),
357+
})
358+
.expect("FATAL: failed to encode infallible data"),
359+
),
421360
)
422361
.expect("FATAL: failed to construct request from infallible data")
423362
}

0 commit comments

Comments
 (0)