1
0
mirror of https://github.com/danog/ton.git synced 2024-11-26 20:14:55 +01:00
ton/validator/block-handle.hpp

504 lines
15 KiB
C++

/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Library 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 Lesser General Public License for more details.
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/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "interfaces/block-handle.h"
#include "ton/ton-shard.h"
#include "td/actor/actor.h"
#include "interfaces/validator-manager.h"
#include "ton/ton-io.hpp"
#include "td/utils/ThreadSafeCounter.h"
namespace ton {
namespace validator {
class ValidatorManager;
struct BlockHandleImpl : public BlockHandleInterface {
private:
enum Flags : td::uint32 {
dbf_masterchain = 0x1,
dbf_inited_prev_left = 0x2,
dbf_inited_prev_right = 0x4,
dbf_inited_next_left = 0x8,
dbf_inited_next_right = 0x10,
dbf_inited_split_after = 0x20,
dbf_split_after = 0x40,
dbf_inited_merge_before = 0x80,
dbf_merge_before = 0x100,
dbf_received = 0x200,
dbf_is_key_block = 0x400,
dbf_inited_proof = 0x800,
dbf_inited_proof_link = 0x1000,
dbf_inited_lt = 0x2000,
dbf_inited_ts = 0x4000,
dbf_inited_is_key_block = 0x8000,
dbf_inited_state = 0x20000,
dbf_inited_signatures = 0x40000,
dbf_inited_state_boc = 0x100000,
dbf_archived = 0x200000,
dbf_applied = 0x400000,
dbf_moved = 0x1000000,
dbf_deleted = 0x2000000,
dbf_deleted_boc = 0x4000000,
dbf_processed = 0x10000000,
};
std::atomic<td::uint64> version_{0};
std::atomic<td::uint32> written_version_{0};
BlockIdExt id_;
std::atomic<td::uint32> flags_{0};
std::array<BlockIdExt, 2> prev_;
std::array<BlockIdExt, 2> next_;
LogicalTime lt_;
UnixTime ts_;
RootHash state_;
static constexpr td::uint64 lock_const() {
return static_cast<td::uint64>(1) << 32;
}
bool locked() const {
return version_.load(std::memory_order_consume) >> 32;
}
void lock() {
version_ += 1 + lock_const();
}
void unlock() {
version_ -= lock_const();
}
public:
BlockIdExt id() const override {
return id_;
}
bool received() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_received;
}
bool moved_to_storage() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_moved;
}
bool deleted() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_deleted;
}
bool inited_next_left() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_next_left;
}
bool inited_next_right() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_next_right;
}
bool inited_next() const override {
auto f = flags_.load(std::memory_order_consume);
if (!(f & Flags::dbf_inited_next_left)) {
return false;
}
if (f & Flags::dbf_inited_next_right) {
return true;
}
if ((f & Flags::dbf_inited_split_after) && !(f & Flags::dbf_split_after)) {
return true;
}
return false;
}
bool inited_prev_left() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_prev_left;
}
bool inited_prev_right() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_prev_right;
}
bool inited_prev() const override {
auto f = flags_.load(std::memory_order_consume);
if (!(f & Flags::dbf_inited_prev_left)) {
return false;
}
if (f & Flags::dbf_inited_prev_right) {
return true;
}
if ((f & Flags::dbf_inited_merge_before) && !(f & Flags::dbf_merge_before)) {
return true;
}
return false;
}
bool inited_proof() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_proof;
}
bool inited_proof_link() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_proof_link;
}
bool inited_signatures() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_signatures;
}
bool inited_split_after() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_split_after;
}
bool inited_merge_before() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_merge_before;
}
bool inited_is_key_block() const override {
auto f = flags_.load(std::memory_order_consume);
return f & Flags::dbf_inited_is_key_block;
}
bool split_after() const override {
auto f = flags_.load(std::memory_order_consume);
CHECK(f & Flags::dbf_inited_split_after);
return f & Flags::dbf_split_after;
}
bool merge_before() const override {
auto f = flags_.load(std::memory_order_consume);
CHECK(f & Flags::dbf_inited_merge_before);
return f & Flags::dbf_merge_before;
}
bool is_key_block() const override {
auto f = flags_.load(std::memory_order_consume);
CHECK(f & Flags::dbf_inited_is_key_block);
return f & Flags::dbf_is_key_block;
}
bool inited_state_root_hash() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_state;
}
bool inited_state_boc() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_state_boc;
}
bool deleted_state_boc() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_deleted_boc;
}
bool received_state() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_state_boc;
}
bool need_flush() const override {
return written_version_.load(std::memory_order_consume) < version();
}
bool is_zero() const override {
return id_.id.seqno == 0;
}
bool is_archived() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_archived;
}
bool is_applied() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_applied;
}
std::vector<BlockIdExt> prev() const override {
if (is_zero()) {
return {};
}
auto f = flags_.load(std::memory_order_consume);
CHECK(f & Flags::dbf_inited_merge_before);
if (!(f & Flags::dbf_merge_before)) {
CHECK(f & Flags::dbf_inited_prev_left);
return {prev_[0]};
} else {
CHECK(f & Flags::dbf_inited_prev_left);
CHECK(f & Flags::dbf_inited_prev_right);
return {prev_[0], prev_[1]};
}
}
BlockIdExt one_prev(bool left) const override {
CHECK(!is_zero());
if (left) {
CHECK(flags_.load(std::memory_order_consume) & Flags::dbf_inited_prev_left);
} else {
CHECK(flags_.load(std::memory_order_consume) & Flags::dbf_inited_prev_right);
}
return prev_[left ? 0 : 1];
}
std::vector<BlockIdExt> next() const override {
auto f = flags_.load(std::memory_order_consume);
CHECK(f & Flags::dbf_inited_split_after);
if (!(f & Flags::dbf_split_after)) {
CHECK(f & Flags::dbf_inited_next_left);
return {next_[0]};
} else {
CHECK(f & Flags::dbf_inited_next_left);
CHECK(f & Flags::dbf_inited_next_right);
return {next_[0], next_[1]};
}
}
BlockIdExt one_next(bool left) const override {
if (left) {
CHECK(flags_.load(std::memory_order_consume) & Flags::dbf_inited_next_left);
} else {
CHECK(flags_.load(std::memory_order_consume) & Flags::dbf_inited_next_right);
}
return next_[left ? 0 : 1];
}
RootHash state() const override {
CHECK(flags_.load(std::memory_order_consume) & Flags::dbf_inited_state);
return state_;
}
bool processed() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_processed;
}
void set_processed() override {
// does not increase version
flags_ |= Flags::dbf_processed;
}
td::uint32 version() const override {
return static_cast<td::uint32>(version_.load(std::memory_order_consume));
}
void flush(td::actor::ActorId<ValidatorManagerInterface> manager, BlockHandle self,
td::Promise<td::Unit> promise) override;
void flushed_upto(td::uint32 version) override {
if (version > written_version_.load(std::memory_order_consume)) {
written_version_.store(version, std::memory_order_release);
}
}
bool inited_logical_time() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_lt;
}
LogicalTime logical_time() const override {
CHECK(inited_logical_time());
return lt_;
}
void set_logical_time(LogicalTime lt) override {
if (inited_logical_time()) {
CHECK(lt_ == lt);
} else {
lock();
lt_ = lt;
flags_ |= Flags::dbf_inited_lt;
unlock();
}
}
bool inited_unix_time() const override {
return flags_.load(std::memory_order_consume) & Flags::dbf_inited_ts;
}
UnixTime unix_time() const override {
CHECK(inited_unix_time());
return ts_;
}
void set_unix_time(UnixTime ts) override {
if (inited_unix_time()) {
CHECK(ts_ == ts);
} else {
lock();
ts_ = ts;
flags_ |= Flags::dbf_inited_ts;
unlock();
}
}
void set_proof() override {
if (!inited_proof()) {
lock();
flags_ |= Flags::dbf_inited_proof;
unlock();
}
}
void set_proof_link() override {
if (!inited_proof_link()) {
lock();
flags_ |= Flags::dbf_inited_proof_link;
unlock();
}
}
void set_signatures() override {
if (!inited_signatures()) {
lock();
flags_ |= Flags::dbf_inited_signatures;
unlock();
}
}
void set_next_left(BlockIdExt next) {
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_next_left) {
LOG_CHECK(next_[0] == next) << "id=" << id_ << " next=" << next_[0] << " to_be_next=" << next;
} else {
lock();
next_[0] = next;
flags_ |= Flags::dbf_inited_next_left;
unlock();
}
}
void set_next_right(BlockIdExt next) {
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_next_right) {
LOG_CHECK(next_[1] == next) << "id=" << id_ << " next=" << next_[1] << " to_be_next=" << next;
} else {
lock();
next_[1] = next;
flags_ |= Flags::dbf_inited_next_right;
unlock();
}
}
void set_next(BlockIdExt next) override {
bool right = shard_child(id_.id.shard, false) == next.id.shard;
if (right) {
set_next_right(next);
} else {
set_next_left(next);
}
}
void set_prev_left(BlockIdExt prev) {
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_prev_left) {
LOG_CHECK(prev_[0] == prev) << "id=" << id_ << " prev=" << prev_[0] << " to_be_prev=" << prev;
} else {
lock();
prev_[0] = prev;
flags_ |= Flags::dbf_inited_prev_left;
unlock();
}
}
void set_prev_right(BlockIdExt prev) {
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_prev_right) {
LOG_CHECK(prev_[1] == prev) << "id=" << id_ << " prev=" << prev_[1] << " to_be_prev=" << prev;
} else {
lock();
prev_[1] = prev;
flags_ |= Flags::dbf_inited_prev_right;
unlock();
}
}
void set_prev(BlockIdExt prev) override {
bool right = shard_child(id_.id.shard, false) == prev.id.shard;
if (right) {
set_prev_right(prev);
} else {
set_prev_left(prev);
}
}
void set_received() override {
if (flags_.load(std::memory_order_consume) & Flags::dbf_received) {
return;
}
lock();
flags_ |= Flags::dbf_received;
unlock();
}
void set_moved_to_storage() override {
if (flags_.load(std::memory_order_consume) & Flags::dbf_moved) {
return;
}
lock();
flags_ |= Flags::dbf_moved;
unlock();
}
void set_deleted() override {
if (flags_.load(std::memory_order_consume) & Flags::dbf_deleted) {
return;
}
lock();
flags_ |= Flags::dbf_deleted;
unlock();
}
void set_split(bool value) override {
td::uint32 v = value ? static_cast<td::uint32>(Flags::dbf_split_after) : 0;
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_split_after) {
CHECK((f & Flags::dbf_split_after) == v);
} else {
lock();
flags_ |= v | Flags::dbf_inited_split_after;
unlock();
}
}
void set_merge(bool value) override {
td::uint32 v = value ? static_cast<td::uint32>(Flags::dbf_merge_before) : 0;
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_merge_before) {
CHECK((f & Flags::dbf_merge_before) == v);
} else {
lock();
flags_ |= v | Flags::dbf_inited_merge_before;
unlock();
}
}
void set_is_key_block(bool value) override {
td::uint32 v = value ? static_cast<td::uint32>(Flags::dbf_is_key_block) : 0;
auto f = flags_.load(std::memory_order_consume);
if (f & Flags::dbf_inited_is_key_block) {
CHECK((f & Flags::dbf_is_key_block) == v);
} else {
lock();
flags_ |= v | Flags::dbf_inited_is_key_block;
unlock();
}
}
void set_state_root_hash(RootHash hash) override {
if (!(flags_.load(std::memory_order_consume) & Flags::dbf_inited_state)) {
lock();
state_ = hash;
flags_ |= Flags::dbf_inited_state;
unlock();
}
}
void set_state_boc() override {
if (!inited_state_boc()) {
CHECK(inited_state_root_hash());
lock();
flags_ |= Flags::dbf_inited_state_boc;
unlock();
}
}
void set_deleted_state_boc() override {
if (flags_.load(std::memory_order_consume) & Flags::dbf_deleted_boc) {
return;
}
lock();
flags_ |= Flags::dbf_deleted_boc;
unlock();
}
void set_archived() override {
if (!is_archived()) {
lock();
flags_ |= Flags::dbf_archived;
unlock();
}
}
void set_applied() override {
if (!is_applied()) {
lock();
flags_ |= Flags::dbf_applied;
unlock();
}
}
td::BufferSlice serialize() const override;
BlockHandleImpl(BlockIdExt id)
: id_(id), flags_(id_.is_masterchain() ? static_cast<td::uint32>(dbf_masterchain) : 0) {
get_thread_safe_counter().add(1);
}
BlockHandleImpl(td::BufferSlice data);
~BlockHandleImpl() {
LOG_CHECK(!need_flush()) << "flags=" << flags_;
get_thread_safe_counter().add(-1);
}
static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() {
static auto res = td::NamedThreadSafeCounter::get_default().get_counter("BlockHandleImpl");
return res;
}
static BlockHandle create_empty(BlockIdExt id) {
return std::make_shared<BlockHandleImpl>(id);
}
static BlockHandle create(td::BufferSlice data) {
return std::make_shared<BlockHandleImpl>(std::move(data));
}
};
} // namespace validator
} // namespace ton