Przejdź do głównej zawartości
Change page

Transakcje

Ostatnia edycja: @wosek_(opens in a new tab), 16 lipca 2024

Transakcje to podpisane kryptograficznie instrukcje od kont. Konto inicjuje transakcję, aby zaktualizować stan sieci Ethereum. Najprostszą transakcją jest przeniesienie ETH z jednego konta na drugie.

Warunki wstępne

Aby lepiej zrozumieć tę stronę, zalecamy najpierw przeczytanie rozdziału o kontach oraz naszym wprowadzeniu do Ethereum.

Czym jest transakcja?

Transakcja Ethereum odnosi się do działania zainicjowanego przez konto zewnętrzne, czyli takie, które jest zarządzane przez człowieka, a nie przez kontrakt. Na przykład, jeśli Bob wysyła Alice 1 ETH, na koncie Boba musi się pojawić obciążenie, a na koncie Alice uznanie. Ta zmiana stanu ma miejsce w ramach transakcji.

Schemat pokazujący transakcję powodującą zmianę stanu Diagram zaadaptowany z Ilustrowanego Ethereum EVM(opens in a new tab)

Transakcje, które zmieniają stan EVM, muszą być rozesłane do całej sieci. Każdy węzeł może rozesłać prośbę o wykonanie transakcji na EVM; po tym wydarzeniu walidator wykona transakcję i roześle powstałą zmianę stanu do reszty sieci.

Transakcje wymagają opłaty i muszą być uwzględnione w ważnym bloku. Aby uprościć ten przegląd, omówimy opłaty za gaz i walidację w innym miejscu.

Przesłana transakcja zawiera następujące informacje:

  • from — adres nadawcy, który będzie podpisywać transakcję. Będzie to konto zewnętrzne, ponieważ konta kontraktowe nie mogą wysyłać transakcji
  • to — adres odbiorcy (jeśli jest to konto zewnętrzne, to transakcja przekaże wartość. Natomiast jeśli jest to konto kontraktowe to, transakcja wykona kod kontraktu)
  • signature — identyfikator nadawcy. Jest on generowany, kiedy klucz prywatny nadawcy podpisuje transakcję i potwierdza, że nadawca autoryzował tę transakcję
  • nonce — sekwencyjnie zwiększający się licznik, który wskazuje na numer transakcji konta
  • value — kwota ETH do przesłania od nadawcy do odbiorcy (wyrażona w WEI, gdzie 1 ETH jest równy 1e+18wei)
  • input data — opcjonalne pole do umieszczania dowolnych danych
  • gasLimit — maksymalna ilość jednostek gazu, które mogą zostać zużyte w trakcie transakcji. EVM określa, ile jednostek gazu wymaga każdy krok obliczeniowy
  • maxPriorityFeePerGas — maksymalna cena zużytego gazu, która zostanie uwzględniona jako napiwek dla walidatora
  • maxFeePerGas — maksymalna opłata za jednostkę gazu, jaką użytkownik jest w stanie zapłacić za transakcję (w tym baseFeePerGas i maxPriorityFeePerGas)

Gaz jest odniesieniem do obliczeń wymaganych do przetworzenia transakcji przez walidatora. Użytkownicy muszą zapłacić opłatę za to obliczenie. gasLimit i maxPriorityFeePerGas określają maksymalną opłatę transakcyjną płaconą walidatorowi. Więcej na temat gazu.

Obiekt transakcji będzie wyglądał mniej więcej w ten sposób:

1{
2 from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
3 to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a",
4 gasLimit: "21000",
5 maxFeePerGas: "300",
6 maxPriorityFeePerGas: "10",
7 nonce: "0",
8 value: "10000000000"
9}
Pokaż wszystko
Kopiuj

Obiekt transakcji musi być podpisany jednak przy użyciu klucza prywatnego nadawcy. Dowodzi to, że transakcja mogła pochodzić jedynie od nadawcy i nie została wysłana w sposób nieuczciwy.

Klient Ethereum, jak Geth, będzie obsługiwać ten proces podpisywania.

Przykład wywołania 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}
Pokaż wszystko
Kopiuj

Przykładowa odpowiedź:

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}
Pokaż wszystko
Kopiuj
  • raw jest podpisaną transakcją w zakodowanym formacie prefiksu o rekursywnej długości (RLP)
  • tx jest podpisaną transakcją w formacie JSON

