Fabric и Ethereum: одна задача, два решения
Зачем это нужно
За пять глав про Fabric и двадцать глав про Ethereum накопилось два способа делать одно и то же. На чемпионате может достаться любой, а в жизни выбор придётся обосновывать перед человеком, который спросит «зачем нам блокчейн вообще».
Эта глава — не список «десять отличий». Это одна и та же задача, написанная дважды и запущенная вживую: зачётная книжка на Solidity в сети geth и она же чейнкодом в сети Fabric. Числа ниже сняты в этой же сессии.
Та же зачётка на Solidity
Вот контракт, который делает ровно то же, что чейнкод из главы про смарт-контракт Fabric:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract Zachetka {
struct Ocenka { string predmet; uint8 ball; }
struct Zapis { string fio; string gruppa; bool est; }
mapping(string => Zapis) private zapisi;
mapping(string => Ocenka[]) private ocenki;
event Zavedena(string id, string fio);
event OcenkaPostavlena(string id, string predmet, uint8 ball);
function zavesti(string calldata id, string calldata fio, string calldata gruppa) external {
require(!zapisi[id].est, "Zachetka uzhe zavedena");
zapisi[id] = Zapis(fio, gruppa, true);
emit Zavedena(id, fio);
}
function postavitOcenku(string calldata id, string calldata predmet, uint8 ball) external {
require(zapisi[id].est, "Zachetki net");
require(ball >= 2 && ball <= 5, "Ball vne diapazona 2..5");
ocenki[id].push(Ocenka(predmet, ball));
emit OcenkaPostavlena(id, predmet, ball);
}
}
Сравните построчно с чейнкодом. Проверки те же: «уже заведена», «зачётки нет», «балл вне диапазона». Логика та же. Разница — в четырёх местах:
Живой прогон обеих
Развёртываем контракт в сети geth и проделываем те же операции:
развёртывание: газ 994183 | адрес 0x5FbDB2315678afecb367f032d93F642f64180aa3
завести зачётку: газ 95512
поставить оценку: газ 96830
вторая оценка: газ 79802
чтение (бесплатно): Ковалик Олег | ИС-21 | Базы данных=5, Веб-разработка=4
балл 7: execution reverted: "Ball vne diapazona 2..5"
повторная зачётка: execution reverted: "Zachetka uzhe zavedena"
чужая зачётка: execution reverted: "Zachetki net"
найдено событий: 2 → Базы данных=5, Веб-разработка=4
Те же операции в Fabric:
поставить оценку (с ожиданием записи): real 2.22 / real 2.11 / real 2.12
прочитать зачётку: real 0.06 / real 0.07 / real 0.06
Три наблюдения из этих чисел.
Газ. Каждая запись в Ethereum стоит: почти сто тысяч единиц за постановку одной оценки. В настоящей сети это деньги. В Fabric платы нет вообще — сеть своя, а расходы это расходы на серверы.
Задержка. Fabric пишет за 2,1 секунды, и это почти целиком таймаут пачки блоков (BatchTimeout: 2s). То есть задержкой здесь управляют: уменьшили настройку — стало быстрее. В открытой сети время блока задано снаружи, и повлиять на него нельзя.
Вторая оценка дешевле первой — 79 802 против 96 830. Так работает плата за память в Ethereum: первая запись в пустую ячейку дороже последующих. В Fabric такой арифметики нет вовсе.
Интересная мелочь: кириллица в данных прошла оба пути нормально. А вот сообщения об отказе в Fabric утилита peer печатает восьмеричными последовательностями, тогда как ethers показывает текст require как есть. Поэтому в чейнкоде тексты ошибок лучше писать латиницей — их читают через CLI.
Восемь отличий, из которых следует всё остальное
| Ось | Ethereum | Fabric |
|---|---|---|
| Личность | ключ, сгенерированный самим | сертификат, выданный организацией |
| Кто читает | весь мир | участники канала |
| Язык | Solidity | TypeScript, Go, Java |
| Порядок работы | упорядочить → исполнить | исполнить → упорядочить → проверить |
| Окончательность | через подтверждения | сразу |
| Плата | газ в монете сети | нет |
| Обновление кода | новый адрес или прокси-контракт | номер правки плюс один |
| Состояние | поля контракта | общее хранилище «ключ — значение» |
Остановимся на двух строках, потому что из них выводится больше всего.
Порядок работы. В Ethereum узел исполняет транзакции из уже готового блока, строго по очереди. Поэтому недетерминированный код там не проблема — все считают одно и то же в одном порядке. В Fabric код исполняют независимые пиры до всякой очереди, поэтому детерминизм становится жёстким требованием, а состязание за один ключ даёт MVCC_READ_CONFLICT.
Обновление. В Ethereum развёрнутый контракт неизменяем. Чтобы поправить ошибку, разворачивают новый и переводят на него пользователей, либо заранее строят схему с прокси-контрактом — отдельная большая тема со своими уязвимостями. В Fabric обновление — штатная операция: те же пять шагов с номером правки на единицу больше, состояние остаётся на месте.
Возможность обновлять код — это одновременно и удобство, и потеря гарантии. В открытой сети «код есть закон» работает потому, что код нельзя подменить. В Fabric большинство организаций канала может поменять правила — и это нормально ровно настолько, насколько они связаны договором.
Что осталось одинаковым
Список различий длинный, и от него легко сделать вывод, что это разные миры. Одинакового не меньше.
- Цепочка блоков, где каждый ссылается на хеш предыдущего. Переписать прошлое нельзя ни там, ни там.
- Только дописывание. Ошибочную запись исправляют новой записью, а не правкой старой.
- Подписи под каждой сделкой и проверка, что подписант имеет право.
- Код как источник правды: правила применяются одинаково ко всем и выполняются автоматически.
- Исполнение на нескольких независимых узлах с последующей сверкой.
- Детерминизм и явные проверки как основа: те же
require, те же отказы, та же привычка писать проверку первой строкой функции.
Поэтому переход между ними — это переучивание инструментов, а не образа мышления. Человек, который разобрал повторный вход и порядок «проверки, запись, вызовы», в Fabric сядет и напишет рабочий чейнкод к вечеру.
Как выбирать
Вопрос ровно один: можно ли назвать участников по именам заранее?
Если нет — открытая сеть. Токены, публичные рынки, обмен без посредника, любой желающий с кошельком. Цена: газ, публичность и чужая скорость.
Если да — закрытая. Журнал дипломов, цепочка поставок, документооборот между филиалами, медицинские записи. Цена: своя инфраструктура и договор между участниками.
И третий, самый частый на практике ответ: блокчейн не нужен вовсе. Если участник один — хватит базы данных с журналом изменений. Блокчейн решает задачу недоверия между несколькими сторонами; там, где сторона одна, он добавляет сложность и ничего не возвращает.
Три признака, что задача действительно для блокчейна:
- участников несколько, и они не подчиняются друг другу;
- им нужен общий журнал, а не обмен копиями;
- никто из них не должен иметь возможности переписать прошлое незаметно для остальных.
Не набралось всех трёх — скорее всего, нужна база данных.
Типичные ошибки
Ошибка 1. «Fabric — это Ethereum попроще».
Нет. Это ответ на другой вопрос. Из Fabric нельзя сделать открытую сеть, а из Ethereum — закрытую, не выбросив половину смысла.
Ошибка 2. Переносить привычки Solidity в чейнкод.
Самая частая: попытка держать состояние в полях класса. Поля есть, они даже работают между вызовами внутри контейнера, но в реестр не попадают — и на другом пире их не будет.
Ошибка 3. Считать, что закрытая сеть безопаснее.
Закрытая сеть защищена ровно настолько, насколько защищены выданные сертификаты и настроены политики. Ошибка в политике — и одна организация тихо получает право менять всё.
Ошибка 4. Обещать неизменяемость там, где код можно обновить.
В Fabric большинство организаций канала может поменять чейнкод. Формулировка «запись нельзя подделать» верна, «правила нельзя изменить» — нет.
Ошибка 5. Брать блокчейн туда, где участник один.
Самая дорогая. База данных с журналом изменений решит задачу быстрее, дешевле и понятнее.
Шпаргалка по главе
| Вопрос | Ethereum | Fabric |
|---|---|---|
| Как войти | завести ключ самому | получить сертификат |
| Кто видит записи | все | участники канала |
| Сколько стоит запись | газ | нисколько |
| Когда запись окончательна | после подтверждений | сразу |
| Где состояние | поля контракта | хранилище «ключ — значение» |
| История поля | собирают из событий | getHistoryForKey |
| Как обновить код | новый адрес или прокси | номер правки + 1 |
| Что проверять после вызова | чек транзакции | состояние или --waitForEvent |
Словарь главы
| Термин | Что это |
|---|---|
| Открытая сеть | Сеть, куда входят без разрешения; записи видны всем |
| Закрытая сеть | Сеть по сертификатам; записи видны участникам канала |
| Газ | Плата за вычисления и память в открытой сети |
| Окончательность | Момент, с которого запись точно не исчезнет |
| Прокси-контракт | Приём обновления кода в Ethereum: адрес постоянный, логика заменяемая |
| Номер правки | Способ обновления в Fabric: определение с номером на единицу больше |
| «Код есть закон» | Правило открытых сетей, держащееся на невозможности подменить код |
Цель: скорость ≥ 95 зн/мин, точность ≥ 88%
require(!zapisi[id].est, "Zachetka uzhe zavedena");
Что должен уметь после главы
- написать одну и ту же логику двумя способами и объяснить, чем отличается код;
- назвать цену записи в обеих системах и объяснить, из чего складывается задержка;
- перечислить восемь отличий и вывести из них остальные особенности;
- назвать то, что осталось одинаковым, и объяснить, почему переход несложен;
- выбрать систему под задачу одним вопросом про участников;
- честно сказать заказчику, когда блокчейн не нужен вовсе.
Проверка по главе
Сводная проверка по всей главе: 10 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.
Сводная проверка по 6 главам блока: 25 вопросов, 10:00 на всё, по одному вопросу, без возврата. Пересдавать можно сколько угодно раз.
Готовность: экзамены глав сданы 0 из 6. Блок можно сдавать и так, но шанс выше после всех глав.
Куда дальше: проверенные ресурсы
- Сравнение платформ распределённого реестра — официальный разбор, чем Fabric отличается от открытых сетей.
- Модель Fabric — все ключевые решения платформы в одном месте.
- Прокси-контракты OpenZeppelin — как обновляют код в Ethereum и чем за это платят.
- Blockchain, Not Bitcoin — материалы фонда о применении закрытых сетей в отраслях.
Комментарии
Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.