Blockchain Entwécklung fir Industrie mat Go. Deel 1

Zënter véier Méint hunn ech un engem Projet geschafft mam Numm "Entwécklung vum Dateschutz a Gestiounsinstrumenter a Regierungs- an Industriesecteuren baséiert op Blockchain."
Elo wéilt ech Iech soen wéi ech dëse Projet ugefaang hunn, an elo wäert ech de Programmcode am Detail beschreiwen.

Blockchain Entwécklung fir Industrie mat Go. Deel 1

Dëst ass den éischten Artikel an enger Serie vun Artikelen. Hei beschreiwen ech de Server a Protokoll. Tatsächlech kann de Lieser souguer seng eege Versioune vun dëse Blockchain Elementer schreiwen.

An hei ass den zweeten Deel - iwwer Blockchain an Transaktiounsdatenstrukturen, wéi och iwwer de Package deen Interaktioun mat der Datebank implementéiert.

D'lescht Joer, um Digital Breakthrough Hackathon, si si mat enger Iddi komm fir en nëtzlechen System fir d'Industrie an d'Digital Wirtschaft mat Hëllef vun verdeelt Ledger Technologie ze maachen; e Subventioun gouf och fir d'Entwécklung vum Innovation Assistance Fund ausgestallt (ech soll eng separat schreiwen Artikel iwwer de Subventioun, fir déi, déi just ufänken Startups ze maachen), an elo an Uerdnung.

Entwécklung fënnt an der Go Sprooch statt, an d'Datebank an där d'Blöcke gespäichert sinn ass LevelDB.
D'Haaptdeeler sinn de Protokoll, de Server (deen TCP a WebSocket leeft - déi éischt fir d'Blockchain ze synchroniséieren, déi zweet fir Clienten ze verbannen, Transaktiounen a Kommandoen aus JavaScript ze schécken, zum Beispill.

Wéi scho gesot, ass dëse Blockchain haaptsächlech gebraucht fir den Austausch vu Produkter tëscht Liwweranten a Clienten ze automatiséieren an ze schützen, oder béid an enger Persoun. Dës Leit sinn net presséiert géigesäiteg ze trauen. Awer d'Aufgab ass net nëmmen e "Checkbook" mat engem agebaute Rechner ze kreéieren, mee e System deen déi meescht vun de Routine Aufgaben automatiséiert, déi entstinn wann Dir mam Produktliewenszyklus schafft. De Bytecode, dee fir dës Matière verantwortlech ass, wéi et üblech ass mat Blockchainen, gëtt an den Inputen an Ausgänge vun Transaktiounen gespäichert (d'Transaktioune selwer ginn a Blocken gespäichert, d'Blöcke am LevelDB sinn am GOB-Format virkodéiert). Als éischt schwätze mer iwwer de Protokoll an de Server (alias Node).

De Protokoll ass net komplizéiert, säi ganze Punkt ass op de Modus ze wiesselen fir e puer Daten ze lueden, normalerweis e Block oder Transaktioun, als Äntwert op eng speziell Kommandozeil, an et ass och néideg fir Inventar auszetauschen, sou datt den Node weess wien et ass ass ugeschloss a wéi se Geschäfter hunn ze maachen (d'Noden, déi fir d'Synchroniséierungssitzung verbonne sinn, ginn och "Nopesch" genannt, well hir IP bekannt ass an hir Staatsdaten an der Erënnerung gespäichert sinn).

Folders (Verzeichnungen wéi Linux se nennt) am Verständnis vu Go Programméierer ginn Packagen genannt, also am Ufank vun all Datei mat Go Code aus dësem Verzeichnis schreiwen se Package folder_name_where_this_file. Soss kënnt Dir de Package net un de Compiler fidderen. Gutt, dëst ass kee Geheimnis fir déi, déi dës Sprooch kennen. Dëst sinn d'Packagen:

  • Netzwierk Kommunikatioun (Server, Client, Protokoll)
  • Strukture vu gespäicherten an iwwerdroenen Donnéeën (Block, Transaktioun)
  • Datebank (Blockchain)
  • Konsens
  • Gestapelt virtuell Maschinn (xvm)
  • Auxiliary (Krypto, Typen) dat ass alles fir de Moment.

Hei ass de Link op github

Dëst ass eng pädagogesch Versioun, et feelt Inter-Prozess Interaktioun a verschidde experimentell Komponenten, awer d'Struktur entsprécht deem op deem d'Entwécklung duerchgefouert gëtt. Wann Dir eppes an de Kommentaren ze proposéieren hutt, wäert ech frou et an der Weiderentwécklung Rechnung ze huelen. An elo fir eng Erklärung vum Server an Protokoll.

Loosst eis als éischt de Server kucken.

D'Server Subroutine wierkt als Dateserver deen uewen um TCP Protokoll leeft mat Datenstrukturen aus dem Protokollpaket.

D'Routine benotzt déi folgend Packagen: Server, Protokoll, Zorte. Am Package selwer tcp_server.go enthält Daten Struktur Serve.

type Serve struct {
	Port string
	BufSize int
	ST *types.Settings
}

Et kann déi folgend Parameteren akzeptéieren:

  • Netzwierkport duerch deen Daten austauscht ginn
  • Server Konfiguratiounsdatei am JSON Format
  • Fändel fir am Debug Modus ze lafen (private Blockchain)

Fortschrëtt:

  • Liest d'Konfiguratioun vun der JSON Datei
  • Den Debug Modus Fändel gëtt iwwerpréift: wann et agestallt ass, gëtt den Netzwierk Synchroniséierung Scheduler net gestart an de Blockchain ass net gelueden
  • D'Initialiséierung vun der Konfiguratiounsdatenstruktur an de Server starten

Server

  • Féiert de Start vum TCP Server an Netzwierk Interaktioun am Aklang mam Protokoll.
  • Et huet eng Serve-Datenstruktur besteet aus enger Portnummer, enger Puffergréisst an engem Zeiger op d'Struktur Zorte.Astellungen
  • D'Run-Methode fänkt d'Netzwierkinteraktioun un (lauschtert no erakommende Verbindungen op engem bestëmmten Hafen, wann eng nei Verbindung kritt gëtt, gëtt seng Veraarbechtung op d'private Handle-Methode an engem neie Fuedem transferéiert)
  • В packen Daten aus der Verbindung ginn an e Puffer gelies, an eng Stringrepresentatioun ëmgewandelt a weidergeleet Protokoll.Wiel
  • Protokoll.Wiel geet zréck Resultat oder verursaacht e Feeler. Resultat dann iwwerdroen ze Protokoll.Interpretéierendéi zréck intrpr - Objet vun Typ InterpretData, oder verursaacht e Feeler beim Veraarbechtung vum Selektiounsresultat
  • Da gëtt de Schalter ausgefouert intrpr.Commands[0] déi kontrolléiert ee vun: Resultat, inv, Feeler an et gëtt eng Rubrik Standarddrécker
  • An der Rubrik Resultat Schalter gëtt duerch Wäert fonnt intrpr.Commands[1] déi d'Wäerter iwwerpréift Bufferlängt и Versioun (an all Fall gëtt déi entspriechend Funktioun genannt)

Functions GetVersion и Buffer Längt sinn am Dossier srvlib.go Server Package

GetVersion(conn net.Conn, version string)

et dréckt einfach op d'Konsole a schéckt d'Versioun, déi am Parameter un de Client passéiert ass:

conn.Write([]byte("result:" + version))

.
Funktioun

BufferLength(conn net.Conn, intrpr *protocol.InterpreteData)

lued e Block, Transaktioun oder aner spezifesch Donnéeën wéi follegt:

  • Dréckt op d'Konsole d'Zort vun Daten, déi am Protokoll spezifizéiert sinn, déi akzeptéiert musse ginn:
    fmt.Println("DataType:", intrpr.Commands[2])
  • Liest de Wäert intrpr.Kierper zu enger numerescher Variabel buff_len
  • Erstellt e Puffer neibuf spezifizéiert Gréisst:
    make([]byte, buf_len)
  • Schéckt eng ok Äntwert:
    conn.Write([]byte("result:ok"))
  • Fëllt de Puffer komplett aus dem Liesstream:
    io.ReadFull(conn, newbuf)

    .

  • Dréckt den Inhalt vum Puffer op d'Konsole
    fmt.Println(string(newbuf))

    an d'Zuel vun Bytes liesen

    fmt.Println("Bytes length:", n)
  • Schéckt eng ok Äntwert:
    conn.Write([]byte("result:ok"))

Methoden aus dem Server Package sinn konfiguréiert fir kritt Daten ze veraarbecht mat Funktiounen aus dem Package Protokoll.

Protokoll

E Protokoll déngt als Mëttel dat Daten am Netzaustausch duerstellt.

Wiel (Str string) (String, Feeler) mécht primär Veraarbechtung vun Daten, déi vum Server kritt ginn, kritt eng String Representatioun vun den Daten als Input a bréngt e String zréck Dolmetscher:

  • D'Input String ass opgedeelt a Kapp a Kierper benotzt ReqParseN2(str)
  • De Kapp gëtt an Elementer opgedeelt an an e Kommando Slice gesat mat ReqParseHead (Kapp)
  • В schalt (Commande[0]) wielt de kritt Kommando (cmd, Schlëssel, Adress oder d'Sektioun gëtt ausgeléist Standarddrécker)
  • 2 Kommandoen ginn am cmd gepréift schalt (Kommando[1]) - Längt и getversion.
  • Längt kontrolléiert d'Datentyp Kommandoen [2] a rett et an Datatyp
  • Schecken dat Kierper enthält e Stringwäert
    len(body) < 1
  • Gitt d'Äntwert String zréck:
    "result:bufferlength:" + datatype + "/" + body
  • getversion gëtt eng String zréck
    return "result:version/auto"

Dolmetscher

Enthält d'InterpreteData Struktur a mécht sekundär Veraarbechtung vun den Donnéeën aus presentéiert Saiten an Objet Formatioun InterpretData.

type InterpreteData struct {
	Head string
	Commands []string
	Body string
	IsErr bool
	ErrCode int 
	ErrMessage string
}

Funktioun

Interprete(str string) (*InterpreteData, error)

akzeptéiert eng String Resultat a schafft a gëtt eng Referenz op den Objet zréck InterpretData.

Fortschrëtt:

  • Ähnlech presentéiert Kapp a Kierper ginn extrahéiert benotzt ReqParseN2(str)
  • Kapp gëtt an Elementer opgedeelt benotzt ReqParseHead (Kapp)
  • Den Objet gëtt initialiséiert InterpretData an en Zeigefanger drop gëtt zréckginn:

res := &InterpreteData{
	Head: head,
	Commands: commands,
	Body: body,
}
return res, nil

Dësen Objet gëtt benotzt an server.goen Package Haaptsäit.

Client

De Client Package enthält d'Funktiounen TCPConnect и TCPResponseData.

Funktioun

TCPConnect(s *types.Settings, data []byte, payload []byte)

funktionnéiert sou:

  • Eng Verbindung gëtt mat der Verbindung gemaach, déi am passéierten Astellungsobjekt spezifizéiert ass
    net.Dial("tcp", s.Host + ":" + s.Port)
  • D'Daten, déi am Dateparameter passéiert sinn, ginn iwwerdroen:
    conn.Write(data)
  • D'Äntwert ass gelies
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    an op der Konsol gedréckt

    fmt.Println(string(resp[:n]))
  • Wann iwwerdroen Notzlaascht da gitt et weider
    conn.Write(payload)

    a liest och d'Serverreaktioun, dréckt se op d'Konsole

Funktioun

 TCPResponseData(conn net.Conn, bufsiz int) ([]byte, int, error)

schaaft e Puffer vun der spezifizéierter Gréisst, liest d'Serverreaktioun do a gëtt dëse Puffer zréck an d'Zuel vun de Bytes gelies, souwéi e Feelerobjekt.

Client Subroutine

Déngt fir Kommandoen op Node Server ze schécken, souwéi kuerz Statistiken an Tester ze kréien.

Kann déi folgend Parameteren akzeptéieren: Konfiguratiounsdatei am JSON-Format, Donnéeën, déi op de Server als String geschéckt ginn, Wee fir d'Datei, déi op d'Notzlaascht geschéckt gëtt, Node Scheduler Emulatiounsflagg, Typ vun Daten, déi als numeresche Wäert transferéiert ginn.

  • Kréien d'Konfiguratioun
    st := types.ParseConfig(*config)
  • Wann den Emu Fändel passéiert ass, fänkt et un sheduler
  • Wann de f Fändel, deen de Wee op d'Datei weist, geliwwert gëtt, da luede mir seng Donnéeën an fdb an den Inhalt gëtt op de Server geschéckt
    client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
  • Wann d'Datei net spezifizéiert ass, da ginn d'Donnéeë vum Fändel einfach geschéckt -d:
    client.TCPConnect(st, []byte(*data), nil)

All dëst ass eng vereinfacht Representatioun déi d'Struktur vum Protokoll weist. Wärend der Entwécklung gëtt déi néideg Funktionalitéit zu senger Struktur bäigefüügt.

Am zweeten Deel wäert ech iwwer Datestrukture fir Blocken an Transaktiounen schwätzen, am 3 iwwer de WebSocket Server fir d'Verbindung vu JavaScript, am 4 wäert ech de Synchroniséierungsplang kucken, dann eng Stackmaschinn déi Bytecode vun Input an Output veraarbecht, Kryptografie an Pools fir Ausgänge.

Source: will.com

Setzt e Commentaire