Děkuji Google: Jak těžit bitcoiny na BigQuery Google

Využívá sílu SQL k těžbě kryptoměny v cloudu

Miluji Google BigQuery. Jedná se o spravovanou, vysoce škálovatelnou datovou platformu, což znamená, že můžete velmi rychle vyhledávat obrovské množství dat (např. 4 terabajty za méně než 30 sekund!). Pravidelně ho využívám ve svých projektech (jako je Španělská lekce akce pro Asistenta Google) a vždy jsem ohromen vysokým výkonem.

Minulý týden jsme uspořádali setkání Dev.IL o blockchainu, technologii za bitcoiny, a byl jsem zasažen jedním z rozhovorů od Asafa Nadlera, vysvětlující mechanismy za technologií, která způsobuje, že bitcoinový klíště (klidně sledujte rozhovor zde) , ale spravedlivé varování, je to v hebrejštině :-). Když jsem se po schůzce vrátil domů, měl jsem otevřenou konzoli BigQuery s nějakým analytickým dotazem, který jsem napsal den předtím, a dostal jsem tento nápad: Co kdybych mohl použít BigQuery pro těžbu bitcoinů? Je to vůbec možné? Může to být nákladově efektivní? Vzhledem k působivé škálovatelnosti BigQuery se zdálo, že by to mohl být dobrý zápas.

(Spoiler: Bylo to! Až 25 Giga-hash / s, zdarma a velmi zábavné! Přečtěte si, jak ...)

Byl jsem velmi zaujatý, a tak jsem se rozhodl to zkusit. Chvíli jsem měl zájem experimentovat s technologií Blockchain a byla to skvělá příležitost. Trvalo to čtení četných článků a pár hodin práce, ale měl jsem nějaký úspěch! (Nebo spíše, úspěch konceptu ;-)

Myslel jsem, že by mohlo být zajímavé, kdybych se s vámi podělil o svou cestu k přeměně datového analytického stroje na těžební stroj bitcoinů. Výsledky mě docela překvapily. a vsadím se, že budete také!

Nejdříve však první: udělejme super rychlý přehled toho, jak funguje těžba bitcoinů.

Těžba bitcoinů v kostce

Pravděpodobně jste slyšeli, že těžba bitcoinů zahrnuje řešení výpočetně náročného matematického problému, a to je pravda: bitcoinový systém sestává z transakcí (tj. Převodu peněz mezi uživateli) a tyto transakce jsou registrovány ve veřejné knize, nazývané blockchain. Blockchain, jak název napovídá, je propojeným seznamem bloků transakčních dat.

Těžba bitcoinů v podstatě zahrnuje nalezení platného dalšího bloku, který vám zase dá, horník, cenu - v současné době 12,5 BTC za každý nalezený blok.

Každý blok se skládá ze dvou částí: záhlaví o velikosti 80 bajtů, následovaného seznamem transakcí. Záhlaví obsahuje identifikátor předchozího bloku (tj. Hash záhlaví předchozího bloku), stejně jako hash SHA256 seznamu transakcí, jakož i některé další informace. Jako horník musíte v zásadě nějak zajistit, aby záhlaví bloku, když hashuje dvakrát pomocí hashovací funkce SHA256, bylo menší než dané číslo, také nazývané „obtížnost“ - nebo jak těžké je najít cíl číslo (tj. platný další blok).

Bitcoinové bloky se těží rychlostí přibližně 1 blok každých 10 minut. S cílem zajistit, aby sazba zůstala konstantní, je obtížnost automaticky upravována každých 2016 bloků (zhruba každé dva týdny), takže je víceméně úměrná celkovému výkonu výpočetního výkonu, který do procesu vkládají horníci.

Těžba v podstatě zahrnuje vyzkoušení různých variací záhlaví, hlavně v poli nonce (poslední 4 bajty záhlaví), dokud nakonec nenajdete záhlaví, jehož hash začíná daným počtem nul (nebo, jinak řečeno - menší než některé) číslo, jak jsem uvedl výše).

