-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Fix ewasm polyfills & enable corresponding tests. #9508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
a3cd729 to
20ade27
Compare
edd351a to
d3eb416
Compare
c0b6db3 to
90e3deb
Compare
d3eb416 to
f496857
Compare
5cd0a49 to
36193b2
Compare
215b340 to
614734e
Compare
05269ce to
cdddda1
Compare
614734e to
71958e6
Compare
cdddda1 to
88af39d
Compare
71958e6 to
0c462ac
Compare
88af39d to
f66a09a
Compare
|
Rebased in order to get the changes from #10135. |
|
We may want to clarify what memory model we are following with the EVM->Wasm translator. I assume we are trying to keep the memory matching with EVM aka. numbers stored are in big-endian order. This means we need to byteswap balances, but can just copy addresses and storage, as those are not treated as numbers in ewasm host functions. |
|
inline assembly should "just work". |
Agreed. I think in this case this PR may need quite a bit of work to only swap the correct things. It may be swapping sload/store right now which masks the problem. |
521e631 to
d7e23f1
Compare
I added a test |
| z3 := bswap64(i64.load(i32.add(pos, 16:i32))) | ||
| z4 := bswap64(i64.load(i32.add(pos, 24:i32))) | ||
| } | ||
| function mload_address(pos:i32) -> z2, z3, z4 { |
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.
We should start adding comments. Is this expecting to read 32 or 20 bytes from pos?
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 would read 24 bytes from pos. Yeah, we really need to add more comments in that file.
| z4 := bswap64(i64.load(i32.add(pos, 24:i32))) | ||
| } | ||
| function mload_address(pos:i32) -> z2, z3, z4 { | ||
| z2 := i64.and(bswap64(i64.load(pos)), 0x00000000ffffffff) |
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 not just read 32-bits here? (And adjust the offset in the caller too)
| z2 := i64.and(bswap64(i64.load(pos)), 0x00000000ffffffff) | |
| z2 := bswap32(i32.load(pos)) |
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 would only work, if we do something like bswap32(i64.extend_i32_u(i32.load(i32.add(pos, 4:i32)))). I think i64.and(bswap64(i64.load(pos)), 0x00000000ffffffff) is better readable.
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 really get it. As long as you only put in 20 bytes of the address in the memory and pos refers to that offset there is no extension needed. Why would bswap32 need i64 inputs?
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.
bswap32 is just defined like this - function bswap32(x) -> y. Maybe this can just be changed, I didn't tried that.
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 just changed that. I think it is better now.
|
I think what needs to be done is documenting how this is supposed to operate above the polyfill:
|
8fe45ba to
0b45a88
Compare
0b45a88 to
162ee37
Compare
| // address need to be encoded as a little endian unsigned integer. | ||
| // balance is of type u128 represented as a 16 bytes long | ||
| // little endian unsigned integer in memory. | ||
| eth.getExternalBalance(12:i32, 32:i32) |
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.
Following the hera implementation, eth.getExternalBalance(..) get the balance as big endian (evmc_uint256be), where this value is written to the defined offset via storeUint128, that uses storeMemoryReverse - resulting in little endianness.
| // little endian unsigned integer in memory. | ||
| eth.getExternalBalance(12:i32, 32:i32) | ||
| z3 := i64.load(40:i32) |
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 really understand why this actually works.
If z1, z2, z3, z4 is big endian, where the data is currently encoded as little endian, should'nt this be z3 := bswap64(i64.load(40)) and z4 := bswap64(i64.load(32)) - or, if that data is already stored as big endian, shouldn't this be z3 := i64.load(32) and z4 := i64.load(40).
Both variants are not working.
I don't understand why the i64's need to get loaded "reversely" z3 := i64.load(40) and z4:= i64.load(32) without the need of using bswap64.
| // eth.getAddress: Gets address of currently executing account and stores it | ||
| // in memory at the given offset. This address is encoded as a 160 bit number, | ||
| // represented as a 20 bytes long little endian unsigned integer in 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.
stores little-endian encoded 160 bit number
| // mload_address takes the little endian unsigned integer from memory and converts | ||
| // it to an big endian unsigned integer (evm is big endian). | ||
| z2, z3, z4 := mload_address(0:i32) |
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 adds 4 again - could either use 4 here or 0 above.
| lo := i64.and(x, 0xffffffff) | ||
| } | ||
| // xor(x, y): bitwise “xor” of x and y |
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.
Please do not use non-ascii characters
|
Is this PR still needed? |
|
@aarlt can we close this? |
Replaced by #10319, #10323, #10368, #10369, #10406.