Conversation
…g and direct usage.
wasm-runtime/std/src/lib.rs
Outdated
| $crate::vec::Vec::new() | ||
| } else { | ||
| unsafe { | ||
| $crate::vec::Vec::from_raw_parts(input_data, input_len, input_len) |
There was a problem hiding this comment.
as I said earlier in the chat, this will take ownership of this allocation and Vec will drop it at the end of the method. And if for some reason this pointer will be deallocated in other way it was deallocated then some bad things might happen.
I think that the best way to do this is to make client code responsible for deallocating input_data pointer (because the client code allocated this pointer in a first place) and use slice instead of a vector.
If this isn't desired for some reason, then I think it would be better to use slice and deallocate this pointer explicitly, preferably with a comment
| } | ||
| } | ||
|
|
||
| const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; |
There was a problem hiding this comment.
these constants should be at the top of the file
There was a problem hiding this comment.
ok - i put them down below as they're private and i wanted all public API first.
There was a problem hiding this comment.
for readability I usually prefer any constants to be declared before their usage rather than scattered throughout the file
There was a problem hiding this comment.
otherwise it can be hard to tell if they are actually from that file or imported from elsewhere
| if code == &native_equivalent[..] { | ||
| runtime_std::with_externalities(ext, || match method { | ||
| "execute_block" => safe_call(|| runtime::execute_block(&data.0)), | ||
| "execute_transaction" => safe_call(|| runtime::execute_transaction(&data.0)), |
There was a problem hiding this comment.
I am little worried about this since &mut T isn't UnwindSafe. But this code compiles because we've hidden the mutable reference in the with_externalities global.
Doesn't have to be for this PR, but the entire runtime should eventually change to not use panics unless the program should actually halt.
| assert_eq!( | ||
| WasmExecutor.call(&mut ext, &test_code[..], "test_ed25519_verify", &CallData(calldata)).unwrap(), | ||
| vec![1] | ||
| vec![0] |
There was a problem hiding this comment.
Why this set to 0? Is this workaround?
There was a problem hiding this comment.
0 is the legitimately expected result.
There was a problem hiding this comment.
Hm, could you help me to understand this?
- I thought this is a positive test, i.e. checks for successful verification.
- Looking at test_ed25519_verify it returns casted bool taken from
ed25519_verifyto u8, so ifed25519_verifyreturnstruethen it should returnvec![1u8]orvec![0u8]otherwise. ed25519_verifyhave no documentation which one of boolean values returns in case of successful result, but I almost certain thattrueshould be returned for successful verification.
There was a problem hiding this comment.
you're right about point 1, but ed25519_verify returns a u32 not a bool, with success being 0 and error conditions (of which there are several types) being non-zero. test_ed25519_verify is just a passthrough with a u8 cast, so we still expect a 0 for success.
There was a problem hiding this comment.
Hm, but if you follow my link, https://github.com/paritytech/polkadot/blob/1344dadd131629e39109ca7506d9f004da69eef4/wasm-runtime/std/src/lib.rs#L113
‘ed25519_verify’ in fact returbs a ‘bool’ not a u32
it is ‘ext_ed25519_verify’ returns u32
| pub fn ed25519_verify(sig: &[u8], msg: &[u8], pubkey: &[u8]) -> bool { | ||
| sig.len() != 64 || pubkey.len() != 32 || unsafe { | ||
| ext_ed25519_verify(&msg[0], msg.len() as u32, &sig[0], &pubkey[0]) | ||
| ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ptr()) |
There was a problem hiding this comment.
It seems to me the code above contains an error, and can be rewritten as:
if sig.len() ≠ 64 {
return true;
}
if pubkey.len() ≠ 32 {
return true;
}
let err_code = unsafe {
ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ptr())
};
err_code == 0I guess this isn't intended behavior...
| } else { | ||
| 0 | ||
| } | ||
| }, |
There was a problem hiding this comment.
memcmp should return 0 if sl1 == sl2, i.e. all bytes are equal,
should return a negative value if first different byte in sl1 is less than byte at the same position in sl2 and should return a positive value if this different byte from sl1 is greater than corresponding byte from sl2.
The problem is memcmp::Memcmp for some reason returns bool value, and seems like it returns true if slices are equal. So this implementation returns 1 in case slices are equal and 0 in other cases.
Also, in case if s1 or s2 can't be read, you return zero. This is not strictly a problem, because passing s1 or s2 which are out of bounds is undefined behavior and for such case returning 0 is perfeclty legal.
However, I strongly recommend to trap here, because:
- returning some value, especially
0(meaning thats1==s2), might lead to serious security problems, - such behavior will be inline with behavior of
memcmpimplemented within wasm itself.
Here you can find test cases which might help you to test implementation of memcmp extern.
wasm-runtime/pwasm-libc/src/lib.rs
Outdated
| ext_memcpy(dest, src, n) | ||
| } | ||
|
|
||
| /// memcpy extern |
There was a problem hiding this comment.
typo memcmp extern (or can we just get rid of these comments?)
executor/src/wasm_executor.rs
Outdated
| use memcmp::Memcmp; | ||
| (&sl1).memcmp(&sl2) as i32 | ||
| unsafe { | ||
| memcmp(sl1.as_ptr() as *const u8 as *const c_void, |
There was a problem hiding this comment.
can be replaced with safe code:
match sl1.cmp(&sl2) {
Ordering::Greater => 1,
Ordering::Less => -1,
Ordering::Equal => 0,
}There was a problem hiding this comment.
https://doc.rust-lang.org/stable/src/core/slice/mod.rs.html#2571
it's specialized to compile down to a memcmp and be inlined.
Insert keys using curl
* Add runtime/pos module * Add staking module and new substrate
Unify the styling of dependencies in Cargo.toml
Pass signature as &[u8] to avoid triggering From::from conversion
* Fix the module index used to create a encoded func Same as Events, modules with no calls should be ignored when calculating the module index. * Update substrate
Based on #42.
Executes the runtime natively, falling back to wasm if the code at compile time is different to that which should be executed.
Still todo: