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 single step for GasedMachine #217

Merged
merged 3 commits into from
Nov 18, 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
51 changes: 36 additions & 15 deletions jsontests/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,19 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test) -> Result<(), Err
})
.collect::<BTreeMap<_, _>>();

let mut backend = InMemoryBackend {
let etable = Etable::runtime();
let invoker = Invoker::new(&config);
let args = TransactArgs::Call {
caller: test.transaction.sender,
address: test.transaction.to,
value: test.transaction.value,
data: test.transaction.data,
gas_limit: test.transaction.gas_limit,
gas_price: test.transaction.gas_price,
access_list: Vec::new(),
};

let mut run_backend = InMemoryBackend {
environment: env,
layers: vec![InMemoryLayer {
state,
Expand All @@ -60,26 +72,35 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test) -> Result<(), Err
hots: BTreeSet::new(),
}],
};
let mut step_backend = run_backend.clone();

let etable = Etable::runtime();
let invoker = Invoker::new(&config);
let _result = evm::transact::<RuntimeState, Gasometer, _, _, _, _>(
TransactArgs::Call {
caller: test.transaction.sender,
address: test.transaction.to,
value: test.transaction.value,
data: test.transaction.data,
gas_limit: test.transaction.gas_limit,
gas_price: test.transaction.gas_price,
access_list: Vec::new(),
},
// Run

let _run_result = evm::transact::<RuntimeState, Gasometer, _, _, _, _>(
args.clone(),
Some(4),
&mut backend,
&mut run_backend,
&invoker,
&etable,
);

let state_root = crate::hash::state_root(&backend);
// Step
let mut stepper = evm::HeapTransact::<RuntimeState, Gasometer, _, _, _>::new(
args,
&invoker,
&mut step_backend,
)?;
let _step_result = loop {
println!(
"opcode: {:?}",
stepper.last_machine()?.machine.peek_opcode()
);
if let Err(result) = stepper.step(&etable) {
break result;
}
};

let state_root = crate::hash::state_root(&run_backend);

if state_root != test.post.hash {
return Err(TestError::StateMismatch.into());
Expand Down
104 changes: 85 additions & 19 deletions src/call_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
{
loop {
let step_ret = self.step(etable);
let step_ret = self.step_run(etable);

if let Some(step_ret) = step_ret {
if let Err(step_ret) = step_ret {
return step_ret;
}
}
Expand All @@ -75,9 +75,40 @@ where
pub fn step<F>(
&mut self,
etable: &Etable<S, H, Tr, F>,
) -> Option<Capture<Result<(ExitResult, GasedMachine<S, G>), ExitFatal>, I::Interrupt>>
) -> Result<(), Capture<Result<(ExitResult, GasedMachine<S, G>), ExitFatal>, I::Interrupt>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
{
self.step_with(etable, |machine, handler, etable| {
let result = machine.step(handler, etable);
match result {
Ok(()) => LastSubstackStatus::Running,
Err(result) => LastSubstackStatus::Exited(result),
}
})
}

pub fn step_run<F>(
&mut self,
etable: &Etable<S, H, Tr, F>,
) -> Result<(), Capture<Result<(ExitResult, GasedMachine<S, G>), ExitFatal>, I::Interrupt>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
{
self.step_with(etable, |machine, handler, etable| {
let result = machine.run(handler, etable);
LastSubstackStatus::Exited(result)
})
}

fn step_with<F, FS>(
&mut self,
etable: &Etable<S, H, Tr, F>,
fs: FS,
) -> Result<(), Capture<Result<(ExitResult, GasedMachine<S, G>), ExitFatal>, I::Interrupt>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
FS: Fn(&mut GasedMachine<S, G>, &mut H, &Etable<S, H, Tr, F>) -> LastSubstackStatus<Tr>,
{
let mut step_ret = None;

Expand All @@ -97,11 +128,8 @@ where
status: LastSubstackStatus::Running,
mut machine,
}) => {
let result = machine.run(self.backend, etable);
Some(LastSubstack {
status: LastSubstackStatus::Exited(result),
machine,
})
let status = fs(&mut machine, self.backend, etable);
Some(LastSubstack { status, machine })
}
Some(LastSubstack {
status: LastSubstackStatus::Exited(Capture::Exit(exit)),
Expand Down Expand Up @@ -173,7 +201,10 @@ where
}
};

step_ret
match step_ret {
Some(res) => Err(res),
None => Ok(()),
}
}
}

Expand Down Expand Up @@ -274,19 +305,27 @@ where
})
}

