Транзакции
Последнее редактирование: @dovbyshbgd(opens in a new tab), 16 июля 2024 г.
Транзакции — это криптографически подписанные инструкции от аккаунтов. Аккаунт инициирует транзакцию для обновления состояния сети Ethereum. Самая простая транзакция — перевод ETH с одного аккаунта на другой.
Прежде чем начать
Чтобы помочь вам лучше понять эту страницу, мы рекомендуем сначала прочитать разделы Аккаунты и наше Введение в Ethereum.
Что такое транзакция?
Транзакция Ethereum относится к действию, инициированному внешним аккаунтом, то есть аккаунтом, управляемым человеком, а не контрактом. Например, если Боб отправляет Алисе 1 ETH, аккаунт Боба должен быть дебетован, а счет Алисы — кредитован. Это действие по изменению состояния происходит внутри транзакции.
Источник адаптированной диаграммы: Ethereum EVM illustrated(opens in a new tab)
Транзакции, которые изменяют состояние EVM, должны транслироваться по всей сети. Любой узел может транслировать запрос на выполнение транзакции на EVM; после этого валидатор выполнит транзакцию и распространит результирующее измененное состояние на остальную часть сети.
Транзакции требуют уплаты комиссии и должны быть включены в подтвержденный блок. Чтобы упростить этот обзор, мы рассмотрим плату за газ и валидацию в другом месте.
Отправленная транзакция включает следующую информацию:
from
- адрес отправителя, который будет подписывать транзакцию. Это будет внешний аккаунт, поскольку аккаунты контрактов не могут отправлять транзакции.to
— адрес получателя (если аккаунт внешний, транзакция передаст информацию о стоимости. Если это аккаунт контракта, транзакция выполнит код контракта).signature
— идентификатор отправителя. Он генерируется, когда приватный ключ отправителя подписывает транзакцию и подтверждает, что отправитель авторизовал эту транзакцию.nonce
- последовательно возрастающий счетчик, указывающий номер транзакции аккаунта.value
— количество ETH для передачи от отправителя получателю (номинировано в WEI, где 1ETH равен 1e+18wei).input data
— необязательное поле для включения произвольных данных.gasLimit
— максимальное количество единиц газа, которое может быть использовано транзакцией. EVM определяет количество газа, необходимого для каждого этапа вычислений.maxPriorityFeePerGas
— максимальная цена потребленного газа, которая будет включена в качестве чаевых для валидатора.maxFeePerGas
— максимальная комиссия за единицу газа, которая будет выплачена за транзакцию (включаяbaseFeePerGas
иmaxPriorityFeePerGas
).
Газ — это ссылка на вычисления, необходимые для обработки транзакции валидатором. Пользователи должны платить за это вычисление. GasLimit
и maxPriorityFeePerGas
определяют максимальную комиссию за транзакцию, выплачиваемую валидатору. Подробнее о газе.
Объект транзакции будет выглядеть примерно так:
1{2 from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",3 to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a",4 gasLimit: "21000",5 maxFeePerGas: "300",6 maxPriorityFeePerGas: "10",7 nonce: "0",8 value: "10000000000"9}Показать всеКопировать
Но объект транзакции должен быть подписан с использованием приватного ключа отправителя. Это доказывает, что транзакция могла исходить только от отправителя и не была отправлена обманным путем.
Клиент Ethereum, такой как Geth, будет обрабатывать этот процесс подписи.
Пример вызова JSON-RPC:
1{2 "id": 2,3 "jsonrpc": "2.0",4 "method": "account_signTransaction",5 "params": [6 {7 "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",8 "gas": "0x55555",9 "maxFeePerGas": "0x1234",10 "maxPriorityFeePerGas": "0x1234",11 "input": "0xabcd",12 "nonce": "0x0",13 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",14 "value": "0x1234"15 }16 ]17}Показать всеКопировать
Пример ответа:
1{2 "jsonrpc": "2.0",3 "id": 2,4 "result": {5 "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",6 "tx": {7 "nonce": "0x0",8 "maxFeePerGas": "0x1234",9 "maxPriorityFeePerGas": "0x1234",10 "gas": "0x55555",11 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",12 "value": "0x1234",13 "input": "0xabcd",14 "v": "0x26",15 "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",16 "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",17 "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"18 }19 }20}Показать всеКопировать
raw
— это подписанная транзакция в закодированной форме рекурсивной длины префикса (RLP).tx
— это подписанная транзакция в форме JSON.
С помощью хэша подписи можно криптографически доказать, что транзакция пришла от отправителя и была отправлена в сеть.
Поле данных
В подавляющем большинстве операций доступ к контракту осуществляется с внешнего аккаунта. Большинство контрактов написаны на Solidity и интерпретируют свое поле данных в соответствии с .
Первые четыре байта указывают, какую функцию следует вызвать, используя хэш имени функции и ее аргументов. Иногда можно определить функцию по селектору, используя эту базу данных(opens in a new tab).
Остальная часть calldata — это аргументы, закодированные в соответствии со спецификациями ABI(opens in a new tab).
Например, рассмотрим эту транзакцию(opens in a new tab). Чтобы увидеть calldata, используйте Нажмите, чтобы увидеть больше.
Селектор функции — 0xa9059cbb
. Существует несколько известных функций с такой сигнатурой(opens in a new tab). В этом случае исходный код контракта(opens in a new tab) был загружен в Etherscan, поэтому мы функцию: transfer(address, uint256)
.
Остальные данные таковы:
10000000000000000000000004f6742badb049791cd9a37ea913f2bac38d012792000000000000000000000000000000000000000000000000000000003b0559f4
Согласно спецификациям ABI целочисленные значения (такие как адреса, которые являются 20-байтовыми целыми числами) отображаются в ABI как 32-байтовые слова, заполненные нулями спереди. Итак, мы знаем адрес to
: 4f6742badb049791cd9a37ea913f2bac38d01279
(opens in a new tab). Значение value
равно 0x3b0559f4 = 990206452.
Типы транзакций
В Ethereum существует несколько различных типов транзакций:
- Обычные транзакции: транзакция с одной учетной записи на другую.
- Транзакции развертывания контракта: транзакция без адреса «to», где поле данных используется для кода контракта.
- Исполнение контракта: транзакция, которая взаимодействует с развернутым умным контрактом. В этом случае адрес «to» — это адрес умного контракта.
О газе
Как уже упоминалось, выполнение транзакций требует затрат газа. Для простых транзакций перевода требуется 21 000 единиц газа.
Таким образом, чтобы Боб отправил Алисе 1 ETH с baseFeePerGas
190 gwei и maxPriorityFeePerGas
10 gwei, Бобу необходимо будет заплатить следующую комиссию:
1(190 + 10) * 21 000 = 4 200 000 gwei2--или--30,0042 ETH
Со счета Боба будет списано 1,0042 ETH (1 ETH для Алисы + 0,0042 ETH как комиссия за газ)
На счет Алисы будет зачислено +1,0 ETH
Сжигаемая базовая комиссия составит -0,00399 ЕТН
Валидатор получит +0,000210 ETH
Источник адаптированной диаграммы: Ethereum EVM illustrated(opens in a new tab)
Любой газ, не использованный в транзакции, возвращается в аккаунт пользователя.
Взаимодействия смарт-контрактов
Газ необходим для любой транзакции, которая связана со смарт-контрактом.
Смарт-контракты также могут содержать функции, известные как view
(opens in a new tab) или pure
(opens in a new tab), которые не изменяют состояние контракта. Поэтому для вызова этих функций из внешней учетной записи (EOA) не требуется газ. Базовый вызов RPC для этого сценария — eth_call
В отличие от доступа с помощью eth_call
, эти функции view
или pure
также обычно вызываются внутри (т. е. из самого контракта или из другого контракта), что требует затрат газа.
Жизненный цикл транзакции
После отправки транзакции происходит следующее:
- Хэш транзакции генерируется криптографически:
0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017
- Затем транзакция транслируется в сеть и добавляется в пул транзакций, состоящий из всех других ожидающих транзакций сети.
- Валидатор должен взять вашу транзакцию и включить ее в блок, чтобы подтвердить транзакцию и признать ее «успешной».
- По прошествии времени блок, содержащий вашу транзакцию, будет обновлен до уровня «утвержденный», а затем «завершенный» Эти обновления дают гораздо больше уверенности, что ваша сделка была успешной, а изменить ее невозможно. Как только блок «завершен», он может быть изменен только при атаке на сетевом уровне, которая стоила бы миллиарды долларов.
Визуализация
Посмотрите, как Остин рассказывает о транзакциях, газе и майнинге.
Типизированная оболочка транзакций
Ethereum изначально имел один формат транзакций. Каждая транзакция содержала значение nonce, цену на газ, лимит газа, адрес, значение, данные, v, r и s. Эти поля кодируются с помощью RLP, чтобы выглядеть примерно так:
RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])
Ethereum эволюционировал до поддержки нескольких типов транзакций, чтобы реализовать новые функции, такие как списки доступа и EIP-1559(opens in a new tab), без влияния на старые форматы транзакций.
EIP-2718(opens in a new tab) — это то, что позволяет такие действия. Транзакции интепретируются следующим образом:
TransactionType || TransactionPayload
Где поля определяются так:
TransactionType
: число между 0 и 0x7f, в общей сложности 128 возможных типов транзакций.TransactionPayload
— произвольный байтовый массив, определяемый типом транзакции.
В зависимости от значения TransactionType
транзакция может быть классифицирована как
Транзакции типа 0 (устаревшие). Исходный формат транзакций, используемый с момента запуска Ethereum. Они не включают функций от EIP-1559(opens in a new tab), таких как динамические расчеты затрат газа или списки доступа для смарт-контрактов. Устаревшие транзакции не имеют конкретного префикса, указывающего их тип в сериализованной форме, и начинаются с байта
0xf8
при использовании кодировки RLP. Значение TransactionType для этих транзакций —0x0
.Транзакции типа 1. Эти транзакции, которые появились в EIP-2930(opens in a new tab) в результате обновления Berlin, включают параметр
accessList
. В этом списке указываются адреса и ключи хранения, к которым транзакция должна получить доступ, что потенциально помогает снизить затраты на газ в сложных транзакциях, связанных со смарт-контрактами. Изменения рынка комиссий EIP-1559 не включены в транзакции типа 1. Транзакции типа 1 также включают параметрyParity
, который может быть либо0x0
, либо0x1
, что указывает на четность y-значения подписи secp256k1. Они идентифицируются по байту в начале —0x01
, а их значение TransactionType —0x1
.Транзакции типа 2, обычно называемые транзакциями EIP-1559, являются транзакциями, которые появились в EIP-1559(opens in a new tab) в результате обновления London. Они стали стандартным типом транзакций в сети Ethereum. Эти транзакции создают новый механизм рынка комиссий, который повышает предсказуемость, разделяя комиссию за транзакции на базовую и приоритетную. Они начинаются с байта
0x02
и включают такие поля, какmaxPriorityFeePerGas
иmaxFeePerGas
. Транзакции типа 2 теперь являются стандартными из-за их гибкости и эффективности, особенно предпочтительны в периоды высокой загруженности сети из-за их способности помочь пользователям управлять комиссиями за транзакции более предсказуемо. Значение TransactionType для этих транзакций —0x2
.
Дополнительные ресурсы
Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!