Перейти до основного вмісту

Вступ до Етеріуму для Python-розробників, частина 1

Python
web3.py
Для початківців
Марк Гарро
8 вересня 2020 р.
11 хвилин на читання
Редагувати сторінку (opens in a new tab)

Отже, ви чули про цей Етеріум і готові зануритися в кролячу нору? У цій статті ми швидко розглянемо основи блокчейну, а потім перейдемо до взаємодії із симульованим вузлом Етеріуму — читання даних блоку, перевірки балансів акаунтів і надсилання транзакцій. Попутно ми виділимо відмінності між традиційними способами створення застосунків і цією новою децентралізованою парадигмою.

(Базові) передумови

Ця стаття прагне бути зрозумілою для широкого кола розробників. Ми будемо використовувати інструменти Python, але вони є лише засобом для передачі ідей — нічого страшного, якщо ви не є Python-розробником. Однак я зроблю кілька припущень щодо того, що ви вже знаєте, щоб ми могли швидко перейти до специфічних для Етеріуму деталей.

Припущення:

  • Ви вмієте працювати в терміналі,
  • Ви написали кілька рядків коду на Python,
  • На вашому комп'ютері встановлено Python версії 3.6 або вище (настійно рекомендується використовувати віртуальне середовище (opens in a new tab)), і
  • ви використовували pip, інсталятор пакетів Python. Знову ж таки, якщо щось із цього не так, або ви не плануєте відтворювати код із цієї статті, ви, швидше за все, все одно зможете без проблем стежити за матеріалом.

Коротко про блокчейни

Існує багато способів описати Етеріум, але в його основі лежить блокчейн. Блокчейни складаються з послідовності блоків, тому почнемо з цього. Простіше кажучи, кожен блок у блокчейні Етеріуму — це лише деякі метадані та список транзакцій. У форматі JSON це виглядає приблизно так:

{
   "number": 1234567,
   "hash": "0xabc123...",
   "parentHash": "0xdef456...",
   ...,
   "transactions": [...]
}

Кожен блок має посилання на блок, який був перед ним; parentHash — це просто хеш попереднього блоку.

Примітка: Етеріум регулярно використовує хеш-функції для створення значень фіксованого розміру («хешів»). Хеші відіграють важливу роль в Етеріумі, але поки що ви можете сміливо вважати їх унікальними ідентифікаторами.

A diagram depicting a blockchain including the data inside  each block

Блокчейн — це, по суті, зв'язний список; кожен блок має посилання на попередній блок.

Ця структура даних не є чимось новим, але правила (тобто однорангові протоколи), які керують мережею, є такими. Немає центрального органу управління; мережа вузлів повинна співпрацювати для підтримки мережі та конкурувати, щоб вирішити, які транзакції включити в наступний блок. Отже, коли ви хочете надіслати трохи грошей другові, вам потрібно буде транслювати цю транзакцію в мережу, а потім дочекатися, поки вона буде включена в один із наступних блоків.

Єдиний спосіб для блокчейну перевірити, що гроші дійсно були надіслані від одного користувача до іншого, — це використовувати валюту, яка є рідною для цього блокчейну (тобто створена та керована ним). В Етеріумі ця валюта називається етер, і блокчейн Етеріуму містить єдиний офіційний запис балансів акаунтів.

Нова парадигма

Цей новий децентралізований технологічний стек породив нові інструменти для розробників. Такі інструменти існують для багатьох мов програмування, але ми будемо розглядати їх через призму Python. Повторюся: навіть якщо Python не є вашою основною мовою, вам не складе труднощів стежити за матеріалом.

Python-розробники, які хочуть взаємодіяти з Етеріумом, швидше за все, звернуться до Web3.py (opens in a new tab). Web3.py — це бібліотека, яка значно спрощує підключення до вузла Етеріуму, а також надсилання та отримання даних від нього.

Примітка: Терміни «вузол Етеріуму» та «клієнт Етеріуму» використовуються як взаємозамінні. В обох випадках мається на увазі програмне забезпечення, яке запускає учасник мережі Етеріум. Це програмне забезпечення може читати дані блоку, отримувати оновлення при додаванні нових блоків у ланцюг, транслювати нові транзакції тощо. Технічно, клієнт — це програмне забезпечення, а вузол — це комп'ютер, на якому працює це програмне забезпечення.

