Skip to main content
Improvado
Международный агрегатор рекламных кампаний
60 млн $
капитализация
22 млн $
инвестиции в серии А
Создаем стартапы на блокчейне Cardano с использованием платформы Plutus, написанной на Haskell
Узнать больше

Как работает технология zero knowledge proofs: обзор блокчейна zkSync

zero knowledge proofs

В этой статье я расскажу что такое zero knowledge proofs технология, а также про достаточно хайповый блокчейн — zkSync. Как работают транзакции в zkSync и основные отличия от обычной EVM, а также плюсы и минусы этого блокчейна, за которым, по нашему мнению, может быть будущее.

ZkSync — это блокчейн второго уровня (Layer 2 - L2) для Ethereum, разработанный для устранения проблем высоких комиссий и ограниченной пропускной способности (Transaction Per Second - TPS) в сети Ethereum. Эта платформа применяет технологию ZK-Rollups, которая использует доказательства с нулевым разглашением (Zero-Knowledge Proofs - ZKP) для объединения множества транзакций вне основной сети (L1). В L1 отправляются только криптографические доказательства верности транзакций и их сжатые данные, значительно повышая эффективность и снижая затраты.

Разработанный Matter Labs, zkSync заявлен как полностью открытый (100% open source) продукт, управляемый сообществом. Согласно Cryptorank, проект уже привлек внимание, собрав инвестиции на сумму 458 миллионов долларов. В долгосрочной перспективе Matter Labs стремится создать обширную экосистему. На текущий момент в эксплуатации находятся два блокчейна: zkSync Lite, который обрабатывает платежи в ETH и ERC20-токенах, и zkSync Era, поддерживающий полноценные смарт-контракты. Будущие планы включают запуск системы гиперчейнов (L3), обеспечивающих высокую безопасность. Цель Matter Labs – масштабировать технологию до уровня, который позволит привлечь следующий миллиард пользователей блокчейна.

Предпосылки

ZkSync представляет собой новый подход к решению проблемы масштабирования, известной как трилемма блокчейна. Этот проект, как и другие решения второго уровня (L2), направлен на поиск баланса между безопасностью, масштабируемостью и децентрализацией в блокчейн-сетях.

  1. Масштабируемость: Способность системы эффективно обрабатывать растущий объем транзакций или данных, не теряя в производительности и безопасности.

  2. Безопасность в блокчейне: Обеспечение надежности и защиты данных от неавторизированного доступа, подделки или внесения изменений.

  3. Децентрализация: Отсутствие централизованной контролирующей структуры. В децентрализованной системе управление и принятие решений демократично распределены среди всех участников сети.

Ethereum ориентирован на безопасность и децентрализацию, подчеркивая его статус как протокола peer-to-peer с нодами, распределенными по всему миру. Для актуальной информации о распределении нод можно обратиться к NodeWatch.

Для поддержания децентрализации в сети, каждый узел должен проверять все транзакции. Это делает сеть по своей природе менее быстрой. Кроме того, при высокой нагрузке на сеть, транзакции могут обходиться весьма дорого и требовать значительного времени на обработку.

Layer 2

Основной задачей для увеличения TPS сети Ethereum без повышения нагрузки на ноды было внедрение Sharding в сочетании с переходом на PoS (Proof of Stake) консенсус. Это предполагало разделение валидаторов на подгруппы для обработки отдельных сегментов сети, тем самым уменьшая общую нагрузку и увеличивая пропускную способность. Однако, сообщество сделало ставку на Layer 2 решения, учитывая их бурное развитие.

Помимо идеи осуществить Sharding в Ethereum, появились другие решения проблемы масштабируемости, такие как:

  • Payment and State Channels
  • Sidechains
  • Plasma
  • Optimistic Rollup

А также технологии, основанные на доказательствах с нулевым разглашением (ZKP), включая:

  • Validium
  • zkRollup
  • Volition

Более подробную информацию можно найти здесь.

Хотя Sharding еще находится в разработке, в начале 2024 года запланирован хардфорк Dencun, который внедрит Proto-Danksharding. Этот промежуточный этап направлен на улучшение Layer 2 решений, делая хранение данных на L1 более экономичным. Таким образом, Proto-Danksharding обещает снизить стоимость транзакций на L2, являясь шагом к полноценному решению Sharding.

На первый взгляд, L2-блокчейны могут казаться схожими, так как их основная задача — увеличение количества транзакций за пределами L1, при этом делегируя L1 роль гаранта безопасности. Разработчики таких блокчейнов часто утверждают, что их решения являются самыми быстрыми, надежными и простыми. На деле, каждый подход к масштабированию имеет свои нюансы, и неизбежны компромиссы, касающиеся скорости транзакций, уровня безопасности или степени децентрализации. Нередко встречаются и полностью централизованные решения. Все эти аспекты возвращают нас к основным вопросам трилеммы блокчейна.

В этой статье, предложены ключевые критерии для оценки протоколов, используемых в Layer-2 решениях. Они включают в себя:

  • безопасность,
  • производительность и экономическую эффективность,
  • удобство использования,
  • дополнительные аспекты, такие как поддержка смарт-контрактов, совместимость с EVM-байткодом и опции конфиденциальности.

Важно! Статья написана Matter Labs и на мой взгляд некоторые вещи "притянуты за уши" в пользу zkRollup (т.к. тут явный конфликт интересов), но это не так важно, главное посмотреть какие вообще различия существуют между Layer-2 протоколами.

Ниже я приведу таблицу, а здесь верхнеуровнево опишу ее содержимое по пунктам.

Безопасность

  • Предположение о работоспособности или "живучести" Layer-2. Предполагается, что для поддержания работоспособности Layer-2 некоторые участники всегда будут ончейн на уровне Layer-1, чтобы реагировать на возможные случаи мошенничества. Это либо валидаторы, которые стейкают какое-то количество средств (в таблице отмечено статусом "Bonded") на L1, либо третьи стороны которые обеспечивают безопасность протокола за вознаграждение. Как видно из таблицы у решений испльзующих ZKP (Validium и zkRollup) такой необходимости нет.

  • Проблема массового выхода. Проблема которая возникает если в целях безопасности нужно инициировать вывод средств всеми пользователями с L2 на L1 . Как видно из таблицы такая проблема есть только у протокола Plasma, подробнее об этом можно почитать тут.

  • Кастодиальность. Вопрос о том, могут ли валидаторы L2 временно заблокировать или конфисковать средства пользователей.

  • Экономические уязвимости. Включает в себя различные атаки на L2 валидаторов, включая подкуп майнеров L1, создание "теневых" DAO и другие экономически мотивированные атаки.

  • Криптография. Различие между стандартными и новыми криптографическими примитивами. Стандартные более изучены и потенциально уязвимы, в то время как новые (например, SNARK и STARK) обеспечивают большую надежность, но требуют от разработчиков дополнительных знаний и аудитов.

Производительность и экономика

С производительностью все просто. TPS (Transaction Per Second) показывает пропускную способность сети, в контексте масштабирования это самый главный параметр.

Экономические аспекты:

  • Эффективность капитала: Этот аспект особенно важен для платежных каналов (Payment Channels). В них необходимо замораживать средства, равные среднему объему операций в канале, что делает их менее эффективными в плане капиталовложений.

  • Транзакция на L1 для создания аккаунта на L2. Также камень в огород платежных каналов, т.к во всех остальных решениях аккаунт созданный в L1 работает в L2 по умолчанию.

  • Цена транзакции: Вместе с TPS, это один из важнейших факторов масштабируемости, определяющий экономическую привлекательность решения. 

Удобство использования

  • Время вывода средств с L2 на L1: Этот период может варьироваться от нескольких минут до нескольких недель. Optimistic Rollups и Plasma особенно неудобны в этом плане, так как требуют более длительного времени для вывода средств.

  • Время до субъективной необратимости транзакции: Определяет, как быстро транзакция становится неотменяемой на L1 с точки зрения внешних наблюдателей. Например, в Optimistic Rollups для достижения необратимости на L1 требуется всего одно подтверждение на Ethereum, но полная окончательность транзакции занимает около недели.

  • Верифицируемость субъективной необратимости с помощью клиентского кода: Определяет, можно ли проверить время до субъективной необратимости легкими клиентами (браузеры/мобильные кошельки). Продолжая пример с Optimistic Rollups, для подтверждения окончательности транзакции пользователь должен загрузить и проверить весь стейт роллапа за последнюю неделю.

  • Мгновенные подтверждения транзакций. Может ли протокол обеспечить мгновенные подтверждения транзакций с полной гарантией? Либо же он может гарантировать это только на уровне консенсуса L2.

  • Мгновенная видимая окончательность: может быть реализована поверх большинства протоколов L2, то есть транзакции будут мгновенно подтверждены в пользовательском интерфейсе. Только платежные каналы (каналы состояний) предлагают полные гарантии безопасности для этих подтверждений, в то время как в других протоколах эти транзакции все еще могут быть отменены в течение определенного времени, прежде чем они будут подтверждены в L1.

