Ton

Форк
0
/
PrecompiledSmartContract.cpp 
170 строк · 7.1 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

4
    TON Blockchain Library is free software: you can redistribute it and/or modify
5
    it under the terms of the GNU Lesser General Public License as published by
6
    the Free Software Foundation, either version 2 of the License, or
7
    (at your option) any later version.
8

9
    TON Blockchain Library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13

14
    You should have received a copy of the GNU Lesser General Public License
15
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
#include "common.h"
18
#include <memory>
19
#include "vm/memo.h"
20

21
namespace block::precompiled {
22

23
using namespace vm;
24

25
Result PrecompiledSmartContract::run(td::Ref<vm::CellSlice> my_address, ton::UnixTime now, ton::LogicalTime cur_lt,
26
                                     CurrencyCollection balance, td::Ref<vm::Cell> c4, vm::CellSlice msg_body,
27
                                     td::Ref<vm::Cell> msg, CurrencyCollection msg_balance, bool is_external,
28
                                     std::vector<td::Ref<vm::Cell>> libraries, int global_version,
29
                                     td::uint16 max_data_depth, td::Ref<vm::Cell> my_code,
30
                                     td::Ref<vm::Tuple> unpacked_config, td::RefInt256 due_payment,
31
                                     td::uint64 precompiled_gas_usage) {
32
  my_address_ = std::move(my_address);
33
  now_ = now;
34
  cur_lt_ = cur_lt;
35
  balance_ = std::move(balance);
36
  c4_ = (c4.not_null() ? std::move(c4) : CellBuilder().finalize());
37
  in_msg_body_ = std::move(msg_body);
38
  in_msg_ = std::move(msg);
39
  in_msg_balance_ = std::move(msg_balance);
40
  is_external_ = is_external;
41
  my_code_ = std::move(my_code);
42
  unpacked_config_ = std::move(unpacked_config);
43
  due_payment_ = std::move(due_payment);
44
  precompiled_gas_usage_ = precompiled_gas_usage;
45

46
  vm::DummyVmState vm_state{std::move(libraries), global_version};
47
  vm::VmStateInterface::Guard guard{&vm_state};
48

49
  Result result;
50
  try {
51
    result = do_run();
52
  } catch (vm::VmError &e) {
53
    result = Result::error(e.get_errno(), e.get_arg());
54
  } catch (Result &r) {
55
    result = std::move(r);
56
  }
57

58
  if (result.exit_code != 0 && result.exit_code != 1) {
59
    // see VmState::try_commit()
60
    if (c4_.is_null() || c4_->get_depth() > max_data_depth || c4_->get_level() != 0 || c5_.is_null() ||
61
        c5_->get_depth() > max_data_depth || c5_->get_level() != 0) {
62
      result = Result::error(Excno::cell_ov, 0);
63
    }
64
  }
65
  return result;
66
}
67

68
void PrecompiledSmartContract::send_raw_message(const td::Ref<Cell> &msg, int mode) {
69
  CellBuilder cb;
70
  if (!(cb.store_ref_bool(c5_)                 // out_list$_ {n:#} prev:^(OutList n)
71
        && cb.store_long_bool(0x0ec3c86d, 32)  // action_send_msg#0ec3c86d
72
        && cb.store_long_bool(mode, 8)         // mode:(## 8)
73
        && cb.store_ref_bool(msg))) {
74
    throw VmError{Excno::cell_ov, "cannot serialize raw output message into an output action cell"};
75
  }
76
  c5_ = cb.finalize_novm();
77
}
78

79
void PrecompiledSmartContract::raw_reserve(const td::RefInt256 &amount, int mode) {
80
  if (amount->sgn() < 0) {
81
    throw VmError{Excno::range_chk, "amount of nanograms must be non-negative"};
82
  }
83
  CellBuilder cb;
84
  if (!(cb.store_ref_bool(c5_)                             // out_list$_ {n:#} prev:^(OutList n)
85
        && cb.store_long_bool(0x36e6b809, 32)              // action_reserve_currency#36e6b809
86
        && cb.store_long_bool(mode, 8)                     // mode:(## 8)
87
        && util::store_coins(cb, std::move(amount), true)  //
88
        && cb.store_maybe_ref({}))) {
89
    throw VmError{Excno::cell_ov, "cannot serialize raw reserved currency amount into an output action cell"};
90
  }
91
  c5_ = cb.finalize_novm();
92
}
93

94
td::RefInt256 PrecompiledSmartContract::get_compute_fee(ton::WorkchainId wc, td::uint64 gas_used) {
95
  if (gas_used >= (1ULL << 63)) {
96
    throw VmError{Excno::range_chk};
97
  }
98
  block::GasLimitsPrices prices = util::get_gas_prices(unpacked_config_, wc);
99
  return util::check_finite(prices.compute_gas_price(gas_used));
100
}
101

102
td::RefInt256 PrecompiledSmartContract::get_forward_fee(ton::WorkchainId wc, td::uint64 bits, td::uint64 cells) {
103
  if (bits >= (1ULL << 63) || cells >= (1ULL << 63)) {
104
    throw VmError{Excno::range_chk};
105
  }
106
  block::MsgPrices prices = util::get_msg_prices(unpacked_config_, wc);
107
  return util::check_finite(prices.compute_fwd_fees256(cells, bits));
108
}
109

110
td::RefInt256 PrecompiledSmartContract::get_storage_fee(ton::WorkchainId wc, td::uint64 duration, td::uint64 bits,
111
                                                        td::uint64 cells) {
112
  if (bits >= (1ULL << 63) || cells >= (1ULL << 63) || duration >= (1ULL << 63)) {
113
    throw VmError{Excno::range_chk};
114
  }
115
  td::optional<block::StoragePrices> maybe_prices = util::get_storage_prices(unpacked_config_);
116
  return util::check_finite(util::calculate_storage_fee(maybe_prices, wc, duration, bits, cells));
117
}
118

119
td::RefInt256 PrecompiledSmartContract::get_simple_compute_fee(ton::WorkchainId wc, td::uint64 gas_used) {
120
  if (gas_used >= (1ULL << 63)) {
121
    throw VmError{Excno::range_chk};
122
  }
123
  block::GasLimitsPrices prices = util::get_gas_prices(unpacked_config_, wc);
124
  return util::check_finite(td::rshift(td::make_refint(prices.gas_price) * gas_used, 16, 1));
125
}
126

127
td::RefInt256 PrecompiledSmartContract::get_simple_forward_fee(ton::WorkchainId wc, td::uint64 bits, td::uint64 cells) {
128
  if (bits >= (1ULL << 63) || cells >= (1ULL << 63)) {
129
    throw VmError{Excno::range_chk};
130
  }
131
  block::MsgPrices prices = util::get_msg_prices(unpacked_config_, wc);
132
  return util::check_finite(
133
      td::rshift(td::make_refint(prices.bit_price) * bits + td::make_refint(prices.cell_price) * cells, 16, 1));
134
}
135

136
td::RefInt256 PrecompiledSmartContract::get_original_fwd_fee(ton::WorkchainId wc, const td::RefInt256 &x) {
137
  if (x->sgn() < 0) {
138
    throw VmError{Excno::range_chk, "fwd_fee is negative"};
139
  }
140
  block::MsgPrices prices = util::get_msg_prices(unpacked_config_, wc);
141
  return util::check_finite(td::muldiv(x, td::make_refint(1 << 16), td::make_refint((1 << 16) - prices.first_frac)));
142
}
143

144
static std::atomic_bool precompiled_execution_enabled{false};
145

146
std::unique_ptr<PrecompiledSmartContract> get_implementation(td::Bits256 code_hash) {
147
  if (!precompiled_execution_enabled) {
148
    return nullptr;
149
  }
150
  static std::map<td::Bits256, std::unique_ptr<PrecompiledSmartContract> (*)()> map = []() {
151
    auto from_hex = [](td::Slice s) -> td::Bits256 {
152
      td::Bits256 x;
153
      CHECK(x.from_hex(s) == 256);
154
      return x;
155
    };
156
    std::map<td::Bits256, std::unique_ptr<PrecompiledSmartContract> (*)()> map;
157
#define CONTRACT(hash, cls) \
158
  map[from_hex(hash)] = []() -> std::unique_ptr<PrecompiledSmartContract> { return std::make_unique<cls>(); };
159
    // CONTRACT("CODE_HASH_HEX", ClassName);
160
    return map;
161
  }();
162
  auto it = map.find(code_hash);
163
  return it == map.end() ? nullptr : it->second();
164
}
165

166
void set_precompiled_execution_enabled(bool value) {
167
  precompiled_execution_enabled = value;
168
}
169

170
}  // namespace block::precompiled
171

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

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

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

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