github.com/aergoio/aergo@v1.3.1/contract/system_module.c (about)

     1  #include <string.h>
     2  #include <stdlib.h>
     3  #include <time.h>
     4  #include <stdint.h>
     5  #include "vm.h"
     6  #include "util.h"
     7  #include "_cgo_export.h"
     8  
     9  #define STATE_DB_KEY_PREFIX "_"
    10  
    11  extern const int *getLuaExecContext(lua_State *L);
    12  
    13  static int systemPrint(lua_State *L)
    14  {
    15      char *jsonValue;
    16  	int *service = (int *)getLuaExecContext(L);
    17  
    18      jsonValue = lua_util_get_json_from_stack (L, 1, lua_gettop(L), true);
    19      if (jsonValue == NULL) {
    20  		luaL_throwerror(L);
    21  	}
    22      LuaPrint(L, service, jsonValue);
    23      free(jsonValue);
    24  	return 0;
    25  }
    26  
    27  static char *getDbKey(lua_State *L, int *len)
    28  {
    29      size_t size;
    30      char *key;
    31  
    32  	lua_pushvalue(L, 1);    /* prefix key */
    33  	lua_concat(L, 2);       /* dbKey(prefix..key) */
    34  	key = (char *)lua_tolstring(L, -1, &size);
    35  	*len = size;
    36  	return key;
    37  }
    38  
    39  int setItemWithPrefix(lua_State *L)
    40  {
    41  	char *dbKey;
    42  	char *jsonValue;
    43  	int *service = (int *)getLuaExecContext(L);
    44  	char *errStr;
    45  	int keylen;
    46  
    47  	if (service == NULL) {
    48  		luaL_error(L, "cannot find execution context");
    49  	}
    50  
    51  	luaL_checkstring(L, 1);
    52  	luaL_checkany(L, 2);
    53  	luaL_checkstring(L, 3);
    54  	dbKey = getDbKey(L, &keylen);
    55  
    56  	jsonValue = lua_util_get_json (L, 2, false);
    57  	if (jsonValue == NULL) {
    58  		luaL_throwerror(L);
    59  	}
    60  
    61  	if ((errStr = LuaSetDB(L, service, dbKey, keylen, jsonValue)) != NULL) {
    62  		free(jsonValue);
    63  		strPushAndRelease(L, errStr);
    64  		luaL_throwerror(L);
    65  	}
    66  	free(jsonValue);
    67  
    68  	return 0;
    69  }
    70  
    71  int setItem(lua_State *L)
    72  {
    73  	luaL_checkstring(L, 1);
    74  	luaL_checkany(L, 2);
    75  	lua_pushstring(L, STATE_DB_KEY_PREFIX);
    76  	return setItemWithPrefix(L);
    77  }
    78  
    79  int getItemWithPrefix(lua_State *L)
    80  {
    81  	char *dbKey;
    82  	int *service = (int *)getLuaExecContext(L);
    83  	char *jsonValue;
    84  	char *blkno = NULL;
    85  	struct LuaGetDB_return ret;
    86  	int keylen;
    87  
    88  	if (service == NULL) {
    89  		luaL_error(L, "cannot find execution context");
    90  	}
    91  	luaL_checkstring(L, 1);
    92  	if(lua_gettop(L) == 2) {
    93  	    luaL_checkstring(L, 2);
    94  	}
    95  	else if (lua_gettop(L) == 3) {
    96  	    if (!lua_isnil(L, 2)) {
    97  	        int type = lua_type(L,2);
    98  	        if (type != LUA_TNUMBER && type != LUA_TSTRING)
    99  	            luaL_error(L, "snap height permitted number or string type");
   100  	        blkno = (char *)lua_tostring(L, 2);
   101  	    }
   102  	    luaL_checkstring(L, 3);
   103  	}
   104  	dbKey = getDbKey(L, &keylen);
   105  
   106  	ret = LuaGetDB(L, service, dbKey, keylen, blkno);
   107  	if (ret.r1 != NULL) {
   108          strPushAndRelease(L, ret.r1);
   109  		luaL_throwerror(L);
   110  	}
   111  	if (ret.r0 == NULL)
   112  		return 0;
   113  
   114      minus_inst_count(L, strlen(ret.r0));
   115  	if (lua_util_json_to_lua(L, ret.r0, false) != 0) {
   116  	    strPushAndRelease(L, ret.r0);
   117  		luaL_error(L, "getItem error : can't convert %s", lua_tostring(L, -1));
   118  	}
   119  	return 1;
   120  }
   121  
   122  int getItem(lua_State *L)
   123  {
   124  	luaL_checkstring(L, 1);
   125  	lua_pushstring(L, STATE_DB_KEY_PREFIX);
   126  	if (lua_gettop(L) == 3) {
   127  	    if (!lua_isnil(L, 2))
   128  	        luaL_checknumber(L, 2);
   129  	}
   130  	return getItemWithPrefix(L);
   131  }
   132  
   133  int delItemWithPrefix(lua_State *L)
   134  {
   135  	char *dbKey;
   136  	int *service = (int *)getLuaExecContext(L);
   137  	char *jsonValue;
   138  	char *ret;
   139  	int keylen;
   140  
   141  	if (service == NULL) {
   142  		luaL_error(L, "cannot find execution context");
   143  	}
   144  	luaL_checkstring(L, 1);
   145  	luaL_checkstring(L, 2);
   146  	dbKey = getDbKey(L, &keylen);
   147  	ret = LuaDelDB(L, service, dbKey, keylen);
   148  	if (ret != NULL) {
   149  	    strPushAndRelease(L, ret);
   150  		luaL_throwerror(L);
   151  	}
   152      return 0;
   153  }
   154  
   155  static int getSender(lua_State *L)
   156  {
   157  	int *service = (int *)getLuaExecContext(L);
   158  	char *sender;
   159  	if (service == NULL) {
   160  		luaL_error(L, "cannot find execution context");
   161  	}
   162  	sender = LuaGetSender(L, service);
   163  	strPushAndRelease(L, sender);
   164  	return 1;
   165  }
   166  
   167  static int getTxhash(lua_State *L)
   168  {
   169  	int *service = (int *)getLuaExecContext(L);
   170  	char *hash;
   171  	if (service == NULL) {
   172  		luaL_error(L, "cannot find execution context");
   173  	}
   174  	hash = LuaGetHash(L, service);
   175  	strPushAndRelease(L, hash);
   176  	return 1;
   177  }
   178  
   179  static int getBlockHeight(lua_State *L)
   180  {
   181  	int *service = (int *)getLuaExecContext(L);
   182  	if (service == NULL) {
   183  		luaL_error(L, "cannot find execution context");
   184  	}
   185  	lua_pushinteger(L, LuaGetBlockNo(L, service));
   186  	return 1;
   187  }
   188  
   189  static int getTimestamp(lua_State *L)
   190  {
   191  	int *service = (int *)getLuaExecContext(L);
   192  	if (service == NULL) {
   193  		luaL_error(L, "cannot find execution context");
   194  	}
   195  	lua_pushinteger(L, LuaGetTimeStamp(L, service));
   196  	return 1;
   197  }
   198  
   199  static int getContractID(lua_State *L)
   200  {
   201  	int *service = (int *)getLuaExecContext(L);
   202  	char *id;
   203  	if (service == NULL) {
   204  		luaL_error(L, "cannot find execution context");
   205  	}
   206  	id = LuaGetContractId(L, service);
   207  	strPushAndRelease(L, id);
   208  	return 1;
   209  }
   210  
   211  static int getCreator(lua_State *L)
   212  {
   213  	int *service = (int *)getLuaExecContext(L);
   214  	struct LuaGetDB_return ret;
   215  	int keylen = 7;
   216  
   217  	if (service == NULL) {
   218  		luaL_error(L, "cannot find execution context");
   219  	}
   220  	ret = LuaGetDB(L, service, "Creator", keylen, 0);
   221  	if (ret.r1 != NULL) {
   222  	    strPushAndRelease(L, ret.r1);
   223  		luaL_throwerror(L);
   224  	}
   225  	if (ret.r0 == NULL)
   226  		return 0;
   227  	strPushAndRelease(L, ret.r0);
   228  	return 1;
   229  }
   230  
   231  static int getAmount(lua_State *L)
   232  {
   233  	int *service = (int *)getLuaExecContext(L);
   234  	char *amount;
   235  	if (service == NULL) {
   236  		luaL_error(L, "cannot find execution context");
   237  	}
   238  	amount = LuaGetAmount(L, service);
   239  	strPushAndRelease(L, amount);
   240  	return 1;
   241  }
   242  
   243  static int getOrigin(lua_State *L)
   244  {
   245  	int *service = (int *)getLuaExecContext(L);
   246  	char *origin;
   247  	if (service == NULL) {
   248  		luaL_error(L, "cannot find execution context");
   249  	}
   250  	origin = LuaGetOrigin(L, service);
   251  	strPushAndRelease(L, origin);
   252  	return 1;
   253  }
   254  
   255  static int getPrevBlockHash(lua_State *L)
   256  {
   257  	int *service = (int *)getLuaExecContext(L);
   258  	char *hash;
   259  	if (service == NULL) {
   260  		luaL_error(L, "cannot find execution context");
   261  	}
   262  	hash = LuaGetPrevBlockHash(L, service);
   263  	strPushAndRelease(L, hash);
   264  	return 1;
   265  }
   266  /* datetime-related functions from lib_os.c. time(NULL) is replaced by blocktime(L) */
   267  
   268  static void setfield(lua_State *L, const char *key, int value)
   269  {
   270      lua_pushinteger(L, value);
   271      lua_setfield(L, -2, key);
   272  }
   273  
   274  static void setboolfield(lua_State *L, const char *key, int value)
   275  {
   276      if (value < 0)  /* undefined? */
   277          return;  /* does not set field */
   278      lua_pushboolean(L, value);
   279      lua_setfield(L, -2, key);
   280  }
   281  
   282  static int getboolfield(lua_State *L, const char *key)
   283  {
   284      int res;
   285      lua_getfield(L, -1, key);
   286      res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
   287      lua_pop(L, 1);
   288      return res;
   289  }
   290  
   291  static int getfield(lua_State *L, const char *key, int d)
   292  {
   293      int res;
   294      lua_getfield(L, -1, key);
   295      if (lua_isnumber(L, -1)) {
   296          res = (int)lua_tointeger(L, -1);
   297      } else {
   298          if (d < 0)
   299              luaL_error(L, "field " LUA_QS " missing in date table", key);
   300          res = d;
   301      }
   302      lua_pop(L, 1);
   303      return res;
   304  }
   305  
   306  static time_t blocktime(lua_State *L)
   307  {
   308      time_t t;
   309      getTimestamp(L);
   310      t = (time_t)lua_tointeger(L, -1);
   311      lua_pop(L, 1);
   312      return t;
   313  }
   314  
   315  static int os_date(lua_State *L)
   316  {
   317      const char *s = luaL_optstring(L, 1, "%c");
   318      time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, blocktime(L));
   319      struct tm *stm;
   320  #if LJ_TARGET_POSIX
   321      struct tm rtm;
   322  #endif
   323      if (*s == '!') {  /* UTC? */
   324          s++;  /* Skip '!' */
   325      }
   326  #if LJ_TARGET_POSIX
   327      stm = gmtime_r(&t, &rtm);
   328  #else
   329      stm = gmtime(&t);
   330  #endif
   331      if (stm == NULL) {  /* Invalid date? */
   332          lua_pushnil(L);
   333      } else if (strcmp(s, "*t") == 0) {
   334          lua_createtable(L, 0, 9);  /* 9 = number of fields */
   335          setfield(L, "sec", stm->tm_sec);
   336          setfield(L, "min", stm->tm_min);
   337          setfield(L, "hour", stm->tm_hour);
   338          setfield(L, "day", stm->tm_mday);
   339          setfield(L, "month", stm->tm_mon+1);
   340          setfield(L, "year", stm->tm_year+1900);
   341          setfield(L, "wday", stm->tm_wday+1);
   342          setfield(L, "yday", stm->tm_yday+1);
   343          setboolfield(L, "isdst", stm->tm_isdst);
   344      } else {
   345          char cc[3];
   346          luaL_Buffer b;
   347          cc[0] = '%'; cc[2] = '\0';
   348          luaL_buffinit(L, &b);
   349          for (; *s; s++) {
   350              if (*s != '%' || *(s + 1) == '\0') {  /* No conversion specifier? */
   351                  luaL_addchar(&b, *s);
   352              } else {
   353                  size_t reslen;
   354                  char buff[200];  /* Should be big enough for any conversion result. */
   355                  cc[1] = *(++s);
   356                  if (cc[1] == 'c') {
   357                      reslen = strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", stm);
   358                  } else {
   359                      reslen = strftime(buff, sizeof(buff), cc, stm);
   360                  }
   361                  luaL_addlstring(&b, buff, reslen);
   362              }
   363          }
   364          luaL_pushresult(&b);
   365      }
   366      return 1;
   367  }
   368  
   369  static int os_time(lua_State *L)
   370  {
   371      time_t t;
   372      if (lua_isnoneornil(L, 1)) {
   373          t = blocktime(L);
   374      } else {
   375          struct tm ts;
   376          luaL_checktype(L, 1, LUA_TTABLE);
   377          lua_settop(L, 1);  /* make sure table is at the top */
   378          ts.tm_sec = getfield(L, "sec", 0);
   379          ts.tm_min = getfield(L, "min", 0);
   380          ts.tm_hour = getfield(L, "hour", 12);
   381          ts.tm_mday = getfield(L, "day", -1);
   382          ts.tm_mon = getfield(L, "month", -1) - 1;
   383          ts.tm_year = getfield(L, "year", -1) - 1900;
   384          ts.tm_isdst = getboolfield(L, "isdst");
   385  #if LJ_TARGET_POSIX
   386          t = timegm(&ts);
   387  #else
   388          t = _mkgmtime(&ts);
   389  #endif
   390      }
   391      if (t == (time_t)(-1))
   392          lua_pushnil(L);
   393      else
   394          lua_pushnumber(L, (lua_Number)t);
   395      return 1;
   396  }
   397  
   398  static int os_difftime(lua_State *L)
   399  {
   400      lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
   401                  (time_t)(luaL_optnumber(L, 2, (lua_Number)0))));
   402      return 1;
   403  }
   404  
   405  /* end of datetime functions */
   406  
   407  static int lua_random(lua_State *L)
   408  {
   409  	int *service = (int *)getLuaExecContext(L);
   410  	int min, max;
   411  
   412  	if (service == NULL) {
   413  		luaL_error(L, "cannot find execution context");
   414      }
   415  
   416  	switch (lua_gettop(L)) {
   417  	case 1:
   418          max = luaL_checkint(L, 1);
   419          if (max < 1) {
   420              luaL_error(L, "system.random: the maximum value must be greater than zero");
   421          }
   422          lua_pushinteger(L, LuaRandomInt(1, max, *service));
   423          break;
   424  	case 2:
   425  		min = luaL_checkint(L, 1);
   426  		max = luaL_checkint(L, 2);
   427  		if (min < 1) {
   428  			luaL_error(L, "system.random: the minimum value must be greater than zero");
   429  		}
   430  		if (min > max) {
   431  			luaL_error(L, "system.random: the maximum value must be greater than the minimum value");
   432  		}
   433          lua_pushinteger(L, LuaRandomInt(min, max, *service));
   434          break;
   435  	default:
   436          luaL_error(L, "system.random: 1 or 2 arguments required");
   437          break;
   438  	}
   439  
   440      return 1;
   441  }
   442  
   443  static int is_contract(lua_State *L)
   444  {
   445      char *contract;
   446  	int *service = (int *)getLuaExecContext(L);
   447  	struct LuaIsContract_return ret;
   448  
   449  	if (service == NULL) {
   450  		luaL_error(L, "cannot find execution context");
   451      }
   452  
   453  	contract = (char *)luaL_checkstring(L, 1);
   454      ret = LuaIsContract(L, service, contract);
   455  	if (ret.r1 != NULL) {
   456  	    strPushAndRelease(L, ret.r1);
   457  		luaL_throwerror(L);
   458  	}
   459  	if (ret.r0 == 0)
   460  	    lua_pushboolean(L, false);
   461  	else
   462  	    lua_pushboolean(L, true);
   463  
   464      return 1;
   465  }
   466  
   467  static const luaL_Reg sys_lib[] = {
   468  	{"print", systemPrint},
   469  	{"setItem", setItem},
   470  	{"getItem", getItem},
   471  	{"getSender", getSender},
   472  	{"getCreator", getCreator},
   473  	{"getTxhash", getTxhash},
   474  	{"getBlockheight", getBlockHeight},
   475  	{"getTimestamp", getTimestamp},
   476  	{"getContractID", getContractID},
   477  	{"getOrigin", getOrigin},
   478  	{"getAmount", getAmount},
   479  	{"getPrevBlockHash", getPrevBlockHash},
   480  	{"date", os_date},
   481  	{"time", os_time},
   482  	{"difftime", os_difftime},
   483  	{"random", lua_random},
   484  	{"isContract", is_contract},
   485  	{NULL, NULL}
   486  };
   487  
   488  int luaopen_system(lua_State *L)
   489  {
   490  	luaL_register(L, "system", sys_lib);
   491  	lua_pop(L, 1);
   492  	return 1;
   493  }