Friday, December 25, 2015

Vremenski zaključane transakcije: Primjeri

Zajamčeni polog (escrow)


Ako Alice i Bob žele zajedno upravljati poslom, zajednička sredtva mogu držati u 2-od-2 višepotpisnoj transakciji. No u slučaju smrti jedne strane, druga strana neće imati pristup zajedničkim sredstvima. Zato bi mogli zaposili odvjetnika Lennyja da bude treća strana u slučaju nezgode. No kod 2-od-3 višepotpisne transakcije, odvjetnik se može urotit s bilokojom stranom te ukrasti zajednička sredstva. U ovakvom se slučaju može iskoristiti operator CHECKLOCKTIMEVERIFY u scriptSig dijelu transakcije:

IF
    <sad + 3 mjeseca> CHECKLOCKTIMEVERIFY DROP
    <Lennyjev pubkey> CHECKSIGVERIFY
    1
ELSE
    2
ENDIF


<Alicin pubkey> <Bobov pubkey> 2 CHECKMULTISIG

Ovakva se transakcija može potrošiti u bilokojem trenutku ovako:

0 <Alicin potpis> <Bobov potpis> 0
Postupak trošenja je sljedeći:
 
0
Bobov potpis
Alicin potpis
0
 
 
Ovako izgleda stog nakon pokušaja trošenja gornje vremenski zaključane transakcije prije isteka roka valjanosti. Naredba IF provjerava prvi element na stogu te se izvršavanje dalje nastavlja ovisno o tom elementu. Na vrhu stoga je 0 koja se tretira kao neistina te se prelazi na ELSE dio naredbe koja na stog stavlja 2.

2
Bobov potpis
Alicin potpis
0

 
Izgled stoga nakon izvršavanja naredbe IF. Ovo je sada normalna 2-od-2 višepotpisna transakcija
0 <Bobov potpis> <Alicin potpis> 2 <Alicin pubkey> <Bobov pubkey> 2 CHECKMULTISIG
Zbog buga u naredbu CHECKMULTISIG, m-od-n višepotpisna transakcija uzima jedan više potpis nego je zapravo potrebno.

Nakon isteka roka valjanosti ovu je transakciju moguće potrošiti na sljedeći način:
0 <Alicin/Bobov potpis> <Lennyjev potpis> 1

1
Lennyje potpis
Alicin/Bobov potpis
0

 
Ovako izgleda stog nakon pokušaja trošenja gornje vremenski zaključane transakcije nakon isteka roka valjanosti. Na stogu je 1 koji se tretira kao istina te se prelazi na provjeru roka valjanosti. Rok valjanosti ističe tri mjeseca nakon nastanka transakcije.

sad + 3 mjeseca
Lennyjev potpis
Alicin/Bobov potpis
0

 
Na stog se stavlja rok valjanosti te se uspoređuje s poljem nLockTime transakcije koja taj izlaz želi potrošiti. Budući da je rok istekao, izlaz se smije potrošiti. Naredba DROP odbacuje gornji element stoga (u ovom slučaju rok valjanosti).

Zatim se uzima Lennyjev javni ključ s kojim naredba CHECKSIGVERIFY provjerava Lennyjev potpis na stogu. Ako je potpis ispravan na stog se na kraju stavlja 1.

1
Alicin/Bobov potpis
0

Sada je ovo 1-od-2 višepotpisna transakcija koja se može potrošiti pomoću Alicinog ili pomoću Bobovog potpisa
0 Alicin/Bobov potpis 1 <Alicin pubkey> <Bobov pubkey> 2 CHECKMULTISIG

Neinteraktivna vremenski zaključana nadoknada


U nekim je protokolima potrebna suradnja dvije strane da bi se potrošila neka transakcija. U slučaju nedostupnosti jedne strane, povrat novca (nadoknada) se vremenski zaključati kako bi se nakon isteka roka valjanosti vratio pošiljatelju. Takva transakcija u kojoj Alice šalje Bobu sredstva može izgledati ovako
 
IF
     <rok_valjanosti> CHECKLOCKTIMEVERIFY DROP
    1
ELSE
     2
ENDIF
<Alicin pubkey> <Bobov pubkey> 2 CHECKMULTISIG

Slično kao i u prethodnom primjeru, ovakva se transakcija može prije isteka roka potrošiti s

0 <Alicin potpis> <Bobov potpis> 0

U slučaju nedostupnosti jedne strane i nakon isteka roka valjanosti, transakcija se može potrošiti s

0 <Alicin/Bobov potpis> 1

Plaćanje za objavljivanje podataka


Postoje usluge koje omogućuju plaćanje za objavljivanje informacija. Osoba koja objavljuje informaciju prvo mora dokazati da kriptirani dokument sadrži tražene podatke, a zatim konstruirati transakciju koja će otkriti ključ za dekripciju podataka. Trenutačne implementacije takvih sustava omogućuju osobi koja objavljuje informaciju da nikad ne otkrije tajni ključ. Taj se nedostatak može riješiti korištenjem naredbe CHECKLOCKTIMEVERIFY:

IF
    HASH160 <hash160(tajni_ključ)> EQUALVERIFY
    <pubkey objavljivača> CHECKSIG
ELSE
     <rok valjanosti> CHECKLOCKTIMEVERIFY DROP
     <pubkey platitelja> CHECKSIG
ENDIF

Objavljivač informacije transakciju može potrošiti ovako:
<potpis objavljivača> <tajni ključ> 1
 
1
Tajni ključ
Pubkey objavljivača

Ovako izgleda stog nakon pokušaja trošenja transakcije. 1 se smatra istinom te se prelazi na verifikaciju tajnog ključa.
 
Tajni ključ
Pubkey objavljivača

Gornji element stoga se hashira funkcijom HASH160 te uspoređuje s hashem podatka u transakciji. U slučaju da su identični (objavljen je pravi tajni ključ), verificira se potpis objavljivača te je tajna otkrivena onome tko je platio za nju.

U slučaju da objavljivač ne objavi tajni ključ, platitelj može dobit povrat novca nakon isteka roka valjanosti:
 
0 <potpis platitelja>
 
0
potpis platitelja

Zbog 0 se pralazi u ELSE dio transakcije koji na stog stavlja rok valjanosti i uspoređuje ga s poljem nLockTime:
 
Rok valjanosti
Potpis platitelja

Ako je rok prošao, odbacuje se sa stoga te se verificira potpis platitelja te on dobiva uplaćeni novac natrag.

Friday, December 18, 2015

Vremenski zaključane transakcije (BIP 65)


Svaka bitcoin transakcija ima polje nLockTime. Zamišljeno je da sadrži vrijednost koja govori kada se transakcija može potrošiti u budućnosti. Vrijednost polja može se interpertirati na dva načina: ako je vrijednost manja od 500.000.000 tretira se kao visina bloka u kojem transakcija postane validna, a ako je vrijednost veća od toga, tretira se kao datum kada transakcija postaje validna (broj sekundi od 1. siječnja 1970.).

Takva se transakcija može uključiti u blok koji je na zadanoj ili većoj visini, odnosno čije je vrijeme pronalaska veće ili jednako onome u polju nLockTime. Problem je što se ne može garantirati da izlazi koje koristi transakcija s popunjem nLockTime poljem neće prije potrošiti neka druga transakcija.

Zato je definirana naredba CHECKLOCKTIMEVERIFY (odnosno redefinirana je naredba NOP2). Ona služi tome da se zaključaju pojedini izlazi iz transakcija koji će se potrošiti u budućnosti te prima jedan parametar: rok valjanosti. Kada se tako zaključani izlaz želi potrošiti, njegov se rok valjanosti uspoređuje s poljem nLockTime transakcije koja ga troši. Izlaz će se potrošiti samo ako je rok valjanosti manji od nLockTime. Transakcije zaključane s CHECKLOCKTIMEVERIFY mogu se normalno uvrstiti u blok.

Primjer zamrzavanja sredstava


Slijedi primjer skripte u skriptnom jeziku Bitcoina kojom je moguće zamrznuti sredstva sve dok ne istekne zadani rok valjanosti:


<rok valjanosti> CHECKLOCKTIMEVERIFY DROP DUP HASH160 <pubKeyHash> EQUALVERIFY CHECKSIG


Transakcija koja će potrošiti ovaj izlaz mora imati nLockTime veći od roka valjanosti. Budući da se transakcija s takvim poljem može tek uključiti u blok čija je visina ili vrijeme veće od vrijednosti nLockTime, originalna će transakcija ostati nepotrošena do zadanog vremena. Nakon isteka roka valjanosti, transakcija se dalje normalno validira.

Zaobilaženje roka valjanosti


Rok valjanosti moguće je zaobići ako transakcija koja troši vremenski zaključani izlaz redne brojeve svojih izlaza postavi na maksimum (0xffffffff). To je zaostatak iz starih verzija protokola Bitcoin te operacija CHECKLOCKTIMEVERIFY provjerava vrijednosti rednih brojeva ulaza. Ako redni broj nije maksimum transakcija će moći normalno potrošiti izlaz ako je prošao rok valjanosti. U suprotnom, transakcija ne može potrošiti izlaz.

Sunday, December 6, 2015

Detalji coinbase transakcije


Na početku svakog bloka transakcija nalazi se tzv. coinbase transakcija. Ona donosi nagradu onome tko je uspješno izrudario blok. Sama nagrada sastoji se od subvencije za blok (trenutačno 25 BTC) te od naknada za sve transakcije u bloku.

