{"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\/nl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","title":{"rendered":"Blockchain: wat kost het ons om een PoC op te zetten?","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><i>De ogen zijn bang, maar de handen jeuken!<\/i><\/p>\n<p>In eerdere artikelen hebben we de technologie\u00ebn behandeld waarop blockchains zijn gebouwd (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/443282\/\">Wat kost het ons om een blockchain te bouwen?<\/a><\/noindex>) en de cases die daarmee gerealiseerd kunnen worden (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/449986\/\">Wat kost het om een case te bouwen?<\/a><\/noindex>). Het is tijd om aan de slag te gaan! Voor het realiseren van pilots en PoC (Proof of Concept) geef ik de voorkeur aan clouds, omdat ze vanaf elke locatie ter wereld toegankelijk zijn en je vaak geen tijd hoeft te verspillen aan het vervelende installeren van omgevingen, aangezien er vooraf ge\u00efnstalleerde configuraties zijn. Laten we iets eenvoudigs doen, bijvoorbeeld een netwerk voor het overdragen van munten tussen deelnemers en het bescheiden de naam CitoCoin geven. Hiervoor gaan we de cloud van IBM en de universele blockchain Hyperledger Fabric gebruiken. Laten we eerst begrijpen waarom Hyperledger Fabric een universele blockchain wordt genoemd.<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" 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 de universele blockchain<\/h2>\n<p>\nIn algemene termen is een universeel informatiesysteem:<\/p>\n<ul>\n<li>Een set servers en een programmatische kern die de bedrijfslogica uitvoert;<\/li>\n<li>Interfaces voor interactie met het systeem;<\/li>\n<li>Middelen voor registratie, authenticatie en autorisatie van apparaten\/mensen;<\/li>\n<li>Een database die operationele en archiefgegevens opslaat:<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/f11fe73de54b0573d44fae903d367df9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDe offici\u00eble versie van wat Hyperledger Fabric is, kan worden gelezen op <noindex><a rel=\"nofollow\" href=\"https:\/\/www.hyperledger.org\">website<\/a><\/noindex>, maar kort samengevat is Hyperledger Fabric een opensource platform waarmee gesloten blockchains kunnen worden gebouwd en willekeurige smart contracts kunnen worden uitgevoerd die zijn geschreven in de programmeertalen JS en Go. Laten we de architectuur van Hyperledger Fabric gedetailleerd bekijken en ervoor zorgen dat dit een universeel systeem is, waarbij alleen de specificiteit van het opslaan en schrijven van gegevens bestaat. De specificiteit is dat gegevens, zoals in alle blockchains, in blokken worden opgeslagen, die alleen in de blockchain worden geplaatst als de deelnemers consensus hebben bereikt en na opname kunnen de gegevens niet ongemerkt worden gewijzigd of verwijderd.<\/p>\n<h2>Architectuur van Hyperledger Fabric<\/h2>\n<p>\nIn het diagram is de architectuur van Hyperledger Fabric weergegeven:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/7488d70b330af2bbae1db67005f22a3e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Organisaties <\/b> \u2014 organisaties bevatten peers, zodat de blockchain bestaat dankzij de ondersteuning van organisaties. Verschillende organisaties kunnen deel uitmaken van \u00e9\u00e9n channel.<\/p>\n<p><b>Channel <\/b> \u2014 een logische structuur die peers in groepen verenigt, zodat de blockchain wordt gedefinieerd. Hyperledger Fabric kan tegelijkertijd meerdere blockchains verwerken met verschillende bedrijfslogica.<\/p>\n<p><b>Membership Services Provider (MSP)<\/b> \u2014 dit is de CA (Certificate Authority) voor het verstrekken van identiteiten en het toewijzen van rollen. Voor het cre\u00ebren van een node moet interactie plaatsvinden met de MSP.<\/p>\n<p><b>Peer-nodes<\/b> \u2014 controleren transacties, slaan de blockchain op, voeren smart contracts uit en interageren met applicaties. Peer-nodes hebben een identiteit (digitale certificaat), dat wordt uitgegeven door MSP. In tegenstelling tot netwerken zoals Bitcoin of Ethereum, waar alle nodes gelijkwaardig zijn, spelen nodes in Hyperledger Fabric verschillende rollen:<\/p>\n<ul>\n<li>Een peer kan zijn <b>endorsing peer<\/b> (EP) en smart contracts uitvoeren.<\/li>\n<li><b>Committing peer<\/b> (CP) \u2013 slaat alleen gegevens op in de blockchain en actualiseert de \"World state\".<\/li>\n<li><b>Anchor Peer<\/b> (AP) \u2013 als er meerdere organisaties in de blockchain deelnemen, worden anchor peers gebruikt voor de communicatie tussen hen. Elke organisatie moet \u00e9\u00e9n of meerdere anchor peers hebben. Met AP kan elke peer binnen een organisatie informatie krijgen over alle peers in andere organisaties. Voor de synchronisatie van informatie tussen AP's wordt <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Gossip_protocol\">het gossipprotocol<\/a><\/noindex>.<\/li>\n<li><b>Leader Peer<\/b> \u2013 als een organisatie meerdere peers heeft, zal alleen de leader peer blokken ontvangen van de Ordering service en deze aan de andere peers doorgeven. De leider kan zowel statisch worden ingesteld als dynamisch worden gekozen door peers binnen de organisatie. Voor de synchronisatie van informatie over de leiders wordt ook het gossipprotocol gebruikt.<\/li>\n<\/ul>\n<p>\n<b>Assets <\/b> \u2013 entiteiten met waarde die worden opgeslagen in de blockchain. Meer specifiek zijn dit key-value gegevens in JSON-formaat. Deze gegevens worden vastgelegd in de blockchain \"Blockchain\". Ze hebben een geschiedenis, die in de blockchain wordt opgeslagen, en een huidige staat, die in de database \"World state\" wordt opgeslagen. De datastructuren worden willekeurig gevuld, afhankelijk van de zakelijke behoeften. Er zijn geen verplichte velden, de enige aanbeveling is dat assets een eigenaar moeten hebben en waarde moeten vertegenwoordigen. <\/p>\n<p><b>Ledger <\/b> \u2013 bestaat uit de blockchain \"Blockchain\" en de database \"World state\", waarin de huidige staat van de assets wordt opgeslagen. World state maakt gebruik van LevelDB of CouchDB.<\/p>\n<p><b>Slim contract<\/b> \u2013 met behulp van smart contracts wordt de bedrijfslogica van het systeem ge\u00efmplementeerd. In Hyperledger Fabric worden smart contracts chaincode genoemd. Met chaincode worden assets en transacties daarop gedefinieerd. Technisch gesproken zijn smart contracts softwaremodules die zijn ge\u00efmplementeerd in programmeertalen zoals JS of Go.<\/p>\n<p><b>Endorsement policy<\/b> \u2013 voor elke chaincode kan worden vastgesteld welke en hoeveel bevestigingen voor een transactie nodig zijn van wie. Als er geen beleid is vastgesteld, geldt standaard: \"de transactie moet worden goedgekeurd door elk lid (member) van elke organisatie in het kanaal\". Voorbeelden van beleidsregels:<\/p>\n<ul>\n<li>De transactie moet worden bevestigd door een administrator van de organisatie;<\/li>\n<li>Moet bevestigd worden door een lid of klant van de organisatie;<\/li>\n<li>Moet bevestigd worden door een peer van de organisatie.<\/li>\n<\/ul>\n<p>\n<b>Ordering service<\/b> \u2014 verpakt transacties in blokken en verzendt deze naar de peers in het kanaal. Het garandeert de levering van berichten aan alle peers in het netwerk. Voor industri\u00eble systemen wordt gebruikt <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Apache_Kafka\">berichtenbroker Kafka<\/a><\/noindex>, voor ontwikkeling en testen <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: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/9060864bd1002da881d7f17ef8ec0b0c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>De applicatie communiceert met Hyperledger Fabric via Go, Node.js of Java SDK;<\/li>\n<li>De client cre\u00ebert de transactie tx en stuurt deze naar de endorsing peers;<\/li>\n<li>De peer controleert de handtekening van de client, voert de transactie uit en stuurt de endorsement signature terug naar de client. Chaincode wordt alleen uitgevoerd op de endorsing peer en het resultaat van de uitvoering wordt naar alle peers verzonden. Dit werkalgoritme wordt PBFT (Practical Byzantine Fault Tolerant) consensus genoemd. Dit verschilt van <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Byzantine_fault\">klassieke BFT<\/a><\/noindex> doordat het bericht wordt verzonden en een bevestiging wordt verwacht niet van alle deelnemers, maar alleen van een bepaalde set;<\/li>\n<li>Nadat de client het aantal antwoorden heeft ontvangen dat overeenkomt met de endorsement policy, stuurt hij de transactie naar de Ordering service;<\/li>\n<li>De Ordering service vormt een blok en verzendt dit naar alle committing peers. De Ordering service zorgt voor een consistente opname van blokken, waardoor zogenaamde ledger forks worden uitgesloten (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/443282\/\">zie sectie 'Forks'<\/a><\/noindex>);<\/li>\n<li>De peers ontvangen het blok, controleren opnieuw de endorsement policy, registreren het blok in de blockchain en wijzigen de status in de 'World state' DB.<\/li>\n<\/ul>\n<p>\nDat is, er is een scheiding van rollen tussen de knopen. Dit zorgt voor schaalbaarheid en veiligheid van de blockchain:<\/p>\n<ul>\n<li>Slimme contracten (chaincode) worden uitgevoerd door de endorsing peers. Dit waarborgt de vertrouwelijkheid van slimme contracten, omdat het niet bij alle deelnemers is opgeslagen, maar alleen op de endorsing peers.<\/li>\n<li>Ordering moet snel werken. Dit wordt mogelijk gemaakt doordat Ordering alleen blokken vormt en deze naar een vaste set van leader peers verzendt.<\/li>\n<li>Committing peers slaan alleen de blockchain op \u2014 er kunnen er veel zijn en ze vereisen geen grote kracht of directe werking. <\/li>\n<\/ul>\n<p>\nMeer informatie over de architectonische oplossingen van Hyperledger Fabric en waarom het op deze manier werkt, kan hier worden bekeken: <noindex><a rel=\"nofollow\" href=\"https:\/\/hyperledger-fabric.readthedocs.io\/en\/latest\/arch-deep-dive.html\">Architecture Origins<\/a><\/noindex> of hier: <noindex><a rel=\"nofollow\" href=\"https:\/\/arxiv.org\/abs\/1801.10228v2\">Hyperledger Fabric: A Distributed Operating System for Permissioned Blockchains<\/a><\/noindex>.<\/p>\n<p>Dus, Hyperledger Fabric is echt een veelzijdig systeem waarmee je kunt:<\/p>\n<ul>\n<li>Arbitraire bedrijfslogica implementeren met behulp van slimme contracten;<\/li>\n<li>Gegevens opnemen en ophalen uit een blockchain-database in JSON-formaat;<\/li>\n<li>Toegang tot de API verlenen en controleren met behulp van een Certificate Authority. <\/li>\n<\/ul>\n<p>\nLaten we iets nuttigs gaan doen nu we een beetje begrijpen van de specificaties van Hyperledger Fabric!<\/p>\n<h2>Blockchain implementeren<\/h2>\n<p><\/p>\n<h3>Taakstelling<\/h3>\n<p>\nDe taak is om een Citcoin-netwerk te implementeren met de volgende functies: een account aanmaken, saldo opvragen, rekening aanvullen, munten van het ene account naar het andere overmaken. Laten we een objectmodel schetsen dat we vervolgens in een smart contract zullen implementeren. We hebben dus accounts die worden ge\u00efdentificeerd door namen (name) en een saldo (balance) bevatten, en een lijst van accounts. Accounts en de lijst van accounts zijn in de terminologie van Hyperledger Fabric assets. Ze hebben respectievelijk een geschiedenis en een huidige status. Ik zal proberen dit visueel weer te geven:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/a4f111da59bc7982b51d583857db6d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDe bovenste figuren zijn de huidige status, die wordt opgeslagen in de 'World state' database. Onder hen zijn de figuren die de geschiedenis tonen, die in de blockchain zijn opgeslagen. De huidige status van assets verandert door transacties. Een asset wordt alleen geheel gewijzigd, daarom wordt er na het uitvoeren van een transactie een nieuw object aangemaakt, en de huidige waarde van de asset gaat naar de geschiedenis. <\/p>\n<h3>IBM Cloud <\/h3>\n<p>\nLaten we een account aanmaken in <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.ibm.com\">de IBM Cloud<\/a><\/noindex>. Voor het gebruik van het blockchainplatform moet het worden ge\u00fcpgraded naar Pay-As-You-Go. Dit proces kan niet snel zijn, omdat IBM aanvullende informatie aanvraagt en deze handmatig controleert. Positief is dat IBM goede leermaterialen heeft die het mogelijk maken om Hyperledger Fabric in hun cloud in te zetten. Ik vond de volgende cyclus van artikelen en voorbeelden leuk:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/Create-BlockchainNetwork-IBPV20\/blob\/master\/README.md\">Maak een basis blockchain-netwerk met het Blockchain-platform<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/SmartContractTrading-wFabric1-4-VSCodeExt\/blob\/master\/README.md\">Bouw en voer een blockchain smart contract uit<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/IBM\/auction-events\/blob\/master\/README.md\">Stuur gebeurtenissen van het Blockchain-platform uit<\/a><\/noindex><\/li>\n<\/ul>\n<p>\nHieronder staan schermafbeeldingen van het IBM Blockchain-platform. Dit is geen handleiding voor het maken van een blockchain, maar gewoon een demonstratie van de omvang van de taak. Dus, voor onze doeleinden maken we \u00e9\u00e9n organisatie:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/7cb30cade6315abc69f4322a2dbcd094.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDaar cre\u00ebren we nodes: Orderer CA, Org1 CA, Orderer Peer:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/4a2239a9b7ded8ba5a11ffad86a35094.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWe maken gebruikers aan:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/6792b12c9316f47b0cdfaf771dacc782.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWe cre\u00ebren een kanaal en noemen het citcoin:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/ea3983f209326713dcd25762c348ac96.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn wezen is een kanaal een blockchain, dus het begint met een nulblok (Genesis block):<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/416df6b6ef832c6550a2642592e57250.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>We schrijven een 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>\nIntu\u00eftief moet hier alles duidelijk zijn:<\/p>\n<ul>\n<li>Er zijn verschillende functies (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) die het demo-programma zal aanroepen met behulp van de Hyperledger Fabric API.<\/li>\n<li>De functies SendFrom en RefillBalance genereren evenementen (Event) die het demo-programma zal ontvangen.<\/li>\n<li>De functie instantiate wordt eenmaal aangeroepen bij het instanti\u00ebren van een smart contract. In werkelijkheid wordt deze niet \u00e9\u00e9n keer aangeroepen, maar elke keer dat de versie van het smart contract verandert. Daarom is het initialiseren van de lijst met een lege array een slecht idee, omdat we nu de huidige lijst verliezen bij de wijziging van de versie van het smart contract. Maar goed, ik leer alleen maar).<\/li>\n<li>Accounts en de lijst van accounts (accounts) zijn JSON-gegevensstructuren. Voor gegevensmanipulaties wordt JS gebruikt.<\/li>\n<li>De huidige waarde van een asset kan worden verkregen met de functie getState, en kan worden bijgewerkt met putState.<\/li>\n<li>Bij het aanmaken van een Account wordt de functie AddAccount aangeroepen, waarin de vergelijking wordt gemaakt met het maximum aantal accounts in de blockchain (maxAccounts = 5). En hier zit een fout (opgemerkt?), die leidt tot een oneindige groei van het aantal accounts. Dit soort fouten moet je vermijden)<\/li>\n<\/ul>\n<p>\nLaten we nu het smart contract in het Channel laden en het instanti\u00ebren:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/45ad234efc9838b711f96642988f073e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLaten we de transactie voor het instellen van het Smart Contract bekijken:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/39605b9d09468fd0c5f0557ed8b692a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLaten we de details van ons Channel bekijken:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/ccaf803cf34e52f77dac448f9c83e672.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAls resultaat krijgen we het volgende schema van het blockchain-netwerk in de cloud van IBM. Ook op het schema staat een demo-applicatie die draait in de cloud van Amazon op een virtuele server (meer daarover in de volgende sectie):<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/64e5c0f27d351ee3b60d2ea471a7f58c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>GUI maken voor het aanroepen van de Hyperledger Fabric API<\/h2>\n<p>\nHyperledger Fabric heeft een API die kan worden gebruikt voor:<\/p>\n<ul>\n<li>Het aanmaken van een channel;<\/li>\n<li>Het verbinden van een peer aan een channel;<\/li>\n<li>Het installeren en instanti\u00ebren van smart contracts in het channel;<\/li>\n<li>Het aanroepen van transacties;<\/li>\n<li>Informatie opvragen in de blockchain.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Applicatieontwikkeling<\/h3>\n<p>\nIn onze demo-applicatie gebruiken we de API alleen voor het aanroepen van transacties en het opvragen van informatie, aangezien we de andere stappen al hebben uitgevoerd met behulp van het blockchain-platform van IBM. We schrijven de GUI met behulp van de standaardtechnologiestack: Express.js + Vue.js + Node.js. Hoe je moderne webapplicaties kunt beginnen te maken, kan in een apart artikel worden behandeld. Hier laat ik een link achter naar een serie lezingen die ik het leukst vond: <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/Fa4cRMaTDUI\">Full Stack Web App using Vue.js &amp; Express.js<\/a><\/noindex>. Het resultaat is een client-serverapplicatie met een bekend grafisch interface in de stijl van Material Design van Google. REST API tussen de client en de server bestaat uit verschillende aanroepen:<\/p>\n<ul>\n<li>HyperledgerDemo\/v1\/init \u2014 blockchain initialiseren;<\/li>\n<li>HyperledgerDemo\/v1\/accounts\/list \u2014 lijst van alle accounts ophalen;<\/li>\n<li>HyperledgerDemo\/v1\/account?name=Bob&amp;balance=100 \u2014 Bob account aanmaken;<\/li>\n<li>HyperledgerDemo\/v1\/info?account=Bob \u2014 informatie over Bob account ophalen;<\/li>\n<li>HyperledgerDemo\/v1\/transaction?from=Bob&amp;to=Alice&amp;volume=2 \u2014 twee munten overmaken van Bob naar Alice;<\/li>\n<li>HyperledgerDemo\/v1\/disconnect \u2014 verbindt met de blockchain.<\/li>\n<\/ul>\n<p>\nDe API-beschrijving met voorbeelden heb ik geplaatst op<noindex><a rel=\"nofollow\" href=\"https:\/\/documenter.getpostman.com\/view\/7152141\/SVfTNSeb\"> de site 'Postman'<\/a><\/noindex> \u2014 een wereldwijd bekend programma voor het testen van HTTP-API's.<\/p>\n<h3>Demo-applicatie in de Amazon-cloud.<\/h3>\n<p>\nIk heb de applicatie ge\u00fcpload naar Amazon, omdat IBM nog steeds mijn account niet heeft ge\u00fcpgraded en ik geen virtuele servers kan aanmaken. Als kers op de taart heb ik het domein toegevoegd: <noindex><a rel=\"nofollow\" href=\"http:\/\/www.citcoin.info\">www.citcoin.info<\/a><\/noindex>. Ik houd de server een beetje aan, daarna zet ik hem uit, omdat de kosten voor de huur oplopen en de citcoin-munten nog niet op de beurs worden verhandeld) Ik voeg screenshots van de demo toe om de werklogica te verduidelijken. De demo-applicatie kan:<\/p>\n<ul>\n<li>De blockchain initialiseren;<\/li>\n<li>Een account aanmaken (maar op dit moment kan er geen nieuw account worden aangemaakt, omdat het maximale aantal accounts in het smart contract bereikt is);<\/li>\n<li>Een lijst van accounts opvragen;<\/li>\n<li>Citcoin-munten overdragen tussen Alice, Bob en Alex;<\/li>\n<li>Gebeurtenissen ontvangen (maar op dit moment kunnen gebeurtenissen niet worden getoond, daarom staat er voor de eenvoud in de interface dat gebeurtenissen niet worden ondersteund);<\/li>\n<li>Acties loggen.<\/li>\n<\/ul>\n<p>\nLaten we eerst de blockchain initialiseren:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/773ce08270f1b22e64a79fce267bb25f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVervolgens maken we een account aan, laten we niet zuinig zijn met het saldo:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/f1cd24aedd5e9618046c5e1ab49ceede.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLaten we een lijst van alle beschikbare accounts opvragen:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/796f897ca1345430f755055372d03421.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWe kiezen een verzender en ontvanger, en bekijken hun saldi. Als de verzender en ontvanger dezelfde zijn, wordt zijn rekening aangevuld:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/58eb2ed4a4bac51e0dca1b0331d7910a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn het log volgen we de uitvoering van transacties:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/528760998e8dc27a73c4409f55b22087.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDat was het dan met de demo-applicatie. Laten we nu onze transactie in de blockchain bekijken:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/1d6bc12f3609b118472afec31b089f09.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn de algemene lijst van transacties:<\/p>\n<p><img decoding=\"async\" alt=\"Blockchain: wat kost het ons om een PoC op te zetten?\" src=\"\/wp-content\/uploads\/2019\/09\/96675fcda8088307326dadf7852e6ce7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nHiermee hebben we de implementatie van de PoC voor het opzetten van het Citcoin-netwerk succesvol afgerond. Wat moet er nog meer gebeuren om Citcoin een volwaardig netwerk voor het overdragen van munten te maken? Heel weinig:<\/p>\n<ul>\n<li>Bij het aanmaken van een account moet de generatie van een priv\u00e9-\/publieke sleutel worden gerealiseerd. De priv\u00e9sleutel moet bij de gebruiker van het account worden bewaard, de publieke sleutel in de blockchain.<\/li>\n<li>Doe een muntoverdracht waarin de identificatie van de gebruiker niet via de naam, maar via de publieke sleutel verloopt.<\/li>\n<li>Versleutel transacties die van de gebruiker naar de server gaan met zijn priv\u00e9sleutel.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Conclusie <\/h2>\n<p>\nWe hebben het Citcoin-netwerk gerealiseerd met de functies: account toevoegen, saldo opvragen, rekening aanvullen, munten van de ene rekening naar de andere overdragen. Dus, wat heeft het ons gekost om de PoC te bouwen?<\/p>\n<ul>\n<li>We moeten de blockchain in het algemeen en Hyperledger Fabric in het bijzonder bestuderen;<\/li>\n<li>Leren om gebruik te maken van IBM- of Amazon-cloudservices;<\/li>\n<li>De programmeertaal JS leren en een webframework kiezen;<\/li>\n<li>Als bepaalde gegevens niet in de blockchain, maar in een aparte database moeten worden opgeslagen, leer dan bijvoorbeeld te integreren met PostgreSQL;<\/li>\n<li>En als laatste op de lijst, maar niet minder belangrijk - zonder kennis van Linux kom je de moderne wereld niet door!)<\/li>\n<\/ul>\n<p>\nNatuurlijk, het is geen rocket science, maar je moet wel je best doen!<\/p>\n<h3>Bronbestanden op GitHub<\/h3>\n<p>\nDe broncodes zijn geplaatst op <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/AlexeySushkov\/Citcoin-blockchain\">GitHub<\/a><\/noindex>. Korte beschrijving van de repository:<br \/>\nCatalog &#171;<b>server<\/b>&#187; \u2014 Node.js server<br \/>\nCatalog &#171;<b>client<\/b>&#187; \u2014 Node.js client<br \/>\nCatalog &#171;<b>blockchain<\/b>&#187; (de waarden van parameters en sleutels zijn uiteraard niet werkend en dienen slechts ter illustratie):<\/p>\n<ul>\n<li>contract - broncode van het smart contract<\/li>\n<li>wallet - gebruikerssleutels voor het gebruik van de Hyperledger Fabric API. <\/li>\n<li>*.cds - gecompileerde versies van smart contracts<\/li>\n<li>*.json bestanden - voorbeelden van configuratiebestanden voor het gebruik van de Hyperledger Fabric API<\/li>\n<\/ul>\n<p>\n<b>Het is pas het begin!<\/b><br \/>\n<br \/>Bron: <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.3 - 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\/nl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\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\/nl\/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: wat kost het om een PoC te bouwen? | ProHoster","description":"De ogen zijn bang, maar de handen jeuken! In eerdere artikelen hebben we de technologie\u00ebn besproken waarop blockchains zijn gebaseerd (Wat ons blockchain kost.","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/blokchejn-chto-nam-stoit-poc-postroit","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","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\/nl\/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\/nl\/wp-json\/wp\/v2\/posts\/37868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=37868"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/37868\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/28421"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=37868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=37868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=37868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}