Naciśnij ESC, aby zamknąć

EIP-4844 i bloby w Ethereum: Jak obniżyć opłaty i dane

Marzec 2024 roku na zawsze zmienił ekonomię warstwy drugiej. Przed aktualizacją Dencun rollupy pokroju Arbitrum czy Optimism paliły budżety zespołów na ładowanie calldata w sieci głównej. Smart kontrakty Ethereum zapisywały tę tablicę bajtów w stanie globalnym na zawsze, zmuszając każdego walidatora do przechowywania jej wiecznie. Pochłaniało to nawet dziewięćdziesiąt procent kosztów użytkowników L2.

EIP-4844 rozbił ten schemat, wprowadzając transakcje trzeciego typu i bloby. Jednak za ładnymi cyframi obniżki opłat rzędu 10-50 razy kryje się mnóstwo niuansów inżynieryjnych, o których marketerzy zazwyczaj wolą nie wspominać.

Jak działa blob na poziomie pamięci i konsensusu

Blob to nie zwykły plik wysłany do blockchaina. To izolowana tablica danych o dokładnie 131 072 bajtach (128 KB), która istnieje równolegle z egzekucją EVM. Smart kontrakty w Ethereum nie potrafią odczytać zawartości bloba wewnątrz wywołania CALL lub STATICCALL. Mają dostęp tylko do jednego kodu bajtowego - specjalnego opkodu BLOBHASH, który zwraca wersję oraz hash zobowiązania.

  • Rozmiar bloku: docelowa wartość wynosi 3 bloby (~384 KB), a maksimum w szczycie to 6 blobów (~768 KB).
  • Czas życia: około 4096 epok (w przybliżeniu 18 dni), po czym węzły konsensusu czyszczą dane ze swoich dysków.
  • Izolacja mempoola: bloby nie kręcą się w zwykłym mempoolu wykonawczym. Posiadają własną pulę na poziomie klientów konsensusu (P2P blob pool), co chroni główne kolejki transakcji przed przeciążeniem.

Parametr | Klasyczny calldata | Blob według EIP-4844 (Type 3)
Gdzie leżą dane: W stałym stanie EVM | W tymczasowej puli P2P konsensusu
Czas przechowywania: Na zawsze | ~18 dni
Dostęp z EVM: Bezpośredni (przez odczyt bajtów) | Pośredni (tylko przez hash i KZG)
Wycena: Wspólny execution gas | Niezależny rynek blob gas (EIP-1559)

Nieoczywiste funkcje i pułapki architektoniczne proto-dankshardingu

Mało kto zwraca uwagę na to, jak działa wycena blob gasu. W przeciwieństwie do standardowego gazu, który skacze przy każdym kichnięciu w DeFi, rynek blobów jest sterowany przez niezależny algorytm korekty. Jeśli rollupy zapychają sloty powyżej docelowych trzech blobów, cena zaczyna rosnąć wykładniczo. Jeśli sloty świecą pustkami, spada do minimalnego progu. W praktyce prowadzi to do sytuacji, w której wysłanie bloba w spokojnych godzinach kosztuje mikroskopijne ułamki centa, ale w momencie nagłego szturmu na sieć cena może podskoczyć setki razy szybciej niż w warstwie wykonawczej.

Kolejna delikatna kwestia to weryfikacja kryptograficzna poprzez zobowiązania KZG (Kate-Zaverucha-Goldberg). Walidatorzy nie muszą pobierać całych 128 KB, aby upewnić się co do poprawności danych. Wystarczy, że zweryfikują 48-bajtowy wielomian. Obniża to wymagania wobec procesorów walidatorów, ale przerzuca całe obciążenie na łącze sieciowe.

Gdzie zrzucać "niewygodne" info w praktyce

Tymczasowa natura blobów czyni z nich idealny kontener dla danych, które nie potrzebują wiecznej księgowości, lecz wymagają kryptograficznej niezmienności w krótkim interwale walidacji:

  • Zrzuty wyroczni i surowe metryki: pośrednie tablice danych, które są podpisywane przez dostawców przed agregacją do smart kontraktu.
  • Migawki stanu L3 i światów gier: zmiany stanu typu delta, którym wystarczy potwierdzić poprawność za ostatni tydzień.
  • Logi audytowe backendu: pakiety transakcji lub rachunki, które muszą być weryfikowalne publicznie, lecz po miesiącu tracą wartość operacyjną.

Wrzucanie ładunku do bloba poprzez skrypty Pythona w web3.py wymaga osobnego pakowania bajtów w wielomiany i generowania hasha wersjonowanego z prefiksem 0x01. Błędne obliczenie maxFeePerBlobGas w momencie wysyłki gwarantuje zawieszenie transakcji w mempoolu.

Teoria i ekonomia są jasne, ale jak wygląda praca z blobami na poziomie kodu? Użycie standardowego wywołania send_transaction zakończy się błędem, ponieważ transakcje trzeciego typu wymagają ręcznego przygotowania zobowiązań KZG, wygenerowania dowodów (proofs) oraz obliczenia osobnego limitu gazu.

Wysyłanie transakcji Type-3 w Pythonie

Poniżej zaprezentowano działający wzorzec wysyłania bloba przy użyciu aktualnych bibliotek do obsługi węzła (Geth lub Reth), który wspiera aktualizację Dencun:

import os
from eth_account import Account
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
key = os.environ["OPERATOR_KEY"]
acct = Account.from_key(key)
FE_COUNT, FE_PAYLOAD = 4096, 31  # 31 bajtów danych na element pola
def encode_blob(data: bytes) -> bytes:
    data = len(data).to_bytes(4, "big") + data
    if len(data) > FE_COUNT * FE_PAYLOAD:
        raise ValueError("payload nie mieszcz się w jednym blobie")
    data = data.ljust(FE_COUNT * FE_PAYLOAD, b"\x00")
    # starszy bajt każdego elementu = 0, aby wartość < modułu BLS
    return b"".join(b"\x00" + data[i:i + FE_PAYLOAD]
                    for i in range(0, len(data), FE_PAYLOAD))
blob = encode_blob(b"EXMON Infrastructure DA Payload: batch #98412")
# Aktualna cena blob gasu z zapasem na wzrost
blob_base_fee = int(w3.provider.make_request("eth_blobBaseFee", [])["result"], 16)
base_fee = w3.eth.get_block("latest")["baseFeePerGas"]
tx = {
    "type": 3,
    "chainId": w3.eth.chain_id,
    "nonce": w3.eth.get_transaction_count(acct.address),
    "gas": 21000,
    "maxPriorityFeePerGas": w3.to_wei(1, "gwei"),
    "maxFeePerGas": base_fee * 2 + w3.to_wei(1, "gwei"),
    "maxFeePerBlobGas": max(blob_base_fee * 2, w3.to_wei(1, "gwei")),
    "to": acct.address,  # nie tworzenie kontraktu: dla blob-tx `to` jest obowiązkowe
    "value": 0,
    "data": b"",
}
# ckzg liczy zobowiązanie, dowody i versioned hash; sidecar jest wstrzykiwany do raw tx
signed = Account.sign_transaction(tx, key, blobs=[blob])
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"Blob-tx wysłana: {tx_hash.to_0x_hex()}")

Jeśli nie uwzględnisz zmienności maxFeePerBlobGas, w momentach szczytowego obciążenia rollupów transakcja zawiesi się w mempoolu konsensusu, dopóki rynek nie ostygnie.

Problem węzłów archiwalnych: gdzie trafiają dane po 18 dniach

Główna pułapka przy projektowaniu architektury opartej na blobach wiąże się z ich usuwaniem. Klienci konsensusu przechowują ciała blobów przez co najmniej 4096 epok (około 18 dni), po czym je kasują. Sama transakcja oraz zobowiązanie KZG pozostają w blockchainie na zawsze, ale odzyskanie zawartości bloba na ich podstawie jest niemożliwe. Jeśli po miesiącu zajdzie potrzeba pobrania danych bloba, standardowy węzeł zwróci błąd.

Zespoły budujące produkty w oparciu o EIP-4844 muszą rozwiązać ten problem na jeden z trzech sposobów:

  • Własne skrippery archiwalne: wdrażanie usług w tle, które pobierają obiekty blob z sieci P2P w momencie ich pojawienia się i zapisują w chłodnym magazynie (bucketach kompatybilnych z S3).
  • Archiwa zdecentralizowane: korzystanie z sieci takich jak Celestia, Avail czy The Graph do długoterminowego przechowywania Data Availability.
  • Rezygnacja z głębokiej historii: przechowywanie lokalnych indeksów tylko dla aktywnego dwutygodniowego okna, zrzucając starsze agregaty w formie skompresowanej.

Praktyka EXMON: optymalizacja przechowywania

W infrastrukturze EXMON wykorzystujemy tymczasowe przestrzenie blobów do wynoszenia ciężkich, pośrednich logów transakcyjnych, zrzutów serwisowych oraz migawek weryfikacyjnych.

Pozwala to na rozwiązanie dwóch zadań jednocześnie:

  • Oszczędność budżetu: koszty publikacji danych spadły o rząd wielkości w porównaniu do starszych metod opartych na calldata.
  • Czystość blockchaina: globalny stan sieci nie jest zapychany śmieciami, które tracą na aktualności już po tygodniu, przy jednoczesnym zachowaniu stumprocentowej weryfikowalności kryptograficznej w przedziale cyklu życia danych.
Podsumuj ten wpis na blogu za pomocą:

FAQ

EIP-4844 wprowadza proto-danksharding za pomocą transakcji typu 3, które przenoszą tymczasowe kontenery danych zwane blobami z pominięciem stałego stanu EVM. Każdy blob mieści dokładnie 128 KB danych przetwarzanych wyłącznie w warstwie konsensusu P2P, a ich poprawność jest weryfikowana za pomocą zobowiązań KZG bez możliwości bezpośredniego odczytu z poziomu смарт-kontraktu.

Walidatorzy Ethereum przechowują ciała blobów przez 4096 epok, czyli około 18 dni, po czym dane są automatycznie kasowane z lokalnych dysków. Ze względu na to usuwanie, pobieranie archiwalnych surowych bajtów po upływie tego okna wymaga użycia zewnętrznych indeksatorów lub własnych serwerów archiwizujących zamiast standardowej węzła L1.

Wysyłanie transakcji z blobem w Pythonie wymaga zbudowania słownika transakcji typu 3 z wyodrębnionym parametrem maxFeePerBlobGas oraz tablicą blobVersionedHashes. Po spakowaniu ładunku do zobowiązania KZG i wygenerowaniu wersji hasza, całość podpisuje się kluczem prywatnym i wysyła do puli P2P węzła konsensusu.
Astra EXMON

Astra is the official voice of EXMON and the editorial collective dedicated to bringing you the most timely and accurate information from the crypto market. Astra represents the combined expertise of our internal analysts, product managers, and blockchain engineers.

...

Dodaj opinię

Twój adres e-mail nie zostanie opublikowany. Obowiązkowe pola są oznaczone*