Изучение базовых тем Эфириума с помощью SQL
Многие руководства по Эфириуму ориентированы на разработчиков, но не хватает образовательных ресурсов для аналитиков данных или для людей, которые хотят просматривать ончейн-данные без запуска клиента или узла.
Это руководство поможет читателям понять фундаментальные концепции Эфириума, включая транзакции, блоки и газ, путем запроса ончейн-данных с помощью языка структурированных запросов (SQL) через интерфейс, предоставляемый Dune Analytics (opens in a new tab).
Ончейн-данные могут помочь нам понять Эфириум, сеть и экономику вычислительных мощностей, а также должны служить базой для понимания проблем, с которыми Эфириум сталкивается сегодня (например, рост цен на газ), и, что более важно, дискуссий вокруг решений для масштабирования.
Транзакции
Путь пользователя в Эфириуме начинается с инициализации контролируемого пользователем аккаунта или сущности с балансом ETH. Существует два типа аккаунтов: контролируемые пользователем и смарт-контракты (см. ethereum.org).
Любой аккаунт можно просмотреть в обозревателе блоков, таком как Etherscan (opens in a new tab) или Blockscout (opens in a new tab). Обозреватели блоков — это портал к данным Эфириума. Они отображают в реальном времени данные о блоках, транзакциях, майнерах, аккаунтах и другой ончейн-активности (см. здесь).
Однако пользователь может захотеть запросить данные напрямую, чтобы сверить информацию, предоставляемую внешними обозревателями блоков. Dune Analytics (opens in a new tab) предоставляет такую возможность любому, кто обладает некоторыми знаниями SQL.
Для справки, аккаунт смарт-контракта Фонда Ethereum (EF) можно просмотреть на Blockscout (opens in a new tab).
Следует отметить, что все аккаунты, включая аккаунт EF, имеют публичный адрес, который можно использовать для отправки и получения транзакций.
Баланс аккаунта на Etherscan состоит из обычных и внутренних транзакций. Внутренние транзакции, несмотря на название, не являются фактическими транзакциями, которые изменяют состояние цепи. Это переводы средств, инициированные выполнением контракта (источник (opens in a new tab)). Поскольку внутренние транзакции не имеют подписи, они не включаются в блокчейн и не могут быть запрошены с помощью Dune Analytics.
Поэтому в данном руководстве основное внимание будет уделено обычным транзакциям. Их можно запросить следующим образом:
WITH temp_table AS (
SELECT
hash,
block_number,
block_time,
"from",
"to",
value / 1e18 AS ether,
gas_used,
gas_price / 1e9 AS gas_price_gwei
FROM ethereum."transactions"
WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
ORDER BY block_time DESC
)
SELECT
hash,
block_number,
block_time,
"from",
"to",
ether,
(gas_used * gas_price_gwei) / 1e9 AS txn_fee
FROM temp_table
Это даст ту же информацию, что и на странице транзакций Etherscan. Для сравнения, вот два источника:
Etherscan
Страница контракта EF на Blockscout. (opens in a new tab)
Dune Analytics
Вы можете найти дашборд здесь (opens in a new tab). Нажмите на таблицу, чтобы увидеть запрос (также см. выше).
Разбор транзакций
Отправленная транзакция включает в себя несколько элементов информации, в том числе (источник):
- Получатель (Recipient): Адрес получения (запрашивается как «to»).
- Подпись (Signature): Хотя транзакция подписывается закрытыми ключами отправителя, с помощью SQL мы можем запросить публичный адрес отправителя («from»).
- Сумма (Value): Это количество переведенных ETH (см. столбец
ether). - Данные (Data): Это произвольные данные, которые были хешированы (см. столбец
data). - Лимит газа (gasLimit) — максимальное количество единиц газа, которое может быть потреблено транзакцией. Единицы газа представляют собой вычислительные шаги.
- maxPriorityFeePerGas — максимальное количество газа, которое будет включено в качестве чаевых майнеру.
- maxFeePerGas — максимальное количество газа, которое отправитель готов заплатить за транзакцию (включая baseFeePerGas и maxPriorityFeePerGas).
Мы можем запросить эти конкретные данные для транзакций на публичный адрес Фонда Ethereum:
SELECT
"to",
"from",
value / 1e18 AS ether,
data,
gas_limit,
gas_price / 1e9 AS gas_price_gwei,
gas_used,
ROUND(((gas_used / gas_limit) * 100),2) AS gas_used_pct
FROM ethereum."transactions"
WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
ORDER BY block_time DESC
Блоки
Каждая транзакция изменяет состояние виртуальной машины Эфириума (EVM) (источник). Транзакции транслируются в сеть для проверки и включения в блок. Каждая транзакция связана с номером блока. Чтобы увидеть данные, мы можем запросить конкретный номер блока: 12396854 (самый последний блок среди транзакций Фонда Ethereum на момент написания статьи, 11.05.2021).
Более того, когда мы запрашиваем следующие два блока, мы видим, что каждый блок содержит хеш предыдущего блока (т. е. родительский хеш), что иллюстрирует, как формируется блокчейн.
Каждый блок содержит ссылку на свой родительский блок. Это показано ниже между столбцами hash и parent_hash (источник):
Вот запрос (opens in a new tab) в Dune Analytics:
SELECT
time,
number,
hash,
parent_hash,
nonce
FROM ethereum."blocks"
WHERE "number" = 12396854 OR "number" = 12396855 OR "number" = 12396856
LIMIT 10
Мы можем изучить блок, запросив время, номер блока, сложность, хеш, родительский хеш и нонс.
Единственное, что не охватывает этот запрос, — это список транзакций, для которого требуется отдельный запрос ниже, и корень состояния (state root). Полный или архивный узел будет хранить все транзакции и переходы состояний, позволяя клиентам запрашивать состояние цепи в любое время. Поскольку для этого требуется большой объем дискового пространства, мы можем отделить данные цепи от данных состояния:
- Данные цепи (список блоков, транзакции)
- Данные состояния (результат перехода состояния каждой транзакции)
Корень состояния относится к последним и является неявными данными (не хранится ончейн), в то время как данные цепи являются явными и хранятся в самой цепи (источник (opens in a new tab)).
В этом руководстве мы сосредоточимся на ончейн-данных, которые можно запросить с помощью SQL через Dune Analytics.
Как указывалось выше, каждый блок содержит список транзакций, мы можем запросить его, отфильтровав по конкретному блоку. Мы попробуем самый последний блок, 12396854:
SELECT * FROM ethereum."transactions"
WHERE block_number = 12396854
ORDER BY block_time DESC`
Вот результат SQL-запроса в Dune:
Добавление этого единственного блока в цепь изменяет состояние виртуальной машины Эфириума (EVM). Десятки, а иногда и сотни транзакций проверяются одновременно. В данном конкретном случае было включено 222 транзакции.
Чтобы увидеть, сколько из них были фактически успешными, мы добавим еще один фильтр для подсчета успешных транзакций:
WITH temp_table AS (
SELECT * FROM ethereum."transactions"
WHERE block_number = 12396854 AND success = true
ORDER BY block_time DESC
)
SELECT
COUNT(success) AS num_successful_txn
FROM temp_table
Для блока 12396854 из 222 транзакций 204 были успешно проверены:
Запросы на транзакции происходят десятки раз в секунду, но блоки фиксируются примерно раз в 15 секунд (источник).
Чтобы убедиться, что один блок создается примерно каждые 15 секунд, мы можем разделить количество секунд в сутках (86400) на 15, чтобы получить расчетное среднее количество блоков в день (~ 5760).
График количества создаваемых блоков Эфириума в день (с 2016 года по настоящее время) выглядит так:
Среднее количество блоков, создаваемых ежедневно за этот период времени, составляет ~5874:
Запросы:
# query to visualize number of blocks produced daily since 2016
SELECT
DATE_TRUNC('day', time) AS dt,
COUNT(*) AS block_count
FROM ethereum."blocks"
GROUP BY dt
OFFSET 1
# average number of blocks produced per day
WITH temp_table AS (
SELECT
DATE_TRUNC('day', time) AS dt,
COUNT(*) AS block_count
FROM ethereum."blocks"
GROUP BY dt
OFFSET 1
)
SELECT
AVG(block_count) AS avg_block_count
FROM temp_table
Среднее количество блоков, создаваемых в день с 2016 года, немного превышает это число и составляет 5874. В качестве альтернативы, разделив 86400 секунд на 5874 средних блока, мы получим 14,7 секунды, или примерно один блок каждые 15 секунд.
Газ
Блоки ограничены в размере. Максимальный размер блока динамичен и варьируется в зависимости от спроса в сети от 12 500 000 до 25 000 000 единиц. Лимиты необходимы для предотвращения создания произвольно больших блоков, создающих нагрузку на полные узлы с точки зрения дискового пространства и требований к скорости (источник).
Один из способов концептуализации лимита газа в блоке — рассматривать его как предложение доступного пространства блока, в котором можно пакетировать транзакции. Лимит газа в блоке можно запросить и визуализировать с 2016 года по сегодняшний день:
SELECT
DATE_TRUNC('day', time) AS dt,
AVG(gas_limit) AS avg_block_gas_limit
FROM ethereum."blocks"
GROUP BY dt
OFFSET 1
Кроме того, существует фактический газ, ежедневно используемый для оплаты вычислений, выполняемых в цепи Эфириума (т. е. отправка транзакции, вызов смарт-контракта, чеканка NFT). Это спрос на доступное пространство блоков Эфириума:
SELECT
DATE_TRUNC('day', time) AS dt,
AVG(gas_used) AS avg_block_gas_used
FROM ethereum."blocks"
GROUP BY dt
OFFSET 1
Мы также можем сопоставить эти два графика вместе, чтобы увидеть, как соотносятся спрос и предложение:
Таким образом, мы можем понимать цены на газ как функцию спроса на пространство блоков Эфириума при наличии доступного предложения.
Наконец, мы можем захотеть запросить средние ежедневные цены на газ для цепи Эфириума, однако это приведет к особенно долгому времени выполнения запроса, поэтому мы отфильтруем наш запрос по среднему количеству газа, уплаченному за транзакцию Фондом Ethereum.
Мы можем увидеть цены на газ, уплаченные за все транзакции, совершенные на адрес Фонда Ethereum за эти годы. Вот запрос:
SELECT
block_time,
gas_price / 1e9 AS gas_price_gwei,
value / 1e18 AS eth_sent
FROM ethereum."transactions"
WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
ORDER BY block_time DESC
Итоги
С помощью этого руководства мы поняли базовые концепции Эфириума и то, как работает блокчейн Эфириума, запрашивая и изучая ончейн-данные.
Дашборд, содержащий весь код, использованный в этом руководстве, можно найти здесь (opens in a new tab).
Чтобы узнать больше об использовании данных для изучения Web3, найдите меня в Твиттере (opens in a new tab).










