mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated block header
1. Updated block header, proofs now contain more data Notice, that old proofs may become invalid in the future 2. Fixed message routing 3. Fixed block creator id in block header 4. Support for full proofs in tonlib 5. Support for partial state download 6. Some other bugfixes
This commit is contained in:
parent
bce33f588a
commit
13140ddf29
73 changed files with 2084 additions and 304 deletions
|
@ -21,6 +21,7 @@
|
|||
#include "block/block-auto.h"
|
||||
#include "block/block-parse.h"
|
||||
#include "ton/ton-shard.h"
|
||||
#include "common/bigexp.h"
|
||||
#include "common/util.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/tl_storers.h"
|
||||
|
@ -367,14 +368,14 @@ std::unique_ptr<MsgProcessedUptoCollection> MsgProcessedUptoCollection::unpack(t
|
|||
return v && v->valid ? std::move(v) : std::unique_ptr<MsgProcessedUptoCollection>{};
|
||||
}
|
||||
|
||||
bool MsgProcessedUpto::contains(const MsgProcessedUpto& other) const& {
|
||||
bool MsgProcessedUpto::contains(const MsgProcessedUpto& other) const & {
|
||||
return ton::shard_is_ancestor(shard, other.shard) && mc_seqno >= other.mc_seqno &&
|
||||
(last_inmsg_lt > other.last_inmsg_lt ||
|
||||
(last_inmsg_lt == other.last_inmsg_lt && !(last_inmsg_hash < other.last_inmsg_hash)));
|
||||
}
|
||||
|
||||
bool MsgProcessedUpto::contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash,
|
||||
ton::BlockSeqno other_mc_seqno) const& {
|
||||
ton::BlockSeqno other_mc_seqno) const & {
|
||||
return ton::shard_is_ancestor(shard, other_shard) && mc_seqno >= other_mc_seqno &&
|
||||
(last_inmsg_lt > other_lt || (last_inmsg_lt == other_lt && !(last_inmsg_hash < other_hash)));
|
||||
}
|
||||
|
@ -788,6 +789,14 @@ td::Status ShardState::unpack_state(ton::BlockIdExt blkid, Ref<vm::Cell> prev_st
|
|||
if (!global_balance_.validate_unpack(extra.global_balance)) {
|
||||
return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain a valid global_balance");
|
||||
}
|
||||
if (extra.r1.flags & 1) {
|
||||
if (extra.r1.block_create_stats->prefetch_ulong(8) != 0x17) {
|
||||
return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain a valid BlockCreateStats");
|
||||
}
|
||||
block_create_stats_ = std::make_unique<vm::Dictionary>(extra.r1.block_create_stats->prefetch_ref(), 256);
|
||||
} else {
|
||||
block_create_stats_ = std::make_unique<vm::Dictionary>(256);
|
||||
}
|
||||
}
|
||||
return unpack_out_msg_queue_info(std::move(state.out_msg_queue_info));
|
||||
}
|
||||
|
@ -1387,6 +1396,114 @@ std::ostream& operator<<(std::ostream& os, const ValueFlow& vflow) {
|
|||
return os;
|
||||
}
|
||||
|
||||
bool DiscountedCounter::increase_by(unsigned count, ton::UnixTime now) {
|
||||
if (!validate()) {
|
||||
return false;
|
||||
}
|
||||
td::uint64 scaled = (td::uint64(count) << 32);
|
||||
if (!total) {
|
||||
last_updated = now;
|
||||
total = count;
|
||||
cnt2048 = scaled;
|
||||
cnt65536 = scaled;
|
||||
return true;
|
||||
}
|
||||
if (count > ~total || cnt2048 > ~scaled || cnt65536 > ~scaled) {
|
||||
return false /* invalidate() */; // overflow
|
||||
}
|
||||
unsigned dt = (now >= last_updated ? now - last_updated : 0);
|
||||
if (dt > 0) {
|
||||
// more precise version of cnt2048 = llround(cnt2048 * exp(-dt / 2048.));
|
||||
// (rounding error has absolute value < 1)
|
||||
cnt2048 = (dt >= 48 * 2048 ? 0 : td::umulnexps32(cnt2048, dt << 5));
|
||||
// more precise version of cnt65536 = llround(cnt65536 * exp(-dt / 65536.));
|
||||
// (rounding error has absolute value < 1)
|
||||
cnt65536 = td::umulnexps32(cnt65536, dt);
|
||||
}
|
||||
total += count;
|
||||
cnt2048 += scaled;
|
||||
cnt65536 += scaled;
|
||||
last_updated = now;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiscountedCounter::validate() {
|
||||
if (!is_valid()) {
|
||||
return false;
|
||||
}
|
||||
if (!total) {
|
||||
if (cnt2048 | cnt65536) {
|
||||
return invalidate();
|
||||
}
|
||||
} else if (!last_updated) {
|
||||
return invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiscountedCounter::fetch(vm::CellSlice& cs) {
|
||||
valid = (cs.fetch_uint_to(32, last_updated) && cs.fetch_uint_to(64, total) && cs.fetch_uint_to(64, cnt2048) &&
|
||||
cs.fetch_uint_to(64, cnt65536));
|
||||
return validate() || invalidate();
|
||||
}
|
||||
|
||||
bool DiscountedCounter::unpack(Ref<vm::CellSlice> csr) {
|
||||
return (csr.not_null() && fetch(csr.write()) && csr->empty_ext()) || invalidate();
|
||||
}
|
||||
|
||||
bool DiscountedCounter::store(vm::CellBuilder& cb) const {
|
||||
return is_valid() && cb.store_long_bool(last_updated, 32) && cb.store_long_bool(total, 64) &&
|
||||
cb.store_long_bool(cnt2048, 64) && cb.store_long_bool(cnt65536, 64);
|
||||
}
|
||||
|
||||
Ref<vm::CellSlice> DiscountedCounter::pack() const {
|
||||
vm::CellBuilder cb;
|
||||
if (store(cb)) {
|
||||
return vm::load_cell_slice_ref(cb.finalize());
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool DiscountedCounter::show(std::ostream& os) const {
|
||||
if (!is_valid()) {
|
||||
os << "<invalid-counter>";
|
||||
return false;
|
||||
}
|
||||
os << "(counter last_updated:" << last_updated << " total:" << total << " cnt2048: " << (double)cnt2048 / (1LL << 32)
|
||||
<< " cnt65536: " << (double)cnt65536 / (1LL << 32) << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string DiscountedCounter::to_str() const {
|
||||
std::ostringstream stream;
|
||||
if (show(stream)) {
|
||||
return stream.str();
|
||||
} else {
|
||||
return "<invalid-counter>";
|
||||
}
|
||||
}
|
||||
|
||||
bool fetch_CreatorStats(vm::CellSlice& cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt) {
|
||||
return cs.fetch_ulong(4) == 4 // creator_info#4
|
||||
&& mc_cnt.fetch(cs) // mc_blocks:Counters
|
||||
&& shard_cnt.fetch(cs); // shard_blocks:Counters
|
||||
}
|
||||
|
||||
bool store_CreatorStats(vm::CellBuilder& cb, const DiscountedCounter& mc_cnt, const DiscountedCounter& shard_cnt) {
|
||||
return cb.store_long_bool(4, 4) // creator_info#4
|
||||
&& mc_cnt.store(cb) // mc_blocks:Counters
|
||||
&& shard_cnt.store(cb); // shard_blocks:Counters
|
||||
}
|
||||
|
||||
bool unpack_CreatorStats(Ref<vm::CellSlice> cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt) {
|
||||
if (cs.is_null()) {
|
||||
return mc_cnt.set_zero() && shard_cnt.set_zero();
|
||||
} else {
|
||||
return fetch_CreatorStats(cs.write(), mc_cnt, shard_cnt) && cs->empty_ext();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Other block-related functions
|
||||
|
@ -1565,8 +1682,8 @@ std::pair<int, int> perform_hypercube_routing(ton::AccountIdPrefixFull src, ton:
|
|||
if (!ton::shard_contains(cur, transit)) {
|
||||
return {-1, -1};
|
||||
}
|
||||
if (transit.account_id_prefix == dest.account_id_prefix || ton::shard_contains(cur, dest)) {
|
||||
// if destination is already reached, or is in this shard, set cur:=next_hop:=dest
|
||||
if (ton::shard_contains(cur, dest)) {
|
||||
// if destination is in this shard, set cur:=next_hop:=dest
|
||||
return {96, 96};
|
||||
}
|
||||
if (transit.workchain == ton::masterchainId || dest.workchain == ton::masterchainId) {
|
||||
|
|
|
@ -159,12 +159,12 @@ struct MsgProcessedUpto {
|
|||
MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash)
|
||||
: shard(_shard), mc_seqno(_mcseqno), last_inmsg_lt(_lt), last_inmsg_hash(_hash) {
|
||||
}
|
||||
bool operator<(const MsgProcessedUpto& other) const& {
|
||||
bool operator<(const MsgProcessedUpto& other) const & {
|
||||
return shard < other.shard || (shard == other.shard && mc_seqno < other.mc_seqno);
|
||||
}
|
||||
bool contains(const MsgProcessedUpto& other) const&;
|
||||
bool contains(const MsgProcessedUpto& other) const &;
|
||||
bool contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash,
|
||||
ton::BlockSeqno other_mc_seqno) const&;
|
||||
ton::BlockSeqno other_mc_seqno) const &;
|
||||
// NB: this is for checking whether we have already imported an internal message
|
||||
bool already_processed(const EnqueuedMsgDescr& msg) const;
|
||||
};
|
||||
|
@ -392,6 +392,7 @@ struct ShardState {
|
|||
CurrencyCollection total_balance_, total_validator_fees_, global_balance_;
|
||||
std::unique_ptr<vm::AugmentedDictionary> out_msg_queue_;
|
||||
std::unique_ptr<vm::Dictionary> ihr_pending_;
|
||||
std::unique_ptr<vm::Dictionary> block_create_stats_;
|
||||
std::shared_ptr<block::MsgProcessedUptoCollection> processed_upto_;
|
||||
|
||||
bool is_valid() const {
|
||||
|
@ -467,6 +468,67 @@ struct ValueFlow {
|
|||
|
||||
std::ostream& operator<<(std::ostream& os, const ValueFlow& vflow);
|
||||
|
||||
struct DiscountedCounter {
|
||||
struct SetZero {};
|
||||
bool valid;
|
||||
ton::UnixTime last_updated;
|
||||
td::uint64 total;
|
||||
td::uint64 cnt2048;
|
||||
td::uint64 cnt65536;
|
||||
DiscountedCounter() : valid(false) {
|
||||
}
|
||||
DiscountedCounter(SetZero) : valid(true), last_updated(0), total(0), cnt2048(0), cnt65536(0) {
|
||||
}
|
||||
DiscountedCounter(ton::UnixTime _lastupd, td::uint64 _total, td::uint64 _cnt2048, td::uint64 _cnt65536)
|
||||
: valid(true), last_updated(_lastupd), total(_total), cnt2048(_cnt2048), cnt65536(_cnt65536) {
|
||||
}
|
||||
static DiscountedCounter Zero() {
|
||||
return SetZero();
|
||||
}
|
||||
bool is_valid() const {
|
||||
return valid;
|
||||
}
|
||||
bool invalidate() {
|
||||
return (valid = false);
|
||||
}
|
||||
bool set_zero() {
|
||||
last_updated = 0;
|
||||
total = cnt2048 = cnt65536 = 0;
|
||||
return (valid = true);
|
||||
}
|
||||
bool is_zero() const {
|
||||
return !total;
|
||||
}
|
||||
bool almost_zero() const {
|
||||
return (cnt2048 | cnt65536) <= 1;
|
||||
}
|
||||
bool operator==(const DiscountedCounter& other) const {
|
||||
return last_updated == other.last_updated && total == other.total && cnt2048 == other.cnt2048 &&
|
||||
cnt65536 == other.cnt65536;
|
||||
}
|
||||
bool almost_equals(const DiscountedCounter& other) const {
|
||||
return last_updated == other.last_updated && total == other.total && cnt2048 <= other.cnt2048 + 1 &&
|
||||
other.cnt2048 <= cnt2048 + 1 && cnt65536 <= other.cnt65536 + 1 && other.cnt65536 <= cnt65536 + 1;
|
||||
}
|
||||
bool validate();
|
||||
bool increase_by(unsigned count, ton::UnixTime now);
|
||||
bool fetch(vm::CellSlice& cs);
|
||||
bool unpack(Ref<vm::CellSlice> csr);
|
||||
bool store(vm::CellBuilder& cb) const;
|
||||
Ref<vm::CellSlice> pack() const;
|
||||
bool show(std::ostream& os) const;
|
||||
std::string to_str() const;
|
||||
};
|
||||
|
||||
static inline std::ostream& operator<<(std::ostream& os, const DiscountedCounter& dcount) {
|
||||
dcount.show(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
bool fetch_CreatorStats(vm::CellSlice& cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt);
|
||||
bool store_CreatorStats(vm::CellBuilder& cb, const DiscountedCounter& mc_cnt, const DiscountedCounter& shard_cnt);
|
||||
bool unpack_CreatorStats(Ref<vm::CellSlice> cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt);
|
||||
|
||||
struct BlockProofLink {
|
||||
ton::BlockIdExt from, to;
|
||||
bool is_key{false}, is_fwd{false};
|
||||
|
|
|
@ -499,14 +499,20 @@ _ key:Bool blk_ref:ExtBlkRef = KeyExtBlkRef;
|
|||
|
||||
_ (HashmapAugE 32 KeyExtBlkRef KeyMaxLt) = OldMcBlocksInfo;
|
||||
|
||||
|
||||
counters#_ last_updated:uint32 total:uint64 cnt2048:uint64 cnt65536:uint64 = Counters;
|
||||
creator_info#4 mc_blocks:Counters shard_blocks:Counters = CreatorStats;
|
||||
block_create_stats#17 counters:(HashmapE 256 CreatorStats) = BlockCreateStats;
|
||||
|
||||
masterchain_state_extra#cc26
|
||||
shard_hashes:ShardHashes
|
||||
config:ConfigParams
|
||||
^[ flags:(## 16) { flags = 0 }
|
||||
^[ flags:(## 16) { flags <= 1 }
|
||||
validator_info:ValidatorInfo
|
||||
prev_blocks:OldMcBlocksInfo
|
||||
after_key_block:Bool
|
||||
last_key_block:(Maybe ExtBlkRef) ]
|
||||
last_key_block:(Maybe ExtBlkRef)
|
||||
block_create_stats:(flags . 0)?BlockCreateStats ]
|
||||
global_balance:CurrencyCollection
|
||||
= McStateExtra;
|
||||
|
||||
|
|
|
@ -80,4 +80,15 @@ struct TransactionList {
|
|||
td::Result<Info> validate() const;
|
||||
};
|
||||
|
||||
struct BlockChain {
|
||||
ton::BlockIdExt from;
|
||||
ton::BlockIdExt to;
|
||||
td::int32 mode;
|
||||
td::BufferSlice proof;
|
||||
|
||||
using Info = std::unique_ptr<block::BlockProofChain>;
|
||||
|
||||
td::Result<Info> validate() const;
|
||||
};
|
||||
|
||||
} // namespace block
|
||||
|
|
252
crypto/block/dump-block.cpp
Normal file
252
crypto/block/dump-block.cpp
Normal file
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
This file is part of TON Blockchain source code.
|
||||
|
||||
TON Blockchain is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU 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 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
You must obey the GNU General Public License in all respects for all
|
||||
of the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
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
|
||||
*/
|
||||
#include "block/block.h"
|
||||
#include "vm/boc.h"
|
||||
#include <iostream>
|
||||
#include "block-db.h"
|
||||
#include "block-auto.h"
|
||||
#include "block-parse.h"
|
||||
#include "vm/cp0.h"
|
||||
#include <getopt.h>
|
||||
|
||||
using td::Ref;
|
||||
|
||||
int verbosity;
|
||||
|
||||
struct IntError {
|
||||
std::string err_msg;
|
||||
IntError(std::string _msg) : err_msg(_msg) {
|
||||
}
|
||||
IntError(const char* _msg) : err_msg(_msg) {
|
||||
}
|
||||
};
|
||||
|
||||
td::Ref<vm::Cell> load_boc(std::string filename) {
|
||||
std::cerr << "loading bag-of-cell file " << filename << std::endl;
|
||||
auto bytes_res = block::load_binary_file(filename);
|
||||
if (bytes_res.is_error()) {
|
||||
throw IntError{PSTRING() << "cannot load file `" << filename << "` : " << bytes_res.move_as_error()};
|
||||
}
|
||||
vm::BagOfCells boc;
|
||||
auto res = boc.deserialize(bytes_res.move_as_ok());
|
||||
if (res.is_error()) {
|
||||
throw IntError{PSTRING() << "cannot deserialize bag-of-cells " << res.move_as_error()};
|
||||
}
|
||||
if (res.move_as_ok() <= 0 || boc.get_root_cell().is_null()) {
|
||||
throw IntError{"cannot deserialize bag-of-cells "};
|
||||
}
|
||||
return boc.get_root_cell();
|
||||
}
|
||||
|
||||
void test1() {
|
||||
block::ShardId id{ton::masterchainId}, id2{ton::basechainId, 0x11efULL << 48};
|
||||
std::cout << '[' << id << "][" << id2 << ']' << std::endl;
|
||||
vm::CellBuilder cb;
|
||||
cb << id << id2;
|
||||
std::cout << "ShardIdent.pack() = " << block::tlb::t_ShardIdent.pack(cb, {12, 3, 0x3aeULL << 52}) << std::endl;
|
||||
std::cout << cb << std::endl;
|
||||
auto cref = cb.finalize();
|
||||
td::Ref<vm::CellSlice> cs{true, cref}, cs2;
|
||||
block::ShardId id3{cs.write()}, id4, id5;
|
||||
cs >> id4 >> id5;
|
||||
std::cout << '[' << id3 << "][" << id4 << "][" << id5 << ']' << std::endl;
|
||||
vm::CellSlice csl{std::move(cref)};
|
||||
std::cout << "ShardIdent.get_size() = " << block::tlb::t_ShardIdent.get_size(csl) << std::endl;
|
||||
std::cout << "MsgAddress.get_size() = " << block::tlb::t_MsgAddress.get_size(csl) << std::endl;
|
||||
std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl) << std::endl;
|
||||
std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl) << std::endl;
|
||||
(csl + 8).print_rec(std::cout);
|
||||
std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl + 8) << std::endl;
|
||||
std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl + 8) << std::endl;
|
||||
|
||||
vm::CellSlice csl2{csl};
|
||||
block::gen::ShardIdent::Record sh_id;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
std::cout << csl2 << std::endl;
|
||||
bool ok = tlb::unpack(csl2, sh_id);
|
||||
std::cout << "block::gen::ShardIdent.unpack() = " << ok << std::endl;
|
||||
if (ok) {
|
||||
std::cout << " (shard_ident shard_pfx_bits:" << sh_id.shard_pfx_bits << " workchain_id:" << sh_id.workchain_id
|
||||
<< " shard_prefix:" << std::hex << sh_id.shard_prefix << std::dec << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
block::tlb::ShardIdent::Record shard_id;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate(csl) << std::endl;
|
||||
csl.print_rec(std::cerr);
|
||||
csl.dump(std::cerr, 7);
|
||||
std::cout << "ShardIdent.unpack() = " << block::tlb::t_ShardIdent.unpack(csl, shard_id) << std::endl;
|
||||
if (shard_id.is_valid()) {
|
||||
std::cout << "shard_pfx_bits:" << shard_id.shard_pfx_bits << " workchain_id:" << shard_id.workchain_id
|
||||
<< " shard_prefix:" << shard_id.shard_prefix << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
|
||||
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
|
||||
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
|
||||
using namespace td::literals;
|
||||
std::cout << "Grams.store_intval(239) = " << block::tlb::t_Grams.store_integer_value(cb, "239"_i256) << std::endl;
|
||||
std::cout << "Grams.store_intval(17239) = " << block::tlb::t_Grams.store_integer_value(cb, "17239"_i256) << std::endl;
|
||||
std::cout << "Grams.store_intval(-17) = " << block::tlb::t_Grams.store_integer_value(cb, "-17"_i256) << std::endl;
|
||||
std::cout << "Grams.store_intval(0) = " << block::tlb::t_Grams.store_integer_value(cb, "0"_i256) << std::endl;
|
||||
std::cout << cb << std::endl;
|
||||
cs = td::Ref<vm::CellSlice>{true, cb.finalize()};
|
||||
std::cout << "Grams.store_intval(666) = " << block::tlb::t_Grams.store_integer_value(cb, "666"_i256) << std::endl;
|
||||
std::cout << cb << std::endl;
|
||||
cs2 = td::Ref<vm::CellSlice>{true, cb.finalize()};
|
||||
std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate(*cs) << std::endl;
|
||||
std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate(*cs2) << std::endl;
|
||||
//
|
||||
block::gen::SplitMergeInfo::Record data;
|
||||
block::gen::Grams::Record data2;
|
||||
std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate(*cs) << std::endl;
|
||||
std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate(*cs2) << std::endl;
|
||||
std::cout << "[cs = " << cs << "]" << std::endl;
|
||||
bool ok = tlb::csr_unpack_inexact(cs, data);
|
||||
std::cout << "block::gen::SplitMergeInfo.unpack(cs, data) = " << ok << std::endl;
|
||||
if (ok) {
|
||||
std::cout << " cur_shard_pfx_len = " << data.cur_shard_pfx_len << "; acc_split_depth = " << data.acc_split_depth
|
||||
<< "; this_addr = " << data.this_addr << "; sibling_addr = " << data.sibling_addr << std::endl;
|
||||
}
|
||||
ok = tlb::csr_unpack_inexact(cs, data2);
|
||||
std::cout << "block::gen::Grams.unpack(cs, data2) = " << ok << std::endl;
|
||||
if (ok) {
|
||||
std::cout << " amount = " << data2.amount << std::endl;
|
||||
block::gen::VarUInteger::Record data3;
|
||||
ok = tlb::csr_type_unpack(data2.amount, block::gen::t_VarUInteger_16, data3);
|
||||
std::cout << " block::gen::VarUInteger16.unpack(amount, data3) = " << ok << std::endl;
|
||||
if (ok) {
|
||||
std::cout << " len = " << data3.len << "; value = " << data3.value << std::endl;
|
||||
vm::CellBuilder cb;
|
||||
std::cout << " block::gen::VarUInteger16.pack(cb, data3) = "
|
||||
<< tlb::type_pack(cb, block::gen::t_VarUInteger_16, data3) << std::endl;
|
||||
std::cout << " cb = " << cb.finalize() << std::endl;
|
||||
}
|
||||
}
|
||||
/*
|
||||
{
|
||||
vm::CellBuilder cb;
|
||||
td::BitArray<256> hash;
|
||||
std::memset(hash.data(), 0x69, 32);
|
||||
bool ok = tlb::pack(
|
||||
cb, block::gen::Test::Record{1000000000000, {170239, -888, {239017, "1000000000000000000"_ri256}, hash}, 17});
|
||||
std::cout << " block::gen::Test::pack(cb, {1000000000000, ...}) = " << ok << std::endl;
|
||||
std::cout << " cb = " << cb << std::endl;
|
||||
auto cell = cb.finalize();
|
||||
vm::CellSlice cs{cell};
|
||||
cs.print_rec(std::cout);
|
||||
block::gen::Test::Record data;
|
||||
std::cout << " block::gen::Test::validate_ref(cell) = " << block::gen::t_Test.validate_ref(cell) << std::endl;
|
||||
ok = tlb::unpack(cs, data);
|
||||
std::cout << " block::gen::Test::unpack(cs, data) = " << ok << std::endl;
|
||||
if (ok) {
|
||||
std::cout << "a:" << data.a << " b:" << data.r1.b << " c:" << data.r1.c << " d:" << data.r1.r1.d
|
||||
<< " e:" << data.r1.r1.e << " f:" << data.r1.f << " g:" << data.g << std::endl;
|
||||
}
|
||||
std::cout << " block::gen::Test::print_ref(cell) = ";
|
||||
block::gen::t_Test.print_ref(std::cout, cell, 2);
|
||||
block::gen::t_CurrencyCollection.print_ref(std::cout, cell, 2);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
*/
|
||||
std::cout << "Grams.add_values() = " << block::tlb::t_Grams.add_values(cb, cs.write(), cs2.write()) << std::endl;
|
||||
std::cout << cb << std::endl;
|
||||
std::cout << "block::gen::t_HashmapAug_64_...print_type() = "
|
||||
<< block::gen::t_HashmapAug_64_Ref_Transaction_CurrencyCollection << std::endl;
|
||||
}
|
||||
|
||||
void test2(vm::CellSlice& cs) {
|
||||
std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate(cs) << std::endl;
|
||||
std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate(cs) << std::endl;
|
||||
std::cout << "HashmapE(32,UInt16).validate() = " << block::tlb::HashmapE(32, block::tlb::t_uint16).validate(cs)
|
||||
<< std::endl;
|
||||
std::cout << "block::gen::HashmapE(32,UInt16).validate() = "
|
||||
<< block::gen::HashmapE{32, block::gen::t_uint16}.validate(cs) << std::endl;
|
||||
}
|
||||
|
||||
void usage() {
|
||||
std::cout << "usage: test-block [-S][<boc-file>]\n\tor test-block -h\n\tDumps specified blockchain block or state "
|
||||
"from <boc-file>, or runs some tests\n\t-S\tDump a blockchain state\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
int main(int argc, char* const argv[]) {
|
||||
int i;
|
||||
int new_verbosity_level = VERBOSITY_NAME(INFO);
|
||||
bool dump_state = false;
|
||||
auto zerostate = std::make_unique<block::ZerostateInfo>();
|
||||
while ((i = getopt(argc, argv, "Shv:")) != -1) {
|
||||
switch (i) {
|
||||
case 'S':
|
||||
dump_state = true;
|
||||
break;
|
||||
case 'v':
|
||||
new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer<int>(td::Slice(optarg)));
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
std::exit(2);
|
||||
default:
|
||||
usage();
|
||||
std::exit(2);
|
||||
}
|
||||
}
|
||||
SET_VERBOSITY_LEVEL(new_verbosity_level);
|
||||
try {
|
||||
bool done = false;
|
||||
while (optind < argc) {
|
||||
auto boc = load_boc(argv[optind++]);
|
||||
if (boc.is_null()) {
|
||||
std::cerr << "(invalid boc)" << std::endl;
|
||||
std::exit(2);
|
||||
} else {
|
||||
done = true;
|
||||
vm::CellSlice cs{vm::NoVm(), boc};
|
||||
cs.print_rec(std::cout);
|
||||
std::cout << std::endl;
|
||||
auto& type = dump_state ? (const tlb::TLB&)block::gen::t_ShardStateUnsplit : block::gen::t_Block;
|
||||
std::string type_name = dump_state ? "ShardState" : "Block";
|
||||
type.print_ref(std::cout, boc);
|
||||
std::cout << std::endl;
|
||||
bool ok = type.validate_ref(boc);
|
||||
std::cout << "(" << (ok ? "" : "in") << "valid " << type_name << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
test1();
|
||||
}
|
||||
} catch (IntError& err) {
|
||||
std::cerr << "caught internal error " << err.err_msg << std::endl;
|
||||
return 1;
|
||||
} catch (vm::VmError& err) {
|
||||
std::cerr << "caught vm error " << err.get_msg() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -260,6 +260,22 @@ td::Status Config::unpack() {
|
|||
workchains_ = std::move(pair.first);
|
||||
workchains_dict_ = std::move(pair.second);
|
||||
}
|
||||
if (mode & needCapabilities) {
|
||||
auto cell = get_config_param(8);
|
||||
if (cell.is_null()) {
|
||||
version_ = 0;
|
||||
capabilities_ = 0;
|
||||
} else {
|
||||
block::gen::GlobalVersion::Record gv;
|
||||
if (!tlb::unpack_cell(std::move(cell), gv)) {
|
||||
return td::Status::Error(
|
||||
"cannot extract global blockchain version and capabilities from GlobalVersion in configuration parameter "
|
||||
"#8");
|
||||
}
|
||||
version_ = gv.version;
|
||||
capabilities_ = gv.capabilities;
|
||||
}
|
||||
}
|
||||
// ...
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
@ -339,7 +355,7 @@ bool ConfigInfo::get_last_key_block(ton::BlockIdExt& blkid, ton::LogicalTime& bl
|
|||
blkid = block_id;
|
||||
blklt = lt;
|
||||
}
|
||||
return blkid.is_valid() && blkid.seqno();
|
||||
return blkid.is_valid();
|
||||
}
|
||||
|
||||
td::Result<std::pair<WorkchainSet, std::unique_ptr<vm::Dictionary>>> Config::unpack_workchain_list_ext(
|
||||
|
|
|
@ -441,7 +441,7 @@ class Config {
|
|||
};
|
||||
|
||||
public:
|
||||
enum { needValidatorSet = 16, needSpecialSmc = 32, needWorkchainInfo = 256 };
|
||||
enum { needValidatorSet = 16, needSpecialSmc = 32, needWorkchainInfo = 256, needCapabilities = 512 };
|
||||
int mode{0};
|
||||
ton::BlockIdExt block_id;
|
||||
|
||||
|
@ -452,6 +452,8 @@ class Config {
|
|||
std::unique_ptr<ValidatorSet> cur_validators_;
|
||||
std::unique_ptr<vm::Dictionary> workchains_dict_;
|
||||
WorkchainSet workchains_;
|
||||
int version_{-1};
|
||||
long long capabilities_{-1};
|
||||
|
||||
protected:
|
||||
std::unique_ptr<vm::Dictionary> special_smc_dict;
|
||||
|
@ -474,6 +476,24 @@ class Config {
|
|||
bool is_masterchain() const {
|
||||
return block_id.is_masterchain();
|
||||
}
|
||||
bool has_capabilities() const {
|
||||
return capabilities_ >= 0;
|
||||
}
|
||||
long long get_capabilities() const {
|
||||
return capabilities_;
|
||||
}
|
||||
int get_global_version() const {
|
||||
return version_;
|
||||
}
|
||||
bool has_capability(long long cap_set) const {
|
||||
return has_capabilities() && (capabilities_ & cap_set) == cap_set;
|
||||
}
|
||||
bool ihr_enabled() const {
|
||||
return has_capability(ton::capIhrEnabled);
|
||||
}
|
||||
bool create_stats_enabled() const {
|
||||
return has_capability(ton::capCreateStatsEnabled);
|
||||
}
|
||||
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;
|
||||
bool is_special_smartcontract(const ton::StdSmcAddress& addr) const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue