Blockchain: šta da napravimo PoC?

Oči se boje, a ruke svrbe!

U prethodnim člancima bavili smo se tehnologijama na kojima se grade blokovi (Šta da izgradimo blockchain?) i slučajeve koji se uz njihovu pomoć mogu implementirati (Koliko nas košta izgradnja kućišta?). Vrijeme je da radite svojim rukama! Za implementaciju pilota i PoC (Proof of Concept) radije koristim oblake, jer. imaju pristup s bilo kojeg mjesta u svijetu i, često, nema potrebe trošiti vrijeme na zamornu instalaciju okruženja, jer. Postoje unaprijed postavljene konfiguracije. Dakle, napravimo nešto jednostavno, poput mreže za prijenos kovanica između sudionika i nazovimo to skromno Citcoin. Da bismo to učinili, koristit ćemo IBM oblak i univerzalni blockchain Hyperledger Fabric. Prvo, hajde da shvatimo zašto se Hyperledger Fabric naziva univerzalnim blockchainom?

Blockchain: šta da napravimo PoC?

Hyperledger Fabric - Univerzalni Blockchain

Uopšteno govoreći, univerzalni informacioni sistem je:

  • Skup servera i softversko jezgro koje obavlja poslovnu logiku;
  • Interfejsi za interakciju sa sistemom;
  • Sredstva za registraciju, autentifikaciju i autorizaciju uređaja/osoba;
  • Baza podataka koja pohranjuje operativne i arhivirane podatke:

Blockchain: šta da napravimo PoC?

Zvanična verzija onoga što je Hyperledger Fabric može se pročitati na site, i ukratko, Hyperledger Fabric je platforma otvorenog koda koja vam omogućava izgradnju privatnih blockchaina i izvršavanje proizvoljnih pametnih ugovora napisanih u JS i Go programskim jezicima. Pogledajmo izbliza arhitekturu Hyperledger Fabric i uvjerimo se da je ovo univerzalni sistem koji ima samo specifičnosti za pohranjivanje i snimanje podataka. Specifičnost je u tome što se podaci, kao i u svim blockchainima, pohranjuju u blokove koji se postavljaju u blockchain samo ako su sudionici postigli konsenzus i nakon snimanja podaci se ne mogu tiho ispravljati ili brisati.

Hyperledger Fabric Architecture

Dijagram prikazuje arhitekturu Hyperledger Fabric:

Blockchain: šta da napravimo PoC?

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

kanal - logička struktura koja ujedinjuje vršnjake u grupe, dakle. blockchain je postavljen. Hyperledger Fabric može istovremeno obraditi više blokova sa različitom poslovnom logikom.

Pružalac usluga članstva (MSP) je CA (Certificate Authority) za izdavanje identiteta i dodjelu uloga. Da biste kreirali čvor, morate komunicirati sa MSP-om.

Peer čvorovi — verificirati transakcije, pohraniti blockchain, izvršavati pametne ugovore i komunicirati s aplikacijama. Vršnjaci imaju identitet (digitalni certifikat) koji izdaje MSP. Za razliku od Bitcoin ili Etherium mreže, gdje su svi čvorovi jednaki, čvorovi igraju različite uloge u Hyperledger Fabric-u:

  • Vršnjaci mogu biti podržavajući vršnjak (EP) i izvršavati pametne ugovore.
  • Obvezujući vršnjak (CP) - čuvajte samo podatke u blockchainu i ažurirajte "Stanje svijeta".
  • Anchor Peer (AP) - ako nekoliko organizacija učestvuje u blockchainu, tada se sidreni kolege koriste za komunikaciju između njih. Svaka organizacija mora imati jednog ili više sidrenih kolega. Uz pomoć AP-a, bilo koji kolega u organizaciji može dobiti informacije o svim kolegama u drugim organizacijama. Koristi se za sinhronizaciju informacija između AP-ova. trač protokol.
  • Leader Peer - ako organizacija ima nekoliko vršnjaka, tada će samo vođa vršnjaka primati blokove od usluge naručivanja i dati ih ostalim kolegama. Vođa se može postaviti statički ili dinamički od strane kolega u organizaciji. Gossip protokol se također koristi za sinhronizaciju informacija o vođi.

imovina — entiteti vrijednosti koji su pohranjeni u blockchainu. Preciznije, ovo su podaci ključ/vrijednost u JSON formatu. To su podaci koji se bilježe u Blockchain blockchain. Imaju historiju koja je pohranjena na blockchainu i trenutno stanje koje je pohranjeno u bazi podataka "Stanje svijeta". Strukture podataka se popunjavaju proizvoljno u zavisnosti od poslovnih zadataka. Nema obaveznih polja, jedina preporuka je da imovina mora da ima vlasnika i da ima vrednost.

glavna knjiga - sastoji se od Blockchain blockchaina i Word baze podataka stanja, koja pohranjuje trenutno stanje imovine. Država svijeta koristi LevelDB ili CouchDB.

Pametan ugovor — uz pomoć pametnih ugovora implementirana je poslovna logika sistema. U Hyperledger Fabric, pametni ugovori se nazivaju lančani kod. Uz pomoć lančanog koda specificiraju se sredstva i transakcije nad njima. Tehničkim jezikom, pametni ugovori su softverski moduli implementirani u JS ili Go programskim jezicima.

Politika odobravanja - za svaki lančani kod možete postaviti pravila koliko i od koga trebate očekivati ​​potvrde za transakciju. Ako pravilo nije postavljeno, onda je zadana postavka: "transakciju mora potvrditi bilo koji član bilo koje organizacije na kanalu". Primjeri politike:

  • Transakciju mora potvrditi bilo koji administrator organizacije;
  • Mora biti potvrđen od strane bilo kojeg člana ili klijenta organizacije;
  • Mora potvrditi bilo koji kolega iz organizacije.

Usluga naručivanja - pakuje transakcije u blokove i šalje ih kolegama u kanalu. Osigurava isporuku poruka svim kolegama na mreži. Koristi se za industrijske sisteme Kafka broker poruka, za razvoj i testiranje solo.

protok poziva

Blockchain: šta da napravimo PoC?

  • Aplikacija komunicira sa Hyperledger Fabric koristeći Go, Node.js ili Java SDK;
  • Klijent kreira transakcijski tx i šalje ga kolegama koji podržavaju;
  • Peer provjerava potpis klijenta, završava transakciju i šalje potpis odobrenja nazad klijentu. Chaincode se izvršava samo na ravnopravnom nivou koji ga podržava, a rezultat njegovog izvršenja se šalje svim ravnopravnim jedinicama. Takav algoritam rada naziva se - PBFT (Practical Byzantine Fault Tolerant) konsenzus. Razlikuje se od classic BFT činjenica da se poruka šalje i očekuje se potvrda ne od svih učesnika, već samo od određenog skupa;
  • Nakon što klijent primi broj odgovora koji odgovara politici indosamenta, on šalje transakciju Službi naručivanja;
  • Usluga naručivanja formira blok i šalje ga svim kolegama koji su izvršili urezivanje. Usluga naručivanja osigurava da se blokovi zapisuju sekvencijalno, što eliminira tzv.vidi odjeljak "Viljuške");
  • Peers primaju blok, ponovo provjeravaju politiku odobravanja, upisuju blok u blockchain i mijenjaju stanje u DB-u “Stanje svijeta”.

One. ispostavlja se podjela uloga između čvorova. Ovo osigurava skalabilnost i sigurnost blockchaina:

  • Pametni ugovori (lančani kod) obavljaju potvrđivanje kolega. Ovo osigurava povjerljivost pametnih ugovora, kao ne pohranjuju ga svi učesnici, već samo vršnjaci koji podržavaju.
  • Naručivanje bi trebalo da funkcioniše brzo. Ovo je osigurano činjenicom da Ordering samo formira blok i šalje ga fiksnom skupu vodećih kolega.
  • Posvećeni vršnjaci samo pohranjuju blockchain - može ih biti mnogo i ne zahtijevaju mnogo snage i trenutnog rada.

Više arhitektonskih rješenja Hyperledger Fabric-a i zašto funkcionira na ovaj način, a ne drugačije možete pronaći ovdje: Architecture Origins ili ovdje: Hyperledger Fabric: Distribuirani operativni sistem za dozvoljene blokove.

Dakle, Hyperledger Fabric je zaista univerzalan sistem sa kojim možete:

  • Implementirati proizvoljnu poslovnu logiku koristeći mehanizam pametnog ugovora;
  • Pisanje i primanje podataka iz blockchain baze podataka u JSON formatu;
  • Dodijelite i potvrdite pristup API-ju koristeći ovlaštenje za izdavanje certifikata.

