github.com/aergoio/aergo@v1.3.1/contract/vm.c (about) 1 #include <string.h> 2 #include <stdlib.h> 3 #include "vm.h" 4 #include "system_module.h" 5 #include "contract_module.h" 6 #include "db_module.h" 7 #include "state_module.h" 8 #include "crypto_module.h" 9 #include "util.h" 10 #include "lgmp.h" 11 #include "_cgo_export.h" 12 13 const char *luaExecContext= "__exec_context__"; 14 const char *construct_name= "constructor"; 15 extern int luaopen_utf8 (lua_State *L); 16 17 static void preloadModules(lua_State *L) 18 { 19 int status; 20 21 luaopen_system(L); 22 luaopen_contract(L); 23 luaopen_state(L); 24 luaopen_json(L); 25 luaopen_crypto(L); 26 luaopen_gmp(L); 27 luaopen_utf8(L); 28 29 if (!IsPublic()) { 30 luaopen_db(L); 31 } 32 #ifdef MEASURE 33 lua_register(L, "nsec", lj_cf_nsec); 34 luaopen_jit(L); 35 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 36 lua_getfield(L, -1, "jit"); 37 lua_remove(L, -2); 38 lua_getfield(L, -1, "off"); 39 status = lua_pcall(L, 0, 0, 0); 40 if (status != LUA_OK) { 41 lua_pushstring(L, "cannot load the `jit` module"); 42 lua_error(L); 43 } 44 lua_remove(L, -1); /* remove jit.* */ 45 #endif 46 } 47 48 static void setLuaExecContext(lua_State *L, int *service) 49 { 50 lua_pushlightuserdata(L, service); 51 lua_setglobal(L, luaExecContext); 52 } 53 54 const int *getLuaExecContext(lua_State *L) 55 { 56 int *service; 57 lua_getglobal(L, luaExecContext); 58 service = (int *)lua_touserdata(L, -1); 59 lua_pop(L, 1); 60 if (*service == -1) 61 luaL_error(L, "not permitted state referencing at global scope"); 62 63 return service; 64 } 65 66 static int loadLibs(lua_State *L) 67 { 68 luaL_openlibs(L); 69 preloadModules(L); 70 return 0; 71 } 72 73 lua_State *vm_newstate() 74 { 75 lua_State *L = luaL_newstate(); 76 int status; 77 if (L == NULL) 78 return NULL; 79 status = lua_cpcall(L, loadLibs, NULL); 80 if (status != 0) 81 return NULL; 82 return L; 83 } 84 85 static int pcall(lua_State *L, int narg, int nret, int maxinstcount) 86 { 87 int err; 88 89 vm_set_count_hook(L, maxinstcount); 90 luaL_enablemaxmem(L); 91 92 err = lua_pcall(L, narg, nret, 0); 93 94 luaL_disablemaxmem(L); 95 lua_sethook(L, NULL, 0, 0); 96 97 return err; 98 } 99 100 const char *vm_loadbuff(lua_State *L, const char *code, size_t sz, char *hex_id, int *service) 101 { 102 int err; 103 104 setLuaExecContext(L, service); 105 106 err = luaL_loadbuffer(L, code, sz, hex_id) || pcall(L, 0, 0, 5000000); 107 if (err != 0) { 108 return lua_tostring(L, -1); 109 } 110 111 return NULL; 112 } 113 114 void vm_getfield(lua_State *L, const char *name) 115 { 116 lua_getfield(L, LUA_GLOBALSINDEX, name); 117 } 118 119 int vm_isnil(lua_State *L, int idx) 120 { 121 return lua_isnil(L, idx); 122 } 123 124 void vm_get_constructor(lua_State *L) 125 { 126 lua_getfield(L, LUA_GLOBALSINDEX, construct_name); 127 } 128 129 void vm_remove_constructor(lua_State *L) 130 { 131 lua_pushnil(L); 132 lua_setfield(L, LUA_GLOBALSINDEX, construct_name); 133 } 134 135 static void count_hook(lua_State *L, lua_Debug *ar) 136 { 137 luaL_setuncatchablerror(L); 138 lua_pushstring(L, "exceeded the maximum instruction count"); 139 luaL_throwerror(L); 140 } 141 142 void vm_set_count_hook(lua_State *L, int limit) 143 { 144 lua_sethook(L, count_hook, LUA_MASKCOUNT, limit); 145 } 146 147 const char *vm_pcall(lua_State *L, int argc, int *nresult) 148 { 149 int err; 150 int nr = lua_gettop(L) - argc - 1; 151 152 luaL_enablemaxmem(L); 153 154 err = lua_pcall(L, argc, LUA_MULTRET, 0); 155 156 luaL_disablemaxmem(L); 157 158 if (err != 0) { 159 lua_cpcall(L, lua_db_release_resource, NULL); 160 return lua_tostring(L, -1); 161 } 162 err = lua_cpcall(L, lua_db_release_resource, NULL); 163 if (err != 0) { 164 return lua_tostring(L, -1); 165 } 166 *nresult = lua_gettop(L) - nr; 167 return NULL; 168 } 169 170 const char *vm_get_json_ret(lua_State *L, int nresult, int* err) 171 { 172 int top = lua_gettop(L); 173 char *json_ret = lua_util_get_json_from_stack(L, top - nresult + 1, top, true); 174 175 if (json_ret == NULL) { 176 *err = 1; 177 return lua_tostring(L, -1); 178 } 179 180 lua_pushstring(L, json_ret); 181 free(json_ret); 182 183 return lua_tostring(L, -1); 184 } 185 186 const char *vm_copy_result(lua_State *L, lua_State *target, int cnt) 187 { 188 int i; 189 int top = lua_gettop(L); 190 char *json; 191 192 for (i = top - cnt + 1; i <= top; ++i) { 193 json = lua_util_get_json (L, i, false); 194 if (json == NULL) 195 return lua_tostring(L, -1); 196 197 minus_inst_count(L, strlen(json)); 198 lua_util_json_to_lua(target, json, false); 199 free (json); 200 } 201 return NULL; 202 } 203 204 sqlite3 *vm_get_db(lua_State *L) 205 { 206 int *service; 207 sqlite3 *db; 208 209 service = (int *)getLuaExecContext(L); 210 db = LuaGetDbHandle(service); 211 if (db == NULL) { 212 lua_pushstring(L, "can't open a database connection"); 213 luaL_throwerror(L); 214 } 215 return db; 216 } 217 218 void vm_get_abi_function(lua_State *L, char *fname) 219 { 220 lua_getfield(L, LUA_GLOBALSINDEX, "abi"); 221 lua_getfield(L, -1, "call"); 222 lua_pushstring(L, fname); 223 } 224