Blockchain: co nás stojí postavit PoC?

Oči se bojí, ale ruce se těší!

V předchozích článcích jsme se podívali na technologie, na kterých se blockchainy staví (Co nás stojí postavit blockchain?) a na případy použití, které lze s jejich pomocí realizovat (Co nás stojí postavit případ?). Nastal čas dát ruce k dílu! Pro realizaci pilotů a PoC (Proof of Concept) preferuji používat cloud, protože k nim je přístup odkudkoli na světě a často není třeba ztrácet čas nudnou instalací prostředí, protože existují předinstalované konfigurace. Takže si udělejme něco jednoduchého, například síť pro převod mincí mezi účastníky a nazveme ji skromně Citcoin. K tomu použijeme cloud IBM a univerzální blockchain Hyperledger Fabric. Nejprve si objasníme, proč se Hyperledger Fabric nazývá univerzálním blockchainem?

Blockchain: co nás stojí postavit PoC?

Hyperledger Fabric — univerzální blockchain

Obecně řečeno, univerzální informační systém je:

  • Soubor serverů a programové jádro vykonávající obchodní logiku;
  • Rozhraní pro interakci se systémem;
  • Prostředky pro registraci, autentizaci a autorizaci zařízení/ lidí;
  • Databáze uchovávající operativní a archivní data:

Blockchain: co nás stojí postavit PoC?

Oficiální verzi o tom, co je Hyperledger Fabric, lze přečíst na webu, a pokud to shrneme, tak Hyperledger Fabric je open-source platforma, která umožňuje vytvářet uzavřené blockchainy a provádět libovolné chytré smlouvy napsané v programovacích jazycích JS a Go. Podívejme se podrobně na architekturu Hyperledger Fabric a přesvědčme se, že se jedná o univerzální systém, ve kterém je pouze specifika ohledně ukládání a zápisu dat. Specifika spočívají v tom, že data, stejně jako ve všech blockchainových systémech, jsou uchovávána v blocích, které jsou zahrnuty do blockchainu pouze pokud účastníci dosáhli konsenzu a po zápisu nelze data nenápadně opravit nebo odstranit.

Architektura Hyperledger Fabric

Na schématu je znázorněna architektura Hyperledger Fabric:

Blockchain: co nás stojí postavit PoC?

Organizations — organizace obsahují peer-y, tím pádem blockchain existuje díky podpoře organizací. Různé organizace mohou patřit do jednoho kanálu.

Channel — logická struktura, která spojuje peer-y do skupin, čímž se upravuje blockchain. Hyperledger Fabric může současně zpracovávat několik blockchainů s různou obchodní logikou.

Membership Services Provider (MSP) — je CA (Certificate Authority) pro vydávání identity a přidělování rolí. Pro vytvoření uzlu je potřeba komunikovat s MSP.

Peer uzly — ověřují transakce, uchovávají blockchain, vykonávají chytré smlouvy a interagují s aplikacemi. Peery mají identitu (digitální certifikát), který vydává MSP. Na rozdíl od sítě Bitcoin nebo Ethereum, kde jsou všechny uzly rovnocenné, v Hyperledger Fabric uzly hrají různé role:

  • Peer může být endorsing peer (EP) a vykonávat chytré smlouvy.
  • Committing peer (CP) — pouze ukládají data do blockchainu a aktualizují „World state“.
  • Anchor Peer (AP) — pokud se na blockchainu podílí více organizací, používají se anchor peery pro komunikaci mezi nimi. Každá organizace musí mít jeden nebo více anchor peerů. Pomocí AP může jakýkoli peer v organizaci získat informace o všech peerách v jiných organizacích. Pro synchronizaci informací mezi AP se používá gossip protokol.
  • Leader Peer — pokud organizace má více peerů, pouze leader peer bude přijímat bloky z Ordering service a předávat je ostatním peerům. Leader může být určen staticky nebo vybírán dynamicky peerami v organizaci. Pro synchronizaci informací o vůdcích se také používá gossip protokol.

Aktiva — entity, které mají hodnotu a jsou uchovávány v blockchainu. Přesněji řečeno — to jsou key-value data ve formátu JSON. Tyto údaje jsou vlastně zapisovány do blockchainu „Blockchain“. Mají historii, která je uchovávána v blockchainu, a aktuální stav, který se uchovává v databázi „World state“. Datové struktury jsou vyplňovány podle obchodních potřeb. Neexistují žádná povinná pole, jediným doporučením je, že aktiva by měla mít vlastníka a představovat hodnotu.

