{"id":37868,"date":"2019-10-31T22:20:16","date_gmt":"2019-10-31T19:20:16","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blokchejn-chto-nam-stoit-poc-postroit\/"},"modified":"2019-10-31T22:20:16","modified_gmt":"2019-10-31T19:20:16","slug":"blokchejn-chto-nam-stoit-poc-postroit","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","title":{"rendered":"Blockchain: co nam kosztuje zbudowanie PoC?","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><i>Oczy si\u0119 boj\u0105, a r\u0119ce si\u0119 drapi\u0105!<\/i><\/p>\n<p>W poprzednich artyku\u0142ach om\u00f3wili\u015bmy technologie, na kt\u00f3rych opieraj\u0105 si\u0119 blockchainy (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/443282\/\">Co nam przeszkadza w budowie blockchaina?<\/a><\/noindex>) oraz przypadki u\u017cycia, kt\u00f3re mo\u017cna z ich pomoc\u0105 zrealizowa\u0107 (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/449986\/\">Co nam przeszkadza w budowaniu przypadku u\u017cycia?<\/a><\/noindex>). Nadszed\u0142 czas, aby zabra\u0107 si\u0119 do pracy! Do realizacji pilot\u00f3w i PoC (Proof of Concept) preferuj\u0119 u\u017cywa\u0107 chmur, poniewa\u017c s\u0105 dost\u0119pne z dowolnego miejsca na \u015bwiecie i cz\u0119sto nie trzeba traci\u0107 czasu na nudn\u0105 instalacj\u0119 \u015brodowiska, poniewa\u017c s\u0105 dost\u0119pne prekonfigurowane ustawienia. Zr\u00f3bmy co\u015b prostego, na przyk\u0142ad sie\u0107 do transferu monet pomi\u0119dzy uczestnikami i nazwijmy j\u0105 skromnie Citcoin. W tym celu u\u017cyjemy chmury IBM oraz uniwersalnego blockchaina Hyperledger Fabric. Najpierw przyjrzyjmy si\u0119, dlaczego Hyperledger Fabric nazywa si\u0119 uniwersalnym blockchainem?<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/c19278d99d5b7edb9f50ea6306c2fd46.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Hyperledger Fabric \u2014 uniwersalny blockchain<\/h2>\n<p>\nM\u00f3wi\u0105c og\u00f3lnie, uniwersalny system informacyjny to:<\/p>\n<ul>\n<li>Zestaw serwer\u00f3w i rdze\u0144 oprogramowania realizuj\u0105cy logik\u0119 biznesow\u0105;<\/li>\n<li>Interfejsy do interakcji z systemem;<\/li>\n<li>\u015arodki do rejestracji, uwierzytelniania i autoryzacji urz\u0105dze\u0144 \/ ludzi;<\/li>\n<li>Baza danych, przechowuj\u0105ca dane operacyjne i archiwalne:<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/f11fe73de54b0573d44fae903d367df9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOficjaln\u0105 wersj\u0119, czym jest Hyperledger Fabric, mo\u017cna przeczyta\u0107 na <noindex><a rel=\"nofollow\" href=\"https:\/\/www.hyperledger.org\">stronie<\/a><\/noindex>, a je\u015bli kr\u00f3tko, to Hyperledger Fabric to platforma open source, kt\u00f3ra umo\u017cliwia budow\u0119 zamkni\u0119tych blockchain\u00f3w i realizacj\u0119 dowolnych inteligentnych kontrakt\u00f3w napisanych w j\u0119zykach programowania JS i Go. Przyjrzyjmy si\u0119 szczeg\u00f3\u0142owo architekturze Hyperledger Fabric i upewnijmy si\u0119, \u017ce jest to uniwersalny system, w kt\u00f3rym istnieje jedynie specyfika przechowywania i zapisu danych. Specyfika polega na tym, \u017ce dane, jak we wszystkich blockchainach, s\u0105 przechowywane w blokach, kt\u00f3re s\u0105 umieszczane w blockchainie tylko wtedy, gdy uczestnicy osi\u0105gn\u0119li konsensus, a po zapisaniu danych nie mo\u017cna ich niezauwa\u017calnie poprawi\u0107 ani usun\u0105\u0107.<\/p>\n<h2>Architektura Hyperledger Fabric<\/h2>\n<p>\nNa schemacie przedstawiona jest architektura Hyperledger Fabric:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/7488d70b330af2bbae1db67005f22a3e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Organizations <\/b> \u2014 organizacje zawieraj\u0105 peer-y, przez co blockchain istnieje dzi\u0119ki wsparciu organizacji. R\u00f3\u017cne organizacje mog\u0105 wchodzi\u0107 w jeden channel.<\/p>\n<p><b>Channel <\/b> \u2014 struktura logiczna, \u0142\u0105cz\u0105ca peer-y w grupy, przez co definiowany jest blockchain. Hyperledger Fabric mo\u017ce jednocze\u015bnie obs\u0142ugiwa\u0107 wiele blockchain\u00f3w z r\u00f3\u017cn\u0105 logik\u0105 biznesow\u0105.<\/p>\n<p><b>Membership Services Provider (MSP)<\/b> \u2014 to CA (Certificate Authority) do wydawania to\u017csamo\u015bci i przydzielania r\u00f3l. Aby utworzy\u0107 w\u0119ze\u0142, nale\u017cy wsp\u00f3\u0142dzia\u0142a\u0107 z MSP.<\/p>\n<p><b>W\u0119z\u0142y peer<\/b> \u2014 sprawdzaj\u0105 transakcje, przechowuj\u0105 blockchain, wykonuj\u0105 inteligentne kontrakty i wsp\u00f3\u0142dzia\u0142aj\u0105 z aplikacjami. W\u0119z\u0142y peer maj\u0105 to\u017csamo\u015b\u0107 (certyfikat cyfrowy), kt\u00f3ry wydaje MSP. W przeciwie\u0144stwie do sieci Bitcoin lub Ethereum, gdzie wszystkie w\u0119z\u0142y s\u0105 r\u00f3wne, w Hyperledger Fabric w\u0119z\u0142y pe\u0142ni\u0105 r\u00f3\u017cne role:<\/p>\n<ul>\n<li>Peer mo\u017ce by\u0107 <b>w\u0119z\u0142em zatwierdzaj\u0105cym<\/b> (EP) i wykonywa\u0107 inteligentne kontrakty.<\/li>\n<li><b>W\u0119ze\u0142 zatwierdzaj\u0105cy<\/b> (CP) \u2014 tylko przechowuj\u0105 dane w blockchainie i aktualizuj\u0105 \u201eStan \u015bwiata\u201d.<\/li>\n<li><b>W\u0119ze\u0142 ankruj\u0105cy<\/b> (AP) \u2014 je\u015bli w blockchainie uczestniczy wiele organizacji, w\u0119z\u0142y ankruj\u0105ce s\u0105 u\u017cywane do \u0142\u0105czenia ich. Ka\u017cda organizacja powinna mie\u0107 jeden lub wi\u0119cej w\u0119z\u0142\u00f3w ankruj\u0105cych. Dzi\u0119ki AP ka\u017cdy w\u0119ze\u0142 w organizacji mo\u017ce uzyska\u0107 informacje o wszystkich w\u0119z\u0142ach w innych organizacjach. Do synchronizacji informacji mi\u0119dzy AP u\u017cywany jest <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Gossip_protocol\">protok\u00f3\u0142 gossip<\/a><\/noindex>.<\/li>\n<li><b>W\u0119ze\u0142 lidera<\/b> \u2014 je\u015bli organizacja ma kilka w\u0119z\u0142\u00f3w, to tylko w\u0119ze\u0142 lidera b\u0119dzie odbiera\u0107 bloki z us\u0142ugi zamawiania i przekazywa\u0107 je innym w\u0119z\u0142om. Lider mo\u017ce by\u0107 ustalony statycznie lub wybierany dynamicznie przez w\u0119z\u0142y w organizacji. Do synchronizacji informacji o liderach r\u00f3wnie\u017c u\u017cywany jest protok\u00f3\u0142 gossip.<\/li>\n<\/ul>\n<p>\n<b>Zasoby <\/b> \u2014 podmioty o warto\u015bci, kt\u00f3re s\u0105 przechowywane w blockchainie. Dok\u0142adniej m\u00f3wi\u0105c \u2014 to dane key-value w formacie JSON. To w\u0142a\u015bnie te dane s\u0105 zapisywane w blockchainie \u201eBlockchain\u201d. Posiadaj\u0105 histori\u0119, kt\u00f3ra jest przechowywana w blockchainie oraz aktualny stan, kt\u00f3ry jest przechowywany w bazie danych \u201eStan \u015bwiata\u201d. Struktury danych s\u0105 wype\u0142niane wed\u0142ug potrzeb w zale\u017cno\u015bci od zada\u0144 biznesowych. Nie ma \u017cadnych obowi\u0105zkowych p\u00f3l, jedynym zaleceniem jest \u2014 zasoby powinny mie\u0107 w\u0142a\u015bciciela i reprezentowa\u0107 warto\u015b\u0107. <\/p>\n<p><b>Ksi\u0119ga <\/b> \u2014 sk\u0142ada si\u0119 z blockchaina \u201eBlockchain\u201d oraz bazy danych \u201eStan \u015bwiata\u201d, w kt\u00f3rej przechowywany jest aktualny stan zasob\u00f3w. Stan \u015bwiata korzysta z LevelDB lub CouchDB.<\/p>\n<p><b>Inteligentny kontrakt<\/b> \u2014 za pomoc\u0105 inteligentnych kontrakt\u00f3w realizowana jest logika biznesowa systemu. W Hyperledger Fabric inteligentne kontrakty nazywane s\u0105 chaincode. Za pomoc\u0105 chaincode definiuje si\u0119 zasoby i transakcje zwi\u0105zane z nimi. M\u00f3wi\u0105c technicznym j\u0119zykiem, inteligentne kontrakty to modu\u0142y programowe realizowane w j\u0119zykach programowania JS lub Go.<\/p>\n<p><b>Polityka zatwierdzania<\/b> \u2014 dla ka\u017cdego chaincode mo\u017cna ustali\u0107 polityki dotycz\u0105ce tego, ile i od kogo nale\u017cy oczekiwa\u0107 potwierdze\u0144 dla transakcji. Je\u015bli polityka nie jest okre\u015blona, domy\u015blnie stosuje si\u0119: \u201etransakcj\u0119 musi zatwierdzi\u0107 ka\u017cdy cz\u0142onek (member) ka\u017cdej organizacji w kanale\u201d. Przyk\u0142ady polityk:<\/p>\n<ul>\n<li>Transakcj\u0119 musi zatwierdzi\u0107 ka\u017cdy administrator organizacji;<\/li>\n<li>Wszyscy cz\u0142onkowie (member) lub klienci organizacji musz\u0105 j\u0105 zatwierdzi\u0107;<\/li>\n<li>Ka\u017cdy peer organizacji musi to zatwierdzi\u0107.<\/li>\n<\/ul>\n<p>\n<b>Us\u0142uga porz\u0105dkowania<\/b> \u2014 pakuje transakcje w bloki i wysy\u0142a do peer\u00f3w w channel. Gwarantuje dostarczenie wiadomo\u015bci do wszystkich peer\u00f3w w sieci. Do przemys\u0142owych system\u00f3w wykorzystywana jest <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Apache_Kafka\">broker wiadomo\u015bci Kafka<\/a><\/noindex>, do rozwoju i testowania <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hyperledger\/fabric\/tree\/master\/orderer\/consensus\/solo\">Solo<\/a><\/noindex>.<\/p>\n<h2>CallFlow<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/9060864bd1002da881d7f17ef8ec0b0c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Aplikacja wsp\u00f3\u0142dzia\u0142a z Hyperledger Fabric, wykorzystuj\u0105c Go, Node.js lub Java SDK;<\/li>\n<li>Klient tworzy transakcj\u0119 tx i wysy\u0142a j\u0105 do endorsuj\u0105cych peer\u00f3w;<\/li>\n<li>Peer sprawdza podpis klienta, wykonuje transakcj\u0119 i wysy\u0142a podpis zatwierdzenia z powrotem do klienta. Chaincode wykonuje si\u0119 tylko na endorsuj\u0105cych peerach, a wynik jego wykonania jest rozsy\u0142any do wszystkich peer\u00f3w. Taki algorytm pracy nazywa si\u0119 \u2014 konsensusem PBFT (Practical Byzantine Fault Tolerant). R\u00f3\u017cni si\u0119 od <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Byzantine_fault\">klasycznego BFT<\/a><\/noindex> tym, \u017ce wiadomo\u015b\u0107 jest rozsy\u0142ana i oczekiwane jest potwierdzenie nie od wszystkich uczestnik\u00f3w, a tylko od okre\u015blonego zestawu;<\/li>\n<li>Po tym, jak klient otrzyma liczb\u0119 odpowiedzi odpowiadaj\u0105c\u0105 polityce zatwierdzenia, wysy\u0142a transakcj\u0119 do us\u0142ugi porz\u0105dkowania;<\/li>\n<li>Us\u0142uga porz\u0105dkowania tworzy blok i wysy\u0142a go do wszystkich peer\u00f3w zatwierdzaj\u0105cych. Us\u0142uga porz\u0105dkowania zapewnia sekwencyjne zapisywanie blok\u00f3w, co wyklucza tak zwany fork ksi\u0119gi g\u0142\u00f3wnej (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/443282\/\">patrz rozdzia\u0142 \u00abForki\u00bb<\/a><\/noindex>);<\/li>\n<li>Peerzy otrzymuj\u0105 blok, ponownie sprawdzaj\u0105 polityk\u0119 zatwierdzenia, zapisuj\u0105 blok w blockchainie i zmieniaj\u0105 stan w bazie danych \u201eWorld state\u201d.<\/li>\n<\/ul>\n<p>\nTo zatem prowadzi do podzia\u0142u r\u00f3l mi\u0119dzy w\u0119z\u0142ami. Zapewnia to skalowalno\u015b\u0107 i bezpiecze\u0144stwo blockchaina:<\/p>\n<ul>\n<li>Smart kontrakty (chaincode) wykonuj\u0105 endorsuj\u0105cy peerzy. Zapewnia to prywatno\u015b\u0107 smart kontrakt\u00f3w, poniewa\u017c s\u0105 one przechowywane nie przez wszystkich uczestnik\u00f3w, a tylko na endorsuj\u0105cych peerach.<\/li>\n<li>Us\u0142uga porz\u0105dkowania musi dzia\u0142a\u0107 szybko. Zapewnia to fakt, \u017ce Us\u0142uga porz\u0105dkowania tylko tworzy blok i wysy\u0142a go do ustalonego zestawu peer\u00f3w lider\u00f3w.<\/li>\n<li>Zatwierdzaj\u0105cy peerzy tylko przechowuj\u0105 blockchain \u2014 mo\u017ce ich by\u0107 wielu i nie wymagaj\u0105 du\u017cej mocy obliczeniowej ani natychmiastowej pracy. <\/li>\n<\/ul>\n<p>\nSzczeg\u00f3\u0142y dotycz\u0105ce architektonicznych rozwi\u0105za\u0144 Hyperledger Fabric oraz dlaczego dzia\u0142a tak, a nie inaczej, mo\u017cna zobaczy\u0107 tutaj: <noindex><a rel=\"nofollow\" href=\"https:\/\/hyperledger-fabric.readthedocs.io\/en\/latest\/arch-deep-dive.html\">Pochodzenie architektury<\/a><\/noindex> lub tutaj: <noindex><a rel=\"nofollow\" href=\"https:\/\/arxiv.org\/abs\/1801.10228v2\">Hyperledger Fabric: Rozproszony system operacyjny dla autoryzowanych blockchain\u00f3w<\/a><\/noindex>.<\/p>\n<p>Tak wi\u0119c, Hyperledger Fabric to rzeczywi\u015bcie uniwersalny system, za pomoc\u0105 kt\u00f3rego mo\u017cna:<\/p>\n<ul>\n<li>Realizowa\u0107 dowoln\u0105 logik\u0119 biznesow\u0105, u\u017cywaj\u0105c mechanizmu smart kontrakt\u00f3w;<\/li>\n<li>Zapisuj i odbieraj dane z bazy danych blockchain w formacie JSON;<\/li>\n<li>Zapewnij i zweryfikuj dost\u0119p do API, korzystaj\u0105c z Certyfikatu Autoryzacji. <\/li>\n<\/ul>\n<p>\nTeraz, gdy nieco zrozumieli\u015bmy specyfik\u0119 Hyperledger Fabric, w ko\u0144cu zr\u00f3bmy co\u015b u\u017cytecznego!<\/p>\n<h2>Rozwijamy blockchain<\/h2>\n<p><\/p>\n<h3>Sformu\u0142owanie zadania<\/h3>\n<p>\nZadanie \u2014 zaimplementowa\u0107 sie\u0107 Citcoin z nast\u0119puj\u0105cymi funkcjami: utworzy\u0107 konto, uzyska\u0107 saldo, do\u0142adowa\u0107 konto, przela\u0107 monety z jednego konta na drugie. Stw\u00f3rzmy model obiektowy, kt\u00f3ry nast\u0119pnie zaimplementujemy w smart kontrakcie. Tak wi\u0119c, b\u0119dziemy mieli konta, kt\u00f3re b\u0119d\u0105 identyfikowane nazwami (name) i b\u0119d\u0105 mia\u0142y saldo (balance), a tak\u017ce list\u0119 kont. Konta i lista kont b\u0119d\u0105 w terminologii Hyperledger Fabric aktywami. Odpowiednio, maj\u0105 histori\u0119 i bie\u017c\u0105cy stan. Postaram si\u0119 to wizualnie nakre\u015bli\u0107:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/a4f111da59bc7982b51d583857db6d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nG\u00f3rne figury to bie\u017c\u0105cy stan, kt\u00f3ry jest przechowywany w bazie \u201eWorld state\u201d. Poni\u017cej figury pokazuj\u0105ce histori\u0119, kt\u00f3ra jest przechowywana w blockchainie. Bie\u017c\u0105cy stan aktyw\u00f3w zmienia si\u0119 w wyniku transakcji. Aktywa zmieniaj\u0105 si\u0119 tylko w ca\u0142o\u015bci, dlatego w wyniku wykonania transakcji powstaje nowy obiekt, a bie\u017c\u0105ca warto\u015b\u0107 aktywa przechodzi do historii. <\/p>\n<h3>Chmura IBM <\/h3>\n<p>\nTworzymy konto w <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.ibm.com\">chmurze IBM<\/a><\/noindex>. Aby skorzysta\u0107 z platformy blockchain, nale\u017cy j\u0105 zaktualizowa\u0107 do op\u0142aty zgodnie z u\u017cytkowaniem. Proces ten mo\u017ce nie by\u0107 szybki, poniewa\u017c IBM prosi o dodatkowe informacje i sprawdza je r\u0119cznie. Z pozytywnych rzeczy mog\u0119 powiedzie\u0107, \u017ce IBM ma dobre materia\u0142y szkoleniowe, kt\u00f3re pozwalaj\u0105 na uruchomienie Hyperledger Fabric w ich chmurze. Podoba\u0142 mi si\u0119 nast\u0119puj\u0105cy cykl artyku\u0142\u00f3w i przyk\u0142ad\u00f3w:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/Create-BlockchainNetwork-IBPV20\/blob\/master\/README.md\">Utw\u00f3rz podstawow\u0105 sie\u0107 blockchain przy u\u017cyciu platformy Blockchain<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/SmartContractTrading-wFabric1-4-VSCodeExt\/blob\/master\/README.md\">Utw\u00f3rz i uruchom smart kontrakt blockchain<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/auction-events\/blob\/master\/README.md\">Emituj zdarzenia z platformy Blockchain<\/a><\/noindex><\/li>\n<\/ul>\n<p>\nPoni\u017cej znajduj\u0105 si\u0119 zrzuty ekranu z platformy Blockchain IBM. To nie jest instrukcja tworzenia blockchaina, tylko demonstracja zakresu zadania. Tak wi\u0119c, dla naszych cel\u00f3w tworzymy jedn\u0105 organizacj\u0119:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/7cb30cade6315abc69f4322a2dbcd094.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW niej tworzymy w\u0119z\u0142y: Orderer CA, Org1 CA, Orderer Peer:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/4a2239a9b7ded8ba5a11ffad86a35094.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTworzymy u\u017cytkownik\u00f3w:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/6792b12c9316f47b0cdfaf771dacc782.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTworzymy Channel i nazywamy go citcoin:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/ea3983f209326713dcd25762c348ac96.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW istocie Channel to blockchain, dlatego zaczyna si\u0119 od bloku zerowego (Genesis block):<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/416df6b6ef832c6550a2642592e57250.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Pisz\u0119 Smart Contract<\/h3>\n<p><\/p>\n<pre><code class=\"javascript\">\/*\n * Citcoin smart-contract v1.5 for Hyperledger Fabric\n * (c) Alexey Sushkov, 2019\n *\/\n \n'use strict';\n \nconst { Contract } = require('fabric-contract-api');\nconst maxAccounts = 5;\n \nclass CitcoinEvents extends Contract {\n \n    async instantiate(ctx) {\n        console.info('instantiate');\n        let emptyList = [];\n        await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList)));\n    }\n    \/\/ Get all accounts\n    async GetAccounts(ctx) {\n        \/\/ Get account list:\n        let accounts = '{}'\n        let accountsData = await ctx.stub.getState('accounts');\n        if (accountsData) {\n            accounts = JSON.parse(accountsData.toString());\n        } else {\n            throw new Error('accounts not found');\n        }\n        return accountsData.toString()\n    }\n     \/\/ add a account object to the blockchain state identifited by their name\n    async AddAccount(ctx, name, balance) {\n        \/\/ this is account data:\n        let account = {\n            name: name,\n            balance: Number(balance),       \n            type: 'account',\n        };\n        \/\/ create account:\n        await ctx.stub.putState(name, Buffer.from(JSON.stringify(account)));\n \n        \/\/ Add account to list:\n        let accountsData = await ctx.stub.getState('accounts');\n        if (accountsData) {\n            let accounts = JSON.parse(accountsData.toString());\n            if (accounts.length &lt; maxAccounts)\n            {\n                accounts.push(name);\n                await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts)));\n            } else {\n                throw new Error('Max accounts number reached');\n            }\n        } else {\n            throw new Error('accounts not found');\n        }\n        \/\/ return  object\n        return JSON.stringify(account);\n    }\n    \/\/ Sends money from Account to Account\n    async SendFrom(ctx, fromAccount, toAccount, value) {\n        \/\/ get Account from\n        let fromData = await ctx.stub.getState(fromAccount);\n        let from;\n        if (fromData) {\n            from = JSON.parse(fromData.toString());\n            if (from.type !== 'account') {\n                throw new Error('wrong from type');\n            }   \n        } else {\n            throw new Error('Accout from not found');\n        }\n        \/\/ get Account to\n        let toData = await ctx.stub.getState(toAccount);\n        let to;\n        if (toData) {\n            to = JSON.parse(toData.toString());\n            if (to.type !== 'account') {\n                throw new Error('wrong to type');\n            }  \n        } else {\n            throw new Error('Accout to not found');\n        }\n \n        \/\/ update the balances\n        if ((from.balance - Number(value)) &gt;= 0 ) {\n            from.balance -= Number(value);\n            to.balance += Number(value);\n        } else {\n            throw new Error('From Account: not enought balance');          \n        }\n \n        await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from)));\n        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));\n                 \n        \/\/ define and set Event\n        let Event = {\n            type: \"SendFrom\",\n            from: from.name,\n            to: to.name,\n            balanceFrom: from.balance,\n            balanceTo: to.balance,\n            value: value\n        };\n        await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event)));\n \n        \/\/ return to object\n        return JSON.stringify(from);\n    }\n \n    \/\/ get the state from key\n    async GetState(ctx, key) {\n        let data = await ctx.stub.getState(key);\n        let jsonData = JSON.parse(data.toString());\n        return JSON.stringify(jsonData);\n    }\n    \/\/ GetBalance   \n    async GetBalance(ctx, accountName) {\n        let data = await ctx.stub.getState(accountName);\n        let jsonData = JSON.parse(data.toString());\n        return JSON.stringify(jsonData);\n    }\n     \n    \/\/ Refill own balance\n    async RefillBalance(ctx, toAccount, value) {\n        \/\/ get Account to\n        let toData = await ctx.stub.getState(toAccount);\n        let to;\n        if (toData) {\n            to = JSON.parse(toData.toString());\n            if (to.type !== 'account') {\n                throw new Error('wrong to type');\n            }  \n        } else {\n            throw new Error('Accout to not found');\n        }\n \n        \/\/ update the balance\n        to.balance += Number(value);\n        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));\n                 \n        \/\/ define and set Event\n        let Event = {\n            type: \"RefillBalance\",\n            to: to.name,\n            balanceTo: to.balance,\n            value: value\n        };\n        await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event)));\n \n        \/\/ return to object\n        return JSON.stringify(from);\n    }\n}\nmodule.exports = CitcoinEvents;\n<\/code><\/pre>\n<p>\nIntuicyjnie powinno to by\u0107 wszystko zrozumia\u0142e:<\/p>\n<ul>\n<li>Istnieje kilka funkcji (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance), kt\u00f3re b\u0119d\u0105 wywo\u0142ywane przez program demo za pomoc\u0105 API Hyperledger Fabric.<\/li>\n<li>Funkcje SendFrom i RefillBalance generuj\u0105 zdarzenia (Event), kt\u00f3re b\u0119dzie otrzymywa\u0142 program demo.<\/li>\n<li>Funkcja instantiate jest wywo\u0142ywana raz podczas instancjonowania smart kontraktu. W rzeczywisto\u015bci jest wywo\u0142ywana nie raz, a za ka\u017cdym razem, gdy zmienia si\u0119 wersja smart kontraktu. Dlatego inicjalizacja listy pust\u0105 tablic\u0105 to z\u0142a idea, poniewa\u017c teraz przy zmianie wersji smart kontraktu utracimy bie\u017c\u0105c\u0105 list\u0119. Ale nic, dopiero si\u0119 ucz\u0119).<\/li>\n<li>Konta i lista kont (accounts) to struktury danych w formacie JSON. Do manipulacji danymi u\u017cywany jest JS.<\/li>\n<li>Bie\u017c\u0105c\u0105 warto\u015b\u0107 aktyw\u00f3w asset mo\u017cna uzyska\u0107 za pomoc\u0105 wywo\u0142ania funkcji getState, a zaktualizowa\u0107 za pomoc\u0105 putState.<\/li>\n<li>Podczas tworzenia konta wywo\u0142ywana jest funkcja AddAccount, w kt\u00f3rej nast\u0119puje por\u00f3wnanie maksymalnej liczby kont w blockchainie (maxAccounts = 5). I tu jest b\u0142\u0105d (zauwa\u017cyli\u015bcie?), kt\u00f3ry prowadzi do niesko\u0144czonego wzrostu liczby kont. Nale\u017cy unika\u0107 takich b\u0142\u0119d\u00f3w).<\/li>\n<\/ul>\n<p>\nNast\u0119pnie \u0142adujemy smart kontrakt do Channel i instancjonujemy go:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/45ad234efc9838b711f96642988f073e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSprawdzamy transakcj\u0119 instalacji Smart Contract:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/39605b9d09468fd0c5f0557ed8b692a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSprawdzamy szczeg\u00f3\u0142y naszego Channel:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/ccaf803cf34e52f77dac448f9c83e672.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW rezultacie otrzymujemy nast\u0119puj\u0105c\u0105 schem\u0119 sieci blockchain w chmurze IBM. Na schemacie znajduje si\u0119 r\u00f3wnie\u017c program demo, uruchomiony w chmurze Amazon na wirtualnym serwerze (szczeg\u00f3\u0142owo b\u0119dzie o nim w nast\u0119pnym rozdziale):<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/64e5c0f27d351ee3b60d2ea471a7f58c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Tworzenie GUI do wywo\u0142ywania Hyperledger Fabric API<\/h2>\n<p>\nHyperledger Fabric ma API, kt\u00f3re mo\u017ce by\u0107 u\u017cywane do:<\/p>\n<ul>\n<li>Tworzenia channel;<\/li>\n<li>Pod\u0142\u0105czenia peera do channel;<\/li>\n<li>Instalacji i instancjonowania smart kontrakt\u00f3w w channel;<\/li>\n<li>Wywo\u0142ywania transakcji;<\/li>\n<li>\u017b\u0105dania informacji w blockchainie.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Rozw\u00f3j aplikacji<\/h3>\n<p>\nW naszym programie demo u\u017cyjemy API tylko do wywo\u0142ywania transakcji i \u017c\u0105dania informacji, poniewa\u017c pozosta\u0142e kroki ju\u017c wykonali\u015bmy, korzystaj\u0105c z platformy blockchain IBM. Tworzymy GUI, u\u017cywaj\u0105c standardowego stosu technologii: Express.js + Vue.js + Node.js. O tym, jak rozpocz\u0105\u0107 tworzenie nowoczesnych aplikacji internetowych, mo\u017cna napisa\u0107 osobny artyku\u0142. Tutaj zostawi\u0119 link do serii wyk\u0142ad\u00f3w, kt\u00f3re najbardziej mi si\u0119 podoba\u0142y: <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/Fa4cRMaTDUI\">Full Stack Web App using Vue.js &amp; Express.js<\/a><\/noindex>. W rezultacie powsta\u0142a aplikacja kliencka z znanym interfejsem graficznym w stylu Material Design od Google. REST API mi\u0119dzy klientem a serwerem sk\u0142ada si\u0119 z kilku wywo\u0142a\u0144:<\/p>\n<ul>\n<li>HyperledgerDemo\/v1\/init \u2014 zainicjowa\u0107 blockchain;<\/li>\n<li>HyperledgerDemo\/v1\/accounts\/list \u2014 uzyska\u0107 list\u0119 wszystkich kont;<\/li>\n<li>HyperledgerDemo\/v1\/account?name=Bob&amp;balance=100 \u2014 utworzy\u0107 konto Boba;<\/li>\n<li>HyperledgerDemo\/v1\/info?account=Bob \u2014 uzyska\u0107 informacje o koncie Boba;<\/li>\n<li>HyperledgerDemo\/v1\/transaction?from=Bob&amp;to=Alice&amp;volume=2 \u2014 przela\u0107 dwie monety od Boba do Alice;<\/li>\n<li>HyperledgerDemo\/v1\/disconnect \u2014 zamkn\u0105\u0107 po\u0142\u0105czenie z blockchainem.<\/li>\n<\/ul>\n<p>\nOpis API z przyk\u0142adami umie\u015bci\u0142em na<noindex><a rel=\"nofollow\" href=\"https:\/\/documenter.getpostman.com\/view\/7152141\/SVfTNSeb\"> stronie \u201ePostman\u201d<\/a><\/noindex> \u2014 powszechnie znanym programie do testowania API HTTP.<\/p>\n<h3>Aplikacja demo w chmurze Amazon<\/h3>\n<p>\nAplikacj\u0119 umie\u015bci\u0142em na Amazonie, poniewa\u017c IBM wci\u0105\u017c nie zdo\u0142a\u0142 zaktualizowa\u0107 mojego konta i zezwoli\u0107 na tworzenie wirtualnych serwer\u00f3w. Jako wisienk\u0119 na torcie doda\u0142em domen\u0119: <noindex><a rel=\"nofollow\" href=\"http:\/\/www.citcoin.info\">www.citcoin.info<\/a><\/noindex>. Utrzymam serwer w\u0142\u0105czony przez chwil\u0119, potem go wy\u0142\u0105cz\u0119, bo op\u0142aty za wynajem naliczaj\u0105 si\u0119, a monety citcoin na gie\u0142dzie jeszcze nie s\u0105 notowane) W artykule umieszczam zrzuty ekranu z demo, aby pokaza\u0107 logik\u0119 dzia\u0142ania. Aplikacja demo mo\u017ce:<\/p>\n<ul>\n<li>Inicjowa\u0107 blockchain;<\/li>\n<li>Tworzy\u0107 Konto (ale teraz nie mo\u017cna utworzy\u0107 nowego Konta, poniewa\u017c w blockchainie osi\u0105gni\u0119to maksymaln\u0105 liczb\u0119 kont okre\u015blon\u0105 w smart kontrakcie);<\/li>\n<li>Pobiera\u0107 list\u0119 Kont;<\/li>\n<li>Przela\u0107 monety citcoin mi\u0119dzy Alice, Bobem i Alexem;<\/li>\n<li>Pobiera\u0107 zdarzenia (ale teraz zdarzenia nie mog\u0105 by\u0107 pokazywane, dlatego w interfejsie dla uproszczenia napisano, \u017ce zdarzenia nie s\u0105 obs\u0142ugiwane);<\/li>\n<li>Logowa\u0107 dzia\u0142ania.<\/li>\n<\/ul>\n<p>\nNajpierw inicjujemy blockchain:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/773ce08270f1b22e64a79fce267bb25f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNast\u0119pnie zak\u0142adamy swoje konto, nie oszcz\u0119dzaj\u0105c na saldzie:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/f1cd24aedd5e9618046c5e1ab49ceede.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPobieramy list\u0119 wszystkich dost\u0119pnych kont:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/796f897ca1345430f755055372d03421.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWybieramy nadawc\u0119 i odbiorc\u0119, sprawdzamy ich salda. Je\u015bli nadawca i odbiorca s\u0105 tacy sami, saldo zostanie do\u0142adowane:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/58eb2ed4a4bac51e0dca1b0331d7910a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW logu \u015bledzimy realizacj\u0119 transakcji:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/528760998e8dc27a73c4409f55b22087.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTo wszystko w kontek\u015bcie programu demo. Nast\u0119pnie mo\u017cna zobaczy\u0107 nasz\u0105 transakcj\u0119 w blockchainie:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/1d6bc12f3609b118472afec31b089f09.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nI og\u00f3ln\u0105 list\u0119 transakcji:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: co nam kosztuje zbudowanie PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/96675fcda8088307326dadf7852e6ce7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW ten spos\u00f3b pomy\u015blnie zako\u0144czyli\u015bmy realizacj\u0119 PoC tworzenia sieci Citcoin. Co jeszcze nale\u017cy zrobi\u0107, aby Citcoin sta\u0142 si\u0119 pe\u0142noprawn\u0105 sieci\u0105 do transferu monet? Zaledwie kilka rzeczy:<\/p>\n<ul>\n<li>Na etapie tworzenia konta zrealizowa\u0107 generacj\u0119 klucza prywatnego \/ publicznego. Klucz prywatny powinien by\u0107 przechowywany przez u\u017cytkownika konta, publiczny w blockchainie.<\/li>\n<li>Zrealizowa\u0107 transfer monet, w kt\u00f3rym do identyfikacji u\u017cytkownika wykorzystywany jest nie jego imi\u0119, ale klucz publiczny.<\/li>\n<li>Szyfrowa\u0107 transakcje wychodz\u0105ce od u\u017cytkownika do serwera jego kluczem prywatnym.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Podsumowanie <\/h2>\n<p>\nZrealizowali\u015bmy sie\u0107 Citcoin z funkcjami: dodanie konta, uzyskanie salda, do\u0142adowanie swojego konta, przelanie monet z jednego konta na drugie. Wi\u0119c co nas kosztowa\u0142o zbudowanie PoC?<\/p>\n<ul>\n<li>Trzeba pozna\u0107 blockchain w og\u00f3le i Hyperledger Fabric w szczeg\u00f3lno\u015bci;<\/li>\n<li>Nauczy\u0107 si\u0119 korzysta\u0107 z chmur IBM lub Amazon;<\/li>\n<li>Nauka j\u0119zyka programowania JS i dowolnego frameworka webowego;<\/li>\n<li>Je\u015bli jakie\u015b dane musz\u0105 by\u0107 przechowywane nie w blockchainie, a w oddzielnej bazie, naucz si\u0119 integrowa\u0107, na przyk\u0142ad, z PostgreSQL;<\/li>\n<li>I ostatnia rzecz na li\u015bcie, ale nie mniej wa\u017cna - bez znajomo\u015bci Linuxa w nowoczesnym \u015bwiecie ani rusz!)<\/li>\n<\/ul>\n<p>\nOczywi\u015bcie, to nie jest rocket science, ale musisz si\u0119 troch\u0119 napracowa\u0107!<\/p>\n<h3>Kody \u017ar\u00f3d\u0142owe na GitHubie<\/h3>\n<p>\nKody \u017ar\u00f3d\u0142owe wrzuci\u0142em na <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/AlexeySushkov\/Citcoin-blockchain\">GitHub<\/a><\/noindex>. Kr\u00f3tkie opisanie repozytorium:<br \/>\nKatalog &#171;<b>server<\/b>&#187; - serwer Node.js<br \/>\nKatalog &#171;<b>client<\/b>&#187; - klient Node.js<br \/>\nKatalog &#171;<b>blockchain<\/b>&#187; (warto\u015bci parametr\u00f3w i klucze, oczywi\u015bcie, nie s\u0105 funkcjonalne i podane tylko jako przyk\u0142ad):<\/p>\n<ul>\n<li>contract - kod \u017ar\u00f3d\u0142owy smart kontraktu<\/li>\n<li>wallet - klucze u\u017cytkownika do korzystania z Hyperledger Fabric API. <\/li>\n<li>*.cds - skompilowane wersje smart kontrakt\u00f3w<\/li>\n<li>*.json pliki - przyk\u0142ady plik\u00f3w konfiguracyjnych do u\u017cycia Hyperledger Fabric API<\/li>\n<\/ul>\n<p>\n<b>To dopiero pocz\u0105tek!<\/b><br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466157\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0413\u043b\u0430\u0437\u0430 \u0431\u043e\u044f\u0442\u0441\u044f, \u0430 \u0440\u0443\u043a\u0438 \u0447\u0435\u0448\u0443\u0442\u0441\u044f! \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u044b (\u0427\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c?) \u0438 \u043a\u0435\u0439\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0441 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c (\u0427\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u043a\u0435\u0439\u0441 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c?). \u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0443\u043a\u0430\u043c\u0438! \u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0438\u043b\u043e\u0442\u043e\u0432 \u0438 PoC (Proof of Concept) \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u043a\u0430, \u0442.\u043a. \u043a \u043d\u0438\u043c \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28421,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-37868","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0413\u043b\u0430\u0437\u0430 \u0431\u043e\u044f\u0442\u0441\u044f, \u0430 \u0440\u0443\u043a\u0438 \u0447\u0435\u0448\u0443\u0442\u0441\u044f! \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u044b (\u0427\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u043b\u043e\u043a\u0447\u0435\u0439\u043d: \u0447\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 PoC \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c? | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0413\u043b\u0430\u0437\u0430 \u0431\u043e\u044f\u0442\u0441\u044f, \u0430 \u0440\u0443\u043a\u0438 \u0447\u0435\u0448\u0443\u0442\u0441\u044f! \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u044b (\u0427\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:20:16+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:20:16+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Blockchain: co nam kosztuje zbudowanie PoC? | ProHoster","description":"Oczy si\u0119 boj\u0105, a r\u0119ce si\u0119 drapi\u0105! W poprzednich artyku\u0142ach om\u00f3wili\u015bmy technologie, na kt\u00f3rych opieraj\u0105 si\u0119 blockchainy (Co nam w tym przeszkadza?).","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u043b\u043e\u043a\u0447\u0435\u0439\u043d: \u0447\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 PoC \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c? | ProHoster","og:description":"\u0413\u043b\u0430\u0437\u0430 \u0431\u043e\u044f\u0442\u0441\u044f, \u0430 \u0440\u0443\u043a\u0438 \u0447\u0435\u0448\u0443\u0442\u0441\u044f! \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u044b (\u0427\u0442\u043e \u043d\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:20:16+00:00","article:modified_time":"2019-10-31T19:20:16+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"37868","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 19:34:11","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:19:22","updated":"2026-01-23 19:34:11","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/37868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=37868"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/37868\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/28421"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=37868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=37868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=37868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}