mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated vm
- updated func/fift - additional checks in block validator - docs - tunnel prototype in ADNL
This commit is contained in:
parent
ba76f1404e
commit
54c7a4dcc3
50 changed files with 972 additions and 300 deletions
|
@ -48,6 +48,7 @@ set(TON_CRYPTO_SOURCE
|
|||
common/refint.h
|
||||
common/bigexp.h
|
||||
common/util.h
|
||||
common/linalloc.hpp
|
||||
|
||||
ellcurve/Ed25519.h
|
||||
ellcurve/Fp25519.h
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "block/block.h"
|
||||
#include "block/block-auto.h"
|
||||
#include "block/block-parse.h"
|
||||
#include "block/mc-config.h"
|
||||
#include "ton/ton-shard.h"
|
||||
#include "common/bigexp.h"
|
||||
#include "common/util.h"
|
||||
|
@ -1602,33 +1603,46 @@ bool check_one_config_param(Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key, td::
|
|||
|
||||
const int mandatory_config_params[] = {18, 20, 21, 22, 23, 24, 25, 28, 34};
|
||||
|
||||
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0) {
|
||||
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0,
|
||||
Ref<vm::Cell> old_mparams) {
|
||||
using namespace std::placeholders;
|
||||
if (cell.is_null()) {
|
||||
return false;
|
||||
}
|
||||
if (!catch_errors) {
|
||||
vm::Dictionary dict{std::move(cell), 32};
|
||||
for (int x : mandatory_config_params) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
|
||||
return false;
|
||||
}
|
||||
if (catch_errors) {
|
||||
try {
|
||||
return valid_config_data(std::move(cell), addr, false, relax_par0, std::move(old_mparams));
|
||||
} catch (vm::VmError&) {
|
||||
return false;
|
||||
}
|
||||
return dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0));
|
||||
}
|
||||
try {
|
||||
vm::Dictionary dict{std::move(cell), 32};
|
||||
for (int x : mandatory_config_params) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0));
|
||||
} catch (vm::VmError&) {
|
||||
vm::Dictionary dict{std::move(cell), 32};
|
||||
if (!dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0))) {
|
||||
return false;
|
||||
}
|
||||
for (int x : mandatory_config_params) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return config_params_present(dict, dict.lookup_ref(td::BitArray<32>{9})) &&
|
||||
config_params_present(dict, std::move(old_mparams));
|
||||
}
|
||||
|
||||
bool config_params_present(vm::Dictionary& dict, Ref<vm::Cell> param_dict_root) {
|
||||
auto res = block::Config::unpack_param_dict(std::move(param_dict_root));
|
||||
if (res.is_error()) {
|
||||
return false;
|
||||
}
|
||||
for (int x : res.move_as_ok()) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "configuration parameter #" << x
|
||||
<< " (declared as mandatory in configuration parameter #9) is missing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res) {
|
||||
|
|
|
@ -606,7 +606,8 @@ bool unpack_CurrencyCollection(Ref<vm::CellSlice> csr, td::RefInt256& value, Ref
|
|||
bool valid_library_collection(Ref<vm::Cell> cell, bool catch_errors = true);
|
||||
|
||||
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors = true,
|
||||
bool relax_par0 = false);
|
||||
bool relax_par0 = false, Ref<vm::Cell> old_mparams = {});
|
||||
bool config_params_present(vm::Dictionary& dict, Ref<vm::Cell> param_dict_root);
|
||||
|
||||
bool add_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res);
|
||||
bool sub_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res);
|
||||
|
|
|
@ -572,6 +572,7 @@ _ to_mint:ExtraCurrencyCollection = ConfigParam 7;
|
|||
capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion;
|
||||
_ GlobalVersion = ConfigParam 8; // all zero if absent
|
||||
_ mandatory_params:(Hashmap 32 True) = ConfigParam 9;
|
||||
_ critical_params:(Hashmap 32 True) = ConfigParam 10;
|
||||
|
||||
wfmt_basic#1 vm_version:int32 vm_mode:uint64 = WorkchainFormat 1;
|
||||
wfmt_ext#0 min_addr_len:(## 12) max_addr_len:(## 12) addr_len_step:(## 12)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
namespace block {
|
||||
using namespace std::literals::string_literals;
|
||||
using td::Ref;
|
||||
|
||||
Config::Config(Ref<vm::Cell> config_root, const td::Bits256& config_addr, int _mode)
|
||||
|
@ -335,6 +336,59 @@ std::unique_ptr<vm::Dictionary> ShardConfig::extract_shard_hashes_dict(Ref<vm::C
|
|||
}
|
||||
}
|
||||
|
||||
td::Result<std::vector<int>> Config::unpack_param_dict(vm::Dictionary& dict) {
|
||||
try {
|
||||
std::vector<int> vect;
|
||||
if (dict.check_for_each(
|
||||
[&vect](Ref<vm::CellSlice> value, td::ConstBitPtr key, int key_len) {
|
||||
bool ok = (key_len == 32 && value->empty_ext());
|
||||
if (ok) {
|
||||
vect.push_back((int)key.get_int(32));
|
||||
}
|
||||
return ok;
|
||||
},
|
||||
true)) {
|
||||
return std::move(vect);
|
||||
} else {
|
||||
return td::Status::Error("invalid parameter list dictionary");
|
||||
}
|
||||
} catch (vm::VmError& vme) {
|
||||
return td::Status::Error("error unpacking parameter list dictionary: "s + vme.get_msg());
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<std::vector<int>> Config::unpack_param_dict(Ref<vm::Cell> dict_root) {
|
||||
vm::Dictionary dict{std::move(dict_root), 32};
|
||||
return unpack_param_dict(dict);
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::Dictionary> Config::get_param_dict(int idx) const {
|
||||
return std::make_unique<vm::Dictionary>(get_config_param(idx), 32);
|
||||
}
|
||||
|
||||
td::Result<std::vector<int>> Config::unpack_param_list(int idx) const {
|
||||
return unpack_param_dict(*get_param_dict(idx));
|
||||
}
|
||||
|
||||
bool Config::all_mandatory_params_defined(int* bad_idx_ptr) const {
|
||||
auto res = get_mandatory_param_list();
|
||||
if (res.is_error()) {
|
||||
if (bad_idx_ptr) {
|
||||
*bad_idx_ptr = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (int x : res.move_as_ok()) {
|
||||
if (get_config_param(x).is_null()) {
|
||||
if (bad_idx_ptr) {
|
||||
*bad_idx_ptr = x;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::AugmentedDictionary> ConfigInfo::create_accounts_dict() const {
|
||||
if (mode & needAccountsRoot) {
|
||||
return std::make_unique<vm::AugmentedDictionary>(accounts_root, 256, block::tlb::aug_ShardAccounts);
|
||||
|
|
|
@ -534,6 +534,21 @@ class Config {
|
|||
bool create_stats_enabled() const {
|
||||
return has_capability(ton::capCreateStatsEnabled);
|
||||
}
|
||||
std::unique_ptr<vm::Dictionary> get_param_dict(int idx) const;
|
||||
td::Result<std::vector<int>> unpack_param_list(int idx) const;
|
||||
std::unique_ptr<vm::Dictionary> get_mandatory_param_dict() const {
|
||||
return get_param_dict(9);
|
||||
}
|
||||
std::unique_ptr<vm::Dictionary> get_critical_param_dict() const {
|
||||
return get_param_dict(10);
|
||||
}
|
||||
td::Result<std::vector<int>> get_mandatory_param_list() const {
|
||||
return unpack_param_list(9);
|
||||
}
|
||||
td::Result<std::vector<int>> get_critical_param_list() const {
|
||||
return unpack_param_list(10);
|
||||
}
|
||||
bool all_mandatory_params_defined(int* bad_idx_ptr = nullptr) const;
|
||||
td::Result<ton::StdSmcAddress> get_dns_root_addr() const;
|
||||
bool set_block_id_ext(const ton::BlockIdExt& block_id_ext);
|
||||
td::Result<std::vector<ton::StdSmcAddress>> get_special_smartcontracts(bool without_config = false) const;
|
||||
|
@ -580,6 +595,8 @@ class Config {
|
|||
static td::Result<std::unique_ptr<Config>> extract_from_state(Ref<vm::Cell> mc_state_root, int mode = 0);
|
||||
static td::Result<std::unique_ptr<Config>> extract_from_key_block(Ref<vm::Cell> key_block_root, int mode = 0);
|
||||
static td::Result<std::pair<ton::UnixTime, ton::UnixTime>> unpack_validator_set_start_stop(Ref<vm::Cell> root);
|
||||
static td::Result<std::vector<int>> unpack_param_dict(vm::Dictionary& dict);
|
||||
static td::Result<std::vector<int>> unpack_param_dict(Ref<vm::Cell> dict_root);
|
||||
|
||||
protected:
|
||||
Config(int _mode) : mode(_mode) {
|
||||
|
|
50
crypto/common/linalloc.hpp
Normal file
50
crypto/common/linalloc.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2020 Telegram Systems LLP
|
||||
*/
|
||||
namespace td {
|
||||
|
||||
class LinearAllocator {
|
||||
std::size_t size;
|
||||
char *ptr, *cur, *end;
|
||||
|
||||
public:
|
||||
LinearAllocator(std::size_t _size) : size(_size) {
|
||||
cur = ptr = (char*)malloc(size);
|
||||
if (!ptr) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
end = ptr + size;
|
||||
}
|
||||
~LinearAllocator() {
|
||||
free(ptr);
|
||||
}
|
||||
void* allocate(std::size_t count) {
|
||||
char* t = cur;
|
||||
cur += (count + 7) & -8;
|
||||
if (cur > end) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return (void*)t;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
||||
inline void* operator new(std::size_t count, td::LinearAllocator& alloc) {
|
||||
return alloc.allocate(count);
|
||||
}
|
|
@ -1288,7 +1288,9 @@ void parse_func_def(Lexer& lex) {
|
|||
sym::close_scope(lex);
|
||||
}
|
||||
|
||||
bool parse_source(std::istream* is, const src::FileDescr* fdescr) {
|
||||
std::vector<const src::FileDescr*> source_fdescr;
|
||||
|
||||
bool parse_source(std::istream* is, src::FileDescr* fdescr) {
|
||||
src::SourceReader reader{is, fdescr};
|
||||
Lexer lex{reader, true, ";,()[] ~."};
|
||||
while (lex.tp() != _Eof) {
|
||||
|
@ -1306,6 +1308,7 @@ bool parse_source_file(const char* filename) {
|
|||
throw src::Fatal{"source file name is an empty string"};
|
||||
}
|
||||
src::FileDescr* cur_source = new src::FileDescr{filename};
|
||||
source_fdescr.push_back(cur_source);
|
||||
std::ifstream ifs{filename};
|
||||
if (ifs.fail()) {
|
||||
throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"};
|
||||
|
@ -1314,7 +1317,9 @@ bool parse_source_file(const char* filename) {
|
|||
}
|
||||
|
||||
bool parse_source_stdin() {
|
||||
return parse_source(&std::cin, new src::FileDescr{"stdin", true});
|
||||
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
|
||||
source_fdescr.push_back(cur_source);
|
||||
return parse_source(&std::cin, cur_source);
|
||||
}
|
||||
|
||||
} // namespace funC
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "srcread.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace src {
|
||||
|
||||
|
@ -34,9 +35,47 @@ std::ostream& operator<<(std::ostream& os, const Fatal& fatal) {
|
|||
return os << fatal.get_msg();
|
||||
}
|
||||
|
||||
const char* FileDescr::convert_offset(long offset, long* line_no, long* line_pos, long* line_size) const {
|
||||
long lno = 0, lpos = -1, lsize = 0;
|
||||
const char* lstart = nullptr;
|
||||
if (offset >= 0 && offset < (long)text.size()) {
|
||||
auto it = std::upper_bound(line_offs.begin(), line_offs.end(), offset);
|
||||
lno = it - line_offs.begin();
|
||||
if (lno && it != line_offs.end()) {
|
||||
lsize = it[0] - it[-1];
|
||||
lpos = offset - it[-1];
|
||||
lstart = text.data() + it[-1];
|
||||
}
|
||||
} else {
|
||||
lno = (long)line_offs.size();
|
||||
}
|
||||
if (line_no) {
|
||||
*line_no = lno;
|
||||
}
|
||||
if (line_pos) {
|
||||
*line_pos = lpos;
|
||||
}
|
||||
if (line_size) {
|
||||
*line_size = lsize;
|
||||
}
|
||||
return lstart;
|
||||
}
|
||||
|
||||
const char* FileDescr::push_line(std::string new_line) {
|
||||
if (line_offs.empty()) {
|
||||
line_offs.push_back(0);
|
||||
}
|
||||
std::size_t cur_size = text.size();
|
||||
text += new_line;
|
||||
text += '\0';
|
||||
line_offs.push_back((long)text.size());
|
||||
return text.data() + cur_size;
|
||||
}
|
||||
|
||||
void SrcLocation::show(std::ostream& os) const {
|
||||
os << fdescr;
|
||||
if (line_no > 0) {
|
||||
long line_no, line_pos;
|
||||
if (fdescr && convert_pos(&line_no, &line_pos)) {
|
||||
os << ':' << line_no;
|
||||
if (line_pos >= 0) {
|
||||
os << ':' << (line_pos + 1);
|
||||
|
@ -45,13 +84,15 @@ void SrcLocation::show(std::ostream& os) const {
|
|||
}
|
||||
|
||||
bool SrcLocation::show_context(std::ostream& os) const {
|
||||
if (text.empty() || line_pos < 0 || (unsigned)line_pos > text.size()) {
|
||||
long line_no, line_pos, line_size;
|
||||
if (!fdescr || !convert_pos(&line_no, &line_pos, &line_size)) {
|
||||
return false;
|
||||
}
|
||||
bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < text.size());
|
||||
const char* start = skip_left ? text.c_str() + line_pos - 100 : text.c_str();
|
||||
const char* end = skip_right ? text.c_str() + line_pos + 100 : text.c_str() + text.size();
|
||||
const char* here = text.c_str() + line_pos;
|
||||
bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < line_size);
|
||||
const char* here = fdescr->text.data() + char_offs;
|
||||
const char* base = here - line_pos;
|
||||
const char* start = skip_left ? here - 100 : base;
|
||||
const char* end = skip_right ? here + 100 : base + line_size;
|
||||
os << " ";
|
||||
if (skip_left) {
|
||||
os << "... ";
|
||||
|
@ -99,8 +140,8 @@ void ParseError::show(std::ostream& os) const {
|
|||
where.show_context(os);
|
||||
}
|
||||
|
||||
SourceReader::SourceReader(std::istream* _is, const FileDescr* _fdescr)
|
||||
: ifs(_is), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
|
||||
SourceReader::SourceReader(std::istream* _is, FileDescr* _fdescr)
|
||||
: ifs(_is), fdescr(_fdescr), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
|
||||
load_line();
|
||||
}
|
||||
|
||||
|
@ -139,7 +180,7 @@ const char* SourceReader::set_ptr(const char* ptr) {
|
|||
if (ptr < cur || ptr > end) {
|
||||
error("parsing position went outside of line");
|
||||
}
|
||||
loc.line_pos = (int)(ptr - start);
|
||||
loc.char_offs += ptr - cur;
|
||||
cur = ptr;
|
||||
}
|
||||
return ptr;
|
||||
|
@ -149,12 +190,11 @@ bool SourceReader::load_line() {
|
|||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
loc.set_eof();
|
||||
if (ifs->eof()) {
|
||||
set_eof();
|
||||
return false;
|
||||
}
|
||||
++loc.line_no;
|
||||
loc.line_pos = -1;
|
||||
std::getline(*ifs, cur_line);
|
||||
if (ifs->fail()) {
|
||||
set_eof();
|
||||
|
@ -174,11 +214,16 @@ bool SourceReader::load_line() {
|
|||
cur_line.pop_back();
|
||||
--len;
|
||||
}
|
||||
loc.text = cur_line;
|
||||
cur_line_len = (int)len;
|
||||
loc.line_pos = 0;
|
||||
cur = start = cur_line.c_str();
|
||||
end = start + cur_line_len;
|
||||
if (fdescr) {
|
||||
cur = start = fdescr->push_line(std::move(cur_line));
|
||||
end = start + len;
|
||||
loc.char_offs = (std::size_t)(cur - fdescr->text.data());
|
||||
cur_line.clear();
|
||||
} else {
|
||||
cur = start = cur_line.c_str();
|
||||
end = start + cur_line_len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace src {
|
||||
|
@ -31,9 +32,13 @@ namespace src {
|
|||
|
||||
struct FileDescr {
|
||||
std::string filename;
|
||||
std::string text;
|
||||
std::vector<long> line_offs;
|
||||
bool is_stdin;
|
||||
FileDescr(std::string _fname, bool _stdin = false) : filename(std::move(_fname)), is_stdin(_stdin) {
|
||||
}
|
||||
const char* push_line(std::string new_line);
|
||||
const char* convert_offset(long offset, long* line_no, long* line_pos, long* line_size = nullptr) const;
|
||||
};
|
||||
|
||||
struct Fatal {
|
||||
|
@ -49,16 +54,23 @@ std::ostream& operator<<(std::ostream& os, const Fatal& fatal);
|
|||
|
||||
struct SrcLocation {
|
||||
const FileDescr* fdescr;
|
||||
int line_no;
|
||||
int line_pos;
|
||||
std::string text;
|
||||
SrcLocation() : fdescr(nullptr), line_no(0), line_pos(-1) {
|
||||
long char_offs;
|
||||
SrcLocation() : fdescr(nullptr), char_offs(-1) {
|
||||
}
|
||||
SrcLocation(const FileDescr* _fdescr, int line = 0, int pos = -1) : fdescr(_fdescr), line_no(line), line_pos(pos) {
|
||||
SrcLocation(const FileDescr* _fdescr, long offs = -1) : fdescr(_fdescr), char_offs(-1) {
|
||||
}
|
||||
bool defined() const {
|
||||
return fdescr;
|
||||
}
|
||||
bool eof() const {
|
||||
return char_offs == -1;
|
||||
}
|
||||
void set_eof() {
|
||||
char_offs = -1;
|
||||
}
|
||||
const char* convert_pos(long* line_no, long* line_pos, long* line_size = nullptr) const {
|
||||
return defined() ? fdescr->convert_offset(char_offs, line_no, line_pos, line_size) : nullptr;
|
||||
}
|
||||
void show(std::ostream& os) const;
|
||||
bool show_context(std::ostream& os) const;
|
||||
void show_gen_error(std::ostream& os, std::string message, std::string err_type = "") const;
|
||||
|
@ -98,6 +110,7 @@ struct ParseError : Error {
|
|||
|
||||
class SourceReader {
|
||||
std::istream* ifs;
|
||||
FileDescr* fdescr;
|
||||
SrcLocation loc;
|
||||
bool eof;
|
||||
std::string cur_line;
|
||||
|
@ -106,7 +119,7 @@ class SourceReader {
|
|||
const char *start, *cur, *end;
|
||||
|
||||
public:
|
||||
SourceReader(std::istream* _is, const FileDescr* _fdescr);
|
||||
SourceReader(std::istream* _is, FileDescr* _fdescr);
|
||||
bool load_line();
|
||||
bool is_eof() const {
|
||||
return eof;
|
||||
|
|
|
@ -52,43 +52,50 @@
|
|||
// elected-for elections-begin-before elections-end-before stakes-frozen
|
||||
{ 4 0 reverse <b { swap 32 u, } 4 times b> 15 config! } : config.election_params!
|
||||
|
||||
dictnew 0 2constant validator-dict
|
||||
{ @' validator-dict } : validator-dict@
|
||||
{ validator-dict@ nip } : validator#
|
||||
variable validator-dict
|
||||
dictnew 0 validator-dict 2!
|
||||
{ validator-dict @ second } : validator#
|
||||
// val-pubkey weight --
|
||||
{ dup 0<= abort"validator weight must be non-negative"
|
||||
dup 64 ufits not abort"validator weight must fit into 64 bits"
|
||||
over Blen 32 <> abort"validator public key must be 32 bytes long"
|
||||
<b x{538e81278a} s, rot B, swap 64 u, b> <s
|
||||
validator-dict@ dup 1+ 3 -roll swap
|
||||
validator-dict 2@ dup 1+ 3 -roll swap
|
||||
16 udict!+ 0= abort"cannot add validator"
|
||||
swap 2 'nop does : validator-dict
|
||||
swap validator-dict 2!
|
||||
} : add-validator
|
||||
// since-ut until-ut main-val-cnt-or-0 --
|
||||
{ ?dup 0= { validator# } if
|
||||
validator# 0= abort"no initial validators defined"
|
||||
rot <b x{11} s, swap 32 u, rot 32 u, validator# 16 u, swap 16 u,
|
||||
validator-dict@ drop <s s, b>
|
||||
validator-dict @ first <s s, b>
|
||||
34 config!
|
||||
} : config.validators!
|
||||
|
||||
dictnew constant workchain-dict
|
||||
variable workchain-dict
|
||||
// root-hash file-hash enable-utime actual-min-split min-split max-split workchain-id --
|
||||
{ <b x{a6} s, 5 roll 32 u, 4 roll 8 u, 3 roll 8 u, rot 8 u, x{e000} s,
|
||||
3 roll 256 u, rot 256 u, 0 32 u, x{1} s, -1 32 i, 0 64 u, b>
|
||||
dup isWorkchainDescr? not abort"invalid WorkchainDescr created"
|
||||
<s swap @' workchain-dict 32 idict!+ 0= abort"cannot add workchain"
|
||||
=: workchain-dict
|
||||
<s swap workchain-dict @ 32 idict!+ 0= abort"cannot add workchain"
|
||||
workchain-dict !
|
||||
} : add-std-workchain
|
||||
// --
|
||||
{ @' workchain-dict dict>s s>c 12 config! } : config.workchains!
|
||||
{ workchain-dict @ dict>s s>c 12 config! } : config.workchains!
|
||||
|
||||
dictnew constant special-dict
|
||||
variable special-dict
|
||||
// special-smc-addr --
|
||||
{ x{} swap @' special-dict 256 udict! not abort"cannot add a new special smart contract"
|
||||
=: special-dict
|
||||
{ x{} swap special-dict @ 256 udict! not abort"cannot add a new special smart contract"
|
||||
special-dict !
|
||||
} : make_special
|
||||
{ @' special-dict dict>s s>c 31 config! } : config.special!
|
||||
{ special-dict @ dict>s s>c 31 config! } : config.special!
|
||||
|
||||
// ( l -- D ) Converts a list of parameter indices into a dictionary
|
||||
{ dictnew { swap uncons -rot <b swap rot 32 b>idict! not abort"cannot add parameter index" over null?
|
||||
} until nip
|
||||
} : param-list-to-dict
|
||||
{ param-list-to-dict 9 config! } : config.mandatory_params!
|
||||
{ param-list-to-dict 10 config! } : config.critical_params!
|
||||
|
||||
// bit-pps cell-pps mc-bit-pps mc-cell-pps --
|
||||
{ <b x{cc} s, 0 32 u, 4 roll 64 u, 3 roll 64 u, rot 64 u, swap 64 u,
|
||||
|
|
|
@ -217,6 +217,7 @@ builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inli
|
|||
int msg_seqno = cs~load_uint(32);
|
||||
var valid_until = cs~load_uint(32);
|
||||
throw_if(35, valid_until < now());
|
||||
throw_if(39, slice_depth(cs) > 64);
|
||||
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
|
||||
throw_unless(33, msg_seqno == stored_seqno);
|
||||
ifnot ((action - 0x566f7465) & -2) {
|
||||
|
@ -228,6 +229,7 @@ builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inli
|
|||
stored_seqno += 1;
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
commit();
|
||||
var (_, bits, refs) = cs.slice_compute_data_size(1024);
|
||||
(vote_dict, var accepted) = register_vote(vote_dict, action, cs, idx, weight, total_weight, config_param(34).cell_hash());
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
ifnot (accepted.null?()) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/create-state -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
"Lists.fif" include
|
||||
|
||||
def? $1 { @' $1 } { "" } cond constant suffix
|
||||
{ suffix $+ } : +suffix
|
||||
|
@ -199,6 +201,9 @@ smc1_addr config.minter_smc!
|
|||
|
||||
1000000000000 -17 of-cc 666666666666 239 of-cc cc+ config.to_mint!
|
||||
|
||||
( 9 10 18 20 21 22 23 24 25 28 34 ) config.mandatory_params!
|
||||
( -1000 -1001 9 10 32 34 36 ) config.critical_params!
|
||||
|
||||
"validator-keys" +suffix +".pub" file>B
|
||||
{ dup Blen } { 32 B| swap dup ."Validator public key = " Bx. cr
|
||||
17 add-validator } while drop
|
||||
|
|
|
@ -42,8 +42,10 @@ int string_hash(slice s) asm "SHA256U";
|
|||
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
|
||||
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
|
||||
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) asm "CDATASIZE";
|
||||
(int, int, int) slice_compute_data_size(slice s, int max_cells) asm "SDATASIZE";
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
|
||||
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
|
||||
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
|
||||
(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
|
||||
|
||||
;; () throw_if(int excno, int cond) impure asm "THROWARGIF";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "GenericAccount.h"
|
||||
|
||||
|
@ -96,4 +96,19 @@ td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& ad
|
|||
|
||||
return res;
|
||||
}
|
||||
td::Result<td::Ed25519::PublicKey> GenericAccount::get_public_key(const SmartContract& sc) {
|
||||
auto answer = sc.run_get_method("get_public_key");
|
||||
if (!answer.success) {
|
||||
return td::Status::Error("get_public_key failed");
|
||||
}
|
||||
auto do_get_public_key = [&]() -> td::Result<td::Ed25519::PublicKey> {
|
||||
auto key = answer.stack.write().pop_int_finite();
|
||||
td::SecureString bytes(32);
|
||||
if (!key->export_bytes(bytes.as_mutable_slice().ubegin(), bytes.size(), false)) {
|
||||
return td::Status::Error("get_public_key failed");
|
||||
}
|
||||
return td::Ed25519::PublicKey(std::move(bytes));
|
||||
};
|
||||
return TRY_VM(do_get_public_key());
|
||||
}
|
||||
} // namespace ton
|
||||
|
|
|
@ -14,11 +14,14 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "vm/cells.h"
|
||||
#include "block/block.h"
|
||||
#include "Ed25519.h"
|
||||
#include "SmartContract.h"
|
||||
|
||||
namespace ton {
|
||||
class GenericAccount {
|
||||
public:
|
||||
|
@ -27,5 +30,7 @@ class GenericAccount {
|
|||
static td::Ref<vm::Cell> create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
|
||||
td::Ref<vm::Cell> body) noexcept;
|
||||
static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms);
|
||||
|
||||
static td::Result<td::Ed25519::PublicKey> get_public_key(const SmartContract& sc);
|
||||
};
|
||||
} // namespace ton
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class HighloadWallet : ton::SmartContract, public WalletInterface {
|
||||
class HighloadWallet : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit HighloadWallet(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class HighloadWalletV2 : ton::SmartContract, public WalletInterface {
|
||||
class HighloadWalletV2 : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit HighloadWalletV2(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class Wallet : ton::SmartContract, public WalletInterface {
|
||||
class Wallet : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit Wallet(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class WalletInterface {
|
|||
virtual td::Result<td::Ref<vm::Cell>> make_a_gift_message(const td::Ed25519::PrivateKey &private_key,
|
||||
td::uint32 valid_until, td::Span<Gift> gifts) const = 0;
|
||||
virtual td::Result<td::Ed25519::PublicKey> get_public_key() const {
|
||||
return td::Status::Error("TODO");
|
||||
return td::Status::Error("Unsupported");
|
||||
}
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> get_init_message(const td::Ed25519::PrivateKey &private_key,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class WalletV3 : ton::SmartContract, public WalletInterface {
|
||||
class WalletV3 : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit WalletV3(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -306,6 +306,8 @@ TEST(Tonlib, WalletV3) {
|
|||
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
|
||||
ASSERT_EQ(123u, wallet.get_seqno().ok());
|
||||
CHECK(priv_key.get_public_key().ok().as_octet_string() == wallet.get_public_key().ok().as_octet_string());
|
||||
CHECK(priv_key.get_public_key().ok().as_octet_string() ==
|
||||
ton::GenericAccount::get_public_key(wallet).ok().as_octet_string());
|
||||
|
||||
auto gift_message = ton::GenericAccount::create_ext_message(
|
||||
address, {}, wallet.make_a_gift_message(priv_key, 60, {gift}).move_as_ok());
|
||||
|
@ -337,6 +339,7 @@ TEST(Tonlib, HighloadWallet) {
|
|||
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
|
||||
ASSERT_EQ(0u, wallet.get_seqno().ok());
|
||||
CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string());
|
||||
CHECK(pub_key.as_octet_string() == ton::GenericAccount::get_public_key(wallet).ok().as_octet_string());
|
||||
|
||||
CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32));
|
||||
|
||||
|
@ -417,6 +420,7 @@ TEST(Tonlib, HighloadWalletV2) {
|
|||
{ton::HighloadWalletV2::get_init_code(-1), ton::HighloadWalletV2::get_init_data(pub_key, 239)});
|
||||
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
|
||||
CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string());
|
||||
CHECK(pub_key.as_octet_string() == ton::GenericAccount::get_public_key(wallet).ok().as_octet_string());
|
||||
|
||||
CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32));
|
||||
|
||||
|
|
|
@ -161,6 +161,10 @@ TEST(VM, infinity_loop_2) {
|
|||
test_run_vm_raw("kpTt7ZLrig==");
|
||||
}
|
||||
|
||||
TEST(VM, oom_1) {
|
||||
test_run_vm_raw("bXflX/BvDw==");
|
||||
}
|
||||
|
||||
TEST(VM, bigint) {
|
||||
td::StringBuilder sb({}, true);
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/linalloc.hpp"
|
||||
|
||||
namespace tlbc {
|
||||
|
||||
|
@ -26,6 +27,8 @@ using src::Lexem;
|
|||
using src::Lexer;
|
||||
using sym::sym_idx_t;
|
||||
|
||||
extern td::LinearAllocator AR;
|
||||
|
||||
struct Type;
|
||||
struct Constructor;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -219,6 +219,8 @@ inline bool is_uc_ident(sym_idx_t idx) {
|
|||
|
||||
namespace tlbc {
|
||||
|
||||
td::LinearAllocator AR(1 << 22);
|
||||
|
||||
/*
|
||||
*
|
||||
* AUXILIARY DATA TYPES
|
||||
|
@ -906,7 +908,7 @@ bool TypeExpr::no_tchk() const {
|
|||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_intconst(const src::SrcLocation& loc, unsigned int_const) {
|
||||
return new TypeExpr{loc, te_IntConst, (int)int_const};
|
||||
return new (AR) TypeExpr{loc, te_IntConst, (int)int_const};
|
||||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_intconst(const src::SrcLocation& loc, std::string int_const) {
|
||||
|
@ -951,16 +953,16 @@ TypeExpr* TypeExpr::mk_mulint(const src::SrcLocation& loc, TypeExpr* expr1, Type
|
|||
return expr2;
|
||||
}
|
||||
// delete expr2;
|
||||
return new TypeExpr{loc, te_MulConst, val, {expr1}, expr1->negated};
|
||||
return new (AR) TypeExpr{loc, te_MulConst, val, {expr1}, expr1->negated};
|
||||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_apply(const src::SrcLocation& loc, int tp, TypeExpr* expr1, TypeExpr* expr2) {
|
||||
TypeExpr* expr = new TypeExpr{loc, tp, 0, {expr1, expr2}};
|
||||
TypeExpr* expr = new (AR) TypeExpr{loc, tp, 0, {expr1, expr2}};
|
||||
return expr;
|
||||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_cellref(const src::SrcLocation& loc, TypeExpr* expr1) {
|
||||
TypeExpr* expr = new TypeExpr{loc, te_Ref, 0, {expr1}};
|
||||
TypeExpr* expr = new (AR) TypeExpr{loc, te_Ref, 0, {expr1}};
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1048,7 @@ bool TypeExpr::close(const src::SrcLocation& loc) {
|
|||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_apply_empty(const src::SrcLocation& loc, sym_idx_t name, Type* type_applied) {
|
||||
TypeExpr* expr = new TypeExpr{loc, te_Apply, name};
|
||||
TypeExpr* expr = new (AR) TypeExpr{loc, te_Apply, name};
|
||||
expr->type_applied = type_applied;
|
||||
expr->is_nat_subtype = (type_applied->produces_nat && !type_applied->arity);
|
||||
return expr;
|
||||
|
@ -1984,7 +1986,7 @@ void parse_field_list(Lexer& lex, Constructor& cs);
|
|||
|
||||
TypeExpr* parse_anonymous_constructor(Lexer& lex, Constructor& cs) {
|
||||
sym::open_scope(lex);
|
||||
Constructor* cs2 = new Constructor(lex.cur().loc); // anonymous constructor
|
||||
Constructor* cs2 = new (AR) Constructor(lex.cur().loc); // anonymous constructor
|
||||
parse_field_list(lex, *cs2);
|
||||
if (lex.tp() != ']') {
|
||||
lex.expect(']');
|
||||
|
@ -2089,7 +2091,7 @@ TypeExpr* parse_term(Lexer& lex, Constructor& cs, int mode) {
|
|||
}
|
||||
int i = sym_val->idx;
|
||||
assert(i >= 0 && i < cs.fields_num);
|
||||
auto res = new TypeExpr{lex.cur().loc, TypeExpr::te_Param, i};
|
||||
auto res = new (AR) TypeExpr{lex.cur().loc, TypeExpr::te_Param, i};
|
||||
auto field_type = cs.fields[i].type;
|
||||
assert(field_type);
|
||||
if ((mode & 4) && !cs.fields[i].known) {
|
||||
|
@ -2345,7 +2347,7 @@ void parse_constructor_def(Lexer& lex) {
|
|||
}
|
||||
//std::cerr << "parsing constructor `" << sym::symbols.get_name(constr_name) << "` with tag " << std::hex << tag
|
||||
// << std::dec << std::endl;
|
||||
auto cs_ref = new Constructor(where, constr_name, 0, tag);
|
||||
auto cs_ref = new (AR) Constructor(where, constr_name, 0, tag);
|
||||
Constructor& cs = *cs_ref;
|
||||
cs.is_special = is_special;
|
||||
parse_field_list(lex, cs);
|
||||
|
@ -2417,7 +2419,9 @@ void parse_constructor_def(Lexer& lex) {
|
|||
*
|
||||
*/
|
||||
|
||||
bool parse_source(std::istream* is, const src::FileDescr* fdescr) {
|
||||
std::vector<const src::FileDescr*> source_fdescr;
|
||||
|
||||
bool parse_source(std::istream* is, src::FileDescr* fdescr) {
|
||||
src::SourceReader reader{is, fdescr};
|
||||
src::Lexer lex{reader, true, "(){}:;? #$. ^~ #", "//", "/*", "*/"};
|
||||
while (lex.tp() != src::_Eof) {
|
||||
|
@ -2432,6 +2436,7 @@ bool parse_source_file(const char* filename) {
|
|||
throw src::Fatal{"source file name is an empty string"};
|
||||
}
|
||||
src::FileDescr* cur_source = new src::FileDescr{filename};
|
||||
source_fdescr.push_back(cur_source);
|
||||
std::ifstream ifs{filename};
|
||||
if (ifs.fail()) {
|
||||
throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"};
|
||||
|
@ -2440,7 +2445,9 @@ bool parse_source_file(const char* filename) {
|
|||
}
|
||||
|
||||
bool parse_source_stdin() {
|
||||
return parse_source(&std::cin, new src::FileDescr{"stdin", true});
|
||||
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
|
||||
source_fdescr.push_back(cur_source);
|
||||
return parse_source(&std::cin, cur_source);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2466,7 +2473,7 @@ Type* define_builtin_type(std::string name_str, std::string args, bool produces_
|
|||
}
|
||||
auto sym_def = sym::define_global_symbol(name, true);
|
||||
assert(sym_def);
|
||||
sym_def->value = new SymValType{type};
|
||||
sym_def->value = new (AR) SymValType{type};
|
||||
if (size < 0) {
|
||||
type->size = MinMaxSize::Any;
|
||||
} else if (min_size >= 0 && min_size != size) {
|
||||
|
|
|
@ -610,30 +610,4 @@ Ref<OrdCont> OrdCont::deserialize(CellSlice& cs, int mode) {
|
|||
: Ref<OrdCont>{};
|
||||
}
|
||||
|
||||
void VmState::init_cregs(bool same_c3, bool push_0) {
|
||||
cr.set_c0(quit0);
|
||||
cr.set_c1(quit1);
|
||||
cr.set_c2(Ref<ExcQuitCont>{true});
|
||||
if (same_c3) {
|
||||
cr.set_c3(Ref<OrdCont>{true, code, cp});
|
||||
if (push_0) {
|
||||
VM_LOG(this) << "implicit PUSH 0 at start\n";
|
||||
get_stack().push_smallint(0);
|
||||
}
|
||||
} else {
|
||||
cr.set_c3(Ref<QuitCont>{true, 11});
|
||||
}
|
||||
if (cr.d[0].is_null() || cr.d[1].is_null()) {
|
||||
auto empty_cell = CellBuilder{}.finalize();
|
||||
for (int i = 0; i < ControlRegs::dreg_num; i++) {
|
||||
if (cr.d[i].is_null()) {
|
||||
cr.d[i] = empty_cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cr.c7.is_null()) {
|
||||
cr.set_c7(Ref<Tuple>{true});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -72,6 +72,32 @@ VmState::VmState(Ref<CellSlice> _code, Ref<Stack> _stack, const GasLimits& gas,
|
|||
init_cregs(flags & 1, flags & 2);
|
||||
}
|
||||
|
||||
void VmState::init_cregs(bool same_c3, bool push_0) {
|
||||
cr.set_c0(quit0);
|
||||
cr.set_c1(quit1);
|
||||
cr.set_c2(Ref<ExcQuitCont>{true});
|
||||
if (same_c3) {
|
||||
cr.set_c3(Ref<OrdCont>{true, code, cp});
|
||||
if (push_0) {
|
||||
VM_LOG(this) << "implicit PUSH 0 at start\n";
|
||||
get_stack().push_smallint(0);
|
||||
}
|
||||
} else {
|
||||
cr.set_c3(Ref<QuitCont>{true, 11});
|
||||
}
|
||||
if (cr.d[0].is_null() || cr.d[1].is_null()) {
|
||||
auto empty_cell = CellBuilder{}.finalize();
|
||||
for (int i = 0; i < ControlRegs::dreg_num; i++) {
|
||||
if (cr.d[i].is_null()) {
|
||||
cr.d[i] = empty_cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cr.c7.is_null()) {
|
||||
cr.set_c7(Ref<Tuple>{true});
|
||||
}
|
||||
}
|
||||
|
||||
Ref<CellSlice> VmState::convert_code_cell(Ref<Cell> code_cell) {
|
||||
if (code_cell.is_null()) {
|
||||
return {};
|
||||
|
@ -388,7 +414,7 @@ void VmState::change_gas_limit(long long new_limit) {
|
|||
}
|
||||
|
||||
int VmState::step() {
|
||||
assert(!code.is_null());
|
||||
CHECK(code.not_null() && stack.not_null());
|
||||
//VM_LOG(st) << "stack:"; stack->dump(VM_LOG(st));
|
||||
//VM_LOG(st) << "; cr0.refcnt = " << get_c0()->get_refcnt() - 1 << std::endl;
|
||||
if (stack_trace) {
|
||||
|
@ -410,8 +436,9 @@ int VmState::step() {
|
|||
}
|
||||
|
||||
int VmState::run() {
|
||||
if (code.is_null()) {
|
||||
throw VmError{Excno::fatal, "cannot run an uninitialized VM"};
|
||||
if (code.is_null() || stack.is_null()) {
|
||||
// throw VmError{Excno::fatal, "cannot run an uninitialized VM"};
|
||||
return (int)Excno::fatal; // no ~ for unhandled exceptions
|
||||
}
|
||||
int res;
|
||||
Guard guard(this);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue