Создайте свою собственную валюту блокчейна за считанные минуты.

Вступление

Важное примечание. Для этого руководства требуются хотя бы базовые знания ES6.

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

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

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

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

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

Кошелек

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

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

Вот наш первый фрагмент кода - он содержит объявление класса кошелька со следующими методами:

  • Конструктор: использует объект параметров и использует его для создания базовой структуры кошелька с двумя присутствующими полями - закрытым и открытым ключом.
  • Создатель кошелька: создает новую пару асимметричных ключей и превращает ее в новый кошелек с правильно заполненными полями.
  • Конвертеры кошелька: утилита, которая преобразует необработанные ключи HEX, хранящиеся в кошельке, в закодированные сертификаты PEM, используемые Node. Длинная загадочная константа - это двоичный заголовок с кодировкой ASN, используемый для тегирования частной и открытой частей результирующего ключа.

Теперь мы можем попробовать использовать его в действии - выполнив пару подписей, как действительных, так и недействительных:

Первый живой пример доступен здесь - так что вы поиграете с разными наборами данных и кошельками.

Сделка

Транзакция - это структура данных, которая содержит всю необходимую информацию о переводе средств с одного счета на другой. Действительная транзакция должна содержать цифровую подпись отправителя, чтобы гарантировать, что она действительно была авторизована. Еще одна вещь, которая есть у каждой транзакции, - это хэш - строка фиксированного размера, которая может быть извлечена из ее тела, когда вам это нужно.

Хеш - это форма контрольной суммы цифрового объекта - вы можете создать один и тот же объект по-разному миллиард раз, но его хеш всегда останется неизменным, если поля будут одинаковыми. Но даже малейшее изменение - и получится совсем другой хеш.

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

Приведенный выше код определяет базовую структуру транзакции - сначала мы можем более внимательно изучить его поля:

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

Но как насчет методов экземпляра? Вот они:

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

Теперь мы можем использовать наш код, моделируя несколько возможных вариантов использования - делая как действительные, так и мошеннические транзакции и проверяя их:

Второй пример доступен здесь - он содержит код транзакции и небольшую площадку с Бобом и Алисой.

Блокировать

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

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

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

Что происходит в объявленном выше классе? Как и в случае с транзакцией, мы можем сначала начать наше исследование со свойств конструктора:

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

Хеширование, майнинг и базовая проверка статуса выполняются с использованием методов экземпляра:

  • Хеш: преобразует заголовок блока и список его транзакций в строку и возвращает хеш на основе этой информации.
  • Mine: реализация синхронного майнера - увеличивает значение nonce до тех пор, пока не будет выполнено условие доказательства работы. В результате возвращает блок с соответствующим одноразовым номером.
  • Тест: возвращает статус добычи, определенный путем подсчета количества начальных нулей в его хэше. Не проверяет транзакции, требует выполнения вручную.

Теперь мы можем моделировать простой блокчейн без состояния - сохраняя связанные блоки в списке:

Третий пример доступен здесь - вы можете попробовать различные комбинации блоков и попытаться написать собственный механизм проверки цепочки.

Штат

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

С точки зрения эфира состояние - это довольно сложная структура, заполненная patricia trie, но наша реализация довольно примитивна:

  • Конструктор: Создает государственный словарь "ключ-значение" для хранения доступных данных учетной записи.
  • Хеш: перебирает существующие учетные записи и использует их для получения хеша текущего состояния.
  • С (для транзакций): принимает транзакцию и возвращает обновленное состояние - с правильной суммой монет, переведенной с одного аккаунта на другой.
  • С (для блоков): потребляет блок и возвращает обновленное состояние - с соответствующим вознаграждением, отправленным на счет майнера. Не обрабатывает блочные транзакции.

Этого достаточно, чтобы опробовать основные мутации состояний - как с транзакциями, так и с блоками:

Четвертый пример доступен здесь - он довольно прост, не стесняйтесь экспериментировать с разными кошельками и ценностями.

Блокчейн

Теперь мы можем связать все в хороший класс, который будет содержать алгоритмы состояния, истории и консенсуса, обеспечивая удобный высокоуровневый интерфейс. Я буду краток, просто взгляните на сам код:

В отличие от предыдущих классов, этот содержит статические методы - оба являются чистыми функциями, которые выполняют проверку и возвращают обновленное состояние:

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

Что насчет методов экземпляра - все они предоставляют удобный доступ к значениям цепочки, таким как ее текущее состояние и история:

  • Конструктор: определяет основные свойства цепочки блоков - историю блоков и текущее состояние.
  • Баланс: возвращает текущий баланс счета, если он существует, в противном случае возвращает нулевой баланс.
  • Push: проверяет блок и помещает его в текущую цепочку блоков, обновляя его состояние и историю.
  • Мой: удобная оболочка для предыдущего метода, которая автоматически добывает блок и помещает его в цепочку блоков.

Теперь мы готовы к нашему последнему примеру - он свяжет все в целостную картину:

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

Заключение

Теперь у нас есть небольшая полнофункциональная криптовалюта. Присмотримся к результатам поближе:

  • Goothereum содержит утилиты для создания кошельков.
  • Goothereum может создавать, подписывать и проверять транзакции.
  • Goothereum умеет упаковывать транзакции в блоки и майнить их.
  • Goothereum может отслеживать изменения состояния и представлять их в удобной форме.
  • Goothereum умещается в 160 строк несжатого кода JavaScript.

Основная цель этой статьи - продемонстрировать основные принципы криптовалюты на основе блокчейна, поэтому Goothereum лишен многих вещей от реального Ethereum:

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

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

Я хочу поблагодарить всю команду Ethereum за создание потрясающей инновационной платформы для смарт-контрактов и децентрализованных вычислений.

Я обещаю написать вторую часть этой статьи, если она станет популярной - она ​​будет посвящена одноранговым сетям - поэтому, пожалуйста, поделитесь и порекомендуйте, если она вам понравится. Спасибо за прочтение!

Прочтите мою предыдущую статью, если вы хотите узнать больше о внутреннем устройстве React: Gooact: React в 160 строках JavaScript.