Primjer strukture coinbase transakcije je
Version
1
Inputs
Prevoius hash
0
Index
0xFFFFFFFF
ScriptSig
03dae7052f4249503130302f040e7164560902c8108999000000d3072f425443432f20
Sequence
0
Outputs
Value
2510629190
ScriptPubKey
76a9142c30a6aaac6d96687291475d7d52f4b469f665a688ac
Locktime
0

U odnosu na ostale transakcije, coinbase transakcija je pojednostavljena. Nema referencu na prethodnu transakciju jer stvara nove bitcoine, a ne preuzima već postojeće. Budući da se ne referira na prethodnu transakciju, nema niti indeks prethodnog izlaza.

Coinbase transakcija nije niti potpisana digitalnim potpisom nego se polje ScriptSig koristi kao tzv. extra nonce polje. Često polje nonce u zaglavlju transakcije nije dovoljno veliko da bi se moglo samo koristiti za pretraživanje svih mogućih vrijednosti noncea. Zato se ono dopunjava poljem ScriptSig u koje se upisuje dio noncea koji nije stao u zaglavlje. Na taj način rudari dobivaju više mogućnosti za kombiniranje.

BIP34

Osim što služi kao extra nonce, u prvi bajt polja ScriptSig zapisuje se i visina bloka u kojem se nalazi coinbase transakcija. To osigurava da je hash svakog idućeg bloka i transakcije jedinstven. Format zapisa je broj bajtova u visini te sama visina zapisana u little endian formatu. U gornjem primjeru to je "03dae705", odnosno "03" bajta za visinu te visina u little endian formatu "dae705", odnosno u big endianu 05e7da te u decimalnom formatu 387034. Blok 227835 je prvi blok takvog formata te on i svi sljedeći imaju verziju 2.

Sunday, November 1, 2015

Vrste potpisa bitcoin transakcija


Bitcoin transakcije sastoje se od ulaza i izlaza. Ulazi sadrže reference na izlaze prethodnih transakcija koji su pod kontrolom korisnika te skripte za svaki ulaz koje omogućuju trošenje sredstava s prethodnih transakcija. Izlazi šalju vrijednosti iz trenutačne transakcije na adrese drugih korisnika.
Kada se bitcoin transakcija potpisuje, moguće je potpisati razne kombinacije ulaza i izlaza. Postoje tri moguće vrste potpisa, tzv. sighash_all, sighash_none te sighash_single. Uz to, uz svaki od tri tipa može ići dodatan modifikator anyonecanpay.

SIGHASH_ALL


Sighash_all najčešća je vrsta potpisa kod koje se potpisuju svi ulazi i izlazi iz transakcije. Ovaj način potpisivanja štiti cijelu transakciju od mogućih promjena.

SIGHASH_NONE


Ovaj način potpisivanja transakcije potpisuje sve ulaze, ali niti jedan izlaz što omogućuje bilokome da odredi kuda će se poslati satoshiji iz transakcije.

SIGHASH_SINGLE


Kod ovakvog se načina potpisivanja potpisuje se točno jedan izlaz čiji indeks odgovara ulazu specificiranom parametrom. Dakle, potpisuje se samo jedan ulaz i izlaz. Ostali se izlazi potpisuju samo djelomično (može im se promijeniti broj u nizu, engl. Sequence number). Takva transakcija omogućue drugim korisnicima da dodaju vlastite izlaze u nju.


Ovaj tip potpisa ne bi smio imati više ulaza nego izlaza, no Bitcoin protokol to ne zabranjuje. Ako se specificira ulaz koji nema pripadajući izlaz, nepostojećem će se izlazu pridijeliti hash 0x01.

SIGHASH_ANYONECANPAY

Ovaj modifikator znači da se potpisuje samo ulaz specificiran parametrom. Ostali korisnici mogu dodavati ulaze po želji.


To daje još tri mogućnosti potpisivanja transakcija.

SIGHASH_ALL SIGHASH_ANYONECANPAY


Potpisuje sve izlaze i samo jedan ulaz. Ovo omogućuje bilo kome da doda još ulaza u transakciju no ostali ne mogu promijeniti koliko će se satoshija poslati i na koju adresu.

SIGHASH_NONE SIGHASH_ANYONECANPAY


Potpisuje samo jedan ulaz te niti jedan od izlaza. Omogućuje ostalima da dodaju ulaze i izlaze po želji, odnosno da potroše transakciju kako žele.

SIGHASH_SINGLE SIGHASH_ANYONECANPAY

 Potpisuje samo jedan ulazi i izlaz. Ostalima omogućuje proizvoljno dodavanje ulaza i izlaza.

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.