Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
abukosek committed Oct 2, 2024
1 parent e890dd5 commit ea63dfd
Show file tree
Hide file tree
Showing 12 changed files with 4,128 additions and 179 deletions.
961 changes: 782 additions & 179 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
# Runtime SDK Modules.
"runtime-sdk/modules/contracts",
"runtime-sdk/modules/evm",
"runtime-sdk/modules/evm-new",

# Smart Contract SDK.
"contract-sdk",
Expand Down
48 changes: 48 additions & 0 deletions runtime-sdk/modules/evm-new/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[package]
name = "oasis-runtime-sdk-evm-new"
description = "New EVM module for the Oasis Runtime SDK."
version = "0.6.0"
authors = ["Oasis Protocol Foundation <[email protected]>"]
edition = "2021"
license = "Apache-2.0"

[dependencies]
cbor = { version = "0.5.1", package = "oasis-cbor" }
oasis-runtime-sdk = { path = "../.." }

# Third party.
anyhow = "1.0"
base64 = "0.22.1"
blake3 = { version = "~1.5.1", features = ["traits-preview"] }
thiserror = "1.0"
hex = "0.4.2"
k256 = "0.13.1"
sha3 = { version = "0.10", default-features = false }
once_cell = "1.8.0"

# Ethereum.
ethabi = { version = "18.0.0", default-features = false, features = ["std"] }
ethereum = "0.15"
revm = { git = "https://github.com/bluealloy/revm", tag = "v42" }
fixed-hash = "0.8.0"
primitive-types = { version = "0.12", default-features = false, features = ["rlp", "num-traits"] }
rlp = "0.5.2"
uint = "0.9.1"

# Fuzzing.
honggfuzz = "0.5.56"
serde = { version = "1.0.203", features = ["derive"], optional = true }
serde_json = { version = "1.0.116", features = ["raw_value"], optional = true }

[dev-dependencies]
criterion = "0.5.1"
oasis-runtime-sdk = { path = "../..", features = ["test"] }
rand = "0.8.5"
serde = { version = "1.0.203", features = ["derive"] }
serde_json = { version = "1.0.116", features = ["raw_value"] }
ethabi = { version = "18.0.0", default-features = false, features = ["std", "full-serde"] }

[features]
default = []
test = ["serde", "serde_json"]

106 changes: 106 additions & 0 deletions runtime-sdk/modules/evm-new/src/db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use revm::{
primitives::{keccak256, AccountInfo, Address, Bytecode, Log, B256, KECCAK_EMPTY, U256},
Database,
};
use std::{convert::Infallible, vec::Vec};

use std::marker::PhantomData;

use oasis_runtime_sdk::{
context::Context,
core::common::crypto::hash::Hash,
modules::{
accounts::API as _,
core::{self, API as _},
},
state::CurrentState,
subcall,
types::token,
Runtime,
};

use crate::{state, types, Config};

pub struct OasisDB<'ctx, C: Context, Cfg: Config> {
ctx: &'ctx C,
_cfg: PhantomData<Cfg>,
}

impl<'ctx, C: Context, Cfg: Config> OasisDB<'ctx, C, Cfg> {
pub fn new(ctx: &'ctx C) -> Self {
Self {
ctx,
_cfg: PhantomData,
}
}
}

impl<'ctx, C: Context, Cfg: Config> Database for OasisDB<'ctx, C, Cfg> {
type Error = Infallible;

/// Get basic account information.
fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
// Derive SDK account address from the Ethereum address.
let sdk_address = Cfg::map_address(address);

// Fetch balance and nonce from SDK accounts. Note that these can never fail.
let balance =
<C::Runtime as Runtime>::Accounts::get_balance(sdk_address, Cfg::TOKEN_DENOMINATION)
.unwrap();
let mut nonce = <C::Runtime as Runtime>::Accounts::get_nonce(sdk_address).unwrap();

// Fetch code for this address from storage.
let code = CurrentState::with_store(|store| {
let codes = state::codes(store);

if let Some(code) = codes.get::<_, Vec<u8>>(address) {
Some(Bytecode::new_raw(code.into()))
} else {
None
}
});

// Calculate hash of code if it exists.
let code_hash = match code {
None => KECCAK_EMPTY,
Some(ref bc) => bc.hash_slow(),
};

Ok(Some(AccountInfo {
nonce: nonce.into(),
balance: U256::from(balance),
code,
code_hash,
}))
}

/// Get account code by its hash (unimplemented).
fn code_by_hash(&mut self, _code_hash: B256) -> Result<Bytecode, Self::Error> {
// XXX: return an error here instead.
Ok(Bytecode::new())
}

/// Get storage value of address at index.
fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
let address: types::H160 = address.into_array().into();
let index: types::H256 = index.to_be_bytes().into(); // XXX: is BE ok?

let res: types::H256 = state::with_storage::<Cfg, _, _, _>(self.ctx, &address, |store| {
store.get(index).unwrap_or_default()
});
Ok(U256::from_be_bytes(res.into())) // XXX: is BE ok?
}

/// Get block hash by block number.
fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
CurrentState::with_store(|store| {
let block_hashes = state::block_hashes(store);

if let Some(hash) = block_hashes.get::<_, Hash>(&number.to_be_bytes()) {
Ok(B256::from_slice(hash.as_ref()))
} else {
Ok(B256::default())
}
})
}
}
21 changes: 21 additions & 0 deletions runtime-sdk/modules/evm-new/src/derive_caller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use oasis_runtime_sdk::types::{
address::SignatureAddressSpec,
transaction::{AddressSpec, AuthInfo, CallerAddress},
};

use crate::{types::H160, Error};

pub fn from_sigspec(spec: &SignatureAddressSpec) -> Result<H160, Error> {
match spec {
SignatureAddressSpec::Secp256k1Eth(pk) => Ok(H160::from_slice(&pk.to_eth_address())),
_ => Err(Error::InvalidSignerType),
}
}

pub fn from_tx_auth_info(ai: &AuthInfo) -> Result<H160, Error> {
match &ai.signer_info[0].address_spec {
AddressSpec::Signature(spec) => from_sigspec(spec),
AddressSpec::Internal(CallerAddress::EthAddress(address)) => Ok(address.into()),
_ => Err(Error::InvalidSignerType),
}
}
Loading

0 comments on commit ea63dfd

Please sign in to comment.