Реестр

Реестр - это последовательная и защищенная от взлома запись всех изменений состояния. Изменения состояний - это результат вызовов чейнкода («транзакций»), сделанных участвующими сторонами. Результат выполнения каждой транзакции - это создание, изменение или удаление множества пар ключей и значений активов.

Реестр состоит из блокчейна („цепочки блоков“) для хранения неизменяемых, последовательных записей в блоках, а также базы данных состояния для поддержания текущего состояния. В каждом канале существует только один реестр. Каждый одноранговый узел поддерживает копию реестра для каждого канала, членом которого он является.

Цепочка блоков

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

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

База данных состояния

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

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

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

Исполнение транзакций

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

Из полученных одобрений клиент собирает данные транзакции и отправляет транзакцию в службу упорядочения. Служба упорядочения рассылает блоки транзакций всем одноранговым узлам в канале.

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

Во-вторых, одноранговые узлы проверяют версии значений в наборе чтения транзакции, чтобы обеспечить целостность данных и защититься от таких угроз, как двойное расходование. В Hyperledger Fabric есть контроль параллелизма, при котором транзакции выполняются параллельно (одобряющими узлами) для увеличения пропускной способности, а при записи транзакции в реестр (всеми одноранговыми узлами) проверятся, что никакая другая транзакция не изменила данные, которые проверяемая транзакция прочитала. Другими словами, проверяется, что данные, которые были прочитаны во время исполнения чейнкода, не изменились с момента одобрения транзакции и результаты исполнения действительны и могут быть записаны в базу состояния реестра. Если же прочитанные данные изменились другой транзакцией, то данная транзакция в блоке помечается как недействительная и ее результаты не применяются к базе состояния реестра. Клиентское приложение получает предупреждение об этом, может обработать ошибку или повторить попытку проведения транзакции в зависимости от ситуации.

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