From 8cb919a3916876d43861663949c12ad8fcb94f31 Mon Sep 17 00:00:00 2001 From: trinitil Date: Wed, 29 Jan 2025 12:02:08 +0400 Subject: [PATCH] add simple block manipulator as example --- CMakeLists.txt | 1 + test/fisherman/block_manipulator/base.hpp | 12 ++++++ test/fisherman/block_manipulator/factory.cpp | 29 ++++++++++++- test/fisherman/block_manipulator/factory.hpp | 16 +++++++ .../block_manipulator/header_corrupter.cpp | 21 +++++++++ .../block_manipulator/header_corrupter.hpp | 23 ++++++++++ test/fisherman/tests.cpp | 43 +++++++++++-------- 7 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 test/fisherman/block_manipulator/factory.hpp create mode 100644 test/fisherman/block_manipulator/header_corrupter.cpp create mode 100644 test/fisherman/block_manipulator/header_corrupter.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e0388fa..18bc0157 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -557,6 +557,7 @@ target_link_libraries(test-emulator PRIVATE emulator) add_executable(test-fisherman test/fisherman/tests.cpp + test/fisherman/block_manipulator/header_corrupter.cpp test/fisherman/block_manipulator/factory.cpp test/fisherman/block_reader.cpp test/fisherman/utils.cpp diff --git a/test/fisherman/block_manipulator/base.hpp b/test/fisherman/block_manipulator/base.hpp index 6f70f09b..c65f581e 100644 --- a/test/fisherman/block_manipulator/base.hpp +++ b/test/fisherman/block_manipulator/base.hpp @@ -1 +1,13 @@ #pragma once + +#include "crypto/block/block-auto.h" + +namespace test::fisherman { + +class BaseManipulator { + public: + virtual void modify(block::gen::Block::Record &block) = 0; + virtual ~BaseManipulator() = default; +}; + +} // namespace test::fisherman diff --git a/test/fisherman/block_manipulator/factory.cpp b/test/fisherman/block_manipulator/factory.cpp index 6b58ff92..17a49f32 100644 --- a/test/fisherman/block_manipulator/factory.cpp +++ b/test/fisherman/block_manipulator/factory.cpp @@ -1 +1,28 @@ -#include "base.hpp" +#include "factory.hpp" + +#include "header_corrupter.hpp" + +namespace test::fisherman { + +auto ManipulatorFactory::create(td::JsonValue jv) -> std::shared_ptr { + auto res = createImpl(std::move(jv)); + if (res.is_error()) { + throw std::runtime_error("Error while creating manipulator: " + res.error().message().str()); + } + return res.move_as_ok(); +} + +auto ManipulatorFactory::createImpl(td::JsonValue jv) -> td::Result> { + CHECK(jv.type() == td::JsonValue::Type::Object); + + auto &obj = jv.get_object(); + TRY_RESULT(type, td::get_json_object_string_field(obj, "type", false)); + TRY_RESULT(json_config, td::get_json_object_field(obj, "config", td::JsonValue::Type::Object, false)); + + if (type == "HeaderCorrupter") { + return std::make_shared(HeaderCorrupter::Config::fromJson(std::move(json_config))); + } + return td::Status::Error(400, PSLICE() << "Unknown manipulator type: " << type); +} + +} // namespace test::fisherman diff --git a/test/fisherman/block_manipulator/factory.hpp b/test/fisherman/block_manipulator/factory.hpp new file mode 100644 index 00000000..91256162 --- /dev/null +++ b/test/fisherman/block_manipulator/factory.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "base.hpp" +#include "td/utils/JsonBuilder.h" + +namespace test::fisherman { + +class ManipulatorFactory { + public: + auto create(td::JsonValue jv) -> std::shared_ptr; + + private: + auto createImpl(td::JsonValue jv) -> td::Result>; +}; + +} // namespace test::fisherman diff --git a/test/fisherman/block_manipulator/header_corrupter.cpp b/test/fisherman/block_manipulator/header_corrupter.cpp new file mode 100644 index 00000000..f019d070 --- /dev/null +++ b/test/fisherman/block_manipulator/header_corrupter.cpp @@ -0,0 +1,21 @@ +#include "header_corrupter.hpp" + +namespace test::fisherman { + +auto HeaderCorrupter::Config::fromJson(td::JsonValue jv) -> Config { + return Config{}; +} + +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); +} + +} // namespace test::fisherman diff --git a/test/fisherman/block_manipulator/header_corrupter.hpp b/test/fisherman/block_manipulator/header_corrupter.hpp new file mode 100644 index 00000000..1fe0f4a6 --- /dev/null +++ b/test/fisherman/block_manipulator/header_corrupter.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "base.hpp" +#include "td/utils/JsonBuilder.h" + +namespace test::fisherman { + +class HeaderCorrupter : public BaseManipulator { + public: + struct Config { + // TODO: add corruption field and method + + static auto fromJson(td::JsonValue jv) -> Config; + }; + + explicit HeaderCorrupter(Config config); + void modify(block::gen::Block::Record &block) final; + + private: + Config config_; +}; + +} // namespace test::fisherman diff --git a/test/fisherman/tests.cpp b/test/fisherman/tests.cpp index f412e85d..4a7249c9 100644 --- a/test/fisherman/tests.cpp +++ b/test/fisherman/tests.cpp @@ -1,6 +1,7 @@ #include "block_reader.hpp" #include "crypto/block/block-auto.h" +#include "block_manipulator/factory.hpp" #include "utils.hpp" using namespace test::fisherman; @@ -30,42 +31,50 @@ auto main(int argc, char **argv) -> int { return 1; } - auto block_id_res = parse_block_id_from_json(decode_result.move_as_ok()); - if (block_id_res.is_error()) { - std::cerr << "Error extracting BlockIdExt: " << block_id_res.error().message().str() << std::endl; + auto js = decode_result.move_as_ok(); + auto &js_obj = js.get_object(); + auto blk_id_obj_res = td::get_json_object_field(js_obj, "block_id", td::JsonValue::Type::Object, false); + CHECK(blk_id_obj_res.is_ok()); + auto blk_id_res = parse_block_id_from_json(blk_id_obj_res.move_as_ok()); + if (blk_id_res.is_error()) { + std::cerr << "Error extracting BlockIdExt: " << blk_id_res.error().message().str() << std::endl; return 1; } - ton::BlockIdExt block_id = block_id_res.move_as_ok(); + ton::BlockIdExt blk_id = blk_id_res.move_as_ok(); BlockDataLoader loader(db_path); - auto block_data_result = loader.load_block_data(block_id); - if (block_data_result.is_error()) { - std::cerr << "Error loading block data: " << block_data_result.error().message().str() << std::endl; + auto blk_data_result = loader.load_block_data(blk_id); + if (blk_data_result.is_error()) { + std::cerr << "Error loading block data: " << blk_data_result.error().message().str() << std::endl; return 1; } - auto block_data = block_data_result.move_as_ok(); - LOG(INFO) << "BlockId: " << block_data->block_id().to_str(); - LOG(INFO) << "Block data size: " << block_data->data().size() << " bytes"; + 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, block_data->root_cell()) << "\n"; + 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, block_data->root_cell()); + 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(block_data->root_cell(), block_rec); + bool ok = block::gen::Block().cell_unpack(blk_data->root_cell(), block_rec); CHECK(ok); block::gen::BlockInfo::Record info_rec; block::gen::BlockInfo().cell_unpack(block_rec.info, info_rec); - LOG(INFO) << "start_lt = " << info_rec.start_lt << ", end_lt = " << info_rec.end_lt; + LOG(INFO) << "Block.info after_merge=" << info_rec.after_merge << ", after_split=" << info_rec.after_split; - block::gen::ShardIdent::Record shard_rec; - block::gen::ShardIdent().unpack(info_rec.shard.write(), shard_rec); - LOG(INFO) << "workchain_id = " << shard_rec.workchain_id; + 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; return 0; }