Skip to content

Commit

Permalink
Fix EXTHASHCODE
Browse files Browse the repository at this point in the history
  • Loading branch information
mickvangelderen committed Jan 11, 2024
1 parent 8aa8917 commit 5b348e8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
5 changes: 5 additions & 0 deletions evm_loader/program/src/evm/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ impl Buffer {
Buffer::new(Inner::Empty)
}

#[must_use]
pub fn buffer_is_empty(&self) -> bool {
matches!(self.inner, Inner::Empty)
}

#[must_use]
pub fn is_initialized(&self) -> bool {
!matches!(self.inner, Inner::AccountUninit { .. })
Expand Down
37 changes: 28 additions & 9 deletions evm_loader/program/src/executor/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,17 +285,36 @@ impl<'a, B: AccountStorage> Database for ExecutorState<'a, B> {
}

async fn code_hash(&self, from_address: Address, chain_id: u64) -> Result<[u8; 32]> {
use solana_program::keccak::hash;

for action in &self.actions {
if let Action::EvmSetCode { address, code, .. } = action {
if &from_address == address {
return Ok(hash(code).to_bytes());
}
}
// https://eips.ethereum.org/EIPS/eip-1052
// https://eips.ethereum.org/EIPS/eip-161

macro_rules! data_account_exists {
($self:ident, $address:ident, $chain_id:ident) => {
$self.nonce($address, $chain_id).await? > 0
|| $self.balance($address, $chain_id).await? > 0
};
}

Ok(self.backend.code_hash(from_address, chain_id).await)
// FIXME: Can we modify self.code to return Option<Buffer> or Option<&[u8]>?

// FIXME: Because buffer is returned by value, we need to store buffer in order to store a
// reference to the bytes. I could use Option<Buffer> instead, but that is storing a more
// powerful type than I need. I just need a byte slice.
let buffer = self.code(from_address).await?;
let bytes_to_hash: Option<&[u8]> = if !buffer.buffer_is_empty() {
// A program account exists at the address.
Some(&buffer)
} else if data_account_exists!(self, from_address, chain_id) {
// A data account exists at the address.
Some(&[])
} else {
// No account exists at the address.
None
};

Ok(bytes_to_hash
.map(|bytes| solana_program::keccak::hash(bytes).to_bytes())
.unwrap_or_default())
}

async fn code(&self, from_address: Address) -> Result<crate::evm::Buffer> {
Expand Down

0 comments on commit 5b348e8

Please sign in to comment.