Razvoj blockchaina za industriju koja koristi Go. 1. dio

Već četiri mjeseca radim na projektu pod nazivom “Razvoj alata za zaštitu i upravljanje podacima u državnom i industrijskom sektoru temeljen na blockchainu”.
Sada bih vam želio ispričati kako sam započeo ovaj projekt, a sada ću detaljno opisati programski kod.

Razvoj blockchaina za industriju koja koristi Go. 1. dio

Ovo je prvi članak u nizu članaka. Ovdje opisujem poslužitelj i protokol. Zapravo, čitatelj čak može napisati vlastitu verziju ovih elemenata blockchaina.

A evo i drugog dijela — o blockchainu i transakcijskim podatkovnim strukturama, kao io paketu koji implementira interakciju s bazom podataka.

Prošle godine na hackathonu Digital Breakthrough došli su na ideju napraviti koristan sustav za industriju i digitalnu ekonomiju koristeći distributed ledger tehnologiju, također je izdana bespovratna sredstva za razvoj od strane Innovation Assistance Fund (trebao bih napisati zasebno članak o bespovratnim sredstvima, za one koji se tek počinju baviti startupima ), a sada po redu.

Razvoj se odvija u Go jeziku, a baza podataka u kojoj se pohranjuju blokovi je LevelDB.
Glavni dijelovi su protokol, poslužitelj (koji pokreće TCP i WebSocket – prvi za sinkronizaciju blockchaina, drugi za povezivanje klijenata, slanje transakcija i naredbi iz JavaScripta, na primjer.

Kao što je spomenuto, ovaj blockchain je prvenstveno potreban za automatizaciju i zaštitu razmjene proizvoda između dobavljača i kupaca, ili oboje u jednoj osobi. Ovi ljudi ne žure da vjeruju jedni drugima. Ali zadatak nije samo stvoriti "čekovnu knjižicu" s ugrađenim kalkulatorom, već sustav koji automatizira većinu rutinskih zadataka koji se javljaju pri radu sa životnim ciklusom proizvoda. Bytecode koji je odgovoran za tu stvar, kao što je uobičajeno kod blockchaina, pohranjen je u ulazima i izlazima transakcija (same transakcije su pohranjene u blokovima, blokovi u LevelDB-u su unaprijed kodirani u GOB formatu). Prvo, razgovarajmo o protokolu i poslužitelju (aka čvor).

Protokol nije kompliciran, cijela mu je poanta da se kao odgovor na posebnu naredbenu liniju prebaci u mod učitavanja nekog podatka, obično bloka ili transakcije, a potreban je i za razmjenu inventara, kako bi čvor znao tko je s kojim je povezan i kako imaju posla (čvorovi povezani za sesiju sinkronizacije nazivaju se i "susjedima" jer je njihov IP poznat, a podaci o stanju pohranjeni su u memoriji).

Mape (direktorije kako ih Linux naziva) u shvaćanju Go programera nazivaju se paketima, pa na početku svake datoteke s Go kodom iz ove mape napišu naziv mape_paketa_gdje_se_ova_datoteka nalazi. U suprotnom, nećete moći ubaciti paket u kompajler. Pa, to nije tajna za poznavaoce ovog jezika. Ovo su paketi:

  • Mrežna komunikacija (poslužitelj, klijent, protokol)
  • Strukture pohranjenih i prenesenih podataka (blok, transakcija)
  • Baza podataka (blockchain)
  • Konsenzus
  • Složeni virtualni stroj (xvm)
  • Pomoćni (kripto, vrste) to je sve za sada.

Ovdje je poveznica na github

Ovo je edukativna verzija, nedostaje joj međuprocesna interakcija i nekoliko eksperimentalnih komponenti, ali struktura odgovara onoj na kojoj se odvija razvoj. Ako imate što predložiti u komentarima, rado ću to uzeti u obzir u daljnjem razvoju. A sada objašnjenje poslužitelja i protokol.

Pogledajmo prvo poslužitelj.

Podrutina poslužitelja djeluje kao podatkovni poslužitelj koji radi povrh TCP protokola koristeći podatkovne strukture iz paketa protokola.

Rutina koristi sljedeće pakete: server, protokol, vrste. U samom paketu tcp_server.go sadrži strukturu podataka Poslužiti.

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

Može prihvatiti sljedeće parametre:

  • Mrežni priključak preko kojeg će se razmjenjivati ​​podaci
  • Konfiguracijska datoteka poslužitelja u JSON formatu
  • Oznaka za pokretanje u načinu rada za otklanjanje pogrešaka (privatni blockchain)

Napredak:

  • Čita konfiguraciju iz JSON datoteke
  • Oznaka načina otklanjanja pogrešaka je provjerena: ako je postavljena, planer mrežne sinkronizacije se ne pokreće i blockchain se ne učitava
  • Inicijalizacija konfiguracijske strukture podataka i pokretanje poslužitelja

Server

  • Provodi pokretanje TCP poslužitelja i mrežne interakcije u skladu s protokolom.
  • Ima Serve podatkovnu strukturu koja se sastoji od broja porta, veličine međuspremnika i pokazivača na strukturu vrste.Postavke
  • Metoda Run pokreće mrežnu interakciju (osluškuje dolazne veze na danom portu, kada se primi nova veza, njezina obrada se prenosi na metodu privatnog rukovanja u novoj niti)
  • В rukovati podaci iz veze se čitaju u međuspremnik, pretvaraju u prikaz niza i prosljeđuju protokol.Izbor
  • protokol.Izbor vraća rezultirati ili uzrokuje grešku. rezultirati zatim prebačen u protokol.Tumačitikoji se vraća intrpr - objekt vrste InterpreteData, ili uzrokuje pogrešku u obradi rezultata odabira
  • Zatim se izvrši prekidač intrpr.Naredbe[0] koji provjerava jedno od: rezultat, inv, greška i postoji odjeljak zadani
  • U odjeljku rezultirati prekidač se nalazi prema vrijednosti intrpr.Naredbe[1] koji provjerava vrijednosti duljina međuspremnika и verzija (u svakom slučaju poziva se odgovarajuća funkcija)

Funkcije GetVersion и BufferLength su u datoteci srvlib.go poslužiteljski paket

GetVersion(conn net.Conn, version string)

jednostavno ispisuje na konzolu i klijentu šalje verziju proslijeđenu u parametru:

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

.
Funkcija

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

učitava blok, transakciju ili druge specifične podatke na sljedeći način:

  • Ispisuje na konzolu vrstu podataka navedenih u protokolu koje treba prihvatiti:
    fmt.Println("DataType:", intrpr.Commands[2])
  • Čita vrijednost intrpr.Tijelo na numeričku varijablu buf_len
  • Stvara međuspremnik newbuf navedena veličina:
    make([]byte, buf_len)
  • Šalje ok odgovor:
    conn.Write([]byte("result:ok"))
  • Potpuno ispunjava međuspremnik iz toka čitanja:
    io.ReadFull(conn, newbuf)

    .

  • Ispisuje sadržaj međuspremnika na konzolu
    fmt.Println(string(newbuf))

    i broj pročitanih bajtova

    fmt.Println("Bytes length:", n)
  • Šalje ok odgovor:
    conn.Write([]byte("result:ok"))

Metode iz poslužiteljskog paketa konfigurirane su za obradu primljenih podataka pomoću funkcija iz paketa protokol.

Protokol

Protokol služi kao sredstvo koje predstavlja podatke u mrežnoj razmjeni.

Choice(str string) (string, error) obavlja primarnu obradu podataka primljenih od strane poslužitelja, prima string reprezentaciju podataka kao ulaz i vraća niz pripremljen za Tumač:

  • Ulazni niz je podijeljen na glavu i tijelo korištenjem ReqParseN2(str)
  • glava se dijeli na elemente i postavlja u isječak naredbi pomoću ReqParseHead(head)
  • В prekidač (naredbe[0]) odaberite primljenu naredbu (cmd, ključ, adresa ili se dionica aktivira zadani)
  • 2 naredbe se provjeravaju u cmd-u prekidač(naredbe[1]) — duljina и dobiti verziju.
  • dužina provjerava tip podataka naredbe[2] i sprema ga u tip podataka
  • Provjerava to tijelo sadrži vrijednost niza
    len(body) < 1
  • Vraća niz odgovora:
    "result:bufferlength:" + datatype + "/" + body
  • dobiti verziju vraća niz
    return "result:version/auto"

Tumač

Sadrži strukturu InterpreteData i izvodi sekundarnu obradu podataka vraćenih iz Izbor nizovi i formiranje objekata InterpreteData.

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

Funkcija

Interprete(str string) (*InterpreteData, error)

prihvaća niz rezultirati te stvara i vraća referencu na objekt InterpreteData.

Napredak:

  • slično Izbor glava i tijelo se izvlače pomoću ReqParseN2(str)
  • glava je podijeljena na elemente pomoću ReqParseHead(head)
  • Objekt je inicijaliziran InterpreteData i vraća se pokazivač na njega:

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

Ovaj objekt se koristi u server.go glavni paket.

Klijent

Paket klijenta sadrži funkcije TCPConnect и TCPResponseData.

Funkcija

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

djeluje na sljedeći način:

  • Veza se uspostavlja s vezom navedenom u proslijeđenom objektu postavki
    net.Dial("tcp", s.Host + ":" + s.Port)
  • Podaci proslijeđeni u parametru podataka prenose se:
    conn.Write(data)
  • Odgovor se čita
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    i ispisuje se na konzoli

    fmt.Println(string(resp[:n]))
  • Ako se prenese korisna nosivost zatim ga prosljeđuje dalje
    conn.Write(payload)

    i također čita odgovor poslužitelja ispisujući ga na konzolu

Funkcija

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

stvara međuspremnik navedene veličine, tamo čita odgovor poslužitelja i vraća ovaj međuspremnik i broj pročitanih bajtova, kao i objekt pogreške.

Podrutina klijenta

Služi za slanje naredbi poslužiteljima čvorova, kao i za dobivanje kratkih statistika i testiranja.

Može prihvatiti sljedeće parametre: konfiguracijsku datoteku u JSON formatu, podatke koji se šalju poslužitelju kao niz, stazu do datoteke koja se šalje u korisni teret, oznaku emulacije planera čvora, vrstu podataka koji se prenose kao numeričku vrijednost.

  • Dobivanje konfiguracije
    st := types.ParseConfig(*config)
  • Ako je proslijeđena emu zastavica, počinje sheduler
  • Ako je navedena zastavica f koja označava stazu do datoteke, tada učitavamo njezine podatke fdb a sadržaj se šalje na poslužitelj
    client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
  • Ako datoteka nije navedena, podaci iz oznake se jednostavno šalju -d:
    client.TCPConnect(st, []byte(*data), nil)

Sve ovo je pojednostavljeni prikaz koji prikazuje strukturu protokola. Tijekom razvoja njegovoj se strukturi dodaje potrebna funkcionalnost.

U drugom dijelu govorit ću o podatkovnim strukturama za blokove i transakcije, u 3. o WebSocket poslužitelju za povezivanje iz JavaScripta, u 4. ću se osvrnuti na planer sinkronizacije, zatim stack stroj koji obrađuje bytecode iz ulaza i izlaza, kriptografiju i bazeni za izlaze.

Izvor: www.habr.com

Dodajte komentar