1
0
mirror of https://github.com/danog/ton.git synced 2024-11-30 04:29:19 +01:00
ton/validator-session/persistent-vector.h
2019-09-07 14:33:36 +04:00

809 lines
25 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 <functional>
#include "td/utils/int_types.h"
#include "td/utils/buffer.h"
#include "adnl/utils.hpp"
#include "validator-session-description.h"
namespace ton {
namespace validatorsession {
using HashType = ValidatorSessionDescription::HashType;
template <class T>
inline HashType get_vs_hash(ValidatorSessionDescription& desc, const T& value) {
return value.get_hash(desc);
}
template <class T>
inline HashType get_vs_hash(ValidatorSessionDescription& desc, const T* value) {
return value ? value->get_hash(desc) : desc.zero_hash();
}
HashType get_vector_hash(ValidatorSessionDescription& desc, std::vector<HashType>&& value);
HashType get_pair_hash(ValidatorSessionDescription& desc, const HashType& left, const HashType& right);
HashType get_vs_hash(ValidatorSessionDescription& desc, const bool& value);
HashType get_vs_hash(ValidatorSessionDescription& desc, const td::uint32& value);
HashType get_vs_hash(ValidatorSessionDescription& desc, const td::uint64& value);
HashType get_vs_hash(ValidatorSessionDescription& desc, const td::Bits256& value);
HashType get_vs_hash(ValidatorSessionDescription& desc, const td::BufferSlice& value);
template <typename T1, typename T2>
inline HashType get_vs_hash(ValidatorSessionDescription& desc, const std::pair<T1, T2>& value) {
return get_pair_hash(desc, get_vs_hash(value.first), get_vs_hash(value.second));
}
template <typename T>
inline HashType get_vs_hash(ValidatorSessionDescription& desc, const std::vector<T>& value) {
std::vector<HashType> v;
v.resize(value.size());
for (size_t i = 0; i < value.size(); i++) {
v[i] = get_vs_hash(desc, value[i]);
}
return get_vector_hash(desc, std::move(v));
}
inline HashType get_vs_hash(ValidatorSessionDescription& desc, const std::vector<bool>& value) {
std::vector<HashType> v;
v.resize(value.size());
for (size_t i = 0; i < value.size(); i++) {
bool b = value[i];
v[i] = get_vs_hash(desc, b);
}
return get_vector_hash(desc, std::move(v));
}
template <typename T>
inline HashType get_vs_hash(ValidatorSessionDescription& desc, td::uint32 size, const T* value) {
std::vector<HashType> v;
v.resize(size);
for (size_t i = 0; i < size; i++) {
v[i] = get_vs_hash(desc, value[i]);
}
return get_vector_hash(desc, std::move(v));
}
inline bool move_to_persistent(ValidatorSessionDescription& desc, bool v) {
return v;
}
inline td::uint32 move_to_persistent(ValidatorSessionDescription& desc, td::uint32 v) {
return v;
}
inline td::uint64 move_to_persistent(ValidatorSessionDescription& desc, td::uint64 v) {
return v;
}
template <typename T>
inline const T* move_to_persistent(ValidatorSessionDescription& desc, const T* v) {
return T::move_to_persistent(desc, v);
}
template <typename T>
class CntVector : public ValidatorSessionDescription::RootObject {
public:
static HashType create_hash(ValidatorSessionDescription& desc, std::vector<T>& value) {
auto obj = create_tl_object<ton_api::hashable_cntVector>(get_vs_hash(desc, value));
return desc.compute_hash(serialize_tl_object(obj, true).as_slice());
}
static HashType create_hash(ValidatorSessionDescription& desc, td::uint32 size, const T* value) {
auto obj = create_tl_object<ton_api::hashable_cntVector>(get_vs_hash(desc, size, value));
return desc.compute_hash(serialize_tl_object(obj, true).as_slice());
}
static bool compare(const RootObject* r, td::uint32 size, const T* data, HashType hash) {
if (!r || r->get_size() < sizeof(CntVector)) {
return false;
}
auto R = static_cast<const CntVector*>(r);
if (R->data_size_ != size * sizeof(T) || R->hash_ != hash) {
return false;
}
for (td::uint32 i = 0; i < size; i++) {
if (R->data_[i] != data[i]) {
return false;
}
}
return true;
}
static bool compare(const RootObject* r, const std::vector<T>& data, HashType hash) {
if (!r || r->get_size() < sizeof(CntVector)) {
return false;
}
auto R = static_cast<const CntVector*>(r);
if (R->data_size_ != sizeof(T) * data.size() || R->hash_ != hash) {
return false;
}
for (td::uint32 i = 0; i < data.size(); i++) {
if (R->data_[i] != data[i]) {
return false;
}
}
return true;
}
static const CntVector* lookup(ValidatorSessionDescription& desc, std::vector<T>& value, HashType hash, bool temp) {
auto r = desc.get_by_hash(hash, temp);
if (compare(r, value, hash)) {
desc.on_reuse();
return static_cast<const CntVector*>(r);
}
return nullptr;
}
static const CntVector* lookup(ValidatorSessionDescription& desc, td::uint32 size, const T* data, HashType hash,
bool temp) {
auto r = desc.get_by_hash(hash, temp);
if (compare(r, size, data, hash)) {
desc.on_reuse();
return static_cast<const CntVector*>(r);
}
return nullptr;
}
static const CntVector* create(ValidatorSessionDescription& desc, std::vector<T> value) {
if (value.size() == 0) {
return nullptr;
}
auto hash = create_hash(desc, value);
auto r = lookup(desc, value, hash, true);
if (r) {
return r;
}
auto size = static_cast<td::uint32>(value.size());
auto data = static_cast<T*>(desc.alloc(sizeof(T) * size, 8, true));
for (td::uint32 i = 0; i < size; i++) {
data[i] = value[i];
}
return new (desc, true) CntVector{desc, size, data, hash};
}
static const CntVector* create(ValidatorSessionDescription& desc, td::uint32 size, const T* value) {
if (!size) {
return nullptr;
}
auto hash = create_hash(desc, size, value);
auto r = lookup(desc, size, value, hash, true);
if (r) {
return r;
}
return new (desc, true) CntVector{desc, size, value, hash};
}
static const CntVector* move_to_persistent(ValidatorSessionDescription& desc, const CntVector* b) {
if (desc.is_persistent(b)) {
return b;
}
std::vector<T> v;
v.resize(b->size());
for (td::uint32 i = 0; i < b->size(); i++) {
v[i] = ton::validatorsession::move_to_persistent(desc, b->data_[i]);
}
auto r = lookup(desc, v, b->hash_, false);
if (r) {
return r;
}
auto data = static_cast<T*>(desc.alloc(sizeof(T) * b->size(), 8, false));
for (td::uint32 i = 0; i < b->size(); i++) {
data[i] = v[i];
}
return new (desc, false) CntVector{desc, b->size(), data, b->hash_};
}
static const CntVector* merge(ValidatorSessionDescription& desc, const CntVector* l, const CntVector* r,
std::function<T(T, T)> merge_f, bool merge_all = false) {
if (!merge_all) {
if (!l) {
return r;
}
if (!r) {
return l;
}
if (l == r) {
return l;
}
}
auto sz = std::max(l->size(), r->size());
bool ret_left = true;
bool ret_right = true;
for (td::uint32 i = 0; i < sz; i++) {
if (i >= l->size()) {
ret_left = false;
break;
} else if (i >= r->size()) {
ret_right = false;
break;
} else if (l->at(i) != r->at(i)) {
if (l->at(i)) {
ret_right = false;
}
if (r->at(i)) {
ret_left = false;
}
}
}
if (!merge_all && ret_left) {
return l;
}
if (!merge_all && ret_right) {
return r;
}
auto v = static_cast<T*>(desc.alloc(sizeof(T) * sz, 8, true));
for (td::uint32 i = 0; i < sz; i++) {
if (i >= l->size()) {
if (!merge_all) {
v[i] = r->at(i);
} else {
v[i] = merge_f(r->at(i), r->at(i));
}
} else if (i >= r->size()) {
if (!merge_all) {
v[i] = l->at(i);
} else {
v[i] = merge_f(l->at(i), l->at(i));
}
} else {
v[i] = merge_f(l->at(i), r->at(i));
}
}
return create(desc, sz, v);
}
static const CntVector* modify(ValidatorSessionDescription& desc, const CntVector* l, std::function<T(T)> mod_f) {
if (!l) {
return l;
}
auto sz = l->size();
auto v = static_cast<T*>(desc.alloc(sizeof(T) * sz, 8, true));
for (td::uint32 i = 0; i < sz; i++) {
v[i] = mod_f(l->at(i));
}
return create(desc, sz, v);
}
static const CntVector* change(ValidatorSessionDescription& desc, const CntVector* l, td::uint32 idx, T value) {
auto sz = l->size();
auto v = static_cast<T*>(desc.alloc(sizeof(T) * sz, 8, true));
std::memcpy(v, l->data_, sizeof(T) * sz);
v[idx] = std::move(value);
return create(desc, sz, v);
}
static const CntVector* push(ValidatorSessionDescription& desc, const CntVector* l, td::uint32 idx, T value) {
td::uint32 sz = l ? l->size() : 0;
CHECK(idx == sz);
sz++;
auto v = static_cast<T*>(desc.alloc(sizeof(T) * sz, 8, true));
if (l) {
std::memcpy(v, l->data_, sizeof(T) * (sz - 1));
}
v[idx] = std::move(value);
return create(desc, sz, v);
}
CntVector(ValidatorSessionDescription& desc, td::uint32 data_size, const T* data, HashType hash)
: RootObject{sizeof(CntVector)}
, data_size_(static_cast<td::uint32>(data_size * sizeof(T)))
, data_(data)
, hash_(std::move(hash)) {
desc.update_hash(this, hash_);
}
td::uint32 size() const {
return static_cast<td::uint32>(data_size_ / sizeof(T));
}
auto data() const {
return data_;
}
auto get_hash(ValidatorSessionDescription& desc) const {
return hash_;
}
T at(td::uint32 idx) const {
CHECK(idx < size());
return data_[idx];
}
//const T& at(size_t idx) const;
private:
const td::uint32 data_size_;
const T* data_;
const HashType hash_;
};
template <>
class CntVector<bool> : public ValidatorSessionDescription::RootObject {
private:
static bool get_bit(const td::uint32* value, td::uint32 idx) {
return (value[idx / 32] & (1u << (idx % 32))) != 0;
}
static void set_bit(td::uint32* value, td::uint32 idx, bool v) {
if (v) {
value[idx / 32] |= (1u << (idx % 32));
} else {
value[idx / 32] &= ~static_cast<td::uint32>((1u << (idx % 32)));
}
}
public:
static HashType create_hash(ValidatorSessionDescription& desc, std::vector<bool>& value) {
CHECK(value.size() % 32 == 0);
auto b = new td::uint32[value.size() / 32];
for (td::uint32 i = 0; i < value.size(); i++) {
set_bit(b, i, value[i]);
}
auto hash = create_hash(desc, static_cast<td::uint32>(value.size()), b);
delete[] b;
return hash;
}
static HashType create_hash(ValidatorSessionDescription& desc, td::uint32 size, const td::uint32* value) {
return desc.compute_hash(td::Slice(reinterpret_cast<const td::uint8*>(value), size / 8));
}
static bool compare(const RootObject* r, td::uint32 size, const td::uint32* data, HashType hash) {
CHECK(size % 32 == 0);
if (!r || r->get_size() < sizeof(CntVector)) {
return false;
}
auto R = static_cast<const CntVector*>(r);
if (R->data_size_ != size / 8 || R->hash_ != hash) {
return false;
}
return std::memcmp(R->data_, data, size / 8) == 0;
}
static bool compare(const RootObject* r, const std::vector<bool>& data, HashType hash) {
CHECK(data.size() % 32 == 0);
if (!r || r->get_size() < sizeof(CntVector)) {
return false;
}
auto R = static_cast<const CntVector*>(r);
if (R->data_size_ != data.size() / 8 || R->hash_ != hash) {
return false;
}
for (td::uint32 i = 0; i < data.size(); i++) {
if (get_bit(R->data_, i) != data[i]) {
return false;
}
}
return true;
}
static const CntVector* lookup(ValidatorSessionDescription& desc, std::vector<bool>& value, HashType hash,
bool temp) {
CHECK(value.size() % 32 == 0);
auto r = desc.get_by_hash(hash, temp);
if (compare(r, value, hash)) {
desc.on_reuse();
return static_cast<const CntVector*>(r);
}
return nullptr;
}
static const CntVector* lookup(ValidatorSessionDescription& desc, td::uint32 size, const td::uint32* data,
HashType hash, bool temp) {
CHECK(size % 32 == 0);
auto r = desc.get_by_hash(hash, temp);
if (compare(r, size, data, hash)) {
desc.on_reuse();
return static_cast<const CntVector*>(r);
}
return nullptr;
}
static const CntVector* create(ValidatorSessionDescription& desc, std::vector<bool> value) {
if (value.size() == 0) {
return nullptr;
}
if (value.size() % 32) {
auto new_size = value.size() - value.size() % 32 + 32;
value.resize(new_size, false);
}
auto hash = create_hash(desc, value);
auto r = lookup(desc, value, hash, true);
if (r) {
return r;
}
auto size = static_cast<td::uint32>(value.size());
auto data = static_cast<td::uint32*>(desc.alloc(sizeof(td::uint32) * size / 32, 8, true));
for (td::uint32 i = 0; i < size; i++) {
set_bit(data, i, value[i]);
}
return new (desc, true) CntVector{desc, size, data, hash};
}
static const CntVector* create(ValidatorSessionDescription& desc, td::uint32 size, const td::uint32* value) {
if (!size) {
return nullptr;
}
CHECK(size % 32 == 0);
auto hash = create_hash(desc, size, value);
auto r = lookup(desc, size, value, hash, true);
if (r) {
return r;
}
return new (desc, true) CntVector{desc, size, value, hash};
}
static const CntVector* move_to_persistent(ValidatorSessionDescription& desc, const CntVector* b) {
if (desc.is_persistent(b)) {
return b;
}
auto r = lookup(desc, b->max_size(), b->data_, b->hash_, false);
if (r) {
return r;
}
auto data = static_cast<td::uint32*>(desc.alloc(b->data_size_, 8, false));
std::memcpy(data, b->data_, b->data_size_);
return new (desc, false) CntVector{desc, b->max_size(), data, b->hash_};
}
static const CntVector* merge(ValidatorSessionDescription& desc, const CntVector* l, const CntVector* r) {
if (!l) {
return r;
}
if (!r) {
return l;
}
if (l == r) {
return l;
}
CHECK(l->max_size() == r->max_size());
auto sz = l->max_size() / 32;
bool ret_left = true;
bool ret_right = true;
for (td::uint32 i = 0; i < sz; i++) {
if (l->data_[i] & ~r->data_[i]) {
ret_right = false;
}
if (r->data_[i] & ~l->data_[i]) {
ret_left = false;
}
}
if (ret_left) {
return l;
}
if (ret_right) {
return r;
}
auto v = static_cast<td::uint32*>(desc.alloc(sz * 4, 8, true));
for (td::uint32 i = 0; i < sz; i++) {
v[i] = l->data_[i] | r->data_[i];
}
return create(desc, sz * 32, v);
}
static const CntVector* merge(ValidatorSessionDescription& desc, const CntVector* l, const CntVector* r,
std::function<bool(bool, bool)> merge_f) {
if (!l) {
return r;
}
if (!r) {
return l;
}
if (l == r) {
return l;
}
auto sz = std::max(l->max_size(), r->max_size());
auto v = static_cast<td::uint32*>(desc.alloc(sz / 8, 8, true));
std::memset(v, 0, sz / 8);
for (td::uint32 i = 0; i < sz; i++) {
if (i >= l->max_size()) {
set_bit(v, i, r->at(i));
} else if (i >= r->max_size()) {
set_bit(v, i, l->at(i));
} else {
set_bit(v, i, merge_f(l->at(i), r->at(i)));
}
}
return create(desc, sz, v);
}
static const CntVector* change(ValidatorSessionDescription& desc, const CntVector* l, td::uint32 idx, bool value) {
if (l->at(idx) == value) {
return l;
}
auto sz = l->max_size();
auto v = static_cast<td::uint32*>(desc.alloc(sz / 8, 8, true));
std::memcpy(v, l->data_, l->data_size_);
set_bit(v, idx, value);
return create(desc, sz, v);
}
CntVector(ValidatorSessionDescription& desc, td::uint32 data_size, const td::uint32* data, HashType hash)
: RootObject{sizeof(CntVector)}
, data_size_(static_cast<td::uint32>(data_size / 8))
, data_(data)
, hash_(std::move(hash)) {
desc.update_hash(this, hash_);
CHECK(data_size % 32 == 0);
}
td::uint32 max_size() const {
return data_size_ * 8;
}
auto data() const {
return data_;
}
auto get_hash(ValidatorSessionDescription& desc) const {
return hash_;
}
bool at(td::uint32 idx) const {
CHECK(idx < max_size());
return get_bit(data_, idx);
}
//const T& at(size_t idx) const;
private:
const td::uint32 data_size_;
const td::uint32* data_;
const HashType hash_;
};
template <typename T, typename Compare = std::less<T>>
class CntSortedVector : public ValidatorSessionDescription::RootObject {
public:
static HashType create_hash(ValidatorSessionDescription& desc, std::vector<T>& value) {
auto obj = create_tl_object<ton_api::hashable_cntSortedVector>(get_vs_hash(desc, value));
return desc.compute_hash(serialize_tl_object(obj, true).as_slice());
}
static HashType create_hash(ValidatorSessionDescription& desc, td::uint32 size, const T* value) {
auto obj = create_tl_object<ton_api::hashable_cntSortedVector>(get_vs_hash(desc, size, value));
return desc.compute_hash(serialize_tl_object(obj, true).as_slice());
}
static bool compare(const RootObject* r, td::uint32 size, const T* data, HashType hash) {
if (!r || r->get_size() < sizeof(CntSortedVector)) {
return false;
}
auto R = static_cast<const CntSortedVector*>(r);
if (R->data_size_ != size * sizeof(T) || R->hash_ != hash) {
return false;
}
for (td::uint32 i = 0; i < size; i++) {
if (R->data_[i] != data[i]) {
return false;
}
}
return true;
}
static bool compare(const RootObject* r, const std::vector<T>& data, HashType hash) {
if (!r || r->get_size() < sizeof(CntSortedVector)) {
return false;
}
auto R = static_cast<const CntSortedVector*>(r);
if (R->data_size_ != data.size() * sizeof(T) || R->hash_ != hash) {
return false;
}
for (td::uint32 i = 0; i < data.size(); i++) {
if (R->data_[i] != data[i]) {
return false;
}
}
return true;
}
static const CntSortedVector* lookup(ValidatorSessionDescription& desc, std::vector<T>& value, HashType hash,
bool temp) {
auto r = desc.get_by_hash(hash, temp);
if (compare(r, value, hash)) {
desc.on_reuse();
return static_cast<const CntSortedVector*>(r);
}
return nullptr;
}
static const CntSortedVector* lookup(ValidatorSessionDescription& desc, td::uint32 size, const T* data, HashType hash,
bool temp) {
auto r = desc.get_by_hash(hash, temp);
if (compare(r, size, data, hash)) {
desc.on_reuse();
return static_cast<const CntSortedVector*>(r);
}
return nullptr;
}
static const CntSortedVector* create(ValidatorSessionDescription& desc, std::vector<T> value) {
if (value.size() == 0) {
return nullptr;
}
auto hash = create_hash(desc, value);
auto r = lookup(desc, value, hash, true);
if (r) {
return r;
}
auto data_size = static_cast<td::uint32>(value.size());
auto data = static_cast<T*>(desc.alloc(sizeof(T) * data_size, 8, true));
for (td::uint32 i = 0; i < data_size; i++) {
data[i] = value[i];
}
return new (desc, true) CntSortedVector{desc, data_size, data, hash};
}
static const CntSortedVector* create(ValidatorSessionDescription& desc, td::uint32 size, const T* value) {
if (size == 0) {
return nullptr;
}
auto hash = create_hash(desc, size, value);
auto r = lookup(desc, size, value, hash, true);
if (r) {
return r;
}
return new (desc, true) CntSortedVector{desc, size, value, hash};
}
static const CntSortedVector* move_to_persistent(ValidatorSessionDescription& desc, const CntSortedVector* b) {
if (desc.is_persistent(b)) {
return b;
}
std::vector<T> v;
v.resize(b->size());
for (td::uint32 i = 0; i < v.size(); i++) {
v[i] = ton::validatorsession::move_to_persistent(desc, b->data_[i]);
}
auto r = lookup(desc, v, b->hash_, false);
if (r) {
return r;
}
auto data = static_cast<T*>(desc.alloc(sizeof(T) * v.size(), 8, false));
for (td::uint32 i = 0; i < v.size(); i++) {
data[i] = v[i];
}
return new (desc, false) CntSortedVector{desc, b->size(), data, b->hash_};
}
static const CntSortedVector* merge(ValidatorSessionDescription& desc, const CntSortedVector* l,
const CntSortedVector* r, std::function<T(T, T)> merge_f) {
if (!l) {
return r;
}
if (!r) {
return l;
}
if (l == r) {
return l;
}
bool ret_left = true;
bool ret_right = true;
const T* li = l->data_;
const T* ri = r->data_;
td::uint32 lp = 0;
td::uint32 rp = 0;
while (lp < l->size() || rp < r->size()) {
if (lp == l->size()) {
ret_left = false;
break;
} else if (rp == r->size()) {
ret_right = false;
break;
} else {
if (Compare()(li[lp], ri[rp])) {
ret_right = false;
lp++;
} else if (Compare()(ri[rp], li[lp])) {
ret_left = false;
rp++;
} else {
if (li[lp++] != ri[rp++]) {
ret_left = false;
ret_right = false;
break;
}
}
}
}
if (ret_left) {
return l;
}
if (ret_right) {
return r;
}
std::vector<T> v;
lp = 0;
rp = 0;
while (lp < l->size() || rp < r->size()) {
if (lp == l->size()) {
v.push_back(ri[rp++]);
} else if (rp == r->size()) {
v.push_back(li[lp++]);
} else {
if (Compare()(li[lp], ri[rp])) {
v.push_back(li[lp++]);
} else if (Compare()(ri[rp], li[lp])) {
v.push_back(ri[rp++]);
} else {
v.push_back(merge_f(li[lp++], ri[rp++]));
}
}
}
return CntSortedVector::create(desc, std::move(v));
}
/*static const CntSortedVector* merge(ValidatorSessionDescription& desc, const CntSortedVector* l,
const CntSortedVector* r) {
return merge(desc, l, r, [](T l, T r) { return l; });
}*/
static const CntSortedVector* push(ValidatorSessionDescription& desc, const CntSortedVector* v, T value) {
if (!v) {
return create(desc, std::vector<T>{value});
}
T* res = nullptr;
td::uint32 res_size = 0;
td::int32 l = -1;
td::int32 r = v->size();
bool found = false;
while (r - l > 1) {
auto x = (r + l) / 2;
if (Compare()(v->at(x), value)) {
l = x;
} else if (Compare()(value, v->at(x))) {
r = x;
} else {
if (v->at(x) == value) {
return v;
}
res = static_cast<T*>(desc.alloc(sizeof(T) * v->size(), 8, true));
std::memcpy(res, v->data(), sizeof(T) * v->size());
res[x] = value;
res_size = v->size();
found = true;
break;
}
}
if (!found) {
res = static_cast<T*>(desc.alloc(sizeof(T) * (v->size() + 1), 8, true));
res_size = v->size() + 1;
std::memcpy(res, v->data(), sizeof(T) * r);
res[r] = value;
std::memcpy(res + r + 1, v->data() + r, sizeof(T) * (v->size() - r));
}
return CntSortedVector::create(desc, res_size, res);
}
CntSortedVector(ValidatorSessionDescription& desc, td::uint32 data_size, const T* data, HashType hash)
: RootObject{sizeof(CntSortedVector)}
, data_size_(static_cast<td::uint32>(data_size * sizeof(T)))
, data_(data)
, hash_(std::move(hash)) {
desc.update_hash(this, hash_);
}
td::uint32 size() const {
return static_cast<td::int32>(data_size_ / sizeof(T));
}
auto data() const {
return data_;
}
auto get_hash(ValidatorSessionDescription& desc) const {
return hash_;
}
T at(td::uint32 idx) const {
CHECK(idx < size());
return data_[idx];
}
//const T& at(size_t idx) const;
private:
const td::uint32 data_size_;
const T* data_;
const HashType hash_;
};
} // namespace validatorsession
} // namespace ton