Петр Емельянов
Петр Емельянов

Привет, Хабр! Петр Емельянов — эксперт по машинному обучению в Skillbox (и не только). Для закрытого комьюнити Skillbox Code Experts, которое я с удовольствием менеджерю, Пётр провёл эфир по технологии блокчейн и объяснил как она на самом деле работает. Мы с Петром решили написать статью с основными мыслями и объяснениями из первых уст — потому что эфиры Петра всегда интересные и посещаемые. Не поделиться таким контентом — просто грешно :)   Поехали! 

Что такое блокчейн на примере Bitcoin

Сложилась терминологическая путаница, и блокчейн стал однозначным синонимом криптовалют, хотя на самом деле блокчейн – это технология, область применения которой выходит далеко за криптовалюты. Если посмотреть «Википедию», то первое определение будет звучать так: блокчейн – это непрерывный связанный список блоков, которые могут содержать любую информацию. И совсем необязательно это будет информация о финансовых транзакциях. 

Блокчейну приписывают три свойства: неизменяемость, распределённость и консенсус. Давайте рассмотрим подробнее.

Неизменяемость

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

Распределённость 

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

Но распределённость, на самом деле, — не обязательное свойство блокчейна. Есть блокчейны, построенные с центром доверия, единой точкой консолидации данных, которая и отвечает за внесение новых блоков. 

Алгоритм консенсуса

В биткоине есть хитрый алгоритм консенсуса, который и обеспечивает доверие во всей этой одноранговой сети. Именно благодаря ему каждый участник имеет более или менее равные права. Если вы сталкивались с любыми другими распределёнными системами, например, кластерами Kafka, Redis, MongoDB, то знаете, что консенсус — это сложно, задача со звёздочкой. И это так, даже если в конкретной распределённой информационной системе, узлы не стремятся друг друга обмануть и доверие предполагается по умолчанию.

Алгоритмов консенсуса существует много. В блокчейне он устроен ещё сложнее, потому что предполагается, что участники могут друг другу лгать, отклоняться от протокола, чтобы получить экономическое преимущество. Ведь биткоин — это деньги, и в этой системе это действительно имеет смысл.

Теперь поговорим о том, что обеспечивает блокчейну биткоина три ключевых свойства.

Хеширование и при чём тут цепь

Первое, о чем стоит сказать – это хэширование.  Именно оно обеспечивает неизменяемость блокчейна. Вообще, хэширование применяется повсеместно, например, в криптографии, в алгоритмах (в качестве основы хэш-таблиц, про которые любят спрашивать на собеседованиях), а некоторые достаточно наивные люди обезличивают с его помощью персональные данные (на самом деле это почти никогда не работает). В блокчейне хеширование – это механизм, который намертво связывает блоки, а еще используется как вычислительная основа механизма консенсуса Proof of Work, но об этом позже. Сперва определения. 

Хэш-функция — это функция, которая берёт данные любого размера, перемешивает и «варит» из них данные фиксированного размера, потенциально снижая энтропию. 

Энтропия – это, если упрощенно, мера вариативности. Например, число в 16 бит может принимать 65 536 (2^16) различных значений, а число в 8 бит – всего 256 (2^8). Получается, что некоторая функция, превращающая шестнадцатиразрядное число в восьмиразрядное сжимает пространство: например, 256 разным шестнадцатиразрядным аргументам будет соответствовать одно и то же восьмиразрядное значение. Это и будут коллизии, вызванные снижением энтропии. 

Так как энтропия снижается, могут возникать коллизии. Коллизия в хешировании – ситуация, в которой разные аргументы функции порождают один и тот же результат. Если hash(Петя) = 42 и hash(Маша) = 42, то по хешу нельзя отличить Машу от Пети. В случае криптовалют, такое «безразличие» может обрушить всю конструкцию: люди, как правило, хотят отличать свои деньги от чужих.

Чем лучше и устойчивее криптографическая хэширующая функция, тем вероятность коллизий и вероятность обратимости — ниже. Даже имея хэш, развернуть его и посмотреть, что внутри, становится сложнее (на самом деле очень сложно). Ещё одно важное свойство хорошей хэш-функции – чувствительность: самое незначительное изменение аргумента до неузнаваемости изменяет результат. Такой вот «эффект бабочки». 

