Вы когда-нибудь хотели узнать больше о том, как работает Rollup? Теория хорошая, но практический опыт всегда предпочтительнее. К сожалению, существующие проекты не всегда позволяют легко увидеть, что происходит. Вот почему мы создали BYOR (Build Your Own Rollup). Это суверенный роллап с минимальной функциональностью, с акцентом на то, чтобы сделать код легким для чтения и понимания.
Наша мотивация для этого проекта заключается в том, чтобы люди, как посторонние, так и инсайдеры, лучше понимали, что на самом деле делают роллапы вокруг нас. Вы можете поэкспериментировать с развернутым BYOR от Holesky или прочитать исходный код на GitHub.
Что такое BYOR?
Проект BYOR представляет собой упрощенную версию суверенного роллапа. В отличие от оптимистичных доказательств и доказательств с нулевым разглашением роллапов, суверенные роллапы не проверяют корни состояний в Ethereum и полагаются только на доступность данных и консенсус в Ethereum. Это предотвращает создание мостов между L1 и BYOR, но значительно упрощает код и идеально подходит для образовательных целей.
Кодовая база состоит из трех программ: смарт-контрактов, узлов и кошельков. При совместном развертывании они позволяют конечным пользователям взаимодействовать с сетью. Интересно, что состояние сети полностью определяется ончейн-данными, а это означает, что на самом деле может работать несколько узлов. Каждый узел также может публиковать данные независимо в качестве секвенсора.
Вот полный список возможностей, реализованных в BYOR:
Сортировка по сборам
Отправка статуса в L1 и получение статуса из L1
Отбрасывайте недействительные транзакции
Проверка баланса счета
Отправляйте транзакции
Проверка статуса транзакции
Используйте кошелек
В приложении-кошельке он выступает в качестве интерфейса сети, где пользователи могут отправлять транзакции и проверять статус своих счетов или статус транзакций. На целевой странице вы увидите обзор, в котором представлена некоторая статистика о текущем статусе накопительного пакета, а также о состоянии вашего аккаунта. Скорее всего, есть только одна кнопка для подключения к выбранному вами кошельку и есть новость о кране токена. Ниже находится строка поиска, куда вы можете вставить чей-то адрес или хэш транзакции, чтобы изучить текущее состояние L2. Наконец, есть два списка транзакций: первый — это список транзакций в мемпуле L2, а второй — список транзакций, опубликованных в L1.
Для начала используйте кнопку WalletConnect, чтобы подключить свой кошелек. После подключения вы можете получить уведомление о том, что ваш кошелек подключен не к той сети. Если ваше приложение поддерживает сетевую коммутацию, нажмите кнопку Переключить сеть, чтобы переключиться на тестовую сеть Holesky. В противном случае переключитесь вручную.
Теперь вы можете отправить токены кому-либо, указав адрес получателя, количество токенов для отправки и необходимые комиссии. После отправки приложение-кошелек предложит вам подписать сообщение. В случае успешной подписи сообщение отправляется в пул памяти узла L2 и ожидает публикации в узле L1. Время, необходимое для включения транзакции в пакетный выпуск, может отличаться. Каждые 10 секунд узел L2 проверяет наличие содержимого для публикации. Транзакции с более высокими комиссиями отправляются первыми, поэтому, если вы укажете более низкие комиссии и у вас будет много трафика транзакций, вы можете столкнуться с длительным временем ожидания.
Как это работает
Диаграмма архитектуры свертки ## стек технологий
Мы построили каждый компонент, используя следующие методы:
Код BYOR разработан таким образом, чтобы его можно было легко понять, взглянув на кодовую базу. Не стесняйтесь изучать нашу кодовую базу! Сначала прочтите README.md, чтобы понять структуру проекта, пожалуйста, прочтите файл ARCHITECTURE.md.
Вот несколько интересных моментов из кода:
Смарт-контракты
Идентификатор лицензии SPDX: MIT
твердость прагмы ^0.8.0;
Входные данные контракта {
событие BatchAppended(адрес отправителя);
function appendBatch(bytes calldata) external {
require(msg.sender == tx.origin);
emit BatchAppended(msg.sender);
}
}
Это единственный необходимый смарт-контракт. Его название происходит от того факта, что входные данные хранятся в функциях перехода между состояниями. Единственной целью этого договора является удобное хранение всех транзакций. Сериализованный пакет публикуется в этом смарт-контракте как calldata, и он генерирует событие BatchAppended с адресом издателя пакета. Хотя мы можем спроектировать систему таким образом, чтобы она публиковала транзакции непосредственно в EOA, а не контракты, данные можно легко получить через JSON-RPC, генерируя события. Единственное требование к этому смарт-контракту заключается в том, что он должен быть вызван не из другого смарт-контракта, а непосредственно из EOA.
Схема базы данных
СОЗДАНИЕ ТАБЛИЦ учетных записей (
address text PRIMARY KEY NOT NULL,
balance integer DEFAULT 0 NOT NULL,
nonce integer ПО УМОЛЧАНИЮ 0 НЕ NULL
);
ТРАНЗАКЦИИ CREATE TABLE (
id целое число,
из текста NOT NULL,
в текст NOT NULL,
value integer NOT NULL,
nonce integer NOT NULL,
fee integer NOT NULL,
feeReceipent текст NOT NULL,
l1SubmittedDate целое число NOT NULL,
хеш-текст НЕ NULL
ПЕРВИЧНЫЙ КЛЮЧ(от, nonce)
);
-- Эта таблица содержит одну строку
CREATE TABLE fetcherStates (
chainId integer PRIMARY KEY NOT NULL,
lastFetchedBlock integer DEFAULT 0 NOT NULL
);
Это вся схема базы данных, используемая для хранения сведений о Rollup. Вы можете задаться вопросом, зачем нужна база данных, когда все необходимые данные хранятся на L1. Несмотря на то, что это так, локальное хранение данных может сэкономить время и ресурсы, избегая дублирования. Обрабатывайте все данные, хранящиеся в этой схеме, как записки о состоянии, хэши транзакций и другую вычисляемую информацию.
Таблица fetcherStates используется для отслеживания последнего блока, который мы извлекли при поиске события BatchAppended. Это полезно, когда узел завершает работу и перезапускается; Он знает, где возобновить поиск.
Функции, показанные выше, лежат в основе механизма перехода от одного состояния к другому в BYOR. Он предполагает, что транзакция может быть выполнена безопасно, с правильным одноразовым номером и достаточным балансом для осуществления определенной выплаты. Из-за этого предположения в этой функции нет шагов по обработке ошибок или проверке. Вместо этого эти шаги выполняются перед вызовом функции. Каждое состояние аккаунта хранится в карте. Если учетная запись еще не существует в этом сопоставлении, для нее будет установлено значение по умолчанию, отображаемое в верхней части списка кода. Из трех используемых учетных записей обновляется одноразовый номер и распределяется баланс.
Подписание транзакций
Подпись транзакции: Мы используем стандарт EIP-712 для подписи вводимых данных. Это позволяет нам четко показывать пользователям, что они подписывают. Как показано выше, при отправке транзакции мы можем отобразить получателя, сумму и комиссию в удобном для пользователя виде.
Чтобы получить новое событие, мы извлекаем все события BatchAppended из последнего выбранного блока из контракта Inputs. Максимальное количество получаемых событий — это самый последний блок или последний выбранный фрагмент плюс ограничение на размер пакета. После получения всех событий мы извлекаем данные вызова, метку времени и адрес издателя из каждой транзакции. Обновите последний блок, который мы извлекаем, на последний блок, который мы получаем. Извлеченные данные вызова, метка времени и издатель затем упаковываются вместе и возвращаются из функции для дальнейшей обработки.
Пулы памяти и их стоимостная сортировка
function popNHighestFee(txPool, n) {
txPool.sort((a, b) => b.fee - a.fee))
return txPool.splice(0, n)
}
Мемпул — это объект, который управляет массивом подписанных транзакций. Наиболее интересным аспектом является то, как он определяет порядок, в котором проводки разносятся в L1. Как показано в приведенном выше коде, транзакции сортируются в соответствии с их комиссиями. Это позволяет медианной цене комиссии в системе колебаться в зависимости от активности в сети.
Даже если вы укажете высокие комиссии, транзакции все равно должны создавать допустимое состояние, если их нужно добавить к текущему состоянию. Таким образом, вы не можете отправлять недействительные транзакции только из-за высоких комиссий.
Действительно ли BYOR масштабирует Ethereum?
Optimism и ZK Rollup создали системы, доказывающие, что опубликованные корни состояний согласуются с функциями перехода состояний и данными, которые они фиксируют, а суверенные роллапы — нет. Поэтому неспособность такого типа роллапа масштабировать Ethereum на первый взгляд может показаться нелогичной. Однако это становится разумным, когда мы понимаем, что другие типы сверток могут использовать только L1 для доказательства правильности опубликованного корня состояния. Чтобы определить, корректны данные суверенного роллапа или нет, нам нужно запустить узел L1 вместе с дополнительным программным обеспечением для формализации узла L2 для выполнения функций перехода состояния, тем самым увеличив вычислительную нагрузку.
Перспективы на будущее
Создание этого проекта стало для нас отличным опытом, и мы надеемся, что наши усилия также оценятся для вас. Мы надеемся вернуться к BYOR в будущем и добавить в него систему защиты от мошенничества. Это сделает его по-настоящему оптимистичным и еще раз уроком внутренней работы систем, которые мы используем каждый день.
Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
Создайте свой собственный Rollup — список проектов BYOR
Подборка: План перевода Denlink
Вы когда-нибудь хотели узнать больше о том, как работает Rollup? Теория хорошая, но практический опыт всегда предпочтительнее. К сожалению, существующие проекты не всегда позволяют легко увидеть, что происходит. Вот почему мы создали BYOR (Build Your Own Rollup). Это суверенный роллап с минимальной функциональностью, с акцентом на то, чтобы сделать код легким для чтения и понимания.
Наша мотивация для этого проекта заключается в том, чтобы люди, как посторонние, так и инсайдеры, лучше понимали, что на самом деле делают роллапы вокруг нас. Вы можете поэкспериментировать с развернутым BYOR от Holesky или прочитать исходный код на GitHub.
Что такое BYOR?
Проект BYOR представляет собой упрощенную версию суверенного роллапа. В отличие от оптимистичных доказательств и доказательств с нулевым разглашением роллапов, суверенные роллапы не проверяют корни состояний в Ethereum и полагаются только на доступность данных и консенсус в Ethereum. Это предотвращает создание мостов между L1 и BYOR, но значительно упрощает код и идеально подходит для образовательных целей.
Кодовая база состоит из трех программ: смарт-контрактов, узлов и кошельков. При совместном развертывании они позволяют конечным пользователям взаимодействовать с сетью. Интересно, что состояние сети полностью определяется ончейн-данными, а это означает, что на самом деле может работать несколько узлов. Каждый узел также может публиковать данные независимо в качестве секвенсора.
Вот полный список возможностей, реализованных в BYOR:
Используйте кошелек
В приложении-кошельке он выступает в качестве интерфейса сети, где пользователи могут отправлять транзакции и проверять статус своих счетов или статус транзакций. На целевой странице вы увидите обзор, в котором представлена некоторая статистика о текущем статусе накопительного пакета, а также о состоянии вашего аккаунта. Скорее всего, есть только одна кнопка для подключения к выбранному вами кошельку и есть новость о кране токена. Ниже находится строка поиска, куда вы можете вставить чей-то адрес или хэш транзакции, чтобы изучить текущее состояние L2. Наконец, есть два списка транзакций: первый — это список транзакций в мемпуле L2, а второй — список транзакций, опубликованных в L1.
Для начала используйте кнопку WalletConnect, чтобы подключить свой кошелек. После подключения вы можете получить уведомление о том, что ваш кошелек подключен не к той сети. Если ваше приложение поддерживает сетевую коммутацию, нажмите кнопку Переключить сеть, чтобы переключиться на тестовую сеть Holesky. В противном случае переключитесь вручную.
Теперь вы можете отправить токены кому-либо, указав адрес получателя, количество токенов для отправки и необходимые комиссии. После отправки приложение-кошелек предложит вам подписать сообщение. В случае успешной подписи сообщение отправляется в пул памяти узла L2 и ожидает публикации в узле L1. Время, необходимое для включения транзакции в пакетный выпуск, может отличаться. Каждые 10 секунд узел L2 проверяет наличие содержимого для публикации. Транзакции с более высокими комиссиями отправляются первыми, поэтому, если вы укажете более низкие комиссии и у вас будет много трафика транзакций, вы можете столкнуться с длительным временем ожидания.
Как это работает
Мы построили каждый компонент, используя следующие методы:
Детализация кода
Код BYOR разработан таким образом, чтобы его можно было легко понять, взглянув на кодовую базу. Не стесняйтесь изучать нашу кодовую базу! Сначала прочтите README.md, чтобы понять структуру проекта, пожалуйста, прочтите файл ARCHITECTURE.md.
Вот несколько интересных моментов из кода:
Смарт-контракты
Идентификатор лицензии SPDX: MIT
твердость прагмы ^0.8.0;
Входные данные контракта {
событие BatchAppended(адрес отправителя);
function appendBatch(bytes calldata) external {
require(msg.sender == tx.origin);
emit BatchAppended(msg.sender);
}
}
Это единственный необходимый смарт-контракт. Его название происходит от того факта, что входные данные хранятся в функциях перехода между состояниями. Единственной целью этого договора является удобное хранение всех транзакций. Сериализованный пакет публикуется в этом смарт-контракте как calldata, и он генерирует событие BatchAppended с адресом издателя пакета. Хотя мы можем спроектировать систему таким образом, чтобы она публиковала транзакции непосредственно в EOA, а не контракты, данные можно легко получить через JSON-RPC, генерируя события. Единственное требование к этому смарт-контракту заключается в том, что он должен быть вызван не из другого смарт-контракта, а непосредственно из EOA.
Схема базы данных
СОЗДАНИЕ ТАБЛИЦ учетных записей (
address text PRIMARY KEY NOT NULL,
balance integer DEFAULT 0 NOT NULL,
nonce integer ПО УМОЛЧАНИЮ 0 НЕ NULL
);
ТРАНЗАКЦИИ CREATE TABLE (
id целое число,
из текста NOT NULL,
в текст NOT NULL,
value integer NOT NULL,
nonce integer NOT NULL,
fee integer NOT NULL,
feeReceipent текст NOT NULL,
l1SubmittedDate целое число NOT NULL,
хеш-текст НЕ NULL
ПЕРВИЧНЫЙ КЛЮЧ(от, nonce)
);
-- Эта таблица содержит одну строку
CREATE TABLE fetcherStates (
chainId integer PRIMARY KEY NOT NULL,
lastFetchedBlock integer DEFAULT 0 NOT NULL
);
Это вся схема базы данных, используемая для хранения сведений о Rollup. Вы можете задаться вопросом, зачем нужна база данных, когда все необходимые данные хранятся на L1. Несмотря на то, что это так, локальное хранение данных может сэкономить время и ресурсы, избегая дублирования. Обрабатывайте все данные, хранящиеся в этой схеме, как записки о состоянии, хэши транзакций и другую вычисляемую информацию.
Таблица fetcherStates используется для отслеживания последнего блока, который мы извлекли при поиске события BatchAppended. Это полезно, когда узел завершает работу и перезапускается; Он знает, где возобновить поиск.
Функции перехода между состояниями
const DEFAULT_ACCOUNT = { balance: 0, nonce: 0 }
function uteTransaction(state, tx, feeRecipient) {
const fromAccount = getAccount(state, tx.from, DEFAULT_ACCOUNT)
const toAccount = getAccount(state, tx.to, DEFAULT_ACCOUNT)
Шаг 1 Обновление nonce
fromAccount.nonce = tx.nonce
Шаг 2 Перевод стоимости
fromAccount.balance -= tx.value
toAccount.balance += tx.value
Шаг 3 Оплатите комиссию
fromAccount.balance -= tx.fee
feeRecipientAccount.balance += tx.fee
}
Функции, показанные выше, лежат в основе механизма перехода от одного состояния к другому в BYOR. Он предполагает, что транзакция может быть выполнена безопасно, с правильным одноразовым номером и достаточным балансом для осуществления определенной выплаты. Из-за этого предположения в этой функции нет шагов по обработке ошибок или проверке. Вместо этого эти шаги выполняются перед вызовом функции. Каждое состояние аккаунта хранится в карте. Если учетная запись еще не существует в этом сопоставлении, для нее будет установлено значение по умолчанию, отображаемое в верхней части списка кода. Из трех используемых учетных записей обновляется одноразовый номер и распределяется баланс.
Подписание транзакций
Событие L1 get
function getNewStates() {
const lastBatchBlock = getLastBatchBlock()
const events = getLogs(lastBatchBlock)
const calldata = getCalldata(events)
const timestamps = getTimestamps(events)
const posters = getTransactionPosters(events)
updateLastFetchedBlock(lastBatchBlock)
return zip(posters, timestamps, calldata)
}
Чтобы получить новое событие, мы извлекаем все события BatchAppended из последнего выбранного блока из контракта Inputs. Максимальное количество получаемых событий — это самый последний блок или последний выбранный фрагмент плюс ограничение на размер пакета. После получения всех событий мы извлекаем данные вызова, метку времени и адрес издателя из каждой транзакции. Обновите последний блок, который мы извлекаем, на последний блок, который мы получаем. Извлеченные данные вызова, метка времени и издатель затем упаковываются вместе и возвращаются из функции для дальнейшей обработки.
Пулы памяти и их стоимостная сортировка
function popNHighestFee(txPool, n) {
txPool.sort((a, b) => b.fee - a.fee))
return txPool.splice(0, n)
}
Мемпул — это объект, который управляет массивом подписанных транзакций. Наиболее интересным аспектом является то, как он определяет порядок, в котором проводки разносятся в L1. Как показано в приведенном выше коде, транзакции сортируются в соответствии с их комиссиями. Это позволяет медианной цене комиссии в системе колебаться в зависимости от активности в сети.
Даже если вы укажете высокие комиссии, транзакции все равно должны создавать допустимое состояние, если их нужно добавить к текущему состоянию. Таким образом, вы не можете отправлять недействительные транзакции только из-за высоких комиссий.
Действительно ли BYOR масштабирует Ethereum?
Optimism и ZK Rollup создали системы, доказывающие, что опубликованные корни состояний согласуются с функциями перехода состояний и данными, которые они фиксируют, а суверенные роллапы — нет. Поэтому неспособность такого типа роллапа масштабировать Ethereum на первый взгляд может показаться нелогичной. Однако это становится разумным, когда мы понимаем, что другие типы сверток могут использовать только L1 для доказательства правильности опубликованного корня состояния. Чтобы определить, корректны данные суверенного роллапа или нет, нам нужно запустить узел L1 вместе с дополнительным программным обеспечением для формализации узла L2 для выполнения функций перехода состояния, тем самым увеличив вычислительную нагрузку.
Перспективы на будущее
Создание этого проекта стало для нас отличным опытом, и мы надеемся, что наши усилия также оценятся для вас. Мы надеемся вернуться к BYOR в будущем и добавить в него систему защиты от мошенничества. Это сделает его по-настоящему оптимистичным и еще раз уроком внутренней работы систем, которые мы используем каждый день.