Blockchain: koji PoC trebamo izgraditi?

Oči te se boje i ruke te svrbe!

U prethodnim člancima bavili smo se tehnologijama na kojima se grade blockchaini (Što bismo trebali izgraditi blockchain?) i slučajevima koji se uz njihovu pomoć mogu implementirati (Zašto bismo trebali izgraditi slučaj?). Vrijeme je za rad sa svojim rukama! Za implementaciju pilota i PoC (Proof of Concept), radije koristim oblake, jer... može im se pristupiti s bilo kojeg mjesta na svijetu i, često, nema potrebe gubiti vrijeme na zamornu instalaciju okruženja, jer Postoje unaprijed postavljene konfiguracije. Dakle, napravimo nešto jednostavno, na primjer, mrežu za prijenos kovanica između sudionika i nazovimo to skromno Bitcoin. Za to ćemo koristiti IBM oblak i univerzalni blockchain Hyperledger Fabric. Prvo, shvatimo zašto se Hyperledger Fabric naziva univerzalnim blockchainom?

Blockchain: koji PoC trebamo izgraditi?

Hyperledger Fabric - univerzalni blockchain

Općenito govoreći, univerzalni informacijski sustav je:

  • Skup poslužitelja i programske jezgre koja izvodi poslovnu logiku;
  • Sučelja za interakciju sa sustavom;
  • Alati za registraciju, autentifikaciju i autorizaciju uređaja/ljudi;
  • Baza podataka koja pohranjuje operativne i arhivske podatke:

Blockchain: koji PoC trebamo izgraditi?

Službena verzija o tome što je Hyperledger Fabric može se pročitati na Online, i ukratko, Hyperledger Fabric je opensource platforma koja vam omogućuje izgradnju privatnih blockchaina i izvršavanje proizvoljnih pametnih ugovora napisanih u JS i Go programskim jezicima. Pogledajmo detaljno arhitekturu Hyperledger Fabrica i uvjerimo se da je riječ o univerzalnom sustavu koji ima samo specifičnosti za pohranu i snimanje podataka. Specifičnost je u tome što se podaci, kao i u svim blockchainovima, pohranjuju u blokove koji se postavljaju na blockchain samo ako sudionici postignu konsenzus te se nakon snimanja podaci ne mogu tiho ispravljati ili brisati.

Hyperledger Fabric Arhitektura

Dijagram prikazuje arhitekturu Hyperledger Fabric:

Blockchain: koji PoC trebamo izgraditi?

Organizacije — organizacije sadrže vršnjake, tj. blockchain postoji zahvaljujući podršci organizacija. Različite organizacije mogu biti dio istog kanala.

Kanal — logična struktura koja spaja vršnjake u grupe, tj. naveden je blockchain. Hyperledger Fabric može istovremeno obrađivati ​​više blockchaina s različitom poslovnom logikom.

Davatelj usluga za članstvo (MSP) je CA (Certificate Authority) za izdavanje identiteta i dodjelu uloga. Da biste stvorili čvor, morate komunicirati s MSP-om.

Ravnopravni čvorovi — provjeravati transakcije, pohranjivati ​​blockchain, izvršavati pametne ugovore i komunicirati s aplikacijama. Peers imaju identitet (digitalni certifikat) koji izdaje MSP. Za razliku od Bitcoin ili Etherium mreže, gdje svi čvorovi imaju jednaka prava, u Hyperledger Fabricu čvorovi imaju različite uloge:

  • Peer možda endorsing peer (EP) i izvršavati pametne ugovore.
  • Upućivanje vršnjaka (CP) - samo sprema podatke u blockchain i ažurira "Svjetsko stanje".
  • Sidro Peer (AP) - ako nekoliko organizacija sudjeluje u blockchainu, tada se za komunikaciju između njih koriste sidreni peeri. Svaka organizacija mora imati jednog ili više usidrenih kolega. Koristeći AP, bilo koji kolega u organizaciji može dobiti informacije o svim kolegama u drugim organizacijama. Koristi se za sinkronizaciju informacija između AP-ova protokol tračanja.
  • Voditelj Peer — ako organizacija ima nekoliko peer-ova, tada će samo vođa peer-a primiti blokove od usluge naručivanja i dati ih ostalim peer-ovima. Vođu mogu odrediti statički ili dinamički odabrati kolege u organizaciji. Protokol ogovaranja također se koristi za sinkronizaciju informacija o vođama.

Imovina — entiteti koji imaju vrijednost i pohranjeni su na blockchainu. Točnije, ovo su podaci ključ-vrijednost u JSON formatu. Upravo se ti podaci bilježe u Blockchainu. Imaju povijest, koja je pohranjena u blockchainu, i trenutno stanje, koje je pohranjeno u bazi podataka "Svjetsko stanje". Strukture podataka popunjavaju se proizvoljno ovisno o poslovnim zadacima. Nema obaveznih polja, jedina preporuka je da imovina mora imati vlasnika i biti vrijedna.

Glavna knjiga — sastoji se od Blockchaina i Word stanja baze podataka, koja pohranjuje trenutno stanje imovine. Svjetska država koristi LevelDB ili CouchDB.

Pametan ugovor — pomoću pametnih ugovora implementira se poslovna logika sustava. U Hyperledger Fabricu, pametni ugovori se nazivaju lančani kod. Pomoću lančanog koda specificiraju se sredstva i transakcije preko njih. U tehničkom smislu, pametni ugovori su softverski moduli implementirani u JS ili Go programskim jezicima.

Politika odobravanja — za svaki lančani kod možete postaviti politiku o tome koliko potvrda za transakciju treba očekivati ​​i od koga. Ako pravilo nije postavljeno, zadana je vrijednost: "transakciju mora potvrditi bilo koji član bilo koje organizacije na kanalu." Primjeri pravila:

  • Transakciju mora odobriti bilo koji administrator organizacije;
  • Mora biti potvrđen od bilo kojeg člana ili klijenta organizacije;
  • Mora biti potvrđeno od bilo koje srodne organizacije.

Usluga naručivanja — pakira transakcije u blokove i šalje ih ravnopravnim korisnicima u kanalu. Jamči isporuku poruka svim peerovima na mreži. Koristi se za industrijske sustave Kafka posrednik poruka, za razvoj i testiranje samo.

CallFlow

Blockchain: koji PoC trebamo izgraditi?

  • Aplikacija komunicira s Hyperledger Fabricom koristeći Go, Node.js ili Java SDK;
  • Klijent kreira tx transakciju i šalje je istovrsnim suradnicima;
  • Peer provjerava potpis klijenta, dovršava transakciju i šalje potpis potvrde natrag klijentu. Chaincode se izvršava samo na ravnopravnom uređaju koji podržava, a rezultat njegovog izvođenja šalje se svim ravnopravnim korisnicima. Ovaj algoritam rada naziva se PBFT (Practical Byzantine Fault Tolerant) konsenzus. Razlikuje se od klasični BFT činjenica da je poruka poslana i da se potvrda ne očekuje od svih sudionika, već samo od određenog skupa;
  • Nakon što klijent primi broj odgovora koji odgovara politici indosamenta, on šalje transakciju Službi za naručivanje;
  • Usluga naručivanja generira blok i šalje ga svim vršnjacima koji predaju. Usluga naručivanja osigurava sekvencijalno snimanje blokova, što eliminira tzv.pogledajte odjeljak "Vilice");
  • Peers primaju blok, ponovno provjeravaju politiku odobravanja, upisuju blok u blockchain i mijenjaju stanje u DB-u "Svjetsko stanje".

Oni. To rezultira podjelom uloga između čvorova. To osigurava da je blockchain skalabilan i siguran:

  • Pametni ugovori (chaincode) obavljaju potvrđivanje ravnopravnih partnera. Time se osigurava povjerljivost pametnih ugovora, jer ne pohranjuju ga svi sudionici, već samo suglasnici.
  • Naručivanje bi trebalo raditi brzo. To je osigurano činjenicom da Ordering samo formira blok i šalje ga fiksnom skupu vodećih peera.
  • Povjerljivi peeri samo pohranjuju blockchain - može ih biti mnogo i ne zahtijevaju puno snage i trenutni rad.

Više detalja o arhitektonskim rješenjima Hyperledger Fabrica i zašto funkcionira na ovaj način, a ne drugačije možete pronaći ovdje: Porijeklo arhitekture ili ovdje: Hyperledger Fabric: Distribuirani operativni sustav za dopuštene blokovske lance.

Dakle, Hyperledger Fabric je uistinu univerzalni sustav s kojim možete:

  • Implementirajte proizvoljnu poslovnu logiku pomoću mehanizma pametnih ugovora;
  • Snimanje i primanje podataka iz blockchain baze podataka u JSON formatu;
  • Odobrite i potvrdite API pristup pomoću Izdavača certifikata.

Sada kada malo razumijemo specifičnosti Hyperledger Fabrica, učinimo konačno nešto korisno!

Uvođenje blockchaina

Formuliranje problema

Zadatak je implementirati Citcoin mrežu sa sljedećim funkcijama: stvoriti račun, dobiti stanje, nadopuniti svoj račun, prebaciti novčiće s jednog računa na drugi. Nacrtajmo objektni model koji ćemo dalje implementirati u pametni ugovor. Dakle, imat ćemo račune koji su identificirani imenima i sadrže stanje i popis računa. Računi i popis računa su, u smislu imovine Hyperledger Fabric. Sukladno tome, imaju povijest i trenutno stanje. Pokušat ću ovo jasno nacrtati:

Blockchain: koji PoC trebamo izgraditi?

Gornje brojke su trenutno stanje, koje je pohranjeno u bazi podataka "Svjetsko stanje". Ispod njih su brojke koje pokazuju povijest koja je pohranjena u blockchainu. Sadašnje stanje imovine mijenja se transakcijama. Imovina se mijenja samo u cjelini, tako da kao rezultat transakcije nastaje novi objekt, a trenutna vrijednost imovine ide u povijest.

IBM Cloud

Izrađujemo račun u IBM oblak. Za korištenje blockchain platforme mora se nadograditi na Pay-As-You-Go. Ovaj proces možda neće biti brz jer... IBM zahtijeva dodatne informacije i ručno ih provjerava. S pozitivne strane, mogu reći da IBM ima dobre materijale za obuku koji vam omogućuju da postavite Hyperledger Fabric u njihov oblak. Svidio mi se sljedeći niz članaka i primjera:

Slijede snimke zaslona IBM Blockchain platforme. Ovo nije uputa o tome kako stvoriti blockchain, već jednostavno demonstracija opsega zadatka. Dakle, za naše potrebe, mi pravimo jednu organizaciju:

Blockchain: koji PoC trebamo izgraditi?

U njemu stvaramo čvorove: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: koji PoC trebamo izgraditi?

Mi stvaramo korisnike:

Blockchain: koji PoC trebamo izgraditi?

Napravite kanal i nazovite ga citcoin:

Blockchain: koji PoC trebamo izgraditi?

U biti Channel je blockchain, tako da počinje s nultim blokom (Genesis blok):

Blockchain: koji PoC trebamo izgraditi?

Pisanje pametnog ugovora

/*
 * 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;

Intuitivno, ovdje bi sve trebalo biti jasno:

  • Postoji nekoliko funkcija (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) koje će demo program pozvati pomoću Hyperledger Fabric API-ja.
  • Funkcije SendFrom i RefillBalance generiraju događaje koje demo program prima.
  • Funkcija instanciranja poziva se jednom kada se instancira pametni ugovor. Zapravo, ne poziva se samo jednom, već svaki put kada se promijeni verzija pametnog ugovora. Stoga je inicijaliziranje liste s praznim nizom loša ideja, jer Sada, kada promijenimo verziju pametnog ugovora, izgubit ćemo trenutni popis. Ali u redu je, tek učim).
  • Računi i popis računa su JSON strukture podataka. JS se koristi za manipulaciju podacima.
  • Možete dobiti trenutnu vrijednost imovine pomoću poziva funkcije getState i ažurirati je pomoću putState.
  • Prilikom kreiranja računa poziva se funkcija AddAccount u kojoj se vrši usporedba maksimalnog broja računa u blockchainu (maxAccounts = 5). I ovdje postoji zastoj (jeste li primijetili?), koji dovodi do beskrajnog povećanja broja računa. Takve se greške moraju izbjegavati)

Zatim učitavamo pametni ugovor u kanal i instanciramo ga:

Blockchain: koji PoC trebamo izgraditi?

Pogledajmo transakciju za instaliranje pametnog ugovora:

Blockchain: koji PoC trebamo izgraditi?

Pogledajmo detalje o našem kanalu:

Blockchain: koji PoC trebamo izgraditi?

Kao rezultat toga, dobivamo sljedeći dijagram blockchain mreže u IBM oblaku. Dijagram također prikazuje demo program koji radi u Amazonovom oblaku na virtualnom poslužitelju (više o tome u sljedećem odjeljku):

Blockchain: koji PoC trebamo izgraditi?

Stvaranje GUI-ja za Hyperledger Fabric API pozive

Hyperledger Fabric ima API koji se može koristiti za:

  • Stvorite kanal;
  • Veze peer to channel;
  • Instalacija i instanciranje pametnih ugovora u kanalu;
  • Transakcije poziva;
  • Zatražite informacije o blockchainu.

Razvoj aplikacija

U našem demo programu koristit ćemo API samo za pozivanje transakcija i traženje informacija, jer Već smo dovršili preostale korake koristeći IBM blockchain platformu. Pišemo GUI koristeći standardni tehnološki skup: Express.js + Vue.js + Node.js. Možete napisati poseban članak o tome kako započeti s izradom modernih web aplikacija. Ovdje ću ostaviti poveznicu na ciklus predavanja koji mi se najviše svidio: Web-aplikacija Full Stack koja koristi Vue.js i Express.js. Rezultat je klijent-poslužitelj aplikacija s poznatim grafičkim sučeljem u Googleovom stilu Material Design. REST API između klijenta i poslužitelja sastoji se od nekoliko poziva:

  • HyperledgerDemo/v1/init - inicijalizirajte blockchain;
  • HyperledgerDemo/v1/accounts/list — dobijte popis svih računa;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — kreirajte Bob račun;
  • HyperledgerDemo/v1/info?account=Bob — dobivanje informacija o Bob računu;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — prijenos dva novčića od Boba do Alice;
  • HyperledgerDemo/v1/disconnect - zatvorite vezu s blockchainom.

Opis API-ja s uključenim primjerima Web stranica poštara - dobro poznati program za testiranje HTTP API-ja.

Demo aplikacija u Amazon oblaku

Učitao sam aplikaciju na Amazon jer... IBM još uvijek nije uspio nadograditi moj račun i omogućiti mi stvaranje virtualnih poslužitelja. Kako dodati trešnju na domenu: www.citcoin.info. Ostavit ću poslužitelj uključenim neko vrijeme, a zatim ga isključiti, jer... centi za najam kapaju, a citcoin kovanice još nisu uvrštene na burzu) Uključujem screenshotove demo u članak tako da je logika rada jasna. Demo aplikacija može:

  • Inicijalizirajte blockchain;
  • Napravite račun (ali sada ne možete stvoriti novi račun jer je maksimalni broj računa navedenih u pametnom ugovoru dosegnut u blockchainu);
  • Primite popis računa;
  • Prijenos citcoin kovanica između Alice, Boba i Alexa;
  • Primanje događaja (ali sada ne postoji način za prikazivanje događaja, pa radi jednostavnosti, sučelje kaže da događaji nisu podržani);
  • Dnevnik radnji.

Prvo inicijaliziramo blockchain:

Blockchain: koji PoC trebamo izgraditi?

Zatim kreiramo svoj račun, ne gubimo vrijeme sa stanjem:

Blockchain: koji PoC trebamo izgraditi?

Dobivamo popis svih dostupnih računa:

Blockchain: koji PoC trebamo izgraditi?

Odabiremo pošiljatelja i primatelja i dobivamo njihova stanja. Ako su pošiljatelj i primatelj isti, tada će se njegov račun nadopuniti:

Blockchain: koji PoC trebamo izgraditi?

U dnevniku pratimo izvršenje transakcija:

Blockchain: koji PoC trebamo izgraditi?

Zapravo, to je sve s demo programom. Ispod možete vidjeti našu transakciju u blockchainu:

Blockchain: koji PoC trebamo izgraditi?

I opći popis transakcija:

Blockchain: koji PoC trebamo izgraditi?

Time smo uspješno dovršili implementaciju PoC-a za stvaranje Citcoin mreže. Što još treba učiniti da Citcoin postane punopravna mreža za prijenos kovanica? Jako malo:

  • U fazi kreiranja računa implementirajte generiranje privatnog / javnog ključa. Privatni ključ mora biti pohranjen kod korisnika računa, javni ključ mora biti pohranjen u blockchainu.
  • Napravite prijenos novčića u kojem se za identifikaciju korisnika koristi javni ključ, a ne ime.
  • Šifrirajte transakcije koje idu od korisnika do poslužitelja njegovim privatnim ključem.

Zaključak

Implementirali smo Citcoin mrežu sa sljedećim funkcijama: dodavanje računa, dobivanje stanja, dopuna računa, prijenos kovanica s jednog računa na drugi. Dakle, koliko nas je koštalo da izgradimo PoC?

  • Morate proučavati blockchain općenito, a posebno Hyperledger Fabric;
  • Naučite koristiti IBM ili Amazon oblake;
  • Naučite JS programski jezik i neki web framework;
  • Ako neke podatke treba pohraniti ne u blockchainu, već u zasebnoj bazi podataka, naučite se integrirati, na primjer, s PostgreSQL;
  • I na kraju, ali ne manje važno - ne možete živjeti u modernom svijetu bez znanja o Linuxu!)

Naravno, to nije raketna znanost, ali morat ćete se potruditi!

Izvori na GitHubu

Izvori stavljeni na GitHub. Kratak opis repozitorija:
Katalog «server» — Node.js poslužitelj
Katalog «klijent» — Node.js klijent
Katalog «blockchain"(vrijednosti parametara i ključevi, naravno, ne rade i dani su samo kao primjer):

  • ugovor — izvorni kod pametnog ugovora
  • wallet — korisnički ključevi za korištenje Hyperledger Fabric API-ja.
  • *.cds - kompajlirane verzije pametnih ugovora
  • *.json datoteke - primjeri konfiguracijskih datoteka za korištenje Hyperledger Fabric API-ja

To je tek početak!

Izvor: www.habr.com

Dodajte komentar