void serialize(BlockTemplate& block, ISerializer& serializer) {
  serializeBlockHeader(block, serializer);

  if (block.majorVersion >= BLOCK_MAJOR_VERSION_2) {
    auto parentBlockSerializer = makeParentBlockSerializer(block, false, false);
    serializer(parentBlockSerializer, "parent_block");
  }

  serializer(block.baseTransaction, "miner_tx");
  serializer(block.transactionHashes, "tx_hashes");
}
bool get_block_hash(const Block& b, crypto::hash& res) {
  blobdata blob;
  if (!get_block_hashing_blob(b, blob)) {
    return false;
  }

  if (BLOCK_MAJOR_VERSION_2 <= b.majorVersion) {
    blobdata parent_blob;
    auto serializer = makeParentBlockSerializer(b, true, false);
    if (!t_serializable_object_to_blob(serializer, parent_blob))
      return false;

    blob.append(parent_blob);
  }

  return get_object_hash(blob, res);
}
bool get_block_hash(const Block& b, Hash& res) {
  BinaryArray ba;
  if (!get_block_hashing_blob(b, ba)) {
    return false;
  }

  // The header of block version 1 differs from headers of blocks starting from v.2
  if (BLOCK_MAJOR_VERSION_2 == b.majorVersion || BLOCK_MAJOR_VERSION_3 == b.majorVersion) {
    BinaryArray parent_blob;
    auto serializer = makeParentBlockSerializer(b, true, false);
    if (!toBinaryArray(serializer, parent_blob))
      return false;

    ba.insert(ba.end(), parent_blob.begin(), parent_blob.end());
  }

  return getObjectHash(ba, res);
}
bool get_parent_block_hashing_blob(const Block& b, BinaryArray& blob) {
  auto serializer = makeParentBlockSerializer(b, true, true);
  return toBinaryArray(serializer, blob);
}
bool get_parent_block_hashing_blob(const Block& b, blobdata& blob) {
  auto serializer = makeParentBlockSerializer(b, true, true);
  return t_serializable_object_to_blob(serializer, blob);
}