mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			118 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
	
		
			4 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-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<BlockSignature> 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<vm::Cell> 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<vm::Cell> &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<BlockSignatureSet> BlockSignatureSetQ::fetch(td::BufferSlice data) {
 | 
						|
  if (!data.size()) {
 | 
						|
    return Ref<BlockSignatureSetQ>{true, std::vector<BlockSignature>{}};
 | 
						|
  }
 | 
						|
  auto res = vm::std_boc_deserialize(std::move(data));
 | 
						|
  if (res.is_error()) {
 | 
						|
    return {};
 | 
						|
  }
 | 
						|
  return fetch(res.move_as_ok());
 | 
						|
}
 | 
						|
 | 
						|
Ref<BlockSignatureSet> BlockSignatureSetQ::fetch(Ref<vm::Cell> cell) {
 | 
						|
  if (cell.is_null()) {
 | 
						|
    return {};
 | 
						|
  }
 | 
						|
  try {
 | 
						|
    std::vector<BlockSignature> vec;
 | 
						|
    vm::Dictionary dict{std::move(cell), 16};  // HashmapE 16 CryptoSignaturePair
 | 
						|
    unsigned i = 0;
 | 
						|
    if (!dict.check_for_each([&](Ref<vm::CellSlice> 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<BlockSignatureSetQ>{true, std::move(vec)};
 | 
						|
  } catch (vm::VmError) {
 | 
						|
    return {};
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace validator
 | 
						|
 | 
						|
}  // namespace ton
 |