ewasm interface methods: synchronous vs asynchronous
Asynchronous ewasm methods were proposed to overcome this limitation of JS wasm environments. In the asynchronous version, contract code has callback entry points. This allows the wasm instance to call the host function, terminate, and then restart the instance at the callback entry point.
Here are example ewasm contracts comparing the two versions:
;; address 5d48c1018904a172886829bbbd9c6f4a2d06c47b has a balance of 0xde0b6b3a7640000 (1 ETH) (module ;; syhchronous getBalance method ;; params are addressOffset, resultOffset (import "ethereum" "getBalance" (func $getBalance (param i32 i32))) (memory 1 ) ;; address memory location at offset 0 (data (i32.const 0) "\5d\48\c1\01\89\04\a1\72\88\68\29\bb\bd\9c\6f\4a\2d\06\c4\7b") (export "memory" (memory 0)) (export "main" (func $main)) (func $main ;; pass 0 as the addressOffset, 100 as the resultOffset (call $getBalance (i32.const 0) (i32.const 100)) ;; getBalance host function result written to memory location 100 (if (i64.eq (i64.load (i32.const 100)) (i64.const 0xde0b6b3a7640000)) (return) ) (unreachable) ;; throw if getBalance result not equal to 1 ETH ) )
async proposal, example using getBalance
;; address 5d48c1018904a172886829bbbd9c6f4a2d06c47b has a balance of 0xde0b6b3a7640000 (1 ETH) (module ;; asynchronous getBalance method ;; params are addressOffset, resultOffset, and callbackIndex (import "ethereum" "getBalance" (func $balance (param i32 i32 i32))) (memory 1) (data (i32.const 0) "\5d\48\c1\01\89\04\a1\72\88\68\29\bb\bd\9c\6f\4a\2d\06\c4\7b") (export "memory" (memory 0)) (export "main" (func $main)) (export "1" (func $callback)) ;; callback entry point is an export with name "1" (func $main ;; pass 0 as the address memory location ;; pass 100 as the result memory location ;; pass 1 as the callback param (call $balance (i32.const 0) (i32.const 100) (i32.const 1)) ) (func $callback (block (if (i64.eq (i64.load (i32.const 100)) (i64.const 0xde0b6b3a7640000)) (return) ) (unreachable) ;; throw if test fails ) ) )
One approach is to use a
SharedArrayBuffer and Atomics inside the host function to block execution of the wasm instance. The problem with this approach is that browser vendors are disabling SharedArrayBuffer to mitigate the Spectre timing attack. For this approach to be practical, the sharedArrayBuffer would need to be reenabled in browsers and remain as an ECMAScript standard feature.