/* 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 . Copyright 2017-2020 Telegram Systems LLP */ #include "signature-set.hpp" #include "auto/tl/ton_api.hpp" #include "adnl/utils.hpp" #include "vm/dict.h" #include "vm/boc.h" namespace ton { namespace validator { using td::Ref; BlockSignatureSetQ *BlockSignatureSetQ::make_copy() const { std::vector vec; auto &sigs = signatures(); for (auto &s : sigs) { vec.emplace_back(BlockSignature{s.node, s.signature.clone()}); } return new BlockSignatureSetQ{std::move(vec)}; } td::BufferSlice BlockSignatureSetQ::serialize() const { if (!signatures().size()) { return {}; } Ref root; CHECK(serialize_to(root)); //std::cerr << "serializing BlockSignatureSet: "; //vm::CellSlice{vm::NoVm{}, root}.print_rec(std::cerr); //std::cerr << std::endl; auto res = vm::std_boc_serialize(std::move(root)); LOG_CHECK(res.is_ok()) << res.move_as_error(); return res.move_as_ok(); } bool BlockSignatureSetQ::serialize_to(Ref &ref) const { auto &sigs = signatures(); vm::Dictionary dict{16}; // HashmapE 16 CryptoSignaturePair for (unsigned i = 0; i < sigs.size(); i++) { vm::CellBuilder cb; if (!(cb.store_bits_bool(sigs[i].node) // sig_pair$_ node_id_short:bits256 && cb.store_long_bool(5, 4) // ed25519_signature#5 && sigs[i].signature.size() == 64 // signature must be 64 bytes long && cb.store_bytes_bool(sigs[i].signature.data(), 64) // R:bits256 s:bits256 && dict.set_builder(td::BitArray<16>{i}, cb, vm::Dictionary::SetMode::Add))) { return false; } } ref = std::move(dict).extract_root_cell(); CHECK(sigs.size()); CHECK(ref.not_null()); return true; } Ref BlockSignatureSetQ::fetch(td::BufferSlice data) { if (!data.size()) { return Ref{true, std::vector{}}; } auto res = vm::std_boc_deserialize(std::move(data)); if (res.is_error()) { return {}; } return fetch(res.move_as_ok()); } Ref BlockSignatureSetQ::fetch(Ref cell) { if (cell.is_null()) { return {}; } try { std::vector vec; vm::Dictionary dict{std::move(cell), 16}; // HashmapE 16 CryptoSignaturePair unsigned i = 0; if (!dict.check_for_each([&](Ref cs_ref, td::ConstBitPtr key, int n) -> bool { if (key.get_int(n) != i || cs_ref->size_ext() != 256 + 4 + 256 + 256) { return false; } vm::CellSlice cs{*cs_ref}; NodeIdShort node_id; unsigned char signature[64]; if (!(cs.fetch_bits_to(node_id) // sig_pair$_ node_id_short:bits256 && cs.fetch_ulong(4) == 5 // ed25519_signature#5 && cs.fetch_bytes(signature, 64) // R:bits256 s:bits256 && !cs.size_ext())) { return false; } vec.emplace_back(BlockSignature{node_id, td::BufferSlice{td::Slice{signature, 64}}}); ++i; return i <= max_signatures; })) { return {}; } return Ref{true, std::move(vec)}; } catch (vm::VmError) { return {}; } } } // namespace validator } // namespace ton