Šis ir Mičiela Muldersa viesu ziņojums par to, kā JavaScript kodēt Bitcoin līdzīgu blokķēdi

Blokķēdes pamatjēdziens ir pavisam vienkāršs: izplatīta datu bāze, kas uztur nepārtraukti augošu pasūtīto ierakstu sarakstu. Pievienojiet šai ieguvei ieguves atlīdzības un blokus, kas satur darījumus. Es domāju, ka jums ir vispārēja ideja par blokķēdi, vai ne?

Nekas nav labāks par to, kā pats kodēt blokķēdi, lai pilnībā izprastu blokķēdes iekšējo darbību. Šī apmācība paskaidros, kā izveidot blokķēdi, kas atdod ieguves atlīdzību. Pilns kods ir atrodams šeit.

Projekta iestatīšana: kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Kā kodēt Bitcoin

Tā kā mums patīk vienkāršība, mēs izmantosim tikai trīs dažādus failus:

  • app.js: satur Express API mijiedarbībai ar mūsu blokķēdi.
  • blockchain.js: satur klases mūsu blokķēdes, bloku un darījumu konstruēšanai.
  • package.json: satur mūsu instalētās npm paketes.

Vissvarīgākā pakete, kuru mēs izmantosim, ir kripto-js. Šajā paketē ir kriptogrāfijas standarti, kurus var izmantot JavaScript, piemēram, mūsu hash aprēķināšanai. Manuprāt, hash ir līme starp diviem blokiem. Šajā package.json failā var atrast daudz citu pakotņu, galvenokārt JavaScript ES7 kompilēšanai.

Apskatīsim dažādas klases.

Bloka struktūra

Bloks sastāv no vairākām īpašībām. Pirmkārt, mēs nododam laika zīmogu, lai norādītu brīdi, kad bloks tika izveidots. Nākamais parametrs ir darījumu masīvs, kas ir gatavs raktuvēs. Visbeidzot, mēs definējam lauku, kurā ir saite uz iepriekšējo bloku, izmantojot hash. Šis lauks nav obligāts, jo ģenēzes blokam nav priekšgājēja.

klases bloks {

konstruktors (laikspiedols, transakcijas, previousHash = ”) {

this.previousHash = previousHash;

this.timestamp = timestamp;

this.darījumi = darījumi;

this.hash = this.culculateHash ();

šī.nonce = 0;

}

}

Kā redzat, blokā ir hash parametrs, kas būs izšķirošs mūsu darba pierādīšanas algoritmam. Jaucējkomandu vislabāk var raksturot kā funkciju, kas ievadei rada unikālu izvadi, veicot matemātiskas darbības ar ievadi. Atšķirībā no šifrēšanas metodes ievadi nevar iegūt, pamatojoties uz jaucējfunkcijas izvadi. Ikreiz, kad mēs atradīsim pareizo jaucēju konkrētam blokam, tas tiks saglabāts bloka iekšpusē, kad tas veido mūsu ķēdi.

Nonce parametrs ir ļoti svarīgs mūsu darba pierādīšanas algoritmam. Iespēja atrast pareizo hash ir ļoti maza. Katru reizi, kad tiek aprēķināts nepareizs hash, nonce tiek palielināts. Kāpēc? Ja mēs nepalielināsim šo nepietiekamību, mēs atkal un atkal aprēķināsim to pašu hash. Tā kā mēs mainām nonce ikreiz, kad atrodam nepareizu hash, mēs katru reizi aprēķināsim citu hash. Tas ir intensīvs aprēķinu (kalnrūpniecības) process, un tāpēc to sauc par darba pierādīšanu.

Bloķēt Hash

Hash tiek aprēķināts, izmantojot sha256 () funkcionalitāti, ko piedāvā pakete crypto-js. Mēs vienkārši izmantojam iepriekšējo jaukšanu, laika zīmogu, neapstiprinātos darījumus un nē kā izejvielu jaunas hash izveidei.

calcHash () {

atgrieziet SHA256 (this.priekšējaisHash + this.timestamp + JSON.stringify (this.transaction) + this.nonce) .toString ();

}

Veidojiet Blockchain

Mēs esam gatavi sākt veidot savu blokķēdi. Mūsu blokķēde ir izveidota, izmantojot tukšu konstruktoru. Šis konstruktors nosaka dažus svarīgus parametrus, piemēram, mūsu ģenēzes bloku, ieguves grūtības, visus gaidītos darījumus un ieguves atlīdzību par jauna bloka ieguvi. Precīzu ieguves grūtību izmantošanu mēs paskaidrosim tālāk šajā rakstā.

klase Blockchain {

konstruktors (genesisNode) {

this.ķēde = [this.createGenesisBlock ()];

this.nodes = [+ genesisNode]

šī.grūtība = 4;

this.pendingTransactions = [];

this.miningReward = 100;

}

}

Mūsu blokķēde ir jāprecizē ar pirmo bloku, ko sauc par ģenēzes bloku. Šis bloks sastāv no faktiskā datuma, tukša darījumu masīva un nulles atsauces uz iepriekšējo jaukšanas parametru.

createGenesisBlock () {

atgriezt jaunu bloku (Date.parse ("2018-03-13"), [], "0");

}

Šis .nodes parametrs ietvers visus aktīvos mezglus mūsu decentralizētajā tīklā. Tas ir svarīgs rekvizīts, jo mēs to izmantosim, lai pārraidītu nesen iegūtos blokus uz citiem mezgliem. To var salīdzināt ar ļoti vienkāršu tenkas protokola ieviešanu.

Iegūt jaunāko bloku

Jaunākā bloka iegūšana ir tikpat vienkārša kā pēdējā elementa paņemšana no mūsu ķēdes masīva.

getLatestBlock () {

atgrieziet šo.ķēde [šī.ķēde.ilgums – 1];

}

Šo funkciju vēlāk izmantos, lai izgūtu jaunākā bloka jaucēju, kas jāiekļauj blokā, kurš ir gatavs raktuvēs un pievienots ķēdei.

Darījuma struktūra

Mūsu darījumu klase vienkārši sastāv no šādiem laukiem:

  • fromAddress: adrese, no kuras jūs sūtāt monētas.
  • toAddress: saņēmēja adrese.
  • Daudzums: monētu daudzums, kuru mēs vēlamies pārskaitīt.

klases darījums {

konstruktors (noAddress, toAddress, summa) {

this.fromAddress = fromAddress;

this.toAddress = toAddress;

this.summa = summa;

}

}

Darījumu un ieguves bloku pievienošana

Ja mēs vēlamies blokā iekļaut darījumu, mēs varam to pievienot mūsu blokshēmas pendingTransactions masīvam. Mēs izmantojam funkciju ar nosaukumu createTransaction, kas pieņem darījuma objektu.

createTransaction (darījums) {

this.pendingTransactions.push (darījums);

}

Tagad tas kļūst interesanti, jo mēs esam gatavi izrakties no jauna izveidotā bloka. Lai saprastu ieguves procesu, mēs jums paskaidrosim, kā tiek izmantots īpašums “grūtības”. Ja mēs nenosakām ieguves grūtības, viss hash (ieguves) izveides process tiktu veikts pāris milisekunžu laikā, pilnībā graujot darba pierādīšanas jēdzienu.

Mūsu piemērā mēs izvirzījām ieguves grūtības divās. Tas nozīmē, ka mēs vēlamies atrast hash, kas sākas ar diviem 0. Faktiski tas nav ierobežots ar 0. Ja vēlaties, lai adreses sākas ar “aa” vai “xx”, tas ir iespējams. Iespēja atrast hash, kas sākas ar diviem 0, ir daudz mazāka nekā tāda, kurā ir tikai viena nulle vai nav. Kā redzat, jo lielākas grūtības, jo mazāka iespēja atrast pareizo jaucējkomandu un jo ilgāk to atrast.

mineBlock (grūtības) {

while (this.hash.substring (0, grūtības)! == Masīvs (grūtības + 1). pievienojieties ("0")) {

šo.nence ++;

this.hash = this.culculateHash ();

}

console.log ("MĒRĶA BLOKS: " + tas.hash);

}

Kods: masīvs (grūtība + 1). Pievienoties (“0”) vispirms tiks izveidots masīvs ar 3 (2 + 1) tukšām vietām. Pēc tam mēs izsaucam masīva pievienošanās funkciju un sakām, ka starp katru tukšo slotu jāielīmē “0”, dodot virkni ar divām nullēm “00”.

Mēs šeit izmantojam brīdi, lai pārbaudītu divu nulļu jaucējkrātu. Ja tas nesākas ar divām nullēm, mēs palielinām nonce un pārrēķinām hash, līdz esam atraduši atbilstošu hash.

Mūsu bloku ķēdes klasē mēs definējam funkciju minePendingTransactions, kas izveidos jaunu bloku, izmantojot gaidītos darījumus. Tālāk mēs izrakām bloku un pievienojam to savai ķēdei. Tā kā mēs vēlamies atdarināt Bitcoin tīklu, jūs varat nodot kalnrūpniecības atlīdzību, kuru kalnrači saņems, lai atrastu pareizo jaucējkrātu.

minePendingTransactions (miningRewardAddress) {

let block = new Block (Date.now (), this.pendingTransactions, this.getLatestBlock (). hash);

block.mineBlock (šī. grūtība);

console.log (‘Bloķēšana veiksmīgi iegūta!’);

this.ķēde.push (bloķēt);

this.pendingTransactions = [

jauns darījums (null, miningRewardAddress, this.miningReward)

];

}

Kalnrači atlīdzību nesaņems uzreiz. Šī atlīdzība tiek uzskatīta par darījumu, un tā tiks iekļauta gaidāmo darījumu masīvā nākamajam blokam. Tātad, kad tiks izrakts nākamais bloks, kalnrači saņems savu atlīdzību.

Apstipriniet Blockchain

