Lau hilabete daramatzat “Blokekatean oinarritutako datuak babesteko eta kudeatzeko tresnen garapena gobernu eta industria sektoreetan” izeneko proiektuan lanean nabil.
Orain proiektu hau nola hasi nuen kontatu nahiko nuke, eta orain programaren kodea zehatz-mehatz deskribatuko dut.
Artikulu sorta bateko lehen artikulua da. Hemen zerbitzaria eta protokoloa deskribatzen ditut. Izan ere, irakurleak bloke-katearen elementu horien bertsio propioak ere idatzi ditzake.
Iaz, Digital Breakthrough hackatoian, industriarako eta ekonomia digitalerako sistema baliagarri bat egiteko ideia bat bururatu zitzaien erregistro banatuaren teknologia erabiliz; Berrikuntzarako Laguntza Funtsak garatzeko beka bat ere eman zuen (bereiz idatzi beharko nuke. bekari buruzko artikulua, startup-ak hasi berriak direnentzat ), eta orain ordenan.
Garapena Go hizkuntzan egiten da, eta blokeak gordetzen diren datu-basea LevelDB da.
Zati nagusiak protokoloa, zerbitzaria (TCP eta WebSocket exekutatzen dituena - lehenengoa blockchain-a sinkronizatzeko, bigarrena bezeroak konektatzeko, transakzioak eta JavaScript-etik komandoak bidaltzeko, adibidez).
Esan bezala, bloke-kate hau hornitzaileen eta bezeroen arteko produktuen trukea automatizatzeko eta babesteko behar da, edo biak pertsona bakarrean. Pertsona hauek ez dute elkarrengan konfiantza izateko presarik. Baina zeregina ez da soilik kalkulagailu integratua duen "txeke-koadernoa" sortzea, produktuaren bizi-zikloarekin lan egitean sortzen diren ohiko zeregin gehienak automatizatzen dituen sistema bat baizik. Gai honen arduraduna den bytecodea, blockchainekin ohikoa den bezala, transakzioen sarrera eta irteeretan gordetzen da (transakzioak berak blokeetan gordetzen dira, LevelDB-ko blokeak GOB formatuan aurrez kodetuta daude). Lehenik eta behin, hitz egin dezagun protokoloaz eta zerbitzariaz (aka nodoaz).
Protokoloa ez da konplikatua, bere helburua datu batzuk kargatzeko modura aldatzea da, normalean bloke edo transakzio bat, komando-lerro berezi bati erantzunez, eta inbentarioa trukatzeko ere beharrezkoa da, nodoak nor den jakin dezan. konektatuta dagoen eta nola egin behar duten negozioa (sinkronizazio-saiorako konektatutako nodoei "inguruko" deitzen zaie, IP ezagutzen dutelako eta haien egoeraren datuak memorian gordetzen direlako).
Karpetei (Linuxek deitzen dien bezala direktorioei) Go programatzaileen ulermenean paketeak deitzen dira, beraz, direktorio honetako Go kodea duen fitxategi bakoitzaren hasieran paketea idazten dute karpeta_izena_non_fitxategi hau kokatzen den. Bestela, ezingo duzu paketea elikatu konpilatzaileari. Bada, hau ez da sekretua hizkuntza hau dakitenentzat. Hauek dira paketeak:
- Sareko komunikazioa (zerbitzaria, bezeroa, protokoloa)
- Biltegiratutako eta transmititutako datuen egiturak (blokea, transakzioa)
- Datu-basea (blockchain)
- Adostasuna
- Pilatutako makina birtuala (xvm)
- Laguntzaile (kripto, motak) hori da oraingoz.
Bertsio hezitzailea da, prozesuen arteko elkarrekintza eta hainbat osagai esperimental falta ditu, baina egitura garapena egiten ari denarekin bat dator. Iruzkinetan zerbait iradokitzeko baduzu, pozik hartuko dut kontuan garapenean. Eta orain zerbitzariaren azalpena eta protokoloa.
Ikus dezagun zerbitzaria lehenik.
Zerbitzariaren azpierrutinak TCP protokoloaren gainean exekutatzen den datu-zerbitzari gisa jokatzen du, protokolo paketearen datu-egiturak erabiliz.
Errutinak pakete hauek erabiltzen ditu: zerbitzaria, protokoloa, motak. Paketean bertan tcp_server.go datuen egitura dauka zerbitzatzeko.
type Serve struct {
Port string
BufSize int
ST *types.Settings
}
Parametro hauek onar ditzake:
- Datuak trukatuko diren sareko ataka
- Zerbitzariaren konfigurazio fitxategia JSON formatuan
- Markatu arazketa moduan exekutatzeko (bloke-kate pribatua)
Aurrerapena:
- JSON fitxategitik konfigurazioa irakurtzen du
- Arazketa moduaren bandera egiaztatuta dago: ezarrita badago, sareko sinkronizazio-planifikatzailea ez da abiarazten eta bloke-katea ez da kargatzen.
- Konfigurazio-datuen egitura hasieratzea eta zerbitzaria abiaraztea
Server
- TCP zerbitzariaren eta sareko interakzioa abiarazten du protokoloaren arabera.
- Portu-zenbaki batez, buffer-tamainaz eta egiturako erakusle batez osaturiko Serve datu-egitura du motak.Ezarpenak
- Exekutatu metodoak sareko elkarrekintza abiarazten du (portu jakin batean sarrerako konexioak entzuten, konexio berri bat jasotzen denean, bere prozesamendua kudeatzaile pribatuaren metodora transferitzen da hari berri batean)
- В kudeatzeko konexioko datuak buffer batean irakurtzen dira, katearen irudikapen bihurtzen dira eta bertara pasatzen dira protokoloa.Aukera
- protokoloa.Aukera itzultzen ondorioz edo errore bat eragiten du. ondorioz gero transferitu protokoloa.Interpretatuitzultzen dena intrpr - motako objektua InterpretatuData, edo errore bat eragiten du hautapenaren emaitza prozesatzen
- Ondoren, etengailua exekutatzen da intrpr.Komandoak[0] hauetako bat egiaztatzen duena: emaitza, inv, errore eta atal bat dago lehenetsi
- atalean ondorioz etengailua balioaren arabera aurkitzen da intrpr.Komandoak[1] balioak egiaztatzen dituena bufferren luzera и bertsioa (kasu bakoitzean dagokion funtzioari deitzen zaio)
funtzio LortuBertsioa и BufferLength fitxategian daude srvlib.go zerbitzari paketea
GetVersion(conn net.Conn, version string)
kontsolara inprimatu besterik ez du eta parametroan emandako bertsioa bezeroari bidaltzen dio:
conn.Write([]byte("result:" + version))
.
Funtzioa
BufferLength(conn net.Conn, intrpr *protocol.InterpreteData)
bloke, transakzio edo beste datu zehatz batzuk kargatzen ditu honela:
- Onartu beharreko protokoloan zehaztutako datu motak inprimatzen ditu kontsolara:
fmt.Println("DataType:", intrpr.Commands[2])
- Balioa irakurtzen du intrpr.Gorputza zenbakizko aldagai bati buf_len
- Buffer bat sortzen du berribuf zehaztutako tamaina:
make([]byte, buf_len)
- Ongi erantzun bat bidaltzen du:
conn.Write([]byte("result:ok"))
- Irakurketa korrontetik bufferra guztiz betetzen du:
io.ReadFull(conn, newbuf)
.
- Bufferaren edukia kontsolara inprimatzen du
fmt.Println(string(newbuf))
eta irakurritako byte kopurua
fmt.Println("Bytes length:", n)
- Ongi erantzun bat bidaltzen du:
conn.Write([]byte("result:ok"))
Zerbitzariaren paketearen metodoak jasotako datuak prozesatzeko konfiguratuta daude paketearen funtzioak erabiliz protokoloa.
Protokoloa
Protokolo batek sare-trukean datuak adierazten dituen bitarteko gisa balio du.
Aukera (katea) (katea, errorea) zerbitzariak jasotako datuen lehen tratamendua egiten du, datuen katearen irudikapena jasotzen du sarrera gisa eta prestatutako kate bat itzultzen du. Interpretea:
- Sarrerako katea buruan eta gorputzean zatitzen da erabiliz ReqParseN2(str)
- burua elementuetan zatitzen da eta komandoen zati batean jartzen da ReqParseHead(head) erabiliz
- В aldatu(aginduak[0]) hautatu jasotako komandoa (cmd, giltza, helbidea edo atala abiarazten da lehenetsi)
- 2 komando markatuta daude cmd-n switch(aginduak[1]) — luzera и getbertsioa.
- luzera datu-mota egiaztatzen du komandoak[2] eta bertan gordetzen du datatype
- Hori egiaztatzen du gorputza kate-balio bat dauka
len(body) < 1
- Erantzun katea ematen du:
"result:bufferlength:" + datatype + "/" + body
- getbertsioa kate bat itzultzen du
return "result:version/auto"
Interpretea
InterpreteData egitura dauka eta itzulitako datuen bigarren mailako prozesamendua egiten du Choice kateak eta objektuen eraketa InterpretatuData.
type InterpreteData struct {
Head string
Commands []string
Body string
IsErr bool
ErrCode int
ErrMessage string
}
Funtzioa
Interprete(str string) (*InterpreteData, error)
kate bat onartzen du ondorioz eta objektuari erreferentzia bat sortu eta itzultzen du InterpretatuData.
Aurrerapena:
- Era Choice burua eta gorputza ateratzen dira erabiliz ReqParseN2(str)
- burua elementuetan banatzen da erabiliz ReqParseHead(burua)
- Objektua hasieratzen da InterpretatuData eta horren erakusle bat itzultzen da:
res := &InterpreteData{
Head: head,
Commands: commands,
Body: body,
}
return res, nil
Objektu hau erabiltzen da zerbitzari.go pakete nagusia.
Bezero
Bezero paketeak funtzioak ditu TCPConnect и TCPResponseData.
Funtzioa
TCPConnect(s *types.Settings, data []byte, payload []byte)
honela funtzionatzen du:
- Konexio bat egiten da gainditutako ezarpenen objektuan zehaztutako konexioarekin
net.Dial("tcp", s.Host + ":" + s.Port)
- Datu parametroan pasatzen diren datuak transmititzen dira:
conn.Write(data)
- Erantzuna irakurtzen da
resp, n, _ := TCPResponseData(conn, s.BufSize)
eta kontsolan inprimatuta
fmt.Println(string(resp[:n]))
- Transferitu bada karga gero pasatzen du
conn.Write(payload)
eta zerbitzariaren erantzuna ere irakurtzen du, kontsolara inprimatuz
Funtzioa
TCPResponseData(conn net.Conn, bufsiz int) ([]byte, int, error)
zehaztutako tamainako buffer bat sortzen du, hor zerbitzariaren erantzuna irakurtzen du eta buffer hori eta irakurritako byte kopurua itzultzen ditu, baita errore-objektu bat ere.
Bezeroaren azpierrutina
Nodo zerbitzarietara komandoak bidaltzeko balio du, baita estatistika eta proba laburrak lortzeko ere.
Parametro hauek onar ditzake: konfigurazio-fitxategia JSON formatuan, zerbitzariari kate gisa bidali beharreko datuak, kargara bidali beharreko fitxategiaren bidea, nodo-planifikatzailearen emulazio-marka, zenbakizko balio gisa transferitutako datu-mota.
- Konfigurazioa lortzea
st := types.ParseConfig(*config)
- Emu bandera pasatzen bada, hasten da egitaraua
- Fitxategiaren bidea adierazten duen f bandera ematen bada, orduan kargatuko ditugu bere datuak fdb eta edukia zerbitzarira bidaltzen da
client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
- Fitxategia zehazten ez bada, banderako datuak besterik gabe bidaltzen dira -d:
client.TCPConnect(st, []byte(*data), nil)
Hau guztia protokoloaren egitura erakusten duen irudikapen sinplifikatua da. Garapenean, beharrezko funtzionaltasuna gehitzen zaio bere egiturari.
Bigarren zatian blokeen eta transakzioen datu-egiturei buruz hitz egingo dut, 3.ean JavaScript-etik konektatzeko WebSocket zerbitzariari buruz, 4.ean sinkronizazio-planifikatzaileari begiratuko diot, gero sarrera eta irteeratik bytecode prozesatzen duen pila-makina, kriptografia eta irteerarako igerilekuak.
Iturria: www.habr.com