Dzięki hashowi podpisu można udowodnić kryptograficznie, że transakcja pochodzi od nadawcy i została przesłana do sieci.

Pole danych

Zdecydowana większość transakcji uzyskuje dostęp do kontraktu z konta zewnętrznego. Większość kontraktów jest napisana w Solidity i interpretuje swoje pole danych zgodnie z .

Pierwsze cztery bajty określają, które funkcje mają zostać wywołane, korzystając z hasha nazwy funkcji i jej argumentów. Możesz czasami zidentyfikować funkcję z selektora korzystając z tej bazy danych(opens in a new tab).

Reszta danych wywoławczych to argumenty, zakodowane zgodnie ze specyfikacją ABI(opens in a new tab).

Spójrzmy dla przykładu na tę transakcję(opens in a new tab). Kliknij Click to show more, aby zobaczyć dane wywoławcze.

Selektorem funkcji jest 0xa9059cbb. Istnieje kilka znanych funkcji z tym podpisem(opens in a new tab). W tym przypadku kod źródłowy kontraktu(opens in a new tab) został opublikowany na Etherscan, więc wiemy, że funkcją jest transfer(address,uint256).

Reszta danych to:

10000000000000000000000004f6742badb049791cd9a37ea913f2bac38d01279
2000000000000000000000000000000000000000000000000000000003b0559f4

Zgodnie ze specyfikacją ABI wartości całkowite (takie jak adresy, które są 20-bajtowymi wartościami całkowitymi) wyświetlają się w ABI jako 32-bajtowe słowa, uzupełnione zerami z przodu. Wiemy więc, że adres to wygląda tak 4f6742badb049791cd9a37ea913f2bac38d01279(opens in a new tab). Wartość value wynosi 0x3b0559f4 = 990206452.

Rodzaje transakcji

W Ethereum istnieje kilka różnych rodzajów transakcji:

  • Zwykłe transakcje: transakcja z jednego konta na drugie.
  • Transakcje wdrożenia kontraktu: transakcja bez adresu „to”, w którym pole danych jest wykorzystywane dla kodu kontraktu.
  • Wykonanie kontraktu: transakcja, która wchodzi w interakcję z wdrożonym inteligentnym kontraktem. W tym przypadku adres „to” jest adresem inteligentnego kontraktu.

Na temat gazu

Jak już wspomniano, wykonanie transakcji kosztuje gaz. Proste transakcje transferu wymagają 21 000 jednostek gazu.

A więc, aby Bob mógł wysłać Alice 1 ETH przy baseFeePerGas wynoszącym 190 gwei i maxPriorityFeePerGas wynoszącym 10 gwei, Bob będzie musiał zapłacić następującą opłatę:

1(190 + 10) * 21 000 = 4 200 000 gwei
2--lub--
30,0042 ETH

Konto Boba zostanie obciążone kwotą 1,0042 ETH (1 ETH dla Alice + 0,0042 ETH w opłatach za gaz)

Konto Alicji zostanie zasilone kwotą 1,0 ETH

Podstawowa opłata wynosząca 0,00399 ETH zostanie spalona

Walidator zatrzyma napiwek wynoszący 0,000210 ETH

Schemat pokazujący, w jaki sposób zwracany jest niewykorzystany gaz Schemat zaadaptowany z Ilustracja Ethereum EVM(opens in a new tab)

Gaz niewykorzystany w transakcji jest zwracany na konto użytkownika.

Interakcje z inteligentnymi kontraktami

Gaz jest wymagany dla każdej transakcji wiążącej się z inteligentnym kontraktem.

Inteligentne kontrakty mogą również zawierać funkcje takie jak view(opens in a new tab) czy pure(opens in a new tab), które nie zmieniają stanu kontraktu. W związku z tym wywoływanie tych funkcji z konta zewnętrznego nie będzie wymagało żadnego gazu. Podstawowym wywołaniem RPC dla takiego scenariusza jest eth_call

W przeciwieństwie do dostępu przy użyciu eth_call, funkcje view czy pure są również często wywoływane wewnętrznie (tj. z samego kontraktu lub od innego kontraktu) co już wymaga gazu.

Cykl życiowy transakcji