pub fn step<F>(
fn step_with<F, FS>(
&mut self,
etable: &Etable<S, H, Tr, F>,
) -> Option<Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
fs: FS,
) -> Result<(), Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
FS: Fn(
&mut CallStack<S, G, H, Tr, I>,
&Etable<S, H, Tr, F>,
) -> Result<
(),
Capture<Result<(ExitResult, GasedMachine<S, G>), ExitFatal>, I::Interrupt>,
>,
{
match self.call_stack.step(etable) {
None => None,
Some(Capture::Trap(interrupt)) => Some(Capture::Trap(interrupt)),
Some(Capture::Exit(Err(fatal))) => Some(Capture::Exit(Err(fatal.into()))),
Some(Capture::Exit(Ok((ret, machine)))) => {
Some(Capture::Exit(self.call_stack.invoker.finalize_transact(
match fs(&mut self.call_stack, etable) {
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,
Expand All @@ -296,6 +335,26 @@ where
}
}

pub fn step_run<F>(
&mut self,
etable: &Etable<S, H, Tr, F>,
) -> Result<(), Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
{
self.step_with(etable, |call_stack, etable| call_stack.step_run(etable))
}

pub fn step<F>(
&mut self,
etable: &Etable<S, H, Tr, F>,
) -> Result<(), Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
{
self.step_with(etable, |call_stack, etable| call_stack.step(etable))
}

pub fn run<F>(
&mut self,
etable: &Etable<S, H, Tr, F>,
Expand All @@ -304,13 +363,20 @@ where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
{
loop {
let step_ret = self.step(etable);
let step_ret = self.step_run(etable);

if let Some(step_ret) = step_ret {
if let Err(step_ret) = step_ret {
return step_ret;
}
}
}

pub fn last_machine(&self) -> Result<&GasedMachine<S, G>, ExitError> {
match &self.call_stack.last {
Some(last) => Ok(&last.machine),
None => Err(ExitFatal::AlreadyExited.into()),
}
}
}

impl<'backend, 'invoker, S, G, H, Tr, I> Drop for HeapTransact<'backend, 'invoker, S, G, H, Tr, I>
Expand Down
32 changes: 31 additions & 1 deletion src/gasometer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,21 @@ impl Gas for u64 {}
impl Gas for U256 {}

pub trait Gasometer<S, H>: Sized {
fn record_step(
&mut self,
machine: &Machine<S>,
is_static: bool,
backend: &H,
) -> Result<(), ExitError>;
fn record_stepn(
&mut self,
machine: &Machine<S>,
is_static: bool,
backend: &H,
) -> Result<usize, ExitError>;
) -> Result<usize, ExitError> {
self.record_step(machine, is_static, backend)?;
Ok(1)
}
fn record_codedeposit(&mut self, len: usize) -> Result<(), ExitError>;
fn gas(&self) -> U256;
fn submeter(&mut self, gas_limit: U256, code: &[u8]) -> Result<Self, ExitError>;
Expand All @@ -39,6 +48,27 @@ pub struct GasedMachine<S, G> {
}

impl<S: AsMut<RuntimeState>, G> GasedMachine<S, G> {
pub fn step<H, Tr, F>(
&mut self,
handler: &mut H,
etable: &Etable<S, H, Tr, F>,
) -> Result<(), Capture<ExitResult, Tr>>
where
F: Fn(&mut Machine<S>, &mut H, Opcode, usize) -> Control<Tr>,
G: Gasometer<S, H>,
{
match self
.gasometer
.record_step(&self.machine, self.is_static, handler)
{
Ok(()) => {
self.machine.state.as_mut().gas = self.gasometer.gas().into();
self.machine.step(handler, etable)
}
Err(e) => return Err(Capture::Exit(Err(e))),
}
}

pub fn run<H, Tr, F>(
&mut self,
handler: &mut H,
Expand Down
6 changes: 3 additions & 3 deletions src/standard/gasometer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ impl<'config, S: AsRef<RuntimeState>> TransactGasometer<'config, S> for Gasomete
}

impl<'config, S: AsRef<RuntimeState>, H: RuntimeBackend> GasometerT<S, H> for Gasometer<'config> {
fn record_stepn(
fn record_step(
&mut self,
machine: &Machine<S>,
is_static: bool,
handler: &H,
) -> Result<usize, ExitError> {
) -> Result<(), ExitError> {
self.perform(|gasometer| {
let opcode = machine.peek_opcode().ok_or(ExitException::OutOfGas)?;

Expand Down Expand Up @@ -169,7 +169,7 @@ impl<'config, S: AsRef<RuntimeState>, H: RuntimeBackend> GasometerT<S, H> for Ga
gas.extra_check(after_gas, gasometer.config)?;
}

Ok(1)
Ok(())
})
}

Expand Down
1 change: 1 addition & 0 deletions src/standard/invoker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub struct TransactInvoke {
pub caller: H160,
}

#[derive(Clone, Debug)]
pub enum TransactArgs {
Call {
caller: H160,
Expand Down
Loading