В биткоине используется хорошая, криптографически стойкая хэш-функция SHA256. Число 256 в ее названии намекает, что результат функции – число в 256 бит. Это очень, очень большие числа, а сама функция SHA – это довольно хитрая последовательность перемешиваний и арифметики, поэтому вероятность коллизии у SHA256 довольно низкая. А еще значения SHA256 – более или менее псевдослучайные числа из равномерного распределения. То есть, несмотря на то, что размерность результата функции может быть ниже, чем её аргумента, этот результат все равно довольно высокоэнтропийный. 

Хэш-функция SHA256 хэширует заголовок блока. Сейчас не так важно, из чего состоит этот заголовок. Важнее, что от него считается хэш и сохраняется в этом же заголовке. А в заголовке следующего блока считается хэш от заголовка самого блока и от хэша заголовка предыдущего блока. Так, в заголовке блока № N будет хэш заголовка блока № N-1, в заголовке блока N+1 будет хэш от заголовка блока N-1, в заголовке блока N+2 будет хэш заголовка блока N+1 и так далее. 

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

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

Цифровая подпись

Теперь про подлинность. Достанем из чертогов разума цифровую подпись. 

Цифровая подпись — это криптографический примитив, который используется не только в блокчейне. Например, подписать документы на ипотеку можно вообще не попадая в банк — через приложение «Госключ».

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

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

В случае блокчейна в рукаве припасён козырь — вместо классического шифрования у нас здесь используется вычисление хэша и приватный ключ. Теперь подробнее.  

Классическое шифрование VS электронная подпись

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

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

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

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

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

В биткоине (и не только) используется цифровая подпись на эллиптических кривых. Это популярный метод. Дело в том, что алгебра с точками на эллиптических кривых довольно сложно организована, но позволяет использовать ключи короче, чем в RSA и вычислять их быстрее. 

Ключ от кошелька

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

Создавая биткоин-кошелек, вы создаёте приватный ключ. А затем из приватного создаёте публичный, комплементарный вашему приватному. Хэш от публичного ключа и является адресом вашего биткоин-кошелька. Когда деньги переводятся с одного кошелька на другой, в качестве адреса используется хэш от публичного ключа. Это удобно, потому что публичный ключ путешествует, в каждой транзакции он уже есть. А приватный ключ есть только у вас и больше ни у кого. Если кому-то его отдадите, или его украдут, ваши биткоины пропадут, вернуть их вы уже не сможете. Если вы ключ забыли или потеряли, то биткоины тоже пропадут. Таких историй в Интернете достаточно и они очень грустные.

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

Ещё один вариант — пользоваться кошельком на бирже, но важно понимать, что на самом деле, в этом случае вы приватным ключом не владеете. Понятно, что есть репутация биржи или онлайн-кошелька. Но есть риск, что в любой момент их владелец может раствориться в тумане вместе со всеми деньгами пользователей. Так происходит редко, но такой риск есть. И если мы говорим про институт репутации, то у банков и государств она тоже есть. И если мы кому-то настолько сильно доверяем, что отдаём наши деньги на хранение, то зачем вообще нужны биткоин и блокчейн? Моё мнение: если уж в эту игру играть, то играть по правилам, и приватный ключ держать при себе. 

Самое сложное — консенсус

Все перечисленные выше чудесные бонусы не работали бы без алгоритма консенсуса. Достаём ещё один козырь из рукава Сатоши и поговорим про консенсус.

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

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

Блокчейн развивается, транзакции в сети продолжают ходить, а мы пользуемся биткоинами. Более того, правительства некоторых стран задумываются о или даже уже используют биткоин. Другими словами, блокчейны, которые хранят полные ноды, постоянно обновляются. Механизм обновления реализуют специальные ноды – майнеры (которые, на самом деле, тоже хранят копию блокчейна и в этом смысле являются полными нодами). 

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

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

Proof of Work

Но в блокчейне биткоина (и не только) у нас алгоритм консенсуса тоже непростой. В блокчейне генезисно используется консенсус Proof of Work (доказательство работы), но есть и другие алгоритмы консенсуса. Тем не менее Proof of Work — наиболее используемый в современных блокчейнах. 

Сам способ доказательства работы, на самом деле, придуман раньше, чем блокчейн. Когда-то в нулевых я работал в компании, которая занимается сетевыми железяками и софтом, связанным с сетями. Типичной задачей была защита от DDoS. Одним из методов защиты как раз и был Proof of Work. Клиент запрашивает у вас услугу, а вы понимая, что находитесь под нагрузкой, даёте ему вычислительно сложную задачку. Делаете это, предполагая, что если клиент действительно настоящий, то ему ничего не будет стоить её решить и вернуться с ответом. Если же это не клиент, а бот, задача которого положить ваш сайт, вызвав Denied Service, то он уйдёт (и туда ему и дорога). 