Клієнти Етеріуму можна налаштувати так, щоб вони були доступні через IPC (opens in a new tab), HTTP або Websockets, тому Web3.py повинен відображати цю конфігурацію. Web3.py називає ці варіанти підключення провайдерами. Вам потрібно буде вибрати одного з трьох провайдерів, щоб зв'язати екземпляр Web3.py з вашим вузлом.

A diagram showing how web3.py uses IPC to connect your application to an Ethereum node

Налаштуйте вузол Етеріуму та Web3.py для зв'язку через один і той самий протокол, наприклад, IPC на цій діаграмі.

Після правильного налаштування Web3.py ви можете почати взаємодіяти з блокчейном. Ось кілька прикладів використання Web3.py як попередній огляд того, що буде далі:

# зчитати дані блоку:
w3.eth.get_block('latest')

# надіслати транзакцію:
w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})

Встановлення

У цьому посібнику ми будемо працювати лише в інтерпретаторі Python. Ми не будемо створювати жодних каталогів, файлів, класів чи функцій.

Примітка: У наведених нижче прикладах команди, що починаються з $, призначені для виконання в терміналі. (Не вводьте $, це просто позначає початок рядка.)

Спочатку встановіть IPython (opens in a new tab) для зручного середовища дослідження. IPython пропонує автодоповнення за допомогою клавіші Tab, серед інших функцій, що значно полегшує розуміння можливостей Web3.py.

pip install ipython

Web3.py публікується під назвою web3. Встановіть його таким чином:

pip install web3

Ще одне — пізніше ми будемо симулювати блокчейн, для чого знадобиться ще кілька залежностей. Ви можете встановити їх за допомогою:

pip install 'web3[tester]'

Ви повністю готові до роботи!

Примітка: Пакет web3[tester] працює до версії Python 3.10.xx

Запуск пісочниці

Відкрийте нове середовище Python, запустивши ipython у вашому терміналі. Це можна порівняти із запуском python, але з більшою кількістю додаткових функцій.

ipython

Це виведе деяку інформацію про версії Python та IPython, які ви використовуєте, після чого ви побачите запрошення, що очікує на введення:

In [1]:

Зараз ви дивитеся на інтерактивну оболонку Python. По суті, це пісочниця для гри. Якщо ви дійшли до цього моменту, час імпортувати Web3.py:

In [1]: from web3 import Web3

Знайомство з модулем Web3

Окрім того, що модуль Web3 (opens in a new tab) є шлюзом до Етеріуму, він пропонує кілька зручних функцій. Давайте розглянемо деякі з них.

У застосунку Етеріуму вам часто доведеться конвертувати номінали валют. Модуль Web3 надає кілька допоміжних методів саме для цього: from_wei (opens in a new tab) та to_wei (opens in a new tab).

Примітка: Комп'ютери, як відомо, погано справляються з десятковою математикою. Щоб обійти це, розробники часто зберігають суми в доларах у центах. Наприклад, товар із ціною $5,99 може зберігатися в базі даних як 599.

Подібний шаблон використовується при обробці транзакцій в етері. Однак замість двох знаків після коми етер має 18! Найменший номінал етеру називається Wei, тому саме це значення вказується під час надсилання транзакцій.

1 етер = 1000000000000000000 Wei

1 Wei = 0.000000000000000001 етер

Спробуйте конвертувати деякі значення у Wei та з нього. Зверніть увагу, що існують назви для багатьох номіналів (opens in a new tab) між етером та Wei. Одним із найвідоміших серед них є Gwei, оскільки саме в ньому часто відображається комісія за транзакцію.

In [2]: Web3.to_wei(1, 'ether')
Out[2]: 1000000000000000000

In [3]: Web3.from_wei(500000000, 'gwei')
Out[3]: Decimal('0.5')

