1
0
mirror of https://github.com/danog/ton.git synced 2024-11-30 04:29:19 +01:00
ton/crypto/block/mc-config.h

641 lines
26 KiB
C
Raw Permalink Normal View History

2019-09-07 12:03:22 +02:00
/*
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/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "common/refcnt.hpp"
#include "vm/db/StaticBagOfCellsDb.h"
#include "vm/dict.h"
#include "ton/ton-types.h"
#include "ton/ton-shard.h"
#include "common/bitstring.h"
#include "block.h"
#include <vector>
#include <limits>
#include <map>
#include <set>
#include <cstring>
namespace block {
using td::Ref;
struct ValidatorDescr {
ton::Ed25519_PublicKey pubkey;
td::Bits256 adnl_addr;
td::uint64 weight;
td::uint64 cum_weight;
ValidatorDescr(const td::Bits256& _pubkey, td::uint64 _weight, td::uint64 _cum_weight)
: pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) {
adnl_addr.set_zero();
}
ValidatorDescr(const td::Bits256& _pubkey, td::uint64 _weight, td::uint64 _cum_weight, const td::Bits256& _adnl_addr)
: pubkey(_pubkey), adnl_addr(_adnl_addr), weight(_weight), cum_weight(_cum_weight) {
}
ValidatorDescr(const ton::Ed25519_PublicKey& _pubkey, td::uint64 _weight, td::uint64 _cum_weight)
: pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) {
adnl_addr.set_zero();
}
bool operator<(td::uint64 wt_pos) const & {
return cum_weight < wt_pos;
}
};
struct ValidatorSet {
unsigned utime_since;
unsigned utime_until;
int total;
int main;
td::uint64 total_weight;
std::vector<ValidatorDescr> list;
ValidatorSet() = default;
ValidatorSet(unsigned _since, unsigned _until, int _total, int _main = 0)
: utime_since(_since), utime_until(_until), total(_total), main(_main > 0 ? _main : _total), total_weight(0) {
}
const ValidatorDescr& operator[](unsigned i) const {
return list[i];
}
const ValidatorDescr& at_weight(td::uint64 weight_pos) const;
std::vector<ton::ValidatorDescr> export_validator_set() const;
};
#pragma pack(push, 1)
// this structure is hashed with SHA512 to produce pseudo-random bit stream in do_compute_validator_set()
// NB: all integers (including 256-bit seed) are actually big-endian
struct validator_set_descr {
unsigned char seed[32]; // seed for validator set computation, set to zero if none
td::uint64 shard;
td::int32 workchain;
td::uint32 cc_seqno;
validator_set_descr() = default;
validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, bool flag)
: shard(td::bswap64(shard_id.shard))
, workchain(td::bswap32(shard_id.workchain))
, cc_seqno(td::bswap32(cc_seqno_)) {
}
validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_)
: validator_set_descr(shard_id, cc_seqno_, false) {
std::memset(seed, 0, 32);
}
validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const unsigned char seed_[32])
: validator_set_descr(shard_id, cc_seqno_, false) {
std::memcpy(seed, seed_, 32);
}
validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, td::ConstBitPtr seed_)
: validator_set_descr(shard_id, cc_seqno_, false) {
td::BitPtr{seed}.copy_from(seed_, 256);
}
validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const td::Bits256& seed_)
: validator_set_descr(shard_id, cc_seqno_, false) {
td::BitPtr{seed}.copy_from(seed_.cbits(), 256);
}
void incr_seed();
void hash_to(unsigned char hash_buffer[64]) const;
};
#pragma pack(pop)
class ValidatorSetPRNG {
validator_set_descr data;
union {
unsigned char hash[64];
td::uint64 hash_longs[8];
};
int pos{0}, limit{0};
public:
ValidatorSetPRNG() = default;
ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_) : data(shard_id, cc_seqno_) {
}
ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const unsigned char seed_[32])
: data(shard_id, cc_seqno_, seed_) {
}
ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, td::ConstBitPtr seed_)
: data(shard_id, cc_seqno_, std::move(seed_)) {
}
ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const td::Bits256& seed_)
: data(shard_id, cc_seqno_, seed_) {
}
td::uint64 next_ulong();
td::uint64 next_ranged(td::uint64 range); // integer in 0 .. range-1
ValidatorSetPRNG& operator>>(td::uint64& x) {
x = next_ulong();
return *this;
}
};
class McShardHashI : public td::CntObject {
public:
enum class FsmState { fsm_none, fsm_split, fsm_merge };
virtual ton::BlockIdExt top_block_id() const = 0;
virtual ton::LogicalTime start_lt() const = 0;
virtual ton::LogicalTime end_lt() const = 0;
virtual ton::UnixTime fsm_utime() const = 0;
virtual FsmState fsm_state() const = 0;
virtual ton::ShardIdFull shard() const = 0;
virtual bool before_split() const = 0;
virtual bool before_merge() const = 0;
};
struct McShardHash : public McShardHashI {
ton::BlockIdExt blk_;
ton::LogicalTime start_lt_, end_lt_;
ton::UnixTime gen_utime_{0};
ton::UnixTime fsm_utime_{0};
ton::UnixTime fsm_interval_{0};
ton::BlockSeqno min_ref_mc_seqno_{std::numeric_limits<ton::BlockSeqno>::max()};
ton::BlockSeqno reg_mc_seqno_{std::numeric_limits<ton::BlockSeqno>::max()};
FsmState fsm_{FsmState::fsm_none};
bool disabled_{false};
bool before_split_{false}, before_merge_{false}, want_split_{false}, want_merge_{false};
ton::CatchainSeqno next_catchain_seqno_{std::numeric_limits<ton::CatchainSeqno>::max()};
ton::ShardId next_validator_shard_{ton::shardIdAll};
CurrencyCollection fees_collected_, funds_created_;
McShardHash(const ton::BlockId& id, ton::LogicalTime start_lt, ton::LogicalTime end_lt, ton::UnixTime gen_utime,
const ton::BlockHash& root_hash, const ton::FileHash& file_hash, CurrencyCollection fees_collected = {},
CurrencyCollection funds_created = {},
ton::BlockSeqno reg_mc_seqno = std::numeric_limits<ton::BlockSeqno>::max(),
ton::BlockSeqno min_ref_mc_seqno = std::numeric_limits<ton::BlockSeqno>::max(),
ton::CatchainSeqno cc_seqno = std::numeric_limits<ton::CatchainSeqno>::max(), ton::ShardId val_shard = 0,
bool nx_cc_updated = false, bool before_split = false, bool before_merge = false, bool want_split = false,
bool want_merge = false)
: blk_(id, root_hash, file_hash)
, start_lt_(start_lt)
, end_lt_(end_lt)
, gen_utime_(gen_utime)
, min_ref_mc_seqno_(min_ref_mc_seqno)
, reg_mc_seqno_(reg_mc_seqno)
, before_split_(before_split)
, before_merge_(before_merge)
, want_split_(want_split)
, want_merge_(want_merge)
, next_catchain_seqno_(cc_seqno)
, next_validator_shard_(val_shard ? val_shard : id.shard)
, fees_collected_(fees_collected)
, funds_created_(funds_created) {
}
McShardHash(const ton::BlockIdExt& blk, ton::LogicalTime start_lt, ton::LogicalTime end_lt)
: blk_(blk), start_lt_(start_lt), end_lt_(end_lt) {
}
McShardHash(const McShardHash&) = default;
bool is_valid() const {
return blk_.is_valid();
}
ton::BlockIdExt top_block_id() const override final {
return blk_;
}
// ZeroStateIdExt zero_state() const override;
ton::LogicalTime start_lt() const override final {
return start_lt_;
}
ton::LogicalTime end_lt() const override final {
return end_lt_;
}
ton::UnixTime fsm_utime() const override final {
return fsm_utime_;
}
ton::UnixTime fsm_utime_end() const {
return fsm_utime_ + fsm_interval_;
}
ton::UnixTime created_at() const {
return gen_utime_;
}
FsmState fsm_state() const override final {
return fsm_;
}
bool is_fsm_none() const {
return fsm_ == FsmState::fsm_none;
}
bool is_fsm_split() const {
return fsm_ == FsmState::fsm_split;
}
bool is_fsm_merge() const {
return fsm_ == FsmState::fsm_merge;
}
ton::ShardIdFull shard() const override final {
return ton::ShardIdFull(blk_);
}
ton::WorkchainId workchain() const {
return blk_.id.workchain;
}
bool contains(const ton::AccountIdPrefixFull& pfx) const {
return ton::shard_contains(shard(), pfx);
}
bool before_split() const override final {
return before_split_;
}
bool before_merge() const override final {
return before_merge_;
}
bool is_disabled() const {
return disabled_;
}
void disable() {
blk_.invalidate();
disabled_ = true;
}
ton::BlockSeqno seqno() const {
return blk_.id.seqno;
}
bool set_reg_mc_seqno(ton::BlockSeqno reg_mc_seqno) {
reg_mc_seqno_ = reg_mc_seqno;
return true;
}
// compares all fields except fsm*, before_merge_, nx_cc_updated_, next_catchain_seqno_, fees_collected_
bool basic_info_equal(const McShardHash& other, bool compare_fees = false, bool compare_reg_seqno = true) const;
void clear_fsm() {
fsm_ = FsmState::fsm_none;
}
void set_fsm(FsmState fsm, ton::UnixTime fsm_utime, ton::UnixTime fsm_interval);
void set_fsm_split(ton::UnixTime fsm_utime, ton::UnixTime fsm_interval) {
set_fsm(FsmState::fsm_split, fsm_utime, fsm_interval);
}
void set_fsm_merge(ton::UnixTime fsm_utime, ton::UnixTime fsm_interval) {
set_fsm(FsmState::fsm_merge, fsm_utime, fsm_interval);
}
bool fsm_equal(const McShardHash& other) const {
return fsm_ == other.fsm_ &&
(is_fsm_none() || (fsm_utime_ == other.fsm_utime_ && fsm_interval_ == other.fsm_interval_));
}
bool pack(vm::CellBuilder& cb) const;
static Ref<McShardHash> unpack(vm::CellSlice& cs, ton::ShardIdFull id);
static Ref<McShardHash> from_block(Ref<vm::Cell> block_root, const ton::FileHash& _fhash, bool init_fees = false);
McShardHash* make_copy() const override {
return new McShardHash(*this);
}
};
struct McShardDescr final : public McShardHash {
Ref<vm::Cell> block_root;
Ref<vm::Cell> state_root;
Ref<vm::Cell> outmsg_root;
std::unique_ptr<vm::AugmentedDictionary> out_msg_queue;
std::shared_ptr<block::MsgProcessedUptoCollection> processed_upto;
McShardDescr(const ton::BlockId& id, ton::LogicalTime start_lt, ton::LogicalTime end_lt, ton::UnixTime gen_utime,
const ton::BlockHash& root_hash, const ton::FileHash& file_hash, CurrencyCollection fees_collected = {},
CurrencyCollection funds_created = {},
ton::BlockSeqno reg_mc_seqno = std::numeric_limits<ton::BlockSeqno>::max(),
ton::BlockSeqno min_ref_mc_seqno = std::numeric_limits<ton::BlockSeqno>::max(),
ton::CatchainSeqno cc_seqno = std::numeric_limits<ton::CatchainSeqno>::max(),
ton::ShardId val_shard = ton::shardIdAll, bool nx_cc_updated = false, bool before_split = false,
bool before_merge = false, bool want_split = false, bool want_merge = false)
: McShardHash(id, start_lt, end_lt, gen_utime, root_hash, file_hash, fees_collected, funds_created, reg_mc_seqno,
min_ref_mc_seqno, cc_seqno, val_shard, nx_cc_updated, before_split, before_merge, want_split,
want_merge) {
}
McShardDescr(const ton::BlockIdExt& blk, ton::LogicalTime start_lt, ton::LogicalTime end_lt)
: McShardHash(blk, start_lt, end_lt) {
}
McShardDescr(const McShardHash& shard_hash) : McShardHash(shard_hash) {
}
McShardDescr(const McShardDescr& other);
McShardDescr(McShardDescr&& other) = default;
McShardDescr& operator=(const McShardDescr& other);
McShardDescr& operator=(McShardDescr&& other) = default;
bool set_queue_root(Ref<vm::Cell> queue_root);
void disable();
static Ref<McShardDescr> from_block(Ref<vm::Cell> block_root, Ref<vm::Cell> state_root, const ton::FileHash& _fhash,
bool init_fees = false);
static Ref<McShardDescr> from_state(ton::BlockIdExt blkid, Ref<vm::Cell> state_root);
};
struct StoragePrices {
ton::UnixTime valid_since{0};
td::uint64 bit_price{0};
td::uint64 cell_price{0};
td::uint64 mc_bit_price{0};
td::uint64 mc_cell_price{0};
StoragePrices() = default;
StoragePrices(ton::UnixTime _valid_since, td::uint64 _bprice, td::uint64 _cprice, td::uint64 _mc_bprice,
td::uint64 _mc_cprice)
: valid_since(_valid_since)
, bit_price(_bprice)
, cell_price(_cprice)
, mc_bit_price(_mc_bprice)
, mc_cell_price(_mc_cprice) {
}
};
struct CatchainValidatorsConfig {
td::uint32 mc_cc_lifetime, shard_cc_lifetime, shard_val_lifetime, shard_val_num;
CatchainValidatorsConfig(td::uint32 mc_cc_lt_, td::uint32 sh_cc_lt_, td::uint32 sh_val_lt_, td::uint32 sh_val_num_)
: mc_cc_lifetime(mc_cc_lt_)
, shard_cc_lifetime(sh_cc_lt_)
, shard_val_lifetime(sh_val_lt_)
, shard_val_num(sh_val_num_) {
}
};
struct WorkchainInfo : public td::CntObject {
ton::WorkchainId workchain{ton::workchainInvalid};
ton::UnixTime enabled_since;
td::uint32 actual_min_split;
td::uint32 min_split, max_split;
bool basic;
bool active;
bool accept_msgs;
int flags;
td::uint32 version;
ton::RootHash zerostate_root_hash;
ton::FileHash zerostate_file_hash;
int min_addr_len, max_addr_len, addr_len_step;
bool is_valid() const {
return workchain != ton::workchainInvalid;
}
bool is_valid_addr_len(int addr_len) const {
return addr_len >= min_addr_len && addr_len <= max_addr_len &&
(addr_len == min_addr_len || addr_len == max_addr_len ||
(addr_len_step > 0 && !((addr_len - min_addr_len) % addr_len_step)));
}
bool unpack(ton::WorkchainId wc, vm::CellSlice& cs);
};
using WorkchainSet = std::map<td::int32, Ref<WorkchainInfo>>;
class ShardConfig {
Ref<vm::Cell> shard_hashes_;
Ref<McShardHash> mc_shard_hash_;
std::unique_ptr<vm::Dictionary> shard_hashes_dict_;
std::set<ton::ShardIdFull> shards_updated_;
bool valid_{false};
public:
ShardConfig() = default;
ShardConfig(const ShardConfig& other);
ShardConfig(ShardConfig&& other) = default;
ShardConfig(Ref<vm::Cell> shard_hashes, Ref<McShardHash> mc_shard_hash = {})
: shard_hashes_(std::move(shard_hashes)), mc_shard_hash_(std::move(mc_shard_hash)) {
init();
}
bool is_valid() const {
return valid_;
}
bool unpack(Ref<vm::Cell> shard_hashes, Ref<McShardHash> mc_shard_hash = {});
bool unpack(Ref<vm::CellSlice> shard_hashes, Ref<McShardHash> mc_shard_hash = {});
Ref<vm::CellSlice> get_root_csr() const;
bool has_workchain(ton::WorkchainId workchain) const;
std::vector<ton::WorkchainId> get_workchains() const;
Ref<McShardHash> get_shard_hash(ton::ShardIdFull id, bool exact = true) const;
bool contains(ton::BlockIdExt blkid) const;
bool get_shard_hash_raw(vm::CellSlice& cs, ton::ShardIdFull id, ton::ShardIdFull& true_id, bool exact = true) const;
ton::LogicalTime get_shard_end_lt(ton::AccountIdPrefixFull acc) const;
ton::LogicalTime get_shard_end_lt_ext(ton::AccountIdPrefixFull acc, ton::ShardIdFull& actual_shard) const;
static bool get_shard_hash_raw_from(vm::Dictionary& shard_hashes_dict, vm::CellSlice& cs, ton::ShardIdFull id,
ton::ShardIdFull& true_id, bool exact = true, Ref<vm::Cell>* leaf = nullptr);
std::vector<ton::BlockId> get_shard_hash_ids(bool skip_mc = false) const;
std::vector<ton::BlockId> get_shard_hash_ids(const std::function<bool(ton::ShardIdFull, bool)>& filter) const;
std::vector<ton::BlockId> get_intersecting_shard_hash_ids(ton::ShardIdFull myself) const;
std::vector<ton::BlockId> get_neighbor_shard_hash_ids(ton::ShardIdFull myself) const;
std::vector<ton::BlockId> get_proper_neighbor_shard_hash_ids(ton::ShardIdFull myself) const;
static std::unique_ptr<vm::Dictionary> extract_shard_hashes_dict(Ref<vm::Cell> mc_state_root);
bool process_shard_hashes(std::function<int(McShardHash&)> func);
bool process_sibling_shard_hashes(std::function<int(McShardHash&, const McShardHash*)> func);
// may become non-static const in the future
static bool is_neighbor(ton::ShardIdFull x, ton::ShardIdFull y);
Ref<McShardHash> get_mc_hash() const {
return mc_shard_hash_;
}
void set_mc_hash(Ref<McShardHash> mc_shard_hash) {
mc_shard_hash_ = std::move(mc_shard_hash);
}
ton::CatchainSeqno get_shard_cc_seqno(ton::ShardIdFull shard) const;
block::compute_shard_end_lt_func_t get_compute_shard_end_lt_func() const {
return std::bind(&ShardConfig::get_shard_end_lt, *this, std::placeholders::_1);
}
bool new_workchain(ton::WorkchainId workchain, ton::BlockSeqno reg_mc_seqno, const ton::RootHash& zerostate_root_hash,
const ton::FileHash& zerostate_file_hash);
td::Result<bool> update_shard_block_info(Ref<McShardHash> new_info, const std::vector<ton::BlockIdExt>& old_blkids);
td::Result<bool> update_shard_block_info2(Ref<McShardHash> new_info1, Ref<McShardHash> new_info2,
const std::vector<ton::BlockIdExt>& old_blkids);
td::Result<bool> may_update_shard_block_info(Ref<McShardHash> new_info,
const std::vector<ton::BlockIdExt>& old_blkids,
ton::LogicalTime lt_limit = std::numeric_limits<ton::LogicalTime>::max(),
Ref<McShardHash>* ancestor = nullptr) const;
private:
bool init();
bool do_update_shard_info(Ref<McShardHash> new_info);
bool do_update_shard_info2(Ref<McShardHash> new_info1, Ref<McShardHash> new_info2);
bool set_shard_info(ton::ShardIdFull shard, Ref<vm::Cell> value);
};
class Config {
enum {
default_mc_catchain_lifetime = 200,
default_shard_catchain_lifetime = 200,
default_shard_validators_lifetime = 3000,
default_shard_validators_num = 7
};
public:
enum { needValidatorSet = 16, needSpecialSmc = 32, needWorkchainInfo = 256, needCapabilities = 512 };
2019-09-07 12:03:22 +02:00
int mode{0};
ton::BlockIdExt block_id;
private:
td::BitArray<256> config_addr;
Ref<vm::Cell> config_root;
std::unique_ptr<vm::Dictionary> config_dict;
std::unique_ptr<ValidatorSet> cur_validators_;
std::unique_ptr<vm::Dictionary> workchains_dict_;
WorkchainSet workchains_;
int version_{-1};
long long capabilities_{-1};
2019-09-07 12:03:22 +02:00
protected:
std::unique_ptr<vm::Dictionary> special_smc_dict;
public:
static constexpr ton::LogicalTime get_lt_align() {
return 1000000;
}
static constexpr ton::LogicalTime get_max_lt_growth() {
return 10 * get_lt_align() - 1;
}
Ref<vm::Cell> get_config_param(int idx) const;
Ref<vm::Cell> get_config_param(int idx, int idx2) const;
Ref<vm::Cell> operator[](int idx) const {
return get_config_param(idx);
}
Ref<vm::Cell> get_root_cell() const {
return config_root;
}
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);
}
2019-09-07 12:03:22 +02:00
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;
static td::Result<std::unique_ptr<ValidatorSet>> unpack_validator_set(Ref<vm::Cell> valset_root);
td::Result<std::vector<StoragePrices>> get_storage_prices() const;
static CatchainValidatorsConfig unpack_catchain_validators_config(Ref<vm::Cell> cell);
CatchainValidatorsConfig get_catchain_validators_config() const;
td::Status visit_validator_params() const;
td::Result<std::unique_ptr<BlockLimits>> get_block_limits(bool is_masterchain = false) const;
auto get_mc_block_limits() const {
return get_block_limits(true);
}
static td::Result<std::pair<WorkchainSet, std::unique_ptr<vm::Dictionary>>> unpack_workchain_list_ext(
Ref<vm::Cell> cell);
static td::Result<WorkchainSet> unpack_workchain_list(Ref<vm::Cell> cell);
const WorkchainSet& get_workchain_list() const {
return workchains_;
}
const ValidatorSet* get_cur_validator_set() const {
return cur_validators_.get();
}
ton::ValidatorSessionConfig get_consensus_config() const;
bool foreach_config_param(std::function<bool(int, Ref<vm::Cell>)> scan_func) const;
Ref<WorkchainInfo> get_workchain_info(ton::WorkchainId workchain_id) const;
std::vector<ton::ValidatorDescr> compute_validator_set(ton::ShardIdFull shard, const block::ValidatorSet& vset,
ton::UnixTime time, ton::CatchainSeqno cc_seqno) const;
std::vector<ton::ValidatorDescr> compute_validator_set(ton::ShardIdFull shard, ton::UnixTime time,
ton::CatchainSeqno cc_seqno) const;
std::vector<ton::ValidatorDescr> compute_total_validator_set(int next) const;
static std::vector<ton::ValidatorDescr> do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf,
ton::ShardIdFull shard,
const block::ValidatorSet& vset, ton::UnixTime time,
ton::CatchainSeqno cc_seqno);
static td::Result<std::unique_ptr<Config>> unpack_config(Ref<vm::Cell> config_root,
const td::Bits256& config_addr = td::Bits256::zero(),
int mode = 0);
static td::Result<std::unique_ptr<Config>> unpack_config(Ref<vm::CellSlice> config_csr, int mode = 0);
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);
protected:
Config(int _mode) : mode(_mode) {
config_addr.set_zero();
}
Config(Ref<vm::Cell> config_root, const td::Bits256& config_addr = td::Bits256::zero(), int _mode = 0);
td::Status unpack_wrapped(Ref<vm::CellSlice> config_csr);
td::Status unpack(Ref<vm::CellSlice> config_csr);
td::Status unpack_wrapped();
td::Status unpack();
};
class ConfigInfo : public Config, public ShardConfig {
public:
enum {
needStateRoot = 1,
needLibraries = 2,
needStateExtraRoot = 4,
needShardHashes = 8,
needAccountsRoot = 64,
needPrevBlocks = 128
};
ton::BlockSeqno vert_seqno{~0U};
2019-09-07 12:03:22 +02:00
int global_id_{0};
ton::UnixTime utime{0};
ton::LogicalTime lt{0};
ton::BlockSeqno min_ref_mc_seqno_{std::numeric_limits<ton::BlockSeqno>::max()};
ton::CatchainSeqno cc_seqno_{std::numeric_limits<ton::CatchainSeqno>::max()};
int shard_cc_updated{-1};
bool nx_cc_updated;
bool is_key_state_{false};
private:
Ref<vm::Cell> state_root;
Ref<vm::Cell> lib_root_;
Ref<vm::Cell> state_extra_root_;
Ref<vm::CellSlice> accounts_root;
ton::ZeroStateIdExt zerostate_id_;
ton::BlockIdExt last_key_block_;
ton::LogicalTime last_key_block_lt_;
Ref<vm::Cell> shard_hashes;
std::unique_ptr<vm::Dictionary> shard_hashes_dict;
std::unique_ptr<vm::AugmentedDictionary> accounts_dict;
std::unique_ptr<vm::AugmentedDictionary> prev_blocks_dict_;
std::unique_ptr<vm::Dictionary> libraries_dict_;
public:
bool set_block_id_ext(const ton::BlockIdExt& block_id_ext);
bool rotated_all_shards() const {
return nx_cc_updated;
}
int get_global_blockchain_id() const {
return global_id_;
}
ton::ZeroStateIdExt get_zerostate_id() const {
return zerostate_id_;
}
Ref<vm::Cell> lookup_library(const ton::Bits256& root_hash) const {
return lookup_library(root_hash.bits());
}
Ref<vm::Cell> lookup_library(td::ConstBitPtr root_hash) const;
Ref<vm::Cell> get_libraries_root() const {
return lib_root_;
}
bool is_key_state() const {
return is_key_state_;
}
Ref<vm::Cell> get_state_extra_root() const {
return state_extra_root_;
}
ton::BlockSeqno get_vert_seqno() const {
return vert_seqno;
}
2019-09-07 12:03:22 +02:00
ton::CatchainSeqno get_shard_cc_seqno(ton::ShardIdFull shard) const;
bool get_last_key_block(ton::BlockIdExt& blkid, ton::LogicalTime& blklt, bool strict = false) const;
bool get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
bool check_old_mc_block_id(const ton::BlockIdExt& blkid, bool strict = false) const;
// returns block with min seqno and req_lt <= block.end_lt
bool get_mc_block_by_lt(ton::LogicalTime lt, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
bool get_prev_key_block(ton::BlockSeqno req_seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
bool get_next_key_block(ton::BlockSeqno req_seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
td::Result<std::vector<std::pair<ton::StdSmcAddress, int>>> get_special_ticktock_smartcontracts(
int tick_tock = 3) const;
int get_smc_tick_tock(td::ConstBitPtr smc_addr) const;
std::unique_ptr<vm::AugmentedDictionary> create_accounts_dict() const;
const vm::AugmentedDictionary& get_accounts_dict() const;
std::vector<ton::ValidatorDescr> compute_validator_set_cc(ton::ShardIdFull shard, const block::ValidatorSet& vset,
ton::UnixTime time,
ton::CatchainSeqno* cc_seqno_delta = nullptr) const;
std::vector<ton::ValidatorDescr> compute_validator_set_cc(ton::ShardIdFull shard, ton::UnixTime time,
ton::CatchainSeqno* cc_seqno_delta = nullptr) const;
static td::Result<std::unique_ptr<ConfigInfo>> extract_config(std::shared_ptr<vm::StaticBagOfCellsDb> static_boc,
int mode = 0);
static td::Result<std::unique_ptr<ConfigInfo>> extract_config(Ref<vm::Cell> mc_state_root, int mode = 0);
private:
ConfigInfo(Ref<vm::Cell> mc_state_root, int _mode = 0);
td::Status unpack_wrapped();
td::Status unpack();
void reset_mc_hash();
void cleanup();
};
} // namespace block