Похожее используется при защите сайтов от DDoS на уровнях выше, чем L3: браузер считает хэш, и потом его возвращает. Если результат сходится с тем, что вы ожидаете, то вы его пропускаете. Этот приём называется HashCache.

В блокчейне все держат очередь транзакций, которая распределена по фулл-нодам. Где находится полные ноды на земном шарике? Да везде: большая часть в Китае, Америке, России. Майнеры забирают из очереди транзакции и складывают в блоки. Когда майнер набрал достаточно транзакций для блока, он готовит для него заголовок. В заголовок блока входит корень дерева Меркла. Это специальным образом собранные хэши от всех транзакций, которые лежат в этом блоке. Там же обязательно есть таймстемп и хэш от заголовка предыдущего блока. Это и есть принцип ссылки в блокчейне. В ней есть версия протокола, сложность и специальная «чиселка», которая называется Nonce

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

Когда вы посчитали хэш набора данных, то получите псевдослучайную комбинацию из более или менее равномерного распределения. И если вы наложите на это условие — например, что Nonce, должна быть меньше, чем заранее установленное значение, то выполнить эту задачу становится сложно. Единственный на сегодняшний день известный способ решить эту задачу – это полный перебор. Майнер должен считать хэши практически безостановочно, меняя заголовки. Если условие не выполнено, считает ещё раз, а Nonce просто увеличивается на единичку. И так повторяется много-много раз — до тех пор, пока не получится значение хэша, удовлетворяющее условию. Как только это произошло, задача решена. Такой блок можно отправить обратно в сеть нодам, которые должны будут включить его в блокчейн. 

У операции хэша есть интересное свойство: она односторонняя. Рассчитать хэш в одну сторону легко, в обратную — вычислительно тяжело. Поэтому ноды, которые получат блок, могут легко проверить. Они просто посчитают хэш от тех данных, которые в этот блок уже вложены, включая Nonce, и сравнят их. Если значение хэша меньше, чем всем известный таргет, значит, вы действительно решили эту задачку, и этот блок можно включать в общую цепочку блоков в блокчейн. Все майнеры соревнуются в подборе хэша, который будет удовлетворять условию.

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

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

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

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

Подтверждения или способы борьбы с опасностями

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

Но главная неприятность, которая может произойти — иная: когда транзакцию отменили и она снова встала в очередь, деньги и у получателя исчезли и вернулись к отправителю. А что если к тому моменту отправитель эти деньги потратит? Чтобы этого не случилось, есть ещё одно усложнение, которое называется «количество подтверждений». Как правило, все биткоин-кошельки меняют баланс и дают вам возможность пользоваться биткоинами после определённого количества подтверждений.

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

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

Вот так работает блокчейн на примере звезды в мире крипты монетки Bitcoin. А вы пользуетесь криптовалютами? Доверяете ли принципам работы блокчейна больше, чем государственным финансовым регуляторам? Напишите в комментариях свою позицию.

Комментарии (4)


  1. Number571
    23.07.2024 19:59
    +18

    Как работает блокчейн: объяснение от эксперта по ML и AI Петра Емельянова

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


  1. Germanjon
    23.07.2024 19:59
    +2

    Почему-то все статьи на тему "блокчейн" скатываются к описанию биткоина и криптовалют.

    Получается, это единственное реальное применение технологии "блокчейн"? Реальное - в моём понимание, это когда технология решает проблему, решает её качественно и более быстро/просто чем остальные технологии


    1. vagon333
      23.07.2024 19:59
      +1

      Ага.
      И с клише "блокчейн"="крипта" очень сложно объяснять другие области применения блокчейн.

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


  1. MatrixResolvere
    23.07.2024 19:59

    Важнее, что от него считается хэш и сохраняется в этом же заголовке. А в заголовке следующего блока считается хэш от заголовка самого блока и от хэша заголовка предыдущего блока. Так, в заголовке блока № N будет хэш заголовка блока № N-1, в заголовке блока N+1 будет хэш от заголовка блока N-1, в заголовке блока N+2 будет хэш заголовка блока N+1 и так далее

    Мне одному кажется что этот абзац и рисунок приведённый дальше противоречивый? Если мы считаем хэш блока N по данным заголовка этого же блока + хэш предыдущего блока (N-1), то почему в заголовке N-го блока будет хранится хэш N-1-го? Ведь в первом предложении написано что от него (т.е. от N-го заголовка блока) считается хэш и сохраняется в нём же.