Добро пожаловать в серию «От нуля до блокчейна на Python», где мы создадим реализацию блокчейн-приложения, в частности криптовалюты, с нуля. На протяжении всей серии мы будем создавать и улучшать функциональные возможности, пока не получим полнофункциональную демонстрацию.

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

В этой части мы создадим следующую базовую функциональность блокчейна:

  • Возможность добавлять блоки в
  • Алгоритм простого доказательства работы (PoW)
  • Возможность добавления сделок
  • Возможность майнить новые блоки
  • Возможность замены цепи на новую

И мы сохраним следующее для будущих сообщений:

  • Управление кошельком
  • Подписывать транзакции
  • Одноранговая связь

Как работает блокчейн?

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



Да начнется веселье

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



Основные структуры

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

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

Block = {
    index: number
    timestamp: number
    transactions: [Transactions]
    nonce: string
    previous_hash: string
    hash: string
}

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

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

Блокчейн

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

Характеристики

self.__chain = []
self.__current_transactions = []

@property
def last_block(self):
    return self.__chain[-1]

@property
def last_transaction(self):
    return self.__current_transactions[-1]

@property
def pending_transactions(self):
    return self.__current_transactions

@property
def full_chain(self):
    return self.__chain

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

  • __chain: список блоков, представляющих блокчейн [частный]
  • __current_transactions: список транзакций, которые еще не являются частью блока [частный]
  • last_block: последний блок, добавленный в цепочку
  • last_transaction: последняя транзакция, добавленная в цепочку
  • pending_transactions: возвращает атрибут __current_transactions
  • full_chain: возвращает атрибут __chain

Конструктор

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

Создание транзакций

Просто как создание объекта транзакции, проверка его правильности и присоединение к цепочке.

Доказательство работы

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

f`{last_nonce}{last_hash}{nonce}`

хеширование с помощью sha256 приведет к 4 ведущим нулям.

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

Мой

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

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

Давайте теперь рассмотрим функцию add_block и то, что она влечет за собой:

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

Замена блокчейна

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

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

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

# Then we compare each block with its previous one
for x in range(1, len(chain_to_validate)):
    if not self.validate_block(chain_to_validate[x], chain_to_validate[x - 1]):
        return False

Это больно глазам? Каждый раз, когда мы хотим проверить входящую цепочку, нам нужно проверить все блоки в цепочке, должен быть лучший подход, особенно если мы рассмотрим многие из тех блоков, которые, вероятно, есть в нашей собственной цепочке. Ну… есть лучший способ, но он не будет рассматриваться сейчас, мы рассмотрим его в следующем посте, но если вы заинтригованы и хотите провести исследование и создать PR, вы можете это сделать. :), просто взгляните на Merkle Trees.

Поздравляю!

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

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

Большое спасибо, что оставались со мной так долго, надеюсь, что этот проект был интересным. Если вы хотите узнать больше или хотите, чтобы я поработал над определенной темой, напишите мне по адресу [email protected], я буду рад поддержать.

Удачного кодирования!

Первоначально опубликовано на https://livecodestream.dev.