Ton

Форк
0
/
emulator-emscripten.cpp 
257 строк · 8.6 Кб
1
#include "emulator-extern.h"
2
#include "td/utils/logging.h"
3
#include "td/utils/JsonBuilder.h"
4
#include "td/utils/misc.h"
5
#include "td/utils/optional.h"
6
#include "StringLog.h"
7
#include <iostream>
8
#include "crypto/common/bitstring.h"
9

10
struct TransactionEmulationParams {
11
  uint32_t utime;
12
  uint64_t lt;
13
  td::optional<std::string> rand_seed_hex;
14
  bool ignore_chksig;
15
  bool is_tick_tock;
16
  bool is_tock;
17
  bool debug_enabled;
18
};
19

20
td::Result<TransactionEmulationParams> decode_transaction_emulation_params(const char* json) {
21
  TransactionEmulationParams params;
22

23
  std::string json_str(json);
24
  TRY_RESULT(input_json, td::json_decode(td::MutableSlice(json_str)));
25
  auto &obj = input_json.get_object();
26

27
  TRY_RESULT(utime_field, td::get_json_object_field(obj, "utime", td::JsonValue::Type::Number, false));
28
  TRY_RESULT(utime, td::to_integer_safe<td::uint32>(utime_field.get_number()));
29
  params.utime = utime;
30

31
  TRY_RESULT(lt_field, td::get_json_object_field(obj, "lt", td::JsonValue::Type::String, false));
32
  TRY_RESULT(lt, td::to_integer_safe<td::uint64>(lt_field.get_string()));
33
  params.lt = lt;
34

35
  TRY_RESULT(rand_seed_str, td::get_json_object_string_field(obj, "rand_seed", true));
36
  if (rand_seed_str.size() > 0) {
37
    params.rand_seed_hex = rand_seed_str;
38
  }
39

40
  TRY_RESULT(ignore_chksig, td::get_json_object_bool_field(obj, "ignore_chksig", false));
41
  params.ignore_chksig = ignore_chksig;
42

43
  TRY_RESULT(debug_enabled, td::get_json_object_bool_field(obj, "debug_enabled", false));
44
  params.debug_enabled = debug_enabled;
45

46
  TRY_RESULT(is_tick_tock, td::get_json_object_bool_field(obj, "is_tick_tock", true, false));
47
  params.is_tick_tock = is_tick_tock;
48

49
  TRY_RESULT(is_tock, td::get_json_object_bool_field(obj, "is_tock", true, false));
50
  params.is_tock = is_tock;
51

52
  if (is_tock && !is_tick_tock) {
53
    return td::Status::Error("Inconsistent parameters is_tick_tock=false, is_tock=true");
54
  }
55

56
  return params;
57
}
58

59
struct GetMethodParams {
60
  std::string code;
61
  std::string data;
62
  int verbosity;
63
  td::optional<std::string> libs;
64
  td::optional<std::string> prev_blocks_info;
65
  std::string address;
66
  uint32_t unixtime;
67
  uint64_t balance;
68
  std::string rand_seed_hex;
69
  int64_t gas_limit;
70
  int method_id;
71
  bool debug_enabled;
72
};
73

74
td::Result<GetMethodParams> decode_get_method_params(const char* json) {
75
  GetMethodParams params;
76

77
  std::string json_str(json);
78
  TRY_RESULT(input_json, td::json_decode(td::MutableSlice(json_str)));
79
  auto &obj = input_json.get_object();
80

81
  TRY_RESULT(code, td::get_json_object_string_field(obj, "code", false));
82
  params.code = code;
83

84
  TRY_RESULT(data, td::get_json_object_string_field(obj, "data", false));
85
  params.data = data;
86

87
  TRY_RESULT(verbosity, td::get_json_object_int_field(obj, "verbosity", false));
88
  params.verbosity = verbosity;
89

90
  TRY_RESULT(libs, td::get_json_object_string_field(obj, "libs", true));
91
  if (libs.size() > 0) {
92
    params.libs = libs;
93
  }
94

95
  TRY_RESULT(prev_blocks_info, td::get_json_object_string_field(obj, "prev_blocks_info", true));
96
  if (prev_blocks_info.size() > 0) {
97
    params.prev_blocks_info = prev_blocks_info;
98
  }
99

100
  TRY_RESULT(address, td::get_json_object_string_field(obj, "address", false));
101
  params.address = address;
102

103
  TRY_RESULT(unixtime_field, td::get_json_object_field(obj, "unixtime", td::JsonValue::Type::Number, false));
104
  TRY_RESULT(unixtime, td::to_integer_safe<td::uint32>(unixtime_field.get_number()));
105
  params.unixtime = unixtime;
106

107
  TRY_RESULT(balance_field, td::get_json_object_field(obj, "balance", td::JsonValue::Type::String, false));
108
  TRY_RESULT(balance, td::to_integer_safe<td::uint64>(balance_field.get_string()));
109
  params.balance = balance;
110

111
  TRY_RESULT(rand_seed_str, td::get_json_object_string_field(obj, "rand_seed", false));
112
  params.rand_seed_hex = rand_seed_str;
113

114
  TRY_RESULT(gas_limit_field, td::get_json_object_field(obj, "gas_limit", td::JsonValue::Type::String, false));
115
  TRY_RESULT(gas_limit, td::to_integer_safe<td::uint64>(gas_limit_field.get_string()));
116
  params.gas_limit = gas_limit;
117

118
  TRY_RESULT(method_id, td::get_json_object_int_field(obj, "method_id", false));
119
  params.method_id = method_id;
120

121
  TRY_RESULT(debug_enabled, td::get_json_object_bool_field(obj, "debug_enabled", false));
122
  params.debug_enabled = debug_enabled;
123

124
  return params;
125
}
126

