Blockchain razvoj za industriju koristeći Go. Dio 1

Već četiri mjeseca radim na projektu pod nazivom „Razvoj alata za zaštitu podataka i upravljanje u državnim i industrijskim sektorima na bazi blockchaina“.
Sada bih vam želio reći kako sam započeo ovaj projekat, a sada ću detaljno opisati programski kod.

Blockchain razvoj za industriju koristeći Go. Dio 1

Ovo je prvi članak u nizu članaka. Ovdje opisujem server i protokol. Zapravo, čitatelj može čak i napisati vlastite verzije ovih blokchain elemenata.

A evo i drugog dijela — o blockchain i strukturama podataka transakcija, kao io paketu koji implementira interakciju sa bazom podataka.

Prošle godine su na hackathonu Digital Breakthrough došli na ideju da naprave koristan sistem za industriju i digitalnu ekonomiju koristeći tehnologiju distribuirane knjige, a za razvoj je izdat i grant od strane Fonda za pomoć inovacijama (trebao bih napisati posebnu članak o grantu, za one koji tek pokreću startape), a sada redom.

Razvoj se odvija u jeziku Go, a baza podataka u kojoj su pohranjeni blokovi je LevelDB.
Glavni dijelovi su protokol, server (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 veruju jedni drugima. Ali zadatak nije samo kreiranje „čekovne knjižice“ sa ugrađenim kalkulatorom, već i sistem koji automatizuje većinu rutinskih zadataka koji se javljaju pri radu sa životnim ciklusom proizvoda. Bajtkod koji je odgovoran za ovo pitanje, kao što je uobičajeno kod blockchaina, pohranjuje se na ulazima i izlazima transakcija (sama transakcije su pohranjene u blokovima, blokovi u LevelDB-u su unaprijed kodirani u GOB formatu). Prvo, hajde da pričamo o protokolu i serveru (aka čvor).

Protokol nije komplikovan, cijela mu je poenta da se prebaci na način učitavanja nekih podataka, obično bloka ili transakcije, kao odgovor na posebnu komandnu liniju, a potreban je i za razmjenu inventara, kako bi čvor znao ko je je povezan i na koji način imaju posla (čvorovi povezani za sesiju sinhronizacije se također nazivaju „susjednim“ jer je njihova IP adresa poznata i podaci o njihovom stanju su pohranjeni u memoriji).

Fascikle (direktorijumi kako ih Linux naziva) u razumijevanju Go programera nazivaju se paketi, tako da na početku svake datoteke sa Go kodom iz ovog direktorija pišu naziv foldera_gdje se_ova_datoteka nalazi. U suprotnom, nećete moći predati paket kompajleru. Pa, to nije tajna za one koji znaju ovaj jezik. Ovo su paketi:

  • Mrežna komunikacija (server, klijent, protokol)
  • Strukture pohranjenih i prenesenih podataka (blok, transakcija)
  • Baza podataka (blockchain)
  • Konsenzus
  • Naslagana virtuelna mašina (xvm)
  • Pomoćni (kripto, tipovi) to je sve za sada.

Evo linka na github

Ovo je obrazovna verzija, nedostaje joj međuprocesna interakcija i nekoliko eksperimentalnih komponenti, ali struktura odgovara onoj na kojoj se odvija razvoj. Ako imate nešto da predložite u komentarima, rado ću to uzeti u obzir u daljem razvoju. A sada za objašnjenje servera i protokol.

Pogledajmo prvo server.

Podrutina servera djeluje kao poslužitelj podataka koji radi na vrhu TCP protokola koristeći strukture podataka iz paketa protokola.

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

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

Može prihvatiti sljedeće parametre:

  • Mrežni port preko kojeg će se podaci razmjenjivati
  • Konfiguracijski fajl servera u JSON formatu
  • Oznaka za rad u načinu za otklanjanje grešaka (privatni blockchain)

napredak:

  • Čita konfiguraciju iz JSON datoteke
  • Oznaka načina otklanjanja grešaka je označena: ako je postavljena, planer mrežne sinkronizacije se ne pokreće i blockchain se ne učitava
  • Inicijalizacija strukture podataka konfiguracije i pokretanje servera

server

  • Vrši pokretanje TCP servera i mrežnu interakciju u skladu sa protokolom.
  • Ima strukturu podataka Serve koja se sastoji od broja porta, veličine bafera i pokazivača na strukturu vrste.Postavke
  • Metoda Run pokreće mrežnu interakciju (osluškujući dolazne veze na datom portu, kada se primi nova veza, njena obrada se prenosi na metodu privatnog rukovanja u novoj niti)
  • В rukovati podaci iz veze se čitaju u bafer, pretvaraju u nizove i prosljeđuju u protokol.Izbor
  • protokol.Izbor vraća rezultat ili uzrokuje grešku. rezultat zatim prebačen u protokol. Interpretekoji se vraća intrpr - objekt tipa InterpreteData, ili uzrokuje grešku u obradi rezultata odabira
  • Zatim se izvršava prebacivanje intrpr.Commands[0] koji provjerava jedno od: rezultat, inv, greška i postoji dio default
  • U sekciji rezultat prekidač se nalazi po vrijednosti intrpr.Commands[1] koji provjerava vrijednosti baferlength и verzija (u svakom slučaju se poziva odgovarajuća funkcija)

Funkcije GetVersion и BufferLength nalaze se u fajlu srvlib.go serverski paket

GetVersion(conn net.Conn, version string)

jednostavno se 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 tip podataka naveden u protokolu koji treba prihvatiti:
    fmt.Println("DataType:", intrpr.Commands[2])
  • Čita vrijednost intrpr.Body na numeričku varijablu buf_len
  • Kreira bafer newbuf navedena veličina:
    make([]byte, buf_len)
  • Šalje u redu odgovor:
    conn.Write([]byte("result:ok"))
  • Potpuno popunjava bafer iz toka čitanja:
    io.ReadFull(conn, newbuf)

    .

  • Ispisuje sadržaj bafera na konzolu
    fmt.Println(string(newbuf))

    i broj pročitanih bajtova

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

Metode iz serverskog paketa su konfigurirane za obradu primljenih podataka korištenjem funkcija iz paketa protokol.

protokol

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

Izbor (str niz) (niz, greška) obavlja primarnu obradu podataka primljenih od servera, prima string reprezentaciju podataka kao ulaz i vraća string pripremljen za Tumač:

  • Ulazni niz se dijeli na glavu i tijelo pomoću ReqParseN2(str)
  • glava je podijeljena na elemente i smještena u komad komandi pomoću ReqParseHead(head)
  • В prekidač (naredbe[0]) izaberite primljenu komandu (cmd, ključ, adresa ili se sekcija aktivira default)
  • 2 komande su provjerene u cmd switch(commands[1]) — dužina и getversion.
  • dužina provjerava tip podataka naredbe[2] i sprema ga tip podataka
  • Provjerava to tijelo sadrži vrijednost niza
    len(body) < 1
  • Vraća niz odgovora:
    "result:bufferlength:" + datatype + "/" + body
  • getversion vraća string
    return "result:version/auto"

Tumač

Sadrži strukturu InterpreteData i obavlja 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)

