1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

updated lite-client

This commit is contained in:
ton 2020-03-31 17:11:56 +04:00
parent 4dd5eea11f
commit 4b5dd4525e
27 changed files with 204 additions and 29 deletions

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 <set> #include <set>
#include "td/actor/PromiseFuture.h" #include "td/actor/PromiseFuture.h"

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 "catchain-types.h" #include "catchain-types.h"
#include "catchain.hpp" #include "catchain.hpp"

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -599,6 +599,18 @@ void interpret_set_config_param(vm::Stack& stack) {
} }
} }
void interpret_check_config_param(vm::Stack& stack) {
int x = stack.pop_smallint_range(0x7fffffff, 0x80000000);
Ref<vm::Cell> value = stack.pop_cell();
if (verbosity > 2 && x >= 0) {
std::cerr << "checking validity as configuration parameter #" << x << " of ";
// vm::load_cell_slice(value).print_rec(std::cerr);
block::gen::ConfigParam{x}.print_ref(std::cerr, value);
std::cerr << std::endl;
}
stack.push_bool(x < 0 || block::gen::ConfigParam{x}.validate_ref(value));
}
void interpret_is_shard_state(vm::Stack& stack) { void interpret_is_shard_state(vm::Stack& stack) {
Ref<vm::Cell> cell = stack.pop_cell(); Ref<vm::Cell> cell = stack.pop_cell();
if (verbosity > 4) { if (verbosity > 4) {
@ -668,6 +680,7 @@ void init_words_custom(fift::Dictionary& d) {
d.def_stack_word("globalid! ", interpret_set_global_id); d.def_stack_word("globalid! ", interpret_set_global_id);
d.def_stack_word("config@ ", interpret_get_config_param); d.def_stack_word("config@ ", interpret_get_config_param);
d.def_stack_word("config! ", interpret_set_config_param); d.def_stack_word("config! ", interpret_set_config_param);
d.def_stack_word("config-valid? ", interpret_check_config_param);
d.def_stack_word("(configdict) ", interpret_get_config_dict); d.def_stack_word("(configdict) ", interpret_get_config_dict);
d.def_stack_word("register_smc ", interpret_register_smartcontract); d.def_stack_word("register_smc ", interpret_register_smartcontract);
d.def_stack_word("set_config_smc ", interpret_set_config_smartcontract); d.def_stack_word("set_config_smc ", interpret_set_config_smartcontract);

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once
#include "common/refcnt.hpp" #include "common/refcnt.hpp"
@ -284,7 +284,7 @@ class BitSliceGen {
ensure_throw(set_size_bool(bits)); ensure_throw(set_size_bool(bits));
return *this; return *this;
} }
BitSliceGen subslice(unsigned from, unsigned bits) const& { BitSliceGen subslice(unsigned from, unsigned bits) const & {
return BitSliceGen(*this, from, bits); return BitSliceGen(*this, from, bits);
} }
BitSliceGen subslice(unsigned from, unsigned bits) && { BitSliceGen subslice(unsigned from, unsigned bits) && {
@ -575,6 +575,14 @@ class BitArray {
std::string to_binary() const { std::string to_binary() const {
return bitstring::bits_to_binary(cbits(), size()); return bitstring::bits_to_binary(cbits(), size());
} }
long from_hex(td::Slice hex_str, bool allow_partial = false) {
auto res = bitstring::parse_bitstring_hex_literal(data(), m, hex_str.begin(), hex_str.end());
return allow_partial ? std::min<long>(res, n) : (res == n ? res : -1);
}
long from_binary(td::Slice bin_str, bool allow_partial = false) {
auto res = bitstring::parse_bitstring_binary_literal(bits(), n, bin_str.begin(), bin_str.end());
return allow_partial ? std::min<long>(res, n) : (res == n ? res : -1);
}
int compare(const BitArray& other) const { int compare(const BitArray& other) const {
return (n % 8 == 0) ? std::memcmp(data(), other.data(), n / 8) : bitstring::bits_memcmp(bits(), other.bits(), n); return (n % 8 == 0) ? std::memcmp(data(), other.data(), n / 8) : bitstring::bits_memcmp(bits(), other.bits(), n);
} }

View file

@ -247,3 +247,16 @@ recursive append-long-bytes {
// ( x a b -- a<=x<=b ) // ( x a b -- a<=x<=b )
{ 2 pick >= -rot >= and } : in-range? { 2 pick >= -rot >= and } : in-range?
// ( c i -- ? ) Checks whether c is a valid value for config param #i
def? config-valid? {
{ nip 0>= { ."warning: cannot check validity of configuration parameter value, use create-state instead of fift to check validity" cr } if
true } : config-valid?
} ifnot
{ dup -1000 = { drop <s ref@ <s 12 u@ 0xFF0 = } {
dup -1001 = { drop <s ref@ <s 12 u@ 0xFF0 = } {
over null? { 2drop true } {
config-valid?
} cond } cond } cond
} : is-valid-config?

View file

@ -41,13 +41,7 @@ boc-filename dup "null" $= {
} cond } cond
=: param-value =: param-value
{ dup -1000 = { drop <s ref@ <s 12 u@ 0xFF0 = } { param-value param-idx is-valid-config? not abort"not a valid value for chosen configuration parameter"
dup -1001 = { drop <s ref@ <s 12 u@ 0xFF0 = } {
2drop true
} cond } cond
} : is-valid-config?
dup param-idx is-valid-config? not abort"not a valid value for chosen configuration parameter"
critical { ."Critical" } { ."Non-critical" } cond critical { ."Critical" } { ."Non-critical" } cond
." configuration proposal will expire at " expire-at . ."(in " expire-in . ."seconds)" cr ." configuration proposal will expire at " expire-at . ."(in " expire-in . ."seconds)" cr

View file

@ -30,8 +30,6 @@ file-base +".pk" load-keypair nip constant config_pk
boc-filename file>B B>boc boc-filename file>B B>boc
dup <s csr. cr dup <s csr. cr
{ 2drop true } : is-valid-config?
dup idx is-valid-config? not abort"not a valid value for chosen configuration parameter" dup idx is-valid-config? not abort"not a valid value for chosen configuration parameter"
// create a message // create a message

View file

@ -375,4 +375,10 @@ const TLB* TypenameLookup::lookup(std::string str) const {
return it != types.end() ? it->second : nullptr; return it != types.end() ? it->second : nullptr;
} }
const TLB* TypenameLookup::lookup(td::Slice str) const {
auto it = std::lower_bound(types.begin(), types.end(), str,
[](const auto& x, const auto& y) { return td::Slice(x.first) < y; });
return it != types.end() && td::Slice(it->first) == str ? it->second : nullptr;
}
} // namespace tlb } // namespace tlb

View file

@ -594,6 +594,7 @@ class TypenameLookup {
bool register_type(const char* name, const TLB* tp); bool register_type(const char* name, const TLB* tp);
bool register_types(register_func_t func); bool register_types(register_func_t func);
const TLB* lookup(std::string str) const; const TLB* lookup(std::string str) const;
const TLB* lookup(td::Slice str) const;
}; };
} // namespace tlb } // namespace tlb

View file

@ -289,6 +289,31 @@ Ref<Atom> StackEntry::as_atom() && {
return move_as<Atom, t_atom>(); return move_as<Atom, t_atom>();
} }
bool StackEntry::for_each_scalar(const std::function<bool(const StackEntry&)>& func) const {
auto t = as<Tuple, t_tuple>();
if (t.not_null()) {
for (const auto& entry : *t) {
if (!entry.for_each_scalar(func)) {
return false;
}
}
return true;
} else {
return func(*this);
}
}
void StackEntry::for_each_scalar(const std::function<void(const StackEntry&)>& func) const {
auto t = as<Tuple, t_tuple>();
if (t.not_null()) {
for (const auto& entry : *t) {
entry.for_each_scalar(func);
}
} else {
func(*this);
}
}
const StackEntry& tuple_index(const Tuple& tup, unsigned idx) { const StackEntry& tuple_index(const Tuple& tup, unsigned idx) {
if (idx >= tup->size()) { if (idx >= tup->size()) {
throw VmError{Excno::range_chk, "tuple index out of range"}; throw VmError{Excno::range_chk, "tuple index out of range"};
@ -672,6 +697,21 @@ void Stack::push_maybe_cellslice(Ref<CellSlice> cs) {
push_maybe(std::move(cs)); push_maybe(std::move(cs));
} }
bool Stack::for_each_scalar(const std::function<bool(const StackEntry&)>& func) const {
for (const auto& v : stack) {
if (!v.for_each_scalar(func)) {
return false;
}
}
return true;
}
void Stack::for_each_scalar(const std::function<void(const StackEntry&)>& func) const {
for (const auto& v : stack) {
v.for_each_scalar(func);
}
}
/* /*
* *
* SERIALIZE/DESERIALIZE STACK VALUES * SERIALIZE/DESERIALIZE STACK VALUES

View file

@ -285,6 +285,8 @@ class StackEntry {
Ref<T> as_object() && { Ref<T> as_object() && {
return dynamic_move_as<T, t_object>(); return dynamic_move_as<T, t_object>();
} }
bool for_each_scalar(const std::function<bool(const StackEntry&)>& func) const;
void for_each_scalar(const std::function<void(const StackEntry&)>& func) const;
void dump(std::ostream& os) const; void dump(std::ostream& os) const;
void print_list(std::ostream& os) const; void print_list(std::ostream& os) const;
std::string to_string() const; std::string to_string() const;
@ -549,6 +551,8 @@ class Stack : public td::CntObject {
push(std::move(val)); push(std::move(val));
} }
} }
bool for_each_scalar(const std::function<bool(const StackEntry&)>& func) const;
void for_each_scalar(const std::function<void(const StackEntry&)>& func) const;
// mode: +1 = add eoln, +2 = Lisp-style lists // mode: +1 = add eoln, +2 = Lisp-style lists
void dump(std::ostream& os, int mode = 1) const; void dump(std::ostream& os, int mode = 1) const;
bool serialize(vm::CellBuilder& cb, int mode = 0) const; bool serialize(vm::CellBuilder& cb, int mode = 0) const;

View file

@ -232,6 +232,68 @@ bool TestNode::complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& compl
return false; return false;
} }
const tlb::TypenameLookup& TestNode::get_tlb_dict() {
static tlb::TypenameLookup tlb_dict = []() {
tlb::TypenameLookup tlb_dict0;
tlb_dict0.register_types(block::gen::register_simple_types);
return tlb_dict0;
}();
return tlb_dict;
}
bool TestNode::list_cached_cells() const {
for (const auto& kv : cell_cache_) {
td::TerminalIO::out() << kv.first.to_hex() << std::endl;
}
return true;
}
bool TestNode::dump_cached_cell(td::Slice hash_pfx, td::Slice type_name) {
if (hash_pfx.size() > 64) {
return false;
}
td::Bits256 hv_min;
int len = (int)hv_min.from_hex(hash_pfx, true);
if (len < 0 || len > 256) {
return set_error("cannot parse hex cell hash prefix");
}
(hv_min.bits() + len).fill(false, 256 - len);
const tlb::TLB* tptr = nullptr;
block::gen::ConfigParam tpconf(0);
if (type_name.size()) {
td::int32 idx;
if (type_name.substr(0, 11) == "ConfigParam" && convert_int32(type_name.substr(11), idx) && idx >= 0) {
tpconf = block::gen::ConfigParam(idx);
tptr = &tpconf;
} else {
tptr = get_tlb_dict().lookup(type_name);
}
if (!tptr) {
return set_error("unknown TL-B type");
}
td::TerminalIO::out() << "dumping cells as values of TLB type " << tptr->get_type_name() << std::endl;
}
auto it = std::lower_bound(cell_cache_.begin(), cell_cache_.end(), hv_min,
[](const auto& x, const auto& y) { return x.first < y; });
int cnt = 0;
for (; it != cell_cache_.end() && it->first.bits().equals(hv_min.bits(), len); ++it) {
std::ostringstream os;
os << "C{" << it->first.to_hex() << "} =" << std::endl;
vm::load_cell_slice(it->second).print_rec(print_limit_, os, 2);
if (tptr) {
tptr->print_ref(print_limit_, os, it->second, 2);
os << std::endl;
}
td::TerminalIO::out() << os.str();
++cnt;
}
if (!cnt) {
LOG(ERROR) << "no known cells with specified hash prefix";
return false;
}
return true;
}
bool TestNode::get_server_time() { bool TestNode::get_server_time() {
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getTime>(), true); auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getTime>(), true);
return envelope_send_query(std::move(b), [&, Self = actor_id(this) ](td::Result<td::BufferSlice> res)->void { return envelope_send_query(std::move(b), [&, Self = actor_id(this) ](td::Result<td::BufferSlice> res)->void {
@ -863,6 +925,10 @@ bool TestNode::show_help(std::string command) {
"updated after <start-utime> by validator public " "updated after <start-utime> by validator public "
"key\n" "key\n"
"known\tShows the list of all known block ids\n" "known\tShows the list of all known block ids\n"
"knowncells\tShows the list of hashes of all known (cached) cells\n"
"dumpcell <hex-hash-pfx>\nDumps a cached cell by a prefix of its hash\n"
"dumpcellas <tlb-type> <hex-hash-pfx>\nFinds a cached cell by a prefix of its hash and prints it as a value "
"of <tlb-type>\n"
"privkey <filename>\tLoads a private key from file\n" "privkey <filename>\tLoads a private key from file\n"
"help [<command>]\tThis help\n" "help [<command>]\tThis help\n"
"quit\tExit\n"; "quit\tExit\n";
@ -966,6 +1032,13 @@ bool TestNode::do_parse_line() {
get_creator_stats(blkid, mode, count, hash, utime); get_creator_stats(blkid, mode, count, hash, utime);
} else if (word == "known") { } else if (word == "known") {
return eoln() && show_new_blkids(true); return eoln() && show_new_blkids(true);
} else if (word == "knowncells") {
return eoln() && list_cached_cells();
} else if (word == "dumpcell" || word == "dumpcellas") {
td::Slice chash;
td::Slice tname;
return (word == "dumpcell" || get_word_to(tname)) && get_word_to(chash) && seekeoln() &&
dump_cached_cell(chash, tname);
} else if (word == "quit" && eoln()) { } else if (word == "quit" && eoln()) {
LOG(INFO) << "Exiting"; LOG(INFO) << "Exiting";
stop(); stop();
@ -1061,6 +1134,16 @@ td::int64 TestNode::compute_method_id(std::string method) {
return method_id; return method_id;
} }
bool TestNode::cache_cell(Ref<vm::Cell> cell) {
if (cell.is_null()) {
return false;
}
td::Bits256 hash = cell->get_hash().bits();
LOG(INFO) << "caching cell " << hash.to_hex();
auto res = cell_cache_.emplace(hash, std::move(cell));
return res.second;
}
bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid,
std::string method_name, bool ext_mode) { std::string method_name, bool ext_mode) {
auto R = vm::parse_stack_entries(td::Slice(parse_ptr_, parse_end_)); auto R = vm::parse_stack_entries(td::Slice(parse_ptr_, parse_end_));
@ -1068,9 +1151,17 @@ bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
return set_error(R.move_as_error().to_string()); return set_error(R.move_as_error().to_string());
} }
parse_ptr_ = parse_end_; parse_ptr_ = parse_end_;
auto P = td::PromiseCreator::lambda([](td::Result<std::vector<vm::StackEntry>> R) { auto P = td::PromiseCreator::lambda([this](td::Result<std::vector<vm::StackEntry>> R) {
if (R.is_error()) { if (R.is_error()) {
LOG(ERROR) << R.move_as_error(); LOG(ERROR) << R.move_as_error();
} else {
for (const auto& v : R.move_as_ok()) {
v.for_each_scalar([this](const vm::StackEntry& val) {
if (val.is_cell()) {
cache_cell(val.as_cell());
}
});
}
} }
}); });
return start_run_method(workchain, addr, ref_blkid, method_name, R.move_as_ok(), ext_mode ? 0x1f : 0, std::move(P)); return start_run_method(workchain, addr, ref_blkid, method_name, R.move_as_ok(), ext_mode ? 0x1f : 0, std::move(P));
@ -1294,7 +1385,8 @@ bool TestNode::show_dns_record(std::ostream& os, int cat, Ref<vm::Cell> value, b
case block::gen::DNSRecord::dns_smc_address: { case block::gen::DNSRecord::dns_smc_address: {
block::gen::DNSRecord::Record_dns_smc_address rec; block::gen::DNSRecord::Record_dns_smc_address rec;
if (tlb::unpack_exact(cs, rec) && block::tlb::t_MsgAddressInt.extract_std_address(rec.smc_addr, wc, addr)) { if (tlb::unpack_exact(cs, rec) && block::tlb::t_MsgAddressInt.extract_std_address(rec.smc_addr, wc, addr)) {
os << "\tsmart contract " << wc << ":" << addr.to_hex() << " = " << block::StdAddress{wc, addr}.rserialize(true); os << "\tsmart contract " << wc << ":" << addr.to_hex() << " = "
<< block::StdAddress{wc, addr}.rserialize(true);
} }
break; break;
} }

View file

@ -85,6 +85,8 @@ class TestNode : public td::actor::Actor {
bool ex_mode_ = false; bool ex_mode_ = false;
std::vector<td::BufferSlice> ex_queries_; std::vector<td::BufferSlice> ex_queries_;
std::map<td::Bits256, Ref<vm::Cell>> cell_cache_;
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> make_callback(); std::unique_ptr<ton::adnl::AdnlExtClient::Callback> make_callback();
struct TransId { struct TransId {
@ -178,6 +180,9 @@ class TestNode : public td::actor::Actor {
void got_creator_stats(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, int req_mode, int mode, void got_creator_stats(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, int req_mode, int mode,
td::Bits256 start_after, ton::UnixTime min_utime, td::BufferSlice state_proof, td::Bits256 start_after, ton::UnixTime min_utime, td::BufferSlice state_proof,
td::BufferSlice data_proof, int count, int req_count, bool complete); td::BufferSlice data_proof, int count, int req_count, bool complete);
bool cache_cell(Ref<vm::Cell> cell);
bool list_cached_cells() const;
bool dump_cached_cell(td::Slice hash_pfx, td::Slice type_name = {});
// parser // parser
bool do_parse_line(); bool do_parse_line();
bool show_help(std::string command); bool show_help(std::string command);
@ -217,6 +222,7 @@ class TestNode : public td::actor::Actor {
bool show_new_blkids(bool all = false); bool show_new_blkids(bool all = false);
bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const; bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const;
td::Promise<td::Unit> trivial_promise(); td::Promise<td::Unit> trivial_promise();
static const tlb::TypenameLookup& get_tlb_dict();
public: public:
void conn_ready() { void conn_ready() {

View file

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here. 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 "validator-engine-console.h" #include "validator-engine-console.h"
#include "adnl/adnl-ext-client.h" #include "adnl/adnl-ext-client.h"

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 "validator-session.hpp" #include "validator-session.hpp"
#include "td/utils/Random.h" #include "td/utils/Random.h"

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 "validator-group.hpp" #include "validator-group.hpp"
#include "fabric.h" #include "fabric.h"

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once

View file

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License 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/>. 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 #pragma once