Вдохновленный build-your-own-x Даниэля Стефановича, я решил, что пора перестать читать и начать строить.
То, что не могу создать, не понимаю. Ричард Фейнман
В этой серии из двух публикаций я собираюсь объяснить, как можно создать очень простую, но функциональную криптовалюту. Он основан на биткойнах, и я надеюсь, что к концу серии вы поймете, в чем разница между блокчейном и криптоактивом.
Я предполагаю, что у читателя есть некоторый опыт программирования, но у вас все будет хорошо, даже если вы новичок. Я собираюсь использовать Kotlin, так как некоторое время возился с ним, но он может быть реализован на любом языке, на самом деле, вперед и реализуйте его на своем любимом языке!
Начиная
Вероятно, это будет самая простая часть: перейдите на сайт IntelliJ, загрузите версию сообщества и создайте новый проект.
Немного теории
Есть два способа организовать общение между сторонами:
- Централизованно, там все коммуникации идет через посредника. Например, в традиционном банковском деле, если вы должны были перевести деньги своему другу, вы сделаете это через банковский интерфейс, и банк может взять за это комиссию.
- Децентрализовано или распределено, где каждая сторона может общаться друг с другом без посредников. Например, 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
майнинг блока уже занимает значительное количество времени.
Проверка
Теперь, когда мы можем создавать, добывать и добавлять блоки, давайте добавим функцию для проверки цепочки блоков.
Чтобы наш блокчейн был действителен:
- Блокчейн действителен, если он пуст
- Блокчейн содержит один блок с действующим хешем
- Все блоки заминированы
- Для каждого блока в блокчейне:
- Текущий хэш блока действителен
- Хеш предыдущего блока действителен
Я использовал конструкцию когда, и она выглядит аккуратно:
Заключение
Мы только что реализовали очень простой, но функциональный блокчейн менее чем в 100 строк кода, поздравляем!
Я надеюсь, что вы, как и я, теперь лучше понимаете, как работают блокчейны, и во второй части, о которой я собираюсь написать, мы можем хранить транзакции в блокчейне и, наконец, сделать из этого криптовалюту, так что следите за обновлениями.
Исходный код на GitHub.