Транзакції
Транзакції — це криптографічно підписані інструкції від акаунтів. Акаунт ініціює транзакцію для оновлення стану мережі Етеріум. Найпростіша транзакція — це переказ ETH з одного акаунта на інший.
Передумови
Щоб краще зрозуміти цю сторінку, ми рекомендуємо спочатку прочитати про Акаунти та наш вступ до Етеріуму.
Що таке транзакція?
Транзакція в Етеріумі — це дія, ініційована зовнішнім акаунтом (externally-owned account, EOA), іншими словами, акаунтом, яким керує людина, а не контракт. Наприклад, якщо Боб надсилає Алісі 1 ETH, з акаунта Боба має бути списано кошти, а на акаунт Аліси — зараховано. Ця дія, що змінює стан, відбувається в межах транзакції.
Діаграму адаптовано з Ethereum EVM illustrated (opens in a new tab)
Транзакції, які змінюють стан EVM, мають бути трансльовані на всю мережу. Будь-який вузол може транслювати запит на виконання транзакції у віртуальній машині Етеріуму (EVM); після цього валідатор виконає транзакцію та поширить отриману зміну стану на решту мережі.
Транзакції вимагають комісії та мають бути включені у валідований блок. Щоб зробити цей огляд простішим, ми розглянемо комісії за газ та валідацію в іншому місці.
Надіслана транзакція містить таку інформацію:
from— адреса відправника, який підписуватиме транзакцію. Це буде зовнішній акаунт, оскільки акаунти контрактів не можуть надсилати транзакціїto— адреса отримувача (якщо це зовнішній акаунт, транзакція перекаже цінність. Якщо це акаунт контракту, транзакція виконає код контракту)signature— ідентифікатор відправника. Він генерується, коли приватний ключ відправника підписує транзакцію та підтверджує, що відправник авторизував цю транзакціюnonce— лічильник, що послідовно збільшується та вказує номер транзакції з акаунта (нонс)value— сума ETH для переказу від відправника до отримувача (номінована у Wei, де 1 ETH дорівнює 1e+18 Wei)input data— необов'язкове поле для включення довільних данихgasLimit— максимальна кількість одиниць газу, яка може бути спожита транзакцією (ліміт газу). EVM визначає одиниці газу, необхідні для кожного обчислювального крокуmaxPriorityFeePerGas— максимальна ціна спожитого газу, яка буде включена як пріоритетна комісія валідаторуmaxFeePerGas— максимальна комісія за одиницю газу, яку готові сплатити за транзакцію (включно зbaseFeePerGasтаmaxPriorityFeePerGas)
Газ — це посилання на обчислення, необхідні для обробки транзакції валідатором. Користувачі повинні сплачувати комісію за ці обчислення. gasLimit та maxPriorityFeePerGas визначають максимальну комісію за транзакцію, що сплачується валідатору. Детальніше про газ.
Об'єкт транзакції виглядатиме приблизно так:
{
from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a",
gasLimit: "21000",
maxFeePerGas: "300",
maxPriorityFeePerGas: "10",
nonce: "0",
value: "10000000000"
}
Але об'єкт транзакції має бути підписаний за допомогою приватного ключа відправника. Це доводить, що транзакція могла надійти лише від відправника і не була надіслана шахрайським шляхом.
Клієнт Етеріуму, такий як Geth, оброблятиме цей процес підписання.
Приклад виклику JSON-RPC:
{
"id": 2,
"jsonrpc": "2.0",
"method": "account_signTransaction",
"params": [
{
"from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
"gas": "0x55555",
"maxFeePerGas": "0x1234",
"maxPriorityFeePerGas": "0x1234",
"input": "0xabcd",
"nonce": "0x0",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x1234"
}
]
}
Приклад відповіді:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"tx": {
"nonce": "0x0",
"maxFeePerGas": "0x1234",
"maxPriorityFeePerGas": "0x1234",
"gas": "0x55555",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x1234",
"input": "0xabcd",
"v": "0x26",
"r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
"s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
}
}
}
raw— це підписана транзакція у закодованій формі Recursive Length Prefix (RLP)tx— це підписана транзакція у форматі JSON
За допомогою хешу підпису можна криптографічно довести, що транзакція надійшла від відправника та була надіслана в мережу.
Поле даних
Переважна більшість транзакцій звертається до контракту із зовнішнього акаунта. Більшість контрактів написані на Solidity та інтерпретують своє поле даних відповідно до .
Перші чотири байти вказують, яку функцію викликати, використовуючи хеш імені функції та її аргументів. Іноді ви можете ідентифікувати функцію за селектором, використовуючи цю базу даних (opens in a new tab).
Решта даних виклику — це аргументи, закодовані відповідно до специфікацій ABI (opens in a new tab).
Наприклад, розглянемо цю транзакцію (opens in a new tab). Використайте Click to see More, щоб побачити дані виклику.
Селектор функції — 0xa9059cbb. Існує кілька відомих функцій із цим підписом (opens in a new tab).
У цьому випадку вихідний код контракту (opens in a new tab) було завантажено на Etherscan, тому ми знаємо, що це функція transfer(address,uint256).
Решта даних:
0000000000000000000000004f6742badb049791cd9a37ea913f2bac38d01279
000000000000000000000000000000000000000000000000000000003b0559f4
Відповідно до специфікацій ABI, цілочисельні значення (наприклад, адреси, які є 20-байтовими цілими числами) з'являються в ABI як 32-байтові слова, доповнені нулями спереду.
Отже, ми знаємо, що адреса to — це 4f6742badb049791cd9a37ea913f2bac38d01279 (opens in a new tab).
value дорівнює 0x3b0559f4 = 990206452.
Дескриптори транзакцій
Оскільки поле даних містить непрозорі шістнадцяткові байти, може бути вкрай важко перевірити, яку саме дію насправді виконає транзакція. Ця вразливість «сліпого підписання» вирішується за допомогою прозорого підписання (Clear Signing) (opens in a new tab) через використання дескрипторів транзакцій (opens in a new tab) (визначених у ERC-7730).
Специфікація ERC-7730 використовує дескриптори транзакцій (часто структуровані як файли JSON) для збагачення даних, що містяться в ABI та структурованих повідомленнях, таких як дані виклику транзакцій EVM, повідомлення EIP-712 та операції користувача EIP-4337. Розробники використовують ці дескриптори для відображення конкретних змінних транзакції безпосередньо в шаблони форматування, гарантуючи, що базові дані залишаються машинозчитуваними для застосунків.
На фронтенді гаманці використовують цей контекст форматування для перекладу непрозорого байт-коду в зрозумілу, зручну для читання людиною інформацію. Завдяки автоматичному перетворенню значень, таких як адреси токенів, у розпізнані тикери, або сум у десяткові дроби, користувачам надається зрозумілий опис точного наміру транзакції (наприклад, «Обмін 1000 USDC на щонайменше 0.25 WETH») перед тим, як вони її підпишуть.
Типи транзакцій
В Етеріумі існує кілька різних типів транзакцій:
- Звичайні транзакції: транзакція з одного акаунта на інший.
- Транзакції розгортання контракту: транзакція без адреси «to» (кому), де поле даних використовується для коду контракту.
- Виконання контракту: транзакція, яка взаємодіє з розгорнутим смарт-контрактом. У цьому випадку адреса «to» — це адреса смарт-контракту.
Про газ
Як уже згадувалося, виконання транзакцій коштує газу. Прості транзакції переказу вимагають 21000 одиниць газу.
Отже, щоб Боб надіслав Алісі 1 ETH за baseFeePerGas (базової комісії) 190 Gwei та maxPriorityFeePerGas (пріоритетної комісії) 10 Gwei, Бобу доведеться сплатити таку комісію:
(190 + 10) * 21000 = 4,200,000 Gwei
--або--
0.0042 ETH
З акаунта Боба буде списано -1.0042 ETH (1 ETH для Аліси + 0.0042 ETH комісії за газ)
На акаунт Аліси буде зараховано +1.0 ETH
Базова комісія буде спалена -0.00399 ETH
Валідатор залишає собі пріоритетну комісію +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 - Потім транзакція транслюється в мережу та додається до пулу транзакцій, що складається з усіх інших мережевих транзакцій, які очікують на виконання.
- Валідатор має вибрати вашу транзакцію та включити її в блок, щоб перевірити транзакцію та вважати її «успішною».
- З часом блок, що містить вашу транзакцію, буде оновлено до статусу «обґрунтований», а потім — «фіналізований». Ці оновлення дають набагато більшу впевненість у тому, що ваша транзакція була успішною і ніколи не буде змінена. Щойно блок стає «фіналізованим», його можна змінити лише за допомогою атаки на рівні мережі, яка коштуватиме багато мільярдів доларів.
Візуальна демонстрація
Подивіться, як Остін розповідає про транзакції, газ та майнінг.
Типізований конверт транзакції
Спочатку Етеріум мав один формат для транзакцій. Кожна транзакція містила нонс, ціну газу, ліміт газу, адресу отримувача (to), суму (value), дані (data), v, r та s. Ці поля кодуються за допомогою RLP і виглядають приблизно так:
RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])
Етеріум еволюціонував для підтримки кількох типів транзакцій, щоб дозволити впровадження нових функцій, таких як списки доступу та EIP-1559 (opens in a new tab), без впливу на застарілі формати транзакцій.
EIP-2718 (opens in a new tab) — це те, що уможливлює таку поведінку. Транзакції інтерпретуються як:
TransactionType || TransactionPayload
Де поля визначаються як:
TransactionType— число від 0 до 0x7f, загалом 128 можливих типів транзакцій.TransactionPayload— довільний масив байтів, визначений типом транзакції.
На основі значення TransactionType транзакцію можна класифікувати як:
-
Транзакції типу 0 (застарілі): Оригінальний формат транзакцій, що використовується з моменту запуску Етеріуму. Вони не включають функції з EIP-1559 (opens in a new tab), такі як динамічні розрахунки комісії за газ або списки доступу для смарт-контрактів. Застарілі транзакції не мають спеціального префікса, що вказує на їхній тип у серіалізованій формі, і починаються з байта
0xf8при використанні кодування Recursive Length Prefix (RLP). Значення TransactionType для цих транзакцій —0x0. -
Транзакції типу 1: Представлені в EIP-2930 (opens in a new tab) як частина оновлення Берлін в Етеріумі, ці транзакції включають параметр
accessList. Цей список визначає адреси та ключі сховища, до яких транзакція очікує отримати доступ, допомагаючи потенційно зменшити витрати газу для складних транзакцій за участю смарт-контрактів. Зміни ринку комісій EIP-1559 не включені в транзакції типу 1. Транзакції типу 1 також включають параметрyParity, який може бути0x0або0x1, що вказує на парність значення y підпису secp256k1. Вони ідентифікуються тим, що починаються з байта0x01, а їхнє значення TransactionType —0x1. -
Транзакції типу 2, які часто називають транзакціями EIP-1559, — це транзакції, представлені в EIP-1559 (opens in a new tab) під час оновлення Лондон в Етеріумі. Вони стали стандартним типом транзакцій у мережі Етеріум. Ці транзакції запроваджують новий механізм ринку комісій, який покращує передбачуваність шляхом поділу комісії за транзакцію на базову комісію та пріоритетну комісію. Вони починаються з байта
0x02і включають такі поля, якmaxPriorityFeePerGasтаmaxFeePerGas. Транзакції типу 2 тепер використовуються за замовчуванням завдяки їхній гнучкості та ефективності, і їм особливо віддають перевагу в періоди високого перевантаження мережі за їхню здатність допомагати користувачам більш передбачувано керувати комісіями за транзакції. Значення TransactionType для цих транзакцій —0x2. -
Транзакції типу 3 (блоб-транзакції) були представлені в EIP-4844 (opens in a new tab) як частина оновлення Денкун в Етеріумі. Ці транзакції призначені для більш ефективної обробки даних «блобів» (великих двійкових об'єктів), що особливо корисно для ролапів рівня 2 (l2), оскільки забезпечує спосіб публікації даних у мережі Етеріум за нижчою ціною. Блоб-транзакції включають додаткові поля, такі як
blobVersionedHashes,maxFeePerBlobGasтаblobGasPrice. Вони починаються з байта0x03, а їхнє значення TransactionType —0x3. Блоб-транзакції є значним покращенням доступності даних та можливостей масштабування Етеріуму. -
Транзакції типу 4 були представлені в EIP-7702 (opens in a new tab) як частина оновлення Пектра в Етеріумі. Ці транзакції розроблені для забезпечення прямої сумісності з абстракцією облікового запису. Вони дозволяють зовнішнім акаунтам (EOA) тимчасово поводитися як акаунти контрактів без шкоди для їхньої початкової функціональності. Вони включають параметр
authorization_list, який визначає смарт-контракт, якому EOA делегує свої повноваження. Після транзакції поле коду EOA міститиме адресу делегованого смарт-контракту.
Додаткові матеріали
Знаєте ресурс спільноти, який вам допоміг? Відредагуйте цю сторінку та додайте його!