Blockchain: welke PoC moeten we bouwen?

Je ogen zijn bang en je handen jeuken!

In eerdere artikelen hebben we de technologieën behandeld waarop blockchains zijn gebouwd (Wat moeten we een blockchain bouwen?) en cases die met hun hulp kunnen worden geïmplementeerd (Waarom zouden we een zaak opbouwen?). Het is tijd om met je handen te werken! Voor het uitvoeren van pilots en PoC (Proof of Concept) maak ik het liefst gebruik van de cloud, omdat... ze zijn overal ter wereld toegankelijk en vaak is het niet nodig om tijd te verspillen aan de vervelende installatie van de omgeving, omdat Er zijn vooraf ingestelde configuraties. Laten we dus iets eenvoudigs maken, bijvoorbeeld een netwerk voor het overbrengen van munten tussen deelnemers, en laten we het bescheiden Bitcoin noemen. Hiervoor zullen we gebruik maken van de IBM cloud en de universele blockchain Hyperledger Fabric. Laten we eerst eens kijken waarom Hyperledger Fabric een universele blockchain wordt genoemd?

Blockchain: welke PoC moeten we bouwen?

Hyperledger Fabric - een universele blockchain

Over het algemeen is een universeel informatiesysteem:

  • Een set servers en een softwarekern die bedrijfslogica uitvoert;
  • Interfaces voor interactie met het systeem;
  • Tools voor registratie, authenticatie en autorisatie van apparaten/personen;
  • Database met operationele en archiefgegevens:

Blockchain: welke PoC moeten we bouwen?

De officiële versie van wat Hyperledger Fabric is, kun je lezen op Online, en kort gezegd is Hyperledger Fabric een opensourceplatform waarmee je privéblockchains kunt bouwen en willekeurige slimme contracten kunt uitvoeren die zijn geschreven in de programmeertalen JS en Go. Laten we de architectuur van Hyperledger Fabric in detail bekijken en ervoor zorgen dat dit een universeel systeem is dat alleen specifieke kenmerken heeft voor het opslaan en vastleggen van gegevens. Het specifieke is dat de gegevens, zoals bij alle blockchains, worden opgeslagen in blokken die alleen op de blockchain worden geplaatst als de deelnemers een consensus bereiken en na het vastleggen kunnen de gegevens niet stilletjes worden gecorrigeerd of verwijderd.

Hyperledger Fabric-architectuur

Het diagram toont de Hyperledger Fabric-architectuur:

Blockchain: welke PoC moeten we bouwen?

organisaties — organisaties bevatten peers, d.w.z. blockchain bestaat dankzij de steun van organisaties. Verschillende organisaties kunnen deel uitmaken van hetzelfde kanaal.

Kanaal — een logische structuur die gelijken in groepen verenigt, d.w.z. de blockchain is gespecificeerd. Hyperledger Fabric kan tegelijkertijd meerdere blockchains met verschillende bedrijfslogica verwerken.

Lidmaatschapsdienstverlener (MSP) is een CA (Certificate Authority) voor het uitgeven van identiteit en het toewijzen van rollen. Om een ​​knooppunt te maken, moet u communiceren met de MSP.

Peer-knooppunten — transacties verifiëren, de blockchain opslaan, slimme contracten uitvoeren en communiceren met applicaties. Peers hebben een identiteit (digitaal certificaat), die wordt uitgegeven door de MSP. In tegenstelling tot het Bitcoin- of Etherium-netwerk, waar alle knooppunten gelijke rechten hebben, spelen knooppunten in Hyperledger Fabric verschillende rollen:

  • Peer misschien peer onderschrijven (EP) en slimme contracten uitvoeren.
  • Collega plegen (CP) - sla alleen gegevens op in de blockchain en update de “Wereldstaat”.
  • Anker Peer (AP) - als meerdere organisaties deelnemen aan de blockchain, worden ankerpeers gebruikt voor de onderlinge communicatie. Elke organisatie moet een of meer anker-peers hebben. Met behulp van AP kan elke peer in een organisatie informatie verkrijgen over alle peers in andere organisaties. Wordt gebruikt om informatie tussen toegangspunten te synchroniseren roddelprotocol.
  • Leider Peer — als een organisatie meerdere peers heeft, ontvangt alleen de leider van de peer blokken van de besteldienst en geeft deze aan de rest van de peers. De leider kan statisch worden gespecificeerd of dynamisch worden geselecteerd door collega's in de organisatie. Het roddelprotocol wordt ook gebruikt om informatie over leiders te synchroniseren.

Activa — entiteiten die waarde hebben en op de blockchain zijn opgeslagen. Meer specifiek zijn dit sleutelwaardegegevens in JSON-indeling. Het zijn deze gegevens die worden vastgelegd in de Blockchain. Ze hebben een geschiedenis, die is opgeslagen in de blockchain, en een huidige staat, die is opgeslagen in de ‘Wereldstaat’-database. Datastructuren worden willekeurig gevuld, afhankelijk van zakelijke taken. Er zijn geen verplichte velden, de enige aanbeveling is dat activa een eigenaar moeten hebben en waardevol moeten zijn.

Grootboek – bestaat uit de Blockchain- en de Word-statusdatabase, die de huidige status van activa opslaat. Wereldstaat gebruikt LevelDB of CouchDB.

Slim contract — met behulp van slimme contracten wordt de bedrijfslogica van het systeem geïmplementeerd. In Hyperledger Fabric worden slimme contracten chaincode genoemd. Met behulp van chaincode worden activa en transacties daarover gespecificeerd. In technische termen zijn slimme contracten softwaremodules die zijn geïmplementeerd in de programmeertalen JS of Go.

Goedkeuringsbeleid — voor elke chaincode kunt u een beleid instellen over hoeveel bevestigingen voor een transactie u mag verwachten en van wie. Als het beleid niet is ingesteld, is de standaardinstelling: “de transactie moet worden bevestigd door elk lid van een organisatie in het kanaal.” Voorbeelden van beleid:

  • De transactie moet worden goedgekeurd door elke beheerder van de organisatie;
  • Moet worden bevestigd door een lid of klant van de organisatie;
  • Moet worden bevestigd door een soortgelijke organisatie.

Bestelservice — verpakt transacties in blokken en stuurt deze naar peers in het kanaal. Garandeert de bezorging van berichten aan alle peers op het netwerk. Gebruikt voor industriële systemen Kafka-berichtenmakelaar, voor ontwikkeling en testen Solo.

BelFlow

Blockchain: welke PoC moeten we bouwen?

  • De applicatie communiceert met Hyperledger Fabric via Go, Node.js of Java SDK;
  • De client maakt een tx-transactie aan en stuurt deze naar onderschrijvende collega's;
  • De Peer verifieert de handtekening van de klant, voltooit de transactie en stuurt de handtekening ter goedkeuring terug naar de klant. Chaincode wordt alleen uitgevoerd op de onderschrijvende peer en het resultaat van de uitvoering ervan wordt naar alle peers verzonden. Dit werkalgoritme wordt PBFT-consensus (Practical Byzantine Fault Tolerant) genoemd. Is anders dan klassieke BFT het feit dat het bericht wordt verzonden en dat er niet van alle deelnemers een bevestiging wordt verwacht, maar alleen van een bepaalde groep;
  • Nadat de klant het aantal reacties heeft ontvangen dat overeenkomt met het goedkeuringsbeleid, stuurt hij de transactie naar de Besteldienst;
  • De Ordering-service genereert een blok en verzendt dit naar alle commiterende peers. De bestelservice zorgt voor een sequentiële registratie van blokken, waardoor de zogenaamde grootboekvork wordt geëlimineerd (zie paragraaf "Vorken");
  • Peers ontvangen een blok, controleren het goedkeuringsbeleid opnieuw, schrijven het blok naar de blockchain en wijzigen de status in de ‘Wereldstaat’ DB.

Die. Dit resulteert in een rolverdeling tussen de knooppunten. Dit zorgt ervoor dat de blockchain schaalbaar en veilig is:

  • Slimme contracten (chaincode) voeren peers uit. Dit garandeert de vertrouwelijkheid van slimme contracten, omdat het wordt niet door alle deelnemers opgeslagen, maar alleen door peers te onderschrijven.
  • Bestellen zou snel moeten werken. Dit wordt verzekerd door het feit dat Ordering slechts een blok vormt en dit naar een vaste groep leider-peers stuurt.
  • Vastleggende peers slaan alleen de blockchain op - er kunnen er veel zijn en ze vereisen niet veel kracht en onmiddellijke werking.

Meer details over de architectonische oplossingen van Hyperledger Fabric en waarom het op deze manier werkt en niet anders, vindt u hier: Architectuur oorsprong of hier: Hyperledger Fabric: een gedistribueerd besturingssysteem voor toegestane blockchains.

Hyperledger Fabric is dus een echt universeel systeem waarmee u:

  • Implementeer willekeurige bedrijfslogica met behulp van het slimme contractmechanisme;
  • Registreer en ontvang gegevens uit de blockchain-database in JSON-formaat;
  • Verleen en verifieer API-toegang met behulp van de certificeringsinstantie.

Nu we iets meer weten over de specifieke kenmerken van Hyperledger Fabric, gaan we eindelijk iets nuttigs doen!

Blockchain implementeren

Formulering van het probleem

De taak is om het Citcoin-netwerk te implementeren met de volgende functies: een account aanmaken, saldo opvragen, uw account aanvullen, munten overboeken van de ene account naar de andere. Laten we een objectmodel tekenen, dat we verder zullen implementeren in een slim contract. We zullen dus rekeningen hebben die met hun naam worden geïdentificeerd en die een saldo bevatten, en een lijst met rekeningen. Accounts en een lijst met accounts zijn, in termen van Hyperledger Fabric-middelen. Dienovereenkomstig hebben ze een geschiedenis en een huidige staat. Ik zal proberen dit duidelijk te tekenen:

Blockchain: welke PoC moeten we bouwen?

De bovenste cijfers zijn de huidige toestand, die is opgeslagen in de database “Wereldstaat”. Daaronder staan ​​figuren die de geschiedenis laten zien die in de blockchain is opgeslagen. De huidige staat van de activa wordt gewijzigd door transacties. Het activum verandert alleen als geheel, dus als gevolg van de transactie wordt een nieuw object gecreëerd en gaat de huidige waarde van het activum de geschiedenis in.

IBM-wolk

Wij maken een account aan IBM-wolk. Om het blockchain-platform te kunnen gebruiken, moet het worden geüpgraded naar Pay-As-You-Go. Dit proces is misschien niet snel, omdat... IBM vraagt ​​om aanvullende informatie en verifieert deze handmatig. Positief kan ik zeggen dat IBM goed trainingsmateriaal heeft waarmee je Hyperledger Fabric in hun cloud kunt implementeren. Ik vond de volgende reeks artikelen en voorbeelden leuk:

Hieronder volgen schermafbeeldingen van het IBM Blockchain-platform. Dit is geen instructie over het maken van een blockchain, maar eenvoudigweg een demonstratie van de omvang van de taak. Dus voor onze doeleinden maken we één organisatie:

Blockchain: welke PoC moeten we bouwen?

We maken er knooppunten in: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: welke PoC moeten we bouwen?

Wij creëren gebruikers:

Blockchain: welke PoC moeten we bouwen?

Maak een kanaal en noem het Citcoin:

Blockchain: welke PoC moeten we bouwen?

In wezen is Channel een blockchain, dus het begint met blok nul (Genesis-blok):

Blockchain: welke PoC moeten we bouwen?

Een slim contract schrijven

/*
 * Citcoin smart-contract v1.5 for Hyperledger Fabric
 * (c) Alexey Sushkov, 2019
 */
 
'use strict';
 
const { Contract } = require('fabric-contract-api');
const maxAccounts = 5;
 
class CitcoinEvents extends Contract {
 
    async instantiate(ctx) {
        console.info('instantiate');
        let emptyList = [];
        await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList)));
    }
    // Get all accounts
    async GetAccounts(ctx) {
        // Get account list:
        let accounts = '{}'
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            accounts = JSON.parse(accountsData.toString());
        } else {
            throw new Error('accounts not found');
        }
        return accountsData.toString()
    }
     // add a account object to the blockchain state identifited by their name
    async AddAccount(ctx, name, balance) {
        // this is account data:
        let account = {
            name: name,
            balance: Number(balance),       
            type: 'account',
        };
        // create account:
        await ctx.stub.putState(name, Buffer.from(JSON.stringify(account)));
 
        // Add account to list:
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            let accounts = JSON.parse(accountsData.toString());
            if (accounts.length < maxAccounts)
            {
                accounts.push(name);
                await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts)));
            } else {
                throw new Error('Max accounts number reached');
            }
        } else {
            throw new Error('accounts not found');
        }
        // return  object
        return JSON.stringify(account);
    }
    // Sends money from Account to Account
    async SendFrom(ctx, fromAccount, toAccount, value) {
        // get Account from
        let fromData = await ctx.stub.getState(fromAccount);
        let from;
        if (fromData) {
            from = JSON.parse(fromData.toString());
            if (from.type !== 'account') {
                throw new Error('wrong from type');
            }   
        } else {
            throw new Error('Accout from not found');
        }
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balances
        if ((from.balance - Number(value)) >= 0 ) {
            from.balance -= Number(value);
            to.balance += Number(value);
        } else {
            throw new Error('From Account: not enought balance');          
        }
 
        await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from)));
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "SendFrom",
            from: from.name,
            to: to.name,
            balanceFrom: from.balance,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
 
    // get the state from key
    async GetState(ctx, key) {
        let data = await ctx.stub.getState(key);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
    // GetBalance   
    async GetBalance(ctx, accountName) {
        let data = await ctx.stub.getState(accountName);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
     
    // Refill own balance
    async RefillBalance(ctx, toAccount, value) {
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balance
        to.balance += Number(value);
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "RefillBalance",
            to: to.name,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
}
module.exports = CitcoinEvents;

Intuïtief zou alles hier duidelijk moeten zijn:

  • Er zijn verschillende functies (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) die het demoprogramma zal aanroepen met behulp van de Hyperledger Fabric API.
  • De functies SendFrom en RefillBalance genereren gebeurtenissen die het demoprogramma zal ontvangen.
  • De instantiatiefunctie wordt één keer aangeroepen wanneer een slim contract wordt geïnstantieerd. In feite wordt het niet slechts één keer genoemd, maar elke keer dat de slimme contractversie verandert. Daarom is het initialiseren van een lijst met een lege array een slecht idee, omdat Als we nu de versie van het slimme contract wijzigen, verliezen we de huidige lijst. Maar het is oké, ik leer alleen maar).
  • Accounts en een lijst met accounts zijn JSON-gegevensstructuren. JS wordt gebruikt voor gegevensmanipulatie.
  • U kunt de huidige waarde van een asset verkrijgen met behulp van de functieaanroep getState, en deze bijwerken met putState.
  • Bij het aanmaken van een Account wordt de functie AddAccount aangeroepen, waarbij een vergelijking wordt gemaakt voor het maximale aantal accounts in de blockchain (maxAccounts = 5). En hier is er een stijl (is het je opgevallen?), wat leidt tot een eindeloze toename van het aantal accounts. Dergelijke fouten moeten worden vermeden)

Vervolgens laden we het slimme contract in het kanaal en instantiëren we het:

Blockchain: welke PoC moeten we bouwen?

Laten we eens kijken naar de transactie voor het installeren van Smart Contract:

Blockchain: welke PoC moeten we bouwen?

Laten we eens kijken naar de details van ons kanaal:

Blockchain: welke PoC moeten we bouwen?

Als resultaat krijgen we het volgende diagram van een blockchain-netwerk in de IBM-cloud. Het diagram toont ook een demoprogramma dat draait in de Amazon-cloud op een virtuele server (meer hierover in de volgende sectie):

Blockchain: welke PoC moeten we bouwen?

Een GUI maken voor Hyperledger Fabric API-aanroepen

Hyperledger Fabric heeft een API die kan worden gebruikt om:

  • Kanaal maken;
  • Verbindingen peer-to-channel;
  • Installatie en instantiëring van slimme contracten in het kanaal;
  • Beltransacties;
  • Vraag informatie op over de blockchain.

Applicatie ontwikkeling

In ons demoprogramma gebruiken we de API alleen om transacties op te roepen en informatie op te vragen, omdat We hebben de resterende stappen al voltooid met behulp van het IBM blockchain-platform. We schrijven een GUI met behulp van een standaard technologiestack: Express.js + Vue.js + Node.js. U kunt een apart artikel schrijven over hoe u kunt beginnen met het maken van moderne webapplicaties. Hier laat ik een link achter naar de serie lezingen die ik het leukst vond: Full-stack webapp met Vue.js en Express.js. Het resultaat is een client-serverapplicatie met een vertrouwde grafische interface in de Material Design-stijl van Google. De REST API tussen client en server bestaat uit verschillende oproepen:

  • HyperledgerDemo/v1/init - initialiseer de blockchain;
  • HyperledgerDemo/v1/accounts/list — krijg een lijst met alle accounts;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — maak een Bob-account aan;
  • HyperledgerDemo/v1/info?account=Bob — krijg informatie over Bob-account;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — breng twee munten over van Bob naar Alice;
  • HyperledgerDemo/v1/disconnect - sluit de verbinding met de blockchain.

Beschrijving van de API met voorbeelden opgenomen in Website van de postbode - een bekend programma voor het testen van HTTP API.

Demo-applicatie in de Amazon-cloud

Ik heb de applicatie naar Amazon geüpload omdat... IBM heeft mijn account nog steeds niet kunnen upgraden en mij toestemming gegeven om virtuele servers te maken. Hoe een kers aan het domein toe te voegen: www.citcoin.info. Ik laat de server een tijdje aanstaan ​​en zet hem dan uit, want... centen voor huur druppelen, en citcoin-munten zijn nog niet genoteerd op de beurs) Ik neem screenshots van de demo op in het artikel zodat de logica van het werk duidelijk is. De demo-applicatie kan:

  • Initialiseer de blockchain;
  • Maak een account aan (maar nu kunt u geen nieuw account aanmaken, omdat het maximale aantal accounts gespecificeerd in het slimme contract in de blockchain is bereikt);
  • Ontvang een lijst met accounts;
  • Citcoin-munten overdragen tussen Alice, Bob en Alex;
  • Gebeurtenissen ontvangen (maar nu is er geen manier om gebeurtenissen weer te geven, dus voor de eenvoud zegt de interface dat gebeurtenissen niet worden ondersteund);
  • Log acties.

Eerst initialiseren we de blockchain:

Blockchain: welke PoC moeten we bouwen?

Vervolgens maken we ons account aan, verspil geen tijd met het saldo:

Blockchain: welke PoC moeten we bouwen?

We krijgen een lijst met alle beschikbare accounts:

Blockchain: welke PoC moeten we bouwen?

We selecteren de afzender en de ontvanger en ontvangen hun saldo. Als de afzender en de ontvanger hetzelfde zijn, wordt zijn account aangevuld:

Blockchain: welke PoC moeten we bouwen?

In het log monitoren wij de uitvoering van transacties:

Blockchain: welke PoC moeten we bouwen?

Eigenlijk is dat alles met het demoprogramma. Hieronder ziet u onze transactie in de blockchain:

Blockchain: welke PoC moeten we bouwen?

En de algemene lijst met transacties:

Blockchain: welke PoC moeten we bouwen?

Hiermee hebben we met succes de implementatie van de PoC afgerond om het Citcoin-netwerk te creëren. Wat moet er nog meer gebeuren voordat Citcoin een volwaardig netwerk voor het overbrengen van munten wordt? Zeer weinig:

  • Implementeer in de fase van het aanmaken van een account het genereren van een private/publieke sleutel. De private sleutel moet bij de accountgebruiker worden opgeslagen, de publieke sleutel moet in de blockchain worden opgeslagen.
  • Voer een muntoverdracht uit waarbij een openbare sleutel in plaats van een naam wordt gebruikt om de gebruiker te identificeren.
  • Versleutel transacties die van de gebruiker naar de server gaan met zijn privésleutel.

Conclusie

We hebben het Citcoin-netwerk geïmplementeerd met de volgende functies: een account toevoegen, saldo opvragen, uw account opwaarderen, munten overboeken van de ene account naar de andere. Wat heeft het ons gekost om een ​​PoC te bouwen?

  • Je moet blockchain in het algemeen en Hyperledger Fabric in het bijzonder bestuderen;
  • Leer IBM- of Amazon-clouds te gebruiken;
  • Leer de programmeertaal JS en een webframework;
  • Als sommige gegevens niet in de blockchain maar in een aparte database moeten worden opgeslagen, leer dan hoe je bijvoorbeeld kunt integreren met PostgreSQL;
  • En last but not least: je kunt niet in de moderne wereld leven zonder kennis van Linux!)

Het is natuurlijk geen rocket science, maar je zult hard moeten werken!

сходники а GitHub

Bronnen aangezet GitHub. Korte beschrijving van de repository:
Catalogus «server» — Node.js-server
Catalogus «klant» — Node.js-client
Catalogus «blockchain"(parameterwaarden en sleutels werken uiteraard niet en worden alleen als voorbeeld gegeven):

  • contract – slimme contractbroncode
  • portemonnee — gebruikerssleutels voor het gebruik van de Hyperledger Fabric API.
  • *.cds - gecompileerde versies van slimme contracten
  • *.json-bestanden: voorbeelden van configuratiebestanden voor het gebruik van de Hyperledger Fabric API

Het is nog maar het begin!

Bron: www.habr.com

Voeg een reactie