Другие аспекты

  • Смарт-контракты: Рассматривается, поддерживает ли L2-решение полностью программируемые смарт-контракты, или только ограниченное подмножество функций через предикаты.

  • Совместимость с EVM-байткодом: Оценивается возможность переноса существующих EVM-байт-кодов контрактов Ethereum на L2 без значительных изменений.

  • Встроенная поддержка конфиденциальности: Рассмотрение эффективности защиты конфиденциальности в решениях L2, особенно в контексте доступности и экономичности конфиденциальных транзакций.

Ниже приведена сравнительная таблица основных ZKP-базированных решений:

Для более детального понимания Zero-Knowledge Proofs (ZKP), рекомендую обратиться к этой статье в нашей blockchain-wiki, которую создают разработчики для разработчиков с любовью к пруфам и глубокому погружению в детали.

Жизненный цикл транзакций в zkSync

Работа ZK-Rollups может быть представлена на высоком уровне следующим образом:

  1. Формирование Rollup: Транзакции упаковываются в rollup.
  2. Создание ZKP: Формируется доказательство с нулевым разглашением.
  3. Проверка в Ethereum: Доказательство отправляется для проверки в смарт-контракт Ethereum.

В контексте архитектуры zkSync процесс выглядит так:

  1. Сбор внутренних блоков: Валидаторы zkSync собирают внутренние блоки из транзакций каждые несколько секунд.
  2. Формирование пакета блоков: Из внутренних блоков каждые 30-90 секунд создается пакет блоков.
  3. Фиксация состояния блокчейна: Валидаторы фиксируют текущее состояние блокчейна и передают измененные данные на L1 в виде calldata для возможности восстановления.
  4. Вычисление и отправка SNARK: Валидаторы вычисляют SNARK (ZKP) для пакета и отправляют его на проверку в смарт-контракт Ethereum. После проверки, новое состояние сети становится окончательным.

Валидаторы в ZK-Rollups играют ключевую роль, упаковывая транзакции в блоки и генерируя для них доказательства с нулевым разглашением. Особенностью системы является то, что валидаторы физически не могут украсть средства. Самый значительный потенциальный вред, который они могут нанести, — это временная остановка сети.

Заметка: В zkSync Era вместо роль валидаторов выполняют операторы.

Разработчики zkSync выделяют следующие гарантии их архитектуры:

  1. Безопасность средств: Операторы никогда не могут повредить состояние сети или украсть средства, что является преимуществом по сравнению с Sidechains.

  2. Возможность возврата средств: Пользователи всегда могут извлечь свои средства даже в случае, если операторы прекратят работу. Это возможно благодаря доступности данных, в отличие от системы Plasma.

  3. Независимость от мониторинга: Благодаря ZKP, для предотвращения мошенничества, пользователям или доверенным третьим сторонам не требуется постоянно отслеживать блоки Rollup, что является преимуществом по сравнению с системами, основанными на доказательствах мошенничества, такими как Payment channels или Optimistic Rollups.

Транзакции в zkSync Era проходят через несколько ключевых состояний, отличающихся от привычных подтверждений Rollup в L1:

  • Pending: Транзакция была получена оператором, но еще не обработана.
  • Processed: Транзакция обрабатывается оператором и готова к включению в следующий блок.
  • Committed: Данные транзакции опубликованы в Ethereum, что гарантирует доступность данных, но не подтверждает их корректное выполнение.
  • Executed: Завершающий этап, на котором доказательство действительности (SNARK) для транзакции проверено смарт-контрактом Ethereum, делая транзакцию окончательной.

Помимо номера блока, транзакции в zkSync отображают также номер пакета. Изначально, такие параметры как block.numberblock.timestamp и blockhash брались с L1. Однако, после обновления, эти значения будут теперь получаться с L2. Несмотря на это, разработчики планируют предоставить методы для доступа к данным из L1.