Kniha — skládá se z blockchainu „Blockchain“ a databáze „World state“, ve které je uchováván aktuální stav aktiv. World state používá LevelDB nebo CouchDB.

Chytrá smlouva — pomocí chytrých smluv se realizuje obchodní logika systému. V Hyperledger Fabric se chytré smlouvy nazývají chaincode. Pomocí chaincode se definují aktiva a transakce s nimi. Technicky řečeno, chytré smlouvy jsou programové moduly realizované v programovacích jazycích JS nebo Go.

Politika schválení — pro každý chaincode lze definovat politiky, kolik a od koho je třeba očekávat potvrzení pro transakci. Pokud politika není stanovena, platí výchozí nastavení: „transakci musí potvrdit libovolný člen (member) jakékoli organizace v channel“. Příklady politik:

  • Transakci by měl potvrdit kterýkoli administrátor organizace;
  • Musí potvrdit kterýkoli člen (member) nebo klient organizace;
  • Musí potvrdit kterýkoli peer organizace.

Služba objednávání — shromažďuje transakce do bloků a odesílá je peerům v channel. Zajišťuje doručení zpráv všem peerům v síti. Pro průmyslové systémy se používá zprávový broker Kafka, pro vývoj a testování Solo.

CallFlow

Blockchain: co nás stojí postavit PoC?

  • Aplikace interaguje s Hyperledger Fabric pomocí Go, Node.js nebo Java SDK;
  • Klient vytváří transakci tx a posílá ji na endorsing peery;
  • Peer kontroluje podpis klienta, provádí transakci a odesílá endorsement signature zpět klientovi. Chaincode se provádí pouze na endorsing peer, a výsledek jeho provedení je rozeslán všem peerům. Tento algoritmus se nazývá — PBFT (Practical Byzantine Fault Tolerant) konsensus. Liší se od klasického BFT tím, že zpráva se rozesílá a potvrzení se očekává nejen od všech účastníků, ale pouze od určitého souboru;
  • Jakmile klient obdrží počet odpovědí odpovídající politice endorsement, odešle transakci na službu objednávání;
  • Služba objednávání vytváří blok a posílá ho všem committing peerům. Služba objednávání zajišťuje sekvenční záznam bloků, což vylučuje takzvaný ledger fork (viz část „Forky“);
  • Peery obdrží blok, znovu zkontrolují politiku endorsement, zapíší blok do blockchainu a změní stav v databázi „World state“.

Tím se dosáhne rozdělení rolí mezi uzly. To zajišťuje škálovatelnost a bezpečnost blockchainu:

  • Chytré kontrakty (chaincode) provádějí endorsing peery. To zajišťuje důvěrnost chytrých kontraktů, protože se neuchovávají u všech účastníků, ale pouze na endorsing peerách.
  • Objednávání musí fungovat rychle. To je zajištěno tím, že objednávání pouze vytváří blok a odesílá ho na pevně stanovenou skupinu leader peerů.
  • Committing peery pouze uchovávají blockchain — může jich být mnoho a nepotřebují velkou výkonovou kapacitu ani okamžitou odezvu.

Podrobněji se o architektonických řešeních Hyperledger Fabric a proč funguje tak, jak funguje, lze podívat zde: Architektonické původy nebo zde: Hyperledger Fabric: Distribuovaný operační systém pro povolené blockchainy.

Hyperledger Fabric je skutečně univerzální systém, který umožňuje:

  • Implementovat libovolnou obchodní logiku pomocí mechanismu chytrých kontraktů;
  • Zapisovat a získávat data z blockchainové databáze ve formátu JSON;
  • Poskytovat a ověřovat přístup k API pomocí certifikační autority.

Nyní, když jsme si trochu vyjasnili specifika Hyperledger Fabric, pojďme konečně udělat něco užitečného!

Nasazení blockchainu

Formulace úkolu

Úkolem je realizovat síť Citcoin, která bude mít následující funkce: vytvořit účet, získat zůstatek, dobít účet, převést mince z jednoho účtu na druhý. Nakreslíme objektový model, který pak implementujeme v chytrém kontraktu. Budeme mít účty, které budou identifikovány jmény (name) a obsahovat zůstatek (balance), a seznam účtů. Účty a seznam účtů jsou v terminologii Hyperledger Fabric aktiva. Mají tedy historii a aktuální stav. Pokusím se to názorně znázornit:

Blockchain: co nás stojí postavit PoC?

Horní figurky představují aktuální stav, který je uložen v databázi „World state“. Pod nimi jsou figurky zobrazující historii, která je uložena v blockchainu. Aktuální stav aktiv se mění transakcemi. Aktivum se mění pouze jako celek, proto se po vykonání transakce vytvoří nový objekt a aktuální hodnota aktiva se přesune do historie.

IBM Cloud

Založte si účet v IBM cloudu. Aby bylo možné používat blockchainovou platformu, je nutné ji upgradovat na model Pay-As-You-Go. Tento proces může trvat déle, protože IBM vyžaduje další informace a provádí jejich ruční kontrolu. Na pozitivní straně mohu říci, že IBM má dobré vzdělávací materiály, které umožňují nasadit Hyperledger Fabric v jejich cloudu. Líbil se mi následující cyklus článků a příkladů:

Následují screenshoty Blockchainové platformy IBM. Toto není návod k vytvoření blockchainu, ale pouze ukázka rozsahu úkolu. Pro naše účely vytvoříme jednu organizaci:

Blockchain: co nás stojí postavit PoC?

V ní vytvoříme uzly: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: co nás stojí postavit PoC?

Založíme uživatele:

Blockchain: co nás stojí postavit PoC?

Vytvoříme kanál a pojmenujeme ho citcoin:

Blockchain: co nás stojí postavit PoC?

V podstatě je kanál blockchain, takže začíná nulovým blokem (Genesis block):

Blockchain: co nás stojí postavit PoC?

Napíšeme chytrý kontrakt

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

Intuitivně by tu mělo být všechno jasné:

  • Existuje několik funkcí (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance), které bude demonstrační program volat pomocí Hyperledger Fabric API.
  • Funkce SendFrom a RefillBalance generují události (Event), které bude demonstrační program přijímat.
  • Funkce instantiate — je volána jednou při instanciaci smart kontraktu. Ve skutečnosti není volána jednou, ale pokaždé při změně verze smart kontraktu. Proto inicializace seznamu prázdným polem není dobrý nápad, protože nyní při změně verze smart kontraktu ztratíme aktuální seznam. Ale to nevadí, já se jen učím).
  • Účty (Account) a seznam účtů (accounts) — jsou JSON struktury dat. Pro manipulaci s daty se používá JS.
  • Aktuální hodnotu assetu lze získat pomocí volání funkce getState a aktualizovat pomocí putState.
  • Při vytváření účtu se volá funkce AddAccount, ve které se provádí porovnání maximálního počtu účtů v blockchainu (maxAccounts = 5). A zde je chyba (všimli jste si?), která vede k nekonečnému nárůstu počtu účtů. Takových chyb je třeba se vyvarovat)

Dále načteme smart kontrakt do Channel a instanciujeme jej:

Blockchain: co nás stojí postavit PoC?

Díváme se na transakci pro instalaci Smart Contract:

Blockchain: co nás stojí postavit PoC?

Díváme se na podrobnosti o našem Channel:

Blockchain: co nás stojí postavit PoC?

V důsledku toho získáváme následující schéma blockchainové sítě v cloudu IBM. Také na schématu je uveden demonstrační program běžící v cloudu Amazon na virtuálním serveru (další podrobnosti budou v následující části):

Blockchain: co nás stojí postavit PoC?

Vytvoření GUI pro volání Hyperledger Fabric API

Hyperledger Fabric má API, které lze použít pro:

  • Vytvoření channelu;
  • Připojení peer k channelu;
  • Instalaci a instanciaci smart kontraktů v channelu;
  • Volání transakcí;
  • Dotazování informací v blockchainu.

Vývoj aplikace

V naší demonstrační aplikaci budeme používat API pouze pro volání transakcí a dotazování informací, protože ostatní kroky jsme již provedli pomocí blockchainové platformy IBM. Píšeme GUI, používající standardní technologický stack: Express.js + Vue.js + Node.js. O tom, jak začít vytvářet moderní webové aplikace, by se dala napsat samostatná článek. Zde přidám odkaz na sérii přednášek, které se mi nejvíce líbily: Full Stack Web App using Vue.js & Express.js. V důsledku toho vznikla klient-server aplikace se známým grafickým rozhraním ve stylu Material Design od Google. REST API mezi klientem a serverem se skládá z několika volání:

  • HyperledgerDemo/v1/init — inicializovat blockchain;
  • HyperledgerDemo/v1/accounts/list — získat seznam všech účtů;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — vytvořit účet Bob;
  • HyperledgerDemo/v1/info?account=Bob — získat informace o účtu Bob;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — převést dvě mince od Boba k Alici;
  • HyperledgerDemo/v1/disconnect — ukončit připojení k blockchainu.

Popis API s příklady jsem umístil na webové stránce „Postman“ — dobře známém programu pro testování HTTP API.

Demo aplikace v cloudu Amazon

Aplikaci jsem nahrál na Amazon, protože IBM stále nebylo schopno upgradovat můj účet a povolit mi vytvářet virtuální servery. Jako třešničku jsem přidělal doménu: www.citcoin.info. Trochu podržím server zapnutý, pak ho vypnu, protože centy za pronájem naskakují, a mince citcoin na burze ještě nejsou kotovány) Do článku přikládám screenshoty dema, aby byla jasná logika práce. Demo aplikace může:

  • Inicializovat blockchain;
  • Vytvářet účet (ale nyní nový účet nelze vytvořit, protože v blockchainu bylo dosaženo maximálního počtu účtů, jak je uvedeno ve smart kontraktu);
  • Získat seznam účtů;
  • Převádět mince citcoin mezi Alicí, Bobem a Alexem;
  • Získávat události (ale momentálně není možné události zobrazit, takže v rozhraní pro jednoduchost je uvedeno, že události nejsou podporovány);
  • Logovat akce.

Nejprve inicializujeme blockchain:

Blockchain: co nás stojí postavit PoC?

Dále zakládáme svůj účet, nešetříme s bilancí:

Blockchain: co nás stojí postavit PoC?

Získáváme seznam všech dostupných účtů:

Blockchain: co nás stojí postavit PoC?

Vybereme odesílatele a příjemce, získáme jejich zůstatky. Pokud je odesílatel a příjemce stejný, dojde k doplnění jeho účtu:

Blockchain: co nás stojí postavit PoC?

V logu sledujeme provádění transakcí:

Blockchain: co nás stojí postavit PoC?

S demoprogramem je to vše. Dále si můžeme prohlédnout naši transakci v blockchainu:

Blockchain: co nás stojí postavit PoC?

A celkový seznam transakcí:

Blockchain: co nás stojí postavit PoC?

Tímto jsme úspěšně dokončili implementaci PoC pro vytvoření sítě Citcoin. Co ještě musíme udělat, aby se Citcoin stal plnohodnotnou sítí pro převod mincí? Je toho jen málo:

  • V etapě vytváření účtu realizovat generaci soukromého/publikovaného klíče. Soukromý klíč by měl být uchováván u uživatele účtu, veřejný v blockchainu.
  • Provést převod mincí, ve kterém k identifikaci uživatele se používá nikoli jméno, ale veřejný klíč.
  • Šifrovat transakce, které jdou od uživatele na server jeho soukromým klíčem.

Závěr

Realizovali jsme síť Citcoin s funkcemi: přidat účet, získat zůstatek, dobít svůj účet, převést mince z jednoho účtu na druhý. Tak co nás stálo postavit PoC?

  • Je třeba studovat blockchain obecně a Hyperledger Fabric konkrétně;
  • Naučit se používat cloudové služby IBM nebo Amazon;
  • Naučit se programovací jazyk JS a nějaký webový framework;
  • Pokud je potřeba uchovávat nějaká data nikoli v blockchainu, ale v samostatné databázi, naučit se integrovat například s PostgreSQL;
  • A poslední na seznamu, ale ne méně důležité — bez znalosti Linuxu se v moderním světě nikam nedostanete!)

Oczywiście to není rocket science, ale potrápit se budete muset!

Zdrojové kódy na GitHubu

Zdrojové kódy jsem položil na GitHub. Krátký popis repozitáře:
Adresář „server“ — Node.js server
Adresář „client“ — Node.js klient
Adresář „blockchain“ (hodnoty parametrů a klíče jsou samozřejmě nefunkční a uvedeny pouze jako příklad):

  • contract — zdrojový kód chytrého kontraktu
  • wallet — klíče uživatele pro použití Hyperledger Fabric API.
  • *.cds — zkompilované verze chytrých kontraktů
  • *.json soubory — příklady konfiguračních souborů pro použití Hyperledger Fabric API

To je teprve začátek!

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster