Blockchain: wat moet ons 'n PoC bou?

Oë is bang, en hande jeuk!

In vorige artikels het ons gehandel oor die tegnologieë waarop blokkettings gebou word (Wat moet ons 'n blokketting bou?) en gevalle wat met hul hulp geïmplementeer kan word (Wat kos dit ons om 'n saak te bou?). Dit is tyd om met jou hande te werk! Vir die implementering van vlieëniers en PoC (Proof of Concept), verkies ek om wolke te gebruik, want. hulle het toegang van enige plek in die wêreld en, dikwels, is dit nie nodig om tyd aan die vervelige installering van die omgewing te spandeer nie, want. Daar is voorafbepaalde konfigurasies. So, kom ons maak iets eenvoudig, soos 'n netwerk vir die oordrag van munte tussen deelnemers en noem dit beskeie Citcoin. Om dit te doen, sal ons die IBM-wolk en die Hyperledger Fabric-universele blokketting gebruik. Kom ons kyk eers uit hoekom Hyperledger Fabric 'n universele blokketting genoem word?

Blockchain: wat moet ons 'n PoC bou?

Hyperledger Stof - Universele Blockchain

Oor die algemeen is 'n universele inligtingstelsel:

  • 'n Stel bedieners en 'n sagtewarekern wat besigheidslogika uitvoer;
  • Koppelvlakke vir interaksie met die stelsel;
  • Middele vir registrasie, verifikasie en magtiging van toestelle / mense;
  • Databasis wat operasionele en geargiveerde data stoor:

Blockchain: wat moet ons 'n PoC bou?

Die amptelike weergawe van wat Hyperledger Fabric is, kan gelees word by Online, en in kort, Hyperledger Fabric is 'n oopbronplatform wat jou toelaat om private blokkettings te bou en arbitrêre slim kontrakte uit te voer wat in JS en Go-programmeertale geskryf is. Kom ons kyk van naderby na die Hyperledger Fabric-argitektuur en maak seker dat dit 'n universele stelsel is wat slegs besonderhede het vir die stoor en opneem van data. Die spesifisiteit lê daarin dat data, soos in alle blokkettings, in blokke gestoor word wat slegs in die blokketting geplaas word as die deelnemers 'n konsensus bereik het en na opname kan die data nie stilweg reggestel of uitgevee word nie.

Hyperledger Fabric Argitektuur

Die diagram toon die Hyperledger Fabric-argitektuur:

Blockchain: wat moet ons 'n PoC bou?

Organisasies - organisasies bevat eweknieë, so blockchain bestaan ​​as gevolg van die ondersteuning van organisasies. Verskillende organisasies kan deel wees van dieselfde kanaal.

Channel - 'n logiese struktuur wat eweknieë in groepe verenig, dus. blockchain is ingestel. Hyperledger Fabric kan gelyktydig verskeie blokkettings met verskillende besigheidslogika verwerk.

Lidmaatskapdiensverskaffer (MSP) is 'n CA (Sertifikaat-owerheid) vir die uitreiking van identiteit en die toekenning van rolle. Om 'n nodus te skep, moet jy interaksie met die MSP hê.

Eweknie nodusse - verifieer transaksies, stoor die blokketting, voer slim kontrakte uit en interaksie met toepassings. Eweknieë het 'n identiteit (digitale sertifikaat) uitgereik deur die MSP. Anders as die Bitcoin- of Etherium-netwerk, waar alle nodusse gelyk is, speel nodusse verskillende rolle in Hyperledger Fabric:

  • Eweknie kan wees eweknie onderskryf (EP) en slim kontrakte uit te voer.
  • Pleeg eweknie (CP) - stoor slegs data in die blokketting en werk die "Wêreldstaat" op.
  • Anker Peer (AP) - as verskeie organisasies aan die blokketting deelneem, word anker-eweknieë gebruik om tussen hulle te kommunikeer. Elke organisasie moet een of meer anker-eweknieë hê. Met die hulp van die AP kan enige eweknie in 'n organisasie inligting bekom oor alle eweknieë in ander organisasies. Word gebruik om inligting tussen AP's te sinchroniseer. skinder protokol.
  • Leier Peer - as die organisasie verskeie eweknieë het, sal slegs die leier van die eweknie blokke van die Besteldiens ontvang en dit aan die res van die eweknieë gee. Die leier kan staties of dinamies gekies word deur eweknieë in die organisasie. Die skinderprotokol word ook gebruik om leierinligting te sinchroniseer.

Bates - entiteite van waarde wat in die blokketting gestoor word. Meer spesifiek, dit is sleutelwaarde-data in JSON-formaat. Dit is hierdie data wat in die Blockchain blockchain aangeteken word. Hulle het 'n geskiedenis wat op die blokketting gestoor word en 'n huidige toestand wat in die "World state" databasis gestoor word. Datastrukture word arbitrêr gevul na gelang van saketake. Daar is geen vereiste velde nie, die enigste aanbeveling is dat bates 'n eienaar moet hê en van waarde moet wees.

grootboek - bestaan ​​uit die Blockchain blockchain en die Word state databasis, wat die huidige toestand van die bates stoor. Wêreldstaat gebruik LevelDB of CouchDB.

Slim kontrak — met behulp van slim kontrakte word die besigheidslogika van die stelsel geïmplementeer. In Hyperledger Fabric word slim kontrakte kettingkode genoem. Met behulp van kettingkode word bates en transaksies daaroor gespesifiseer. In tegniese taal is slim kontrakte sagtewaremodules wat in JS- of Go-programmeertale geïmplementeer word.

Endossementbeleid - vir elke kettingkode kan jy beleide stel vir hoeveel en van wie jy bevestigings vir die transaksie moet verwag. As die beleid nie gestel is nie, dan is die verstek: "die transaksie moet bevestig word deur enige lid van enige organisasie in die kanaal". Beleidsvoorbeelde:

  • Die transaksie moet deur enige administrateur van die organisasie bevestig word;
  • Moet deur enige lid of kliënt van die organisasie bevestig word;
  • Moet enige eweknie van die organisasie bevestig.

Bestel diens - pak transaksies in blokke en stuur dit na eweknieë in kanaal. Verseker boodskapaflewering aan alle eweknieë op die netwerk. Word gebruik vir industriële stelsels Kafka boodskap makelaar, vir ontwikkeling en toetsing Solo.

oproepvloei

Blockchain: wat moet ons 'n PoC bou?

  • Die toepassing is in wisselwerking met Hyperledger Fabric deur Go, Node.js of Java SDK te gebruik;
  • Die kliënt skep 'n transaksie tx en stuur dit aan onderskryf eweknieë;
  • Die eweknie verifieer die kliënt se handtekening, voltooi die transaksie en stuur die endossementhandtekening terug na die kliënt. Kettingkode word slegs uitgevoer op die onderskryf eweknie, en die resultaat van die uitvoering daarvan word aan alle eweknieë gestuur. So 'n algoritme van werk word genoem - PBFT (Practical Byzantine Fault Tolerant) konsensus. Verskil van klassieke BFT die feit dat die boodskap gestuur word en bevestiging nie van alle deelnemers verwag word nie, maar slegs van 'n sekere stel;
  • Nadat die kliënt die aantal antwoorde ontvang het wat ooreenstem met die endossementbeleid, stuur dit die transaksie na die Besteldiens;
  • Bestellingsdiens vorm 'n blok en stuur dit aan alle toegewyde eweknieë. Die Besteldiens verseker dat blokke opeenvolgend geskryf word, wat die sogenaamde grootboekvurk (sien afdeling "Vurke");
  • Eweknieë ontvang die blok, kyk weer na die endossementbeleid, skryf die blok na die blokketting en verander die toestand in die "Wêreldstaat" DB.

