Wprowadzenie do Bitcoin Script
Strona G艂贸wna
Artyku艂y
Wprowadzenie do Bitcoin Script

Wprowadzenie do Bitcoin Script

Zaawansowany
Opublikowane Jul 10, 2020Zaktualizowane Jan 18, 2022
13m

Spis Tre艣ci


Wprowadzenie

Bitcoin jest czasem okre艣lany jako programowalny pieni膮dz. Ze wzgl臋du na sw贸j cyfrowy charakter pozwala u偶ytkownikom na du偶膮 elastyczno艣膰, je艣li chodzi o ustalanie warunk贸w wydawania 艣rodk贸w.聽
M贸wi膮c o bitcoinach, m贸wimy o portfelach i monetach, ale mogliby艣my r贸wnie偶 my艣le膰 o portfelach jak o kluczach, monetach jako czekach, a blockchainie jako o rz臋dzie zamkni臋tych sejf贸w. Ka偶dy sejf ma ma艂膮 dziurk臋, dzi臋ki czemu ka偶dy mo偶e zdeponowa膰 czeki lub sprawdzi膰, jak wiele got贸wki jest w sejfie. Jednak tylko posiadacz klucza b臋dzie m贸g艂 uzyska膰 dost臋p do wn臋trza.

Kiedy posiadacz klucza chce da膰 pieni膮dze komu艣 innemu, odblokowuje swoje "pude艂ko". Tworz膮 nowy czek odwo艂uj膮cy si臋 do starszego (kt贸ry jest nast臋pnie niszczony) i zamyka go w pudle, kt贸re odbiorca mo偶e otworzy膰. Aby go wyda膰, nowy odbiorca powtarza proces.

W tym artykule przyjrzymy si臋 Script'owi, j臋zykowi programowania interpretowanemu przez w臋z艂y w sieci Bitcoina. Script rz膮dzi mechanizmem blokowania/odblokowywania wy偶ej wymienionych sejf贸w.


Jak dzia艂a Bitcoin?

Korzystaj膮c z naszej analogii, mo偶na powiedzie膰, 偶e ka偶da transakcja sk艂ada si臋 z dw贸ch cz臋艣ci - klucza (do odblokowania skrzynki) i blokady. Klucz s艂u偶y do otwierania pola zawieraj膮cego czek, kt贸ry chcesz wys艂a膰, a nast臋pnie dodajesz nowy do nowego pude艂ka z inn膮 blokad膮. Aby wyda膰 fundusze z nowego pude艂ka, potrzebujesz innego klucza.
Dosy膰 proste. Istnieje tak偶e pewna r贸偶norodno艣膰 blokad w systemie. By膰 mo偶e niekt贸re sejfy wymagaj膮 podania wielu kluczy, a inne mog膮 wymaga膰 udowodnienia, 偶e znasz okre艣lony sekret. Istnieje wiele warunk贸w, kt贸re ludzie mog膮 ustawi膰.聽
Naszym kluczem nazywamy scriptSig. Blokada to nasz scriptPubKey. Je艣li spojrzymy na te komponenty nieco bardziej szczeg贸艂owo, przekonamy si臋, 偶e sk艂adaj膮 si臋 one z kawa艂k贸w danych i blok贸w kodu. Po po艂膮czeniu tworz膮 niewielki program.

Dokonuj膮c transakcji, transmitujesz t臋 kombinacj臋 do sieci. Ka偶dy otrzymuj膮cy j膮 w臋ze艂 sprawdzi program, kt贸ry poinformuje go, czy transakcja jest prawid艂owa. Je艣li nie, zostanie ona po prostu odrzucona i nie b臋dziesz m贸g艂 wyda膰 zablokowanych 艣rodk贸w.

Czeki (monety), kt贸re posiadasz, nazywane s膮 niewydanymi wynikami transakcji (UTXO). Z funduszy mo偶e korzysta膰 ka偶dy, kto mo偶e dostarczy膰 klucz pasuj膮cy do blokady. Dok艂adniej kluczem jest scriptSig, a blokada to scriptPubKey.
Je艣li UTXO znajduj膮 si臋 w twoim portfelu, prawdopodobnie b臋d膮 one mia艂y warunek, 偶e tylko osoba, kt贸ra mo偶e udowodni膰 posiadanie tego klucza publicznego, jest w stanie odblokowa膰 te fundusze. Aby je odblokowa膰, udost臋pniasz scriptSig, kt贸ry zawiera podpis cyfrowy, za pomoc膮聽klucza prywatnego, b臋d膮cego odwzorowaniem klucza publicznego okre艣lonego w scriptPubKey. Brzmi zawile? Nie martw si臋, wszystko to wkr贸tce stanie si臋 jasne.


Zrozumienie stosu Bitcoina

Script to tak zwany j臋zyk oparty na stosie. Wszystko to oznacza, 偶e kiedy czytamy zestaw instrukcji, umieszczamy je w czym艣, co mo偶na uzna膰 za pionow膮 kolumn臋. Na przyk艂ad lista A, B, C spowoduje utworzenie stosu z A na dole i C na g贸rze. Gdy instrukcje m贸wi膮 nam, aby艣my co艣 zrobili, dzia艂amy na jednym lub kilku elementach le偶膮cych na g贸rze stosu.


Elementy A, B i C dodawane i usuwane ze stosu.


Mo偶emy rozr贸偶ni膰 dane (takie jak podpisy, hashe i klucze publiczne) od instrukcji (lub kod贸w operacyjnych). Instrukcje usuwaj膮 dane i w jaki艣 spos贸b je obs艂uguj膮. Oto bardzo prosty przyk艂ad tego, jak m贸g艂by wygl膮da膰 skrypt:
<xyz><md5 hasher> <d16fb36f0911f878998c136191af705e><check if equal>
Na czerwono mamy dane, a na niebiesko kody. Czytamy od lewej do prawej, wi臋c najpierw umieszczamy ci膮g <xyz> na stosie. Nast臋pny mamy kod operacji <md5 hasher>. Ten nie istnieje w Bitcoinie, ale powiedzmy, 偶e usuwa g贸rny element stosu (<xyz>) i hashuje go za pomoc膮 algorytmu MD5. Nast臋pnie dane wyj艣ciowe s膮 ponownie dodawane do stosu. Dane wyj艣ciowe to w tym wypadku d16fb36f0911f878998c136191af705e.
Co za zbieg okoliczno艣ci! Nasz nast臋pny element do dodania to <d16fb36f0911f878998c136191af705e>, wi臋c teraz nasz stos ma dwa identyczne elementy. Na koniec <check if equal> wysuwa dwa elementy z g贸ry i sprawdza, czy s膮 one r贸wne. Je艣li tak, dodaje <1> do stosu. Je艣li nie, dodaje <0>.聽
Doszli艣my do ko艅ca naszej listy instrukcji. Nasz skrypt m贸g艂 zawie艣膰 na dwa sposoby - je艣li pozosta艂y element by艂 zerem lub je艣li jeden z operator贸w spowodowa艂by awari臋, gdy niekt贸re warunki nie zosta艂y spe艂nione. W tym przyk艂adzie nie mieli艣my takich operator贸w i otrzymali艣my element niezerowy (<1>), wi臋c nasz skrypt by艂 prawid艂owy. Te zasady obowi膮zuj膮 r贸wnie偶 w przypadku prawdziwych transakcji Bitcoina.

To by艂 tylko wymy艣lony program. Przyjrzyjmy si臋 teraz realnym przyk艂adom.


Pay-to-Pubkey (P2PK)

Pay-to-Pubkey (P2PK) jest niezwykle prosty. Polega na zablokowaniu 艣rodk贸w na okre艣lonym kluczu publicznym. Je艣li chcesz otrzyma膰 艣rodki w ten spos贸b, przeka偶 nadawcy sw贸j klucz publiczny, a nie adres Bitcoin.

Pierwsz膮 transakcj膮 mi臋dzy Satoshi Nakamoto i Halem Finneyem w 2009 roku by艂a transakcja P2PK. Struktura by艂a intensywnie u偶ywana na pocz膮tku istnienia Bitcoina, ale obecnie w du偶ej mierze zast膮pi艂a j膮 metoda Pay-to-Pubkey-Hash (P2PKH).聽
Skrypt blokuj膮cy dla transakcji P2PK ma format <public key>OP_CHECKSIG. To proste. By膰 mo偶e zgad艂e艣, 偶e OP_CHECKSIG sprawdza podpis pod podanym kluczem publicznym. W zwi膮zku z tym nasz scriptSig b臋dzie prostym <signature>. Pami臋taj, scriptSig jest kluczem do zamka.



Nie ma nic prostszego. Do stosu dodawany jest podpis, a nast臋pnie klucz publiczny. OP_CHECKSIG usuwa je oba i weryfikuje podpis wzgl臋dem klucza publicznego. Je艣li si臋 zgadzaj膮, dodaje <1> do stosu. W przeciwnym razie dodaje <0>.

Z powod贸w, kt贸re om贸wimy w nast臋pnej sekcji, P2PK nie jest ju偶 tak naprawd臋 u偶ywany.


Pay-to-Pubkey-Hash (P2PKH)

Pay-to-Pubkey-Hash (P2PKH) jest obecnie najpopularniejszym rodzajem transakcji. O ile nie robisz nic, aby pobra膰 archaiczne oprogramowanie, Tw贸j portfel prawdopodobnie obs艂uguje go domy艣lnie.

ScriptPubKey w P2PKH jest nast臋puj膮cy:

OP_DUP OP_HASH160 <public key hash> (hash klucza publicznego) OP_EQUALVERIFY OP_CHECKSIG

Zanim wprowadzimy scriptSig, zobaczmy, co zrobi膮 nowe kody operacyjne:


OP_DUP

OP_DUP wyci膮ga pierwszy element i kopiuje go. Nast臋pnie dodaje oba z powrotem do stosu. Zazwyczaj robi si臋 to, aby艣my mogli wykona膰 operacj臋 na duplikacie, nie wp艂ywaj膮c na orygina艂.


OP_HASH160

Wyci膮ga pierwszy element i dwa razy go hashuje. W pierwszej rundzie zostanie zaszyfrowany algorytmem SHA-256. Wyj艣cie SHA-256 jest nast臋pnie hashowane za pomoc膮 algorytmu RIPEMD-160. Ko艅cowy wynik jest dodawany z powrotem na stos.


OP_EQUALVERIFY

OP_EQUALVERIFY 艂膮czy dwa inne operatory - OP_EQUAL i OP_VERIFY. OP_EQUAL wyci膮ga dwa elementy i sprawdza, czy s膮 one identyczne. Je艣li tak, dodaje 1 do stosu. Je艣li nie, dodaje 0. OP_VERIFY wyci膮ga g贸rny element i sprawdza, czy zwraca Prawd臋 (tzn. jest niezerowy). Je艣li tak nie jest, transakcja ko艅czy si臋 niepowodzeniem. Z艂膮czone, OP_EQUALVERIFY powoduje, 偶e transakcja ko艅czy si臋 niepowodzeniem, je艣li dwa g贸rne elementy nie pasuj膮 do siebie.

Tym razem scriptSig wygl膮da tak:

<signature> <public key>

Musisz poda膰 podpis i odpowiedni klucz publiczny, aby odblokowa膰 wyj艣cia P2PKH.



Mo偶esz zobaczy膰, co si臋 dzieje w powy偶szym GIF-ie. Nie r贸偶ni si臋 to zbytnio od skryptu P2PK. Dodajemy tylko kolejny krok, aby sprawdzi膰, czy klucz publiczny pasuje do hashu w skrypcie.

