-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Updated WASM Runtime & new interpreter (wasmi) #7796
Conversation
ethcore/wasm/src/tests.rs
Outdated
@@ -516,128 +519,10 @@ fn keccak() { | |||
}; | |||
|
|||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); | |||
assert_eq!(gas_left, U256::from(81_067)); | |||
assert_eq!(gas_left, U256::from(70_217)); | |||
} | |||
|
|||
// memcmp test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you delete this line too?
ethcore/wasm/src/runtime.rs
Outdated
} | ||
|
||
pub fn call(&mut self, context: InterpreterCallerContext) | ||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError> | ||
/// Read from the storage to wasm memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this should be the other way around: from wasm memory to the storage
?
ethcore/wasm/src/lib.rs
Outdated
|
||
if params.gas > ::std::u64::MAX.into() { | ||
return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned())); | ||
} | ||
|
||
let initial_memory = instantiation_resolover.memory_size().map_err(Error)? | ||
.saturating_sub(MEMORY_STIPEND); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite obscure IMO, could you please add comment clarifying why this is here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved to the schedule
ethcore/wasm/src/runtime.rs
Outdated
&self.result | ||
} | ||
|
||
pub fn dissolve(self) -> Vec<u8> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about into_result
?
25afff3
to
f85433b
Compare
@pepyakin addressed |
7db1f31
to
1332adf
Compare
ethcore/wasm/src/env.rs
Outdated
pub fn with_limit(max_memory: u32) -> ImportResolver { | ||
ImportResolver { | ||
max_memory: max_memory, | ||
.. Default::default() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this supposed to be memory (0, 0)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see.
Maybe it would be better to explicitly initialize memory
like RefCell::new(None)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed!
ethcore/wasm/src/env.rs
Outdated
pub fn memory_ref(&self) -> Result<MemoryRef, Error> { | ||
{ | ||
let mut mem_ref = self.memory.borrow_mut(); | ||
if mem_ref.is_none() { *mem_ref = Some(MemoryInstance::alloc(0, Some(0))?); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This invocation actually can't return error since params (0, Some(0))
are perfectly valid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But i don't want to depend on this invariant from other lib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But otherwise this code embeds this invariant into the consensus
ethcore/wasm/src/env.rs
Outdated
} | ||
} | ||
|
||
impl wasmi::ModuleImportResolver for ImportResolver { | ||
// todo: check against `_signature` ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stray TODO
IMO we should check signatures early and don't rely that execution engine will check them for us.
ethcore/wasm/src/env.rs
Outdated
|
||
impl ImportResolver { | ||
/// New import resolver with specifed maximum amount of inital memory. | ||
pub fn with_limit(max_memory: u32) -> ImportResolver { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is not clear that max_memory
is denoted in pages. Maybe it would be better if we leave a comments on this? Or maybe change the name to something like max_memory_pages
ethcore/wasm/src/env.rs
Outdated
) -> Result<MemoryRef, Error> { | ||
if field_name == "memory" { | ||
if descriptor.initial() >= self.max_memory || | ||
(descriptor.maximum().map_or(false, |m| m < descriptor.initial() || m > self.max_memory)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting check.
If I understand the intent correctly, it checks whether initial
or maximum
number of memory pages requested by the module is greater than some limit. In case if maximum
isn't provided then this check is passed and runtime proceeds to execution.
If that's correct, then I don't see the point. What stops the contract writer to not set maximum
limit on memory and then allocate amount of memory larger than the limit (don't we have the control on grow_memory
op, do we?).
And as I remember, don't we agreed that we don't want to restrict the upper memory limit by any means except the gas price?
5446ec8
to
b33fca5
Compare
/// Internal ids all functions runtime supports. This is just a glue for wasmi interpreter | ||
/// that lacks high-level api and later will be factored out | ||
pub mod ids { | ||
pub const STORAGE_WRITE_FUNC: usize = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the point of this 10-step numbering.
Also, maybe we can use some macro which will generate C-like enum, so we don't have to number this constants by hand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's implementation detail, will refactored once more high-level api for wasmi is available
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I'm fine with it.
ethcore/wasm/src/runtime.rs
Outdated
} else { | ||
Ok(()) | ||
} | ||
} | ||
|
||
pub fn overflow_charge<F>(&mut self, f: F) -> Result<(), InterpreterError> | ||
/// Adjusted charge applies wasm divisor coeff as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im not sure what you meant here...
9fac2ff
to
4ae0130
Compare
ethcore/wasm/src/runtime.rs
Outdated
} | ||
|
||
/// Return. Syscall takes 2 arguments - pointer in sandboxed memory where result is and | ||
/// the lendth of the result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: lendth → length
e9bdba7
to
9716018
Compare
ethcore/wasm/src/runtime.rs
Outdated
let result_alloc_len = context.value_stack.pop_as::<i32>()? as u32; | ||
trace!(target: "wasm", " result_len: {:?}", result_alloc_len); | ||
let vofs = if use_val { 1 } else { 0 }; | ||
let val = if use_val { Some(self.u256_at(args.nth(2)?)?) } else { None }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think such sorta dynamic signatures might lead to a disaster.
Can we fix this somehow? For example, change pwasm-std
in a such way that we always pass some dummy val
parameter?
I think even duplicating parameter decoding in methods *call
below would be a better solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't lead to disaster if there is test that shows that all arguments are mapped correctly, which is the case here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this multiplexing on the pwasm-std side? This way we'll get rid of all this dcall
/scall
and etc exports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so, these are mostly different operations, and might be handled completely differently lately, so it might be good idea to differentiate them at link time
also, EVM has different opcodes for those, so it's good to have 1-1 mapping opcode<->wasm external
let code_len: u32 = args.nth(2)?; | ||
trace!(target: "wasm", " code_len: {:?}", code_len); | ||
let result_ptr: u32 = args.nth(3)?; | ||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this code will more legible if we won't interleave argument decoding code with displaying it, as we do in do_call
.
At least, I'm wondering, should we synchronize them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
448c914
to
249327e
Compare
ethcore/wasm/src/lib.rs
Outdated
runtime.write_descriptor( | ||
if data_position < code.len() { &code[data_position..] } else { &[] } | ||
).map_err(Error)? | ||
// We count all memory except free (MEMORY_STIPEND) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the MEMORY_STIPEND?
@pepyakin all addressed |
* update back-references more aggressively after answering from cache (#7578) * Add new EF ropstens nodes. (#7824) * Add new EF ropstens nodes. * Fix tests * Add a timeout for light client sync requests (#7848) * Add a timeout for light client sync requests * Adjusting timeout to number of headers * Flush keyfiles. Resolves #7632 (#7868) * Fix wallet import (#7873) * rpc: generate new account id for imported wallets * ethstore: handle duplicate wallet filenames * ethstore: simplify deduplication of wallet file names * ethstore: do not dedup wallet filenames on update * ethstore: fix minor grumbles * [WASM] mem_cmp added to the Wasm runtime (#7539) * mem_cmp added to the Wasm runtime * schedule.wasm.mem_copy to schedule.wasm.mem_cmp for mem_cmp * [Wasm] memcmp fix and test added (#7590) * [Wasm] memcmp fix and test added * [Wasm] use reqrep_test! macro for memcmp test * wasmi interpreter (#7796) * adjust storage update evm-style (#7812) * disable internal memory (#7842)
cc @pepyakin