Skip to content
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
13 changes: 8 additions & 5 deletions crates/common/types/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ use crate::{
pub struct Code {
pub hash: H256,
pub bytecode: Bytes,
// TODO: Consider using Arc<[u16]> (needs to enable serde rc feature)
pub jump_targets: Vec<u16>,
// TODO: Consider using Arc<[u32]> (needs to enable serde rc feature)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment here or anywhere you consider convenient about the reason why we use 32 bits? So nobody changes it to u16 back again
If you want you can link EIP-3860 but it's not necessary

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it would be a good idea to link to the EIP. Also to the failing EEST test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When in doubt, overcommenting is better than undercommenting. Don't let school tell you otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment in da77868

// The valid addresses are 32-bit because, despite EIP-3860 restricting initcode size,
// this does not apply to previous forks. This is tested in the EEST tests, which would
// panic in debug mode.
pub jump_targets: Vec<u32>,
}

impl Code {
Expand All @@ -40,16 +43,16 @@ impl Code {
}
}

fn compute_jump_targets(code: &[u8]) -> Vec<u16> {
debug_assert!(code.len() <= u16::MAX as usize);
fn compute_jump_targets(code: &[u8]) -> Vec<u32> {
debug_assert!(code.len() <= u32::MAX as usize);
let mut targets = Vec::new();
let mut i = 0;
while i < code.len() {
// TODO: we don't use the constants from the vm module to avoid a circular dependency
match code[i] {
// OP_JUMPDEST
0x5B => {
targets.push(i as u16);
targets.push(i as u32);
}
// OP_PUSH1..32
c @ 0x60..0x80 => {
Expand Down
57 changes: 28 additions & 29 deletions crates/storage/store_db/rocksdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,14 +894,16 @@ impl StoreEngine for Store {
}

for (code_hash, code) in update_batch.code_updates {
let mut buf = Vec::with_capacity(6 + code.bytecode.len() + 2 * code.jump_targets.len());
let mut buf = Vec::with_capacity(
6 + code.bytecode.len()
+ code
.jump_targets
.iter()
.map(std::mem::size_of_val)
.sum::<usize>(),
);
code.bytecode.encode(&mut buf);
code.jump_targets
.into_iter()
.flat_map(|t| t.to_le_bytes())
.collect::<Vec<u8>>()
.as_slice()
.encode(&mut buf);
code.jump_targets.encode(&mut buf);
batch.put_cf(&cf_codes, code_hash.0, buf);
}

Expand Down Expand Up @@ -1268,14 +1270,16 @@ impl StoreEngine for Store {

async fn add_account_code(&self, code: Code) -> Result<(), StoreError> {
let hash_key = code.hash.0.to_vec();
let mut buf = Vec::with_capacity(6 + code.bytecode.len() + 2 * code.jump_targets.len());
let mut buf = Vec::with_capacity(
6 + code.bytecode.len()
+ code
.jump_targets
.iter()
.map(std::mem::size_of_val)
.sum::<usize>(),
);
code.bytecode.encode(&mut buf);
code.jump_targets
.into_iter()
.flat_map(|t| t.to_le_bytes())
.collect::<Vec<u8>>()
.as_slice()
.encode(&mut buf);
code.jump_targets.encode(&mut buf);
self.write_async(CF_ACCOUNT_CODES, hash_key, buf).await
}

Expand Down Expand Up @@ -1308,17 +1312,10 @@ impl StoreEngine for Store {
};
let bytes = Bytes::from_owner(bytes);
let (bytecode, targets) = decode_bytes(&bytes)?;
let (targets, rest) = decode_bytes(targets)?;
if !rest.is_empty() || !targets.len().is_multiple_of(2) {
return Err(StoreError::DecodeError);
}
let code = Code {
hash: code_hash,
bytecode: Bytes::copy_from_slice(bytecode),
jump_targets: targets
.chunks_exact(2)
.map(|c| u16::from_le_bytes([c[0], c[1]]))
.collect(),
jump_targets: <Vec<_>>::decode(targets)?,
};
Ok(Some(code))
}
Expand Down Expand Up @@ -1878,14 +1875,16 @@ impl StoreEngine for Store {

for (code_hash, code) in account_codes {
let key = code_hash.as_bytes().to_vec();
let mut buf = Vec::with_capacity(6 + code.bytecode.len() + 2 * code.jump_targets.len());
let mut buf = Vec::with_capacity(
6 + code.bytecode.len()
+ code
.jump_targets
.iter()
.map(std::mem::size_of_val)
.sum::<usize>(),
);
code.bytecode.encode(&mut buf);
code.jump_targets
.into_iter()
.flat_map(|t| t.to_le_bytes())
.collect::<Vec<u8>>()
.as_slice()
.encode(&mut buf);
code.jump_targets.encode(&mut buf);
batch_ops.push((CF_ACCOUNT_CODES.to_string(), key, buf));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'a> VM<'a> {
/// - Checking that the byte at the requested target PC is a JUMPDEST (0x5B).
/// - Ensuring the byte is not blacklisted. In other words, the 0x5B value is not part of a
/// constant associated with a push instruction.
fn target_address_is_valid(call_frame: &mut CallFrame, jump_address: u16) -> bool {
fn target_address_is_valid(call_frame: &mut CallFrame, jump_address: u32) -> bool {
call_frame
.bytecode
.jump_targets
Expand All @@ -305,14 +305,16 @@ impl<'a> VM<'a> {
/// to be equal to the specified address. If the address is not a
/// valid JUMPDEST, it will return an error
pub fn jump(call_frame: &mut CallFrame, jump_address: U256) -> Result<(), VMError> {
let jump_address_u16 = jump_address
let jump_address_u32 = jump_address
.try_into()
.map_err(|_err| ExceptionalHalt::VeryLargeNumber)?;

#[expect(clippy::arithmetic_side_effects)]
if Self::target_address_is_valid(call_frame, jump_address_u16) {
if Self::target_address_is_valid(call_frame, jump_address_u32) {
call_frame.increase_consumed_gas(gas_cost::JUMPDEST)?;
call_frame.pc = usize::from(jump_address_u16) + 1;
call_frame.pc = usize::try_from(jump_address_u32)
.map_err(|_err| ExceptionalHalt::VeryLargeNumber)?
+ 1;
Ok(())
} else {
Err(ExceptionalHalt::InvalidJump.into())
Expand Down
Loading