Jest jednak co艣 wartego zauwa偶enia. W skrypcie blokuj膮cym P2PKH klucz publiczny nie jest widoczny - widzimy tylko jego hash. Je艣li przejdziemy do eksploratora blockchain i spojrzymy na dane wyj艣ciowe P2PKH, kt贸re nie zosta艂y wydane, nie mo偶emy ustali膰 klucza publicznego. Jest ujawniany tylko wtedy, gdy odbiorca decyduje si臋 na przekazanie 艣rodk贸w.
Ma to kilka zalet. Po pierwsze, hash klucza publicznego jest po prostu 艂atwiejszy do przekazania ni偶 pe艂ny klucz publiczny. W艂a艣nie z tego powodu Satoshi uruchomi艂 go w 2009 roku. Hash klucza publicznego to ta rzecz kt贸r膮 dzisiaj nazywamy adresem Bitcoin.
Drug膮 korzy艣ci膮 jest to, 偶e hashe klucza publicznego mog膮 zapewni膰 dodatkow膮 warstw臋 zabezpiecze艅 przed obliczeniami kwantowymi. Poniewa偶 nasz klucz publiczny nie jest znany, dop贸ki nie wydamy funduszy, innym osobom jeszcze trudniej jest odgadn膮膰 klucz prywatny. Musieliby odwr贸ci膰 dwie rundy hashowania (RIPEMD-160 i SHA-256), aby je zdoby膰.



Pay-to-Script-Hash (P2SH)

Pay-to-Script-Hash (P2SH) by艂 bardzo interesuj膮cym rozwini臋ciem dla Bitcoina. Pozwala on nadawcy zablokowa膰 艣rodki na hashu skryptu - nie musz膮 oni wiedzie膰, co faktycznie robi skrypt. We藕my nast臋puj膮cy hash SHA-256:

e145fe9ed5c23aa71fdb443de00c7d9b4a69f8a27a2e4fbb1fe1d0dbfb6583f1

Nie musisz zna膰 wej艣cia hashu, aby zablokowa膰 fundusze. Wydaj膮cy musi jednak dostarczy膰 skrypt u偶yty do tego hashowania i spe艂ni膰 warunki tego skryptu.

Powy偶szy hash zosta艂 utworzony z nast臋puj膮cego skryptu:

<multiply by 2> <4> <check if equal>

Je艣li chcesz wyda膰 monety powi膮zane z tym scriptPubKey, nie tylko udost臋pniasz te polecenia. Potrzebujesz tak偶e scriptSig, kt贸ry sprawi, 偶e warto艣膰 uko艅czonego skryptu b臋dzie Prawd膮. W tym przyk艂adzie jest to element kt贸ry musisz (pomno偶y膰 przez 2) <multiply by 2>, aby otrzyma膰 wynik <4>. Oczywi艣cie oznacza to, 偶e nasz scriptSig to po prostu <2>.

W rzeczywisto艣ci skrypt scriptPubKey dla wyniku P2SH to:

OP_HASH160 <redeemScript hash> OP_EQUAL

Nie ma tu nowych operator贸w, ale mamy <redeemScript hash> jako nowy element. Jak sama nazwa wskazuje, jest to hash skryptu, kt贸ry musimy dostarczy膰, aby zrealizowa膰 fundusze (zwany redeemScript). ScriptSig zmieni si臋 w zale偶no艣ci od tego, co jest w redeemScript. Og贸lnie jednak oka偶e si臋, 偶e jest to kombinacja podpis贸w i do艂膮czonych kluczy publicznych, po kt贸rych nast臋puje (obowi膮zkowy) redeemScript:

<signature> <public key> <redeemScript>

Nasza ewaluacja r贸偶ni si臋 teraz nieco od "wykonania" stosu, kt贸re widzieli艣my do tej pory. Dzieje si臋 to w dw贸ch cz臋艣ciach. W pierwszej sprawdzamy po prostu, czy poda艂e艣 poprawny hash.



Zauwa偶, 偶e nie robimy nic z elementami poprzedzaj膮cymi redeemScript. W tym momencie nie s膮 u偶ywane. Dotarli艣my do ko艅ca tego miniprogramu, a najwy偶szy element jest niezerowy. To znaczy, 偶e jest poprawny.

