Перейти к основному содержанию
Change page

Транзакции

Последнее редактирование: @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).

Остальные данные таковы:

10000000000000000000000004f6742badb049791cd9a37ea913f2bac38d01279
2000000000000000000000000000000000000000000000000000000003b0559f4

Согласно спецификациям 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 gwei
2--или--
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 также обычно вызываются внутри (т. е. из самого контракта или из другого контракта), что требует затрат газа.

Жизненный цикл транзакции

После отправки транзакции происходит следующее:

  1. Хэш транзакции генерируется криптографически: 0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017
  2. Затем транзакция транслируется в сеть и добавляется в пул транзакций, состоящий из всех других ожидающих транзакций сети.
  3. Валидатор должен взять вашу транзакцию и включить ее в блок, чтобы подтвердить транзакцию и признать ее «успешной».
  4. По прошествии времени блок, содержащий вашу транзакцию, будет обновлен до уровня «утвержденный», а затем «завершенный» Эти обновления дают гораздо больше уверенности, что ваша сделка была успешной, а изменить ее невозможно. Как только блок «завершен», он может быть изменен только при атаке на сетевом уровне, которая стоила бы миллиарды долларов.

Визуализация

Посмотрите, как Остин рассказывает о транзакциях, газе и майнинге.

Типизированная оболочка транзакций

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 транзакция может быть классифицирована как

  1. Транзакции типа 0 (устаревшие). Исходный формат транзакций, используемый с момента запуска Ethereum. Они не включают функций от EIP-1559(opens in a new tab), таких как динамические расчеты затрат газа или списки доступа для смарт-контрактов. Устаревшие транзакции не имеют конкретного префикса, указывающего их тип в сериализованной форме, и начинаются с байта 0xf8 при использовании кодировки RLP. Значение TransactionType для этих транзакций — 0x0.

  2. Транзакции типа 1. Эти транзакции, которые появились в EIP-2930(opens in a new tab) в результате обновления Berlin, включают параметр accessList. В этом списке указываются адреса и ключи хранения, к которым транзакция должна получить доступ, что потенциально помогает снизить затраты на газ в сложных транзакциях, связанных со смарт-контрактами. Изменения рынка комиссий EIP-1559 не включены в транзакции типа 1. Транзакции типа 1 также включают параметр yParity, который может быть либо 0x0, либо 0x1, что указывает на четность y-значения подписи secp256k1. Они идентифицируются по байту в начале — 0x01, а их значение TransactionType — 0x1.

  3. Транзакции типа 2, обычно называемые транзакциями EIP-1559, являются транзакциями, которые появились в EIP-1559(opens in a new tab) в результате обновления London. Они стали стандартным типом транзакций в сети Ethereum. Эти транзакции создают новый механизм рынка комиссий, который повышает предсказуемость, разделяя комиссию за транзакции на базовую и приоритетную. Они начинаются с байта 0x02 и включают такие поля, как maxPriorityFeePerGas и maxFeePerGas. Транзакции типа 2 теперь являются стандартными из-за их гибкости и эффективности, особенно предпочтительны в периоды высокой загруженности сети из-за их способности помочь пользователям управлять комиссиями за транзакции более предсказуемо. Значение TransactionType для этих транзакций — 0x2.

Дополнительные ресурсы

Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!

  • Аккаунты
  • Виртуальная машина Ethereum (EVM)
  • Газ

Была ли эта статья полезной?