Інші допоміжні методи модуля Web3 включають конвертери форматів даних (наприклад, toHex (opens in a new tab)), помічники для адрес (наприклад, isAddress (opens in a new tab)) та хеш-функції (наприклад, keccak (opens in a new tab)). Багато з них будуть розглянуті пізніше в цій серії. Щоб переглянути всі доступні методи та властивості, скористайтеся автодоповненням IPython, ввівши Web3. і двічі натиснувши клавішу Tab після крапки.

Спілкування з ланцюгом

Зручні методи — це чудово, але давайте перейдемо до блокчейну. Наступним кроком є налаштування Web3.py для зв'язку з вузлом Етеріуму. Тут ми маємо можливість використовувати провайдери IPC, HTTP або Websocket.

Ми не підемо цим шляхом, але приклад повного робочого процесу з використанням HTTP-провайдера може виглядати приблизно так:

  • Завантажте вузол Етеріуму, наприклад, Geth (opens in a new tab).
  • Запустіть Geth в одному вікні термінала та зачекайте, поки він синхронізує мережу. Стандартний HTTP-порт — 8545, але його можна налаштувати.
  • Вкажіть Web3.py підключитися до вузла через HTTP на localhost:8545. w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • Використовуйте екземпляр w3 для взаємодії з вузлом.

Хоча це один із «реальних» способів зробити це, процес синхронізації займає години і є непотрібним, якщо вам просто потрібне середовище для розробки. Для цієї мети Web3.py пропонує четвертого провайдера — EthereumTesterProvider. Цей тестовий провайдер підключається до симульованого вузла Етеріуму з послабленими дозволами та фальшивою валютою для гри.

A diagram showing the EthereumTesterProvider linking your web3.py application to a simulated Ethereum node

EthereumTesterProvider підключається до симульованого вузла і є зручним для швидкого створення середовищ розробки.

Цей симульований вузол називається eth-tester (opens in a new tab), і ми встановили його як частину команди pip install web3[tester]. Налаштувати Web3.py для використання цього тестового провайдера дуже просто:

In [4]: w3 = Web3(Web3.EthereumTesterProvider())

Тепер ви готові серфити по ланцюгу! Так ніхто не каже. Я щойно це вигадав. Давайте проведемо коротку екскурсію.

Коротка екскурсія

Насамперед, перевірка працездатності:

In [5]: w3.is_connected()
Out[5]: True

Оскільки ми використовуємо тестового провайдера, це не дуже цінний тест, але якщо він завершиться невдало, швидше за все, ви ввели щось неправильно під час створення екземпляра змінної w3. Двічі перевірте, чи ви включили внутрішні дужки, тобто Web3.EthereumTesterProvider().

Зупинка екскурсії №1: акаунти

Для зручності тестовий провайдер створив кілька акаунтів і попередньо поповнив їх тестовим етером.

Спочатку давайте подивимося на список цих акаунтів:

In [6]: w3.eth.accounts
Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]

Якщо ви виконаєте цю команду, ви побачите список із десяти рядків, які починаються з 0x. Кожен із них є публічною адресою і певною мірою аналогічний номеру розрахункового рахунку. Ви б надали цю адресу тому, хто хотів би надіслати вам етер.

Як уже згадувалося, тестовий провайдер попередньо поповнив кожен із цих акаунтів тестовим етером. Давайте дізнаємося, скільки його на першому акаунті:

In [7]: w3.eth.get_balance(w3.eth.accounts[0])
Out[7]: 1000000000000000000000000

Це багато нулів! Перш ніж ви з радістю побіжите до фальшивого банку, згадайте той урок про номінали валют, який був раніше. Значення етеру представлені в найменшому номіналі — Wei. Конвертуйте це в етер:

In [8]: w3.from_wei(1000000000000000000000000, 'ether')
Out[8]: Decimal('1000000')

Один мільйон тестових етерів — теж непогано.

Зупинка екскурсії №2: дані блоку

Давайте поглянемо на стан цього симульованого блокчейну:

In [9]: w3.eth.get_block('latest')
Out[9]: AttributeDict({
   'number': 0,
   'hash': HexBytes('0x9469878...'),
   'parentHash': HexBytes('0x0000000...'),
   ...
   'transactions': []
})