Jednak jeszcze nie sko艅czyli艣my. W臋z艂y sieciowe rozpoznaj膮 t臋 struktur臋 jako P2SH, wi臋c faktycznie posiadaj膮 elementy scriptSig oczekuj膮ce na innym stosie. Tam w艂a艣nie b臋dzie u偶ywany podpis i klucz publiczny.
Jak dot膮d potraktowali艣my redeemScript jako element, lecz teraz b臋dzie on interpretowany jako instrukcje, kt贸re mog膮 by膰 czymkolwiek. We藕my przyk艂ad skryptu blokuj膮cego P2PKH, do kt贸rego musimy poda膰 <signature> i <public key> pasuj膮ce do <public key hash> wewn膮trz <redeemScript>.



Po rozszerzeniu redeemScriptu mo偶esz zauwa偶y膰, 偶e mamy sytuacj臋, kt贸ra wygl膮da dok艂adnie jak zwyk艂a transakcja P2PKH. Z tego miejsca po prostu uruchamiamy go tak, jak normalnie.

Pokazali艣my tutaj tak zwany skrypt P2SH (P2PKH), ale jest ma艂o prawdopodobne, aby艣 znalaz艂 go "na wolno艣ci". Nic nie stoi na przeszkodzie, aby艣 go stworzy艂, ale nie daje on 偶adnych dodatkowych korzy艣ci i ostatecznie zajmuje wi臋cej miejsca w bloku (a zatem kosztuje wi臋cej).

P2SH zazwyczaj przydaje si臋 w takich transakcjach, jak multisignature lub kompatybilnych z SegWit. Transakcje Multisig mog膮 by膰 bardzo du偶e, poniewa偶 czasem wymagaj膮 wielu kluczy. Przed wdro偶eniem funkcji Pay-to-Script-Hash nadawca musia艂by wymieni膰 wszystkie mo偶liwe klucze publiczne w swoim skrypcie blokuj膮cym.聽

W przypadku P2SH nie ma znaczenia, jak skomplikowane s膮 warunki wydatkowania. Hash redeemScriptu ma zawsze sta艂y rozmiar. Koszty s膮 zatem przenoszone na u偶ytkownik贸w, kt贸rzy chc膮 odblokowa膰 skrypt blokuj膮cy.

Kompatybilno艣膰 z SegWit to kolejny przypadek, w kt贸rym przydaje si臋 P2SH (om贸wimy szczeg贸艂owo r贸偶nice w strukturze transakcji w nast臋pnej sekcji). SegWit by艂 soft-forkiem, kt贸ry spowodowa艂 zmian臋 format贸w blok贸w/transakcji. Poniewa偶 jest to aktualizacja opcjonalna, nie ka偶dy software'owy portfel rozpoznaje zmiany.

To nie ma znaczenia, czy klienci zwijaj膮 hash skryptu SegWit w P2SH. Podobnie jak w przypadku wszystkich tego typu transakcji, nie musz膮 wiedzie膰, jaki b臋dzie odblokowuj膮cy redeemScript.


Transakcje SegWit (P2WPKH i P2WSH)

Bardziej kompleksowe wprowadzenie do SegWit znajduje si臋 w Przewodniku dla Pocz膮tkuj膮cych Dotycz膮cym Segregated Witness.
Aby zrozumie膰 format transakcji w SegWit, musisz wiedzie膰, 偶e nie mamy ju偶 tylko scriptSig i scriptPubKey. Teraz pojawia si臋 nam nowe pole zwane聽艣wiadkiem (witness). Dane, kt贸re przechowywali艣my w scriptSig, s膮 przenoszone do 艣wiadka, wi臋c scriptSig jest pusty.

Je艣li natrafisz na adresy zaczynaj膮ce si臋 na 鈥瀊c1鈥, nazywamy je rodzimymi SegWit (w przeciwie艅stwie do tylko zgodnych z SegWit, kt贸re zaczynaj膮 si臋 na 鈥3鈥, poniewa偶 s膮 to adresy P2SH).


Pay-to-Witness-Pubkey-Hash (P2WPKH)

Pay-to-Witness-Pubkey-Hash (P2WPKH) to SegWit'owa wersja P2PKH. Nasz 艣wiadek wygl膮da nast臋puj膮co:

<signature> <public key>

Zauwa偶, 偶e jest to dok艂adnie to samo, co scriptSig z P2PKH. Tutaj scriptSig jest pusty. Tymczasem scriptPubKey przypomina:

<OP_0> <public key hash>

Wygl膮da to nieco dziwnie, prawda? Gdzie s膮 kody, kt贸re pozwalaj膮 nam por贸wna膰 podpis, klucz publiczny i jego hash?

Nie pokazujemy tutaj dodatkowych operator贸w, poniewa偶 w臋z艂y, kt贸re otrzymuj膮 transakcj臋, wiedz膮, co z ni膮 zrobi膰 na podstawie d艂ugo艣ci <public key hash>. Oblicz膮 d艂ugo艣膰 i zrozumiej膮, 偶e musi by膰 prowadzona w tym samym stylu, co dobra, tradycyjna transakcja P2PKH.
Niezaktualizowane w臋z艂y nie wiedz膮, jak interpretowa膰 transakcj臋 w ten spos贸b, ale to nie ma znaczenia. Zgodnie ze starymi zasadami nie ma 艣wiadka, wi臋c czytaj膮 pusty scriptSig i niekt贸re dane. Oceniaj膮 to i okre艣laj膮 jako wa偶ne - je艣li o to chodzi, ka偶dy mo偶e wyda膰 otrzymany wynik (output). Dlatego SegWit jest uwa偶any za soft fork ze wsteczn膮 kompatybilno艣ci膮.


Pay-to-Witness-Script-Hash (P2WSH)

Hash Pay-to-Witness-Script (P2WSH) to nowy P2SH. Je艣li dotar艂e艣 tak daleko, prawdopodobnie mo偶esz si臋 domy艣li膰, jak to b臋dzie wygl膮da膰, niemniej i tak przez to przejdziemy. Naszym 艣wiadkiem jest to, co zwykle umieszczamy w scriptSigu. Na przyk艂ad w P2WSH, kt贸ry zwija transakcj臋 P2PKH, mo偶e wygl膮da膰 mniej wi臋cej tak:

<signature 1> <public key>

Oto nasz scriptPubKey:

<OP_0> <script hash>

Obowi膮zuj膮 te same zasady. W臋z艂y SegWit odczytuj膮 d艂ugo艣膰 hashu skryptu i okre艣laj膮, 偶e jest to wyj艣cie P2WSH, kt贸re ewaluuje si臋 podobnie jak P2SH. Tymczasem stare w臋z艂y postrzegaj膮 to jako wynik, kt贸ry ka偶dy mo偶e wyda膰.


Przemy艣lenia ko艅cowe

W tym artykule dowiedzieli艣my si臋 troch臋 o elementach sk艂adowych Bitcoina. Podsumujmy je szybko:


Typ skryptuOpis

Pay-to-Pubkey (P2PK)

Zamyka fundusze na okre艣lonym kluczu publicznym

Pay-to-Pubkey-Hash (P2PKH)

Zamyka fundusze na okre艣lonym hashu klucza publicznego (np. adresie)

Pay-to-Script-Hash (P2SH)

Zamyka fundusze na hashu skryptu, kt贸ry mo偶e dostarczy膰 odbiorca

Pay-to-Witness-Pubkey-Hash (P2WPKH)

SegWit'owa wersja P2PK

Pay-to-Witness-Script-Hash (P2WSH)

SegWit'owa wersja P2SH


Gdy brniesz coraz g艂臋biej w Bitcoina, zaczynasz rozumie膰, dlaczego ma on tak du偶y potencja艂. Transakcje mog膮 sk艂ada膰 si臋 z wielu r贸偶nych sk艂adnik贸w. Manipuluj膮c tymi elementami, u偶ytkownicy maj膮 du偶膮 elastyczno艣膰, je艣li chodzi o ustalanie warunk贸w, w jaki spos贸b i kiedy mo偶na wydawa膰 艣rodki.