Devlopman Blockchain pou endistri lè l sèvi avèk Go. Pati 1

Depi kat mwa kounye a mwen ap travay sou yon pwojè ki rele "Devlopman pwoteksyon done ak zouti jesyon nan gouvènman an ak sektè endistriyèl ki baze sou blockchain."
Koulye a, mwen ta renmen di ou sou ki jan mwen te kòmanse pwojè sa a, epi kounye a mwen pral dekri kòd pwogram nan an detay.

Devlopman Blockchain pou endistri lè l sèvi avèk Go. Pati 1

Sa a se premye atik nan yon seri de atik. Isit la mwen dekri sèvè a ak pwotokòl. An reyalite, lektè a ka menm ekri pwòp vèsyon li nan eleman sa yo blòk.

Ak isit la se dezyèm pati a — sou blòk ak estrikti done tranzaksyon yo, osi byen ke sou pake a ki aplike entèraksyon ak baz done a.

Ane pase a, nan Hackathon Digital Breakthrough, yo te vini ak yon lide pou fè yon sistèm itil pou endistri ak ekonomi dijital la lè l sèvi avèk teknoloji liv distribiye; Fon Asistans Inovasyon te bay yon sibvansyon tou pou devlopman (mwen ta dwe ekri yon lòt dokiman separe). atik sou sibvansyon an, pou moun ki jis kòmanse demaraj), e kounye a, nan lòd.

Devlopman fèt nan lang Go, ak baz done kote blòk yo estoke se LevelDB.
Pati prensipal yo se pwotokòl la, sèvè a (ki kouri TCP ak WebSocket - premye a pou senkronize blockchain a, dezyèm lan pou konekte kliyan, voye tranzaksyon ak kòmandman soti nan JavaScript, pou egzanp.

Kòm yo te mansyone, blòk sa a nesesè prensipalman pou otomatize ak pwoteje echanj pwodwi ant founisè ak kliyan, oswa toude nan yon sèl moun. Moun sa yo pa prese pou youn fè lòt konfyans. Men, travay la se pa sèlman yo kreye yon "chèk" ak yon kalkilatris bati-an, men yon sistèm ki otomatize pi fò nan travay yo woutin ki rive lè w ap travay ak sik la lavi pwodwi. Bytecode ki responsab zafè sa a, jan sa abitye ak blockchains, yo estoke nan antre ak rezilta tranzaksyon yo (tranzaksyon yo tèt yo yo estoke nan blòk, blòk yo nan LevelDB yo pre-kode nan fòma GOB). Premyèman, ann pale sou pwotokòl la ak sèvè a (aka ne).

Pwotokòl la pa konplike, pwen antye li se chanje nan mòd nan chaje kèk done, anjeneral, yon blòk oswa tranzaksyon, an repons a yon liy lòd espesyal, epi li nesesè tou pou echanj envantè, se konsa ke ne a konnen ki moun li. se konekte ak ki jan yo gen biznis yo fè (nœuds ki konekte pou sesyon an senkronizasyon yo rele tou "vwazen" paske IP yo li te ye epi done eta yo estoke nan memwa).

Dosye (anyè kòm Linux rele yo) nan konpreyansyon yo genyen sou pwogramasyon Go yo rele pakè, se konsa nan kòmansman an nan chak dosye ak kòd Go soti nan anyè sa a yo ekri pake folder_name_where_this_file sitiye. Sinon, ou pa pral kapab bay pakè a nan du a. Oke, sa a pa sekrè pou moun ki konnen lang sa a. Sa yo se pakè yo:

  • Kominikasyon rezo (sèvè, kliyan, pwotokòl)
  • Estrikti done ki estoke ak transmèt (blòk, tranzaksyon)
  • Baz done (blockchain)
  • Konsantman
  • Anpile machin vityèl (xvm)
  • Oksilyè (kripto, kalite) sa a tout pou kounye a.

Men lyen ki mennen nan github

Sa a se yon vèsyon edikatif, li manke entèraksyon entè-pwosesis ak plizyè eleman eksperimantal, men estrikti a koresponn ak youn nan ki devlopman yo te pote. Si ou gen nenpòt bagay yo sijere nan kòmantè yo, mwen pral kontan pran li an kont nan plis devlopman. Epi, koulye a pou yon eksplikasyon sou sèvè a ak pwotokòl.

Ann gade sèvè an premye.

Souroutine sèvè a aji kòm yon sèvè done ki kouri sou tèt pwotokòl TCP la lè l sèvi avèk estrikti done ki soti nan pake pwotokòl la.

Woutin nan itilize pakè sa yo: sèvè, pwotokòl, kalite. Nan pake a li menm tcp_server.go gen estrikti done Sèvi.

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

Li ka aksepte paramèt sa yo:

  • Pò rezo kote done yo pral fè echanj
  • Fichye konfigirasyon sèvè nan fòma JSON
  • Flag pou kouri nan mòd debug (blockchain prive)

Pwogrè:

  • Li konfigirasyon nan dosye JSON
  • Yo tcheke drapo mòd debug la: si li mete, pwogramasyon senkronizasyon rezo a pa lanse epi blockchain a pa chaje.
  • Inisyalize estrikti done konfigirasyon an epi kòmanse sèvè a

sèvè

  • Fè lansman sèvè TCP a ak rezo entèraksyon an akò ak pwotokòl la.
  • Li gen yon estrikti done Sèvi ki fòme ak yon nimewo pò, yon gwosè tanpon ak yon konsèy sou estrikti a kalite.Anviwònman
  • Metòd Run la kòmanse entèraksyon rezo a (koute koneksyon fèk ap rantre sou yon pò bay, lè yo resevwa yon nouvo koneksyon, pwosesis li yo transfere nan metòd manch prive a nan yon nouvo fil)
  • В manyen done ki soti nan koneksyon an li nan yon tanpon, konvèti nan yon reprezantasyon fisèl epi yo pase nan pwotokòl.Chwa
  • pwotokòl.Chwa retounen lakòz oswa lakòz yon erè. lakòz Lè sa a, transfere nan pwotokòl.Entèpreteki retounen intrpr - objè nan kalite InterpreteData, oswa lakòz yon erè nan pwosesis rezilta seleksyon an
  • Lè sa a, switch la egzekite Intrpr.Commands[0] ki tcheke youn nan: rezilta, env, erè epi gen yon seksyon default
  • Nan seksyon an lakòz switch yo jwenn pa valè Intrpr.Commands[1] ki tcheke valè yo longè tanpon и vèsyon (nan chak ka yo rele fonksyon korespondan an)

Fonksyon GetVersion и Tanpon Length yo nan dosye a srvlib.go pake sèvè

GetVersion(conn net.Conn, version string)

li tou senpleman enprime nan konsole a epi voye vèsyon an pase nan paramèt la bay kliyan an:

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

.
Fonksyon

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

chaje yon blòk, tranzaksyon, oswa lòt done espesifik jan sa a:

  • Enprime sou konsole a kalite done ki espesifye nan pwotokòl la ki bezwen aksepte:
    fmt.Println("DataType:", intrpr.Commands[2])
  • Li valè a intrpr.Kò nan yon varyab nimerik buf_len
  • Kreye yon tanpon newbuf gwosè espesifye:
    make([]byte, buf_len)
  • Voye yon repons ok:
    conn.Write([]byte("result:ok"))
  • Konplètman ranpli tanpon ki soti nan kouran lekti a:
    io.ReadFull(conn, newbuf)

    .

  • Enprime sa ki nan tanpon an nan konsole a
    fmt.Println(string(newbuf))

    ak kantite bytes li

    fmt.Println("Bytes length:", n)
  • Voye yon repons ok:
    conn.Write([]byte("result:ok"))

Metòd ki soti nan pake sèvè a yo configuré pou trete done resevwa lè l sèvi avèk fonksyon ki soti nan pake a pwotokòl.

Pwotokòl

Yon pwotokòl sèvi kòm yon mwayen ki reprezante done nan echanj rezo a.

Chwa (string string) (string, erè) fè tretman prensipal done sèvè a resevwa, resevwa yon reprezantasyon fisèl nan done yo kòm opinyon epi retounen yon fisèl prepare pou Entèprèt:

  • Se fisèl la opinyon divize an tèt ak kò lè l sèvi avèk ReqParseN2(str)
  • tèt yo divize an eleman epi yo mete l nan yon tranch kòmandman lè l sèvi avèk ReqParseHead (tèt)
  • В chanje (kòmand[0]) chwazi lòd ou resevwa a (cmd, kle, adrès oswa se seksyon an deklanche default)
  • 2 kòmandman yo tcheke nan cmd switch(kòmand [1]) - longè и getversion.
  • longè tcheke kalite done yo kòmandman [2] epi sove li nan datatip
  • Tcheke sa gen yon valè fisèl
    len(body) < 1
  • Retounen kòd repons lan:
    "result:bufferlength:" + datatype + "/" + body
  • getversion retounen yon fisèl
    return "result:version/auto"

Entèprèt

Gen estrikti InterpreteData a epi li fè pwosesis segondè nan done yo retounen nan Chwa fisèl ak fòmasyon objè InterpreteData.

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

Fonksyon

Interprete(str string) (*InterpreteData, error)

aksepte yon kòd lakòz epi kreye epi retounen yon referans sou objè a InterpreteData.

Pwogrè:

  • Menm jan an tou Chwa tèt ak kò yo ekstrè lè l sèvi avèk ReqParseN2(str)
  • se tèt divize an eleman lè l sèvi avèk ReqParseHead (tèt)
  • Objè a inisyalize InterpreteData epi yo retounen yon konsèy sou li:

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

Objè sa a itilize nan server.go pake prensipal la.

Kliyan

Pake kliyan an gen fonksyon yo TCPConnect и TCPResponseData.

Fonksyon

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

travay tankou sa a:

  • Yo fè yon koneksyon ak koneksyon ki espesifye nan objè a anviwònman pase
    net.Dial("tcp", s.Host + ":" + s.Port)
  • Done yo pase nan paramèt done a transmèt:
    conn.Write(data)
  • Se repons lan li
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    epi enprime sou konsole a

    fmt.Println(string(resp[:n]))
  • Si transfere chaj Lè sa a, pase li sou
    conn.Write(payload)

    epi tou li repons sèvè a, enprime li nan konsole a

Fonksyon

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

kreye yon tanpon nan gwosè a espesifye, li repons sèvè a la epi li retounen tanpon sa a ak kantite byte li, osi byen ke yon objè erè.

Souroutine kliyan an

Li sèvi pou voye kòmandman nan serveurs ne, osi byen ke jwenn estatistik kout ak tès.

Ka aksepte paramèt sa yo: fichye konfigirasyon nan fòma JSON, done yo dwe voye nan sèvè a kòm yon fisèl, chemen nan dosye a yo dwe voye nan payload, drapo emulation planifikatè ne, kalite done transfere kòm yon valè nimerik.

  • Jwenn konfigirasyon an
    st := types.ParseConfig(*config)
  • Si drapo emu a pase, li kòmanse sheduler
  • Si drapo f ki endike chemen an nan dosye a apwovizyone, Lè sa a, nou chaje done li yo nan fdb epi yo voye kontni an sou sèvè a
    client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
  • Si fichye a pa espesifye, Lè sa a, done ki soti nan drapo a tou senpleman voye -d:
    client.TCPConnect(st, []byte(*data), nil)

Tout bagay sa a se yon reprezantasyon senplifye ki montre estrikti pwotokòl la. Pandan devlopman, fonksyonalite ki nesesè yo ajoute nan estrikti li yo.

Nan dezyèm pati a mwen pral pale sou estrikti done pou blòk ak tranzaksyon yo, nan 3 sou sèvè WebSocket pou konekte soti nan JavaScript, nan 4 mwen pral gade nan pwogramasyon an senkronizasyon, Lè sa a, yon machin chemine ki trete bytecode soti nan entrées ak pwodiksyon, kriptografi ak pisin pou pwodiksyon.

Sous: www.habr.com

Add nouvo kòmantè