Отличия zkEVM от EVM

Совместимость L2 решений, основанных на ZKP с Ethereum представляет собой сложную задачу. Это связано с тем, что Ethereum изначально не был разработан для оптимального взаимодействия с ZKP. В результате, при разработке таких систем приходится искать компромисс между производительностью и потенциалом к масштабированию с одной стороны и совместимостью с Ethereum и EVM с другой. В статье Виталика Бутерина "The different types of ZK-EVMs" подробно обсуждаются эти аспекты и выделяются различные уровни совместимости.

zkSync выбрал один из самых сложных путей, ориентируясь на высокую производительность, но с ограниченной совместимостью как с Ethereum, так и с EVM. Для получения байт-кода, совместимого с zkEVM, используется проект LLVM с комплексом собственных компиляторов и оптимизаторов. В случае с Solidity и Yul, после стандартного компилятора solc, код проходит еще несколько стадий, прежде чем перейти в состояние байт-кода zkEVM. Ниже представлена схема, иллюстрирующая все этапы этого процесса (более подробно описанные здесь):

Важно! Оптимизации в zksolc поддерживаются.

Байт-код, скомпилированный специально для EVM, не совместим с zkEVM. Это означает, что адреса идентичных смарт-контрактов в Ethereum и zkSync будут различаться. Однако, разработчики планируют решить эту проблему в будущем.

Одним из значительных преимуществ такого подхода является независимость от конкретных языков программирования. Разработчики zkSync в перспективе обещают добавить поддержку таких языков, как Rust и C++. Важно, чтобы задержка в обновлениях и интеграции нововведений между верхнеуровневыми компиляторами (например, solc) и компиляторами платформы (например, zksolc) была минимальной. Изначально упоминалась идея о создании собственного языка программирования Zinc, но на данный момент команда сконцентрирована на поддержке более популярных языков программирования.

Проблема совместимости zk-компиляторов с существующими инструментами для разработки и отладки смарт-контрактов на Solidity и Vyper является значительной. Текущие платформы разработки, такие как Remix, Hardhat и Foundry, не поддерживают zk-компиляторы из коробки, что создает трудности при работе с ними. Однако, разрабатываются решения, которые обещают облегчить процесс миграции проектов и адаптации к новым технологиям.

В статье Виталика Бутерина упоминается, что со временем Ethereum, скорее всего, будет стремиться к улучшению совместимости с ZKP на уровне протокола. Аналогично, L2-решения с ZKP будут адаптироваться к лучшей совместимости с Ethereum. В результате, в будущем, различия между этими системами могут стать почти незаметными, обеспечивая более гладкую интеграцию и переход для разработчиков.

Особенности zkEVM

Важно! Протокол активно разрабатывается, всегда обращайтесь к актуальной версии документации!

zkEVM отличается от EVM и несмотря на то, что разработчики стараются спрятать эти отличия "под капотом", есть важные особенности. Их стоит учитывать при написании смарт-контрактов:

  1. Отличия от EVM: Поведение кода, написанного на Solidity для zkEVM, может отличаться, особенно в таких аспектах, как block.timestamp и block.number. Важно регулярно проверять документацию на предмет изменений.

  2. Системные контракты: В zkSync существуют системные контракты для выполнения различных функций, таких как ContractDeployer для развертывания смарт-контрактов и MsgValueSimulator для работы с ETH. Подробнее о системных контрактах можно узнать в документации.

  3. Шаблон прокси для развертывания: Рекомендуется использовать шаблон прокси в течение первых нескольких месяцев после развертывания, чтобы предотвратить возможные ошибки компилятора.

  4. Расчет газа: Модель расчета газа в zkEVM отличается от Ethereum, включая различный набор опкодов и зависимость цены газа от L1. Детали можно найти здесь.

  5. Локальное тестирование: Стандартные инструменты, такие как Hardhat Node или Anvil, не подходят для локального тестирования zkEVM. Вместо этого используются специальные варианты, включая тестирование в режиме форка.

  6. Проверка подписи: Рекомендуется использовать встроенную поддержку абстракции учетных записей вместо ecrecover.

  7. Отслеживание ошибок, связанных с газом: В zkSync невозможно отследить ошибки, связанные с нехваткой газа из-за специфики выполнения внутри системного контракта DefaultAccount.

