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