Про блок повертається багато інформації, але тут варто відзначити лише кілька речей:

  • Номер блоку дорівнює нулю — незалежно від того, як давно ви налаштували тестового провайдера. На відміну від реальної мережі Етеріум, яка додає новий блок кожні 12 секунд, ця симуляція чекатиме, поки ви не дасте їй якусь роботу.
  • transactions — це порожній список із тієї ж причини: ми ще нічого не зробили. Цей перший блок є порожнім блоком, просто для того, щоб запустити ланцюг.
  • Зверніть увагу, що parentHash — це просто набір порожніх байтів. Це означає, що це перший блок у ланцюзі, також відомий як генезис-блок.

Зупинка екскурсії №3: транзакції

Ми застрягли на нульовому блоці, поки не з'явиться транзакція в очікуванні, тому давайте створимо її. Надішліть кілька тестових етерів з одного акаунта на інший:

In [10]: tx_hash = w3.eth.send_transaction({
   'from': w3.eth.accounts[0],
   'to': w3.eth.accounts[1],
   'value': w3.to_wei(3, 'ether'),
   'gas': 21000
})

Зазвичай на цьому етапі ви б чекали кілька секунд, поки ваша транзакція буде включена в новий блок. Повний процес виглядає приблизно так:

  1. Надішліть транзакцію та збережіть хеш транзакції. Поки блок, що містить транзакцію, не буде створено та трансльовано, транзакція перебуває «в очікуванні». tx_hash = w3.eth.send_transaction({ … })
  2. Дочекайтеся включення транзакції в блок: w3.eth.wait_for_transaction_receipt(tx_hash)
  3. Продовжте логіку застосунку. Щоб переглянути успішну транзакцію: w3.eth.get_transaction(tx_hash)

Наше симульоване середовище миттєво додасть транзакцію в новий блок, тому ми можемо відразу переглянути транзакцію:

Тут ви побачите деякі знайомі деталі: поля from, to та value повинні збігатися з вхідними даними нашого виклику send_transaction. Ще один обнадійливий момент полягає в тому, що ця транзакція була включена як перша транзакція ('transactionIndex': 0) у блок номер 1.

Ми також можемо легко перевірити успішність цієї транзакції, перевіривши баланси двох залучених акаунтів. Три етери мали перейти з одного на інший.

In [12]: w3.eth.get_balance(w3.eth.accounts[0])
Out[12]: 999996999979000000000000

In [13]: w3.eth.get_balance(w3.eth.accounts[1])
Out[13]: 1000003000000000000000000

Останній виглядає добре! Баланс збільшився з 1 000 000 до 1 000 003 етерів. Але що сталося з першим акаунтом? Здається, він втратив трохи більше трьох етерів. На жаль, у житті немає нічого безкоштовного, і використання публічної мережі Етеріум вимагає від вас компенсації вашим колегам за їхню допоміжну роль. З акаунта, який надіслав транзакцію, була списана невелика комісія за транзакцію — ця комісія дорівнює кількості спаленого газу (21000 одиниць газу для переказу ETH), помноженій на базову комісію, яка змінюється залежно від активності мережі, плюс пріоритетна комісія, яка йде валідатору, що включає транзакцію в блок.

Детальніше про газ

Примітка: У публічній мережі комісії за транзакції змінюються залежно від попиту в мережі та того, наскільки швидко ви хочете, щоб транзакція була оброблена. Якщо вас цікавить детальний розбір того, як розраховуються комісії, перегляньте мою попередню статтю про те, як транзакції включаються в блок.

І видихніть

Ми займаємося цим уже деякий час, тому це місце здається цілком підходящим для перерви. Кроляча нора продовжується, і ми продовжимо дослідження у другій частині цієї серії. Деякі концепції, які будуть розглянуті: підключення до реального вузла, смарт-контракти та токени. Маєте додаткові запитання? Дайте мені знати! Ваш відгук вплине на те, куди ми рухатимемося далі. Запити вітаються через Twitter (opens in a new tab).

Останнє оновлення сторінки: 3 березня 2026 р.