diff --git a/blockchain-explorer/blockchain-explorer-http.cpp b/blockchain-explorer/blockchain-explorer-http.cpp index 8642e900..e2322ff7 100644 --- a/blockchain-explorer/blockchain-explorer-http.cpp +++ b/blockchain-explorer/blockchain-explorer-http.cpp @@ -35,9 +35,38 @@ #include "vm/cells/MerkleProof.h" #include "block/mc-config.h" #include "ton/ton-shard.h" +#include "td/utils/date.h" bool local_scripts{false}; +static std::string time_to_human(unsigned ts) { + td::StringBuilder sb; + sb << date::format("%F %T", + std::chrono::time_point{std::chrono::seconds(ts)}) + << ", "; + auto now = (unsigned)td::Clocks::system(); + bool past = now >= ts; + unsigned x = past ? now - ts : ts - now; + if (!past) { + sb << "in "; + } + if (x < 60) { + sb << x << "s"; + } else if (x < 3600) { + sb << x / 60 << "m " << x % 60 << "s"; + } else if (x < 3600 * 24) { + x /= 60; + sb << x / 60 << "h " << x % 60 << "m"; + } else { + x /= 3600; + sb << x / 24 << "d " << x % 24 << "h"; + } + if (past) { + sb << " ago"; + } + return sb.as_cslice().str(); +} + HttpAnswer& HttpAnswer::operator<<(AddressCell addr_c) { ton::WorkchainId wc; ton::StdSmcAddress addr; @@ -84,7 +113,7 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) { << "source" << AddressCell{info.src} << "\n" << "destinationNONE\n" << "lt" << info.created_lt << "\n" - << "time" << info.created_at << "\n"; + << "time" << info.created_at << " (" << time_to_human(info.created_at) << ")\n"; break; } case block::gen::CommonMsgInfo::int_msg_info: { @@ -103,7 +132,7 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) { << "source" << AddressCell{info.src} << "\n" << "destination" << AddressCell{info.dest} << "\n" << "lt" << info.created_lt << "\n" - << "time" << info.created_at << "\n" + << "time" << info.created_at << " (" << time_to_human(info.created_at) << ")\n" << "value" << value << "\n"; break; } @@ -277,7 +306,7 @@ HttpAnswer& HttpAnswer::operator<<(TransactionCell trans_c) { << "account" << trans_c.addr.rserialize(true) << "" << "hash" << trans_c.root->get_hash().to_hex() << "\n" << "lt" << trans.lt << "\n" - << "time" << trans.now << "\n" + << "time" << trans.now << " (" << time_to_human(trans.now) << ")\n" << "out messages"; vm::Dictionary dict{trans.r1.out_msgs, 15}; for (td::int32 i = 0; i < trans.outmsg_cnt; i++) { @@ -456,7 +485,7 @@ HttpAnswer& HttpAnswer::operator<<(BlockHeaderCell head_c) { << "block" << block_id.id.to_str() << "\n" << "roothash" << block_id.root_hash.to_hex() << "\n" << "filehash" << block_id.file_hash.to_hex() << "\n" - << "time" << info.gen_utime << "\n" + << "time" << info.gen_utime << " (" << time_to_human(info.gen_utime) << ")\n" << "lt" << info.start_lt << " .. " << info.end_lt << "\n" << "global_id" << blk.global_id << "\n" << "version" << info.version << "\n" @@ -543,7 +572,8 @@ HttpAnswer& HttpAnswer::operator<<(BlockShardsCell shards_c) { ton::ShardIdFull shard{id.workchain, id.shard}; if (ref.not_null()) { *this << "" << shard.to_str() << "top_block_id()} - << "\">" << ref->top_block_id().id.seqno << "" << ref->created_at() << "" + << "\">" << ref->top_block_id().id.seqno << "created_at()) << "\">" << ref->created_at() << "" << "" << ref->want_split_ << "" << "" << ref->want_merge_ << "" << "" << ref->before_split_ << "" diff --git a/crypto/block/transaction.cpp b/crypto/block/transaction.cpp index 92a5bfe2..0c77317f 100644 --- a/crypto/block/transaction.cpp +++ b/crypto/block/transaction.cpp @@ -962,7 +962,12 @@ int output_actions_count(Ref list) { int i = -1; do { ++i; - list = load_cell_slice(std::move(list)).prefetch_ref(); + bool special = true; + auto cs = load_cell_slice_special(std::move(list), special); + if (special) { + break; + } + list = cs.prefetch_ref(); } while (list.not_null()); return i; } @@ -1079,6 +1084,11 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { } else if (in_msg_state.not_null()) { unpack_msg_state(true); // use only libraries } + if (in_msg_extern && in_msg_state.not_null() && account.addr != in_msg_state->get_hash().bits()) { + LOG(DEBUG) << "in_msg_state hash mismatch in external message"; + cp.skip_reason = ComputePhase::sk_bad_state; + return true; + } // initialize VM Ref stack = prepare_vm_stack(cp); if (stack.is_null()) { @@ -1148,7 +1158,8 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { int out_act_num = output_actions_count(cp.actions); if (verbosity > 2) { std::cerr << "new smart contract data: "; - load_cell_slice(cp.new_data).print_rec(std::cerr); + bool can_be_special = true; + load_cell_slice_special(cp.new_data, can_be_special).print_rec(std::cerr); std::cerr << "output actions: "; block::gen::OutList{out_act_num}.print_ref(std::cerr, cp.actions); } @@ -1219,7 +1230,15 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) { int n = 0; while (true) { ap.action_list.push_back(list); - auto cs = load_cell_slice(std::move(list)); + bool special = true; + auto cs = load_cell_slice_special(std::move(list), special); + if (special) { + ap.result_code = 32; // action list invalid + ap.result_arg = n; + ap.action_list_invalid = true; + LOG(DEBUG) << "action list invalid: special cell"; + return true; + } if (!cs.size_ext()) { break; } diff --git a/overlay/overlay.cpp b/overlay/overlay.cpp index 88518eb7..ced7efea 100644 --- a/overlay/overlay.cpp +++ b/overlay/overlay.cpp @@ -287,7 +287,11 @@ void OverlayImpl::alarm() { if (peers_.size() > 0) { std::vector vec; for (td::uint32 i = 0; i < 20; i++) { - vec.push_back(get_random_peer()->get()); + auto P = get_random_peer(); + if (!P) { + break; + } + vec.push_back(P->get()); } td::actor::send_closure(manager_, &OverlayManager::save_to_db, local_id_, overlay_id_, std::move(vec)); } diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index 49885a5f..7ae4bbff 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -4904,27 +4904,27 @@ bool ValidateQuery::check_one_library_update(td::ConstBitPtr key, Ref old_publishers, new_publishers; if (new_value.not_null()) { - if (!block::gen::t_LibDescr.validate_csr(new_value)) { - return reject_query("LibDescr with key "s + key.to_hex(256) + - " in the libraries dictionary of the new state failed to pass automatic validity tests"); + block::gen::LibDescr::Record rec; + if (!block::gen::csr_unpack(std::move(new_value), rec)) { + return reject_query("failed to unpack LibDescr with key "s + key.to_hex(256) + + " in the libraries dictionary of the new state"); } - auto lib_ref = new_value->prefetch_ref(); - CHECK(lib_ref.not_null()); - if (lib_ref->get_hash().as_bitslice() != key) { + if (rec.lib->get_hash().as_bitslice() != key) { return reject_query("LibDescr with key "s + key.to_hex(256) + " in the libraries dictionary of the new state contains a library with different root hash " + - lib_ref->get_hash().to_hex()); + rec.lib->get_hash().to_hex()); } - CHECK(new_value.write().advance_ext(2, 1)); - new_publishers = std::make_unique(vm::DictNonEmpty(), std::move(new_value), 256); + new_publishers = std::make_unique(vm::DictNonEmpty(), std::move(rec.publishers), 256); } else { new_publishers = std::make_unique(256); } - if (old_value.not_null() && !block::gen::t_LibDescr.validate_csr(old_value)) { - return reject_query("LibDescr with key "s + key.to_hex(256) + - " in the libraries dictionary of the old state failed to pass automatic validity tests"); - CHECK(old_value.write().advance_ext(2, 1)); - old_publishers = std::make_unique(vm::DictNonEmpty(), std::move(old_value), 256); + if (old_value.not_null()) { + block::gen::LibDescr::Record rec; + if (!block::gen::csr_unpack(std::move(old_value), rec)) { + return reject_query("failed to unpack LibDescr with key "s + key.to_hex(256) + + " in the libraries dictionary of the old state"); + } + old_publishers = std::make_unique(vm::DictNonEmpty(), std::move(rec.publishers), 256); } else { old_publishers = std::make_unique(256); }