Odkrywanie CryptoKitties - Część 1: Ekstrakcja danych

Źródło: https://www.cryptokitties.co/kitty/101

Jeśli to czytasz, prawdopodobnie słyszałeś o grze, która przyciągnęła uwagę wszystkich w sieci Ethereum w ciągu ostatnich kilku miesięcy: CryptoKitties!

Krótko mówiąc, gra polega na zbieraniu wirtualnych kotów. Koty są tworzone przez graczy w grze, którzy mogą hodować dwa koty, aby wygenerować nowy. Każdy kot ma własną sekwencję genetyczną, która określa ich fizyczne atrybuty. Ich genom jest funkcją genów ich rodziców oraz pewnej losowości. Oprócz hodowli Axiom Zen, firma stojąca za grą, może stworzyć do 50 000 kotów o określonych właściwościach. Istnieje rynek na kupno i sprzedaż kotów, a drugi na „wypożyczanie” kotów do celów hodowlanych. Możesz przeczytać więcej o grze tutaj.

Block Science to firma zajmująca się badaniami i analizą technologii, specjalizująca się w projektowaniu i ocenie zdecentralizowanych systemów ekonomicznych. Analiza aspektów gospodarki CryptoKitties wydawała się świetną okazją do udoskonalenia naszych narzędzi do ekstrakcji danych, a jednocześnie zdobycia niektórych danych z rzeczywistego świata z żywej (i żywej!) Zdecentralizowanej aplikacji.

Ten post został podzielony na dwie części:

  • Część 1 (ten post) obejmuje aspekty techniczne związane z wydobywaniem i przekształcaniem danych z łańcucha bloków Ethereum.
  • Część 2 zawiera rzeczywistą analizę niektórych danych gry.

Wyodrębnianie danych z Blockchain Ethereum

Chociaż wszystko, co kiedykolwiek wydarzyło się w sieci Ethereum, jest rejestrowane w blockchainie, przekształcenie tych bitów w znaczące dane nie zawsze jest proste. Łatwo jest wyodrębnić dane transakcji stwierdzające, że na danym rachunku blokowym A wysłano trochę eteru (ETH) na konto B i ustawiono określoną cenę gazu dla tej transakcji, która ma zostać przetworzona. Jednak gdy pracujemy nad transakcjami wysyłanymi do umów, dekodowanie danych łańcucha bloków przypomina implementację ETL z wielu plików tekstowych o stałej szerokości, których formaty są opisane tylko w kodzie źródłowym oprogramowania, które je utworzyło.

Transakcje, które wywołują funkcje w inteligentnych kontraktach

Weźmy na przykład transakcję wysłaną do umowy 0xb1690c08e213a35ed9bab7b318de14420fb57d8c z następującą zawartością w polu danych

0x454a2ab3000000000000000000000000000000000000000000000000000000000871ad

Co to robi?

Pierwsza część pola danych (0x454a2ab3) odnosi się do funkcji wewnątrz inteligentnego kontraktu wywoływanego przez transakcję. Są to cztery pierwsze bajty skrótu sygnatury funkcji, która jest zdefiniowana jako nazwa funkcji, po której następują typy danych jej parametrów.

keccak256 („ (, <…>, )”)

Pozostałe bajty to wartości parametrów funkcji. Możesz przeczytać o tym szczegółowo tutaj.

Nawet znając te 4 bajty, jak możemy stwierdzić, która funkcja jest wywoływana lub ile ma parametrów? W tym konkretnym przypadku wiemy, że umowa 0xb1690c… jest inteligentną umową aukcyjną CryptoKitties - rynkiem kupna i sprzedaży kotów. A ponieważ jego kod źródłowy został upubliczniony, wiemy, że ma on funkcję o nazwie bid

/// Licytuje na aukcji otwartej, kończąc aukcję i
/// przenoszenie własności NFT, jeśli dostarczona jest wystarczająca ilość Etheru.
/// param _tokenID: identyfikator tokena do licytacji.
funkcja bid (uint256 _tokenId)