Для глубокого понимания работы с zkEVM рекомендуется изучить документацию, в том числе раздел "Security and best practices".

Account Abstraction

Абстракция аккаунтов в zkSync предлагает несколько ключевых преимуществ по сравнению с ERC-4337:

  1. Уровень реализации: В zkSync абстракция аккаунтов встроена на уровне протокола, делая все учетные записи, включая внешние учетные записи (EOA), функционально аналогичными смарт-контрактам.

  2. Обработка транзакций: В то время как ERC-4337 использует отдельный мемпул для бандлеров, создавая два разных потока транзакций, zkSync Era имеет единый mempool. Это означает, что транзакции, исходящие от EOA и смарт-контрактов, обрабатываются в одном потоке, обеспечивая более гладкую интеграцию и обработку.

  3. Поддержка Paymasters: zkSync поддерживает paymasters для всех типов учетных записей, позволяя настроить оплату газа в токенах ERC20 для любой учетной записи.

Инфраструктура zkSync

Инфраструктура zkSync Era довольно быстро набирает обороты и уже включает десятки протоколов: Bridges, DeFi, инфраструктурные протоколы и другое. (Актуальный список смотреть тут).

Еще одним преимуществом является совместимость с кошелками Ethereum, например MetaMask или TrustWallet.

Hyperchains

Протокол zkSync начал свое развитие с запуска zkSync Lite, ориентированного только на переводы эфира и токенов ERC-20, без возможности развертывания полноценных протоколов. Этот этап был важным шагом в разработке, но только предварял появление zkSync Era — полноценного L2 решения для Ethereum, который теоретически может быть адаптирован и для других блокчейнов L1. Однако, амбиции zkSync не ограничиваются этим, ведь в планах развития стоит запуск так называемых гиперчейнов.

Гиперчейны, или "фрактальное масштабирование", представляют собой сети ZKP, каждая из которых формирует свои блоки и доказательства. Эти доказательства затем собираются вместе и размещаются в основной сети L1. Каждая из этих сетей является полной копией всей системы и может рассматриваться как ее "фрактал".

Особенность гиперчейнов в том, что они могут быть созданы и развернуты независимо. Для сохранения согласованности и совместимости, каждый гиперчейн должен использовать общий движок zkEVM, который является частью стека ZK (где zkSync Era выступает в роли первого гиперчейна). Это позволяет гиперчейнам наследовать свою безопасность от L1, обеспечивая их надежность и устраняя необходимость в дополнительных мерах по обеспечению доверия и безопасности.

Гиперчейны представляют собой новаторский подход к масштабированию блокчейн-сетей, позволяя снизить нагрузку на основную сеть и увеличить скорость обработки транзакций. Ключевые аспекты этого подхода включают:

  • Передача доказательств между гиперчейнами: Гиперчейны будут передавать доказательства блоков друг другу, увеличивая расстояние, которое должна пройти транзакция до достижения основной сети L1. Это способствует распределению нагрузки и избеганию проблемы узкого горлышка.
  • Прозрачность для пользователей: Пользователи не замечают разницу – их транзакции обрабатываются в гиперчейнах и могут проходить через несколько уровней перед достижением основной сети, создавая асинхронность в обработке.

  • Преимущества над существующими решениями: В отличие от нынешних L2 решений, которые быстрее, но все еще ограничены в количестве транзакций и иногда идут на компромиссы в безопасности, гиперчейны обещают значительно большее масштабирование.

  • Гибкость в создании кастомных блокчейнов: Гиперчейны позволяют создавать кастомные блокчейны и аккаунты с различными уровнями безопасности и приватности. При этом, даже с более низким уровнем безопасности, в худшем случае предполагается лишь временная заморозка средств.

Подробнее обо все этом тут.

Плюсы и минусы zkSync

Плюсы

  1. Безопасность: Безопасность на уровне, близком к L1, и потенциал к децентрализации в будущем.
  2. Совместимость с EVM: Поддержка смарт-контрактов, совместимых с EVM.
  3. Web3 API и кошельки: Стандартный Web3 API и поддержка кошельков Ethereum, таких как MetaMask.
  4. Абстракция учетных записей: Нативная поддержка абстракции аккаунтов.
  5. Скорость транзакций: Быстрая обработка транзакций на L2 с последующим подтверждением на L1.
  6. Низкие комиссии: Снижение стоимости комиссий за газ в сравнение с L1.
  7. Оплата газа в ERC20: Возможность оплаты комиссий за газ в токенах ERC20.
  8. Развивающаяся инфраструктура: Очень активное развитие инфраструктуры.
  9. Потенциал к масштабированию: Возможности для значительного улучшения масштабируемости.

