1use crate::{
2 error::{
3 InterpreterError,
4 IoResult,
5 RuntimeError,
6 },
7 interpreter::{
8 EcalHandler,
9 ExecutableTransaction,
10 Interpreter,
11 Memory,
12 },
13 state::ExecuteState,
14 storage::InterpreterStorage,
15 verification::Verifier,
16};
17
18use fuel_asm::{
19 Instruction,
20 PanicInstruction,
21 PanicReason,
22 RawInstruction,
23 RegId,
24};
25
26impl<M, S, Tx, Ecal, V> Interpreter<M, S, Tx, Ecal, V>
27where
28 M: Memory,
29 S: InterpreterStorage,
30 Tx: ExecutableTransaction,
31 Ecal: EcalHandler,
32 V: Verifier,
33{
34 pub fn execute<const PREDICATE: bool>(
36 &mut self,
37 ) -> Result<ExecuteState, InterpreterError<S::DataError>> {
38 let raw_instruction = self.fetch_instruction()?;
39 self.instruction_per_inner::<PREDICATE>(raw_instruction)
40 }
41
42 fn fetch_instruction(&self) -> Result<[u8; 4], InterpreterError<S::DataError>> {
45 let pc = self.registers[RegId::PC];
46
47 let raw_instruction: [u8; 4] =
48 self.memory().read_bytes(pc).map_err(|reason| {
49 InterpreterError::PanicInstruction(PanicInstruction::error(
50 reason,
51 0, ))
53 })?;
54 if pc < self.registers[RegId::IS] || pc >= self.registers[RegId::SSP] {
55 return Err(InterpreterError::PanicInstruction(PanicInstruction::error(
56 PanicReason::MemoryNotExecutable,
57 RawInstruction::from_be_bytes(raw_instruction),
58 )))
59 }
60 Ok(raw_instruction)
61 }
62
63 pub fn instruction<R, const PREDICATE: bool>(
65 &mut self,
66 raw: R,
67 ) -> Result<ExecuteState, InterpreterError<S::DataError>>
68 where
69 R: Into<RawInstruction> + Copy,
70 {
71 let raw = raw.into();
72 let raw = raw.to_be_bytes();
73
74 self.instruction_per_inner::<PREDICATE>(raw)
75 }
76
77 fn instruction_per_inner<const PREDICATE: bool>(
78 &mut self,
79 raw: [u8; 4],
80 ) -> Result<ExecuteState, InterpreterError<S::DataError>> {
81 if self.debugger.is_active() {
82 let debug = self.eval_debugger_state();
83 if !debug.should_continue() {
84 return Ok(debug.into())
85 }
86 }
87
88 self.instruction_inner::<PREDICATE>(raw).map_err(|e| {
89 InterpreterError::from_runtime(e, RawInstruction::from_be_bytes(raw))
90 })
91 }
92
93 fn instruction_inner<const PREDICATE: bool>(
94 &mut self,
95 raw: [u8; 4],
96 ) -> IoResult<ExecuteState, S::DataError> {
97 let instruction = Instruction::try_from(raw)
98 .map_err(|_| RuntimeError::from(PanicReason::InvalidInstruction))?;
99
100 if PREDICATE {
101 if !instruction.opcode().is_predicate_allowed() {
104 return Err(PanicReason::ContractInstructionNotAllowed.into())
105 }
106 }
107
108 instruction.execute(self)
109 }
110}
111
112pub trait Execute<M, S, Tx, Ecal, V>
113where
114 M: Memory,
115 S: InterpreterStorage,
116 Tx: ExecutableTransaction,
117 Ecal: EcalHandler,
118 V: Verifier,
119{
120 fn execute(
121 self,
122 interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
123 ) -> IoResult<ExecuteState, S::DataError>;
124}
125
126impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for Instruction
127where
128 M: Memory,
129 S: InterpreterStorage,
130 Tx: ExecutableTransaction,
131 Ecal: EcalHandler,
132 V: Verifier,
133{
134 fn execute(
135 self,
136 interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
137 ) -> IoResult<ExecuteState, S::DataError> {
138 match self {
139 Instruction::ADD(op) => op.execute(interpreter),
140 Instruction::AND(op) => op.execute(interpreter),
141 Instruction::DIV(op) => op.execute(interpreter),
142 Instruction::EQ(op) => op.execute(interpreter),
143 Instruction::EXP(op) => op.execute(interpreter),
144 Instruction::GT(op) => op.execute(interpreter),
145 Instruction::LT(op) => op.execute(interpreter),
146 Instruction::MLOG(op) => op.execute(interpreter),
147 Instruction::MROO(op) => op.execute(interpreter),
148 Instruction::MOD(op) => op.execute(interpreter),
149 Instruction::MOVE(op) => op.execute(interpreter),
150 Instruction::MUL(op) => op.execute(interpreter),
151 Instruction::NOT(op) => op.execute(interpreter),
152 Instruction::OR(op) => op.execute(interpreter),
153 Instruction::SLL(op) => op.execute(interpreter),
154 Instruction::SRL(op) => op.execute(interpreter),
155 Instruction::SUB(op) => op.execute(interpreter),
156 Instruction::XOR(op) => op.execute(interpreter),
157 Instruction::MLDV(op) => op.execute(interpreter),
158 Instruction::RET(op) => op.execute(interpreter),
159 Instruction::RETD(op) => op.execute(interpreter),
160 Instruction::ALOC(op) => op.execute(interpreter),
161 Instruction::MCL(op) => op.execute(interpreter),
162 Instruction::MCP(op) => op.execute(interpreter),
163 Instruction::MEQ(op) => op.execute(interpreter),
164 Instruction::BHSH(op) => op.execute(interpreter),
165 Instruction::BHEI(op) => op.execute(interpreter),
166 Instruction::BURN(op) => op.execute(interpreter),
167 Instruction::CALL(op) => op.execute(interpreter),
168 Instruction::CCP(op) => op.execute(interpreter),
169 Instruction::CROO(op) => op.execute(interpreter),
170 Instruction::CSIZ(op) => op.execute(interpreter),
171 Instruction::CB(op) => op.execute(interpreter),
172 Instruction::LDC(op) => op.execute(interpreter),
173 Instruction::LOG(op) => op.execute(interpreter),
174 Instruction::LOGD(op) => op.execute(interpreter),
175 Instruction::MINT(op) => op.execute(interpreter),
176 Instruction::RVRT(op) => op.execute(interpreter),
177 Instruction::SCWQ(op) => op.execute(interpreter),
178 Instruction::SRW(op) => op.execute(interpreter),
179 Instruction::SRWQ(op) => op.execute(interpreter),
180 Instruction::SWW(op) => op.execute(interpreter),
181 Instruction::SWWQ(op) => op.execute(interpreter),
182 Instruction::TR(op) => op.execute(interpreter),
183 Instruction::TRO(op) => op.execute(interpreter),
184 Instruction::ECK1(op) => op.execute(interpreter),
185 Instruction::ECR1(op) => op.execute(interpreter),
186 Instruction::ED19(op) => op.execute(interpreter),
187 Instruction::K256(op) => op.execute(interpreter),
188 Instruction::S256(op) => op.execute(interpreter),
189 Instruction::TIME(op) => op.execute(interpreter),
190 Instruction::NOOP(op) => op.execute(interpreter),
191 Instruction::FLAG(op) => op.execute(interpreter),
192 Instruction::BAL(op) => op.execute(interpreter),
193 Instruction::JMP(op) => op.execute(interpreter),
194 Instruction::JNE(op) => op.execute(interpreter),
195 Instruction::SMO(op) => op.execute(interpreter),
196 Instruction::ADDI(op) => op.execute(interpreter),
197 Instruction::ANDI(op) => op.execute(interpreter),
198 Instruction::DIVI(op) => op.execute(interpreter),
199 Instruction::EXPI(op) => op.execute(interpreter),
200 Instruction::MODI(op) => op.execute(interpreter),
201 Instruction::MULI(op) => op.execute(interpreter),
202 Instruction::ORI(op) => op.execute(interpreter),
203 Instruction::SLLI(op) => op.execute(interpreter),
204 Instruction::SRLI(op) => op.execute(interpreter),
205 Instruction::SUBI(op) => op.execute(interpreter),
206 Instruction::XORI(op) => op.execute(interpreter),
207 Instruction::JNEI(op) => op.execute(interpreter),
208 Instruction::LB(op) => op.execute(interpreter),
209 Instruction::LW(op) => op.execute(interpreter),
210 Instruction::SB(op) => op.execute(interpreter),
211 Instruction::SW(op) => op.execute(interpreter),
212 Instruction::MCPI(op) => op.execute(interpreter),
213 Instruction::GTF(op) => op.execute(interpreter),
214 Instruction::MCLI(op) => op.execute(interpreter),
215 Instruction::GM(op) => op.execute(interpreter),
216 Instruction::MOVI(op) => op.execute(interpreter),
217 Instruction::JNZI(op) => op.execute(interpreter),
218 Instruction::JMPF(op) => op.execute(interpreter),
219 Instruction::JMPB(op) => op.execute(interpreter),
220 Instruction::JNZF(op) => op.execute(interpreter),
221 Instruction::JNZB(op) => op.execute(interpreter),
222 Instruction::JNEF(op) => op.execute(interpreter),
223 Instruction::JNEB(op) => op.execute(interpreter),
224 Instruction::JI(op) => op.execute(interpreter),
225 Instruction::CFEI(op) => op.execute(interpreter),
226 Instruction::CFSI(op) => op.execute(interpreter),
227 Instruction::CFE(op) => op.execute(interpreter),
228 Instruction::CFS(op) => op.execute(interpreter),
229 Instruction::PSHL(op) => op.execute(interpreter),
230 Instruction::PSHH(op) => op.execute(interpreter),
231 Instruction::POPL(op) => op.execute(interpreter),
232 Instruction::POPH(op) => op.execute(interpreter),
233 Instruction::WDCM(op) => op.execute(interpreter),
234 Instruction::WQCM(op) => op.execute(interpreter),
235 Instruction::WDOP(op) => op.execute(interpreter),
236 Instruction::WQOP(op) => op.execute(interpreter),
237 Instruction::WDML(op) => op.execute(interpreter),
238 Instruction::WQML(op) => op.execute(interpreter),
239 Instruction::WDDV(op) => op.execute(interpreter),
240 Instruction::WQDV(op) => op.execute(interpreter),
241 Instruction::WDMD(op) => op.execute(interpreter),
242 Instruction::WQMD(op) => op.execute(interpreter),
243 Instruction::WDAM(op) => op.execute(interpreter),
244 Instruction::WQAM(op) => op.execute(interpreter),
245 Instruction::WDMM(op) => op.execute(interpreter),
246 Instruction::WQMM(op) => op.execute(interpreter),
247 Instruction::ECAL(op) => op.execute(interpreter),
248 Instruction::BSIZ(op) => op.execute(interpreter),
249 Instruction::BLDD(op) => op.execute(interpreter),
250 Instruction::ECOP(op) => op.execute(interpreter),
251 Instruction::EPAR(op) => op.execute(interpreter),
252 }
253 }
254}
255
256pub fn checked_nth_root(target: u64, nth_root: u64) -> Option<u64> {
260 if nth_root == 0 {
261 return None
263 }
264
265 if nth_root == 1 || target <= 1 {
266 return Some(target)
268 }
269
270 if nth_root >= target || nth_root > 64 {
271 return Some(1)
274 }
275
276 let nth_root = u32::try_from(nth_root).expect("Never loses bits, checked above");
277
278 #[cfg(feature = "std")]
282 let powf = f64::powf;
283 #[cfg(not(feature = "std"))]
284 let powf = libm::pow;
285
286 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
287 let guess = powf(target as f64, (nth_root as f64).recip()) as u64;
288
289 debug_assert!(guess != 0, "This should never occur for {{target, n}} > 1");
290
291 let is_nth_power_below_target = |v: u64| match v.checked_pow(nth_root) {
294 Some(pow) => target < pow,
295 None => true, };
297
298 if is_nth_power_below_target(guess) {
302 return Some(guess.saturating_sub(1))
303 }
304
305 let guess_plus_one = guess.checked_add(1).expect(
307 "Guess cannot be u64::MAX, as we have taken a root > 2 of a value to get it",
308 );
309 if is_nth_power_below_target(guess_plus_one) {
310 return Some(guess)
311 }
312
313 Some(guess_plus_one)
315}
316
317#[cfg(test)]
318mod tests;