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

fix: Fix decommitment logic on out-of-gas #56

Merged
merged 2 commits into from
Aug 27, 2024
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
5 changes: 4 additions & 1 deletion src/decommit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,15 @@ impl WorldDiff {
decommit: UnpaidDecommit,
gas: &mut u32,
) -> Option<Program> {
// We intentionally record a decommitment event even if actual decommitment never happens because of an out-of-gas error.
// This is how the old VM behaves.
self.decommitted_hashes.insert(decommit.code_key, ());

if decommit.cost > *gas {
// Unlike all other gas costs, this one is not paid if low on gas.
return None;
}
*gas -= decommit.cost;
self.decommitted_hashes.insert(decommit.code_key, ());
Some(world.decommit(decommit.code_key))
}
}
Expand Down
40 changes: 37 additions & 3 deletions src/heap.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::instruction_handlers::HeapInterface;
use std::mem;
use std::ops::{Index, Range};
use std::{fmt, mem};
use u256::U256;

#[derive(Copy, Clone, PartialEq, Debug)]
Expand Down Expand Up @@ -31,11 +31,36 @@ impl Default for HeapPage {
}
}

#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Debug, Clone, Default)]
pub struct Heap {
pages: Vec<Option<HeapPage>>,
}

// We never remove `HeapPage`s (even after rollbacks – although we do zero all added pages in this case),
// we allow additional pages to be present if they are zeroed.
impl PartialEq for Heap {
fn eq(&self, other: &Self) -> bool {
for i in 0..self.pages.len().max(other.pages.len()) {
let this_page = self.pages.get(i).and_then(Option::as_ref);
let other_page = other.pages.get(i).and_then(Option::as_ref);
match (this_page, other_page) {
(Some(this_page), Some(other_page)) => {
if this_page != other_page {
return false;
}
}
(Some(page), None) | (None, Some(page)) => {
if page.0.iter().any(|&byte| byte != 0) {
return false;
}
}
(None, None) => { /* do nothing */ }
}
}
true
}
}

impl Heap {
fn from_bytes(bytes: &[u8], pagepool: &mut PagePool) -> Self {
let pages = bytes
Expand Down Expand Up @@ -272,9 +297,18 @@ impl PartialEq for Heaps {
}
}

#[derive(Default, Clone, Debug)]
#[derive(Default, Clone)]
struct PagePool(Vec<HeapPage>);

impl fmt::Debug for PagePool {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("PagePool")
.field("len", &self.0.len())
.finish_non_exhaustive()
}
}

impl PagePool {
fn allocate_page(&mut self) -> HeapPage {
self.get_dirty_page()
Expand Down
Loading