Jeśli obliczymy skrót sygnatury funkcji licytacji, zobaczymy, że pierwsze cztery bajty są dokładnie tymi obecnymi w danych transakcji.

keccak256 („bid (uint256)”) = 454a2ab3c602fd9…

Ponieważ funkcja przyjmuje tylko jeden argument, możemy stwierdzić, że wszystko następujące po pierwszych czterech bajtach w danych transakcji jest tym parametrem. Innymi słowy, transakcja dotyczy licytacji o numerze cat 0x871ad (553389).

Inteligentne kontrakty, które rejestrują informacje

Inteligentne umowy często rejestrują informacje podczas ich wykonywania. Dzienniki zarejestrowane przez umowę można uzyskać, wywołując metodę eth_getlogs interfejsu API JSON RPC. Podobnie jak w przypadku transakcji wywołujących funkcje kontraktu, musimy znać kod źródłowy kontraktu, aby dekodować dane zwracane przez ten interfejs API. Na przykład, co oznacza dziennik z następującymi danymi?

blockNumber: 0x51968f
tematów: [0x0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad5] Data: 0x0000000000000000000000001b8f7b13b14a59d9770f7c1789cf727046f7e542000000000000000000000000000000000000000000000000000000000009fac1000000000000000000000000000000000000000000000000000000000009f80e000000000000000000000000000000000000000000000000000000000008957200004a50b390a6738697012a030ac21d585b4c8214ae39446194054b98e0b98f

Dzienniki są rejestrowane, gdy umowa wywołuje zdarzenie. Pierwszym elementem tablicy tematów (który ma tylko jeden element w naszym przykładzie) jest skrót sygnatury zdarzenia. W przypadku CryptoKitties dzienniki są rejestrowane na przykład, gdy kot zajdzie w ciążę i kiedy się urodzi.

/// Zdarzenie w ciąży jest odpalane, gdy dwa koty pomyślnie się rozmnażają
/// i rozpoczyna się licznik czasu ciąży dla matrony.
Zdarzenie W ciąży (właściciel adresu, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock);
/// Urodziny są uruchamiane za każdym razem, gdy pojawia się nowy kotek
/// istnienie. Dotyczy to oczywiście każdego stworzenia kota
/// za pomocą metody giveBirth, ale jest również wywoływana when
/// tworzony jest nowy kot gen0.
Narodziny zdarzenia (właściciel adresu, uint256 kittyId, uint256 matronId, uint256 sireId, geny uint256);

Zobacz, w jaki sposób skrót podpisu zdarzenia urodzenia odpowiada wartości w dzienniku w naszym przykładzie

keccak256 („Narodziny (adres, uint256, uint256, uint256, uint256)”) = 0x0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad5

Jak dotąd wiemy, że na bloku nr 51968F (5346959) narodził się kryptokitty! Następnym krokiem w naszym procesie dekodowania jest podzielenie pola danych zgodnie z pięcioma parametrami zdarzenia Narodziny. Pierwszym parametrem jest adres Ethereum, który ma 160 bitów długości, ale jest zakodowany 256 bitami (zera są dodawane po lewej stronie adresu). Pozostałe parametry to 256-bitowe liczby całkowite. Pole danych jest zatem podzielone na 5 części, każda z 256 bitami (64 znaki szesnastkowe).

właściciel: 0000000000000000000000001b8f7b13b14a59d9770f7c1789cf727046f7e542
KittyId:
000000000000000000000000000000000000000000000000000000000009fac1
matronId:
000000000000000000000000000000000000000000000000000000000009f80e
sireId:
0000000000000000000000000000000000000000000000000000000000089572
geny:
00004a50b390a6738697012a030ac21d585b4c8214ae39446194054b98e0b98f

Widzisz, co miałem na myśli przez „wdrażanie ETL z wielu plików tekstowych o stałej szerokości, których formaty są opisane tylko w kodzie źródłowym oprogramowania, które je utworzyło”? :-)

Przejdź do części 2, w której podzielimy się interesującymi faktami, które napotkaliśmy podczas analizy danych gry CryptoKitties!

Specjalne podziękowania dla zespołu Block Science za badania, spostrzeżenia i recenzje.