Po przesłaniu transakcji dzieją się następujące wydarzenia:

  1. Hash transakcji zostaje kryptograficznie wygenerowany: 0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017
  2. Transakcja zostaje następnie rozgłoszona do sieci i dodawana do puli transakcji składającej się z wszystkich innych oczekujących transakcji w sieci.
  3. Walidator musi wybrać Twoją transakcję i uwzględnić ją w bloku, aby ją zweryfikować transakcję i uznać ją za „udaną”.
  4. W miarę upływu czasu blok zawierający Twoją transakcję zostanie zaktualizowany do kategorii „uzasadniony”, a następnie „sfinalizowany”. Aktualizacje te znacznie zwiększają pewność, że Twoja transakcja zakończyła się sukcesem i nie będzie można jej zmienić. Po „sfinalizowaniu” bloku mógłby on zostać zmieniony tylko przez atak na poziomie sieci, który kosztowałby miliardy dolarów.

Demo wizualne

Zobacz, jak Austin opowiada o transakcjach, gazie i kopaniu.

Typed Transaction Envelope

Ethereum pierwotnie miało jeden format transakcji. Każda transakcja zawierała nonce, cenę gazu, limit gazu, adres docelowy, wartość, dane, v, r oraz s. Pola te są zakodowane w RLP, aby wyglądały mniej więcej tak:

RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])

Ethereum wyewoluowało i wspiera wiele rodzajów transakcji, zezwalając na wdrażanie nowych funkcji takich jak listy dostępu i EIP-1559(opens in a new tab), bez wpływania na starsze formaty transakcji.

EIP-2718(opens in a new tab) jest tym, co umożliwia takie zachowanie. Transakcję są interpretowane jako:

TransactionType || TransactionPayload

Gdzie pola są definiowane jako:

  • TransactionType — liczba z zakresu od 0 do 0x7f, zapewniająca w sumie 128 możliwych rodzajów transakcji.
  • TransactionPayload — dowolna tablica bajtów zdefiniowana przez rodzaj transakcji.

Na podstawie wartości TransactionType, transakcje mogą być definiowane jako:

  1. Transakcje typu 0 (starsze): oryginalny format transakcji używany od samego początku Ethereum. Nie zawierają funkcji z EIP-1559(opens in a new tab), takich jak dynamiczne obliczenia opłat za gaz czy list dostępu do inteligentnych kontraktów. Starsze transakcje nie mają określonego prefiksu wskazującego na ich typ w ich serializowanej formie, począwszy od bajtu 0xf8 przy użyciu kodowania prefiksu o rekursywnej długości (RLP). Wartość TransactionType dla tych transakcji wynosi 0x0.

  2. Transakcje typu 1: wprowadzone w EIP-2930(opens in a new tab) jako część uaktualnienia Berlin sieci Ethereum transakcje te zawierają parametr accessList. Ta lista określa adresy i klucze przechowywania, do których transakcja oczekuje dostępu, potencjalnie pomagając zmniejszyć koszty gazu złożonych transakcji wykorzystujących inteligentne kontrakty. Zmiany rynku opłat EIP-1559 nie są uwzględnione w transakcjach typu 1. Transakcje typu 1 zawierają również parametr yParity, który może wynosić zarówno 0x0 jak i 0x1, wskazując na parzystość wartości y podpisu secp256k1. Są identyfikowane przez początkowy bajt 0x01, a ich wartość TransactionType wynosi 0x1.

  3. Transakcje typu 2, powszechnie określane jako transakcje EIP-1559, to transakcje wprowadzone w EIP-1559(opens in a new tab), w ramach uaktualnienia London sieci Ethereum. Stały się one standardowym rodzajem transakcji w sieci Ethereum. Transakcje te wprowadziły nowy mechanizm rynku opłat, który poprawia przewidywalność, rozdzielając opłaty transakcyjne na opłatę podstawową oraz opłatę priorytetową. Zaczynają się bajtem 0x02 i zawierają takie pola jak maxPriorityFeePerGas i maxFeePerGas. Transakcje typu 2 są teraz domyślnymi, ze względu na ich elastyczność i wydajność, są szczególnie preferowanie podczas okresów dużego przeciążenia sieci ze względu na zdolność pomagania użytkownikom w zarządzaniu opłatami transakcyjnymi w bardziej przewidywalny sposób. Wartość TransactionType dla tych transakcji wynosi 0x2.

Dodatkowo przeczytaj

Znasz jakieś zasoby społeczności, które Ci pomogły? Wyedytuj tę stronę i dodaj je!

  • Konta
  • Maszyna wirtualna Ethereum (EVM)
  • Paliwo

Czy ten artykuł był pomocny?