Sunday, October 18, 2015

Striktni DER potpisi (BIP66)


U protokolu Bitcoin digitalni se potpisi enkodiraju u DER formatu. DER (distinguished encoding rules) je potskup BER formata (basic encoding rules) koji služi za enkodiranje podatkovnih struktura. DER format koristi se za jednoznačno enkodiranje, na primjer u kriptografskim protokolima.

Za validaciju potpisa transakcija u protokolu Bitcoin koristila se biblioteka OpenSSL. Budući da je ta biblioteka dopuštala određena odstupanja od DER formata, propisan je striktni DER format za enkodiranje potpisa. Taj format ne dopušta odstupanja te potpis koji nije u striktnom DER formatu nije validan.

Striktni DER format


Striktni DER format izgleda ovako:

0x30 [ukupna-duljina] 0x02 [R-duljina] [R-vrijednost] 0x02 [S-duljina] [S-vrijednost][tip potpisa]
 
  • Svaki DER potpis počinje bajtom 0x30.
  • Ukupna-duljina je duljina u bajtovima svega što slijedi, ne računajući bajt za tip potpisa.
  • 0x02 je bajt separatora.
  • R-duljina je bajt koji predstavlja duljina vrijednosti R u bajtovima.
  • R je vrijednost proizvoljne duljine enkodirana u big-endian formatu. Predstavlja r vrijednost u algoritmu ECDSA. Vrijednost ne može počinjati bajtom 0x00, osim ako bajt koji slijedi nije 0x80 ili veći. Ako je to slučaj, početni bajt mora biti 0x00.
  • S-duljina je bajt koji predstavlja duljina vrijednosti S u bajtovima.
  • S je vrijednost proizvoljne duljine enkodirana u big-endian formatu. Predstavlja s vrijednost u algoritmu ECDSA. Vrijednost ne može počinjati bajtom 0x00, osim ako bajt koji slijedi nije 0x80 ili veći. Ako je to slučaj, početni bajt mora biti 0x00.
  • Tip potpisa je bajt koji označuje vrstu potpisa. Dozvoljene su mu vrijednosti 0x01, 0x02, 0x03, 0x81, 0x82 te 0x83.
Ukupna duljina potpisa je najviše 72 bajta. Svi blokovi čiji rudari prepoznaju BIP66 imaju verziju 3.

Thursday, October 8, 2015

Formati ključeva


U protokolu Bitcoin postoje dvije vrste ključeva: privatni i javni. Privatni je ključ broj u rasponu od 1 do 115792089237316195423570985008687907852837564279074904382605163141518161494336. Javni ključ generira se iz privatnog množenjem privatnog ključa generatorom sliptičke krivulje. Rezultat su dva broja, x koordinata krivulje te y koordinata krivulje. Javni se i privatni ključevi radi praktičnosti zapisa ne prikauzju uvijek u decimalnom obliku.
Slijede primjeri različitih oblika zapisa ključeva. Za primjer privatnog ključa uzet je
d = 105627842363267744400190144423808258002852957479547731009248450467191077417570. Njemu pripadajući javni ključ je
Q = [40052878126280527701260741223305245603564636128202744842713277751919610658249,
 112427920116541844817408230468149218341228927370925731589596315545721129686052] gdje je prvi broj x koordinata, a drugi y koordinata eliptičke krivulje.

Privatni ključevi

Slijede formati zapisa privatnih ključeva. Duljina privatnog ključa je 32 bajta ili 256 bitova.

Heksadecimalni


Najčešći format zapisa privatnog ključe je heksadecimalni. To je ujedno i najjednostavniji zapis jer je privatni ključ potrebno samo pretvoriti u heksadecimalni oblik. Takav zapis izgledao bi ovako:
E9873D79C6D87DC0FB6A5778633389F4453213303DA61F20BD67FC233AA33262. Njegova duljina je 64 heksadecimalna znaka.

Heksadecimalni kompresirani


Još jedan jednostavni format zapisa privatnog ključa je heksadecimalni kompresirani format. Sastoji se od dodavanja bajta '0x1' na kraj ključa. Tako bi ključ iz primjera izgledao ovako: E9873D79C6D87DC0FB6A5778633389F4453213303DA61F20BD67FC233AA3326201. Duljina mu je 66 heksadecimalna znaka.

Heksadecimalni kompresirani format zapravo je dulji od normalnog heksadecimalnog formata. Naziva se kompresirani samo zato što služi za generiranje kompresiranih javnih ključeva koji umjesto 65 bajtova zauzimaju samo 33 bajta.

Wallet Import Format (WIF)

WIF je jedan od najčešćih formata zapisa privatnog ključa. Najčešće ga koriste novčanici za spremanje ključa. Postupak pretvaranja privatnog ključa u WIF format ima nekoliko koraka:
  1. Generira se privatni ključ.
  2. Na početak mu se doda bajt 0x80.
  3. Taj se niz dva puta hashira algoritmom SHA256.
  4. Od dobivenog se rezultata uzmu početna četiri bajta koji će služiti kao zaština suma.
  5. Ta se četiri bajta dodaju na kraju niza dobivenog u drugom koraku.
  6. Dobiveni se niz zatim pretvori u base58check bazu.
Za ključ iz primjera WIF je 5Kb8kLf9zgWQnogidDA76MzPL6TsZZY36hWXMssSzNydYXYB9KF. Wallet import format uvijek počinje brojem 5.

Kompresirani WIF

Kompresirani WIF sličan je normalnom WIF zapisu samo što se dobiva iz kompresiranog privatnog ključa. U koracima navedenima za dobivanje wallet import formata u drugom je koraku potrebno dodati i bajt '0x1' na kraj niza uz bajt '0x80' na početku niza. Rezultat je L53fCHmQhbNp1B4JipfBtfeHZH7cAibzG9oK19XfiFzxHgAkz6JK. Kompresirani WIF ključevi počinju s 'K' ili 'L'.

Javni ključevi

Slijede formati zapisa javnih ključeva. Duljina privatnog ključa je 64 bajta plus bajt prefiksa što daje 512, odnosno 520 bitova.

Heksadecimalni

Zapis javnog ključa u heksadecimalnom formatu je: 04 || x || y. Operator || označuje konkatenaciju, a x i y su x i y koordinate javnog ključa u heksadecimalnom obliku. Javni ključbi tad izgledao:
04588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9f88ff2a00d7e752d44cbe16e1ebcf0890b76ec7c78886109dee76ccfc8445424. Duljina mu je 130 heksadecimalnih znakova odnosno 65 bajtova računajući bajt prefiksa '0x4'.

Heksadecimalni kompresirani

Kompresirani javni ključ dobiva se iz kompresiranog privatnog ključa. Umjesto da se sastoji od x i y koordinate, dovoljna je samo x koordinata. Y se dobije rješavanjem jednadžbe eliptičke krivulje (y2 = x3 + 7) mod p. Da bi se jednoznačno odredio y potrebna je informacija je li on pozitivan ili negativan (odnosno, u slučaju konačnog polja, paran ili neparan). Ako je y paran, x koordinati dodaje se bajt prefiksa '0x2', ako je neparan dodaje se '0x3'. Kompresirani ključ tada izgleda ovako: 02588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9. U ovom je slučaju y paran pa je prefiks '0x2'. Duljina mu je 66 znakova, odnosno 33 bajta računajući bajt prefiksa.

Budući da se i kompresirani i nekompresirani javni ključevi komu koristiti za dobivanje bitcoin adresa te da će te adrese biti različite, potrebno je paziti koji se ključ koristi. O tome računa vode bitcoin novčanici koji uglavnom koriste kompresirani format budući da zauzima manje mjesta.

Sunday, December 7, 2014

Mnemonički kod za generiranje determinističkih ključeva (BIP 39)


Mnemonički kod korisit se za pretvaranje nizova znamenki u jednoznačno određene riječi engleskog jezika kako bi se olakšalo njihovo zapisivanje, pamćenje i prenošenje drugim osobama. Oni se koriste i u generiranju determinističkih novčanika.

Generiranje mnemoničkih kodova


Mnemonički kod mora enkodirati entropiju u grupama po 32 bita. Što je entropija veća, veća je i sigurnost, no rečenice su dulje. Propručena veličina entropije (ENT) je 128 do 256 bitova.


Nakon generiranja entropije, generira se zaštitna suma uzimajući prvih ENT/32 bitova od SHA256(ENT). Drugim riječima, izračuna se broj grupa od 32 bita (ENT/32) te se zatim uzme toliko bitova od SHA256 hasha entropije. Zaštitna suma doda se na kraj generiranih bitova entropije.


Ti se bitovi zatim podijele u grupe duljine 11 bitova. Svaka grupa predstavlja broj od 0 do 2047 koji predstavljaju indeks u listi riječi. Te se grupe zatim pretvaraju u riječi i to je generirani mnemonički kod.


Sljedeća tablica prikazuje odnos duljine entropije (ENT), duljine zaštitne sume (CS) te duljine generiranog mnemoničkog koda (MS) u riječima.


ENT
CS
ENT+CS
MS
128
4
132
12
160
5
165
15
192
6
198
18
224
7
231
21
256
8
264
24

 Lista riječi


Idealna lista riječi ima sljedeće karakteristike:
a) Pametan izbor riječi (dovoljno je upisati prva četiri slova riječi da bi se ona jednoznačno odedila)
b) Izbjegavaju se slične riječi
c) Sortirana lista riječi
Sve riječi moraju biti kodirane u UTF-8 formatu. Ovdje je lista takvih riječi.

 Korištenje mnemoničkog koda kao sjemena


Ako se generirani mnemonički kod želi koristit kao sjeme za hijerarhijski deterministički novčanik potrebno je koristiti funkciju PBKDF2. Mnemonički kod koristi se kao lozinka, salt je riječ “mnemonic” + lozinka, broj iteracija je 2048, a koristi se HMAC-SHA512.


Generiranje sjemena odvojeno je od generiranja koda.

Saturday, August 9, 2014

Kriptirani privatni ključevi (BIP38)


Privatne ključeve moguće je kriptirati tako da su zaštićeni lozinkom. Takav ključ može vidjti bilo tko, no samo osoba koja zna lozinku može ga dešifrirati. Takva zaštita pogodna je za kreiranje papirnatih novčanika i fizičkih bitcoina.


Postoje dva načina kriptiranja. Prvi omogućuje da se bilo koji privatni ključ zaštiti bilo kojom lozinkom. Drugi omogućuje dijeljeni ključ gdje jedna strana derivira međuključ iz lozinke, a druga strana derivira konačni ključ i adresu iz međuključa. Trošenje bitcoina moguće je jedino onome tko zna lozinku.


Uz svaki se kriptirani ključ sprema i hash rezultirajuće adrese koji služi za provjeru ispravnosti adrese.

Korištene funkcije


AES256Encrypt, AES256Decrpyt – šifriranje i dešifriranje pomoću AES šifre. Prima ključ od 256 bitova te 16 bajtova ulaza i deterministički daje 16 bajtova izlaza.
SHA256 – Algoritam za hashitanje koji uzima ulaz proizvoljne duljine te daje fiksni izlaz od 256 bitova (32 bajta).
Scrypt – Algoritam za deriviranje ključeva (engl. key derivation algorithm). Parametri: lozinka, salt, n, r, p, duljina. Kao izlaz daje niz znakova dužine parametra "duljina".
ECMultiply – množenje na krivulji secp256k1.
G, N – generator i red generatora eliptičke krivulje secp256k1.
Base58Check – alfanumerička baza 58 koja se koristi za enkodiranje bitcoin adresa.

