Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement PrecompileSet trait #227

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions jsontests/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use evm::backend::in_memory::{
};
use evm::standard::{Config, Etable, Gasometer, Invoker, TransactArgs};
use evm::utils::u256_to_h256;
use evm::{Capture, GasedMachine};
use evm::Capture;
use primitive_types::U256;
use std::collections::{BTreeMap, BTreeSet};

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

let etable = Etable::runtime();
let invoker = Invoker::<_, Gasometer, _, _, _>::new(&config, &etable);
let invoker = Invoker::<_, Gasometer, _, (), _, _>::new(&config, &(), &etable);
let args = TransactArgs::Call {
caller: test.transaction.sender,
address: test.transaction.to,
Expand Down Expand Up @@ -101,13 +101,14 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test, debug: bool) -> R
let _step_result = evm::HeapTransact::new(args, &invoker, &mut step_backend).and_then(
|mut stepper| loop {
{
let machine: &GasedMachine<_, Gasometer> = stepper.last_machine()?;
println!(
"pc: {}, opcode: {:?}, gas: 0x{:x}",
machine.machine.position(),
machine.machine.peek_opcode(),
machine.gasometer.gas(),
);
if let Some(machine) = stepper.last_machine() {
println!(
"pc: {}, opcode: {:?}, gas: 0x{:x}",
machine.machine.position(),
machine.machine.peek_opcode(),
machine.gasometer.gas(),
);
}
}
if let Err(Capture::Exit(result)) = stepper.step() {
break result;
Expand Down
237 changes: 180 additions & 57 deletions src/call_stack.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Capture, ExitError, ExitFatal, ExitResult, Invoker};
use crate::{Capture, ExitError, ExitFatal, ExitResult, Invoker, InvokerControl};
use core::convert::Infallible;

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

let machine = self.invoker.deconstruct_machine(machine);
let feedback_result = self.invoker.exit_substack(
exit,
machine,
Expand Down Expand Up @@ -153,7 +154,7 @@ where
self.backend,
self.initial_depth + self.stack.len() + 1,
) {
Capture::Exit(Ok((trap_data, sub_machine))) => {
Capture::Exit(Ok((trap_data, InvokerControl::Enter(sub_machine)))) => {
self.stack.push(Substack {
invoke: trap_data,
machine,
Expand All @@ -164,6 +165,29 @@ where
machine: sub_machine,
})
}
Capture::Exit(Ok((
trap_data,
InvokerControl::DirectExit((exit, sub_machine)),
))) => {
let feedback_result = self.invoker.exit_substack(
exit,
sub_machine,
trap_data,
&mut machine,
self.backend,
);

match feedback_result {
Ok(()) => Some(LastSubstack {
status: LastSubstackStatus::Running,
machine,
}),
Err(err) => Some(LastSubstack {
machine,
status: LastSubstackStatus::Exited(Capture::Exit(Err(err))),
}),
}
}
Capture::Exit(Err(err)) => Some(LastSubstack {
status: LastSubstackStatus::Exited(Capture::Exit(Err(err))),
machine,
Expand Down Expand Up @@ -204,7 +228,7 @@ where
Capture::Exit(exit) => return Ok((exit, machine)),
Capture::Trap(trap) => {
match invoker.enter_substack(trap, &mut machine, backend, initial_depth + 1) {
Capture::Exit(Ok((trap_data, sub_machine))) => {
Capture::Exit(Ok((trap_data, InvokerControl::Enter(sub_machine)))) => {
let (sub_result, sub_machine) = if heap_depth
.map(|hd| initial_depth + 1 >= hd)
.unwrap_or(false)
Expand All @@ -219,6 +243,23 @@ where
execute(sub_machine, initial_depth + 1, heap_depth, backend, invoker)?
};

match invoker.exit_substack(
sub_result,
invoker.deconstruct_machine(sub_machine),
trap_data,
&mut machine,
backend,
) {
Ok(()) => {
result = invoker.run_machine(&mut machine, backend);
}
Err(err) => return Ok((Err(err), machine)),
}
}
Capture::Exit(Ok((
trap_data,
InvokerControl::DirectExit((sub_result, sub_machine)),
))) => {
match invoker.exit_substack(
sub_result,
sub_machine,
Expand All @@ -240,11 +281,22 @@ where
}
}

pub struct HeapTransact<'backend, 'invoker, H, Tr, I: Invoker<H, Tr>> {
call_stack: CallStack<'backend, 'invoker, H, Tr, I>,
transact_invoke: I::TransactInvoke,
enum HeapTransactState<'backend, 'invoker, H, Tr, I: Invoker<H, Tr>> {
Created {
args: I::TransactArgs,
invoker: &'invoker I,
backend: &'backend mut H,
},
Running {
call_stack: CallStack<'backend, 'invoker, H, Tr, I>,
transact_invoke: I::TransactInvoke,
},
}

pub struct HeapTransact<'backend, 'invoker, H, Tr, I: Invoker<H, Tr>>(
Option<HeapTransactState<'backend, 'invoker, H, Tr, I>>,
);

impl<'backend, 'invoker, H, Tr, I> HeapTransact<'backend, 'invoker, H, Tr, I>
where
I: Invoker<H, Tr>,
Expand All @@ -254,13 +306,11 @@ where
invoker: &'invoker I,
backend: &'backend mut H,
) -> Result<Self, ExitError> {
let (transact_invoke, machine) = invoker.new_transact(args, backend)?;
let call_stack = CallStack::new(machine, 0, backend, invoker);

Ok(Self {
transact_invoke,
call_stack,
})
Ok(Self(Some(HeapTransactState::Created {
args,
invoker,
backend,
})))
}

fn step_with<FS>(
Expand All @@ -269,22 +319,70 @@ where
) -> Result<(), Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
where
FS: Fn(
&mut CallStack<H, Tr, I>,
&mut CallStack<'backend, 'invoker, H, Tr, I>,
) -> Result<(), Capture<Result<(ExitResult, I::Machine), ExitFatal>, I::Interrupt>>,
{
match fs(&mut self.call_stack) {
Ok(()) => Ok(()),
Err(Capture::Trap(interrupt)) => Err(Capture::Trap(interrupt)),
Err(Capture::Exit(Err(fatal))) => Err(Capture::Exit(Err(fatal.into()))),
Err(Capture::Exit(Ok((ret, machine)))) => {
Err(Capture::Exit(self.call_stack.invoker.finalize_transact(
&self.transact_invoke,
ret,
machine,
self.call_stack.backend,
)))
let ret;

self.0 = match self.0.take() {
Some(HeapTransactState::Running {
mut call_stack,
transact_invoke,
}) => {
ret = match fs(&mut call_stack) {
Ok(()) => Ok(()),
Err(Capture::Trap(interrupt)) => Err(Capture::Trap(interrupt)),
Err(Capture::Exit(Err(fatal))) => Err(Capture::Exit(Err(fatal.into()))),
Err(Capture::Exit(Ok((ret, machine)))) => {
let machine = call_stack.invoker.deconstruct_machine(machine);
Err(Capture::Exit(call_stack.invoker.finalize_transact(
&transact_invoke,
ret,
machine,
call_stack.backend,
)))
}
};

Some(HeapTransactState::Running {
call_stack,
transact_invoke,
})
}
}
Some(HeapTransactState::Created {
args,
invoker,
backend,
}) => {
let (transact_invoke, control) = match invoker.new_transact(args, backend) {
Ok((transact_invoke, control)) => (transact_invoke, control),
Err(err) => return Err(Capture::Exit(Err(err))),
};

match control {
InvokerControl::Enter(machine) => {
let call_stack = CallStack::new(machine, 0, backend, invoker);

ret = Ok(());
Some(HeapTransactState::Running {
call_stack,
transact_invoke,
})
}
InvokerControl::DirectExit((exit, machine)) => {
return Err(Capture::Exit(invoker.finalize_transact(
&transact_invoke,
exit,
machine,
backend,
)));
}
}
}
None => return Err(Capture::Exit(Err(ExitFatal::AlreadyExited.into()))),
};

ret
}

pub fn step_run(
Expand All @@ -309,10 +407,13 @@ where
}
}

pub fn last_machine(&self) -> Result<&I::Machine, ExitError> {
match &self.call_stack.last {
Some(last) => Ok(&last.machine),
None => Err(ExitFatal::AlreadyExited.into()),
pub fn last_machine(&self) -> Option<&I::Machine> {
match &self.0 {
Some(HeapTransactState::Running { call_stack, .. }) => match &call_stack.last {
Some(last) => Some(&last.machine),
None => None,
},
_ => None,
}
}
}
Expand All @@ -322,34 +423,47 @@ where
I: Invoker<H, Tr>,
{
fn drop(&mut self) {
if let Some(mut last) = self.call_stack.last.take() {
loop {
if let Some(mut parent) = self.call_stack.stack.pop() {
let _ = self.call_stack.invoker.exit_substack(
ExitFatal::Unfinished.into(),
last.machine,
parent.invoke,
&mut parent.machine,
self.call_stack.backend,
);
if let Some(state) = self.0.take() {
match state {
HeapTransactState::Running {
mut call_stack,
transact_invoke,
} => {
if let Some(mut last) = call_stack.last.take() {
loop {
if let Some(mut parent) = call_stack.stack.pop() {
let last_machine =
call_stack.invoker.deconstruct_machine(last.machine);
let _ = call_stack.invoker.exit_substack(
ExitFatal::Unfinished.into(),
last_machine,
parent.invoke,
&mut parent.machine,
call_stack.backend,
);

last = LastSubstack {
machine: parent.machine,
status: LastSubstackStatus::Exited(Capture::Exit(
ExitFatal::Unfinished.into(),
)),
};
} else {
break;
}
}

last = LastSubstack {
machine: parent.machine,
status: LastSubstackStatus::Exited(Capture::Exit(
let last_machine = call_stack.invoker.deconstruct_machine(last.machine);
let _ = call_stack.invoker.finalize_transact(
&transact_invoke,
ExitFatal::Unfinished.into(),
)),
};
} else {
break;
last_machine,
call_stack.backend,
);
}
}
_ => (),
}

let _ = self.call_stack.invoker.finalize_transact(
&self.transact_invoke,
ExitFatal::Unfinished.into(),
last.machine,
self.call_stack.backend,
);
}
}
}
Expand All @@ -363,7 +477,16 @@ pub fn transact<H, Tr, I>(
where
I: Invoker<H, Tr, Interrupt = Infallible>,
{
let (transact_invoke, machine) = invoker.new_transact(args, backend)?;
let (ret, machine) = execute(machine, 0, heap_depth, backend, invoker)?;
invoker.finalize_transact(&transact_invoke, ret, machine, backend)
let (transact_invoke, control) = invoker.new_transact(args, backend)?;

match control {
InvokerControl::Enter(machine) => {
let (ret, machine) = execute(machine, 0, heap_depth, backend, invoker)?;
let machine = invoker.deconstruct_machine(machine);
invoker.finalize_transact(&transact_invoke, ret, machine, backend)
}
InvokerControl::DirectExit((exit, machine)) => {
invoker.finalize_transact(&transact_invoke, exit, machine, backend)
}
}
}
Loading
Loading