Jak zbudować prosty blockchain kryptowaluty w Node.js
Opublikowany: 2022-03-10smashingCoin
, korzystając z koncepcji klas JavaScript i Node.js. Spróbuj — to prostsze niż myślisz!Bezprecedensowy rozwój kryptowalut i leżąca u ich podstaw technologia blockchain podbiły świat szturmem — od skromnych początków bycia koncepcją akademicką ponad dekadę temu po obecne zwiększone zastosowanie w różnych branżach.
Technologia blockchain cieszy się dużym zainteresowaniem ze względu na jej zdolność do zwiększania bezpieczeństwa w środowiskach pozbawionych zaufania, wymuszania decentralizacji i zwiększania wydajności procesów.
Tradycyjnie Python był de facto językiem programowania do programowania blockchain. Jednak wraz z rozpowszechnianiem się tej niesamowitej technologii zwiększyły się również możliwości rozwoju — i Node.js nie pozostał w tyle.
W tym samouczku opowiem o tym, jak zbudować prosty blockchain kryptowaluty w Node.js. Nie będzie to zbyt wyszukane, ale wystarczy, aby pomóc Ci zrozumieć, jak działa blockchain.
Nazwę tę prostą kryptowalutę smashingCoin
.
Jeśli jesteś programistą JavaScript, który chce zrobić krok w kierunku rozwijającej się dziedziny kryptowalut, ten artykuł wyposaży Cię w umiejętności niezbędne do rozpoczęcia pracy. Lub, jeśli jesteś ciekawy, jak działają rzeczy w świecie kryptowalut, ten samouczek może pomóc w odpowiedzi na niektóre z twoich pytań.
Zalecana literatura : Zrozumienie integralności podzasobów autorstwa Drew McLellan
Warunki wstępne
Aby pomyślnie wykonać ten samouczek, musisz mieć:
- Node.js zainstalowany na Twoim komputerze. Możesz go pobrać stąd;
- Edytor kodu, taki jak Visual Studio Code, Sublime Text lub dowolny inny.
Zacznijmy…
Co to jest łańcuch bloków?
Blockchain to technologia, która napędza waluty cyfrowe, takie jak Bitcoin i Ethereum. Jest to innowacyjna technologia rozproszonej księgi publicznej, która utrzymuje stale rosnącą listę rekordów, zwanych blokami, które są bezpiecznie połączone za pomocą kryptografii.
Termin blockchain zyskał swoją nazwę ze względu na sposób, w jaki przechowuje dane transakcyjne, tj. w blokach , które są ze sobą połączone w celu utworzenia łańcucha . Rozmiar łańcucha bloków rośnie wraz ze wzrostem liczby podejmowanych transakcji.
Wszelkie prawidłowe dane transakcyjne są rejestrowane w sieci blockchain, która podlega zasadom peer-to-peer określonym przez uczestników. Na przykład dane te mogą zawierać „wartość” bloku, na przykład w walutach cyfrowych, zapis transakcji (na przykład, gdy strony wymieniają towary i usługi) lub przywileje uprawnień, na przykład gdy łańcuch rejestruje informacje o własności.
Oprócz danych transakcyjnych, każdy blok może zawierać własny skrót kryptograficzny (unikalny identyfikator lub cyfrowy ślad), własną wartość jednorazową (dowolną liczbę losową użytą raz w obliczeniach kryptograficznych), skrót poprzedniego bloku oraz znacznik czasu ostatniego uwierzytelnione transakcje.
Ponieważ każdy nowy blok powinien wskazywać na poprzedni blok, jeśli blok zostanie włączony do łańcucha bez prawego skrótu ostatniego bloku, może to spowodować, że cały łańcuch bloków będzie nieważny. Ta właściwość niezmienności jest kluczem do bezpieczeństwa łańcuchów bloków.
Ponadto często stosuje się różne rodzaje protokołów konsensusu, aby zachować autentyczność łańcucha bloków. Konsensus zapewnia, że wszyscy uczestnicy zgadzają się na transakcje walidowane przez sieć.
Na przykład powszechnie stosowanym protokołem konsensusu jest dowód pracy, którego celem jest zidentyfikowanie liczby, która po wykonaniu określonej pracy obliczeniowej znajduje rozwiązanie skomplikowanego problemu matematycznego.
Główną ideą prac dowodowych jest to, że każdy uczestnik sieci blockchain powinien uważać tę liczbę za trudną do zidentyfikowania, ale łatwą do zweryfikowania. W konsekwencji zniechęca do spamowania i manipulowania strukturą łańcucha bloków.
W przypadku większości kryptowalut dodanie nowego bloku do łańcucha bloków wymaga rozwiązania złożonego równania matematycznego, którego trudność z czasem rośnie wraz z rozwojem łańcucha bloków. W związku z tym każda osoba, która udowodni, że wykonała pracę, rozwiązując ten problem, otrzymuje wynagrodzenie w postaci cyfrowej waluty w procesie zwanym „wydobyciem”.
Jak stworzyć blok
Teraz, po przedstawieniu technologii blockchain i jej działaniu, zobaczmy, jak możemy zastosować koncepcje w tworzeniu bloku. Jak wspomniano wcześniej, bloki są ze sobą powiązane, tworząc łańcuch bloków.
Do stworzenia waluty smashingCoin
klas JavaScript, które zostały wprowadzone w ES6.
Gotowy?
Ubrudźmy sobie ręce…
Oto kod dla klasy CryptoBlock
:
const SHA256 = require('crypto-js/sha256'); class CryptoBlock{ constructor(index, timestamp, data, precedingHash=" "){ this.index = index; this.timestamp = timestamp; this.data = data; this.precedingHash = precedingHash; this.hash = this.computeHash(); } computeHash(){ return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)).toString(); } }
Jak widać w powyższym kodzie, stworzyłem klasę CryptoBlock
i dodałem do niej metodę constructor()
— tak jak robi się to w każdej innej klasie JavaScript. Następnie, aby zainicjować jego właściwości, przypisałem metodzie constructor
następujące parametry:
index | To unikalna liczba, która śledzi pozycję każdego bloku w całym łańcuchu bloków. |
timestamp | Prowadzi ewidencję czasu wystąpienia każdej zrealizowanej transakcji. |
data | Dostarcza dane o zrealizowanych transakcjach, takie jak dane nadawcy, dane odbiorcy i ilość transakcji. |
precedingHash | Wskazuje na skrót poprzedniego bloku w łańcuchu bloków, co jest ważne dla zachowania integralności łańcucha bloków. |
Ponadto użyłem metody computeHash
do obliczenia skrótu bloku na podstawie jego właściwości, jak podano w powyższych danych.
Jak widać, zaimportowałem bibliotekę JavaScript crypto-js i użyłem jej modułu crypto-js/sha256
do obliczenia skrótu każdego bloku. Ponieważ moduł zwraca obiekt liczby, użyłem metody toString()
do przekonwertowania go na ciąg.
Aby dodać bibliotekę crypto-js do swojego projektu, przejdź do terminala i uruchom następujące polecenie, aby zainstalować go za pomocą npm
:
npm install --save crypto-js
Po uruchomieniu powyższego polecenia katalog node modules, który zawiera bibliotekę i inne niezbędne pliki, zostanie dodany do folderu twojego projektu.
Jak stworzyć łańcuch bloków
Jak wyjaśniono wcześniej, technologia blockchain opiera się na koncepcji, że wszystkie bloki są ze sobą połączone. Stwórzmy więc klasę CryptoBlockchain
, która będzie odpowiedzialna za obsługę operacji całego łańcucha. Tu guma spotyka się z drogą.
Klasa CryptoBlockchain
zachowa operacje łańcucha bloków przy użyciu metod pomocniczych, które wykonują różne zadania, takie jak tworzenie nowych bloków i dodawanie ich do łańcucha.
Oto kod dla klasy CryptoBlockchain
:
class CryptoBlockchain{ constructor(){ this.blockchain = [this.startGenesisBlock()]; } startGenesisBlock(){ return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain", "0"); } obtainLatestBlock(){ return this.blockchain[this.blockchain.length - 1]; } addNewBlock(newBlock){ newBlock.precedingHash = this.obtainLatestBlock().hash; newBlock.hash = newBlock.computeHash(); this.blockchain.push(newBlock); } }
Pozwólcie, że opowiem o rolach każdej z metod pomocniczych składających się na klasę CryptoBlockchain
.
1. Metoda konstruktora
Ta metoda tworzy instancję łańcucha bloków. Wewnątrz konstruktora utworzyłem właściwość blockchain
, która odnosi się do tablicy bloków. Zauważ, że przekazałem do niego startGenesisBlock()
, która tworzy początkowy blok w łańcuchu.
2. Tworzenie bloku Genesis
W łańcuchu blokowym blok genezy odnosi się do pierwszego w historii bloku utworzonego w sieci. Za każdym razem, gdy blok jest zintegrowany z resztą łańcucha, powinien odwoływać się do poprzedniego bloku.
I odwrotnie, w przypadku tego początkowego bloku nie ma żadnego poprzedzającego bloku, na który można by wskazać. Dlatego blok genezy jest zwykle zakodowany na sztywno w łańcuchu bloków. W ten sposób można na nim tworzyć kolejne bloki. Zwykle ma indeks 0.
Do stworzenia bloku genesis użyłem metody startGenesisBlock()
. Zauważ, że utworzyłem go za pomocą wcześniej utworzonej klasy CryptoBlock
i przekazałem parametry index
, timestamp
, data
, oraz precedingHash
.
3. Uzyskanie najnowszego bloku
Uzyskanie najnowszego bloku w łańcuchu bloków pomaga w zapewnieniu, że hash bieżącego bloku wskazuje na hash poprzedniego bloku — w ten sposób zachowując integralność łańcucha.
Do jego pobrania użyłem metody obtainLatestBlock()
.
4. Dodawanie nowych bloków
Użyłem metody addNewBlock()
, aby dodać nowy blok do łańcucha. Aby to osiągnąć, ustawiłem poprzedni hash nowego bloku tak, aby był równy hashowi ostatniego bloku w łańcuchu — zapewniając w ten sposób, że łańcuch jest odporny na manipulacje.
Ponieważ właściwości nowego bloku zmieniają się z każdym nowym obliczeniem, ważne jest ponowne obliczenie jego skrótu kryptograficznego. Po zaktualizowaniu skrótu nowy blok jest umieszczany w tablicy blockchain.
W rzeczywistości dodanie nowego bloku do łańcucha bloków nie jest takie proste ze względu na kilka wprowadzonych kontroli. Niemniej jednak w przypadku tej prostej kryptowaluty wystarczy zademonstrować, jak faktycznie działa blockchain.
Testowanie łańcucha bloków
Teraz przetestujmy nasz prosty blockchain i zobaczmy, czy działa.
Oto kod:
let smashingCoin = new CryptoBlockchain(); smashingCoin.addNewBlock(new CryptoBlock(1, "01/06/2020", {sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50})); smashingCoin.addNewBlock(new CryptoBlock(2, "01/07/2020", {sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100}) ); console.log(JSON.stringify(smashingCoin, null, 4));
Jak widać w powyższym kodzie, stworzyłem nową instancję klasy CryptoBlockchain
i nazwałem ją smashingCoin
. Następnie dodałem dwa bloki do łańcucha bloków, używając arbitralnych wartości. W parametrze data
użyłem obiektu i dodałem dane nadawcy, dane odbiorcy oraz ilość transakcji.
Jeśli uruchomię kod na terminalu, oto wynik, który otrzymuję:
Tak wygląda smashingCoin
! Jest to obiekt zawierający właściwość blockchain
, która jest tablicą zawierającą wszystkie bloki w łańcuchu. Jak widać na powyższym obrazku, każdy blok odwołuje się do skrótu poprzedniego bloku. Na przykład drugi blok odwołuje się do skrótu pierwszego bloku. Po przetestowaniu i stwierdzeniu, że nasz blockchain działa, dodajmy kilka dodatkowych funkcji, aby ulepszyć funkcje smashingCoin
.
Jak zweryfikować integralność Blockchain?
Jak wspomniano wcześniej, kluczową cechą łańcucha bloków jest to, że po dodaniu bloku do łańcucha nie można go zmienić bez unieważnienia integralności reszty łańcucha.
Dlatego, aby zweryfikować integralność łańcucha bloków, dodam metodę checkChainValidity()
do klasy CryptoBlockchain
.
Skróty mają kluczowe znaczenie dla zapewnienia ważności i bezpieczeństwa łańcucha bloków, ponieważ każda zmiana zawartości bloku spowoduje powstanie całkowicie nowego skrótu i unieważnienie łańcucha bloków.
W związku z tym metoda checkChainValidity()
użyje instrukcji if
do sprawdzenia, czy hash każdego bloku został naruszony. Zaczynając od pierwszego utworzonego bloku, zapętli się po całym łańcuchu bloków i sprawdzi jego poprawność. Zauważ, że ponieważ blok genezy został zakodowany na sztywno, nie będzie sprawdzany.
Ponadto metoda zweryfikuje, czy skróty każdego z dwóch kolejnych bloków wskazują na siebie. Jeśli integralność łańcucha bloków nie została naruszona, zwraca prawdę; w przeciwnym razie, w przypadku jakichkolwiek anomalii, zwraca fałsz.
Oto kod:
checkChainValidity(){ for(let i = 1; i < this.blockchain.length; i++){ const currentBlock = this.blockchain[i]; const precedingBlock= this.blockchain[i-1]; if(currentBlock.hash !== currentBlock.computeHash()){ return false; } if(currentBlock.precedingHash !== precedingBlock.hash) return false; } return true; }
Jak dodać dowód pracy
Jak wspomniano wcześniej, proof of work to koncepcja stosowana w celu zwiększenia trudności związanych z wydobyciem lub dodaniem nowych bloków do blockchaina.
W przypadku smashingCoin
wykorzystam prosty algorytm, który zniechęca ludzi do łatwego generowania nowych bloków lub spamowania łańcucha bloków.
Tak więc w klasie CryptoBlock
dodam kolejną metodę o nazwie proofOfWork().
Zasadniczo ten prosty algorytm identyfikuje liczbę przekazaną jako właściwość difficulty
, tak że skrót każdego bloku zawiera wiodące zera, które odpowiadają temu poziomowi difficulty
.
Upewnienie się, że hash każdego bloku zaczyna się od liczby zer określonej na poziomie difficulty
, wymaga dużej mocy obliczeniowej. Im wyższy poziom trudności, tym więcej czasu zajmuje wydobycie nowych bloków.
Co więcej, dodam losową wartość nonce
do każdego haszowanego bloku, tak aby podczas ponownego mieszania nadal można było spełnić ograniczenia poziomu trudności.
Oto kod:
proofOfWork(difficulty){ while(this.hash.substring(0, difficulty) !==Array(difficulty + 1).join("0")){ this.nonce++; this.hash = this.computeHash(); } }
A oto zaktualizowana computeHash()
z dołączoną zmienną nonce
:
computeHash(){ return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)+this.nonce).toString(); }
Dodatkowo, aby zaimplementować mechanizm proof of work przy generowaniu nowych bloków, uwzględnię go w addNewBlock()
:
addNewBlock(newBlock){ newBlock.precedingHash = this.obtainLatestBlock().hash; //newBlock.hash = newBlock.computeHash(); newBlock.proofOfWork(this.difficulty); this.blockchain.push(newBlock); }
Zawijanie
Oto cały kod do budowy kryptowaluty smashingCoin
przy użyciu Node.js:
const SHA256 = require("crypto-js/sha256"); class CryptoBlock { constructor(index, timestamp, data, precedingHash = " ") { this.index = index; this.timestamp = timestamp; this.data = data; this.precedingHash = precedingHash; this.hash = this.computeHash(); this.nonce = 0; } computeHash() { return SHA256( this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data) + this.nonce ).toString(); } proofOfWork(difficulty) { while ( this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0") ) { this.nonce++; this.hash = this.computeHash(); } } } class CryptoBlockchain { constructor() { this.blockchain = [this.startGenesisBlock()]; this.difficulty = 4; } startGenesisBlock() { return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain", "0"); } obtainLatestBlock() { return this.blockchain[this.blockchain.length - 1]; } addNewBlock(newBlock) { newBlock.precedingHash = this.obtainLatestBlock().hash; //newBlock.hash = newBlock.computeHash(); newBlock.proofOfWork(this.difficulty); this.blockchain.push(newBlock); } checkChainValidity() { for (let i = 1; i < this.blockchain.length; i++) { const currentBlock = this.blockchain[i]; const precedingBlock = this.blockchain[i - 1]; if (currentBlock.hash !== currentBlock.computeHash()) { return false; } if (currentBlock.precedingHash !== precedingBlock.hash) return false; } return true; } } let smashingCoin = new CryptoBlockchain(); console.log("smashingCoin mining in progress...."); smashingCoin.addNewBlock( new CryptoBlock(1, "01/06/2020", { sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50 }) ); smashingCoin.addNewBlock( new CryptoBlock(2, "01/07/2020", { sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100 }) ); console.log(JSON.stringify(smashingCoin, null, 4));
Jeśli uruchomię kod na terminalu, oto wynik, który otrzymuję:
Jak widać na powyższym obrazku, skróty zaczynają się teraz od czterech zer, które odpowiadają poziomowi trudności ustawionemu w mechanizmie proof of work.
Wniosek
Otóż to! W ten sposób możesz zbudować prosty blockchain kryptowaluty przy użyciu Node.js.
Oczywiście kryptowaluta smashingCoin
jest daleka od ukończenia. W rzeczywistości, jeśli wydasz ją bez wprowadzania dalszych ulepszeń, jest mało prawdopodobne, aby spełniła obecne wymagania rynku dotyczące bezpiecznej, niezawodnej i intuicyjnej waluty cyfrowej — dzięki czemu będziesz jedyną osobą, która z niej korzysta!
Niemniej jednak mam nadzieję, że ten samouczek wyposażył Cię w podstawowe umiejętności, dzięki którym zmoczysz stopy w ekscytującym świecie kryptowalut.
Jeśli masz jakieś uwagi lub pytania, zamieść je poniżej.
Dalsze zasoby
- „Blockchain 101”, CoinDesk
- „Bitcoin: elektroniczny system gotówkowy peer-to-peer”, Satoshi Nakamoto, Bitcoin.org