Format kriptiranog ključa

  1. Ključ počinje prefiksom 0x0142 ili 0x0143 ovisno o tome je li korišteno množenje na eliptičkoj krivulji. Kad se na to primijeni Base58Check, korisnik će vidjeti 6P. Svaki kriptirani ključ počinje znakovima 6P. 6 zato da se razlikuje od normalnog privatnog ključa koji uvijek počinju brojem 5. Broj 6 znači da se radi o kriptiranom ključu koji se dekriptira pomoću metode P. P u ovom slučaju označuje lozinku (engl. Passphrase).
     
  2. 37 bajtova sadržaja:
    1. zastavica (1 bajt) označuje koristi li se množenje na krivulji ili ne
    2. zaštitna suma (4 bajta) SHA256(SHA256(očekivana_bitcoin_adresa))[0..3]
    3. 16 bajtova ovisno o množenju
    4. 16 bajtova AES šifrirani sadržaj (ovisi o množenju)

 Enkripcija bez množenja na eliptičkoj krivulji

 

Enkripcija:
  1. Izračunati bitcoin adresu i uzeti prva četiri bajta od SHA256(SHA256(adresa)). To je hash_adrese.
  2. Derivirati ključ iz lozinke pomoću funkcije scrypt s parametrima n=16384, r=8, p=8, duljina=64. Salt je hash_adrese. Podijeliti dobivena 64 bajta na dva dijela: polovica1 i polovica2.
  3. Napraviti AES256Encrypt(privatni_ključ[0..15] xor polovica1[0..15], polovica2). Rezultat je enkriptirana_polovica1.
  4. Napraviti AES256Encrypt(privatni_ključ[16..31] xor polovica1[16..31], polovica2). Rezultat je enkriptirana_polovica2.

Konačan je rezultat: Base58Check(0x01 0x42 + zastavica + salt + enkriptirana_polovica1 + enkriptirana_polovica2).

 Dekripcija:

  1. Uzeti enkriptirani ključ i lozinku.
  2. Izračunati polovica1 i polovica2 korištenjem algoritma scrypt predajući mu lozinku i hash_adrese.
  3. Izračunati enkriptirana_polovica1 i enkriptirana_polovica2 korištenjem AES256Decrypt.
  4. Iz privatnog ključa izračunati bitcoin adresu.
  5. Hashirati bitcoin adresu i provjeriti odgovara li hash_adrese.

Enkripcija s množenjem na eliptičkoj krivulji


Ovakav način enkripcije omogućuje da se kriptirani ključ generira poznavajući samo točku na eliptičkoj krivulji i salt koji je korisnik generirao bez poznavanja lozinke. Osoba koja zna lozinku naziva se vlasnik i ona generira jedan ili više međuključeva te i predaje osobi, pisaču, koja će generirati enkriptirani privatni ključ.
Enkriptirani privatni ključ može sadržavati broj čestice i redni broj. Zajedno su duljine 32 bita. Broj čestice je duljine 20 bitova, a redni broj 12 bitova.


Algoritam kojim vlasnik generira međuključ:

  1. Generirati 4 nasumična bajta salt_vlasnika
  2. Kodirati broj čestice i redni broj u big-endian formatu: čestica * 4096 + redni_broj. Ta se četiri bajta nazivaju čestica_redni broj.
  3. Konkatenirati salt_vlasnika i čestica_redni_broj. To se naziva entropija_vlasnika. Ako se ne koriste čestica i redni broj, entropija_vlasnika = salt_vlasnika.
  4. Generirati ključ iz lozinke pomoću algoritma scrypt duljine 32 bajta. Ti se bajtovi nazivaju predfaktor. Napraviti SHA256(SHA256(predfaktor + entropija_vlasnika)). To se naziva faktor_lozinke. Ako se ne koriste čestica i redni broj, faktor_lozinke je rezultat izvođenja algoritma scrypt.
  5. Pomnožiti faktor_lozinke s generatorom eliptičke krivulje te zapisati u kompresiranom formatu (33 bajta).
  6. Proslijediti rezultat množenja i salt_vlasnika pisaču.


Nakon što dobije međuključ od vlasnika, pisač provodi algoritam:

  1. Postavi zastavicu.
  2. Generira 24 nasumična bajta zvana sjemeb te napravi SHA256(SHA256()) nad njima. Rezultat se naziva faktorb.
  3. Pomnoži točku dobivenu od vlasnika sa faktoromb. Rezltat koristit kao javni ključ iz kojeg se izvede bitcoin adresa. To se zove generirana_adresa.
  4. SHA256(SHA256(generirana_adresa))[0..3] = hash_adrese
  5. scrypt(sjemeb) duljine 64 bajta, salt je hash_adrese + entropija_vlasnika
  6. Podijeliti dobivena 64 bajta na dva dijela: polovica1 i polovica2.
  7. Napraviti AES256Encrypt(sjemeb[0..15] xor polovica1[0..15], polovica2). Rezultat je enkriptirana_polovica1.
  8. Napraviti AES256Encrypt(enkriptirana_polovica1[8..15] + sjemeb[16..23] xor polovica1[16..235], polovica2). Rezultat je enkriptirana_polovica2.

Za konačan rezultat potrebno je napraviti Base58Check od 0x01 0x43 + zastavica + hash_adrese + entropija_vlasnika + enkriptirana_polovica1[0..7] + enkriptirana_polovica2.

Dekripcija:

  1. Prikupiti enkriptirani privatni ključ i lozinku od korisnika.
  2. Dobiti faktor_lozinke pomoću algoritma scrypt koristeći salt_vlasnika i lozinku.
  3. Dobiti ključ za dekripciju za sjemeb koristeći scrypt sa hash_adrese, entropija_vlasnika i rezultatom iz prethodnog koraka.
  4. Dekriptirati enkriptirana_polovica2 pomoću AES256Decrpyt da se dobije početnih 8 bajtova sjemeb i završnih 8 bajtova za enkriptirana_polovica1.
  5. Dekriptirati enkriptirana_polovica1 da se dobije ostatak sjemeb.
  6. Iz sjemeb izvesti faktorb.
  7. Pomnožiti faktor_lozinke i faktorb da se dobije privatni ključ povezan s generirana_adresa.
  8. Iz privatnog ključa izvesti bitcoin adresu.
  9. Provjeriti odgovara li hash_adrese.











Thursday, June 26, 2014

Hijerarhijski deterministički novčanici (BIP32)


Bitcoin novčanici mogu se podijeliti u dvije generacije. Prva generira privatne ključeve nasumično, tj. nedeterministički (npr. Bitcoin client ili Multibit). Novčanici druge generacije privatne ključeve generiraju iz jednog alfanumeričkog niza znakova, tzv. sjemena (npr. Electrum). Prednost takvih novčanika je što se ne mora raditi backup svakog ključa nego je dovoljno napraviti backup samo sjemena iz kojeg se zatim deterministički generiraju privatni i odgovarajući javni ključevi.

 Hijerarhijski deterministički novčanici

 

HD novčanici temelje se na matematici eliptičkih krivulja. Tipovi podataka koji se koriste su: cijeli brojevi (modulo red krivulje), koordinate točaka na krivulji i nizovi bajtova. Funkcije koje će se koristiti su (|| označuje konkatenaciju):


  • point (p) – vraća koordinate točke koja se dobije množenjem broja p generatorom krivulje G.
  • ser32(i) – serijalizira 32-bitni cijeli broj bez predznaka kao niz od 4 bajta, najznačajniji bajt prvi
  • ser256(p) – serijalizira cijeli broj p kao niz od 32 bajta, najznačajniji bajt prvi
  • serP(P) – serijalizira točku P kao niz bajtova koristeći SEC1 kompresirani oblik: serP(P) = (0x02 ili 0x03) || ser256(x)
  • parse256(p) – interpretira niz od 32 bajta kao 256-bitni broj, najznačajniji bajt prvi
     
U HD novčanicima koriste se tzv. prošireni ključevi. Ključevi su prošireni s dodatnih 256 bitova entropije i ta se ekstenzija naziva chain code te se označuje sa "c". Prošireni privatni ključ je tad par (k, c) gdje je k uobičajeni privatni ključ, a c je ekstenzija od 256 bitova. Javni ključ je (K, c) gdje je K uobičajeni javni ključ, K = point(k), a c je chain code koji može biti isti ili različit od roditeljskog.

Svaki prošireni ključ ima 231 normalnih potključeva (ključeva djece) i 231 ojačanih potključeva. Normalni potključevi koriste indekse od 0 do 231 – 1, a ojačani od 231 do 232 – 1. Drugačije zapisano, normalni potključevi su od (k, 0) do (k, 231 – 1), a ojačani od (k, 231) do (k, 232 – 1). Odnosno, chain code ojačanih ključeva počinje bitom 1. Vidimo da svaki prošireni ključ može imati 232 ključeva djece, odnosno 4 294 967 296 potključeva.

Derivacija ključeva djece


HD novčanik stablasta je struktura koja omogućuje da se potključevi (ključevi djeca) deriviraju iz ključeva roditelja. Iz privatnog roditeljskog ključa moguće je izvesti privatni ključ dijete, iz javnog roditeljskog ključa javni ključ dijete te iz privatnog roditeljskog ključa javni ključ dijete.

Funkcije za deriviranje temelje se na HMAC-SHA512 te koriste indeks koji se označuje s "i". HMAC prima dva parametra ključ (Key) i podatke (Data) Derivacije ovise o tome radi li se o normalnom potključu ili o ojačanom.

Privatni roditeljski ključ  → privatni ključ dijete


Funkcija CKDpriv (child key derivation) izračunava prošireni privatni potključ iz proširenog privatnog roditeljskog ključa: CKDpriv((kpar, cpar), i) → (ki, ci).

 
Algoritam:
  • Provjeri je li i ≥ 231 (želimo li derivirati normalan ili ojačani potključ)
    • Ako je, I = HMAC-SHA512(ključ = cpar, podaci = 0x00 || ser256(kpar) || ser32(i))
    • Ako nije, I = HMAC-SHA512(ključ = cpar, podaci = serP(point(kpar)) || ser32(i))
  • Podijeli I na dva dijela po 32 bita IL te IR
  • Dijete ključ je ki = parse256(IL) + kpar
  • Novi chain code je IR
  • Ako je parse256(IL) ≥ n ili ki = 0, uzmi novi i


Iz jednog proširenog roditeljskog privatnog ključa moguće je dobiti 232 privatnih ključeva djece. Polovica tih ključeva su normalni, a polovica ojačani. Iz tih se ključeva zatim može derivirati daljnih 232 ključeva itd.

Javni roditeljski ključ  javni ključ dijete

 

Ojačane ključeve djecu nemoguće je ovako derivirati. Ovaj algoritam derivira samo normalne ključeve i < 231. Algoritam CKDpub((Kpar, cpar), i):
  • I = HMAC-SHA512(ključ = cpar, podaci = serP(Kpar) || ser32(i))
  • Podijeli I na dva dijela po 32 bita IL te IR
  • Dijete ključ je Ki = point(parse256(IL)) + Kpar
  • Novi chain code je IR
  • Ako je parse256(IL) ≥ n ili je Ki točka u beskonačnosti , uzmi novi i

Iz ovog je vidljivo da je moguće generirati javne podključeve bez generiranja privatnih ključeva. Odgovarajuće privatne ključeve moguće je generirati naknadno.

Privatni roditeljski ključ  javni ključ dijete



Iz proširenog se privatnog ključa dobiva prošireni javni ključ na sljedeći način:
  • N(k, c) = (point(k), c) gdje je c chain code iz privatnog ključa


Za dobivanje javnog ključa djeteta iz privatnog roditeljskog ključa primjenjuje se jedna od dvije funkcije:


  • N(CKDpriv(kpar, cpar), i) za sve ključeve
  • CKDpub(N(kpar, cpar), i) samo za normalne ključeve


Kod korištenja ključeva u aplikaciji, chain code se zanemaruje.





Friday, May 23, 2014

Standardne transakcije


U Bitcoinu (verziji klijenta 0.9) postoji pet vrsta standardnih transakcija koje se razvrstavaju prema formatu izalza. Tih pet vrsta su: plaćanje na javni ključ (pay to public key, P2PK), plaćanje na hash javnog ključa (pay to publick key hash, P2PKH), plaćanje na hash skripte (pay to script hash, P2SH), višepotpisna transakcija te null transakcija

Plaćanje na javni ključ (P2PK)


Ovakav se način plaćanja izbjagava jer nije siguran. Koristi se jedino u coinbase transakcijama kad rudaru treba isplatiti nagradu za točno riješen blok.

scriptSig: <sig>
scriptPubKey: <pubKey> OP_CHECKSIG

Plaćanje na hash javnog ključa (P2PKH)


Ovo je najčešći način plaćanja. Ne koristi se direktno javni ključ nego bitcoin adresa (hash javnog ključa).

scriptSig: <sig> <pubKey>
scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG


Plaćanje na hash skripte (P2SH)

Ovo je kompleksniji način plaćanja od gornja dva. Umjesto hash javnog ključa u skripti se nalazi hash druge skripte. Onaj tko hoće potrošiti bitcoine iz takve tranaskcije, mora umjesto javnog ključa dati skriptu koja kad se hashira, odgovara hashu iz potpisa.

scriptSig: <sig><redeemscript>
scriptPubKey: OP_HASH160 <redeemscripthash> OP_EQUAL

Višepotpisna transakcija (multisig)

Transakcije za koje je potrebno m od n potpisa da bi ih se moglo potrošiti.

scriptSig: <sig1> <sig2>
scriptPubKey: OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG

Null transakcija

Tranaskcija koja se ne može potrošit inego je označana kao nevaljala. U nju je moguće dodati malu količinu podataka koju određeni klijenti mogu interpretirati. Tako rade protokoli izgrađeni na bitcoinu, npr. Colored coins.

scriptSig: OP_RETURN <data>


Sve su ostale transakcije nestandardne. To znači da ako izlaz nije u jednom od pet gorenabrojenih formata, rudari neće prihvaćati niti rudariti takve transakcije.

 

 

 



Saturday, May 17, 2014

Naprednije Bitcoin skripte

Transakcija s više potpisa



Transakcije s više potpisa (engl. multisignature/multisig) zathijevaju više od jednog ključa (potpisa) da se pristupi bitcoinima, npr. dva od tri.


Primjer 2-od-3: scriptSig: <sig1> <sig2>
scriptPubKey: OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG


Za ovu je transakciju potrebno dva od tri potpisa. Prva transakcija ima dva potpisa koji su potrebni za otključavanje sredstava na adresi. Za transakciju s više potpisa scriptPubKey dio ima posebnu konstrukciju. Prvo se navodi koliko je potpisa potrebno za otključavanje, zatim javni ključevi (ne hashevi kao kod standardnih), koliko tih ključeva ima te na kraju naredba za provjeru potpisa.


Stog
Naredba
Opis
<sig2>
<sig1>

Potpisi se stavljaju na stog.
<2>
<sig2>
<sig1>

Dodaje se broj potpisa potreban za otključavanje.
<pubKey3>
<pubKey2>
<pubKey1>
<2>
<sig2>
<sig1>

Dodaju se javni ključevi pomoću koji se verificiraju potpisi. Potpisi i ključevi verificiraju se u parovima.
<3>
<pubKey3>
<pubKey2>
<pubKey1>
<2>
<sig2>
<sig1>
OP_CHECKMULTISIG
Dodaje se broj javnih ključeva. Sad su na stogu svi potrebni ulazi za provjeru transakcije.
<1>

Na stogu je rezulat izvršavanja OP_CHECKMULTISIG naredbe

 
Tehnički gledano, OP_CHECKMULTISIG zbog buga uzima jedan parametar previše te se u scriptSig prije potpisa dodaje OP_0 kao lažni parametar.

Odd/Event Bet



Slijedi prijmjer kompleksne skripte koja nasumično izvršava podskripte. Može se, na primjer, koristiti za nasumično određivanje koji korisnik plaća naknadu na transakciju.


Naredba OP_2DUP duplira dva elementa s vrha stoga. OP_SWAP zamijeni dva elementa s vrha stoga. OP_LEFT zadrži samo n lijevih znakova. OP_ADD zbraja dva elementa s vrha stoga. OP_MOD je ostatak pri dijeljenju gornja dva elementa stoga.


Primjer: scriptSig: <Sig><pubKey>
scripPubKey: <7bb...><5aa...> OP_2DUP OP_HASH160 <aHash> OP_EQUALVERIFY OP_HASH160 <bHASH> OP_EQUALVERIFY OP_1 OP_LEFT OP_SWAP OP_1 OP_LEFT OP_ADD OP_2
OP_SWAP OP_MOD
OP_IF
     OP_DUP OP_HASH160 <pubKeyAHash> OP_EQUALVERIFY OP_CHECKSIG
OP_ELSE
     OP_DUP OP_HASH160 <pubKeyBHash> OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF

 
Stog
Naredba
Opis
<5aa...>
<7bb...>
<pubKey>
<sig>
OP_2DUP
Na stog se prvo stavljaju svi elementi i gornja se dva dupliraju.
<5aa...>
<7bb...>
<5aa...>
<7bb...>
<pubKey>
<sig>
OP_HASH160
Hashiranje vrha stoga
<aHash>
<aHash>
<7bb...>
<5aa...>
<7bb...>
<pubKey>
<sig>
OP_EQUALVERIFY
Dodavanje hasha i provjera jesu li jednaki
<7bb...>
<5aa...>
<7bb...>
<pubKey>
<sig>
OP_HASH160
Hashiranje vrha stoga
<bHash>
<5aa...>
<7bb...>
<pubKey>
<sig>

Dodavanja hasha na stog
<bHash>
<bHash>
<5aa...>
<7bb...>
<pubKey>
<sig>
OP_EQUALVERIFY
Provjera jesu li jednaki
<5aa...>
<7bb...>
<pubKey>
<sig>

Dodaje se 1 na stog
<1>
<5aa...>
<7bb...>
<pubKey>
<sig>
OP_LEFT
Uzima se <1> znak hash <5aa...>
<5>
<7bb...>
<pubKey>
<sig>
OP_SWAP
Zamijena dva gornja elementa
<7bb...>
<5>
<pubKey>
<sig>

Na stog se dodaje <1>
<1>
<7bb...>
<5>
<pubKey>
<sig>
OP_LEFT
Uzima se <1> znak hash <7bb...>
<7>
<5>
<pubKey>
<sig>
OP_ADD
Gornja se dva elementa zbrajaju
<12>
<pubKey>
<sig>

Dodaje se 2
<2>
<12>
<pubKey>
<sig>
OP_SWAP
Zamjena
<12>
<2>
<pubKey>
<sig>
OP_MOD
Ostatak pri dijeljenju <12> s <2>
<0>
<pubKey>
<sig>
OP_IF
Ako je na vrhu element isitni != 0 izvrši sljedeću naredbu
<pubKey>
<sig>
OP_ELSE
Ako nije (=0)
<pubKey>
<sig>
OP_DUP OP_HASH160 <pubKeyBHash> OP_EQUALVERIFY OP_CHECKSIG
Izvrši ovo

 
Ova skripta ne može se zapravo izvršiti budući da su naredbe OP_LEFT i OP_MOD onemogućene. Ovdje je stavljena samo kao primjer kompleksne skripte.