Минусы

  1. Ограниченная cовместимость с EVM: По сравнению с конкурентами (например, Polygon zkEVM, Scroll) совместимость с EVM ниже.
  2. Риск ошибок в смарт-контрактах: Повышенный риск ошибок, требующий тщательного тестирования и аудита.
  3. Специфичность стека разработки: Необходимость адаптации стека разработки под особенности протокола.
  4. Отставание от основных технологий: Задержка в принятии нововведений в компиляторах и обновлениях библиотек.
  5. Централизация cети: На данный момент сеть управляется ограниченным числом операторов.
  6. Необходимость обновляемых смарт-контрактов: Из всего вышесказанного вытекает необходимость на старте проекта всегда делать обновляемые контракты, чтобы иметь возможность оперативно устранить недостатки и уязвимости.

Вывод

Протокол zkSync выглядит очень многообещающе и имеет большой потенциал, хотя на данный момент запуск в этом блокчейне все еще сопряжен с рядом рисков, которые нужно учитывать. Разрабатывать для zkSync на данный момент сложнее, чем для блокчейнов, которые гораздо больше совместимы с EVM и стеком для разработки под EVM. Но, возможно в будущем, эта разница станет несущественной либо совсем будет отсутствовать.

Переходите в наш репозиторий на Github, там мы сделали Blockchain Wiki для всех тех, кто желает разобраться, как работает Web3:)

Больше статей о web3

выбор редакции
stock market chart

Статьи

education
ethereum
web3
Вестинг в криптопроектах: зачем нужен и как реализовать

Роман Ярлыков

Solidity разработчик

выбор редакции
crypto wallets

Статьи

ethereum
web3
business
Account Abstraction: что это такое и зачем нужно криптомиру

Павел Найданов

Solidity разработчик

выбор редакции
myths

Статьи

web3
dApps
startup
Мифы о разработке блокчейн продуктов

Николай Бордуненко

Project manager at MetaLamp

sharding
выбор редакции
ton
bottle_wine
выбор редакции
Зачем вину блокчейн: как токенизируют премиальный алкоголь

Елизавета Черная

Редактор Бренд-медиа

Статьи

web3
nft
business
launchpad
twa
Тренды блокчейна и криптоиндустрии 2024: Telegram Mini Apps (TMA)

Елизавета Черная

Редактор Бренд-медиа

Статьи

web3
buildings
anonymus
выбор редакции
Zero-knowledge proof: один из трендов 2024 в блокчейне

Евгений Биктимиров

Венчурный аналитик

Статьи

ethereum
web3
dApps
cpay
выбор редакции
AA zksync
zero knowledge proofs
выбор редакции
stock market chart
выбор редакции
planets
fundraising
выбор редакции
cto
wallet
tokens
выбор редакции
rocket computer
выбор редакции
Как создать дизайн для MVP стартапа за 7 дней

Юлия Черепанова

Head of Design Office

Статьи

startup
MVP
design
nft
AI
crypto wallets
выбор редакции
Account Abstraction: что это такое и зачем нужно криптомиру

Павел Найданов

Solidity разработчик

Статьи

ethereum
web3
business
red space
выбор редакции
speed up development
myths
выбор редакции
Мифы о разработке блокчейн продуктов

Николай Бордуненко

Project manager at MetaLamp

Статьи

web3
dApps
startup
launching
выбор редакции
Кого нужно нанимать в команду для запуска MVP?

Алексей Сухарев

Head of Sales Department

Статьи

business
startup
MVP
galaxy
magazine
spaceman
выбор редакции
coffee
investors
nft
Первый NFT marketplace на Cardano

Станислав Жданович

Haskell разработчик

Статьи

cardano
web3
nft
stair
выбор редакции
bridge
rocket
abstraction
Как мы нанимаем Plutus инженеров через собственную программу обучения

Светлана Дульцева

Супервизор программы обучения

Статьи

education
cardano
web3
mountains
blockchain
salary
salary increase
app
developer with books
keyboard
abstract