1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

Add more headers corruption options

This commit is contained in:
trinitil 2025-02-02 19:40:12 +04:00
parent ed10909dcd
commit 833ef0a4f9
3 changed files with 132 additions and 26 deletions

View file

@ -1,9 +1,34 @@
#include "header_corrupter.hpp"
#include "block/block-parse.h"
#include "block/block-auto.h"
namespace test::fisherman {
auto HeaderCorrupter::Config::fromJson(td::JsonValue jv) -> Config {
return Config{};
HeaderCorrupter::Config HeaderCorrupter::Config::fromJson(td::JsonValue jv) {
Config cfg;
CHECK(jv.type() == td::JsonValue::Type::Object);
auto &obj = jv.get_object();
cfg.distort_timestamp = td::get_json_object_bool_field(obj, "distort_timestamp", true, false).move_as_ok();
cfg.time_offset = td::get_json_object_int_field(obj, "time_offset", true, 999999999).move_as_ok();
cfg.mark_subshard_of_master =
td::get_json_object_bool_field(obj, "mark_subshard_of_master", true, false).move_as_ok();
cfg.invert_lt = td::get_json_object_bool_field(obj, "invert_lt", true, false).move_as_ok();
cfg.mark_keyblock_on_shard = td::get_json_object_bool_field(obj, "mark_keyblock_on_shard", true, false).move_as_ok();
cfg.force_after_merge_for_mc = td::get_json_object_bool_field(obj, "force_after_merge_for_mc", true, false).move_as_ok();
cfg.force_before_split_for_mc = td::get_json_object_bool_field(obj, "force_before_split_for_mc", true, false).move_as_ok();
cfg.force_after_split_for_mc = td::get_json_object_bool_field(obj, "force_after_split_for_mc", true, false).move_as_ok();
cfg.allow_both_after_merge_and_split =
td::get_json_object_bool_field(obj, "allow_both_after_merge_and_split", true, false).move_as_ok();
cfg.shard_pfx_zero_yet_after_split =
td::get_json_object_bool_field(obj, "shard_pfx_zero_yet_after_split", true, false).move_as_ok();
cfg.set_vert_seqno_incr = td::get_json_object_bool_field(obj, "set_vert_seqno_incr", true, false).move_as_ok();
return cfg;
}
HeaderCorrupter::HeaderCorrupter(Config config) : config_(std::move(config)) {
@ -11,11 +36,81 @@ HeaderCorrupter::HeaderCorrupter(Config config) : config_(std::move(config)) {
void HeaderCorrupter::modify(block::gen::Block::Record &block) {
block::gen::BlockInfo::Record info_rec;
bool ok = block::gen::BlockInfo().cell_unpack(block.info, info_rec);
CHECK(ok);
info_rec.after_merge = true;
info_rec.after_split = true;
block::gen::BlockInfo().cell_pack(block.info, info_rec);
CHECK(block::gen::t_BlockInfo.cell_unpack(block.info, info_rec));
// 1) distort_timestamp => сдвигаем info_rec.gen_utime
if (config_.distort_timestamp) {
info_rec.gen_utime += config_.time_offset;
}
// 2) mark_subshard_of_master => если workchain == -1, делаем shard_pfx_bits != 0, то есть блок "подшард" MC
if (config_.mark_subshard_of_master) {
block::gen::ShardIdent::Record shard_rec;
CHECK(block::gen::ShardIdent().unpack(info_rec.shard.write(), shard_rec));
CHECK(shard_rec.workchain_id == -1 && !info_rec.not_master);
if (shard_rec.shard_pfx_bits == 0) {
shard_rec.shard_pfx_bits = 10;
shard_rec.shard_prefix = 123456ULL;
}
vm::CellBuilder cb;
CHECK(block::gen::t_ShardIdent.pack(cb, shard_rec));
info_rec.shard = td::Ref<vm::CellSlice>{true, cb.finalize()};
}
// 3) invert_lt => start_lt >= end_lt
if (config_.invert_lt) {
if (info_rec.start_lt < info_rec.end_lt) {
auto tmp = info_rec.start_lt;
info_rec.start_lt = info_rec.end_lt;
info_rec.end_lt = tmp;
}
}
// 4) mark_keyblock_on_shard => если "not_master" = true, то проставим key_block = true
if (config_.mark_keyblock_on_shard) {
CHECK(info_rec.not_master);
info_rec.key_block = true;
}
// 5) force_after_merge / force_before_split / force_after_split для MC
if (config_.force_after_merge_for_mc) {
CHECK(!info_rec.not_master);
info_rec.after_merge = true;
}
if (config_.force_before_split_for_mc) {
CHECK(!info_rec.not_master);
info_rec.before_split = true;
}
if (config_.force_after_split_for_mc) {
CHECK(!info_rec.not_master);
info_rec.after_split = true;
}
// 6) allow_both_after_merge_and_split => ставим after_merge=1 и after_split=1
if (config_.allow_both_after_merge_and_split) {
info_rec.after_merge = true;
info_rec.after_split = true;
}
// 7) shard_pfx_zero_yet_after_split => shard_pfx_bits=0, after_split=1
if (config_.shard_pfx_zero_yet_after_split) {
info_rec.after_split = true;
block::gen::ShardIdent::Record shard_rec;
CHECK(block::gen::ShardIdent().unpack(info_rec.shard.write(), shard_rec));
shard_rec.shard_pfx_bits = 0;
vm::CellBuilder cb;
CHECK(block::gen::t_ShardIdent.pack(cb, shard_rec));
info_rec.shard = td::Ref<vm::CellSlice>{true, cb.finalize()};
}
// 8) set_vert_seqno_incr => vert_seqno_incr != 0 => ставим true
if (config_.set_vert_seqno_incr) {
info_rec.vert_seq_no = 1;
info_rec.vert_seqno_incr = true;
info_rec.prev_vert_ref = info_rec.prev_ref;
}
CHECK(block::gen::t_BlockInfo.cell_pack(block.info, info_rec));
}
} // namespace test::fisherman

View file

@ -1,20 +1,36 @@
#pragma once
#include "base.hpp"
#include "td/utils/JsonBuilder.h"
#include "block/block-auto.h"
namespace test::fisherman {
class HeaderCorrupter : public BaseManipulator {
public:
struct Config {
// TODO: add corruption field and method
bool distort_timestamp = false;
td::int32 time_offset = 1'000'000'000;
static auto fromJson(td::JsonValue jv) -> Config;
bool mark_subshard_of_master = false;
bool invert_lt = false;
bool mark_keyblock_on_shard = false;
bool force_after_merge_for_mc = false;
bool force_before_split_for_mc = false;
bool force_after_split_for_mc = false;
bool allow_both_after_merge_and_split = false;
bool shard_pfx_zero_yet_after_split = false;
bool set_vert_seqno_incr = false;
static Config fromJson(td::JsonValue jv);
};
explicit HeaderCorrupter(Config config);
void modify(block::gen::Block::Record &block) final;
void modify(block::gen::Block::Record &block) override;
private:
Config config_;

View file

@ -6,6 +6,14 @@
using namespace test::fisherman;
void print_block(const block::gen::Block::Record &block_rec) {
std::ostringstream os;
td::Ref<vm::Cell> block_cell_pack;
CHECK(block::gen::t_Block.cell_pack(block_cell_pack, block_rec));
block::gen::t_Block.print_ref(os, block_cell_pack);
LOG(INFO) << "Block = " << os.str();
}
auto main(int argc, char **argv) -> int {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " /path/to/rootdb config.json\n";
@ -51,30 +59,17 @@ auto main(int argc, char **argv) -> int {
}
auto blk_data = blk_data_result.move_as_ok();
LOG(INFO) << "BlockId: " << blk_data->block_id().to_str();
LOG(INFO) << "Block data size: " << blk_data->data().size() << " bytes";
LOG(INFO) << "Cell has block record = " << block::gen::Block().validate_ref(10000000, blk_data->root_cell()) << "\n";
std::ostringstream os;
block::gen::Block().print_ref(os, blk_data->root_cell());
LOG(INFO) << "Block = " << os.str();
block::gen::Block::Record block_rec;
bool ok = block::gen::Block().cell_unpack(blk_data->root_cell(), block_rec);
CHECK(ok);
CHECK(block::gen::t_Block.cell_unpack(blk_data->root_cell(), block_rec));
block::gen::BlockInfo::Record info_rec;
block::gen::BlockInfo().cell_unpack(block_rec.info, info_rec);
LOG(INFO) << "Block.info after_merge=" << info_rec.after_merge << ", after_split=" << info_rec.after_split;
print_block(block_rec);
auto manipulation_config = td::get_json_object_field(js_obj, "manipulation", td::JsonValue::Type::Object, false);
CHECK(manipulation_config.is_ok());
ManipulatorFactory().create(manipulation_config.move_as_ok())->modify(block_rec);
LOG(INFO) << "Block after manipulation:";
block::gen::BlockInfo().cell_unpack(block_rec.info, info_rec);
LOG(INFO) << "Block.info after_merge=" << info_rec.after_merge << ", after_split=" << info_rec.after_split;
print_block(block_rec);
return 0;
}