Blockchain: milyen PoC-t építsünk?

Fél a szemed és viszket a kezed!

Korábbi cikkeinkben foglalkoztunk azokkal a technológiákkal, amelyekre a blokkláncok épülnek (Mit építsünk blokkláncot?) és a segítségükkel megvalósítható esetek (Miért építsünk ügyet?). Itt az ideje, hogy a kezeddel dolgozz! A pilotok és a PoC (Proof of Concept) megvalósításához inkább a felhőket használom, mert... a világ bármely pontjáról elérhetők, és gyakran nem kell időt vesztegetni a környezet unalmas telepítésére, mert Vannak előre beállított konfigurációk. Tehát készítsünk valami egyszerűt, például egy hálózatot a résztvevők közötti érmék átvitelére, és szerényen nevezzük Bitcoinnak. Ehhez az IBM felhőt és az univerzális blokkláncot, a Hyperledger Fabric-et fogjuk használni. Először is nézzük meg, miért nevezik a Hyperledger Fabric-et univerzális blokkláncnak?

Blockchain: milyen PoC-t építsünk?

Hyperledger Fabric - univerzális blokklánc

Általánosságban elmondható, hogy egy univerzális információs rendszer:

  • Szerverkészlet és egy üzleti logikát végrehajtó szoftvermag;
  • Interfészek a rendszerrel való interakcióhoz;
  • Eszközök az eszközök/személyek regisztrációjához, hitelesítéséhez és engedélyezéséhez;
  • Működési és archív adatokat tároló adatbázis:

Blockchain: milyen PoC-t építsünk?

A Hyperledger Fabric hivatalos verziója itt olvasható Online, és röviden, a Hyperledger Fabric egy nyílt forráskódú platform, amely lehetővé teszi privát blokkláncok építését és tetszőleges, JS és Go programozási nyelveken írt intelligens szerződések végrehajtását. Nézzük meg részletesen a Hyperledger Fabric architektúráját, és győződjön meg arról, hogy ez egy univerzális rendszer, amely csak az adatok tárolására és rögzítésére szolgál. A sajátosság az, hogy az adatokat, mint minden blokkláncnál, blokkokban tárolják, amelyek csak akkor kerülnek a blokkláncra, ha a résztvevők konszenzusra jutnak, és a rögzítés után az adatokat nem lehet csendben javítani vagy törölni.

Hyperledger Fabric Architecture

A diagram a Hyperledger Fabric architektúrát mutatja:

Blockchain: milyen PoC-t építsünk?

Szervezetek — a szervezetek társakat tartalmaznak, pl. A blokklánc a szervezetek támogatásának köszönhetően létezik. Különböző szervezetek lehetnek ugyanannak a csatornának a részei.

csatorna — a társakat csoportokba tömörítő logikai struktúra, pl. a blokklánc meg van adva. A Hyperledger Fabric egyszerre több különböző üzleti logikával rendelkező blokkláncot tud feldolgozni.

Tagsági szolgáltató (MSP) egy CA (Certificate Authority) az identitás kiadására és a szerepek kiosztására. Csomópont létrehozásához kapcsolatba kell lépnie az MSP-vel.

Peer csomópontok — tranzakciók ellenőrzése, blokklánc tárolása, intelligens szerződések végrehajtása és alkalmazásokkal való interakció. A partnerek azonosítóval (digitális tanúsítvánnyal) rendelkeznek, amelyet az MSP bocsát ki. Ellentétben a Bitcoin vagy az Etherium hálózattal, ahol minden csomópont egyenlő jogokkal rendelkezik, a Hyperledger Fabric-ben a csomópontok különböző szerepet töltenek be:

  • Talán egyenrangú támogató társ (EP) és intelligens szerződések végrehajtása.
  • Elkötelezett társ (CP) - csak az adatokat mentse el a blokkláncban, és frissítse a „világállapotot”.
  • Anchor Peer (AP) - ha több szervezet vesz részt a blokkláncban, akkor a köztük lévő kommunikációhoz horgonytársakat használnak. Minden szervezetnek rendelkeznie kell egy vagy több horgonytárssal. Az AP használatával a szervezet bármely partnere információkat szerezhet a többi szervezet összes társáról. Az AP-k közötti információk szinkronizálására szolgál pletykaprotokoll.
  • Vezető Peer — ha egy szervezetnek több társtársa van, akkor csak a partner vezetője kap blokkokat a Megrendelő szolgáltatástól és adja át a többi társnak. A vezetőt statikusan meghatározhatják, vagy dinamikusan kiválaszthatják a szervezet munkatársai. A pletykaprotokollt a vezetőkről szóló információk szinkronizálására is használják.

Eszközök — olyan entitások, amelyeknek van értéke és a blokkláncon tárolódnak. Pontosabban, ezek kulcsérték adatok JSON formátumban. Ezeket az adatokat rögzíti a Blockchain. Van egy előzményük, amelyet a blokkláncban tárolnak, és egy aktuális állapotuk, amelyet a „World state” adatbázisban tárolnak. Az adatstruktúrák az üzleti feladatoktól függően tetszőlegesen töltődnek ki. Nincsenek kötelező mezők, az egyetlen javaslat az, hogy az eszközöknek legyen tulajdonosa és értékesnek kell lenniük.

Főkönyv — a Blockchain és a Word állapotadatbázisból áll, amely az eszközök aktuális állapotát tárolja. A világállam a LevelDB-t vagy a CouchDB-t használja.

Okos szerződés — okos szerződések segítségével valósul meg a rendszer üzleti logikája. A Hyperledger Fabricban az intelligens szerződéseket lánckódnak nevezik. A lánckód segítségével meghatározzák az eszközöket és a rajtuk lévő tranzakciókat. Technikai értelemben az intelligens szerződések JS vagy Go programozási nyelveken implementált szoftvermodulok.

Jóváhagyási politika — minden lánckódhoz beállíthat egy szabályzatot arra vonatkozóan, hogy egy tranzakcióhoz hány visszaigazolást kell várni és kitől. Ha a házirend nincs beállítva, akkor az alapértelmezett: „a tranzakciót a csatornán lévő bármely szervezet bármely tagjának meg kell erősítenie.” Példák az irányelvekre:

  • A tranzakciót a szervezet bármely rendszergazdájának jóvá kell hagynia;
  • A szervezet bármely tagjának vagy ügyfelének meg kell erősítenie;
  • Bármely társszervezetnek meg kell erősítenie.

Rendelési szolgáltatás — blokkokba csomagolja a tranzakciókat, és elküldi azokat a csatornán lévő társaknak. Garantálja az üzenetek kézbesítését a hálózat összes társához. Ipari rendszerekhez használják Kafka üzenetközvetítő, fejlesztésre és tesztelésre Egyetlen.

CallFlow

Blockchain: milyen PoC-t építsünk?

  • Az alkalmazás Go, Node.js vagy Java SDK használatával kommunikál a Hyperledger Fabric-cal;
  • Az ügyfél létrehoz egy tx-tranzakciót, és elküldi a támogató partnereknek;
  • A Peer ellenőrzi az ügyfél aláírását, befejezi a tranzakciót, és visszaküldi a jóváhagyó aláírást az ügyfélnek. A lánckódot csak a jóváhagyó peer hajtja végre, és a végrehajtás eredményét elküldi az összes társnak. Ezt a munkaalgoritmust PBFT (Practical Byzantine Fault Tolerant) konszenzusnak nevezik. Eltér klasszikus BFT az a tény, hogy az üzenetet elküldik, és a megerősítést nem minden résztvevőtől, hanem csak egy bizonyos csoporttól várják;
  • Miután az ügyfél megkapta a jóváhagyási szabályzatnak megfelelő számú választ, elküldi a tranzakciót a Megrendelő szolgáltatásnak;
  • A Rendelési szolgáltatás blokkot generál, és elküldi az összes elkötelezett partnernek. A rendelési szolgáltatás biztosítja a blokkok szekvenciális rögzítését, ami kiküszöböli az ún.lásd a "Villa" részt);
  • A társak blokkot kapnak, újra ellenőrzik a jóváhagyási szabályzatot, írják a blokkot a blokkláncba, és módosítják az állapotot a „World state” DB-ben.

Azok. Ez a csomópontok közötti szereposztáshoz vezet. Ez biztosítja, hogy a blokklánc méretezhető és biztonságos legyen:

  • Az intelligens szerződések (lánckód) jóváhagyó partnereket hajtanak végre. Ez biztosítja az intelligens szerződések titkosságát, mert nem minden résztvevő tárolja, hanem csak jóváhagyó társak.
  • A rendelésnek gyorsan kell működnie. Ezt az a tény biztosítja, hogy a Rendelés csak egy blokkot képez, és azt elküldi a vezetőtársak rögzített halmazának.
  • Az elkötelezett társak csak a blokkláncot tárolják - sok lehet belőlük, és nem igényelnek nagy energiát és azonnali működést.

További részletek a Hyperledger Fabric építészeti megoldásairól és arról, hogy miért így működik és nem másként, itt találhatók: Az építészet eredete vagy itt: Hyperledger Fabric: Elosztott operációs rendszer engedélyezett blokkláncokhoz.

Tehát a Hyperledger Fabric egy igazán univerzális rendszer, amellyel:

  • Tetszőleges üzleti logika megvalósítása az intelligens szerződési mechanizmus segítségével;
  • Adatok rögzítése és fogadása a blokklánc adatbázisból JSON formátumban;
  • Adjon meg és ellenőrizze az API-hozzáférést a tanúsító hatóság segítségével.

Most, hogy egy kicsit megértjük a Hyperledger Fabric sajátosságait, végre tegyünk valami hasznosat!

Blokklánc telepítése

Probléma nyilatkozat

A feladat a Citcoin hálózat megvalósítása a következő funkciókkal: számla létrehozása, egyenleg beszerzése, számla feltöltése, érmék átvitele egyik számláról a másikra. Rajzoljunk egy objektummodellt, amit egy intelligens szerződésben fogunk tovább implementálni. Tehát olyan számláink lesznek, amelyeket nevek azonosítanak, és tartalmaznak egyenleget, valamint egy listát a számlákról. A számlák és a számlák listája a Hyperledger Fabric eszközök szempontjából. Ennek megfelelően van történelmük és jelenlegi állapotuk. Megpróbálom világosan lerajzolni:

Blockchain: milyen PoC-t építsünk?

A legfelső számok az aktuális állapotot mutatják, amelyet a „World state” adatbázisban tárolunk. Alatta ábrák a blokkláncban tárolt előzményeket mutatják. Az eszközök jelenlegi állapotát a tranzakciók változtatják. Az Eszköz csak egészében változik, így a tranzakció eredményeként új objektum jön létre, és az eszköz aktuális értéke bekerül a történelembe.

IBM Cloud

fiókot hozunk létre IBM felhő. A blokklánc platform használatához frissíteni kell Pay-As-You-Go-ra. Ez a folyamat nem biztos, hogy gyors, mert... Az IBM további információkat kér, és azokat manuálisan ellenőrzi. Pozitívumként elmondhatom, hogy az IBM jó oktatóanyagokkal rendelkezik, amelyek lehetővé teszik a Hyperledger Fabric telepítését a felhőjükben. Az alábbi cikkek és példák tetszettek:

Az alábbiakban az IBM Blockchain platform képernyőképei láthatók. Ez nem egy blokklánc létrehozására vonatkozó utasítás, hanem egyszerűen a feladat hatókörének bemutatása. Tehát céljaink érdekében létrehozunk egy szervezetet:

Blockchain: milyen PoC-t építsünk?

Csomópontokat hozunk létre benne: Rendelő CA, Org1 CA, Megrendelő Peer:

Blockchain: milyen PoC-t építsünk?

Felhasználókat hozunk létre:

Blockchain: milyen PoC-t építsünk?

Hozz létre egy csatornát, és hívd citcoinnak:

Blockchain: milyen PoC-t építsünk?

