Implement KIP4: create2 for wasm (#9277)

* Basic implementation for kip4

* Add KIP-4 config flags

* typo: docs fix

* Fix args offset

* Add tests for create2

* tests: evm

* Update wasm-tests and fix all gas costs

* Update wasm-tests

* Update wasm-tests and fix gas costs
This commit is contained in:
Wei Tang
2018-08-06 23:15:52 +08:00
committed by GitHub
parent 3f2fd610d9
commit e8b13cb77e
11 changed files with 143 additions and 58 deletions

View File

@@ -321,7 +321,7 @@ impl<'a> Runtime<'a> {
if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); }
Ok(self.gas_limit - self.gas_counter)
}
/// General gas charging extern.
fn gas(&mut self, args: RuntimeArgs) -> Result<()> {
let amount: u32 = args.nth_checked(0)?;
@@ -511,29 +511,7 @@ impl<'a> Runtime<'a> {
self.return_u256_ptr(args.nth_checked(0)?, val)
}
/// Creates a new contract
///
/// Arguments:
/// * endowment - how much value (in Wei) transfer to the newly created contract
/// * code_ptr - pointer to the code data
/// * code_len - lenght of the code data
/// * result_ptr - pointer to write an address of the newly created contract
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue>
{
//
// method signature:
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
//
trace!(target: "wasm", "runtime: CREATE");
let endowment = self.u256_at(args.nth_checked(0)?)?;
trace!(target: "wasm", " val: {:?}", endowment);
let code_ptr: u32 = args.nth_checked(1)?;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let code_len: u32 = args.nth_checked(2)?;
trace!(target: "wasm", " code_len: {:?}", code_len);
let result_ptr: u32 = args.nth_checked(3)?;
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result<RuntimeValue> {
let code = self.memory.get(code_ptr, code_len as usize)?;
self.adjusted_charge(|schedule| schedule.create_gas as u64)?;
@@ -543,7 +521,7 @@ impl<'a> Runtime<'a> {
* U256::from(self.ext.schedule().wasm().opcodes_mul)
/ U256::from(self.ext.schedule().wasm().opcodes_div);
match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
match self.ext.create(&gas_left, &endowment, &code, scheme) {
vm::ContractCreateResult::Created(address, gas_left) => {
self.memory.set(result_ptr, &*address)?;
self.gas_counter = self.gas_limit -
@@ -571,6 +549,59 @@ impl<'a> Runtime<'a> {
}
}
/// Creates a new contract
///
/// Arguments:
/// * endowment - how much value (in Wei) transfer to the newly created contract
/// * code_ptr - pointer to the code data
/// * code_len - lenght of the code data
/// * result_ptr - pointer to write an address of the newly created contract
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
//
// method signature:
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
//
trace!(target: "wasm", "runtime: CREATE");
let endowment = self.u256_at(args.nth_checked(0)?)?;
trace!(target: "wasm", " val: {:?}", endowment);
let code_ptr: u32 = args.nth_checked(1)?;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let code_len: u32 = args.nth_checked(2)?;
trace!(target: "wasm", " code_len: {:?}", code_len);
let result_ptr: u32 = args.nth_checked(3)?;
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderAndCodeHash)
}
/// Creates a new contract using FromSenderSaltAndCodeHash scheme
///
/// Arguments:
/// * endowment - how much value (in Wei) transfer to the newly created contract
/// * salt - salt to be used in contract creation address
/// * code_ptr - pointer to the code data
/// * code_len - lenght of the code data
/// * result_ptr - pointer to write an address of the newly created contract
pub fn create2(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
//
// method signature:
// fn create2(endowment: *const u8, salt: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
//
trace!(target: "wasm", "runtime: CREATE2");
let endowment = self.u256_at(args.nth_checked(0)?)?;
trace!(target: "wasm", " val: {:?}", endowment);
let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into();
trace!(target: "wasm", " salt: {:?}", salt);
let code_ptr: u32 = args.nth_checked(2)?;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let code_len: u32 = args.nth_checked(3)?;
trace!(target: "wasm", " code_len: {:?}", code_len);
let result_ptr: u32 = args.nth_checked(4)?;
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderSaltAndCodeHash(salt))
}
fn debug(&mut self, args: RuntimeArgs) -> Result<()>
{
trace!(target: "wasm", "Contract debug message: {}", {
@@ -744,6 +775,7 @@ mod ext_impl {
SENDER_FUNC => void!(self.sender(args)),
ORIGIN_FUNC => void!(self.origin(args)),
ELOG_FUNC => void!(self.elog(args)),
CREATE2_FUNC => some!(self.create2(args)),
_ => panic!("env module doesn't provide function at index {}", index),
}
}