Изменение протокола
Продолжение статьи о скриптинге транзакций в биткоин сети.
уровень знаний: средний
Как можно внести измнения в биткоин-протокол? Можно поначалу решить, что это просто — выпустить новую версию ПО и велеть всем узлам обновиться. В реальности всё куда сложнее — невозможно и предположить, что каждый узел действительно обновится. Некоторые узлы не смогут получить новое ПО, или получат его не вовремя. Существует два типа таких изменений: те, которые создают хардфорк, и те, что создают софтфорк.
Хардфорк. В этом случае речь идёт о введении особенностей, ранее признаваемых недействительными. Это значит, что новая версия ПО будет считать валидными те блоки, которые предыдущая версия отвергала. Этот тип изменений называется хардфорком из-за того, что разделяет цепочку блоков на две ветви. Каждый узел в сети будет либо на одной, либо на другой стороне в зависимости от используемой версии протокола. Конечно, ветви никогда больше не сойдутся, что считается неприемлемым во всём сообществе, так как старые узлы будут полностью отрезаны от биткоин-сети, если не обновят ПО.
Софтфорк. Далее этот раздел полностью переписал на свой лад (материал подготовлен на основе Принстонского курса). Итак, по моему мнению, изменения в консенсусе вокруг построения цепи блоков в любом случае приводят к хардфорку, так как старая и новая версия софта будут отвергать блоки, созданные второй стороной. А вот с консенсусом по валидации транзакций ситуация другая: если старая версия софта не может принять в цепочку блок, построенный по новым правилам, то с переводами иначе - старый софт без проблем принимает выходы, сформированные по новым правилам. Как протокол понимает, что в транзакции выполняется легитимный перевод? В предыдущей статье я разобрал это процесс, здесь же могу добавить, что протокол не проверяет, как создавались монеты (как сформировался выход), а только отрабатывает скрипт по их переводу-трате. Сразу же возникает вопрос, а кто будет обрабатывать новые аспекты скриптинга? Для ответа на этот вопрос необходимо ввести понятие "Активация софтфорка". Активация происходит через сигналирование в новых блоках, после достижения определенного порога, например 75% из N последних блоков, сигналирующих о готовности обрабатывать новые ОР коды, софтфорк может считаться активированным. Старые узлы по прежнему не смогут валидировать транзакции с новыми ОР кодами, но смогут использовать выходы, сформированные по новым правилам.
В момент траты выход становится входом. Так как же работают софтфорки, и как новые правила скриптинга отрабатывают инструкции в среде, где присутствуют и майнят ноды, работающие по старым правилам? Ведь нода, при поступлении транзакции в мемпул, должна ее валидировать, но если узел не знает новых правил с введёнными ОР кодами, то транзакция увидится ему невалидной. В биткоин эта проблема решена элегантно: разбиением общего скрипта на выход в предыдущей транзакции и на вход в текущей. Та часть скрипта, которая в выходе, она понятна для узлов старого типа, а во вторую часть, которая во входе, уже можно включать ОР коды, понятные только новому типу ноды. Формируя выход, мы указываем хэш скрипта как адрес получения монет, и это понятно старому типу ноды, а что будет происходить внутри этого скрипта, старых узлов не касается. А вот когда уже тратим ранее сформированный выход, то указываем весь скрипт целиком с новыми ОР кодами, старому типу узлов такие транзакции непонятны. Поэтому в сети фактически существует два мемпула: первый включает транзакции созданные по старым правилам; второй мемпул расширяет первый транзакциями, составленными по новым правилам.
Софтфорки интересный механизм, его ключевое отличие - это возможность в сети обрабатывать транзакции по новым правилам, причём добычей блоков и валидацией транзакций могут заниматься ноды старой версии. В первой версии софтфорка, реализуемой через механизм IsSuperMajority, такой возможности не было: старые узлы уже не могли добывать блоки. А новый механизм активации софтфорков BIP9 позволяет старым нодам продолжать участвовать в добыче блоков и запечатывании в них транзакций, но старым узлам будут непонятны транзакции, составленные по новым правилам.
Отличием валидации цепочки блоков от валидации транзакций является проверка истории создания цепи:
- цепь блоков проверяется полностью, примером будет кейс хардфорка, связанным с увеличением размера блока в два раза начиная с номера блока 100500. Когда клиент запускает обновлённый софт, то он считает блоки младше 100500 валидными при размере меньше 1 мб, а начиная с блока 100500 также валидными будут считаться блоки размером до 2 мб. Но старый софт будет рассматривать блоки старше 100500 и размером больше 1 мб как невалидные, так как он не знает о новых правилах построения цепи и считает консенсусом блоки не более 1 мб. В данном случае это хардфорк и цепь блоков разбивается на две ветви;
- транзакции концептуально тоже можно представить в виде цепочки, в которой входы в текущей транзакции являются выходами из предыдущей. Но ключевым отличием от цепочки блоков является отсутствие проверки всей цепи на валидность: когда майнеры принимают транзакцию к обработке, им достаточно удостовериться, что вход ссылается на непотраченный выход, а как он был сформирован, это уже их не касается. Этот механизм позволяет старым нодам валидировать транзакции, ссылающиеся на выходы, сформированные по новым правилам, благодаря тому, что ноде достаточно увидеть непотраченный выход, а как он был сформирован вплоть до coinbase транзакции, ей это не интересно.