A Channel lényegében egy blokklánc, tehát a nulla blokkkal kezdődik (Genesis blokk):

Blockchain: milyen PoC-t építsünk?

Okos szerződés írása

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

Intuitív módon itt mindennek világosnak kell lennie:

  • Számos funkció (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) létezik, amelyeket a bemutató program meghív a Hyperledger Fabric API segítségével.
  • A SendFrom és RefillBalance funkciók eseményeket generálnak, amelyeket a demóprogram fog kapni.
  • A példányosítási funkciót egyszer hívják meg, amikor egy intelligens szerződést példányosítanak. Valójában nem csak egyszer hívják meg, hanem minden alkalommal, amikor az intelligens szerződéses verzió változik. Ezért egy listát üres tömbbel inicializálni rossz ötlet, mert Most, amikor megváltoztatjuk az intelligens szerződés verzióját, elveszítjük az aktuális listát. De nem baj, még csak tanulok).
  • A fiókok és a fiókok listája JSON-adatstruktúrák. A JS-t adatkezelésre használják.
  • Egy eszköz aktuális értékét a getState függvényhívás segítségével kaphatja meg, és a putState segítségével frissítheti.
  • Fiók létrehozásakor meghívásra kerül az AddAccount függvény, amelyben összehasonlítás történik a blokkláncban található fiókok maximális számával (maxAccounts = 5). És itt van egy jamb (észrevetted?), ami a fiókok számának végtelen növekedéséhez vezet. Az ilyen hibákat el kell kerülni)

Ezután betöltjük az intelligens szerződést a csatornába, és példányosítjuk:

Blockchain: milyen PoC-t építsünk?

Nézzük meg a Smart Contract telepítésének tranzakcióját:

Blockchain: milyen PoC-t építsünk?

Nézzük a részleteket csatornánkkal kapcsolatban:

Blockchain: milyen PoC-t építsünk?

Ennek eredményeként a következő diagramot kapjuk egy blokklánc hálózatról az IBM felhőben. Az ábrán egy virtuális szerveren futó Amazon felhőben futó bemutató program is látható (erről bővebben a következő részben):

Blockchain: milyen PoC-t építsünk?

GUI létrehozása Hyperledger Fabric API-hívásokhoz

A Hyperledger Fabric rendelkezik egy API-val, amely a következőkre használható:

  • Csatorna létrehozása;
  • Egyenrangú kapcsolatok;
  • Intelligens szerződések telepítése és példányosítása a csatornában;
  • Lehívási tranzakciók;
  • Kérjen információt a blokkláncról.

Alkalmazásfejlesztés

Demó programunkban az API-t csak tranzakciók lehívására és információk kérésére használjuk, mert A hátralévő lépéseket már elvégeztük az IBM blokklánc platform használatával. GUI-t írunk egy szabványos technológiai verem segítségével: Express.js + Vue.js + Node.js. A modern webalkalmazások létrehozásának megkezdéséről külön cikket írhat. Itt hagyok egy linket a számomra leginkább tetsző előadássorozathoz: Full Stack webalkalmazás Vue.js és Express.js használatával. Az eredmény egy kliens-szerver alkalmazás, ismerős grafikus felülettel a Google Material Design stílusában. A kliens és a szerver közötti REST API több hívásból áll:

  • HyperledgerDemo/v1/init - inicializálja a blokkláncot;
  • HyperledgerDemo/v1/accounts/list — az összes fiók listája;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — Bob-fiók létrehozása;
  • HyperledgerDemo/v1/info?account=Bob — információkat kaphat a Bob-fiókról;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 - két érme átvitele Bobtól Alice-hez;
  • HyperledgerDemo/v1/disconnect – zárja be a kapcsolatot a blokklánccal.

Az API leírása a következő példákkal Postás weboldal - egy jól ismert program a HTTP API tesztelésére.

Demo alkalmazás az Amazon felhőben

Azért töltöttem fel az alkalmazást az Amazonra, mert... Az IBM még mindig nem tudta frissíteni a fiókomat, és lehetővé tenni virtuális szerverek létrehozását. Hogyan adjunk hozzá egy cseresznyét a domainhez: www.citcoin.info. Egy ideig bekapcsolva tartom a szervert, aztán kikapcsolom, mert... csöpögnek a bérleti centek, a citcoin érméket pedig még nem jegyzik a tőzsdén) A cikkben a demóról készült screenshotokat mellékelem, hogy a munka logikája egyértelmű legyen. A demo alkalmazás:

  • Inicializálja a blokkláncot;
  • Fiók létrehozása (de most nem hozhat létre új fiókot, mert a blokkláncban elérte az intelligens szerződésben meghatározott maximális fiókszámot);
  • Megkapja a fiókok listáját;
  • Vigyen át citcoin érméket Alice, Bob és Alex között;
  • Események fogadása (de most nincs mód az események megjelenítésére, így az egyszerűség kedvéért a felület azt írja, hogy az események nem támogatottak);
  • Napló műveletek.

Először inicializáljuk a blokkláncot:

Blockchain: milyen PoC-t építsünk?

Ezután létrehozzuk fiókunkat, ne vesztegessük az időt az egyenleggel:

Blockchain: milyen PoC-t építsünk?

Kapunk egy listát az összes elérhető fiókról:

Blockchain: milyen PoC-t építsünk?

Kiválasztjuk a feladót és a címzettet, és megkapjuk az egyenlegüket. Ha a feladó és a címzett ugyanaz, akkor fiókja feltöltésre kerül:

Blockchain: milyen PoC-t építsünk?

A naplóban figyeljük a tranzakciók végrehajtását:

Blockchain: milyen PoC-t építsünk?

Valójában ez minden a demo programmal. Alább láthatja tranzakciónkat a blokkláncban:

Blockchain: milyen PoC-t építsünk?

És a tranzakciók általános listája:

Blockchain: milyen PoC-t építsünk?

Ezzel sikeresen befejeztük a PoC megvalósítását a Citcoin hálózat létrehozásához. Mit kell még tenni ahhoz, hogy a Citcoin teljes értékű érmék átadási hálózattá váljon? Nagyon kevés:

  • A fiók létrehozásának szakaszában hajtsa végre a privát / nyilvános kulcs generálását. A privát kulcsot a fiók felhasználójánál, a nyilvános kulcsot a blokkláncban kell tárolni.
  • Készítsen érmeátutalást, amelyben név helyett nyilvános kulcsot használnak a felhasználó azonosítására.
  • Titkosítja a felhasználótól a szerverhez tartó tranzakciókat a saját privát kulcsával.

Következtetés

A Citcoin hálózatot a következő funkciókkal hoztuk létre: számla hozzáadása, egyenleg beszerzése, számla feltöltése, érmék átvitele egyik számláról a másikra. Szóval mennyibe került egy PoC építése?

  • Tanulmányoznia kell a blokkláncot általában, és különösen a Hyperledger Fabric-et;
  • Tanulja meg az IBM vagy az Amazon felhők használatát;
  • Tanulja meg a JS programozási nyelvet és néhány webes keretrendszert;
  • Ha bizonyos adatokat nem a blokkláncban, hanem egy külön adatbázisban kell tárolni, akkor tanulj meg integrálni például a PostgreSQL-lel;
  • És végül, de nem utolsósorban: a modern világban nem lehet Linux ismerete nélkül élni!)

Természetesen ez nem rakétatudomány, de keményen kell dolgoznod!

Források a GitHubon

Források fel GitHub. Az adattár rövid leírása:
Katalógus «szerver» — Node.js szerver
Katalógus «vásárló» — Node.js kliens
Katalógus «blockchain"(a paraméterértékek és a kulcsok természetesen nem működnek, és csak példaként szerepelnek):

  • szerződés — intelligens szerződés forráskódja
  • pénztárca — felhasználói kulcsok a Hyperledger Fabric API használatához.
  • *.cds – intelligens szerződések összeállított változatai
  • *.json fájlok – példák konfigurációs fájlokra a Hyperledger Fabric API használatához

Ez még csak a kezdet!

Forrás: will.com

Hozzászólás