{"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\/sl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","title":{"rendered":"Blockchain: what does it cost us to build a PoC?","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><i>The eyes are afraid, but the hands are itching!<\/i><\/p>\n<p>In previous articles, we explored the technologies on which blockchains are built (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/443282\/\">Kaj nam stane zgraditi blockchain?<\/a><\/noindex>) and the cases that can be implemented with their help (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/449986\/\">What does it cost us to build a case?<\/a><\/noindex>). It's time to work with our hands! For implementing pilots and PoCs (Proof of Concept), I prefer to use clouds because they are accessible from anywhere in the world, and often, there's no need to waste time on tedious environment setup as there are pre-installed configurations. So, let's create something simple, like a network for transferring coins between participants and modestly call it Citcoin. We will use IBM Cloud and the universal blockchain Hyperledger Fabric. First, let's understand why Hyperledger Fabric is called a universal blockchain.<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a 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 a universal blockchain<\/h2>\n<p>\nIn general terms, a universal information system is:<\/p>\n<ul>\n<li>A set of servers and a software core that performs business logic;<\/li>\n<li>Interfaces for interacting with the system;<\/li>\n<li>Means for registering, authenticating, and authorizing devices\/people;<\/li>\n<li>A database that stores operational and archived data:<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/f11fe73de54b0573d44fae903d367df9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nThe official version of what Hyperledger Fabric is can be read on the <noindex><a rel=\"nofollow\" href=\"https:\/\/www.hyperledger.org\">website<\/a><\/noindex>, and in short, Hyperledger Fabric is an open-source platform that allows building private blockchains and executing arbitrary smart contracts written in programming languages JS and Go. Let's take a closer look at the architecture of Hyperledger Fabric and confirm that this is a universal system, where there are specific details regarding data storage and recording. The specifics are that data, like in all blockchains, is stored in blocks that are added to the blockchain only if participants reach a consensus, and after recording, the data cannot be quietly modified or deleted.<\/p>\n<h2>Architecture of Hyperledger Fabric<\/h2>\n<p>\nThe diagram shows the architecture of Hyperledger Fabric:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/7488d70b330af2bbae1db67005f22a3e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Organizations <\/b> \u2014 organizations contain peers, thus the blockchain exists thanks to the support of organizations. Different organizations can join one channel.<\/p>\n<p><b>Channel <\/b> \u2014 a logical structure that groups peers, thus defining the blockchain. Hyperledger Fabric can simultaneously process several blockchains with different business logic.<\/p>\n<p><b>Membership Services Provider (MSP)<\/b> \u2014 \u044d\u0442\u043e CA (Certificate Authority) \u0434\u043b\u044f \u0432\u044b\u0434\u0430\u0447\u0438 identity \u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u043e\u043b\u0435\u0439. \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0434\u044b \u043d\u0443\u0436\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 MSP.<\/p>\n<p><b>Peer nodes<\/b> \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u0445\u0440\u0430\u043d\u044f\u0442 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0441\u043c\u0430\u0440\u0442-\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u0423 peer-\u043e\u0432 \u0435\u0441\u0442\u044c identity (\u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0434\u0430\u0435\u0442 MSP. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0435\u0442\u0438 Bitcoin \u0438\u043b\u0438 Etherium, \u0433\u0434\u0435 \u0432\u0441\u0435 \u043d\u043e\u0434\u044b \u0440\u0430\u0432\u043d\u043e\u043f\u0440\u0430\u0432\u043d\u044b, \u0432 Hyperledger Fabric \u043d\u043e\u0434\u044b \u0438\u0433\u0440\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u043e\u043b\u0438:<\/p>\n<ul>\n<li>Peer \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c <b>endorsing peer<\/b> (EP) \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043c\u0430\u0440\u0442-\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b.<\/li>\n<li><b>Committing peer<\/b> (CP) \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435 \u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442 \u00abWorld state\u00bb.<\/li>\n<li><b>Anchor Peer<\/b> (AP) \u2014 \u0435\u0441\u043b\u0438 \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0439, \u0442\u043e \u0430\u043d\u043a\u043e\u0440 peer-\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u041a\u0430\u0436\u0434\u0430\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u043d\u043a\u043e\u0440 peer. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e AP \u043b\u044e\u0431\u043e\u0439 peer \u0432 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0441\u0435\u0445 peer-\u0430\u0445 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f\u0445. \u0414\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 AP \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Gossip_protocol\">gossip \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b<\/a><\/noindex>.<\/li>\n<li><b>Leader Peer<\/b> \u2014 \u0435\u0441\u043b\u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e peer-\u043e\u0432, \u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438\u0434\u0435\u0440 peer \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0431\u043b\u043e\u043a\u0438 \u0438\u0437 Ordering service \u0438 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c peer-\u0430\u043c. \u041b\u0438\u0434\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0442\u0430\u043a \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 peer-\u0430\u043c\u0438 \u0432 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043b\u0438\u0434\u0435\u0440\u0430\u0445 \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f gossip \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b.<\/li>\n<\/ul>\n<p>\n<b>Assets <\/b> \u2014 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435. \u0411\u043e\u043b\u0435\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u2014 \u044d\u0442\u043e key-value \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d \u00abBlockchain\u00bb. \u0423 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435 \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u00abWorld state\u00bb. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0431\u0438\u0437\u043d\u0435\u0441 \u0437\u0430\u0434\u0430\u0447. \u041d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439, \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f \u2014 asset-\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430 \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c. <\/p>\n<p><b>Ledger <\/b> \u2014 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0430 \u00abBlockchain\u00bb \u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u00abWord state\u00bb, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 asset-\u043e\u0432. World state \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 LevelDB \u0438\u043b\u0438 CouchDB.<\/p>\n<p><b>Smart contract<\/b> \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043c\u0430\u0440\u0442-\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0412 Hyperledger Fabric \u0441\u043c\u0430\u0440\u0442-\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f chaincode. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e chaincode \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f asset-\u044b \u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043d\u0430\u0434 \u043d\u0438\u043c\u0438. \u0415\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u0442\u043e \u0441\u043c\u0430\u0440\u0442-\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u044f\u0437\u044b\u043a\u0430\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f JS \u0438\u043b\u0438 Go.<\/p>\n<p><b>Endorsement policy<\/b> Za vsak chaincode lahko dolo\u010dite politike, koliko in od katerih \u010dlanov je potrebno potrditi transakcijo. \u010ce politika ni dolo\u010dena, se privzeto uporablja: \"transakcijo mora potrditi katerikoli \u010dlan katere koli organizacije v channelu\". Primeri politik:<\/p>\n<ul>\n<li>Transakcijo mora potrditi kateri koli administrator organizacije;<\/li>\n<li>Mora potrditi kateri koli \u010dlan ali stranka organizacije;<\/li>\n<li>Mora potrditi kateri koli peer organizacije.<\/li>\n<\/ul>\n<p>\n<b>Storitve razporejanja<\/b> \u2014 pakira transakcije v bloke in jih po\u0161ilja peer-om v channel. Zagotavlja dostavo sporo\u010dil vsem peer-om v omre\u017eju. Za industrijske sisteme se uporablja <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Apache_Kafka\">Kafka sporo\u010dilni posrednik<\/a><\/noindex>, za razvoj in testiranje <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: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/9060864bd1002da881d7f17ef8ec0b0c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Aplikacija komunicira s Hyperledger Fabric z uporabo Go, Node.js ali Java SDK;<\/li>\n<li>Stranka ustvari transakcijo tx in jo po\u0161lje na peer-e, ki potrjujejo;<\/li>\n<li>Peer preveri podpis stranke, izvede transakcijo in po\u0161lje potrditveno podpisovanje nazaj stranki. Chaincode se izvaja le na peer-ih, ki potrjujejo, rezultat njegovega izvajanja pa se po\u0161lje vsem peer-om. Ta algoritem dela se imenuje \u2014 PBFT (Practical Byzantine Fault Tolerant) konsenz. Razlikuje se od <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Byzantine_fault\">klasi\u010dnega BFT<\/a><\/noindex> po tem, da se sporo\u010dilo razpo\u0161lje in pri\u010dakuje potrditev ne od vseh udele\u017eencev, ampak samo od dolo\u010denega nabora;<\/li>\n<li>Ko stranka prejme \u0161tevilo odgovorov, ki ustrezajo politiki potrjevanja, po\u0161lje transakcijo na storitev razporejanja;<\/li>\n<li>Storitve razporejanja oblikujejo blok in ga po\u0161ljejo vsem committing peer-om. Storitve razporejanja zagotavljajo dosledno zapisovanje blokov, kar izklju\u010duje tako imenovano 'ledger fork' (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/443282\/\">glejte oddelek \"Forks\"<\/a><\/noindex>);<\/li>\n<li>Peer-ji prejmejo blok, \u0161e enkrat preverijo politiko potrjevanja, zapi\u0161ejo blok v blockchain in spremenijo stanje v \"World state\" DB.<\/li>\n<\/ul>\n<p>\nTo pomeni, da pride do delitve vlog med vozli\u0161\u010di. To zagotavlja raz\u0161irljivost in varnost blockchaina:<\/p>\n<ul>\n<li>Pametne pogodbe (chaincode) izvajajo peers, ki potrjujejo. To zagotavlja zaupnost pametnih pogodb, saj se shranijo samo pri peers, ki potrjujejo, ne pri vseh udele\u017eencih.<\/li>\n<li>Razporejanje mora delovati hitro. To je zagotovljeno, ker razporejanje samo oblikuje blok in ga po\u0161lje na fiksno \u0161tevilo leader peer-ov.<\/li>\n<li>Committing peers samo shranjujejo blockchain \u2014 teh je lahko veliko in ne potrebujejo velike mo\u010di ter takoj\u0161nje delovanja. <\/li>\n<\/ul>\n<p>\nVe\u010d o arhitekturnih re\u0161itvah Hyperledger Fabric in zakaj deluje tako, kot deluje, si lahko ogledate tukaj: <noindex><a rel=\"nofollow\" href=\"https:\/\/hyperledger-fabric.readthedocs.io\/en\/latest\/arch-deep-dive.html\">Izvor arhitekture<\/a><\/noindex> ali tukaj: <noindex><a rel=\"nofollow\" href=\"https:\/\/arxiv.org\/abs\/1801.10228v2\">Hyperledger Fabric: Distribuirani operacijski sistem za dozvoljene blok\u010deine<\/a><\/noindex>.<\/p>\n<p>Dakle, Hyperledger Fabric je zaista univerzalna platforma koja omogu\u0107ava:<\/p>\n<ul>\n<li>Implementiranje poslovne logike pomo\u0107u pametnih ugovora;<\/li>\n<li>Zapisivanje i dobijanje podataka iz blok\u010dejn baze podataka u JSON formatu;<\/li>\n<li>Obezbe\u0111ivanje i verifikacija pristupa API-ju kori\u0161\u0107enjem Certificate Authority. <\/li>\n<\/ul>\n<p>\nSada kada smo malo bolje razumeli su\u0161tinu Hyperledger Fabric, hajde da napokon uradimo ne\u0161to korisno!<\/p>\n<h2>Implementacija blok\u010dejna<\/h2>\n<p><\/p>\n<h3>Definisanje zadatka<\/h3>\n<p>\nZadatak je implementirati Citcoin mre\u017eu sa slede\u0107im funkcijama: kreirati ra\u010dun, dobiti stanje, dopuniti saldo, prebaciti nov\u010di\u0107e sa jednog ra\u010duna na drugi. Napravimo objektni model koji \u0107emo kasnije implementirati u pametan ugovor. Dakle, ima\u0107emo ra\u010dune koji se identifikuju imenima (name) i sadr\u017ee saldo (balance), kao i listu ra\u010duna. Ra\u010duni i lista ra\u010duna su, u terminologiji Hyperledger Fabric, sredstva (assets). Imaju svoju istoriju i trenutno stanje. Poku\u0161a\u0107u da to slikovito prika\u017eem:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/a4f111da59bc7982b51d583857db6d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nGornje figure predstavljaju trenutno stanje koje se \u010duva u 'World state' bazi. Ispod njih su figure koje pokazuju istoriju koja se \u010duva u blok\u010dejnu. Trenutno stanje sredstava menja se transakcijama. Sredstvo se menja samo u celini, stoga se kao rezultat izvr\u0161enja transakcije kreira novi objekat, a trenutno stanje sredstva se prebacuje u istoriju. <\/p>\n<h3>IBM Cloud <\/h3>\n<p>\nOtvorite ra\u010dun u <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.ibm.com\">IBM Cloud<\/a><\/noindex>. Da biste koristili platformu za blok\u010dejn, morate je nadograditi na Pay-As-You-Go model. Ovaj proces mo\u017ee biti spor, jer IBM tra\u017ei dodatne informacije i ru\u010dno ih proverava. Sa pozitivne strane, mogu re\u0107i da IBM ima dobre obrazovne materijale koji omogu\u0107avaju implementaciju Hyperledger Fabric u njihovom oblaku. Svideo mi se slede\u0107i niz \u010dlanaka i primera:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/Create-BlockchainNetwork-IBPV20\/blob\/master\/README.md\">Kreirajte osnovnu blok\u010dejn mre\u017eu koriste\u0107i Blockchain Platformu<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/SmartContractTrading-wFabric1-4-VSCodeExt\/blob\/master\/README.md\">Kreirajte i izvr\u0161ite pametan ugovor na blok\u010dejnu<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/auction-events\/blob\/master\/README.md\">Emitujte doga\u0111aje sa Blockchain Platforme<\/a><\/noindex><\/li>\n<\/ul>\n<p>\nU nastavku su prikazane slike iz IBM Blockchain platforme. Ovo nije uputstvo za kreiranje blok\u010dejna, ve\u0107 samo demonstracija obima zadatka. Dakle, za na\u0161e potrebe pravimo jednu Organizaciju:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/7cb30cade6315abc69f4322a2dbcd094.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nU njoj kreiramo \u010dvorove: Orderer CA, Org1 CA, Orderer Peer:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/4a2239a9b7ded8ba5a11ffad86a35094.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOtvori korisnike:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/6792b12c9316f47b0cdfaf771dacc782.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKreiramo Channel i nazivamo ga citcoin:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/ea3983f209326713dcd25762c348ac96.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSu\u0161tinski, Channel je blok\u010dejn, stoga po\u010dinje od nultog bloka (Genesis block):<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/416df6b6ef832c6550a2642592e57250.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Pi\u0161emo pametni ugovor<\/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>\nIntuitivno bi ovde sve trebalo biti jasno:<\/p>\n<ul>\n<li>Obstaja ve\u010d funkcij (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance), ki jih bo demo program klical preko Hyperledger Fabric API.<\/li>\n<li>Funkciji SendFrom in RefillBalance generirata dogodke (Event), ki jih bo prejel demo program.<\/li>\n<li>Funkcija instantiate se pokli\u010de enkrat ob instanciranju pametne pogodbe. V resnici pa se pokli\u010de ve\u010dkrat ob spremembi verzije pametne pogodbe. Zato je inicializacija seznama z praznim poljem slaba ideja, saj ob spremembi verzije pametne pogodbe izgubimo trenutni seznam. Ampak ni\u010d, le u\u010dim se).<\/li>\n<li>Ra\u010duni in seznam ra\u010dunov (accounts) so JSON strukture podatkov. Za manipulacijo podatkov se uporablja JS.<\/li>\n<li>Trenutno vrednost sredstva lahko pridobimo s klicem funkcije getState, za posodobitev pa uporabimo putState.<\/li>\n<li>Ob ustvarjanju ra\u010duna se pokli\u010de funkcija AddAccount, kjer se izvede primerjava z najve\u010djim \u0161tevilom ra\u010dunov v blockchainu (maxAccounts = 5). In tukaj je napaka (ste opazili?), ki vodi v neskon\u010dno rast \u0161tevila ra\u010dunov. Tak\u0161nih napak se je treba izogibati)<\/li>\n<\/ul>\n<p>\nNato nalo\u017eimo pametno pogodbo v Channel in jo instanciramo:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/45ad234efc9838b711f96642988f073e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPoglejmo transakcijo za namestitev pametne pogodbe:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/39605b9d09468fd0c5f0557ed8b692a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPoglejmo podrobnosti o na\u0161em Channel:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/ccaf803cf34e52f77dac448f9c83e672.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKot rezultat dobimo naslednjo shemo blockchain omre\u017eja v oblaku IBM. Shema prav tako prikazuje demo program, ki te\u010de v oblaku Amazon na virtualnem stre\u017eniku (podrobneje o tem v naslednjem razdelku):<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/64e5c0f27d351ee3b60d2ea471a7f58c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Ustvarjanje GUI za klice Hyperledger Fabric API<\/h2>\n<p>\nHyperledger Fabric ima API, ki se lahko uporablja za:<\/p>\n<ul>\n<li>Ustvarjanje channel-a;<\/li>\n<li>Povezovanje peer-a s channel-om;<\/li>\n<li>Namestitev in instanciranje pametnih pogodb v channel-u;<\/li>\n<li>Klicanje transakcij;<\/li>\n<li>Zahtevanje informacij iz blockchaina.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Razvoj aplikacije<\/h3>\n<p>\nV na\u0161em demo programu bomo uporabljali API samo za klicanje transakcij in zahtevo informacij, saj smo ostale korake \u017ee izvedli z uporabo blockchain platforme IBM. Pisali bomo GUI z uporabo standardnega tehnolo\u0161kega sklada: Express.js + Vue.js + Node.js. O tem, kako za\u010deti izdelovati sodobne spletne aplikacije, bi lahko napisali poseben \u010dlanek. Tukaj dodajam povezavo na serijo predavanj, ki so mi bila najbolj v\u0161e\u010d: <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/Fa4cRMaTDUI\">Full Stack Web App using Vue.js &amp; Express.js<\/a><\/noindex>. V rezultatu je nastala odjemalsko-stre\u017eni\u0161ka aplikacija z znanim grafi\u010dnim vmesnikom v slogu Material Design od Google. REST API med odjemalcem in stre\u017enikom sestavljajo \u0161tevilni klici:<\/p>\n<ul>\n<li>HyperledgerDemo\/v1\/init \u2014 inicializirati blockchain;<\/li>\n<li>HyperledgerDemo\/v1\/accounts\/list \u2014 pridobiti seznam vseh ra\u010dunov;<\/li>\n<li>HyperledgerDemo\/v1\/account?name=Bob&amp;balance=100 \u2014 ustvariti ra\u010dun Bob;<\/li>\n<li>HyperledgerDemo\/v1\/info?account=Bob \u2014 pridobiti informacije o ra\u010dunu Bob;<\/li>\n<li>HyperledgerDemo\/v1\/transaction?from=Bob&amp;to=Alice&amp;volume=2 \u2014 prenesti dve kovanci od Boba k Alici;<\/li>\n<li>HyperledgerDemo\/v1\/disconnect \u2014 prekiniti povezavo z blokovno verigo.<\/li>\n<\/ul>\n<p>\nOpis API s primeri je na voljo na<noindex><a rel=\"nofollow\" href=\"https:\/\/documenter.getpostman.com\/view\/7152141\/SVfTNSeb\"> spletni strani \u201ePostman\u201c<\/a><\/noindex> \u2014 \u0161iroko znanem programu za testiranje HTTP API.<\/p>\n<h3>Demo aplikacija v oblaku Amazon<\/h3>\n<p>\nAplikacijo sem nalo\u017eil na Amazon, ker IBM \u0161e ni uspel nadgraditi mojega ra\u010duna in omogo\u010diti ustvarjanje virtualnih stre\u017enikov. Na vrhu sem dodal domeno: <noindex><a rel=\"nofollow\" href=\"http:\/\/www.citcoin.info\">www.citcoin.info<\/a><\/noindex>. Malo bom obdr\u017eal stre\u017enik vklopljen, potem ga izklopim, ker se zara\u010dunava najem, kovanci citcoin pa na borzi \u0161e niso uvr\u0161\u010deni) V \u010dlanek dodajam posnetke zaslona demo, da bo razumljena logika delovanja. Demo aplikacija lahko:<\/p>\n<ul>\n<li>Inicijalizirati blokovno verigo;<\/li>\n<li>Ustvarjati Ra\u010dun (trenutno novega ra\u010duna ni mo\u017eno ustvariti, ker je v blokovni verigi dose\u017eeno maksimalno \u0161tevilo ra\u010dunov, kot je zapisano v pametnem pogodbi);<\/li>\n<li>Pridobiti seznam ra\u010dunov;<\/li>\n<li>Prenesti kovance citcoin med Alicjo, Bobom in Aleksandrom;<\/li>\n<li>Pridobiti dogodke (trenutno dogodkov ni mogo\u010de prikazati, zato je v vmesniku za enostavnost zapisano, da dogodki niso podprti);<\/li>\n<li>Zapisovati aktivnosti.<\/li>\n<\/ul>\n<p>\nNajprej inicializiramo blokovno verigo:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/773ce08270f1b22e64a79fce267bb25f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNato ustvarimo svoj ra\u010dun, ne var\u010dujemo s saldo:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/f1cd24aedd5e9618046c5e1ab49ceede.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPridobimo seznam vseh razpolo\u017eljivih ra\u010dunov:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/796f897ca1345430f755055372d03421.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIzberemo po\u0161iljatelja in prejemnika, pridobimo njihove salde. \u010ce sta po\u0161iljatelj in prejemnik ista oseba, bo njegov ra\u010dun pove\u010dal saldo:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/58eb2ed4a4bac51e0dca1b0331d7910a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nV dnevniku spremljamo izvr\u0161evanje transakcij:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/528760998e8dc27a73c4409f55b22087.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nS tem je demo program kon\u010dan. Oglejte si na\u0161o transakcijo v blokovni verigi:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/1d6bc12f3609b118472afec31b089f09.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn skupni seznam transakcij:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: what does it cost us to build a PoC?\" src=\"\/wp-content\/uploads\/2019\/09\/96675fcda8088307326dadf7852e6ce7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUspe\u0161no smo zaklju\u010dili implementacijo PoC za ustvarjanje omre\u017eja Citcoin. Kaj je \u0161e potrebno, da Citcoin postane popoln sistem za prenos kovancev? Skoraj ni\u010d:<\/p>\n<ul>\n<li>Pri ustvarjanju ra\u010duna implementirati generacijo zasebnega\/publik\u010dnega klju\u010da. Zasebni klju\u010d mora biti shranjen pri uporabniku ra\u010duna, javni v blokovni verigi.<\/li>\n<li>Uvesti prenos kovancev, pri \u010demer za identifikacijo uporabnika uporabimo ne ime, temve\u010d javni klju\u010d.<\/li>\n<li>\u0160ifrirati transakcije, ki gredo od uporabnika na stre\u017enik z njegovim zasebnim klju\u010dem.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Zaklju\u010dek <\/h2>\n<p>\nUresni\u010dili smo omre\u017eje Citcoin s funkcijami: dodajanje ra\u010duna, preverjanje stanja, polnjenje ra\u010duna, prenos kovancev z enega ra\u010duna na drugega. Kaj nas je torej stalo izgradnja PoC?<\/p>\n<ul>\n<li>Potrebno je preu\u010diti blockchain na splo\u0161no in Hyperledger Fabric posebej;<\/li>\n<li>Nau\u010diti se uporabljati IBMov ali Amazonove oblake;<\/li>\n<li>Nau\u010diti se programskega jezika JS in kak\u0161en spletni okvir;<\/li>\n<li>\u010ce je treba nekatere podatke hraniti zunaj blockchaina, za integracijo z lo\u010deno bazo, se nau\u010diti, na primer, PostgreSQL;<\/li>\n<li>In zadnje, a ne manj pomembno - brez znanja Linuxa v sodobnem svetu nikamor!)<\/li>\n<\/ul>\n<p>\nSeveda, to ni raketna znanost, a malo dela bo potrebno!<\/p>\n<h3>Izvorna koda na GitHubu<\/h3>\n<p>\nIzvorno kodo sem dal na <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/AlexeySushkov\/Citcoin-blockchain\">GitHub<\/a><\/noindex>. Kratek opis repozitorija:<br \/>\nKatalog &#171;<b>stre\u017enik<\/b>&#187; \u2014 Node.js stre\u017enik<br \/>\nKatalog &#171;<b>odjemalec<\/b>&#187; \u2014 Node.js odjemalec<br \/>\nKatalog &#171;<b>blockchain<\/b>&#187; (vrednosti parametrov in klju\u010di, seveda, niso delujo\u010di in so navedeni zgolj kot primer):<\/p>\n<ul>\n<li>contract - izvorna koda pametnega pogodbe<\/li>\n<li>wallet - klju\u010di uporabnika za uporabo Hyperledger Fabric API. <\/li>\n<li>*.cds - skompilirane razli\u010dice pametnih pogodb<\/li>\n<li>*.json datoteke - primeri konfiguracijskih datotek za uporabo Hyperledger Fabric API<\/li>\n<\/ul>\n<p>\n<b>To je \u0161ele za\u010detek!<\/b><br \/>\n<br \/>Izvor: <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.4 - 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\/sl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sl_SI\" \/>\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\/sl\/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: koliko nas stane izgradnja PoC? | ProHoster","description":"O\u010di se bojijo, roke pa se srbe! V prej\u0161njih \u010dlankih smo se poglobili v tehnologije, na katerih temeljijo blockchaini (Koliko nas stane blockchain.","canonical_url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sl_SI","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\/sl\/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\/sl\/wp-json\/wp\/v2\/posts\/37868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/comments?post=37868"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/37868\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media\/28421"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media?parent=37868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/categories?post=37868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/tags?post=37868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}