Blockchain: jaki PoC zbudować?

Twoje oczy się boją, a ręce swędzą!

W poprzednich artykułach zajmowaliśmy się technologiami, na których zbudowane są blockchainy (Z czego powinniśmy zbudować blockchain?) i przypadki, które można za ich pomocą wdrożyć (Dlaczego powinniśmy zbudować sprawę?). Czas pracować rękami! Do wdrożenia pilotów i PoC (Proof of Concept) wolę używać chmur, bo... można uzyskać do nich dostęp z dowolnego miejsca na świecie i często nie ma potrzeby tracić czasu na żmudną instalację środowiska, ponieważ Istnieją gotowe konfiguracje. Zróbmy więc coś prostego, na przykład sieć do przesyłania monet pomiędzy uczestnikami i nazwijmy to skromnie Bitcoinem. Wykorzystamy do tego chmurę IBM i uniwersalny blockchain Hyperledger Fabric. Najpierw zastanówmy się, dlaczego Hyperledger Fabric nazywa się uniwersalnym blockchainem?

Blockchain: jaki PoC zbudować?

Hyperledger Fabric – uniwersalny blockchain

Najogólniej mówiąc, uniwersalny system informacyjny to:

  • Zestaw serwerów i rdzeń oprogramowania realizujący logikę biznesową;
  • Interfejsy do interakcji z systemem;
  • Narzędzia do rejestracji, uwierzytelniania i autoryzacji urządzeń/osób;
  • Baza danych przechowująca dane operacyjne i archiwalne:

Blockchain: jaki PoC zbudować?

Oficjalną wersję tego, czym jest Hyperledger Fabric, można przeczytać pod adresem witryna internetowaw skrócie Hyperledger Fabric to platforma typu open source, która umożliwia budowanie prywatnych łańcuchów bloków i wykonywanie dowolnych inteligentnych kontraktów napisanych w językach programowania JS i Go. Przyjrzyjmy się szczegółowo architekturze Hyperledger Fabric i upewnijmy się, że jest to system uniwersalny, który ma jedynie specyfikę przechowywania i rejestrowania danych. Specyfiką jest to, że dane, jak we wszystkich blockchainach, przechowywane są w blokach, które umieszczane są na blockchainie tylko wtedy, gdy uczestnicy osiągną konsensus i po zarejestrowaniu danych nie można po cichu poprawić ani usunąć.

Architektura tkaniny Hyperledger

Diagram przedstawia architekturę Hyperledger Fabric:

Blockchain: jaki PoC zbudować?

Organizacje — organizacje zawierają partnerów, tj. Blockchain istnieje dzięki wsparciu organizacji. Różne organizacje mogą być częścią tego samego kanału.

Kanał — logiczna struktura łącząca rówieśników w grupy, tj. określony jest łańcuch bloków. Hyperledger Fabric może jednocześnie przetwarzać wiele łańcuchów bloków o różnej logice biznesowej.

Dostawca usług członkowskich (MSP) jest urzędem certyfikacji (CA) odpowiedzialnym za wydawanie tożsamości i przypisywanie ról. Aby utworzyć węzeł, musisz wejść w interakcję z MSP.

Węzły równorzędne — weryfikuj transakcje, przechowuj blockchain, realizuj inteligentne kontrakty i wchodź w interakcję z aplikacjami. Peers posiadają tożsamość (certyfikat cyfrowy), która jest wydawana przez MSP. W przeciwieństwie do sieci Bitcoin czy Etherium, gdzie wszystkie węzły mają równe prawa, w Hyperledger Fabric węzły pełnią różne role:

  • Może kolega popierający rówieśnik (EP) i realizować inteligentne kontrakty.
  • Zaangażowany rówieśnik (CP) - zapisz tylko dane w blockchainie i zaktualizuj „Stan świata”.
  • Kotwica (AP) - jeśli w blockchainie uczestniczy kilka organizacji, wówczas do komunikacji między nimi wykorzystywane są kotwice peerów. Każda organizacja musi mieć co najmniej jednego partnera-kotwicę. Korzystając z AP, każdy uczestnik w organizacji może uzyskać informacje o wszystkich współpracownikach w innych organizacjach. Służy do synchronizacji informacji pomiędzy punktami dostępowymi protokół plotek.
  • Lider Peer — jeśli organizacja ma kilku równorzędnych partnerów, wówczas tylko lider danego równorzędnego otrzyma bloki od usługi Zamawiania i przekaże je pozostałym równorzędnym. Lider może być wyznaczony statycznie lub dynamicznie przez innych członków organizacji. Protokół plotkarski służy także do synchronizacji informacji o przywódcach.