Sada kada smo izbacili malo specifičnosti Hyperledger Fabric-a, hajde da konačno uradimo nešto korisno!

Uvođenje blockchaina

Izjava o problemu

Zadatak je implementirati Citcoin mrežu sa sljedećim funkcijama: kreirati račun, dobiti stanje, dopuniti račun, prenijeti novčiće s jednog računa na drugi. Nacrtajmo objektni model, koji ćemo dalje implementirati u pametni ugovor. Dakle, imaćemo račune koji su identifikovani po imenima (ime) i sadrže stanje (bilans), i listu računa. Računi i lista računa su u smislu sredstava Hyperledger Fabric. Shodno tome, oni imaju istoriju i trenutno stanje. Pokušat ću to vizualno nacrtati:

Blockchain: šta da napravimo PoC?

Najveće brojke su trenutno stanje koje je pohranjeno u bazi podataka "Stanje svijeta". Ispod njih su slike koje prikazuju povijest koja je pohranjena u blockchainu. Sadašnje stanje imovine mijenja se transakcijama. Imovina se mijenja samo u cijelosti, tako da se kao rezultat transakcije kreira novi objekt, a trenutna vrijednost sredstva ulazi u povijest.

IBM Cloud

Kreiramo nalog u IBM oblak. Da biste koristili blockchain platformu, ona mora biti nadograđena na Pay-As-You-Go. Ovaj proces možda neće biti brz, jer IBM traži dodatne informacije i ručno ih provjerava. Sa pozitivne strane, mogu reći da IBM ima dobre materijale za obuku koji vam omogućavaju da implementirate Hyperledger Fabric u njihov oblak. Svidjela mi se sljedeća serija članaka i primjera:

Slijede slike ekrana IBM Blockchain platforme. Ovo nije instrukcija za kreiranje blockchaina, već jednostavno demonstracija obima zadatka. Dakle, za naše potrebe činimo jednu organizaciju:

Blockchain: šta da napravimo PoC?

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

Blockchain: šta da napravimo PoC?

Pokrećemo korisnike:

Blockchain: šta da napravimo PoC?

Kreirajte kanal i nazovite ga citcoin:

Blockchain: šta da napravimo PoC?

U suštini, Channel je blockchain, tako da počinje od nultog bloka (Genesis blok):

Blockchain: šta da napravimo PoC?

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 koristeći Hyperledger Fabric API.
  • Funkcije SendFrom i RefillBalance generiraju događaje (Event) koje će demo program primiti.
  • Funkcija instantiate se poziva jednom kada se instancira pametni ugovor. Zapravo, poziva se ne jednom, već svaki put kada se verzija pametnog ugovora promijeni. Stoga je inicijalizacija liste sa praznim nizom loša ideja, jer sada ćemo prilikom promjene verzije pametnog ugovora izgubiti trenutnu listu. Ali ništa, samo učim).
  • Nalozi i lista naloga (nalozi) su JSON strukture podataka. JS se koristi za manipulaciju podacima.
  • Možete dobiti trenutnu vrijednost sredstva pozivanjem funkcije getState i ažurirati je pomoću putState.
  • Prilikom kreiranja naloga poziva se funkcija AddAccount u kojoj se vrši poređenje za maksimalan broj naloga u blockchainu (maxAccounts = 5). I tu je dovratak (primjećen?), koji dovodi do beskonačnog povećanja broja računa. Ovakve greške treba izbjegavati

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

Blockchain: šta da napravimo PoC?

Gledamo transakciju za instaliranje Smart Contract-a:

Blockchain: šta da napravimo PoC?

Pogledajte detalje o našem kanalu:

Blockchain: šta da napravimo PoC?

Kao rezultat, dobijamo sljedeću shemu blockchain mreže u IBM oblaku. Također na dijagramu se nalazi demo program koji radi u Amazon oblaku na virtuelnom serveru (detalji o tome će biti u sljedećem odjeljku):

Blockchain: šta da napravimo PoC?

Kreiranje GUI za Hyperledger Fabric API pozive

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

  • Kreirajte kanal;
  • Peer veze sa kanalom;
  • Instalacija i instanciranje pametnih ugovora na 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 uradili ostale korake koristeći IBM blockchain platformu. GUI pišemo koristeći standardni tehnološki stog: Express.js + Vue.js + Node.js. Možete napisati poseban članak o tome kako započeti kreiranje modernih web aplikacija. Ovdje ću ostaviti link do serije predavanja koja su mi se najviše svidjela: Full Stack Web App koristeći Vue.js & Express.js. Rezultat je klijent-server aplikacija sa poznatim grafičkim interfejsom u stilu Google Material Design-a. REST API između klijenta i servera sastoji se od nekoliko poziva:

  • HyperledgerDemo/v1/init - inicijalizira blockchain;
  • HyperledgerDemo/v1/accounts/list - dobijete listu svih naloga;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 - kreirajte Bob nalog;
  • HyperledgerDemo/v1/info?account=Bob - dobiti informacije o Bob računu;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 - prebacite dva novčića od Boba do Alice;
  • HyperledgerDemo/v1/disconnect - zatvorite vezu s blockchainom.

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

Demo aplikacija u Amazon oblaku

Aplikacija je postavljena na Amazon, jer IBM još uvijek nije mogao nadograditi moj račun i dozvoliti mi da kreiram virtuelne servere. Kako je domena spojena na trešnju: www.citcoin.info. Držaću server uključen malo, pa ga isključiti, jer centi za iznajmljivanje kaplju, a citcoin novčići još nisu navedeni na berzi) Stavio sam demo screenshotove u članak da bi logika rada bila jasna. Demo aplikacija može:

  • Inicijalizirajte blockchain;
  • Kreirajte nalog (ali sada se novi nalog ne može kreirati, jer je u blockchainu dostignut maksimalan broj naloga naveden u pametnom ugovoru);
  • Dobiti listu računa;
  • Prenesite citcoin novčiće između Alice, Boba i Alexa;
  • Prijem događaja (ali sada nema načina da se događaji prikazuju, pa je zbog jednostavnosti u interfejsu napisano da događaji nisu podržani);
  • Zabilježite akcije.

Prvo, inicijaliziramo blockchain:

Blockchain: šta da napravimo PoC?

Zatim pokrećemo naš račun, ne šalite se sa stanjem:

Blockchain: šta da napravimo PoC?

Dobijamo listu svih dostupnih računa:

Blockchain: šta da napravimo PoC?

Biramo pošiljaoca i primaoca, dobijamo njihova stanja. Ako su pošiljalac i primalac isti, tada će se njegov račun dopuniti:

Blockchain: šta da napravimo PoC?

U logu pratimo izvršenje transakcija:

Blockchain: šta da napravimo PoC?

Zapravo, uz demo program, to je sve. Zatim možete vidjeti našu transakciju u blockchainu:

Blockchain: šta da napravimo PoC?

I opća lista transakcija:

Blockchain: šta da napravimo PoC?

Ovim smo uspješno završili implementaciju PoC-a za kreiranje Citcoin mreže. Šta još treba učiniti da bi Citcoin postao punopravna mreža za prijenos novčića? Veoma malo:

  • U fazi kreiranja naloga implementirajte generisanje privatnog/javnog ključa. Privatni ključ mora biti pohranjen na korisničkom računu, koji je javan na blockchainu.
  • Izvršite prijenos kovanica, u kojem se ne koristi ime, već javni ključ za identifikaciju korisnika.
  • Šifrirajte transakcije koje idu od korisnika do servera njegovim privatnim ključem.

zaključak

Implementirali smo Citcoin mrežu sa sljedećim funkcijama: dodati račun, dobiti stanje, dopuniti svoj račun, prebaciti novčiće s jednog računa na drugi. Dakle, koliko nas je koštalo da napravimo PoC?

  • Potrebno je proučiti blockchain općenito i Hyperledger Fabric posebno;
  • Naučite kako koristiti IBM ili Amazon oblake;
  • Naučite JS programski jezik i neki web okvir;
  • Ako neke podatke treba pohraniti ne u blockchain, već u zasebnu bazu podataka, naučite kako se integrirati, na primjer, s PostgreSQL-om;
  • I na kraju, ali ne i najmanje važno - bez znanja o Linuxu u modernom svijetu, nigdje!)

Naravno, ne raketna nauka, ali morate se oznojiti!

Izvori na GitHubu

Izvori postavljeni GitHub. Kratak opis spremišta:
Katalog "server» - Node.js server
Katalog "klijent» - Node.js klijent
Katalog "blockchain» (vrijednosti parametara i ključeva, naravno, ne rade i date su samo na primjer):

  • ugovor — izvor pametnog ugovora
  • novčanik - 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 samo početak!

izvor: www.habr.com

Dodajte komentar