127
class NoopLog : public td::LogInterface {
128
 public:
129
  NoopLog() {
130
  }
131

132
  void append(td::CSlice new_slice, int log_level) override {
133
  }
134

135
  void rotate() override {
136
  }
137
};
138

139
extern "C" {
140

141
void* create_emulator(const char *config, int verbosity) {
142
    NoopLog logger;
143

144
    td::log_interface = &logger;
145

146
    SET_VERBOSITY_LEVEL(verbosity_NEVER);
147
    return transaction_emulator_create(config, verbosity);
148
}
149

150
void destroy_emulator(void* em) {
151
    NoopLog logger;
152

153
    td::log_interface = &logger;
154

155
    SET_VERBOSITY_LEVEL(verbosity_NEVER);
156
    transaction_emulator_destroy(em);
157
}
158

159
const char *emulate_with_emulator(void* em, const char* libs, const char* account, const char* message, const char* params) {
160
    StringLog logger;
161

162
    td::log_interface = &logger;
163
    SET_VERBOSITY_LEVEL(verbosity_DEBUG);
164

165
    auto decoded_params_res = decode_transaction_emulation_params(params);
166
    if (decoded_params_res.is_error()) {
167
        return strdup(R"({"fail":true,"message":"Can't decode other params"})");
168
    }
169
    auto decoded_params = decoded_params_res.move_as_ok();
170

171
    bool rand_seed_set = true;
172
    if (decoded_params.rand_seed_hex) {
173
      rand_seed_set = transaction_emulator_set_rand_seed(em, decoded_params.rand_seed_hex.unwrap().c_str());
174
    }
175

176
    if (!transaction_emulator_set_libs(em, libs) ||
177
        !transaction_emulator_set_lt(em, decoded_params.lt) ||
178
        !transaction_emulator_set_unixtime(em, decoded_params.utime) ||
179
        !transaction_emulator_set_ignore_chksig(em, decoded_params.ignore_chksig) ||
180
        !transaction_emulator_set_debug_enabled(em, decoded_params.debug_enabled) ||
181
        !rand_seed_set) {
182
        transaction_emulator_destroy(em);
183
        return strdup(R"({"fail":true,"message":"Can't set params"})");
184
    }
185

186
    const char *result;
187
    if (decoded_params.is_tick_tock) {
188
      result = transaction_emulator_emulate_tick_tock_transaction(em, account, decoded_params.is_tock);
189
    } else {
190
      result = transaction_emulator_emulate_transaction(em, account, message);
191
    }
192

193
    const char* output = nullptr;
194
    {
195
        td::JsonBuilder jb;
196
        auto json_obj = jb.enter_object();
197
        json_obj("output", td::JsonRaw(td::Slice(result)));
198
        json_obj("logs", logger.get_string());
199
        json_obj.leave();
200
        output = strdup(jb.string_builder().as_cslice().c_str());
201
    }
202
    free((void*) result);
203

204
    return output;
205
}
206

207
const char *emulate(const char *config, const char* libs, int verbosity, const char* account, const char* message, const char* params) {
208
    auto em = transaction_emulator_create(config, verbosity);
209
    auto result = emulate_with_emulator(em, libs, account, message, params);
210
    transaction_emulator_destroy(em);
211
    return result;
212
}
213

214
const char *run_get_method(const char *params, const char* stack, const char* config) {
215
    StringLog logger;
216

217
    td::log_interface = &logger;
218
    SET_VERBOSITY_LEVEL(verbosity_DEBUG);
219

220
    auto decoded_params_res = decode_get_method_params(params);
221
    if (decoded_params_res.is_error()) {
222
        return strdup(R"({"fail":true,"message":"Can't decode params"})");
223
    }
224
    auto decoded_params = decoded_params_res.move_as_ok();
225

226
    auto tvm = tvm_emulator_create(decoded_params.code.c_str(), decoded_params.data.c_str(), decoded_params.verbosity);
227

228
    if ((decoded_params.libs && !tvm_emulator_set_libraries(tvm, decoded_params.libs.value().c_str())) ||
229
        !tvm_emulator_set_c7(tvm, decoded_params.address.c_str(), decoded_params.unixtime, decoded_params.balance,
230
                             decoded_params.rand_seed_hex.c_str(), config) ||
231
        (decoded_params.prev_blocks_info &&
232
         !tvm_emulator_set_prev_blocks_info(tvm, decoded_params.prev_blocks_info.value().c_str())) ||
233
        (decoded_params.gas_limit > 0 && !tvm_emulator_set_gas_limit(tvm, decoded_params.gas_limit)) ||
234
        !tvm_emulator_set_debug_enabled(tvm, decoded_params.debug_enabled)) {
235
        tvm_emulator_destroy(tvm);
236
        return strdup(R"({"fail":true,"message":"Can't set params"})");
237
    }
238

239
    auto res = tvm_emulator_run_get_method(tvm, decoded_params.method_id, stack);
240

241
    tvm_emulator_destroy(tvm);
242

243
    const char* output = nullptr;
244
    {
245
        td::JsonBuilder jb;
246
        auto json_obj = jb.enter_object();
247
        json_obj("output", td::JsonRaw(td::Slice(res)));
248
        json_obj("logs", logger.get_string());
249
        json_obj.leave();
250
        output = strdup(jb.string_builder().as_cslice().c_str());
251
    }
252
    free((void*) res);
253

254
    return output;
255
}
256

257
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.