Dié. dit blyk die verdeling van rolle tussen nodusse. Dit verseker die skaalbaarheid en sekuriteit van die blokketting:

  • Slim kontrakte (kettingkode) voer eweknieë onderskryf. Dit verseker die vertroulikheid van slim kontrakte, soos dit word nie deur alle deelnemers gestoor nie, maar slegs deur eweknieë te onderskryf.
  • Bestelling behoort vinnig te werk. Dit word verseker deur die feit dat Bestelling slegs 'n blok vorm en dit na 'n vaste stel leier-eweknieë stuur.
  • Verbindende eweknieë stoor net die blokketting - daar kan baie van hulle wees en hulle benodig nie veel krag en kitswerk nie.

Meer argitektoniese oplossings van Hyperledger Fabric en hoekom dit so werk en nie anders nie, kan hier gevind word: Argitektuur oorsprong of hier: Hyperledger Fabric: 'n Verspreide bedryfstelsel vir gemagtigde blokkettings.

Dus, Hyperledger Fabric is 'n werklik universele stelsel waarmee jy kan:

  • Implementeer arbitrêre besigheidslogika deur die slim kontrakmeganisme te gebruik;
  • Skryf en ontvang data van die blockchain-databasis in JSON-formaat;
  • Verleen en bekragtig API-toegang deur 'n sertifikaatowerheid te gebruik.

Noudat ons 'n bietjie van die Hyperledger Fabric-spesifikasies uit die weg geruim het, laat ons uiteindelik iets nuttigs doen!

Ontplooi die blokketting

Probleemstelling

Die taak is om die Citcoin-netwerk te implementeer met die volgende funksies: skep 'n rekening, kry 'n balans, vul 'n rekening aan, dra munte van een rekening na 'n ander oor. Kom ons teken 'n objekmodel, wat ons verder in 'n slim kontrak sal implementeer. Dus, ons sal rekeninge hê wat deur name (naam) geïdentifiseer word en 'n saldo (saldo) en 'n lys rekeninge bevat. Rekeninge en 'n lys rekeninge is in terme van Hyperledger Fabric-bates. Gevolglik het hulle 'n geskiedenis en 'n huidige toestand. Ek sal probeer om dit visueel te teken:

Blockchain: wat moet ons 'n PoC bou?

Die boonste syfers is die huidige toestand, wat in die "Wêreldstaat"-databasis gestoor word. Onder hulle is syfers wat die geskiedenis wys wat in die blokketting gestoor word. Die huidige toestand van bates word deur transaksies verander. Die bate verander slegs in sy geheel, so as gevolg van die transaksie word 'n nuwe voorwerp geskep, en die huidige waarde van die bate gaan in die geskiedenis in.

IBM Wolk

Ons skep 'n rekening in IBM wolk. Om die blockchain-platform te gebruik, moet dit opgegradeer word na Pay-As-You-Go. Hierdie proses is dalk nie vinnig nie, want IBM versoek bykomende inligting en verifieer dit met die hand. Aan die positiewe kant kan ek sê dat IBM goeie opleidingsmateriaal het wat jou toelaat om Hyperledger Fabric in hul wolk te ontplooi. Ek het van die volgende reeks artikels en voorbeelde gehou:

Die volgende is skermkiekies van die IBM Blockchain-platform. Dit is nie 'n instruksie vir die skep van 'n blokketting nie, maar bloot 'n demonstrasie van die omvang van die taak. Dus, vir ons doeleindes, maak ons ​​een organisasie:

Blockchain: wat moet ons 'n PoC bou?

Ons skep nodusse daarin: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: wat moet ons 'n PoC bou?

Ons begin gebruikers:

Blockchain: wat moet ons 'n PoC bou?

Skep 'n kanaal en noem dit citcoin:

Blockchain: wat moet ons 'n PoC bou?

In wese is Channel 'n blokketting, so dit begin vanaf die nul-blok (Genesis-blok):

Blockchain: wat moet ons 'n PoC bou?

Skryf 'n slim kontrak

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

Intuïtief moet alles hier duidelik wees:

  • Daar is verskeie funksies (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) wat die demo-program sal oproep deur die Hyperledger Fabric API te gebruik.
  • Die SendFrom- en RefillBalance-funksies genereer gebeurtenisse (Gebeurtenis) wat die demo-program sal ontvang.
  • Die instansieerfunksie word een keer genoem wanneer die slimkontrak geïnstantieer word. Trouens, dit word nie een keer genoem nie, maar elke keer verander die weergawe van die slim kontrak. Daarom is die inisiasie van 'n lys met 'n leë skikking 'n slegte idee, want nou wanneer die weergawe van die slim kontrak verander word, sal ons die huidige lys verloor. Maar niks, ek leer net).
  • Rekeninge en die lys van rekeninge (rekeninge) is JSON-datastrukture. JS word gebruik vir data manipulasie.
  • Jy kan die huidige waarde van 'n bate kry deur die getState-funksie te roep, en dit op te dateer met putState.
  • Wanneer 'n rekening geskep word, word die AddAccount-funksie genoem, waarin 'n vergelyking gemaak word vir die maksimum aantal rekeninge in die blokketting (maxAccounts = 5). En daar is 'n jamb (opgemerk?), Wat lei tot 'n oneindige toename in die aantal rekeninge. Sulke foute moet vermy word

Vervolgens laai ons die slim kontrak in die kanaal en instansieer dit:

Blockchain: wat moet ons 'n PoC bou?

Ons kyk na die transaksie vir die installering van die Smart Contract:

Blockchain: wat moet ons 'n PoC bou?

Sien besonderhede oor ons kanaal:

Blockchain: wat moet ons 'n PoC bou?

As gevolg hiervan kry ons die volgende skema van die blockchain-netwerk in die IBM-wolk. Ook op die diagram is daar 'n demonstrasieprogram wat in die Amazon-wolk op 'n virtuele bediener loop (besonderhede daaroor sal in die volgende afdeling wees):

Blockchain: wat moet ons 'n PoC bou?

Skep 'n GUI vir Hyperledger Fabric API-oproepe

Hyperledger Fabric het 'n API wat gebruik kan word om:

  • Skep 'n kanaal;
  • Eweknie-verbindings met kanaal;
  • Installering en instansiasie van slim kontrakte in die kanaal;
  • Oproeptransaksies;
  • Versoek inligting oor die blokketting.

Toepassingsontwikkeling

In ons demo-program sal ons die API net gebruik om transaksies te bel en inligting aan te vra, want. ons het reeds die res van die stappe gedoen met behulp van die IBM blockchain-platform. Ons skryf 'n GUI met behulp van die standaard tegnologie stapel: Express.js + Vue.js + Node.js. Jy kan 'n aparte artikel skryf oor hoe om moderne webtoepassings te begin skep. Hier laat ek 'n skakel na 'n reeks lesings waarvan ek die meeste gehou het: Full Stack Web App met behulp van Vue.js & Express.js. Die resultaat is 'n kliënt-bediener-toepassing met 'n bekende grafiese koppelvlak in die styl van Google se Materiaalontwerp. Die REST API tussen kliënt en bediener bestaan ​​uit verskeie oproepe:

  • HyperledgerDemo/v1/init - inisialiseer die blokketting;
  • HyperledgerDemo/v1/accounts/list - kry 'n lys van alle rekeninge;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 - skep Bob-rekening;
  • HyperledgerDemo/v1/info?account=Bob - kry inligting oor Bob-rekening;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 - dra twee munte van Bob na Alice oor;
  • HyperledgerDemo/v1/disconnect - maak die verbinding met die blokketting toe.

API-beskrywing met voorbeelde aangebring Posman webwerf is 'n bekende program om HTTP API te toets.

Demo-toepassing in die Amazon-wolk

Die toepassing is na Amazon gelaai, want IBM kon steeds nie my rekening opgradeer en my toelaat om virtuele bedieners te skep nie. Hoe die domein aan die kersie geheg is: www.citcoin.info. Ek sal die bediener vir 'n rukkie aangeskakel hou en dit dan afskakel, want sente te huur drup, en citcoin-munte is nog nie op die beurs gelys nie) Ek sit demo-skermkiekies in die artikel sodat die logika van werk duidelik is. Die demo-toepassing kan:

  • Inisialiseer die blokketting;
  • Skep 'n rekening (maar nou kan 'n nuwe rekening nie geskep word nie, want die maksimum aantal rekeninge wat in die slimkontrak gespesifiseer is, is in die blokketting bereik);
  • Kry 'n lys van rekeninge;
  • Dra citcoin-munte oor tussen Alice, Bob en Alex;
  • Ontvang gebeurtenisse (maar daar is nou geen manier om gebeurtenisse te wys nie, so vir eenvoud word daar in die koppelvlak geskryf dat gebeurtenisse nie ondersteun word nie);
  • Teken aksies aan.

Eerstens inisialiseer ons die blokketting:

Blockchain: wat moet ons 'n PoC bou?

Vervolgens begin ons ons rekening, moenie met die saldo skend wees nie:

Blockchain: wat moet ons 'n PoC bou?

Ons kry 'n lys van alle beskikbare rekeninge:

Blockchain: wat moet ons 'n PoC bou?

Ons kies die sender en ontvanger, ons kry hul saldo's. As die sender en ontvanger dieselfde is, sal sy rekening aangevul word:

Blockchain: wat moet ons 'n PoC bou?

In die log, monitor ons die uitvoering van transaksies:

Blockchain: wat moet ons 'n PoC bou?

Eintlik, met 'n demo-program, is dit al. Vervolgens kan u ons transaksie in die blokketting sien:

Blockchain: wat moet ons 'n PoC bou?

En die algemene lys van transaksies:

Blockchain: wat moet ons 'n PoC bou?

Hiermee het ons die implementering van die PoC suksesvol voltooi om die Citcoin-netwerk te skep. Wat moet nog gedoen word om Citcoin 'n volwaardige muntoordragnetwerk te maak? Baie min:

  • In die stadium van die skep van 'n rekening, implementeer die generering van 'n private / publieke sleutel. Die private sleutel moet gestoor word deur die gebruikersrekening, wat publiek op die blokketting is.
  • Maak 'n oordrag van munte, waarin nie 'n naam nie, maar 'n publieke sleutel gebruik word om die gebruiker te identifiseer.
  • Enkripteer transaksies wat van die gebruiker na die bediener gaan met sy private sleutel.

Gevolgtrekking

Ons het die Citcoin-netwerk geïmplementeer met die volgende funksies: voeg 'n rekening by, kry 'n balans, vul jou rekening aan, dra munte van een rekening na 'n ander oor. So wat het dit ons gekos om 'n PoC te bou?

  • Dit is nodig om die blokketting in die algemeen en Hyperledger Fabric in die besonder te bestudeer;
  • Leer hoe om IBM- of Amazon-wolke te gebruik;
  • Leer die JS-programmeertaal en 'n sekere webraamwerk;
  • As sommige data nie in die blokketting gestoor moet word nie, maar in 'n aparte databasis, leer dan hoe om byvoorbeeld met PostgreSQL te integreer;
  • En laaste maar nie die minste nie - sonder kennis van Linux in die moderne wêreld, nêrens nie!)

Natuurlik nie vuurpylwetenskap nie, maar jy moet sweet!

Bronne op GitHub

Bronne aangesit GitHub. Kort beskrywing van die bewaarplek:
Katalogus «bediener» - Node.js-bediener
Katalogus «kliënt» - Node.js kliënt
Katalogus «blockchain»(waardes van parameters en sleutels werk natuurlik nie en word slegs byvoorbeeld gegee):

  • kontrak - slim kontrak bron
  • beursie - gebruikerssleutels vir die gebruik van die Hyperledger Fabric API.
  • *.cd's - saamgestelde weergawes van slim kontrakte
  • *.json-lêers - voorbeelde van konfigurasielêers vir die gebruik van die Hyperledger Fabric API

Dis net die begin!

Bron: will.com

Voeg 'n opmerking