Skip to content

Commit c001e4b

Browse files
Implement clone manually, add docs
1 parent 767e5d3 commit c001e4b

File tree

1 file changed

+50
-4
lines changed

1 file changed

+50
-4
lines changed

vm/src/vm/runners/cairo_runner.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
math_utils::safe_div_usize,
55
stdlib::{
66
any::Any,
7+
cell::RefCell,
78
collections::{BTreeMap, HashMap, HashSet},
89
mem,
910
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
@@ -55,6 +56,7 @@ use crate::{
5556
use num_integer::div_rem;
5657
use num_traits::{ToPrimitive, Zero};
5758
use serde::{Deserialize, Serialize};
59+
use starknet_crypto::Signature;
5860

5961
use super::{builtin_runner::ModBuiltinRunner, cairo_pie::CairoPieAdditionalData};
6062
use super::{
@@ -147,7 +149,13 @@ impl ResourceTracker for RunResources {
147149
}
148150
}
149151

150-
#[derive(Clone)]
152+
/// Handles the creation of a CairoRunner
153+
///
154+
/// This structure can be cloned. This allows to compute the initial state once,
155+
/// and execute it many times. The following elements can be cached:
156+
/// - Compiled hints
157+
/// - Decoded instructions
158+
/// - Loaded program segment
151159
pub struct CairoRunnerBuilder {
152160
program: Program,
153161
layout: CairoLayout,
@@ -243,9 +251,6 @@ impl CairoRunnerBuilder {
243251
/// Note that *initializing* a builtin implies creating a runner for it,
244252
/// and *including* a builtin refers to enabling the builtin runner flag:
245253
/// `included`.
246-
///
247-
/// TODO: Cloning the builder after calling this function leads to bad
248-
/// behaviour (transactions revert). Why?
249254
pub fn initialize_builtin_runners_for_layout(&mut self) -> Result<(), RunnerError> {
250255
let builtin_ordered_list = vec![
251256
BuiltinName::output,
@@ -500,6 +505,47 @@ impl CairoRunnerBuilder {
500505
}
501506
}
502507

508+
impl Clone for CairoRunnerBuilder {
509+
fn clone(&self) -> Self {
510+
let builtin_runners = self
511+
.builtin_runners
512+
.iter()
513+
.cloned()
514+
.map(|mut builtin_runner| {
515+
// The SignatureBuiltinRunner contains an `Rc`, so deriving clone implies that
516+
// all runners built will share state. To workaround this, clone was implemented
517+
// manually.
518+
if let BuiltinRunner::Signature(signature) = &mut builtin_runner {
519+
let signatures = signature
520+
.signatures
521+
.as_ref()
522+
.borrow()
523+
.iter()
524+
.map(|(k, v)| (*k, Signature { r: v.r, s: v.s }))
525+
.collect();
526+
signature.signatures = Rc::new(RefCell::new(signatures))
527+
}
528+
builtin_runner
529+
})
530+
.collect();
531+
Self {
532+
program: self.program.clone(),
533+
layout: self.layout.clone(),
534+
runner_mode: self.runner_mode.clone(),
535+
enable_trace: self.enable_trace,
536+
disable_trace_padding: self.disable_trace_padding,
537+
allow_missing_builtins: self.allow_missing_builtins,
538+
builtin_runners,
539+
program_base: self.program_base,
540+
execution_base: self.execution_base,
541+
memory: self.memory.clone(),
542+
loaded_program: self.loaded_program,
543+
hints: self.hints.clone(),
544+
instructions: self.instructions.clone(),
545+
}
546+
}
547+
}
548+
503549
pub struct CairoRunner {
504550
pub vm: VirtualMachine,
505551
pub(crate) program: Program,

0 commit comments

Comments
 (0)