3
IG

Własny blockchain – implementacja – poradnik

Nazywam się Patryk Szczygło. Jestem blogerem (http://blog.patys.pl) i przygotowałem dla Was wpis o technologii blockchain, kryptowalutach i wytłumaczeniem jak to wszystko działa i dlaczego jest to bezpieczne i nie do złamania.

Każdy chce własny blockchain

Tak jak obiecałem zaczynamy implementację blockchain. Temat prosty nie jest. Jednak zauważyłem, że wystarczy podzielić temat na mniejsze części. Teraz przedstawię same podstawy. Co to blok, transakcja i jak jedno z drugim się łączy.

Transakcja

Chociaż według mnie nie jest to dobra nazwa, to skoro została ogólnie przyjęta to możemy jej tutaj też używać, aby nie robić zamieszania.

Transakcja jest to podstawowa część bloku. To tutaj pojawią się informacje o przeprowadzonych działaniach. Tutaj zostanie wszystko zapisane. Posługując się przykładem kryptowalut, to właśnie w transakcji znajdują się adresy portfeli czy ilość przesłanych środków.

Jednak w transakcji możemy zdefiniować dowolne dane, które chcemy dołączyć do blockchain. Mogą to być informacje o zawartej umowie, crowdfundingu albo o Twoim głosie w ankiecie/wyborach. Możliwości są nieograniczone.

Blok

W skrócie jest to zbiór transakcji.

Pewnie słyszeliście o kopaniu bloków. Ogólnie kopanie składa się z tworzenia bloku z nieprzetworzonych transakcji (czyli takich które nie są jeszcze w jakimś innym bloku), dodaniu transakcji z na przykład nagrodą dla kopiącego i sprawdzeniu poprawności wszystkich transakcji (żeby nikt nie przesłał sobie za dużo pieniędzy) oraz przeliczeniu hashu bloku.

Hash

Bardzo ważny element bloku i transakcji. Jest to losowy ciąg znaków. Jednak jest to zrobione w sposób kryptograficzny. Wszelkie dane z transakcji, czas i hash poprzedniego bloku są brane pod uwagę i z nich jest tworzony nowy, unikalny hash.

Gwarancja niezmienności

Tą gwarancję zapewniają hashe. Każdy blok zawiera dwa hashe: jeden z poprzedniego bloku i jeden wygenerowany na podstawie swoich danych. Czemu to działa? Każdy blok łączy się z poprzednim i zawiera jego hash. Jakakolwiek zmiana w bloku sprawi, że w nowo wygenerowanym bloku hashe nie będą się zgadzać i blok nie zostanie zaakceptowany.

Zaczynamy programować

No to wyjaśniliśmy sobie wszystko, więc przejdźmy do kodu.

Implementacja będzie zawierać wyłącznie najprostszą wersję. Bez kopania, bez transakcji. Będziemy to dodawać później. W kolejnych poradnikach, krok po kroku. Jak to się mówi, nie od razu Rzym zbudowali.

Implementacja bloku

Na początek określmy sobie czym jest blok. W naszym wypadku będzie to miejsce przechowywania dowolnych danych. Będzie posiadało index, hash poprzedniego bloku, aktualny czas oraz własny hash obliczony na podstawie tych wszystkich pól.

1

2

3

4

5

6

7

8

9

10

11

12

13

class Block {

constructor(index, previousHash, timestamp, data) {

this.index = index

this.previousHash = previousHash

this.timestamp = timestamp

this.data = data

this.hash = this.calculateHash()

}

calculateHash() {

return CryptoJS.SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data)).toString()

}

}

W konstruktorze podajemy index, czyli numer naszego bloku, hash poprzedniego aby zapewnić spójność i gwarancję poprawności danych, obecny czas oraz dane, które chcemy zapisać do bloku.
Dodatkowo określiłem funkcję calculateHash, która ma za zadanie przy użyciu biblioteki CryptoJS obliczyć hash tego wszystkiego.

Implementacja blockchain

Skoro mamy już nasz blok, możemy zacząć tworzyć z tego łańcuch z naszymi danymi.

1

2

3

4

constructor() {

this.blockchain = []

this.blockchain.push(this.generateGenesisBlock())

}

Blockchain to tablica zawierająca wszystkie wytworzone bloki. Na samym początku musi posiadać tak zwany genesis block. Jest to pierwszy blok, który nie zawiera żadnych istotnych informacji, poza hashem, dzięki któremu kolejny blok może się podłączyć.

1

2

3

generateGenesisBlock() {

return new Block(0, '0', new Date().toISOString(), { info: 'Genesis Block' })

}

Funkcja generateGenesisBlock zwraca po prostu nowy blok z podstawowymi informacjami. Skoro mamy blok, z którego otrzymamy hash, to nic nie stoi już na przeszkodzie dodawać nowe.

1

2

3

4

5

6

7

8

9

10

addBlock(data) {

const previousHash = this.getLatestBlock().hash

const index = this.blockchain.length

const timestamp = new Date().toISOString()

const newBlock = new Block(index, previousHash, timestamp, data)

if (this.isValidBlock(newBlock, this.getLatestBlock())) {

this.blockchain.push(newBlock)

} else console.error('invalid block!')

}

No to zaczynamy dodawać nowy blok. Normalnie w tym momencie następuje kopanie, jednak dla uproszczenia zrobimy to w taki sposób.

Na samym początku potrzebujemy poprzedni hash. Więc wybieramy go z pomocą funkcji getLatestBlok. Zwraca ona ostatni blok.

1

2

3

getLatestBlock() {

return this.blockchain[this.blockchain.length - 1]

}

Następnie bierzemy index. Do tego posłużymy się po prostu długością naszego blockchainu.
Kolejny jest timestamp. Jest to aktualna data. Dla ułatwienia i spójności zapisujemy ją zgodnie ze standardem ISO.
Mając timestamp możemy przejść do stworzenia nowego bloku.

Po stworzeniu bloku, warto sprawdzić czy wszystko się zgadza.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

isValidBlock(newBlock, previousBlock) {

if (newBlock.index !== previousBlock.index + 1) {

console.error('invalid index')

return false

}

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

console.error('current and previous hash dont match')

return false

}

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

console.error('recalculated hash is wrong')

return false

}

return true

}

Sprawdzanie zaczynamy od poprawności indeksu. Bierzemy poprzedni blok i sprawdzamy czy powiększony o 1 indeks jest taki sam.
Dalej sprawdzamy czy previousHash z nowego bloku zgadza się z hasem poprzedniego.
Na koniec przeliczamy ponownie hash, żeby się upewnić czy po drodze nie nastąpiły jakieś zmiany.

Kiedy wszystko jest ok, dodajemy blok do blockchain.

To prawie cała implementacja. Została ostatnia funkcja.

1

2

3

4

5

6

isChainValid() {

for (var i = 1; i < this.blockchain.length; i++) {

if (!this.isValidBlock(this.blockchain[i], this.blockchain[i - 1])) return false

}

return true

}

Odpowiada ona za sprawdzenie wszystkich bloków po kolei i ich zgodności.
Przeprowadźmy małe testy, czy blockchain jest poprawnie zrobiony.

Test

Zrobimy sobie prostą symulację. Mamy zbiór w blockchain i powiedzmy, że chcemy oszukać. Chcemy zmienić jeden z bloków, tak aby przesyłał inną ilość patyscoin do innego użytkownika.

1

2

3

4

5

6

7

8

9

10

11

const patyscoin = new Blockchain

patyscoin.addBlock({ ownerID: 1, amount: 100 })

patyscoin.addBlock({ ownerID: 2, amount: 132 })

patyscoin.addBlock({ ownerID: 1, amount: -5 })

console.log(patyscoin.isChainValid())

patyscoin.blockchain[1].data = { ownerID: 666, amount: 999999 }

console.log(patyscoin.isChainValid())

Po uruchomieniu otrzymamy następujące wartości w konsoli:

1

2

true

false

Analizując po kolei. Na początku tworzymy blockchain i dodajemy do niego trzy bloki. Sprawdzamy czy nasz blockchain jest poprawny i otrzymujemy ‘true’, czyli wszystko jest ok. Jednak decydujemy, że zmienimy dane jednego z bloków. Po zmianie sprawdzamy, czy blockchain jest poprawny i wychodzi ‘false’. Nasz blockchain jest uszkodzony.

Na tym polega idea blockchain. Raz wrzuconych danych nie da się zmienić. Kiedy blockchain zostaje naruszony, zostaje przywrócona lub pobrana ostatnia poprawna wersja.

Podsumowanie

Tak wygląda implementacja blockchain. Jest najprościej napisana jak tylko się dało. Dalej postaramy się dodać obsługę sieci, żeby można było korzystać z serwerów. Nie nada się do publicznej chmury ze względu na brak różnych zabezpieczeń, ale na prywatny blockchain jest wystarczająca.

Tutaj macie cały kod: https://github.com/Patys/blockchain-basic

Mam nadzieję, że podobało Wam się. Zapraszam do śledzenia kolejnych postów. Wszystkie informacje o nowych postach dostaniecie tutaj:

http://blog.patys.pl
Facebook – Patys Blog
RSS feed – Patys Blog

Zapraszam do subskrypcji email po najnowsze i ekskluzywne materiały:

http://blog.patys.pl/subskrybuj/



Serwis FxParkiet.pl stanowi platformę umożliwiającą Użytkownikom wymianę informacji na temat Forex, szeroko rozumianego rynku finansowego oraz korzystanie z narzędzi analitycznych pozwalających  na lepsze zobrazowanie zasad funkcjonowania gospodarki. Każdy podmiot, a tym samym Użytkownik Serwisu FxParkiet.pl, który korzysta z jego treści zobowiązany jest do zastosowania się do jego Regulaminu. Właściciel Serwisu FxParkiet.pl – FK Capital Sp. z o.o. z siedzibą w Częstochowie (KRS: 0000542919, NIP: 949-220-00-04, REGON: 360779160) nie ponosi żadnej odpowiedzialności za szkody i konsekwencje powstałe w skutek niezastosowania się do Regulaminu Serwisu FxParkiet.pl. przez Użytkownika. Treść Serwisu FxParkiet.pl ma charakter wyłącznie informacyjny i nie stanowi rekomendacji ani porady inwestycyjnej w rozumieniu Rozporządzenia Ministra Finansów z dnia 19 października 2005 r. (Dz. U. z 2005 r. Nr 206, poz. 1715) w sprawie informacji stanowiących rekomendacje dotyczące instrumentów finansowych, ich emitentów lub wystawców. Informacje uzyskane z Serwisu FxParkiet.pl nie mogą być bezpośrednią i samoistną podstawą działań inwestycyjnych Użytkownika. Każda decyzja inwestycyjna użytkownika powinna być starannie przemyślana, a działanie oparte na zweryfikowanych informacjach. Właściciel Serwisu FK Capital Sp. z o.o. i Serwis FxParkiet.pl nie ponosi żadnej odpowiedzialności za decyzje inwestycyjne podjęte na podstawie wyżej wymienionych treści, a w szczególności za straty z nich wynikłe. Niezastosowanie się do postanowień Regulaminu Serwisu FxParkiet.pl będzie skutkowało konsekwencjami wskazanymi w niniejszym regulaminie. Każdy podmiot przed rozpoczęciem korzystania z Serwisu FxParkiet.pl zobowiązany jest do dokładnego i rzetelnego zapoznania się z niniejszym Regulaminem.
Live

int(0)