Skip to content

Commit b2de609

Browse files
authored
Implement PrecompileSet trait (#227)
1 parent 0e81a49 commit b2de609

File tree

6 files changed

+355
-135
lines changed

6 files changed

+355
-135
lines changed

jsontests/src/run.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use evm::backend::in_memory::{
55
};
66
use evm::standard::{Config, Etable, Gasometer, Invoker, TransactArgs};
77
use evm::utils::u256_to_h256;
8-
use evm::{Capture, GasedMachine};
8+
use evm::Capture;
99
use primitive_types::U256;
1010
use std::collections::{BTreeMap, BTreeSet};
1111

@@ -59,7 +59,7 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test, debug: bool) -> R
5959
.collect::<BTreeMap<_, _>>();
6060

6161
let etable = Etable::runtime();
62-
let invoker = Invoker::<_, Gasometer, _, _, _>::new(&config, &etable);
62+
let invoker = Invoker::<_, Gasometer, _, (), _, _>::new(&config, &(), &etable);
6363
let args = TransactArgs::Call {
6464
caller: test.transaction.sender,
6565
address: test.transaction.to,
@@ -101,13 +101,14 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test, debug: bool) -> R
101101
let _step_result = evm::HeapTransact::new(args, &invoker, &mut step_backend).and_then(
102102
|mut stepper| loop {
103103
{
104-
let machine: &GasedMachine<_, Gasometer> = stepper.last_machine()?;
105-
println!(
106-
"pc: {}, opcode: {:?}, gas: 0x{:x}",
107-
machine.machine.position(),
108-
machine.machine.peek_opcode(),
109-
machine.gasometer.gas(),
110-
);
104+
if let Some(machine) = stepper.last_machine() {
105+
println!(
106+
"pc: {}, opcode: {:?}, gas: 0x{:x}",
107+
machine.machine.position(),
108+
machine.machine.peek_opcode(),
109+
machine.gasometer.gas(),
110+
);
111+
}
111112
}
112113
if let Err(Capture::Exit(result)) = stepper.step() {
113114
break result;

src/call_stack.rs

Lines changed: 180 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{Capture, ExitError, ExitFatal, ExitResult, Invoker};
1+
use crate::{Capture, ExitError, ExitFatal, ExitResult, Invoker, InvokerControl};
22
use core::convert::Infallible;
33

44
struct Substack<M, TrD> {
@@ -123,6 +123,7 @@ where
123123
.pop()
124124
.expect("checked stack is not empty above; qed");
125125

126+
let machine = self.invoker.deconstruct_machine(machine);
126127
let feedback_result = self.invoker.exit_substack(
127128
exit,
128129
machine,
@@ -153,7 +154,7 @@ where
153154
self.backend,
154155
self.initial_depth + self.stack.len() + 1,
155156
) {
156-
Capture::Exit(Ok((trap_data, sub_machine))) => {
157+
Capture::Exit(Ok((trap_data, InvokerControl::Enter(sub_machine)))) => {
157158
self.stack.push(Substack {
158159
invoke: trap_data,
159160
machine,
@@ -164,6 +165,29 @@ where
164165
machine: sub_machine,
165166
})
166167
}
168+
Capture::Exit(Ok((
169+
trap_data,
170+
InvokerControl::DirectExit((exit, sub_machine)),
171+
))) => {
172+
let feedback_result = self.invoker.exit_substack(
173+
exit,
174+
sub_machine,
175+
trap_data,
176+
&mut machine,
177+
self.backend,
178+
);
179+
180+
match feedback_result {
181+
Ok(()) => Some(LastSubstack {
182+
status: LastSubstackStatus::Running,
183+
machine,
184+
}),
185+
Err(err) => Some(LastSubstack {
186+
machine,
187+
status: LastSubstackStatus::Exited(Capture::Exit(Err(err))),
188+
}),
189+
}
190+
}
167191
Capture::Exit(Err(err)) => Some(LastSubstack {
168192
status: LastSubstackStatus::Exited(Capture::Exit(Err(err))),
169193
machine,
@@ -204,7 +228,7 @@ where
204228
Capture::Exit(exit) => return Ok((exit, machine)),
205229
Capture::Trap(trap) => {
206230
match invoker.enter_substack(trap, &mut machine, backend, initial_depth + 1) {
207-
Capture::Exit(Ok((trap_data, sub_machine))) => {
231+
Capture::Exit(Ok((trap_data, InvokerControl::Enter(sub_machine)))) => {
208232
let (sub_result, sub_machine) = if heap_depth
209233
.map(|hd| initial_depth + 1 >= hd)
210234
.unwrap_or(false)
@@ -219,6 +243,23 @@ where
219243
execute(sub_machine, initial_depth + 1, heap_depth, backend, invoker)?
220244
};
221245

246+
match invoker.exit_substack(
247+
sub_result,
248+
invoker.deconstruct_machine(sub_machine),
249+
trap_data,
250+
&mut machine,
251+
backend,
252+
) {
253+
Ok(()) => {
254+
result = invoker.run_machine(&mut machine, backend);
255+
}
256+
Err(err) => return Ok((Err(err), machine)),
257+
}
258+
}
259+
Capture::Exit(Ok((
260+
trap_data,
261+
InvokerControl::DirectExit((sub_result, sub_machine)),
262+
))) => {
222263
match invoker.exit_substack(
223264
sub_result,
224265
sub_machine,
@@ -240,11 +281,22 @@ where
240281
}
241282
}
242283

243-
pub struct HeapTransact<'backend, 'invoker, H, Tr, I: Invoker<H, Tr>> {
244-
call_stack: CallStack<'backend, 'invoker, H, Tr, I>,
245-
transact_invoke: I::TransactInvoke,
284+
enum HeapTransactState<'backend, 'invoker, H, Tr, I: Invoker<H, Tr>> {
285+
Created {
286+
args: I::TransactArgs,
287+
invoker: &'invoker I,
288+
backend: &'backend mut H,
289+
},
290+
Running {
291+
call_stack: CallStack<'backend, 'invoker, H, Tr, I>,
292+
transact_invoke: I::TransactInvoke,
293+
},
246294
}
247295

296+
pub struct HeapTransact<'backend, 'invoker, H, Tr, I: Invoker<H, Tr>>(
297+
Option<HeapTransactState<'backend, 'invoker, H, Tr, I>>,
298+
);
299+
248300
impl<'backend, 'invoker, H, Tr, I> HeapTransact<'backend, 'invoker, H, Tr, I>
249301
where
250302
I: Invoker<H, Tr>,
@@ -254,13 +306,11 @@ where
254306
invoker: &'invoker I,
255307
backend: &'backend mut H,
256308
) -> Result<Self, ExitError> {
257-
let (transact_invoke, machine) = invoker.new_transact(args, backend)?;
258-
let call_stack = CallStack::new(machine, 0, backend, invoker);
259-
260-
Ok(Self {
261-
transact_invoke,
262-
call_stack,
263-
})
309+
Ok(Self(Some(HeapTransactState::Created {
310+
args,
311+
invoker,
312+
backend,
313+
})))
264314
}
265315

266316
fn step_with<FS>(
@@ -269,22 +319,70 @@ where
269319
) -> Result<(), Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
270320
where
271321
FS: Fn(
272-
&mut CallStack<H, Tr, I>,
322+
&mut CallStack<'backend, 'invoker, H, Tr, I>,
273323
) -> Result<(), Capture<Result<(ExitResult, I::Machine), ExitFatal>, I::Interrupt>>,
274324
{
275-
match fs(&mut self.call_stack) {
276-
Ok(()) => Ok(()),
277-
Err(Capture::Trap(interrupt)) => Err(Capture::Trap(interrupt)),
278-
Err(Capture::Exit(Err(fatal))) => Err(Capture::Exit(Err(fatal.into()))),
279-
Err(Capture::Exit(Ok((ret, machine)))) => {
280-
Err(Capture::Exit(self.call_stack.invoker.finalize_transact(
281-
&self.transact_invoke,
282-
ret,
283-
machine,
284-
self.call_stack.backend,
285-
)))
325+
let ret;
326+
327+
self.0 = match self.0.take() {
328+
Some(HeapTransactState::Running {
329+
mut call_stack,
330+
transact_invoke,
331+
}) => {
332+
ret = match fs(&mut call_stack) {
333+
Ok(()) => Ok(()),
334+
Err(Capture::Trap(interrupt)) => Err(Capture::Trap(interrupt)),
335+
Err(Capture::Exit(Err(fatal))) => Err(Capture::Exit(Err(fatal.into()))),
336+
Err(Capture::Exit(Ok((ret, machine)))) => {
337+
let machine = call_stack.invoker.deconstruct_machine(machine);
338+
Err(Capture::Exit(call_stack.invoker.finalize_transact(
339+
&transact_invoke,
340+
ret,
341+
machine,
342+
call_stack.backend,
343+
)))
344+
}
345+
};
346+
347+
Some(HeapTransactState::Running {
348+
call_stack,
349+
transact_invoke,
350+
})
286351
}
287-
}
352+
Some(HeapTransactState::Created {
353+
args,
354+
invoker,
355+
backend,
356+
}) => {
357+
let (transact_invoke, control) = match invoker.new_transact(args, backend) {
358+
Ok((transact_invoke, control)) => (transact_invoke, control),
359+
Err(err) => return Err(Capture::Exit(Err(err))),
360+
};
361+
362+
match control {
363+
InvokerControl::Enter(machine) => {
364+
let call_stack = CallStack::new(machine, 0, backend, invoker);
365+
366+
ret = Ok(());
367+
Some(HeapTransactState::Running {
368+
call_stack,
369+
transact_invoke,
370+
})
371+
}
372+
InvokerControl::DirectExit((exit, machine)) => {
373+
return Err(Capture::Exit(invoker.finalize_transact(
374+
&transact_invoke,
375+
exit,
376+
machine,
377+
backend,
378+
)));
379+
}
380+
}
381+
}
382+
None => return Err(Capture::Exit(Err(ExitFatal::AlreadyExited.into()))),
383+
};
384+
385+
ret
288386
}
289387

290388
pub fn step_run(
@@ -309,10 +407,13 @@ where
309407
}
310408
}
311409

312-
pub fn last_machine(&self) -> Result<&I::Machine, ExitError> {
313-
match &self.call_stack.last {
314-
Some(last) => Ok(&last.machine),
315-
None => Err(ExitFatal::AlreadyExited.into()),
410+
pub fn last_machine(&self) -> Option<&I::Machine> {
411+
match &self.0 {
412+
Some(HeapTransactState::Running { call_stack, .. }) => match &call_stack.last {
413+
Some(last) => Some(&last.machine),
414+
None => None,
415+
},
416+
_ => None,
316417
}
317418
}
318419
}
@@ -322,34 +423,47 @@ where
322423
I: Invoker<H, Tr>,
323424
{
324425
fn drop(&mut self) {
325-
if let Some(mut last) = self.call_stack.last.take() {
326-
loop {
327-
if let Some(mut parent) = self.call_stack.stack.pop() {
328-
let _ = self.call_stack.invoker.exit_substack(
329-
ExitFatal::Unfinished.into(),
330-
last.machine,
331-
parent.invoke,
332-
&mut parent.machine,
333-
self.call_stack.backend,
334-
);
426+
if let Some(state) = self.0.take() {
427+
match state {
428+
HeapTransactState::Running {
429+
mut call_stack,
430+
transact_invoke,
431+
} => {
432+
if let Some(mut last) = call_stack.last.take() {
433+
loop {
434+
if let Some(mut parent) = call_stack.stack.pop() {
435+
let last_machine =
436+
call_stack.invoker.deconstruct_machine(last.machine);
437+
let _ = call_stack.invoker.exit_substack(
438+
ExitFatal::Unfinished.into(),
439+
last_machine,
440+
parent.invoke,
441+
&mut parent.machine,
442+
call_stack.backend,
443+
);
444+
445+
last = LastSubstack {
446+
machine: parent.machine,
447+
status: LastSubstackStatus::Exited(Capture::Exit(
448+
ExitFatal::Unfinished.into(),
449+
)),
450+
};
451+
} else {
452+
break;
453+
}
454+
}
335455

336-
last = LastSubstack {
337-
machine: parent.machine,
338-
status: LastSubstackStatus::Exited(Capture::Exit(
456+
let last_machine = call_stack.invoker.deconstruct_machine(last.machine);
457+
let _ = call_stack.invoker.finalize_transact(
458+
&transact_invoke,
339459
ExitFatal::Unfinished.into(),
340-
)),
341-
};
342-
} else {
343-
break;
460+
last_machine,
461+
call_stack.backend,
462+
);
463+
}
344464
}
465+
_ => (),
345466
}
346-
347-
let _ = self.call_stack.invoker.finalize_transact(
348-
&self.transact_invoke,
349-
ExitFatal::Unfinished.into(),
350-
last.machine,
351-
self.call_stack.backend,
352-
);
353467
}
354468
}
355469
}
@@ -363,7 +477,16 @@ pub fn transact<H, Tr, I>(
363477
where
364478
I: Invoker<H, Tr, Interrupt = Infallible>,
365479
{
366-
let (transact_invoke, machine) = invoker.new_transact(args, backend)?;
367-
let (ret, machine) = execute(machine, 0, heap_depth, backend, invoker)?;
368-
invoker.finalize_transact(&transact_invoke, ret, machine, backend)
480+
let (transact_invoke, control) = invoker.new_transact(args, backend)?;
481+
482+
match control {
483+
InvokerControl::Enter(machine) => {
484+
let (ret, machine) = execute(machine, 0, heap_depth, backend, invoker)?;
485+
let machine = invoker.deconstruct_machine(machine);
486+
invoker.finalize_transact(&transact_invoke, ret, machine, backend)
487+
}
488+
InvokerControl::DirectExit((exit, machine)) => {
489+
invoker.finalize_transact(&transact_invoke, exit, machine, backend)
490+
}
491+
}
369492
}

0 commit comments

Comments
 (0)