Pokud chcete podrobnější vysvětlení, podívejte se na blogový příspěvek Ken Shirriff o těžbě bitcoinů, nebo jednoduše sledujte a sbírejte informace, které v příspěvku uvádím.

Těžba s BigQuery

Jste vyzváni, abyste se drželi mých kroků a použili příklady v tomto blogu. Některé zde uvedené dotazy se mohou podobat částem procesu těžby bitcoinů. Pokud máte zkušební účet Google Cloud Platform Free, jejich podmínky vám zakazují účastnit se těžby kryptoměny. I když žádný z příkladů uvedených v tomto příspěvku ve skutečnosti nebude těžit žádnou kryptoměnu, přesto vám doporučuji hrát si bezpečně a mít placený účet Google Cloud Platform, který, pokud je mi známo, žádným způsobem nezakazuje těžbu kryptoměn.

První věci první: Při pohledu na záhlaví bloku

Začněme tím, jak se těží v praxi. Podíváme se na záhlaví nějakého bloku z bitcoinových blockchainů a pokusíme se vypočítat hash sami a uvidíme, jak se to dělá (a pak také ověříme, že dokážeme udělat hashovací část pomocí BigQuery).

Ale kde najdeme blok?

Ukázalo se, že v BigQuery najdete celý Blockchain. Ale pro naše účely použijeme jiný zdroj, který nám také poskytne způsob, jak získat nezpracovaná binární data bloku: web s názvem blockchain.info. Náhodně jsem vybral jeden z posledních bloků, číslo 514868:

Binární data pro tento blok můžete získat (v hexadecimálním formátu) kliknutím na hash bloku a následným připojením? Format = hex k URL, což vede k tomuto odkazu. Blokové zobrazení také ukazuje úplný seznam transakcí a další zajímavá data a já vás vyzývám, abyste prozkoumali sami.

Prozatím se však zaměřme na hlavičku. Zkopírujeme prvních 160 znaků z dat bloku (tj. Prvních 80 bajtů):

000000204a4ef98461ee26898076e6a2cfc7c764d02b5f8d6708320000000000f99f5c4d5025979fcb33d245536a55b628d4564c075c0210cbbc941ad79fdbc5e495a497007497007497

Tato stránka Bitcoin Wiki vysvětluje, jak funguje hashovací algoritmus: v zásadě musíme vzít tuto hlavičku a spustit na ní funkci SHA256, poté ji znovu spustit na výsledek prvního spuštění. To by mělo vést k hašování bloku.

Takže první věc, pokud bychom to chtěli dělat v BigQuery, potřebovali bychom funkci SHA256. Naštěstí to bylo představeno ve verzi 2 BigQuery (a.k.a. Standard SQ). Potřebujeme také nějaký způsob převodu těchto hex hodnot na skutečné bajty. Naštěstí nás pokryla funkce zvaná FROM_HEX. Zatím je vše dobré.

Nyní můžeme zkusit napsat skutečný dotaz (jako jeden řádek):

VÝBĚR TO_HEX (SHA256 (SHA256 (FROM_HEX (
'000000204a4ef98461ee26898076e6a2cfc7c764d02b5f8d6708320000000000000000f99f5c4d5025979fcb33d245536a55b628d4564c075c0210cbbc941ad79fdbc5a497007497007497007497007497007007007007007005

(Pokud chcete postupovat dále, můžete zkusit spustit tento dotaz na konzole BigQuery. Také bude třeba zrušit zaškrtnutí možností dotazu „Použít starší SQL“. Pokud se zobrazí chyba, která zní: „Nerozpoznaná funkce to_hex“, je to znamená, že jste toto políčko nezaškrtli.)

Spuštěním výše uvedeného dotazu získáme následující výsledek:

Očekával jsem, že uvidím „000000000000000000082fac02f1bf91ad4e024e6a5a1537936e9d518f827a53“

Když jsem to udělal poprvé, byl jsem docela zklamaný, protože to vypadalo, že hash se liší od původního hashe bloku. Rychle jsem si však uvědomil, že to bylo právě obrácené! (Zdá se, že bitcoinové hashe jsou uloženy málo endiánsky).

Přidání funkce REVERSE těsně před voláním TO_HEX udělal trik:

VÝBĚR TO_HEX (REVERSE (SHA256 (SHA256 (FROM_HEX)
'000000204a4ef98461ee26898076e6a2cfc7c764d02b5f8d6708320000000000000000f99f5c4d5025979fcb33d245536a55b628d4564c075c0210cbbc941ad79fdbc5e497007497007497007497007497007457007457007005
Teď to vypadá oprávněně!

Takže to už je docela úspěch: nyní víme, že můžeme ověřit hashování bitcoinových bloků na BigQuery. Pokud bychom chtěli použít důl BigQuery, chtěli bychom použít stejnou sadu funkcí, kromě toho, že bychom neměli úplnou hlavičku: museli bychom hledat platnou hlavičku s dostatečně malou hodnotou hash.

Platná hlavička se skládá ze 6 polí:

  1. verze - Hodnoty 2, 3 a 4 jsou společné (přidávají se nové hodnoty)
  2. hashPrevBlock - hash předchozího bloku v řetězci
  3. hashMerkleRoot - Hash všech transakcí v bloku (vysvětlující)
  4. time - Časové razítko, kdy byl blok vytvořen
  5. obtížnost - obtížnost bloku uloženého jako číslo s pohyblivou řádovou čárkou
  6. nonce - 4 bajty, které můžeme měnit, abychom ovlivnili hodnotu záhlaví

Těžba v podstatě zkouší všechny možné kombinace pro nonce a poté kontroluje hash pro každou, dokud hash není pod cílovou hodnotou. Cílovou hodnotu lze snadno odvodit z obtížnosti bloku:

target = (0xffff * 2 ** (256-48)) / obtížnost

Minimální obtížnost pro každý blok je 1. Proto jakýkoli cíl bude mít alespoň 48 vedoucích nul. Protože číslo obtížnosti pro náš blok bylo 3462542391191,563, cíl byl: 0000000000000000000000514a490000000000000000000000000000000000000000000000

Zde najdete aktuální obtížnost a cílovou hodnotu (odkaz vám také poskytne trochu podrobnější vysvětlení vztahu mezi obtížností a cílovou hodnotou).

Takže v podstatě, pokud bychom chtěli reprodukovat proces těžby pro tento blok, museli bychom vyzkoušet všechny různé kombinace pro nonce, poslední 4 bajty záhlaví, dokud nenajdeme ten, jehož hash je menší než výše číslo.

Re-těžba bloku

Rozhodl jsem se začít malým hledáním posledního bytu, protože v tomto případě již máme odpověď. Zpočátku jsem přemýšlel o nahrání malé tabulky se všemi čísly mezi 0 a 255 (platné hodnoty pro tento bajt), ale pak jsem zjistil, že tuto tabulku lze ve skutečnosti napodobit kombinací dvou funkcí SQL: UNNEST () a GENERATE_ARRAY ():

VYBRAT * OD NEJNIŽŠÍ (GENERATE_ARRAY (0, 255)) num;

Vyzbrojeni těmito znalostmi jsem vytvořil svůj první dotaz, který se pokusil reprodukovat proces těžby uvnitř BigQuery:

VYBRAT
  TO_HEX (CODE_POINTS_TO_BYTES ([0xac, 0x99, 0x75, num])) AS
Z
  UNNEST (GENERATE_ARRAY (0, 255)) num
KDE
  TO_HEX (REVERSE (SHA256 (SHA256) (CONCAT (FROM_HEX (
'000000204a4ef98461ee26898076e6a2cfc7c764d02b5f8d670832000000000000000000f99f5c4d5025979fcb33d245536a55b628d4564c075c0210cbbc941ad79fdbc5e491b55a494a5117'), CODE_POINTS_TO_BYTES ([0xac, 0x99, 0x75, num])))))), jako '000000000000000000%'

Dobře, trochu si to škádlíme!

V podstatě, protože hledáme pouze správné nonce, odstranil jsem tuto část ze záhlaví (můžete zkontrolovat - dlouhý hex řetězec v dotazu je dlouhý pouze 152 znaků, což představuje 76 bajtů, tj. Záhlaví bez nonce). Náš dotaz hledá 4-bajtovou hodnotu, která po připojení k záhlaví povede k hash menšímu než cílové číslo.

Protože to byl můj první pokus, použil jsem hodnoty, které už z bloku znám, pro první 3 bajty v nonce, a BigQuery hledal pouze konečný byte. Fungovalo to jako kouzlo a rychle zjistilo správnou hodnotu nonce:

Možná se divíte, proč jsem použil LIKE uvnitř klauzule WHERE pro filtrování správného výsledku. Dělám to proto, že prostě hledáme hash menší než cílová hodnota. Protože cílová hodnota začíná 18 nulami, jednoduše odfiltrujeme libovolné číslo, které nezačíná 18 nulami (protože je zjevně větší než cílová hodnota). To znamená, že můžeme získat falešná pozitiva (např. Číslo začínající 18 nulami a poté libovolnou číslicí větší než 5), ale můžeme je rychle rychle odfiltrovat ručně.

Takže nyní, když víme, jak hledat záludnou neteř, můžeme rychle rozšířit hledání na více bajtů:

VYBRAT
  TO_HEX (CODE_POINTS_TO_BYTES ([0xac, num2, num3, num4])) AS
Z
  UNNEST (GENERATE_ARRAY (0, 255)) num2,
  UNNEST (GENERATE_ARRAY (0, 255)) num3,
  UNNEST (GENERATE_ARRAY (0, 255)) num4
KDE
  TO_HEX (REVERSE (SHA256 (SHA256) (CONCAT (FROM_HEX (
'000000204a4ef98461ee26898076e6a2cfc7c764d02b5f8d670832000000000000000000f99f5c4d5025979fcb33d245536a55b628d4564c075c0210cbbc941ad79fdbc5e491b55a494a5117'), CODE_POINTS_TO_BYTES ([0xac, num2, num3, num4])))))), jako '000000000000000000%'

Zatímco tento dotaz provede trik a najde 3 bajty, vyskytl se jeden problém: běží pomalu! Dokončení tohoto dotazu trvalo asi 30 sekund. Pokud bychom měli hledat všechny 4 bajty, trvalo by to asi dvě hodiny touto rychlostí. Již jsem zmínil, že nový blok se těží každých 10 minut, takže v době, kdy jsme našli výsledek, už jsme byli pozadu a nebylo by to relevantní.

Bylo to trochu zklamání (co se stalo s vysoce škálovatelným příslibem BigQuery?), A tak jsem se rozhodl dále prozkoumat a pokusit se zjistit, zda bych mohl něco udělat, abych to vylepšil.

Z mých předchozích zkušeností s BigQuery jsem si pamatoval, že spojení různých tabulek je nákladná operace, která způsobila, že dotazy běžely mnohem déle. Snažil jsem se odstranit spojovací krok generováním větší tabulky (tj. Říkat GENERATE_ARRAY, aby vygeneroval více čísel), ale po nějaké zkoušce a chybě se zdálo, že maximální velikost tabulky by stále byla kolem 1 milionu řádků, což znamená, že d stále se musím připojit ke stolům nebo hledat vždy jen 1 milion hashů (což je trochu zbytečné, protože CPU mého počítače to dokáže za méně než sekundu).

Vypadalo to, že by bylo možné těžit bitcoiny s BigQuery, ale stěží praktické.

Stále se moc nechci vzdát, a tak jsem vyzkoušel několik dalších přístupů. A jeden z nich skutečně pracoval!

Rychlejší těžba

Připomněl jsem, že BigQuery má několik velmi velkých souborů veřejných dat obsahujících obrovské tabulky. Po prohledání několika z nich jsem našel ten, který obsahoval 5,3 miliardy řádků, což je těsně nad 4 294 967 296, počet různých kombinací pro nonce. Pokud bych mohl vytvořit dotaz, který by prošel touto tabulkou, a vyzkoušet jinou kombinaci pro každý řádek v tabulce, mohl bych pokrýt všechny možné kombinace.

Snažil jsem se pro to použít funkci ROW_NUMBER () OVER () SQL, která by měla vrátit aktuální číslo řádku (pak bych mohl odvodit jinou sadu bajtů pro každý řádek, podle čísla řádku), ale rychle zmizel s následující chyba:

Během provádění dotazu došlo k překročení prostředků: Dotaz nelze provést v přidělené paměti.

Bummer! Ale pak jsem začal přemýšlet - co když jsem zkusil náhodná čísla? nakonec existuje velmi dobrá šance, že pokud existuje odpovídající hash, najdu to, protože počet pokusů je větší než počet kombinací.

Takže jsem přišel s tímto dotazem:

VÝBĚR TO_HEX (nonce)
Z (
  VYBRAT
    CODE_POINTS_TO_BYTES ([
      CAST (TRUNC (256 * RAND ()) AS INT64),
      CAST (TRUNC (256 * RAND ()) AS INT64),
      CAST (TRUNC (256 * RAND ()) AS INT64),
      CAST (TRUNC (256 * RAND ()) AS INT64)
    ]) AS nonce
  Z
    `fh-bigquery.wikipedia.wikipedia_views_201308`
)
KDE
  TO_HEX (REVERSE (SHA256 (SHA256) (CONCAT (FROM_HEX (
'000000204a4ef98461ee26898076e6a2cfc7c764d02b5f8d6708320000000000000000f99f5c4d5025979fcb33d245536a55b628d4564c075c0210cbbc941ad79fdbc5e00) 00700002

CAST (TRUNC (256 * RAND ()) AS INT64) generuje náhodné číslo mezi 0 a 255 a poté vnitřní část SELECT jednoduše vygeneruje tabulku s ~ 5,3 miliardami řádků čtyř náhodných hodnot. Pak vnější dotaz zajistí, že dostaneme pouze hodnoty, které ve skutečnosti vedou k dostatečně nízkému hašování - to je to, co hledáme!

K mému příjemnému překvapení se tento dotaz vrátil za pouhých 20,9 sekund - a skutečně našel správnou hodnotu nonce (dokonce ji našel dvakrát!):

To znamená, že jsem dokázal zkontrolovat téměř 4 miliardy hashů za 20 sekund, nebo asi 200 mega-hashe za sekundu. To není moc špatné - pokud vezmete v úvahu GPU, dostanete jen asi 30–60 mega-hashů za sekundu (CPU ještě méně, nemluvě o těžbě tužkou a papírem).

Takže nás to očividně nedostane nikde poblíž vyhrazeného těžebního hardwaru rychle, ale pod rukávem jsem měl ještě jeden trik ...

Konkurence

Pokud jste ostrostřelcem v kombinatorice, možná jste si všimli, že kontrola všech možných hodnot pro nonce nezaručuje velmi dobrou šanci na nalezení dostatečně malého hashe (jak jsem řekl na začátku, je to těžký problém!).

V době psaní byl cíl zhruba 2 ⁸² (podívejte se, jak vypočítáváme cíl z výše uvedených obtíží), což znamená, že existují 2 ⁸⁸ platné platné hashové kombinace z celkem 2 ⁵⁶⁵⁶ celkem, jinými slovy - šance na libovolné hašování bude nižší než cíl je 1 ku 2⁷⁴.

To v podstatě znamená, že pokud budeme měnit pouze nonce, zkontrolujeme možnosti 2 ²² a naše šance na nalezení požadovaného hashe je super malá: potřebujeme tedy více bajtů, abychom si mohli hrát.

Pokud se znovu podíváme na strukturu záhlaví, všimnete si, že můžeme lehce změnit časové pole (jiné uzly budou blok stále přijímat, pokud je čas mírně vypnutý), nebo můžeme něco změnit v seznamu transakcí našeho bloku, což bude mít za následek úplně jinou hodnotu pro pole hash kořenů merkle.

Jedním ze způsobů, jak změnit seznam transakcí (a tedy generovat různé merkle hash), je přidání dalšího užitečného zatížení k první transakci nazvané extraNonce, která může mít až 100 bajtů. Jiným způsobem by bylo pouze vybrat jinou sadu transakcí, které mají být zahrnuty do bloku.

Jde o to, aby byl úspěšný horník, musí se kromě nonce vyzkoušet různé kombinace seznamu transakcí a / nebo změnit časové pole. To znamená, že můžeme spustit dotaz, který jsme našli vícekrát, paralelně, pokaždé s jinou hlavičkou bloku. Ale kolik současných dotazů umožňuje BigQuery?

Podle stránky kvót si můžete přečíst až 50 souběžných dotazů, což může teoreticky vést až k 50krát rychlejšímu hašování. Opravdu to funguje? Nevím, nezkoušel jsem to. V současné době byl můj nejlepší výsledek s jediným dotazem 500 Mega-hashů za sekundu (s použitím tohoto souboru údajů o wikipedii na 106 miliard řádků jako zdrojové tabulky), což znamená, že s limitem 50 souběžných dotazů můžeme teoreticky získat až 25 Giga- hashe / second. Jako průměrný specializovaný důlní hardware - což není špatné, protože je v podstatě zdarma.

Kolik to tedy stojí?

BigQuery tvrdí, že je nákladově efektivní řešení. Už jsem byl přesvědčen o jejich rozšiřitelnosti, ale jejich cenová struktura byla pro mě také překvapením. Velmi dobré překvapení.

Cenový model pro BigQuery je založen výhradně na množství dotazovaných dat: v zásadě vám bude účtován bajt. Jde o to, že neúčtujete poplatky za zpracování ani za žádná mezilehlá data, která váš dotaz vygeneroval - pouze za bajty, které čtete ze zdrojové tabulky.

V našem případě používáme obrovské zdrojové tabulky, ale používáme je pouze ke generování velkého počtu kombinací náhodných čísel - ve skutečnosti nečteme žádná data pro tabulky. BigQuery má pěknou funkci, kde ukazuje odhadovanou cenu za dotaz (jako počet bytů, za které vám bude účtován). První 1 terabajt je zdarma každý měsíc a za každý další dotaz Tetabyte, který poté zadáte, zaplatíte 5 $. Není špatné!

Pokud tedy zkontrolujeme, jaké odhady BigQuery se týkají našeho velkého dotazu, zjistíme toto:

Takže v podstatě můžeme spouštět tolik dotazů, kolik jen chceme, zdarma! Určitě měří až do své žádosti o efektivitu nákladů (v tomto případě alespoň).

Shrnutí a závěry

Začalo to jako zábavné cvičení s cílem lépe se naučit, jak blockchain funguje. Když jsem začal, byl jsem si docela jistý, že jsem dosáhl nějakého tvrdého limitu (možná nějakého časového limitu CPU nebo tak něco), a musím říct, že jsem pořád docela překvapen, že jsem mohl získat veškerou tuto výpočetní sílu zdarma.

Zatímco můj výzkum ukazuje, že by mělo být možné přeměnit BigQuery na těžební stroj teoreticky, stále je třeba vykonat značné množství práce, kdybych chtěl automatizovat těžební proces. Hrubý výpočet ukazuje, že i kdyby byl takový horník postaven, při soutěži se všemi specializovanými těžebními hardware, které běží po celém světě, by mi to přineslo zhruba 5 $ ročně. Přesto vím, že bitcoiny lze těžit pomocí SQL, což je na nezaplacení ;-)

A co je nejdůležitější, tento experiment mi dal úplně nový pohled na obrovskou výpočetní sílu, která se vynakládá na těžbu bitcoinů. Mluvíme o 26 miliardách giga-hashe za sekundu - to je 2,6 * 10¹⁹, což je více než počet zrn písku na zemi. Každou sekundu. Musíte se divit, čeho bychom dosáhli, kdybychom místo toho využili i zlomek této výpočetní síly pro lékařský výzkum ...