Aktywa — podmioty posiadające wartość i przechowywane na blockchainie. Mówiąc dokładniej, są to dane typu klucz-wartość w formacie JSON. To właśnie te dane są rejestrowane w Blockchain. Mają historię, która jest przechowywana w blockchainie, oraz aktualny stan, który jest przechowywany w bazie danych „Stan świata”. Struktury danych wypełniane są dowolnie w zależności od zadań biznesowych. Nie ma żadnych wymaganych pól, jedyne zalecenie jest takie, że aktywa muszą mieć właściciela i być wartościowe.

Księga główna — składa się z Blockchaina i bazy danych stanu Word, która przechowuje aktualny stan aktywów. Stan świata używa LevelDB lub CouchDB.

Inteligentna umowa — za pomocą inteligentnych kontraktów realizowana jest logika biznesowa systemu. W Hyperledger Fabric inteligentne kontrakty nazywane są kodem łańcuchowym. Za pomocą kodu łańcuchowego określa się aktywa i transakcje na nich. Z technicznego punktu widzenia inteligentne kontrakty to moduły oprogramowania zaimplementowane w językach programowania JS lub Go.

Polityka poparcia — dla każdego łańcucha można ustawić politykę dotyczącą tego, ilu i od kogo należy oczekiwać potwierdzeń transakcji. Jeśli zasada nie jest ustawiona, domyślna wartość to: „transakcja musi zostać potwierdzona przez dowolnego członka dowolnej organizacji w kanale”. Przykłady polityk:

  • Transakcja musi zostać zatwierdzona przez dowolnego administratora organizacji;
  • Musi zostać potwierdzone przez dowolnego członka lub klienta organizacji;
  • Musi zostać potwierdzone przez dowolną organizację równorzędną.

Zamawianie usługi — pakuje transakcje w bloki i wysyła je do partnerów w kanale. Gwarantuje dostarczenie wiadomości do wszystkich partnerów w sieci. Stosowany w systemach przemysłowych Broker wiadomości Kafka, do rozwoju i testowania Serwico Solo.

Przepływ połączeń

Blockchain: jaki PoC zbudować?

  • Aplikacja komunikuje się z Hyperledger Fabric za pomocą Go, Node.js lub Java SDK;
  • Klient tworzy transakcję TX i wysyła ją do partnerów potwierdzających;
  • Peer weryfikuje podpis klienta, finalizuje transakcję i wysyła podpis potwierdzający z powrotem do klienta. Chaincode jest wykonywany tylko na partnerze zatwierdzającym, a wynik jego wykonania jest wysyłany do wszystkich peerów. Ten algorytm pracy nazywa się konsensusem PBFT (Practical Byzantine Fault Tolerant). Różni się od klasyczny BFT fakt, że wiadomość została wysłana i oczekuje się potwierdzenia nie od wszystkich uczestników, a tylko od określonej grupy;
  • Po otrzymaniu przez Klienta liczby odpowiedzi odpowiadającej polityce rekomendacji, Klient przesyła transakcję do Serwisu Zamówień;
  • Usługa Ordering generuje blok i wysyła go do wszystkich partnerów zatwierdzających. Usługa zamawiania zapewnia sekwencyjne zapisywanie bloków, co eliminuje tzw. widełki księgi (patrz rozdział „Widły”);
  • Uczestnicy otrzymują blok, ponownie sprawdzają politykę poparcia, zapisują blok do łańcucha bloków i zmieniają stan w bazie danych „Stan świata”.

Te. Powoduje to podział ról pomiędzy węzłami. Dzięki temu łańcuch bloków jest skalowalny i bezpieczny:

  • Inteligentne kontrakty (kod łańcuchowy) wykonują polecenia równorzędne. Zapewnia to poufność inteligentnych kontraktów, ponieważ nie jest on przechowywany przez wszystkich uczestników, ale jedynie przez potwierdzających go rówieśników.
  • Zamawianie powinno działać szybko. Zapewnia to fakt, że Ordering tworzy jedynie blok i wysyła go do ustalonego zestawu równorzędnych liderów.
  • Zatwierdzający peery przechowują jedynie blockchain - może ich być wiele i nie wymagają dużej mocy i błyskawicznego działania.

Więcej szczegółów na temat rozwiązań architektonicznych Hyperledger Fabric i tego, dlaczego działa to w ten, a nie inny sposób, można znaleźć tutaj: Początki architektury lub tu: Hyperledger Fabric: rozproszony system operacyjny dla dozwolonych łańcuchów bloków.

Zatem Hyperledger Fabric to naprawdę uniwersalny system, dzięki któremu możesz:

  • Implementuj dowolną logikę biznesową za pomocą mechanizmu inteligentnych kontraktów;
  • Rejestruj i odbieraj dane z bazy danych blockchain w formacie JSON;
  • Przyznaj i zweryfikuj dostęp API za pomocą urzędu certyfikacji.

Teraz, gdy rozumiemy już trochę specyfikę Hyperledger Fabric, zróbmy w końcu coś pożytecznego!

Wdrażanie blockchainu

Stwierdzenie problemu

Zadanie polega na zaimplementowaniu sieci Citcoin z następującymi funkcjami: utwórz konto, uzyskaj saldo, doładuj konto, przelej monety z jednego konta na drugie. Narysujmy model obiektowy, który będziemy dalej wdrażać w inteligentnym kontrakcie. Będziemy więc mieć konta identyfikowane po nazwie i zawierające saldo oraz listę rachunków. Konta i lista kont są w zakresie zasobów Hyperledger Fabric. W związku z tym mają historię i stan obecny. Spróbuję to wyraźnie narysować:

Blockchain: jaki PoC zbudować?

Górne liczby to stan aktualny, który jest przechowywany w bazie danych „Stan świata”. Poniżej znajdują się cyfry przedstawiające historię zapisaną w blockchainie. Aktualny stan aktywów zmieniany jest poprzez transakcje. Zasób zmienia się tylko jako całość, zatem w wyniku transakcji powstaje nowy obiekt, a aktualna wartość zasób przechodzi do historii.

Chmura IBM

Tworzymy konto w Chmura IBMa. Aby móc korzystać z platformy blockchain, należy ją zaktualizować do wersji Pay-As-You-Go. Proces ten może nie być szybki, ponieważ... IBM żąda dodatkowych informacji i weryfikuje je ręcznie. Pozytywnie mogę powiedzieć, że IBM ma dobre materiały szkoleniowe, które pozwalają wdrożyć Hyperledger Fabric w swojej chmurze. Podobała mi się następująca seria artykułów i przykładów:

Poniżej znajdują się zrzuty ekranu platformy IBM Blockchain. To nie jest instrukcja jak stworzyć blockchain, a po prostu demonstracja zakresu zadania. Zatem dla naszych celów tworzymy jedną Organizację:

Blockchain: jaki PoC zbudować?

Tworzymy w nim węzły: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: jaki PoC zbudować?

Tworzymy użytkowników:

Blockchain: jaki PoC zbudować?

Utwórz kanał i nazwij go citcoin:

Blockchain: jaki PoC zbudować?

Zasadniczo Channel jest łańcuchem bloków, więc zaczyna się od bloku zerowego (blok Genesis):

Blockchain: jaki PoC zbudować?

Pisanie inteligentnej umowy

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

Intuicyjnie wszystko powinno być tutaj jasne:

  • Istnieje kilka funkcji (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance), które program demonstracyjny wywoła za pomocą interfejsu API Hyperledger Fabric.
  • Funkcje SendFrom i RefillBalance generują zdarzenia, które odbierze program demonstracyjny.
  • Funkcja tworzenia instancji jest wywoływana raz podczas tworzenia instancji inteligentnej umowy. Tak naprawdę nazywa się to nie tylko raz, ale za każdym razem, gdy zmienia się wersja inteligentnego kontraktu. Dlatego inicjowanie listy pustą tablicą jest złym pomysłem, ponieważ Teraz, gdy zmienimy wersję inteligentnej umowy, stracimy dotychczasową listę. Ale nie ma problemu, dopiero się uczę).
  • Konta i lista kont to struktury danych JSON. JS służy do manipulacji danymi.
  • Możesz uzyskać bieżącą wartość zasobu za pomocą wywołania funkcji getState i zaktualizować ją za pomocą putState.
  • Podczas tworzenia Konta wywoływana jest funkcja AddAccount, w której dokonywane jest porównanie maksymalnej liczby kont w blockchainie (maxAccounts = 5). I tutaj pojawia się oścież (zauważyliście?), który prowadzi do niekończącego się wzrostu liczby kont. Należy unikać takich błędów)

Następnie ładujemy inteligentny kontrakt do kanału i tworzymy jego instancję:

Blockchain: jaki PoC zbudować?

Przyjrzyjmy się transakcji instalacji Smart Contract:

Blockchain: jaki PoC zbudować?

Przyjrzyjmy się szczegółom dotyczącym naszego kanału:

Blockchain: jaki PoC zbudować?

W efekcie otrzymujemy poniższy schemat sieci blockchain w chmurze IBM. Na schemacie widać także program demonstracyjny działający w chmurze Amazon na serwerze wirtualnym (więcej o tym w kolejnym podrozdziale):

Blockchain: jaki PoC zbudować?

Tworzenie GUI dla wywołań API Hyperledger Fabric

Hyperledger Fabric ma interfejs API, którego można używać do:

  • Utwórz kanał;
  • Połączenia peer-to-channel;
  • Instalacja i instancja inteligentnych kontraktów w kanale;
  • Wywoływanie transakcji;
  • Poproś o informacje na temat łańcucha bloków.

Rozwój aplikacji

W naszym programie demonstracyjnym będziemy używać API wyłącznie do wywoływania transakcji i żądania informacji, ponieważ Pozostałe kroki wykonaliśmy już przy wykorzystaniu platformy blockchain IBM. GUI piszemy wykorzystując standardowy stos technologii: Express.js + Vue.js + Node.js. O tym, jak zacząć tworzyć nowoczesne aplikacje internetowe, możesz napisać osobny artykuł. Tutaj zostawię link do cyklu wykładów, który najbardziej mi się podobał: Aplikacja internetowa Full Stack wykorzystująca Vue.js i Express.js. Rezultatem jest aplikacja klient-serwer ze znajomym interfejsem graficznym w stylu Material Design firmy Google. Interfejs API REST między klientem a serwerem składa się z kilku wywołań:

  • HyperledgerDemo/v1/init - inicjalizuj blockchain;
  • HyperledgerDemo/v1/accounts/list — uzyskaj listę wszystkich rachunków;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — utwórz konto Boba;
  • HyperledgerDemo/v1/info?account=Bob — uzyskaj informacje o koncie Boba;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — prześlij dwie monety od Boba do Alicji;
  • HyperledgerDemo/v1/disconnect - zamknij połączenie z blockchainem.

Opis API z przykładami zawartymi w Strona internetowa listonosza - znany program do testowania API HTTP.

Aplikacja demonstracyjna w chmurze Amazon