Šī ir tikai demonstrējoša funkcija, lai aprēķinātu mūsu blokķēdes derīgumu. Mēs sākam no ģenēzes bloka un sekojam visām saitēm / jaucieniem, līdz sasniedzam pēdējo bloku. Ir divi scenāriji, kuros mūsu bloku ķēde beidzas nederīga:

  • Aprēķinātais bloka jaukums nav vienāds ar blokā iekļauto jaukšanu.
  • Pašreizējā bloka rekvizīts previousHash nenorāda uz iepriekšējā bloka jaucēju.

isChainValid () {

par (lai i = 1; i < šī.ķēde.ilgums; i ++) {

const currentBlock = šī.ķēde [i];

const previousBlock = šī.ķēde [i – 1];

if (currentBlock.hash! == currentBlock.calculateHash ()) {

atgriezties nepatiesa;

}

if (currentBlock.previousHash! == previousBlock.hash) {

atgriezties nepatiesa;

}

}

atgriezties taisnība;

}

Notiek atlikuma izguve

Konkrēta konta atlikumu var iegūt, apskatot visus darījumus un atrodot ar šo kontu saistītos darījumus. Atlikumu var iegūt, veicot visu ienākošo un izejošo darījumu summu.

getBalanceOfAddress (adrese) {

ļaujiet līdzsvaram = 0;

par (šīs ķēdes konst. bloks) {

par (const trans of block.transactions) {

ja (trans.fromAddress === adrese) {

atlikums – = trans.summa;

}

ja (trans.toAddress === adrese) {

bilance + = trans. summa;

}

}

}

atgriešanās bilance;

}

Mūsu Blockchain API izpēte

API ir mazliet pārāk sarežģīts, lai to detalizēti aprakstītu. Mēs paskaidrosim, kas slēpjas dažādos API maršrutos.

Tā kā neesam ieviesuši tenku protokolu, mezgli ir jāreģistrē manuāli, kad to pievienojam tīklam. POST maršruts / mezgli pieņem veselu skaitli, kas apzīmē jūsu blokķēdes porta numuru.

Pēc mezgla reģistrēšanas mēs varam sākt pievienot darījumus ar POST / darījumu galapunktu. Šis galapunkts paredz trīs parametrus:

  • {string} fromAddress: adrese, no kuras jūs sūtāt codeCoins kādam citam.
  • {string} toAddress: codeCoins saņēmējs.
  • {int} summa: pārskaitītais Codecoins daudzums.

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Tagad mums ir daži darījumi, mēs varam izdzēst savu bloku, ieskaitot gaidāmos darījumus. Endpoint POST / mine ļauj mums to izdarīt. Tas aktivizēs kalnrūpniecības funkciju mūsu blokķēdē un atradīs pareizo hash. Neaizmirstiet pieprasījuma pamattekstā pievienot parametru honorAddress, jo katrs kalnrūpnieks saņem 100 codeCoins kā atlīdzību par jauna bloka ieguvi..

Turklāt funkcija nosūtīs notikumu visiem citiem tīkla mezgliem par jauna bloka pievienošanu. Pārējie mezgli izgūs jauno blokķēdi, izmantojot GET / blockchain.

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Maršruts ar nosaukumu GET / blockchain / atrisināt ir pievienots arī jaunajiem pievienotajiem mezgliem, lai atrastu garāko ķēdi un to izgūtu. To var uzskatīt par sinhronizācijas procesu starp mezgliem.

Beidzot mēs visi vēlamies uzzināt, cik mēs esam bagāti. GET / bilances /: adreses galapunkts atgriež, cik daudz jums ir codeCoins.

Blockchain pārbaude, izmantojot API

Pagriezīsim divus mūsu bloku ķēdes gadījumus 5000 un 5001. portā. Atveriet divus terminālus un izpildiet starta komandu. Mēs pievienojam papildu vides mainīgo, lai norādītu startēšanas komandu, kurā portā tas ir jādarbina.

OSTA = sākums npm

Labi, tagad mums ir divi mezgli. Mums abiem mezgliem jāapzinās viens otra eksistence. Lai nosūtītu šo pieprasījumu, mēs izmantosim Pastnieku. Jūs varat izmantot jebkuru vēlamo rīku. Neliela piezīme. Neaizmirstiet pievienot galveni, lai serverim pateiktu, ka mēs nosūtīsim JSON objektus: Content-Type -> pieteikums / json.

Ļaujiet mezglam 5000 apzināties mezglu 5001. Pēc tam nosūtiet tieši pretēju pieprasījumu, kā redzat attēlā.

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Pievienosim vienu vai vairākus šādus darījumus:

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Beidzot mēs vēlamies iegūt jaunu bloku.

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Izdrukājiet faktisko blokķēdi:

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Lai pabeigtu šo apmācību, vaicāsim par manu codeCoin atlikumu:

Kā kodēt Bitcoin līdzīgu blokķēdi JavaScript

Pilns kods ir atrodams šeit.

Es gribu pateikties Savjee lai padarītu šo rakstu iespējamu.

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me