Wednesday, January 18, 2017

Izdvojeno svjedočanstvo (segregated witness)


Izdvojeno svjedočanstvo (engl. segregated witness) struktura je koja se zapisuje u blok izvan Merkleovog stabla transakcija (svjedočanstva se zapisuju u poseban dio transakcije, a ulazi se referenciraju na njih). Sadrži podatke potrebne za provjeru ispravnosti transakcije, no ne i za provjeru rezultata transakcije. Točnije, sadrži skripte i potpise. Svjedočanstvo se zapisuje stablo koje se ugnježđuje u postojeće Merkleovo stablo preko coinbase transakcije.
Ovakav način strukturiranja transakcije omogućuje nekoliko stvari:
  1. Nema više promjenjivosti transakcije. Budući da potpis više nije dio hasha transakcije (jer je u izdvojenom svjedočanstvu), više nije moguće promijeniti potpis transakcije.
  2. SPV klijenti više ne moraju primati potpise transakcija, ako im je cilj samo provjeriti postoji li transakcija.
  3. Hashiranje transakcija kod potpisivanja više ne ovisi o kvadratu veličine bloka.
  4. Povećava se broj transakcija u bloku zbog mjesta koje je oslobođeno izdvajanjem potpisa.

 ID transakcije


Uvođenjem podatkovne strukture svjedočanstva (engl. witness) transakcija će imati dva identifikatora. Standardni txid koji je dvostruki SHA256 serijalizirane transakcije:
[nVersion][txins][txouts][nLockTime]
I novi wtxid koji je dvostruki SHA256 novog formata serijalizirane transakcije:
[nVersion][marker][flag][txins][txouts][witness][nLockTIme]
Marker je veličine jednog bajta i uvijek nula: 0x00.
Flag je veličine jednog bajta te ima vrijednost različitu od nule. Trenutačno: 0x01.
Witness je serijalizacija svih svjedočanstava transakcije. Svaki ulaz transakcije, txin, povezan je s poljem svjedočanstva. Svako polje svjedočanstva počinje var_int tipom podatka koji prikazuje broj podataka koji se stavljaju na stog za pojedini ulaz. Zatim slijede sami podaci od koji svaki opet počinje tipom podatka var_int koji opisuje duljinu podatka. Svjedočanstvo nije skripta.
Ako je transakciju kreirao stariji klijent koji ne podržava svjedočanstva, ulazi u transakciju moraju imati prazno witness polje: 0x00. U tom je slučaju wtxid = txid.

Zapis svjedočanstva

Svi wtxid-ovi moraju se zapisati. Wtxid coinbase transakcije je 0x0000…0000.
Vršni hash svjedočanstava izračunava se iz svih wtxid-ova u bloku, slično korijenu Merkleovog stabla. Taj se hash zapisuje u scriptPubKey coinbase transakcije. Zapis je minimalne duljine 38 bajtova, s time da je prvih šest 0x6a24aa21a9ed:
1 bajt – OP_RETURN (0x6a)
1 bajt – Stavi sljedećih 36 bajtova (0x24) na stog
4 bajta – zaglavlje zapisa (0xaa21a9ed)
32 bajta – hash zapisa – dvostruki SHA356(vršni hash svjedočanstava | rezervirana vrijednost)
scriptPubKey polje sadrži i 32-bitnu rezerviranu vrijednost. Ako postoji više izlaza takve strukture, onaj s najvećim indeksom smatra se zapisom hasha svjedočanstva. Rezervirana vrijednost zasad nema nikakvog značenja

Program svjedočanstva (witness program)

Skripta scriptPubKey koja se sastoji od bajta [OP_0..OP_16] nakon kojeg slijedi 2 do 40 bajtova dobiva novo značenje. Prvi bajt naziva se bajt verzije. Ostali bajtovi predstavljaju program svjedočanstva.
Dva slučaja u kojima se svjedočanstvo verificira su:
  1. Ako se scriptPubKey sastoji od bajta verzije i programa svjedočanstva. U tom slučaju scriptSig mora biti prazan jer je u suprotnom transakcija neispravna.
  2. Ako je scriptPubKey P2SH skripta. U tom je slučaju redeemScript skripta u polju scriptSig bajt verzije plus program svjedočanstva. Ako u polju scriptSig nije BIP16 redeemScript, transakcija nije ispravna.
 
Ako je bajt verzije 0, a program svjedočanstva je duljine 20 bajtova:
  • Interpretira se kao pay-to-witness-public-key-hash (P2WPKH) program.
  • Svjedočanstvo se sastoji od 2 elementa (oba manja od 520 bajtova). Prvi je potpis, a drugi javni ključ.
  • HASH160 javnog ključa mora odgovarati programu svjedočanstva.
  • Nakon verifikacije skripte, potpis se verificira pomoću javnog ključa korištenjem naredbe CHECKSIG.
Ako je bajt verzije 0, a program svjedočanstva je duljine 32 bajta:
  • Interpretira se kao pay-to-witness-script-hash (P2WSH) program.
  • Svjedočanstvo se sastoji od elemenata koji su ulaz skripti te serijalizirane skripte (witnessScript < 10000 bajtova).
  • SHA256 skripte witnessScript mora odgovarati programu svjedočanstva.
  • witnessScript se deserijalizira i izvršava.


Ako je bajt verzije 0, a program svjedočanstva nije duljine 20 niti 32 bajta, skripta nije ispravna. Ako je verzija veća od nule, program svjedočanstva se ne interpretira.

Parametri i semantika

Težina bloka računa se kao veličina bloka (1 MB) plus ukupna veličina svjedočanstava (3 MB).
Broj potpisa po bloku povećava se s 20.000 na 80.000.
Uvode se tri nova pravila za rudarenje:
  1. Za P2WPKH i P2WSH prihvaćaju se samo komprimirani javni ključevi.
  2. Argumenti za OP_IF i OP_NOTIF moraju biti prazan vektor (neistina) ili 0x01 (istina).
  3. Ako OP_CHECKSIG ili OP_CHECKMULTISIG ne uspiju, potpis mora biti nul-vektor.

Primjeri

P2WPKH


Slijedi primjer verzije 0 P2WPKH:
scriptPubKey: 0 <20 bajtova hasha javnog ključa>
(0x0014{20 bajtova hasha})
scriptSig: (prazno)
svjedočanstvo: <potpis><javni ključ>
Ponašanje je vrlo slično dosadašnjem. Skripta scriptPubKey u izlazu transakcije šalje bitcoine na hash javnog ključa (adresu). Transakcija koja želi te bitcoine potrošiti daje javni ključ koji odgovara hashu u izlazu transakcije koja je bitcoin poslala i potpis transakcije. Umjesto da se potpis i javni ključ nalaze u polju scriptSig, nalaze se u polju svjedočanstva.
U skripti scriptPubKey 0 označuje verziju witness programa. Duljina programa kaže da se radi o vrsti P2WPKH. Potpis se verificira s: <signature><pubkey> CHECKSIG. U usporedbi s P2PKH, P2WPKH koristi tri bajta manje u scriptPubKey.

P2WSH

Slijedi primjer 1 od 2 višepotpisne transakcije verzije 0 P2WSH:
scriptPubKey: 0 <32 bajta hasha skripte svjedočanstva>
(0x0020{32 bajta hasha})
scriptSig: (prazno)
svjedočanstvo: 0 <potpis1> <1 <javni1> <javni2> 2 CHECKMULTISIG>
U skripti scriptPubKey 0 označuje verziju witness programa. Duljina programa kaže da se radi o vrsti P2WSH. Posljednji element u svjedočanstvu (witnessScript) hashira se pomoću SHA256 te se hash uspoređuje s 32-bajtnom vrijednošću u polju scriptSig. Ako odgovaraju, skripta se izvršava. P2WSH povećava veličinu skripte s dosadašnjih 520 bajtova na 10.000.