Przesłałem aplikację do Amazon, ponieważ... IBM nadal nie był w stanie zaktualizować mojego konta i umożliwić mi tworzenie serwerów wirtualnych. Jak dodać wiśnię do domeny: www.citcoin.info. Potrzymam serwer jakiś czas, potem go wyłączę, bo... centów do wynajęcia kapie, a monety citcoin nie są jeszcze notowane na giełdzie) Aby logika pracy była jasna, zamieszczam w artykule zrzuty ekranu z dema. Aplikacja demonstracyjna może:

  • Zainicjuj łańcuch bloków;
  • Utwórz Konto (ale teraz nie możesz utworzyć nowego Konta, ponieważ w blockchainie została osiągnięta maksymalna liczba kont określona w inteligentnej umowie);
  • Otrzymaj listę Rachunków;
  • Przesyłaj monety Citcoin pomiędzy Alicją, Bobem i Alexem;
  • Odbieraj zdarzenia (ale teraz nie ma możliwości pokazania zdarzeń, więc dla uproszczenia interfejs mówi, że zdarzenia nie są obsługiwane);
  • Rejestruj działania.

Najpierw inicjujemy łańcuch bloków:

Blockchain: jaki PoC zbudować?

Następnie tworzymy nasze konto, nie trać czasu na saldo:

Blockchain: jaki PoC zbudować?

Otrzymujemy listę wszystkich dostępnych kont:

Blockchain: jaki PoC zbudować?

Wybieramy nadawcę i odbiorcę oraz pobieramy ich salda. Jeśli nadawca i odbiorca są tacy sami, jego konto zostanie uzupełnione:

Blockchain: jaki PoC zbudować?

W logu monitorujemy realizację transakcji:

Blockchain: jaki PoC zbudować?

Właściwie to wszystko w programie demonstracyjnym. Poniżej możesz zobaczyć naszą transakcję w blockchainie:

Blockchain: jaki PoC zbudować?

Oraz ogólna lista transakcji:

Blockchain: jaki PoC zbudować?

Dzięki temu pomyślnie zakończyliśmy wdrożenie PoC do stworzenia sieci Citcoin. Co jeszcze trzeba zrobić, aby Citcoin stał się pełnoprawną siecią przesyłania monet? Bardzo mało:

  • Na etapie zakładania konta zaimplementuj generację klucza prywatnego/publicznego. Klucz prywatny musi być przechowywany u użytkownika konta, klucz publiczny musi być przechowywany w blockchainie.
  • Wykonaj przelew monetowy, w którym do identyfikacji użytkownika używany jest klucz publiczny, a nie nazwa.
  • Szyfruj transakcje przechodzące od użytkownika do serwera za pomocą jego klucza prywatnego.

wniosek

Wdrożyliśmy sieć Citcoin z następującymi funkcjami: dodaj konto, uzyskaj saldo, doładuj konto, przelej monety z jednego konta na drugie. Ile zatem kosztowało nas zbudowanie PoC?

  • Musisz przestudiować blockchain w ogóle, a w szczególności Hyperledger Fabric;
  • Naucz się korzystać z chmur IBM lub Amazon;
  • Naucz się języka programowania JS i trochę frameworka internetowego;
  • Jeśli jakieś dane wymagają przechowywania nie w blockchainie, a w osobnej bazie danych, to naucz się integrować np. z PostgreSQL;
  • I na koniec – nie można żyć we współczesnym świecie bez znajomości Linuksa!)

Oczywiście nie jest to odkrycie naukowe, ale będziesz musiał ciężko pracować!

Źródła na GitHubie

Źródła podają GitHub. Krótki opis repozytorium:
Katalog «serwer» — Serwer Node.js
Katalog «klient» — Klient Node.js
Katalog «blockchain"(wartości parametrów i klucze oczywiście nie działają i są podane tylko jako przykład):

  • kontrakt — kod źródłowy inteligentnego kontraktu
  • portfel — klucze użytkownika umożliwiające korzystanie z interfejsu API Hyperledger Fabric.
  • *.cds - skompilowane wersje inteligentnych kontraktów
  • Pliki *.json - przykłady plików konfiguracyjnych do korzystania z API Hyperledger Fabric

To dopiero początek!

Źródło: www.habr.com

Dodaj komentarz