def instantiate_wasm_invoke_func(filename,funcname,args): file_ = open(filename, 'rb') if not file_: return "error, could not open "+filename bytestar = memoryview(file_.read()) if not bytestar: return "error, could not read "+filename module = wasm.decode_module(bytestar) #get module as abstract syntax #print("module",module) if not module: return "error, could not decode "+filename store = wasm.init_store() #do this once for each VM instance externvalstar = [] #imports, hopefully none store,moduleinst,ret = wasm.instantiate_module(store,module,externvalstar) if moduleinst == "error": return "error, module could not be instantiated" #print("moduleinst",moduleinst) externval = wasm.get_export(moduleinst, funcname) if not externval or externval[0]!="func": return "error, "+funcname+" is not a function export of the module" #print("externval",externval) funcaddr = externval[1] valstar = [["i32.const",int(arg)] for arg in args] #print("valstar",valstar) store,ret = wasm.invoke_func(store,funcaddr,valstar) if ret=="trap": return "error, invokation resulted in a trap" #print("ret",ret) if type(ret)==list and len(ret)>0: ret = ret[0] return ret
def instantiate_module_from_wasm_file(test,filename,store,registered_modules): if verbose>2: print("instantiate_module_from_wasm_file(",filename,")") if filename[-5:]!=".wasm": if verbose>1: print("we don't yet support .wast or .wat text format files") return store,None moduleinst = None with open(filename, 'rb') as f: #memoryview doesn't make copy, bytearray may require copy wasmbytes = memoryview(f.read()) module = wasm.decode_module(wasmbytes) #module = pywebassembly.decode_module(wasmbytes) #print("module",module) if module=="malformed": return None,"malformed" #validate ret = wasm.validate_module(module) #print("OKOK") #print(module) #ret = pywebassembly.validate_module(module) #print("valid:",ret) if type(ret)==str and ret[:14]=="error: invalid": #print(ret) #print(test["text"]) #if ret=="error: invalid: pop_opd": # #print(test["text"]) # if test["text"] != "type mismatch": # print("#######################################################") # print(test["text"]) # print(ret) #if ret=="pop_opd2" and test["text"]!="type mismatch": # print("#######################################################") return None,"invalid" #if test["type"]=="assert_invalid" and ret!="error: invalid": #TODO remove this # print("INVALID MISSED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",test) # return None,"invalid" #imports preparation externvalstar = [] #print("module",filename,module) for import_ in module["imports"]: if import_["module"] not in registered_modules: return store,"unlinkable" #error: module name doesn't exist importmoduleinst = registered_modules[import_["module"]] externval = None #print("importmoduleinst",importmoduleinst) #for key in importmoduleinst: # print(key,importmoduleinst[key]) for export in importmoduleinst["exports"]: if export["name"] == import_["name"]: externval = export["value"] if externval == None: return store,"unlinkable" #error: export name doesn't exist if externval[0] != import_["desc"][0]: return store,"unlinkable" #error: import type (func, table, mem, globa) doesn't match externvalstar += [externval] #print("store",store) #print("module",module) #print("externvalstar",externvalstar) store,moduleinst,ret = wasm.instantiate_module(store,module,externvalstar) #print("moduleinst",moduleinst) #print(store["mems"][0]["data"]) if moduleinst=="error": #print("instantiate_module_from_wasm_file",moduleinst,ret) return store,ret #ret is the actual error, eg "unlinkable" return store,moduleinst
def instantiate_module_from_wasm_file(filename, store, registered_modules): if verbose > 2: print("instantiate_module_from_wasm_file(", filename, ")") if filename[-5:] != ".wasm": if verbose > 1: print("we don't yet support .wast or .wat text format files") return store, None moduleinst = None with open(filename, 'rb') as f: #memoryview doesn't make copy, bytearray may require copy wasmbytes = memoryview(f.read()) module = pywebassembly.decode_module(wasmbytes) #imports preparation externvalstar = [] for import_ in module["imports"]: if import_["module"] not in registered_modules: return -1, -1 importmoduleinst = registered_modules[import_["module"]] externval = None for export in importmoduleinst["exports"]: if export["name"] == import_["name"]: externval = export["value"] if externval == None: return -1, -1 if externval[0] != import_["desc"][0]: return -1, -1 externvalstar += [externval] #print("store",store) #print("module",module) #print("externvalstar",externvalstar) store, moduleinst = pywebassembly.instantiate_module( store, module, externvalstar) #print("moduleinst",moduleinst) #print(store["mems"][0]["data"]) if moduleinst == "error": return store, None return store, moduleinst
def instantiate_wasm_invoke_start(filename): file_ = open(filename, 'rb') if not file_: return "error, could not open "+filename bytestar = memoryview(file_.read()) if not bytestar: return "error, could not read "+filename module = wasm.decode_module(bytestar) #get module as abstract syntax #print("module",module) if not module: return "error, could not decode "+filename store = wasm.init_store() #do this once for each VM instance externvalstar = [] #imports, hopefully none store,moduleinst,ret = wasm.instantiate_module(store,module,externvalstar) if moduleinst == "error": return "error, module could not be instantiated" return ret
def juno_execute(state, msg, tx_context, computation): logger = logging.getLogger('juno') code = computation.code gas = msg.gas args = msg.data if not has_wasm_preamble(code): raise Exception("Invalid code") logger.debug('juno_execute') # if VERBOSE>1: print("call_contract(",moduleid,funcname,arg,gas,")") # spin-up a VM instance with eei module 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 instantiate_eei_module(store,modules,gas) #instantiate the EEI module "ethereum" registered_modules["ethereum"] = modules["ethereum"] #register module "ethereum" to be import-able # instantiate module which contains the func to-be-called # module_as_bytes = trinity.get_module_as_bytes(moduleid) #TODO: need API to get module bytes module = wasm.decode_module(code) #get module as abstract syntax externvalstar = [] #populate imports for import_ in module["imports"]: if import_["module"] not in registered_modules: logger.error('module not in registered_modules') return -1, -1 importmoduleinst = registered_modules[import_["module"]] externval = None for export in importmoduleinst["exports"]: if export["name"] == import_["name"]: externval = export["value"] if externval == None: logger.error('Missing import') return None #error if externval[0] != import_["desc"][0]: logger.error('Bad imported function signature') return None #error externvalstar += [externval] store,moduleinst,ret = wasm.instantiate_module(store,module,externvalstar) # finally, call the function externval = wasm.get_export(moduleinst, "main") #we want to call function "main" funcaddr = externval[1] #the address of the funcname store,ret = wasm.invoke_func(store,funcaddr,args) #finally, invoke the function print("Initial gas was ", gas, ", gas left is ", store["gasLeft"]) computation.consume_gas(gas - store["gasLeft"], "juno")
def instantiate_module_from_wasm_file(test, filename, store, registered_modules): if verbose > 2: print("instantiate_module_from_wasm_file(", filename, ")") if filename[-5:] != ".wasm": if verbose > 1: print("we don't yet support .wast or .wat text format files") return store, None moduleinst = None with open(filename, 'rb') as f: #memoryview doesn't make copy, bytearray may require copy wasmbytes = memoryview(f.read()) module = wasm.decode_module(wasmbytes) if module == "malformed": return None, "malformed" #validate ret = wasm.validate_module(module) if type(ret) == str and ret[:14] == "error: invalid": return None, "invalid" #imports preparation externvalstar = [] #print("module",filename,module) for import_ in module["imports"]: if import_["module"] not in registered_modules: return store, "unlinkable" #error: module name doesn't exist importmoduleinst = registered_modules[import_["module"]] externval = None for export in importmoduleinst["exports"]: if export["name"] == import_["name"]: externval = export["value"] if externval == None: return store, "unlinkable" #error: export name doesn't exist if externval[0] != import_["desc"][0]: return store, "unlinkable" #error: import type (func, table, mem, globa) doesn't match externvalstar += [externval] store, moduleinst, ret = wasm.instantiate_module( store, module, externvalstar) if moduleinst == "error": return store, ret #ret is the actual error, eg "unlinkable" return store, moduleinst
import sys sys.path.append('..') import pywebassembly as wasm #set up VM for multiple modules store = wasm.init_store() #do this once for each VM instance modules = { } #all moduleinst's indexed by their names, used to call funcs and resolve exports #instantiate first module file_ = open('mod1.wasm', 'rb') bytecode = memoryview( file_.read()) #can also use bytearray or bytes instead of memoryview module = wasm.decode_module(bytecode) #get module as abstract syntax externvalstar = [] #imports, none for fibonacci.wasm store, moduleinst, ret = wasm.instantiate_module(store, module, externvalstar) #register this module instance so it can be imported from modules["mod1"] = moduleinst #instantiate second module file_ = open('mod2.wasm', 'rb') bytecode = memoryview( file_.read()) #can also use bytearray or bytes instead of memoryview module = wasm.decode_module(bytecode) #get module as abstract syntax externvalstar = [] #imports, none for fibonacci.wasm for import_ in module[ "imports"]: #for each import, look for it's matching export importmoduleinst = modules[import_["module"]] externval = None for export in importmoduleinst["exports"]:
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