Blockchain: cosa ci costerebbe costruire un PoC?

Gli occhi hanno paura, ma le mani prurito!

Negli articoli precedenti abbiamo analizzato le tecnologie su cui si basano le blockchain (Cosa ci vuole per costruire una blockchain?) e i casi pratici che è possibile realizzare con esse (Quanto ci costerebbe costruire un caso?). È tempo di metterci al lavoro! Per la realizzazione di pilot e PoC (Proof of Concept) preferisco utilizzare il cloud, poiché è accessibile da qualsiasi punto del mondo e, spesso, non è necessario perdere tempo con noiose installazioni dell'ambiente, dato che ci sono configurazioni preinstallate. Dunque, facciamo qualcosa di semplice, ad esempio, una rete per il trasferimento di monete tra i partecipanti e la chiamiamo modestamente Citcoin. Useremo il cloud IBM e il blockchain universale Hyperledger Fabric. Per prima cosa, vediamo perché Hyperledger Fabric è chiamato blockchain universale?

Blockchain: cosa ci costerebbe costruire un PoC?

Hyperledger Fabric — blockchain universale

Parlando in generale, un sistema informativo universale è:

  • Un insieme di server e un nucleo software che esegue la logica di business;
  • Interfacce per interagire con il sistema;
  • Strumenti per la registrazione, autenticazione e autorizzazione di dispositivi/persone;
  • Un database che memorizza dati operativi e storici:

Blockchain: cosa ci costerebbe costruire un PoC?

La definizione ufficiale di cosa sia Hyperledger Fabric può essere letta su sito, e in breve, Hyperledger Fabric è una piattaforma open-source che consente di costruire blockchain private e di eseguire contratti intelligenti scritti in linguaggi di programmazione JS e Go. Esaminiamo in dettaglio l'architettura di Hyperledger Fabric e confermiamo che si tratta di un sistema universale, il cui unico specifico è la modalità di archiviazione e registrazione dei dati. La particolarità è che i dati, come in tutte le blockchain, sono memorizzati in blocchi, che vengono inseriti nella blockchain solo se i partecipanti raggiungono un consenso e, dopo la registrazione, non è possibile modificare o eliminare i dati senza che ciò sia notato.

Architettura di Hyperledger Fabric

Nello schema è rappresentata l'architettura di Hyperledger Fabric:

Blockchain: cosa ci costerebbe costruire un PoC?

Organizzazioni — le organizzazioni contengono peer, ciò significa che la blockchain esiste grazie al supporto delle organizzazioni. Diverse organizzazioni possono far parte di un unico channel.

Channel — una struttura logica che unisce i peer in gruppi, definendo così la blockchain. Hyperledger Fabric può elaborare simultaneamente più blockchain con diverse logiche di business.

Membership Services Provider (MSP) — è l'CA (Certificate Authority) per il rilascio delle identità e l'assegnazione dei ruoli. Per creare un nodo è necessario interagire con l'MSP.

Node peer — controllano le transazioni, memorizzano la blockchain, eseguono smart contract e interagiscono con le applicazioni. I peer hanno un'identità (certificato digitale), rilasciata da MSP. A differenza della rete Bitcoin o Ethereum, dove tutti i nodi sono uguali, in Hyperledger Fabric i nodi svolgono ruoli diversi:

  • Il peer può essere peer di endorsement (EP) e eseguire smart contract.
  • Peer di commit (CP) — semplicemente memorizzano dati nella blockchain e aggiornano lo 'World state'.
  • Peer di ancoraggio (AP) — se nella blockchain partecipano più organizzazioni, i peer di ancoraggio vengono utilizzati per la comunicazione tra di esse. Ogni organizzazione deve avere uno o più peer di ancoraggio. Con l'AP, qualsiasi peer nell'organizzazione può ottenere informazioni su tutti i peer delle altre organizzazioni. Per la sincronizzazione delle informazioni tra gli AP viene utilizzato il protocollo gossip.
  • Peer leader — se un'organizzazione ha più peer, solo il peer leader riceverà i blocchi dal servizio di ordinamento e li distribuirà agli altri peer. Il leader può essere assegnato staticamente o selezionato dinamicamente dai peer nell'organizzazione. Anche per la sincronizzazione delle informazioni sui leader viene utilizzato il protocollo gossip.

Asset — entità di valore memorizzate nella blockchain. Più specificamente, questi sono dati chiave-valore in formato JSON. Questi dati vengono registrati nella blockchain 'Blockchain'. Hanno una storia conservata nella blockchain e uno stato attuale immagazzinato nel database 'World state'. Le strutture dei dati possono essere riempite in modo arbitrario a seconda delle esigenze aziendali. Non ci sono campi obbligatori, l'unica raccomandazione è che gli asset debbano avere un proprietario e rappresentare valore.

Registro — è composto dalla blockchain 'Blockchain' e dal database 'World state', in cui è memorizzato lo stato attuale degli asset. Lo stato mondiale utilizza LevelDB o CouchDB.

Smart contract — la logica aziendale del sistema viene implementata tramite smart contract. In Hyperledger Fabric, gli smart contract sono chiamati chaincode. Con il chaincode vengono definiti asset e transazioni su di essi. In termini tecnici, gli smart contract sono moduli software implementati in linguaggi di programmazione come JS o Go.

Politica di endorsement — per ogni chaincode è possibile definire politiche su quanti e quali potrebbero essere i membri da cui attendere conferme per una transazione. Se non viene impostata alcuna politica, viene utilizzata per impostazione predefinita: “la transazione deve essere confermata da qualsiasi membro di qualsiasi organizzazione nel canale”. Esempi di politiche:

  • La transazione deve essere confermata da un amministratore dell'organizzazione;
  • Deve essere confermata da un qualsiasi membro o cliente dell'organizzazione;
  • Deve essere confermata da un qualsiasi peer dell'organizzazione.

Servizio di ordinazione — incapsula le transazioni in blocchi e li invia ai peer nel channel. Garantisce la consegna dei messaggi a tutti i peer nella rete. Per i sistemi industriali viene utilizzato il broker di messaggi Kafka, per sviluppo e test Solo.

CallFlow

Blockchain: cosa ci costerebbe costruire un PoC?

  • L'applicazione interagisce con Hyperledger Fabric utilizzando Go, Node.js o Java SDK;
  • Il cliente crea una transazione tx e la invia ai peer di endorsing;
  • Il peer verifica la firma del cliente, esegue la transazione e invia la firma di endorsement al cliente. Il chaincode viene eseguito solo sui peer di endorsing e il risultato della sua esecuzione viene inviato a tutti i peer. Questo algoritmo di lavoro è chiamato consenso PBFT (Practical Byzantine Fault Tolerant). Differisce da BFT classico in quanto il messaggio viene inviato e si attende una conferma non da tutti i partecipanti, ma solo da un determinato insieme;
  • Dopo che il cliente ha ricevuto il numero di risposte corrispondente alla politica di endorsement, invia la transazione al servizio di ordinazione;
  • Il servizio di ordinazione forma un blocco e lo invia a tutti i peer di committing. Il servizio di ordinazione garantisce una registrazione sequenziale dei blocchi, escludendo così, il cosiddetto fork del ledger (vedi sezione 'Forks');
  • I peer ricevono il blocco, verificano nuovamente la politica di endorsement, registrano il blocco nella blockchain e aggiornano lo stato nel database 'World state'.

Si ottiene quindi una separazione dei ruoli tra i nodi. Questo assicura la scalabilità e la sicurezza della blockchain:

  • I contratti intelligenti (chaincode) vengono eseguiti dai peer di endorsing. Questo garantisce la riservatezza dei contratti intelligenti, poiché non sono memorizzati da tutti i partecipanti, ma solo sui peer di endorsing.
  • Ordering deve funzionare rapidamente. Questo è garantito dal fatto che l'Ordering forma solo il blocco e lo invia a un insieme fisso di peer leader.
  • I peer di committing conservano semplicemente la blockchain — possono essere numerosi e non richiedono elevate capacità e prestazioni istantanee.

Per saperne di più sulle soluzioni architetturali di Hyperledger Fabric e sul motivo per cui funziona in questo modo, puoi consultare qui: Origini dell'architettura o qui: Hyperledger Fabric: un sistema operativo distribuito per blockchain autorizzate.

Quindi, Hyperledger Fabric è davvero un sistema versatile, con il quale è possibile:

  • Implementare logiche aziendali arbitrarie utilizzando il meccanismo dei contratti intelligenti;
  • Registrare e ricevere dati da un database blockchain in formato JSON;
  • Fornire e verificare l'accesso all'API utilizzando una Certificazione Autorità.

Ora che abbiamo compreso un po' la specificità di Hyperledger Fabric, facciamo finalmente qualcosa di utile!

Deploy del blockchain

Definizione del compito

L'attività consiste nel realizzare una rete Citcoin con le seguenti funzionalità: creare un account, ottenere un saldo, ricaricare un conto, trasferire monete da un conto all'altro. Disegniamo un modello a oggetti che implementeremo poi nel contratto intelligente. Quindi, avremo account che si identificano con nomi (name) e contengono un saldo (balance), e un elenco di account. Gli account e l'elenco degli account sono, in termini di Hyperledger Fabric, asset. Di conseguenza, hanno una storia e uno stato corrente. Proverò a illustrarlo visivamente:

Blockchain: cosa ci costerebbe costruire un PoC?

Le figure superiori rappresentano lo stato attuale, che è memorizzato nel database "World state". Sotto di esse ci sono figure che mostrano la storia, che è memorizzata nella blockchain. Lo stato attuale degli asset cambia con le transazioni. L'asset viene modificato solo integralmente, quindi a seguito dell'esecuzione della transazione viene creato un nuovo oggetto, mentre il valore corrente dell'asset va nella storia.

Cloud IBM

Creiamo un account in cloud IBM. Per utilizzare la piattaforma blockchain, deve essere aggiornata a Pay-As-You-Go. Questo processo potrebbe non essere veloce, poiché IBM richiede ulteriori informazioni e le verifica manualmente. Posso dire che IBM ha buoni materiali didattici che consentono di implementare Hyperledger Fabric nel loro cloud. Mi è piaciuta la seguente serie di articoli ed esempi:

Di seguito sono riportati screenshot della Blockchain Platform di IBM. Questa non è una guida per creare un blockchain, ma solo una dimostrazione dell'ampiezza del compito. Quindi, per i nostri scopi, creiamo un'Organizzazione:

Blockchain: cosa ci costerebbe costruire un PoC?

All'interno creiamo nodi: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: cosa ci costerebbe costruire un PoC?

Creiamo utenti:

Blockchain: cosa ci costerebbe costruire un PoC?

Creiamo un Channel e lo chiamiamo citcoin:

Blockchain: cosa ci costerebbe costruire un PoC?

Fondamentalmente, Channel è un blockchain, quindi inizia con il blocco zero (Genesis block):

Blockchain: cosa ci costerebbe costruire un PoC?

Scriviamo il 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:

  • Ci sono diverse funzioni (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) che saranno chiamate dal programma demo attraverso l'API di Hyperledger Fabric.
  • Le funzioni SendFrom e RefillBalance generano eventi (Event) che il programma demo riceverà.
  • La funzione instantiate viene chiamata una sola volta durante l'istanza del smart contract. In realtà, non viene chiamata una sola volta, ma ogni volta che viene modificata la versione del smart contract. Pertanto, inizializzare la lista con un array vuoto è una cattiva idea, poiché ora, al cambio della versione del smart contract, perderemo l'attuale lista. Ma non importa, sto solo imparando).
  • Gli account e la lista degli account (accounts) sono strutture dati JSON. Per manipolare i dati si utilizza JS.
  • Per ottenere il valore corrente dell'asset si può chiamare la funzione getState, mentre per aggiornarlo si usa putState.
  • Quando si crea un Account viene chiamata la funzione AddAccount, in cui si effettua un confronto con il numero massimo di account nella blockchain (maxAccounts = 5). E qui c'è un problema (l'avete notato?), che porta a una crescita infinita del numero di account. Errori di questo tipo vanno evitati)

Successivamente carichiamo lo smart contract nel Channel e lo istanziamo:

Blockchain: cosa ci costerebbe costruire un PoC?

Visualizziamo la transazione per l'installazione dello Smart Contract:

Blockchain: cosa ci costerebbe costruire un PoC?

Visualizziamo i dettagli sul nostro Channel:

Blockchain: cosa ci costerebbe costruire un PoC?

Di conseguenza otteniamo il seguente schema della rete blockchain nel cloud IBM. Inoltre, nello schema è presente un programma demo, eseguito nel cloud Amazon su un server virtuale (di cui parleremo nel prossimo capitolo):

Blockchain: cosa ci costerebbe costruire un PoC?

Creazione di un GUI per le chiamate dell'API Hyperledger Fabric

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

  • Creare un channel;
  • Collegare un peer al channel;
  • Installare e istanziare smart contracts nel channel;
  • Chiamare transazioni;
  • Richiedere informazioni nella blockchain.

Sviluppo dell'app

Nella nostra applicazione demo utilizzeremo l'API solo per chiamare transazioni e richiedere informazioni, poiché gli altri passaggi sono già stati effettuati utilizzando la piattaforma blockchain IBM. Scriviamo il GUI utilizzando il stack tecnologico standard: Express.js + Vue.js + Node.js. Riguardo a come iniziare a creare moderne web application si potrebbe scrivere un articolo a parte. Qui lascio un link a una serie di lezioni che mi è piaciuta di più: Full Stack Web App using Vue.js & Express.js. Il risultato è stata un'applicazione client-server con un'interfaccia grafica familiare nello stile Material Design di Google. L'API REST tra il client e il server consiste in diverse chiamate:

  • HyperledgerDemo/v1/init — inizializzare la blockchain;
  • HyperledgerDemo/v1/accounts/list — ottenere la lista di tutti gli account;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — creare l'account Bob;
  • HyperledgerDemo/v1/info?account=Bob — ottenere informazioni sull'account Bob;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — trasferire due monete da Bob a Alice;
  • HyperledgerDemo/v1/disconnect — chiudere la connessione con la blockchain.

