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
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

- run:
name: Checkstyle
command: cargo fmt -p ethcore -p ethcore-transaction -p ethkey -p vm -p wasm -p wasmer -- --check
command: cargo fmt -p ethcore -p ethcore-transaction -p ethkey -p vm -p wasm -- --check

# Build ethcore for runtime (SGX)
- run:
Expand All @@ -34,7 +34,7 @@ jobs:
# Run cargo tests
- run:
name: Run cargo tests
command: cargo test --package ethcore --package ethcore-transaction --package ethkey --package vm --package wasm --package wasmer --features "ethkey-test"
command: cargo test --package ethcore --package ethcore-transaction --package ethkey --package vm --package wasm --features "ethkey-test"

coverage:
machine: true
Expand Down
22 changes: 11 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ Major changes made by Oasis Labs:
* Parity runtime modified to run in Intel SGX, using the [Fortanix Rust Enclave Development Platform](https://github.com/fortanix/rust-sgx).
* Support for *confidential smart contracts*: transactions encrypted end-to-end and contract state encrypted in storage.
* [Blockchain WASI](https://github.com/oasislabs/rfcs/pull/1)-based runtime for WebAssembly contracts.
* Option to use the [Wasmer](https://github.com/wasmerio/wasmer) WebAssembly runtime rather than the standard [wasmi interpreter](https://github.com/oasislabs/wasmi) (*however Wasmer is not supported when running in SGX*).

For an example of how to use, see https://github.com/oasislabs/oasis-chain.
2 changes: 1 addition & 1 deletion ethcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version = "1.12.0"
authors = ["Parity Technologies <admin@parity.io>"]

[dependencies]
blockchain-traits = "0.3"
blockchain-traits = "0.4"
bloomchain = { path = "../util/bloomchain" }
bn = { git = "https://github.com/paritytech/bn", default-features = false }
byteorder = "1.0"
Expand Down
37 changes: 37 additions & 0 deletions ethcore/res/wasi-tests/src/bin/creator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#![feature(wasi_ext)]

use std::io::{Read as _, Write as _};
use std::os::wasi::prelude::FromRawFd;

#[link(wasm_import_module = "wasi_unstable")]
#[allow(improper_ctypes)]
extern "C" {
#[link_name = "blockchain_create"]
fn __wasi_blockchain_create(
value: *const u128,
code: *const u8,
code_len: u64,
fd: *mut libc::__wasi_fd_t,
) -> libc::__wasi_errno_t;
}

fn main() {
let value = 42u128;
let code = include_bytes!("../../target/service/create_ctor.wasm");
let mut fd = Default::default();
assert_eq!(
unsafe {
__wasi_blockchain_create(
&value as *const u128,
code.as_ptr(),
code.len() as u64,
&mut fd as *mut _,
)
},
libc::__WASI_ESUCCESS
);
let mut f_out = unsafe { std::fs::File::from_raw_fd(fd) };
let mut new_addr_bytes = Vec::new();
f_out.read_to_end(&mut new_addr_bytes).unwrap();
std::io::stdout().write_all(&new_addr_bytes).unwrap();
}
1 change: 1 addition & 0 deletions ethcore/res/wasi-tests/src/bin/xcc_a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::io::{Read as _, Write as _};
use std::os::wasi::prelude::FromRawFd;

#[link(wasm_import_module = "wasi_unstable")]
#[allow(improper_ctypes)]
extern "C" {
#[link_name = "blockchain_transact"]
fn __wasi_blockchain_transact(
Expand Down
Binary file not shown.
56 changes: 56 additions & 0 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2770,6 +2770,62 @@ mod tests {
);
}

evm_test! {test_wasm_create: test_wasm_create_int}
fn test_wasm_create(factory: Factory) {
let code = include_bytes!("../res/wasi-tests/target/service/creator.wasm").to_vec();
let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();

create_wasm_executive!(factory -> (state, exec));

exec.state
.add_balance(&sender, &U256::from(0xfffff), CleanupMode::NoEmpty)
.unwrap();

let creator_address = deploy_wasm(&mut exec, sender, &code);

let created_init_balance = 42;

let created_address = {
let mut params = ActionParams::default();
params.sender = sender;
params.address = creator_address;
params.gas = U256::from(1_000_000);
params.code = Some(Arc::new(code));
params.code_address = creator_address;
params.value = ActionValue::transfer(created_init_balance);

Address::from(
&*exec
.call(
params,
&mut Substate::new(),
BytesRef::Fixed(&mut []),
&mut NoopTracer,
&mut NoopVMTracer,
&mut NoopExtTracer,
)
.unwrap()
.return_data,
)
};

assert_eq!(state.balance(&creator_address).unwrap(), U256::zero());
assert_eq!(
state.balance(&created_address).unwrap(),
U256::from(created_init_balance)
);

// the following data is set by the constructor of `create_ctor.wasm`
let k = b"message";
let mut hk = [0u8; 32];
hk[..k.len()].copy_from_slice(k.as_ref());
let new_acct_data = state.storage_bytes_at(&created_address, &H256::from(hk));
assert_eq!(
new_acct_data.as_ref().map(|v| v.as_slice()),
Ok(b"hello".as_ref())
);
}

evm_test! {test_wasm_xcc: test_wasm_xcc_int}
fn test_wasm_xcc(factory: Factory) {
let code_xcc =
Expand Down
2 changes: 1 addition & 1 deletion ethcore/vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]

[dependencies]
blockchain-traits = "0.3"
blockchain-traits = "0.4"
oasis-types = "0.3"
byteorder = "1.0"
ethcore-bytes = { path = "../../util/bytes" }
Expand Down
4 changes: 2 additions & 2 deletions ethcore/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ edition = "2018"

[dependencies]
base64 = "0.10"
bcfs = "0.3"
blockchain-traits = "0.3"
bcfs = "0.4"
blockchain-traits = "0.4"
byteorder = "1.0"
common-types = { path = "../types" }
ethereum-types = { version = "0.3", default-features = false, features = ["std", "serialize"] }
Expand Down
71 changes: 70 additions & 1 deletion ethcore/wasm/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use bcfs::BCFS;
use blockchain_traits::{KVStore, KVStoreMut, PendingTransaction, TransactionOutcome};
use common_types::{u128_from_u256, u256_from_u128};
use ethereum_types::{Address, H256, U256};
use vm::{self, CallType, MessageCallResult, ReturnData};
use vm::{
self, CallType, ContractCreateResult, CreateContractAddress, MessageCallResult, ReturnData,
};
use wasmi::{self, Error as InterpreterError, MemoryRef, Trap, TrapKind};

pub struct RuntimeContext {
Expand Down Expand Up @@ -106,6 +108,71 @@ impl<'a> PendingTransaction for Runtime<'a> {
&self.args
}

fn create(&mut self, value: u128, code: &[u8]) -> Box<dyn blockchain_traits::Receipt> {
trace!(target: "wasm", "runtime: CREATE(value: {:?}), code {:?}", value, code);

let mut receipt = Box::new(Receipt {
caller: *eaddr2maddr(&self.context.address),
callee: oasis_types::Address::default(),
gas_used: 0,
outcome: TransactionOutcome::Fatal,
output: ReturnData::empty(),
});

if let Err(err) = self.adjusted_charge(|schedule| Some(schedule.create_gas as u64)) {
trace!("CREATE failed adjusted charge {:?}", err);
receipt.outcome = TransactionOutcome::InsufficientGas;
return receipt;
}

let pre_gas_left = match self.gas_left() {
Ok(gas_left) => gas_left,
Err(_) => {
receipt.outcome = TransactionOutcome::InsufficientGas;
return receipt;
}
};

let mut salt = H256::new();
self.rng.generate_to_slice(salt.as_mut(), None /* aad */);

let create_result = self.ext.create(
&pre_gas_left.into(),
&u256_from_u128(value),
code,
CreateContractAddress::FromSenderSaltAndCodeHash(salt),
);

match create_result {
ContractCreateResult::Created(new_contract_addr, post_gas_left) => {
receipt.outcome = TransactionOutcome::Success;
receipt.callee = *eaddr2maddr(&new_contract_addr);
receipt.gas_used = pre_gas_left - post_gas_left.low_u64();
// ^ by definition pre_gas_left > post_gas_left so this cannot overflow
if !self.charge_gas(receipt.gas_used) {
receipt.outcome = TransactionOutcome::InsufficientGas;
receipt.gas_used = self.gas_limit;
return receipt;
}
}
ContractCreateResult::Failed => {
receipt.outcome = TransactionOutcome::Fatal;
receipt.gas_used = self.gas_limit;
}
ContractCreateResult::Reverted(post_gas_left, return_data) => {
if !self.charge_gas(receipt.gas_used) {
receipt.outcome = TransactionOutcome::InsufficientGas;
receipt.gas_used = self.gas_limit;
return receipt;
}
receipt.outcome = TransactionOutcome::Aborted;
receipt.gas_used = pre_gas_left - post_gas_left.low_u64();
receipt.output = return_data;
}
}
return receipt;
}

/// Executes a balance-transferring RPC to `callee` with provided input and value.
/// The new transaction will inherit the gas parameters and gas payer of the top level
/// transaction. The current account will be set as the sender.
Expand All @@ -127,6 +194,8 @@ impl<'a> PendingTransaction for Runtime<'a> {

if let Err(err) = self.adjusted_charge(|schedule| Some(schedule.call_gas as u64)) {
trace!("CALL failed adjusted charge {:?}", err);
receipt.outcome = TransactionOutcome::InsufficientGas;
return receipt;
}

let pre_gas_left = match self.gas_left() {
Expand Down
Loading