def instantiate_eei_module(store,modules,gas): # if VERBOSE>1: print("instantiate_eei_module()") store["gasLeft"] = gas #modify store with a gasLeft field, this is not in the Wasm spec wasm.alloc_func(store, [["i64"],[]], useGas) wasm.alloc_func(store, [[],["i64"]], getGasLeft) modules["ethereum"] = {"types": [[["i64"], []], [[], ["i64"]], ], "funcaddrs": [0, 1], "tableaddrs": [], "memaddrs": [], "globaladdrs": [], "exports": [{"name": "useGas", "value": ["func", 0]}, {"name": "getGasLeft", "value": ["func", 1]}, ] }
def instantiate_spectest_module(store): def spectest__print_i32(store, arg): if verbose > 1: print(arg) return store, [] def spectest__print_i64(store, arg): if verbose > 1: print(arg) return store, [] def spectest__print_f32(store, arg): if verbose > 1: print(arg) return store, [] def spectest__print_f64(store, arg): if verbose > 1: print(arg) return store, [] def spectest__print_i32_f32(store, arg): if verbose > 1: print(arg) return store, [] def spectest__print_f64_f64(store, arg): if verbose > 1: print(arg) return store, [] def spectest__print(store, arg): if verbose > 1: print(arg) return store, [] pywebassembly.alloc_func(store, [["i32"], []], spectest__print_i32) pywebassembly.alloc_func(store, [["i64"], []], spectest__print_i64) pywebassembly.alloc_func(store, [["f32"], []], spectest__print_f32) pywebassembly.alloc_func(store, [["f64"], []], spectest__print_f64) pywebassembly.alloc_func(store, [["i32", "f32"], []], spectest__print_i32_f32) pywebassembly.alloc_func(store, [["f64", "f64"], []], spectest__print_f64_f64) pywebassembly.alloc_func(store, [[], []], spectest__print) pywebassembly.alloc_mem(store, { "min": 1, "max": 2 }) #min:1,max:2 required by import.wast: pywebassembly.alloc_global(store, ["const", "i32"], 666) #666 required by import.wast pywebassembly.alloc_global(store, ["const", "f32"], 0.0) pywebassembly.alloc_global(store, ["const", "f64"], 0.0) pywebassembly.alloc_table(store, [{ "min": 10, "max": 20 }, "anyfunc"]) #max was 30, changed to 20 for import.wast moduleinst = { "types": [ [["i32"], []], [["i64"], []], [["i32"], []], [["f64"], []], [["i32", "f32"], []], [["f64", "f64"], []], [[], []], ], "funcaddrs": [0, 1, 2, 3, 4, 5, 6], "tableaddrs": [0], "memaddrs": [0], "globaladdrs": [0, 1, 2], "exports": [{ "name": "print_i32", "value": ["func", 0] }, { "name": "print_i64", "value": ["func", 1] }, { "name": "print_f32", "value": ["func", 2] }, { "name": "print_f64", "value": ["func", 3] }, { "name": "print_i32_f32", "value": ["func", 4] }, { "name": "print_f64_f64", "value": ["func", 5] }, { "name": "print", "value": ["func", 6] }, { "name": "memory", "value": ["mem", 0] }, { "name": "global_i32", "value": ["global", 0] }, { "name": "global_f32", "value": ["global", 1] }, { "name": "global_f64", "value": ["global", 2] }, { "name": "table", "value": ["table", 0] }] } return moduleinst
def instantiate_test_module(store): def test__func(store, arg): pass def test__func_i32(store, arg): pass def test__func_f32(store, arg): pass def test__func__i32(store, arg): pass def test__func__f32(store, arg): pass def test__func_i32_i32(store, arg): pass def test__func_i64_i64(store, arg): pass pywebassembly.alloc_func(store, [[], []], test__func) pywebassembly.alloc_func(store, [["i32"], []], test__func_i32) pywebassembly.alloc_func(store, [["f32"], []], test__func_f32) pywebassembly.alloc_func(store, [[], ["i32"]], test__func__i32) pywebassembly.alloc_func(store, [[], ["f32"]], test__func__f32) pywebassembly.alloc_func(store, [["i32"], ["i32"]], test__func_i32_i32) pywebassembly.alloc_func(store, [["i64"], ["i64"]], test__func_i64_i64) pywebassembly.alloc_mem(store, {"min": 1, "max": None}) pywebassembly.alloc_global(store, ["const", "i32"], 666) pywebassembly.alloc_global(store, ["const", "f32"], 0.0) pywebassembly.alloc_table(store, [{"min": 10, "max": None}, "anyfunc"]) moduleinst = { "types": [[["i32"], []], [["f32"], []], [[], ["i32"]], [[], ["f32"]], [["i32"], ["i32"]], [["i64"], ["i64"]]], "funcaddrs": [0, 1, 2, 3, 4, 5, 6], "tableaddrs": [0], "memaddrs": [0], "globaladdrs": [0, 1], "exports": [{ "name": "func", "value": ["func", 0] }, { "name": "func_i32", "value": ["func", 1] }, { "name": "func_f32", "value": ["func", 2] }, { "name": "func__i32", "value": ["func", 3] }, { "name": "func__f32", "value": ["func", 4] }, { "name": "func__i32_i32", "value": ["func", 5] }, { "name": "func__i64_i64", "value": ["func", 6] }, { "name": "memory-2-inf", "value": ["mem", 0] }, { "name": "global-i32", "value": ["global", 0] }, { "name": "global-f32", "value": ["global", 1] }, { "name": "table-10-inf", "value": ["table", 0] }] } return moduleinst
def exec_(self, calldata): """ The following function is used to call a given contract. This will "spin-up" a new VM, execute the contract, and output the contract's return values and gas used. """ self.calldata = calldata[:] # spin-up a VM modules = {} # all moduleinst's indexed by their names, used to call funcs and resolve exports registered_modules = {} # all moduleinst's which can be imported from, indexed by their registered name store = wasm.init_store() # done once and lasts for lifetime of this abstract machine # create host module def eth2_loadPreStateRoot(store,arg): if verbose: print("eth2_loadPreStateRoot") offset = arg[0] self.module_memory[offset:offset+32] = self.state_root[:] return store,[] def eth2_blockDataSize(store,arg): if verbose: print("eth2_blockDataSize", len(self.calldata)) return store,[len(self.calldata)] def eth2_blockDataCopy(store,arg): if verbose: print("eth2_blockDataCopy") memory_offset = arg[0] calldata_offset = arg[1] length = arg[2] self.module_memory[memory_offset:memory_offset+length] = self.calldata[calldata_offset:calldata_offset+length] return store,[] def eth2_savePostStateRoot(store,arg): if verbose: print("eth2_savePostStateRoot", arg[0]) offset = arg[0] self.state_root[:] = self.module_memory[offset:offset+32] return store,[] def eth2_pushNewDeposit(store,arg): if verbose: print("eth2_pushNewDeposit") offset = arg[0] length = arg[1] return store,[] def eth2_debugPrintMem(store,arg): if verbose: print("eth2_debugPrintMem") offset = arg[0] length = arg[1] print(self.module_memory[offset:offset+length]) return store,[] wasm.alloc_func(store, [["i32"],[]], eth2_loadPreStateRoot) wasm.alloc_func(store, [[],["i32"]], eth2_blockDataSize) wasm.alloc_func(store, [["i32","i32","i32"],[]], eth2_blockDataCopy) wasm.alloc_func(store, [["i32"],[]], eth2_savePostStateRoot) wasm.alloc_func(store, [["i32","i32"],[]], eth2_pushNewDeposit) wasm.alloc_func(store, [["i32","i32"],[]], eth2_debugPrintMem) modules["env"] = {"types":[[["i32"],[]], [[],["i32"]], [["i32","i32","i32"],[]], [["i32","i32"],[]], ], "funcaddrs":[0,1,2,3,4,5], "tableaddrs":[], "memaddrs":[], "globaladdrs":[], "exports":[{"name":"eth2_loadPreStateRoot","value":["func",0]}, {"name":"eth2_blockDataSize","value":["func",1]}, {"name":"eth2_blockDataCopy","value":["func",2]}, {"name":"eth2_savePostStateRoot","value":["func",3]}, {"name":"eth2_pushNewDeposit","value":["func",4]}, {"name":"eth2_debugPrintMem","value":["func",5]}, ] } # register the host module registered_modules["env"] = modules["env"] #register module "ethereum" to be import-able # instantiate module which contains the func to-be-called module = wasm.decode_module(self.bytecode) #get module as abstract syntax externvalstar = [] #populate imports for import_ in module["imports"]: if import_["module"] not in registered_modules: return None #error importmoduleinst = registered_modules[import_["module"]] externval = None for export in importmoduleinst["exports"]: if export["name"] == import_["name"]: externval = export["value"] if externval == None: return None #error if externval[0] != import_["desc"][0]: return None #error externvalstar += [externval] store,moduleinst,ret = wasm.instantiate_module(store,module,externvalstar) # get its memory self.module_memory = store["mems"][0]["data"] # finally, call the function externval = wasm.get_export(moduleinst, "main") #we want to call function "main" funcaddr = externval[1] #the address of the funcname args = [] store,ret = wasm.invoke_func(store,funcaddr,args) #finally, invoke the function return ret