Ho caricato la descrizione dell'API con esempi su sito "Postman" — un programma ampiamente conosciuto per il test delle API HTTP.

Demo app nel cloud di Amazon

Ho caricato l'app su Amazon, poiché IBM non è ancora riuscita ad aggiornare il mio account e a consentire la creazione di server virtuali. Ho aggiunto come ciliegina sulla torta il dominio: www.citcoin.info. Terrò il server acceso un po', poi lo spegnerò, poiché i costi per l'affitto continuano a crescere, e le monete citcoin non sono ancora quotate in borsa) Nella mia articolo includo screenshot del demo per chiarire la logica di funzionamento. L'app demo può:

  • Inizializzare la blockchain;
  • Creare un Account (ma al momento non è possibile creare un nuovo Account, poiché è stato raggiunto il numero massimo di account, definito nel contratto intelligente);
  • Ottenere l'elenco degli Account;
  • Trasferire monete citcoin tra Alice, Bob e Alex;
  • Ricevere eventi (ma attualmente non è possibile mostrare eventi, quindi l'interfaccia per semplicità indica che gli eventi non sono supportati);
  • Registrare le azioni.

Per prima cosa inizializziamo la blockchain:

Blockchain: cosa ci costerebbe costruire un PoC?

Poi creiamo il nostro account, senza badare al saldo:

Blockchain: cosa ci costerebbe costruire un PoC?

Ottenere l'elenco di tutti gli account disponibili:

Blockchain: cosa ci costerebbe costruire un PoC?

Selezioniamo il mittente e il destinatario, otteniamo i loro saldi. Se il mittente e il destinatario sono lo stesso, il suo saldo verrà ricaricato:

Blockchain: cosa ci costerebbe costruire un PoC?

Nel log monitoriamo l'esecuzione delle transazioni:

Blockchain: cosa ci costerebbe costruire un PoC?

In realtà, con la demo program, abbiamo concluso. Successivamente, possiamo vedere la nostra transazione nella blockchain:

Blockchain: cosa ci costerebbe costruire un PoC?

E l'elenco generale delle transazioni:

Blockchain: cosa ci costerebbe costruire un PoC?

Così abbiamo completato con successo l'implementazione del PoC per la creazione della rete Citcoin. Cosa resta da fare affinché Citcoin diventi una rete completa per il trasferimento di monete? Davvero poco:

  • Nella fase di creazione dell'account implementare la generazione della chiave privata/pubblica. La chiave privata dovrebbe essere conservata dall'utente dell'account, quella pubblica nella blockchain.
  • Eseguire un trasferimento di monete in cui per identificare l'utente venga utilizzata non il nome, ma la chiave pubblica.
  • Cifrare le transazioni che vanno dall'utente al server con la sua chiave privata.

Conclusione

Abbiamo realizzato la rete Citcoin con le funzionalità: aggiungere account, ottenere saldo, ricaricare il proprio conto, trasferire monete da un conto all'altro. Quindi, cosa ci è costato costruire il PoC?

  • Dobbiamo studiare la blockchain in generale e Hyperledger Fabric in particolare;
  • Imparare a utilizzare i cloud IBM o Amazon;
  • Imparare il linguaggio di programmazione JS e qualche framework web;
  • Se alcuni dati devono essere memorizzati non nella blockchain, ma in un database separato, è necessario imparare a integrarsi, ad esempio, con PostgreSQL;
  • E ultimo nella lista, ma non per importanza — senza la conoscenza di Linux nel mondo moderno non si va da nessuna parte!)

Certo, non è una scienza missilistica, ma si dovrà sudare un po'!

Sorgenti su GitHub

Ho posizionato i file sorgente su GitHub. Descrizione breve del repository:
Catalogo "server" — server Node.js
Catalogo "client" — client Node.js
Catalogo "blockchain" (i valori dei parametri e le chiavi, ovviamente, non funzionano e sono forniti solo a scopo esemplificativo):

  • contract — sorgente del contratto intelligente
  • wallet — chiavi dell'utente per utilizzare l'API di Hyperledger Fabric.
  • *.cds — versioni compile dei contratti intelligenti
  • *.json file — esempi di file di configurazione per l'uso dell'API di Hyperledger Fabric

È solo l'inizio!

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster