Blockchain-ûntwikkeling foar yndustry mei Go. Diel 1

Foar fjouwer moannen haw ik wurke oan in projekt neamd "Untwikkeling fan gegevensbeskerming en behear ark yn oerheid en yndustriële sektoaren basearre op blockchain."
No wol ik jo fertelle oer hoe't ik dit projekt begon, en no sil ik de programmakoade yn detail beskriuwe.

Blockchain-ûntwikkeling foar yndustry mei Go. Diel 1

Dit is it earste artikel yn in searje artikels. Hjir beskriuw ik de tsjinner en protokol. Yn feite kin de lêzer sels syn eigen ferzjes skriuwe fan dizze blockchain-eleminten.

En hjir is it twadde diel - oer blockchain- en transaksjegegevensstruktueren, lykas oer it pakket dat ynteraksje mei de databank ymplementearret.

Ferline jier kamen se by de Digital Breakthrough hackathon op it idee om in nuttich systeem te meitsjen foar yndustry en de digitale ekonomy mei help fan distribuearre ledgertechnology; foar de ûntwikkeling is ek in subsydzje útrikt troch it Innovation Assistance Fund (ik soe in aparte skriuwe moatte) artikel oer de subsydzje, foar dyjingen dy't krekt begjinne opstarten ), en no yn oarder.

Untwikkeling fynt plak yn 'e Go-taal, en de database wêryn de blokken wurde opslein is LevelDB.
De wichtichste dielen binne it protokol, de tsjinner (dy't TCP en WebSocket rint - de earste foar syngronisaasje fan 'e blockchain, de twadde foar it ferbinen fan kliïnten, ferstjoeren fan transaksjes en kommando's fan JavaScript, bygelyks.

Lykas neamd wurdt, is dizze blockchain primêr nedich om de útwikseling fan produkten tusken leveransiers en klanten te automatisearjen en te beskermjen, of beide yn ien persoan. Dizze minsken hawwe gjin haast om inoar te fertrouwen. Mar de taak is net allinich om in "checkbook" te meitsjen mei in ynboude rekkenmasine, mar in systeem dat de measte routinetaken automatisearret dy't ûntsteane by it wurkjen mei de produktlibbensyklus. De bytekoade dy't ferantwurdlik is foar dizze saak, lykas gewoanlik is mei blockchains, wurdt opslein yn 'e yn- en útgongen fan transaksjes (de transaksjes sels wurde opslein yn blokken, de blokken yn LevelDB binne pre-kodearre yn it GOB-formaat). Litte wy earst prate oer it protokol en de tsjinner (aka node).

It protokol is net yngewikkeld, it hiele punt is om te wikseljen nei de modus fan it laden fan guon gegevens, meastentiids in blok of transaksje, yn antwurd op in spesjale kommandorigel, en it is ek nedich foar it útwikseljen fan ynventarisaasje, sadat de knoop wit wa't it is is ferbûn mei en hoe't se hawwe saken te dwaan (de knopen ferbûn foar de syngronisaasje sesje wurde ek neamd "buorjend" omdat harren IP is bekend en harren steat gegevens wurdt opslein yn it ûnthâld).

Mappen (mappen lykas Linux se neamt) yn it begryp fan Go-programmeurs wurde pakketten neamd, dus oan it begjin fan elke triem mei Go-koade út dizze map skriuwe se pakket folder_name_where_this_file. Oars kinne jo it pakket net nei de kompilator fiede. No, dit is gjin geheim foar dyjingen dy't dizze taal kenne. Dit binne de pakketten:

  • Netwurkkommunikaasje (tsjinner, client, protokol)
  • Struktueren fan opsleine en oerdroegen gegevens (blok, transaksje)
  • Databank (blockchain)
  • Konsensus
  • Opsteapele firtuele masine (xvm)
  • Auxiliary (crypto, typen) dat is alles foar no.

Hjir is de keppeling nei github

Dit is in edukative ferzje, it mist ynter-proses ynteraksje en ferskate eksperimintele komponinten, mar de struktuer komt oerien mei dejinge wêrop ûntwikkeling wurdt útfierd. As jo ​​​​wat hawwe om foar te stellen yn 'e opmerkingen, nim ik it graach yn' e fierdere ûntwikkeling yn 'e rekken. En no foar in útlis fan de tsjinner en Protokol.

Litte wy earst nei de tsjinner sjen.

De tsjinner subroutine fungearret as in gegevens tsjinner dy't rint boppe op it TCP protokol mei help fan gegevens struktueren út it protokol pakket.

De routine brûkt de folgjende pakketten: tsjinner, Protokol, typen. Yn it pakket sels tcp_server.go befettet gegevensstruktuer Serve.

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

It kin de folgjende parameters akseptearje:

  • Netwurkpoarte wêrmei gegevens sille wurde útwiksele
  • Tsjinnerkonfiguraasjetriem yn JSON-formaat
  • Flagge foar rinnen yn debugmodus (privee blockchain)

Foarútgong:

  • Lês konfiguraasje fan JSON-bestân
  • De flagge foar debugmodus wurdt kontrolearre: as it ynsteld is, wurdt de netwurksyngronisaasjeplanner net lansearre en wurdt de blockchain net laden
  • Inisjalisearjen fan de konfiguraasjegegevensstruktuer en begjinne de tsjinner

server

  • Fiert de lansearring fan 'e TCP-tsjinner en netwurkynteraksje út yn oerienstimming mei it protokol.
  • It hat in Serve gegevens struktuer besteande út in poarte nûmer, in buffer grutte en in oanwizer nei de struktuer types.Ynstellings
  • De Run-metoade begjint netwurkynteraksje (harkje nei ynkommende ferbiningen op in opjûne poarte, as in nije ferbining wurdt ûntfongen, wurdt de ferwurking oerbrocht nei de privee-hannelmetoade yn in nije thread)
  • В omgean gegevens fan de ferbining wurdt lêzen yn in buffer, omboud ta in tekenrige fertsjintwurdiging en trochjûn oan protokol.Keuze
  • protokol.Keuze jout werom resultaat of feroarsake in flater. resultaat dan oerdroegen oan protokol. Ynterpretearjedy't weromkomt yntrpr - foarwerp fan type InterpreteData, of feroarsake in flater by it ferwurkjen fan it seleksjeresultaat
  • Dan wurdt de skeakel útfierd intrpr.Commands[0] dy't ien fan kontrolearret: resultaat, inv, flater en der is in seksje standert
  • Yn de seksje resultaat switch wurdt fûn troch wearde intrpr.Commands[1] dy't kontrolearret de wearden bufferlengte и ferzje (yn elk gefal wurdt de oerienkommende funksje neamd)

Funksjes GetVersion и BufferLength binne yn de triem srvlib.go tsjinner pakket

GetVersion(conn net.Conn, version string)

it printsje gewoan nei de konsole en stjoert de ferzje trochjûn yn 'e parameter nei de kliïnt:

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

.
function

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

laadt in blok, transaksje, of oare spesifike gegevens as folget:

  • Printet op de konsole it type gegevens opjûn yn it protokol dat moat wurde akseptearre:
    fmt.Println("DataType:", intrpr.Commands[2])
  • Lêst de wearde intrpr.Body nei in numerike fariabele buff_len
  • Makket in buffer nijbuf oantsjutte grutte:
    make([]byte, buf_len)
  • Stjoert in ok antwurd:
    conn.Write([]byte("result:ok"))
  • Folslein de buffer fan 'e lêsstream foltôgje:
    io.ReadFull(conn, newbuf)

    .

  • Printet de ynhâld fan 'e buffer nei de konsole
    fmt.Println(string(newbuf))

    en it oantal bytes lêzen

    fmt.Println("Bytes length:", n)
  • Stjoert in ok antwurd:
    conn.Write([]byte("result:ok"))

Metoaden fan it serverpakket binne konfigureare om ûntfongen gegevens te ferwurkjen mei funksjes fan it pakket Protokol.

Protokol

In protokol tsjinnet as middel dat gegevens fertsjintwurdiget yn netwurkútwikseling.

Choice(str string) (string, flater) fiert primêre ferwurking út fan gegevens ûntfongen troch de tsjinner, ûntfangt in tekenrige foarstelling fan de gegevens as ynfier en jout in tekenrige werom Tolk:

  • De ynfier string wurdt opsplitst yn holle en lichem mei help ReqParseN2(str)
  • kop wurdt opdield yn eleminten en pleatst yn in kommando-slice mei ReqParseHead (kop)
  • В switch(opdrachten[0]) selektearje it ûntfongen kommando (cmd, kaai, adres of de seksje wurdt aktivearre standert)
  • 2 kommando's wurde kontrolearre yn cmd switch (opdrachten[1]) - lingte и getversion.
  • lingte kontrolearret it gegevenstype yn opdrachten [2] en bewarret it yn Soart data
  • Kontrolearret dat lichem befettet in tekenrige wearde
    len(body) < 1
  • Jout de antwurdstring werom:
    "result:bufferlength:" + datatype + "/" + body
  • getversion jout in tekenrige werom
    return "result:version/auto"

Tolk

Befettet de InterpreteData-struktuer en fiert sekundêre ferwurking fan 'e gegevens werom út Kar snaren en objektfoarming InterpreteData.

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

function

Interprete(str string) (*InterpreteData, error)

akseptearret in tekenrige resultaat en makket en jout in ferwizing nei it objekt InterpreteData.

Foarútgong:

  • Fergelykber Kar holle en lichem wurde ekstrahearre mei help ReqParseN2(str)
  • holle wurdt opdield yn eleminten mei help ReqParseHead (kop)
  • It objekt wurdt inisjalisearre InterpreteData en in oanwizer nei it wurdt weromjûn:

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

Dit objekt wurdt brûkt yn server.go pakket haad.

Kliïnt

It clientpakket befettet de funksjes TCPConnect и TCPResponseData.

function

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

wurket sa:

  • In ferbining wurdt makke mei de ferbining oantsjutte yn it trochjûne ynstellingsobjekt
    net.Dial("tcp", s.Host + ":" + s.Port)
  • De gegevens trochjûn yn 'e gegevensparameter wurde oerdroegen:
    conn.Write(data)
  • It antwurd wurdt lêzen
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    en printe op de konsole

    fmt.Println(string(resp[:n]))
  • As oerdroegen payload dan jout it troch
    conn.Write(payload)

    en ek lêst de tsjinner antwurd, printsjen it nei de konsole

function

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

makket in buffer fan de oantsjutte grutte, lêst de tsjinner antwurd dêr en jout dizze buffer en it oantal bytes lêzen, likegoed as in flater foarwerp.

Client subroutine

Tsjinnet om kommando's te stjoeren nei knooppuntservers, en ek koarte statistiken en testen te krijen.

Kin de folgjende parameters akseptearje: konfiguraasjetriem yn JSON-formaat, gegevens dy't moatte wurde stjoerd nei de tsjinner as in tekenrige, paad nei it bestân dat stjoerd wurdt nei loadload, flagge foar nodeplanner-emulaasje, type gegevens oerdroegen as in numerike wearde.

  • It krijen fan de konfiguraasje
    st := types.ParseConfig(*config)
  • As de emu-flagge wurdt trochjûn, begjint it sheduler
  • As de f-flagge dy't it paad nei it bestân oanjout wurdt levere, dan laden wy de gegevens yn fdb en de ynhâld wurdt stjoerd nei de tsjinner
    client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
  • As de triem net oantsjutte is, dan wurde de gegevens fan 'e flagge gewoan ferstjoerd -d:
    client.TCPConnect(st, []byte(*data), nil)

Dit alles is in ferienfâldige foarstelling dy't de struktuer fan it protokol sjen lit. Tidens ûntwikkeling wurdt de nedige funksjonaliteit tafoege oan syn struktuer.

Yn it twadde diel sil ik prate oer gegevensstruktueren foar blokken en transaksjes, yn 3 oer de WebSocket-tsjinner foar ferbining fan JavaScript, yn 4 sil ik sjen nei de syngronisaasjeplanner, dan in stapelmasine dy't bytekoade ferwurket fan yn- en útgongen, kryptografy en pools foar útgongen.

Boarne: www.habr.com

Add a comment