diff --git a/catchain/catchain-receiver-interface.h b/catchain/catchain-receiver-interface.h
index 0a819f5b..f30b9d64 100644
--- a/catchain/catchain-receiver-interface.h
+++ b/catchain/catchain-receiver-interface.h
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/catchain/catchain-receiver-source.h b/catchain/catchain-receiver-source.h
index 85086573..11faf3db 100644
--- a/catchain/catchain-receiver-source.h
+++ b/catchain/catchain-receiver-source.h
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/catchain/catchain-receiver-source.hpp b/catchain/catchain-receiver-source.hpp
index eda5a344..74082b45 100644
--- a/catchain/catchain-receiver-source.hpp
+++ b/catchain/catchain-receiver-source.hpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/catchain/catchain-receiver.cpp b/catchain/catchain-receiver.cpp
index 95278005..3f49c136 100644
--- a/catchain/catchain-receiver.cpp
+++ b/catchain/catchain-receiver.cpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include
#include "td/actor/PromiseFuture.h"
diff --git a/catchain/catchain-receiver.hpp b/catchain/catchain-receiver.hpp
index 0015230e..c1789f3e 100644
--- a/catchain/catchain-receiver.hpp
+++ b/catchain/catchain-receiver.hpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/catchain/catchain.cpp b/catchain/catchain.cpp
index 0c801deb..4ddbf3c4 100644
--- a/catchain/catchain.cpp
+++ b/catchain/catchain.cpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "catchain-types.h"
#include "catchain.hpp"
diff --git a/catchain/catchain.h b/catchain/catchain.h
index 43fc795c..65182c1e 100644
--- a/catchain/catchain.h
+++ b/catchain/catchain.h
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/catchain/catchain.hpp b/catchain/catchain.hpp
index 7da1a389..5e015873 100644
--- a/catchain/catchain.hpp
+++ b/catchain/catchain.hpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/crypto/block/create-state.cpp b/crypto/block/create-state.cpp
index 2dc3f597..efee71f8 100644
--- a/crypto/block/create-state.cpp
+++ b/crypto/block/create-state.cpp
@@ -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 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) {
Ref cell = stack.pop_cell();
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("config@ ", interpret_get_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("register_smc ", interpret_register_smartcontract);
d.def_stack_word("set_config_smc ", interpret_set_config_smartcontract);
diff --git a/crypto/common/bitstring.h b/crypto/common/bitstring.h
index 901ff709..dc3a2fa5 100644
--- a/crypto/common/bitstring.h
+++ b/crypto/common/bitstring.h
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "common/refcnt.hpp"
@@ -284,7 +284,7 @@ class BitSliceGen {
ensure_throw(set_size_bool(bits));
return *this;
}
- BitSliceGen subslice(unsigned from, unsigned bits) const& {
+ BitSliceGen subslice(unsigned from, unsigned bits) const & {
return BitSliceGen(*this, from, bits);
}
BitSliceGen subslice(unsigned from, unsigned bits) && {
@@ -575,6 +575,14 @@ class BitArray {
std::string to_binary() const {
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(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(res, n) : (res == n ? res : -1);
+ }
int compare(const BitArray& other) const {
return (n % 8 == 0) ? std::memcmp(data(), other.data(), n / 8) : bitstring::bits_memcmp(bits(), other.bits(), n);
}
diff --git a/crypto/fift/lib/TonUtil.fif b/crypto/fift/lib/TonUtil.fif
index 4ee5fc15..bcdb4a7e 100644
--- a/crypto/fift/lib/TonUtil.fif
+++ b/crypto/fift/lib/TonUtil.fif
@@ -247,3 +247,16 @@ recursive append-long-bytes {
// ( x a b -- a<=x<=b )
{ 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 B B>boc
dup 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
diff --git a/crypto/tl/tlblib.hpp b/crypto/tl/tlblib.hpp
index 7543d38f..b3260a74 100644
--- a/crypto/tl/tlblib.hpp
+++ b/crypto/tl/tlblib.hpp
@@ -594,6 +594,7 @@ class TypenameLookup {
bool register_type(const char* name, const TLB* tp);
bool register_types(register_func_t func);
const TLB* lookup(std::string str) const;
+ const TLB* lookup(td::Slice str) const;
};
} // namespace tlb
diff --git a/crypto/vm/stack.cpp b/crypto/vm/stack.cpp
index 43099927..90fea7f6 100644
--- a/crypto/vm/stack.cpp
+++ b/crypto/vm/stack.cpp
@@ -289,6 +289,31 @@ Ref StackEntry::as_atom() && {
return move_as();
}
+bool StackEntry::for_each_scalar(const std::function& func) const {
+ auto t = as();
+ 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& func) const {
+ auto t = as();
+ 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) {
if (idx >= tup->size()) {
throw VmError{Excno::range_chk, "tuple index out of range"};
@@ -672,6 +697,21 @@ void Stack::push_maybe_cellslice(Ref cs) {
push_maybe(std::move(cs));
}
+bool Stack::for_each_scalar(const std::function& 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& func) const {
+ for (const auto& v : stack) {
+ v.for_each_scalar(func);
+ }
+}
+
/*
*
* SERIALIZE/DESERIALIZE STACK VALUES
diff --git a/crypto/vm/stack.hpp b/crypto/vm/stack.hpp
index 3fadce6b..d67a9dbb 100644
--- a/crypto/vm/stack.hpp
+++ b/crypto/vm/stack.hpp
@@ -285,6 +285,8 @@ class StackEntry {
Ref as_object() && {
return dynamic_move_as();
}
+ bool for_each_scalar(const std::function& func) const;
+ void for_each_scalar(const std::function& func) const;
void dump(std::ostream& os) const;
void print_list(std::ostream& os) const;
std::string to_string() const;
@@ -549,6 +551,8 @@ class Stack : public td::CntObject {
push(std::move(val));
}
}
+ bool for_each_scalar(const std::function& func) const;
+ void for_each_scalar(const std::function& func) const;
// mode: +1 = add eoln, +2 = Lisp-style lists
void dump(std::ostream& os, int mode = 1) const;
bool serialize(vm::CellBuilder& cb, int mode = 0) const;
diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp
index 3dedabe2..ad0cae9d 100644
--- a/lite-client/lite-client.cpp
+++ b/lite-client/lite-client.cpp
@@ -232,6 +232,68 @@ bool TestNode::complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& compl
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() {
auto b = ton::serialize_tl_object(ton::create_tl_object(), true);
return envelope_send_query(std::move(b), [&, Self = actor_id(this) ](td::Result res)->void {
@@ -863,6 +925,10 @@ bool TestNode::show_help(std::string command) {
"updated after by validator public "
"key\n"
"known\tShows the list of all known block ids\n"
+ "knowncells\tShows the list of hashes of all known (cached) cells\n"
+ "dumpcell \nDumps a cached cell by a prefix of its hash\n"
+ "dumpcellas \nFinds a cached cell by a prefix of its hash and prints it as a value "
+ "of \n"
"privkey \tLoads a private key from file\n"
"help []\tThis help\n"
"quit\tExit\n";
@@ -966,6 +1032,13 @@ bool TestNode::do_parse_line() {
get_creator_stats(blkid, mode, count, hash, utime);
} else if (word == "known") {
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()) {
LOG(INFO) << "Exiting";
stop();
@@ -1061,6 +1134,16 @@ td::int64 TestNode::compute_method_id(std::string method) {
return method_id;
}
+bool TestNode::cache_cell(Ref 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,
std::string method_name, bool ext_mode) {
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());
}
parse_ptr_ = parse_end_;
- auto P = td::PromiseCreator::lambda([](td::Result> R) {
+ auto P = td::PromiseCreator::lambda([this](td::Result> R) {
if (R.is_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));
@@ -1294,7 +1385,8 @@ bool TestNode::show_dns_record(std::ostream& os, int cat, Ref value, b
case block::gen::DNSRecord::dns_smc_address: {
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)) {
- 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;
}
diff --git a/lite-client/lite-client.h b/lite-client/lite-client.h
index 7ebaaf17..50afe273 100644
--- a/lite-client/lite-client.h
+++ b/lite-client/lite-client.h
@@ -85,6 +85,8 @@ class TestNode : public td::actor::Actor {
bool ex_mode_ = false;
std::vector ex_queries_;
+ std::map> cell_cache_;
+
std::unique_ptr make_callback();
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,
td::Bits256 start_after, ton::UnixTime min_utime, td::BufferSlice state_proof,
td::BufferSlice data_proof, int count, int req_count, bool complete);
+ bool cache_cell(Ref cell);
+ bool list_cached_cells() const;
+ bool dump_cached_cell(td::Slice hash_pfx, td::Slice type_name = {});
// parser
bool do_parse_line();
bool show_help(std::string command);
@@ -217,6 +222,7 @@ class TestNode : public td::actor::Actor {
bool show_new_blkids(bool all = false);
bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const;
td::Promise trivial_promise();
+ static const tlb::TypenameLookup& get_tlb_dict();
public:
void conn_ready() {
diff --git a/validator-engine-console/validator-engine-console.cpp b/validator-engine-console/validator-engine-console.cpp
index 4cd0427f..8f85637e 100644
--- a/validator-engine-console/validator-engine-console.cpp
+++ b/validator-engine-console/validator-engine-console.cpp
@@ -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 "validator-engine-console.h"
#include "adnl/adnl-ext-client.h"
diff --git a/validator-session/validator-session.cpp b/validator-session/validator-session.cpp
index 9b8f9832..a65eb4b8 100644
--- a/validator-session/validator-session.cpp
+++ b/validator-session/validator-session.cpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "validator-session.hpp"
#include "td/utils/Random.h"
diff --git a/validator-session/validator-session.h b/validator-session/validator-session.h
index 4eecbbb1..8a4d6f52 100644
--- a/validator-session/validator-session.h
+++ b/validator-session/validator-session.h
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/validator-session/validator-session.hpp b/validator-session/validator-session.hpp
index 911a08aa..7693df76 100644
--- a/validator-session/validator-session.hpp
+++ b/validator-session/validator-session.hpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp
index 1fc201fd..0989a110 100644
--- a/validator/validator-group.cpp
+++ b/validator/validator-group.cpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "validator-group.hpp"
#include "fabric.h"
diff --git a/validator/validator-group.hpp b/validator/validator-group.hpp
index e50af9ae..431745e9 100644
--- a/validator/validator-group.hpp
+++ b/validator/validator-group.hpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/validator/validator-options.hpp b/validator/validator-options.hpp
index 9bdc61c0..bbd8ce12 100644
--- a/validator/validator-options.hpp
+++ b/validator/validator-options.hpp
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/validator/validator.h b/validator/validator.h
index 347efb29..459df645 100644
--- a/validator/validator.h
+++ b/validator/validator.h
@@ -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 .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once