multiplexer_evm/
flow_builder.rs

1use alloy_primitives::{Address, U256};
2
3use crate::opcodes::{
4    Call, ClearData, Create, DelegateCall, ExtCodeCopy, SetAddr, SetData, SetValue, SetCallback, SetFail, ClearFail,
5};
6
7// Enum for all opcode actions
8enum Action {
9    ClearData(ClearData),
10    SetData(SetData),
11    SetAddr(SetAddr),
12    SetValue(SetValue),
13    ExtCodeCopy(ExtCodeCopy),
14    Call(Call),
15    Create(Create),
16    DelegateCall(DelegateCall),
17    SetFail(SetFail),
18    ClearFail(ClearFail),
19    SetCallback(SetCallback)
20}
21
22impl Action {
23    fn encode(&self) -> Vec<u8> {
24        match self {
25            Action::ClearData(cd) => cd.encode(),
26            Action::SetData(sd) => sd.encode(),
27            Action::SetAddr(sa) => sa.encode(),
28            Action::SetValue(sv) => sv.encode(),
29            Action::ExtCodeCopy(ecc) => ecc.encode(),
30            Action::Call(c) => c.encode(),
31            Action::Create(c) => c.encode(),
32            Action::DelegateCall(dc) => dc.encode(),
33            Action::SetFail(sf) => sf.encode(),
34            Action::ClearFail(cf) => cf.encode(),
35            Action::SetCallback(scb) => scb.encode(),
36        }
37    }
38}
39
40// FlowBuilder to manage the actions
41#[derive(Default)]
42pub struct FlowBuilder {
43    actions: Vec<Action>,
44}
45
46impl FlowBuilder {
47    /// Creates an empty `FlowBuilder` with no actions.
48    pub fn empty() -> Self {
49        Self::default()
50    }
51
52    /// A simple optimizer that will remove redundant sets
53    fn peephole_opt(&mut self) {
54        let mut ops_to_remove = Vec::new();
55        let mut last_value = U256::ZERO;
56        let mut last_target = Address::ZERO;
57        let mut last_data: Vec<u8> = Vec::new();
58        let mut last_fail = false;
59
60        for (idx, action) in self.actions.iter().enumerate() {
61            let to_remove = match action {
62                Action::SetFail(_) => {
63                    if last_fail {
64                        true
65                    } else {
66                        last_fail = true;
67                        false
68                    }
69                }
70                Action::ClearFail(_) => {
71                    if last_fail {
72                        last_fail = false;
73                        false
74                    } else {
75                        true
76                    }
77                }
78                Action::Call(_) => {
79                    last_value = U256::ZERO;
80                    false
81                }
82                Action::Create(Create { created_address }) => {
83                    last_target = *created_address;
84                    last_value = U256::ZERO;
85                    false
86                }
87                Action::SetAddr(SetAddr { addr }) => {
88                    let res = last_target == *addr;
89                    last_target = *addr;
90                    res
91                }
92                Action::SetValue(SetValue { value }) => {
93                    let res = last_value == *value;
94                    last_value = *value;
95                    res
96                }
97                Action::ClearData(ClearData { size }) => {
98                    let res = last_data.len() == *size as usize;
99                    last_data = vec![0; *size as usize];
100                    res
101                }
102                Action::SetData(SetData { offset, data }) => {
103                    let offset_uz = *offset as usize;
104                    let mut new_data = last_data.clone();
105                    new_data.splice(offset_uz..offset_uz + data.len(), data.to_owned());
106                    let res = last_data == new_data;
107                    last_data = new_data;
108                    res
109                }
110                _ => false,
111            };
112            if to_remove {
113                ops_to_remove.push(idx);
114            }
115        }
116
117        for idx in ops_to_remove.into_iter().rev() {
118            self.actions.remove(idx);
119        }
120    }
121
122    /// Adds an `EXTCODECOPY` operation to the action list.
123    pub fn set_extcodecopy_op(&mut self, source: Address, data_offset: u16, code_offset: u16, size: u16) -> &mut Self {
124        self.actions.push(Action::ExtCodeCopy(ExtCodeCopy {
125            source,
126            data_offset,
127            code_offset,
128            size,
129        }));
130        self
131    }
132
133    /// Adds a `SETADDR` operation to the action list.
134    pub fn set_addr_op(&mut self, addr: Address) -> &mut Self {
135        self.actions.push(Action::SetAddr(SetAddr { addr }));
136        self
137    }
138
139    /// Adds a `SETVALUE` operation to the action list.
140    pub fn set_value_op(&mut self, value: U256) -> &mut Self {
141        self.actions.push(Action::SetValue(SetValue { value }));
142        self
143    }
144
145    /// Adds a `SETDATA` operation to the action list.
146    pub fn set_data_op(&mut self, offset: u16, data: &[u8]) -> &mut Self {
147        self.actions.push(Action::SetData(SetData {
148            offset,
149            data: data.to_owned(),
150        }));
151        self
152    }
153
154    /// Adds a `CLEARDATA` operation to the action list.
155    pub fn set_cleardata_op(&mut self, size: u16) -> &mut Self {
156        self.actions.push(Action::ClearData(ClearData { size }));
157        self
158    }
159
160    /// Adds a `CALL` operation to the action list.
161    pub fn call_op(&mut self) -> &mut Self {
162        self.actions.push(Action::Call(Call::new()));
163        self
164    }
165
166    /// Adds a `CREATE` operation to the action list.
167    pub fn create_op(&mut self, created_address: Address) -> &mut Self {
168        self.actions.push(Action::Create(Create { created_address }));
169        self
170    }
171
172    /// Adds a `DELEGATECALL` operation to the action list.
173    pub fn delegatecall_op(&mut self) -> &mut Self {
174        self.actions.push(Action::DelegateCall(DelegateCall::new()));
175        self
176    }
177
178    /// Prepares a `CALL` operation with the specified target, data, and value.
179    pub fn call(&mut self, target: Address, data: &[u8], value: U256) -> &mut Self {
180        assert!(data.len() < u16::MAX as usize, "datalen exceeds 0xffff");
181
182        self.set_addr_op(target)
183            .set_value_op(value)
184            .set_cleardata_op(data.len() as u16)
185            .set_data_op(0, data)
186            .call_op()
187    }
188
189    /// Prepares a `DELEGATECALL` operation with the specified target and data.
190    pub fn delegatecall(&mut self, target: Address, data: &[u8]) -> &mut Self {
191        self.set_addr_op(target)
192            .set_cleardata_op(data.len() as u16)
193            .set_data_op(0, data)
194            .delegatecall_op()
195    }
196
197    /// Prepares a `CREATE` operation with the specified address, data, and value.
198    pub fn create(&mut self, created_address: Address, data: &[u8], value: U256) -> &mut Self {
199        self.set_value_op(value)
200            .set_cleardata_op(data.len() as u16)
201            .set_data_op(0, data)
202            .create_op(created_address)
203    }
204
205    /// prepare set callback
206    pub fn set_callback(&mut self, callback_address: Address) -> &mut Self {
207        self.actions.push(Action::SetCallback(SetCallback::new(callback_address)));
208        self
209    }
210
211    /// Prepares a `SETFAIL` operation.
212    pub fn set_fail(&mut self) -> &mut Self {
213        self.actions.push(Action::SetFail(SetFail::new()));
214        self
215    }
216
217    /// Prepares a `CLEARFAIL` operation.
218    pub fn clear_fail(&mut self) -> &mut Self {
219        self.actions.push(Action::ClearFail(ClearFail::new()));
220        self
221    }
222
223    /// Optimizes the sequence of operations.
224    pub fn optimize(&mut self) -> &mut Self {
225        self.peephole_opt();
226        self
227    }
228
229    /// Builds the sequence of operations into a byte vector, optionally optimizing it.
230   pub fn build_raw(&mut self) -> Vec<u8> {
231        let mut res = Vec::new();
232        for action in &self.actions {
233            res.extend(&action.encode());
234        }
235        res
236    }
237
238
239    /// Builds the sequence of operations into a byte vector, optionally optimizing it.
240    pub fn build(&mut self) -> Vec<u8> {
241        // ======= executor.sol:executor =======
242        // Function signatures:
243        // c94f554d: executeActions()
244        let mut res = vec![0xc9, 0x4f, 0x55, 0x4d];
245        res.extend(self.build_raw());
246        res
247    }
248}