Вдохновленный build-your-own-x Даниэля Стефановича, я решил, что пора перестать читать и начать строить.

То, что не могу создать, не понимаю. Ричард Фейнман

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

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

Начиная

Вероятно, это будет самая простая часть: перейдите на сайт IntelliJ, загрузите версию сообщества и создайте новый проект.

Немного теории

Есть два способа организовать общение между сторонами:

  1. Централизованно, там все коммуникации идет через посредника. Например, в традиционном банковском деле, если вы должны были перевести деньги своему другу, вы сделаете это через банковский интерфейс, и банк может взять за это комиссию.
  2. Децентрализовано или распределено, где каждая сторона может общаться друг с другом без посредников. Например, BitTorrent там вы скачиваете файлы напрямую от пользователей, а не с сервера.

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

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

Блокчейн - это хранилище для распределенной системы.

Думайте об этом как о Amazon S3, но он принадлежит всем, а не Amazon.

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

Важно увидеть, из чего состоит хэш блока:

Хеш блока = хеш (родительский хеш + вспомогательные данные)

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

Реализация

Хеш-утилиты

Поскольку 2/3 данных блока содержат хэши, мы собираемся написать небольшую служебную функцию для получения хэша из String.

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

Это довольно просто: конвертировать String в ByteArray обновить MessageDigest с его помощью и преобразовать дайджест в строку HEX.

Блоки

С помощью классов данных легко моделировать блоки. Они генерируют все шаблоны java и обеспечивают неизменяемость во время компиляции.

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

Создадим пару блоков!

И возможный вывод:

Block(previousHash=0, data=I'm the first, timestamp=1530024961908, hash=dc5e733f548bc8240d04f02884ead8c2ddb4a2add0606277bd8ec7c75983d793)
Block(previousHash=dc5e733f548bc8240d04f02884ead8c2ddb4a2add0606277bd8ec7c75983d793, data=I'm the second, timestamp=1530024961935, hash=1621970956c63d89e077a9122e122fa45ba86d5f478f4fa2b4d7b6cf3f39efa7)
Block(previousHash=1621970956c63d89e077a9122e122fa45ba86d5f478f4fa2b4d7b6cf3f39efa7, data=I'm the third, timestamp=1530024961936, hash=d5a1d82930d157013adb2f8bfb90449dbae66b768c211a207202a80f478d4f64)

Блокчейн

Пока мы только создавали блоки, давайте добавим контейнер для их хранения - Blockchain.

Добыча полезных ископаемых

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

Как оказалось, проблема не нова, и ваш Inbox ежедневно сталкивается с ней в виде спама: многие спамеры хотят писать (отправлять) вам.

Около 20 лет назад Адам Бэк предложил в качестве решения HashCash. Идея Адама заключалась в том, чтобы добавлять стоимость к каждому отправляемому электронному письму, чтобы массовая рассылка стала дорогостоящей, но он не хотел брать деньги, и вместо этого его идея заключалась в том, чтобы попросить отправителя выполнить задачу, требующую интенсивного использования ЦП, например, найти специально отформатированный хеш. Самое интересное в этом решении то, что нет простого способа найти такой хеш без грубой силы.

Биткойн использует эту идею и ожидает, что хэш блока будет special, чтобы быть действительным:

Чтобы блок был действительным, его хэш должен начинаться с определенного числа 0s.

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

Когда у нас есть это поле, фактический алгоритм майнинга становится довольно простым: в цикле мы изменяем значение nonce на единицу, пока не найдем хэш special:

Опять же, класс данных Kotlin удаляет шаблон при копировании. Я также изменил add функцию на мой блок, если он еще не добыт.

Difficulty позволяет контролировать, насколько быстро мы можем найти кеш. Биткойн корректирует этот параметр каждые пару недель в зависимости от среднего времени, которое потребовалось для добычи блоков за это время. У меня модель MacBook Pro 2015 года, и с трудом более 10 майнинг блока уже занимает значительное количество времени.

Проверка

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

Чтобы наш блокчейн был действителен:

  1. Блокчейн действителен, если он пуст
  2. Блокчейн содержит один блок с действующим хешем
  3. Все блоки заминированы
  4. Для каждого блока в блокчейне:
  • Текущий хэш блока действителен
  • Хеш предыдущего блока действителен

Я использовал конструкцию когда, и она выглядит аккуратно:

Заключение

Мы только что реализовали очень простой, но функциональный блокчейн менее чем в 100 строк кода, поздравляем!

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

Исходный код на GitHub.