Blockchain: quale PoC dovremmo costruire?

I tuoi occhi hanno paura e ti prudono le mani!

Negli articoli precedenti ci siamo occupati delle tecnologie su cui sono costruite le blockchain (Cosa dovremmo costruire una blockchain?) e casi che possono essere implementati con il loro aiuto (Perché dovremmo costruire un caso?). È ora di lavorare con le tue mani! Per implementare progetti pilota e PoC (Proof of Concept), preferisco utilizzare i cloud, perché... sono accessibili da qualsiasi parte del mondo e, spesso, non è necessario perdere tempo in noiose installazioni dell'ambiente, perché Ci sono configurazioni preimpostate. Quindi, creiamo qualcosa di semplice, ad esempio una rete per il trasferimento di monete tra i partecipanti e chiamiamola modestamente Bitcoin. Per questo utilizzeremo il cloud IBM e la blockchain universale Hyperledger Fabric. Per prima cosa, scopriamo perché Hyperledger Fabric è chiamata blockchain universale?

Blockchain: quale PoC dovremmo costruire?

Hyperledger Fabric: una blockchain universale

In generale, un sistema informativo universale è:

  • Un insieme di server e un core software che esegue la logica aziendale;
  • Interfacce per l'interazione con il sistema;
  • Strumenti per la registrazione, l'autenticazione e l'autorizzazione di dispositivi/persone;
  • Database che memorizza dati operativi e di archivio:

Blockchain: quale PoC dovremmo costruire?

La versione ufficiale di Hyperledger Fabric può essere letta su sito webe, in breve, Hyperledger Fabric è una piattaforma open source che ti consente di costruire blockchain private ed eseguire contratti intelligenti arbitrari scritti nei linguaggi di programmazione JS e Go. Diamo un'occhiata in dettaglio all'architettura di Hyperledger Fabric e assicuriamoci che si tratta di un sistema universale che ha solo specifiche per l'archiviazione e la registrazione dei dati. La specificità è che i dati, come in tutte le blockchain, vengono archiviati in blocchi che vengono posizionati sulla blockchain solo se i partecipanti raggiungono un consenso e dopo la registrazione i dati non possono essere corretti o cancellati silenziosamente.

Architettura del tessuto Hyperledger

Il diagramma mostra l'architettura Hyperledger Fabric:

Blockchain: quale PoC dovremmo costruire?

Organizations — le organizzazioni contengono pari, vale a dire la blockchain esiste grazie al supporto delle organizzazioni. Diverse organizzazioni possono far parte dello stesso canale.

canale — una struttura logica che unisce i pari in gruppi, ad es. la blockchain è specificata. Hyperledger Fabric può elaborare simultaneamente più blockchain con diverse logiche di business.

Fornitore di servizi di abbonamento (MSP) è una CA (Certificate Authority) per il rilascio di identità e l'assegnazione di ruoli. Per creare un nodo, è necessario interagire con l'MSP.

Nodi paritari — verificare le transazioni, archiviare la blockchain, eseguire contratti intelligenti e interagire con le applicazioni. I peer hanno un'identità (certificato digitale), che viene rilasciata dall'MSP. A differenza della rete Bitcoin o Etherium, dove tutti i nodi hanno uguali diritti, in Hyperledger Fabric i nodi svolgono ruoli diversi:

  • Peer forse pari di appoggio (EP) ed eseguire contratti intelligenti.
  • Coetaneo impegnato (CP) - salva solo i dati nella blockchain e aggiorna lo "Stato mondiale".
  • Ancora Peer (AP) - se più organizzazioni partecipano alla blockchain, per la comunicazione tra loro vengono utilizzati i peer di ancoraggio. Ogni organizzazione deve avere uno o più peer di ancoraggio. Utilizzando AP, qualsiasi peer di un'organizzazione può ottenere informazioni su tutti i peer di altre organizzazioni. Utilizzato per sincronizzare le informazioni tra gli AP protocollo di pettegolezzi.
  • Leader Pari — se un'organizzazione ha più peer, solo il leader del peer riceverà i blocchi dal servizio di ordinazione e li darà al resto dei peer. Il leader può essere specificato staticamente o selezionato dinamicamente dai colleghi dell'organizzazione. Il protocollo gossip viene utilizzato anche per sincronizzare le informazioni sui leader.

Attività — entità che hanno valore e sono archiviate sulla blockchain. Più specificamente, si tratta di dati di valori-chiave in formato JSON. Sono questi i dati che vengono registrati nella Blockchain. Hanno una storia, che è archiviata nella blockchain, e uno stato attuale, che è archiviato nel database “Stato mondiale”. Le strutture dati vengono riempite arbitrariamente a seconda delle attività aziendali. Non ci sono campi obbligatori, l'unica raccomandazione è che gli asset debbano avere un proprietario ed essere di valore.

Ledger - è costituito dalla Blockchain e dal database di stato Word, che memorizza lo stato attuale delle risorse. Lo stato mondiale utilizza LevelDB o CouchDB.

Contratto intelligente — utilizzando i contratti intelligenti, viene implementata la logica aziendale del sistema. In Hyperledger Fabric, i contratti intelligenti sono chiamati chaincode. Utilizzando il chaincode, vengono specificati gli asset e le transazioni su di essi. In termini tecnici, i contratti intelligenti sono moduli software implementati nei linguaggi di programmazione JS o Go.

Politica di approvazione — per ogni chaincode, puoi impostare una politica su quante conferme dovrebbero essere attese per una transazione e da chi. Se la policy non è impostata, l'impostazione predefinita è: "la transazione deve essere confermata da qualsiasi membro di qualsiasi organizzazione nel canale". Esempi di politiche:

  • La transazione deve essere approvata da qualsiasi amministratore dell'organizzazione;
  • Deve essere confermato da qualsiasi membro o cliente dell'organizzazione;
  • Deve essere confermato da qualsiasi organizzazione paritaria.

Servizio di ordinazione — impacchetta le transazioni in blocchi e le invia ai peer nel canale. Garantisce la consegna dei messaggi a tutti i peer della rete. Utilizzato per impianti industriali Broker di messaggi Kafka, per lo sviluppo e il test Vacanze.

Flusso di chiamata

Blockchain: quale PoC dovremmo costruire?

  • L'applicazione comunica con Hyperledger Fabric utilizzando Go, Node.js o Java SDK;
  • Il client crea una transazione tx e la invia ai peer di approvazione;
  • Il Peer verifica la firma del cliente, completa la transazione e invia la firma di approvazione al cliente. Il chaincode viene eseguito solo sul peer di approvazione e il risultato della sua esecuzione viene inviato a tutti i peer. Questo algoritmo di lavoro è chiamato consenso PBFT (Practical Byzantine Fault Tolerant). Si differenzia da BFT classico il fatto che il messaggio venga inviato e la conferma non è prevista da tutti i partecipanti, ma solo da un certo gruppo;
  • Dopo che il cliente ha ricevuto il numero di risposte corrispondenti alla politica di girata, invia la transazione al servizio Ordering;
  • Il servizio Ordering genera un blocco e lo invia a tutti i peer impegnati. Il servizio di ordinazione garantisce la registrazione sequenziale dei blocchi, eliminando il cosiddetto ledger fork (vedere la sezione "Forche");
  • I peer ricevono un blocco, controllano nuovamente la politica di approvazione, scrivono il blocco sulla blockchain e modificano lo stato nel DB “Stato mondiale”.

Quelli. Ciò si traduce in una divisione dei ruoli tra i nodi. Ciò garantisce che la blockchain sia scalabile e sicura:

  • I contratti intelligenti (chaincode) eseguono peer di approvazione. Ciò garantisce la riservatezza dei contratti intelligenti, perché non viene memorizzato da tutti i partecipanti, ma solo dai peer di approvazione.
  • L'ordinazione dovrebbe funzionare rapidamente. Ciò è garantito dal fatto che Ordering forma solo un blocco e lo invia a un insieme fisso di peer leader.
  • I peer impegnati memorizzano solo la blockchain: possono essercene molti e non richiedono molta potenza e operazioni istantanee.

Maggiori dettagli sulle soluzioni architetturali di Hyperledger Fabric e sul perché funziona in questo modo e non altrimenti possono essere trovati qui: Origini dell'architettura o qui: Hyperledger Fabric: un sistema operativo distribuito per blockchain autorizzate.

Quindi, Hyperledger Fabric è un sistema davvero universale con cui puoi:

  • Implementare una logica aziendale arbitraria utilizzando il meccanismo del contratto intelligente;
  • Registra e ricevi dati dal database blockchain in formato JSON;
  • Concedi e verifica l'accesso API utilizzando l'autorità di certificazione.

Ora che abbiamo capito un po' le specifiche di Hyperledger Fabric, facciamo finalmente qualcosa di utile!

Distribuzione della blockchain

Formulazione del problema

Il compito è implementare la rete Citcoin con le seguenti funzioni: creare un account, ottenere un saldo, ricaricare il conto, trasferire monete da un conto all'altro. Disegniamo un modello a oggetti, che implementeremo ulteriormente in un contratto intelligente. Quindi, avremo conti identificati da nomi e contenenti un saldo e un elenco di conti. Gli account e un elenco di account sono, in termini di risorse Hyperledger Fabric. Di conseguenza, hanno una storia e uno stato attuale. Cercherò di disegnarlo chiaramente:

Blockchain: quale PoC dovremmo costruire?

Le cifre in alto rappresentano lo stato attuale, che è memorizzato nel database “Stato mondiale”. Sotto di loro ci sono le figure che mostrano la storia memorizzata nella blockchain. Lo stato attuale delle attività viene modificato dalle transazioni. L'Asset cambia solo nel suo insieme, quindi a seguito della transazione viene creato un nuovo oggetto e il valore attuale dell'asset entra nella storia.

IBM Cloud

Creiamo un account in IBM nuvola. Per utilizzare la piattaforma blockchain, è necessario aggiornarla a Pay-As-You-Go. Questo processo potrebbe non essere rapido, perché... IBM richiede informazioni aggiuntive e le verifica manualmente. Una nota positiva, posso dire che IBM dispone di buoni materiali di formazione che ti consentono di distribuire Hyperledger Fabric nel loro cloud. Mi è piaciuta la seguente serie di articoli ed esempi:

Di seguito sono riportati gli screenshot della piattaforma IBM Blockchain. Questa non è un'istruzione su come creare una blockchain, ma semplicemente una dimostrazione della portata del compito. Quindi, per i nostri scopi, creiamo un'organizzazione:

Blockchain: quale PoC dovremmo costruire?

Creiamo nodi al suo interno: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: quale PoC dovremmo costruire?

Creiamo utenti:

Blockchain: quale PoC dovremmo costruire?

Crea un canale e chiamalo Bitcoin:

Blockchain: quale PoC dovremmo costruire?

Essenzialmente Channel è una blockchain, quindi inizia con il blocco zero (blocco Genesis):

Blockchain: quale PoC dovremmo costruire?

Scrivere un contratto intelligente

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

Intuitivamente qui dovrebbe essere tutto chiaro:

  • Esistono diverse funzioni (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) che il programma demo chiamerà utilizzando l'API Hyperledger Fabric.
  • Le funzioni SendFrom e RefillBalance generano eventi che il programma demo riceverà.
  • La funzione di istanziazione viene chiamata una volta quando viene istanziato un contratto intelligente. Infatti non viene chiamato una sola volta, ma ogni volta che cambia la versione dello smart contract. Pertanto, inizializzare un elenco con un array vuoto è una cattiva idea, perché Ora, quando cambieremo la versione dello smart contract, perderemo l’elenco attuale. Ma va bene, sto solo imparando).
  • Gli account e un elenco di account sono strutture dati JSON. JS viene utilizzato per la manipolazione dei dati.
  • Puoi ottenere il valore corrente di un asset utilizzando la chiamata alla funzione getState e aggiornarlo utilizzando putState.
  • Quando si crea un account, viene richiamata la funzione AddAccount, in cui viene effettuato un confronto per il numero massimo di account nella blockchain (maxAccounts = 5). E qui c'è uno stipite (avete notato?), che porta ad un aumento infinito del numero dei conti. Tali errori dovrebbero essere evitati)

Successivamente, carichiamo lo smart contract nel canale e ne istanziamo:

Blockchain: quale PoC dovremmo costruire?

Diamo un'occhiata alla transazione per l'installazione di Smart Contract:

Blockchain: quale PoC dovremmo costruire?

Diamo un'occhiata ai dettagli sul nostro canale:

Blockchain: quale PoC dovremmo costruire?

Di conseguenza, otteniamo il seguente diagramma di una rete blockchain nel cloud IBM. Il diagramma mostra anche un programma demo in esecuzione nel cloud Amazon su un server virtuale (maggiori informazioni nella sezione successiva):

Blockchain: quale PoC dovremmo costruire?

Creazione di una GUI per le chiamate API Hyperledger Fabric

Hyperledger Fabric dispone di un'API che può essere utilizzata per:

  • Crea canale;
  • Connessioni peer to channel;
  • Installazione e istanziazione di contratti intelligenti nel canale;
  • Transazioni di chiamata;
  • Richiedi informazioni sulla blockchain.

Sviluppo dell'applicazione

Nel nostro programma demo utilizzeremo l'API solo per chiamare transazioni e richiedere informazioni, perché Abbiamo già completato i passaggi rimanenti utilizzando la piattaforma blockchain IBM. Scriviamo una GUI utilizzando uno stack tecnologico standard: Express.js + Vue.js + Node.js. Puoi scrivere un articolo separato su come iniziare a creare applicazioni web moderne. Qui lascerò un link al ciclo di conferenze che mi sono piaciute di più: App Web stack completo che utilizza Vue.js ed Express.js. Il risultato è un'applicazione client-server con un'interfaccia grafica familiare in stile Material Design di Google. L'API REST tra client e server è composta da diverse chiamate:

  • HyperledgerDemo/v1/init - inizializza la blockchain;
  • HyperledgerDemo/v1/accounts/list: ottieni un elenco di tutti gli account;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — crea un account Bob;
  • HyperledgerDemo/v1/info?account=Bob: ottieni informazioni sull'account Bob;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 - trasferisce due monete da Bob ad Alice;
  • HyperledgerDemo/v1/disconnect: chiude la connessione alla blockchain.

Descrizione dell'API con esempi inclusi Sito del postino - un noto programma per testare l'API HTTP.

Applicazione demo nel cloud di Amazon

Ho caricato l'applicazione su Amazon perché... IBM non è ancora stata in grado di aggiornare il mio account e consentirmi di creare server virtuali. Come aggiungere una ciliegia al dominio: www.citcoin.info. Terrò il server acceso per un po', poi lo spegnerò, perché... i centesimi per l'affitto gocciolano e le monete citcoin non sono ancora quotate in borsa) Inserisco gli screenshot della demo nell'articolo in modo che la logica del lavoro sia chiara. L'applicazione demo può:

  • Inizializzare la blockchain;
  • Crea un Account (ma ora non puoi creare un nuovo Account, perché nella blockchain è stato raggiunto il numero massimo di account specificato nello smart contract);
  • Ricevere un elenco di account;
  • Trasferisci monete bitcoin tra Alice, Bob e Alex;
  • Ricevere eventi (ma ora non c'è modo di mostrare gli eventi, quindi per semplicità l'interfaccia dice che gli eventi non sono supportati);
  • Registra azioni.

Per prima cosa inizializziamo la blockchain:

Blockchain: quale PoC dovremmo costruire?

Successivamente, creiamo il nostro account, non perdere tempo con il saldo:

Blockchain: quale PoC dovremmo costruire?

Otteniamo un elenco di tutti gli account disponibili:

Blockchain: quale PoC dovremmo costruire?

Selezioniamo il mittente e il destinatario e otteniamo i loro saldi. Se il mittente e il destinatario sono gli stessi, il suo account verrà reintegrato:

Blockchain: quale PoC dovremmo costruire?

Nel log monitoriamo l'esecuzione delle transazioni:

Blockchain: quale PoC dovremmo costruire?

In realtà, con il programma demo è tutto. Di seguito puoi vedere la nostra transazione nella blockchain:

Blockchain: quale PoC dovremmo costruire?

E l'elenco generale delle transazioni:

Blockchain: quale PoC dovremmo costruire?

Con questo, abbiamo completato con successo l'implementazione del PoC per creare la rete Citcoin. Cos’altro è necessario fare affinché Citcoin diventi una rete a tutti gli effetti per il trasferimento di monete? Molto poco:

  • In fase di creazione dell'account, implementare la generazione di una chiave privata/pubblica. La chiave privata deve essere archiviata presso l'account utente, la chiave pubblica deve essere archiviata nella blockchain.
  • Effettua un trasferimento di moneta in cui viene utilizzata una chiave pubblica, anziché un nome, per identificare l'utente.
  • Crittografa le transazioni che vanno dall'utente al server con la sua chiave privata.

conclusione

Abbiamo implementato la rete Citcoin con le seguenti funzioni: aggiungi un account, ottieni un saldo, ricarica il tuo account, trasferisci monete da un conto all'altro. Quindi, quanto ci è costato costruire un PoC?

  • Devi studiare la blockchain in generale e l’Hyperledger Fabric in particolare;
  • Impara a utilizzare i cloud IBM o Amazon;
  • Impara il linguaggio di programmazione JS e alcuni framework web;
  • Se alcuni dati devono essere archiviati non nella blockchain, ma in un database separato, impara a integrarli, ad esempio, con PostgreSQL;
  • E, ultimo ma non meno importante, non puoi vivere nel mondo moderno senza conoscere Linux!)

Certo, non è scienza missilistica, ma dovrai lavorare sodo!

Fonti su GitHub

Le fonti si mettono GitHub. Breve descrizione del repository:
Catalogare "server»: server Node.js
Catalogare "cliente»: client Node.js
Catalogare "blockchain"(i valori dei parametri e le chiavi, ovviamente, non sono funzionanti e vengono forniti solo come esempio):

  • contratto: codice sorgente del contratto intelligente
  • portafoglio: chiavi utente per l'utilizzo dell'API Hyperledger Fabric.
  • *.cds: versioni compilate di contratti intelligenti
  • File *.json: esempi di file di configurazione per l'utilizzo dell'API Hyperledger Fabric

È solo l'inizio!

Fonte: habr.com

Aggiungi un commento