prihvata niz rezultat i kreira i vraća referencu na objekt InterpreteData.

napredak:

  • Slično tome izbor glava i tijelo se izvlače pomoću ReqParseN2(str)
  • glava se dijeli na elemente pomoću ReqParseHead(glava)
  • Objekt je inicijaliziran InterpreteData i pokazivač na njega se vraća:

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

Ovaj objekat se koristi u server.go paket glavni.

Klijent

Klijentski paket sadrži funkcije TCPConnect и TCPResponseData.

funkcija

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

djeluje na sljedeći način:

  • Uspostavlja se veza sa vezom navedenom u prenesenom objektu postavki
    net.Dial("tcp", s.Host + ":" + s.Port)
  • Podaci proslijeđeni u parametru podataka se prenose:
    conn.Write(data)
  • Odgovor je pročitan
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    i odštampan na konzoli

    fmt.Println(string(resp[:n]))
  • Ako se prenese nosivost onda ga prenosi dalje
    conn.Write(payload)

    i takođe čita odgovor servera, štampajući ga na konzoli

funkcija

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

kreira bafer određene veličine, tamo čita odgovor servera i vraća ovaj bafer i broj pročitanih bajtova, kao i objekat greške.

Podprogram klijenta

Služi za slanje komandi serverima čvorova, kao i za dobijanje kratke statistike i testiranja.

Može prihvatiti sljedeće parametre: konfiguracionu datoteku u JSON formatu, podatke koji se šalju na server kao string, putanju do datoteke koja se šalje u korisni teret, zastavicu emulacije planera čvora, tip podataka koji se prenosi kao numerička vrijednost.

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

Sve ovo je pojednostavljena reprezentacija koja pokazuje strukturu protokola. Tokom razvoja, njegovoj strukturi se dodaje potrebna funkcionalnost.

U drugom dijelu ću govoriti o strukturama podataka za blokove i transakcije, u 3. o WebSocket serveru za povezivanje sa JavaScript-a, u 4. ću pogledati planer sinhronizacije, zatim stack mašinu koja obrađuje bajt kod sa ulaza i izlaza, kriptografiju i bazeni za izlaze.

izvor: www.habr.com

Dodajte komentar