Go-г ашиглан үйлдвэрлэлд зориулсан блокчейн хөгжүүлэлт. 1-р хэсэг

Би дөрвөн сарын турш “Төрийн болон аж үйлдвэрийн салбарт блокчэйнд суурилсан мэдээллийн хамгаалалт, удирдлагын хэрэгслийг хөгжүүлэх” төсөл дээр ажиллаж байна.
Одоо би энэ төслийг хэрхэн эхлүүлсэн тухайгаа ярихыг хүсч байгаа бөгөөд одоо би програмын кодыг нарийвчлан тайлбарлах болно.

Go-г ашиглан үйлдвэрлэлд зориулсан блокчейн хөгжүүлэлт. 1-р хэсэг

Энэ бол цуврал нийтлэлийн анхны нийтлэл юм. Энд би сервер болон протоколыг тайлбарлав. Үнэн хэрэгтээ уншигч эдгээр блокчейн элементүүдийн өөрийн хувилбарыг бичиж болно.

Тэгээд хоёр дахь хэсэг нь энд байна — блокчэйн болон гүйлгээний өгөгдлийн бүтцийн тухай, мөн мэдээллийн сантай харилцан үйлчлэлцдэг багцын тухай.

Өнгөрсөн жил Digital Breakthrough хакатон дээр тэд тархсан дэвтэр технологийг ашиглан аж үйлдвэр, дижитал эдийн засагт ашигтай систем бий болгох санааг дэвшүүлсэн бөгөөд Инновацид туслах сангаас бүтээн байгуулалтад зориулж буцалтгүй тусламж олгосон (би тусдаа бичих ёстой. Дөнгөж гарааны бизнес эхлүүлж буй хүмүүст зориулсан тэтгэлгийн тухай нийтлэл ), одоо дараалалтай байна.

Хөгжүүлэлт нь Go хэл дээр явагддаг бөгөөд блокуудыг хадгалдаг мэдээллийн сан нь LevelDB юм.
Үндсэн хэсгүүд нь протокол, сервер (TCP болон WebSocket-ийг ажиллуулдаг - эхнийх нь блокчейн синхрончлох, хоёр дахь нь үйлчлүүлэгчдийг холбох, JavaScript-ээс гүйлгээ, тушаал илгээх зориулалттай).

Өмнө дурьдсанчлан, энэхүү блокчэйн нь ханган нийлүүлэгчид болон үйлчлүүлэгчдийн хооронд эсвэл нэг хүний ​​​​хоёрын хооронд бүтээгдэхүүний солилцоог автоматжуулах, хамгаалахад шаардлагатай байдаг. Эдгээр хүмүүс бие биедээ итгэх гэж яардаггүй. Гэхдээ даалгавар бол зөвхөн суурилуулсан тооцоолуур бүхий "шалгах дэвтэр" үүсгэх биш, харин бүтээгдэхүүний амьдралын мөчлөгтэй ажиллахад тохиолддог ердийн ажлуудын ихэнхийг автоматжуулах систем юм. Энэ асуудлыг хариуцдаг байт код нь блокчэйнүүдийн нэгэн адил гүйлгээний оролт, гаралтад хадгалагддаг (гүйлгээг өөрөө блок болгон хадгалдаг, LevelDB дахь блокууд нь GOB форматаар урьдчилан кодлогдсон байдаг). Эхлээд протокол болон серверийн талаар ярилцъя.

Протокол нь тийм ч төвөгтэй биш бөгөөд гол зорилго нь тусгай тушаалын мөрийн хариуд зарим өгөгдлийг, ихэвчлэн блок эсвэл гүйлгээг ачаалах горимд шилжих явдал бөгөөд энэ нь бараа материал солилцоход шаардлагатай бөгөөд ингэснээр зангилаа хэн болохыг мэддэг. холбогдсон ба тэд хэрхэн хийх ажилтай байна (синхрончлолын сессэд холбогдсон зангилаануудыг мөн "хөрш" гэж нэрлэдэг, учир нь тэдний IP нь мэдэгдэж, төлөвийн өгөгдөл нь санах ойд хадгалагддаг).

Go программистуудын ойлголт дахь хавтаснуудыг (Линукс гэж нэрлэдэг лавлахуудыг) багц гэж нэрлэдэг тул энэ лавлахаас Go кодтой файл бүрийн эхэнд энэ файлын байрлаж буй хавтас_нэр_хаана багц бичдэг. Үгүй бол та багцыг хөрвүүлэгч рүү оруулах боломжгүй болно. За, энэ хэлийг мэддэг хүмүүст энэ нь нууц биш юм. Эдгээр багцууд нь:

  • Сүлжээний харилцаа холбоо (сервер, үйлчлүүлэгч, протокол)
  • Хадгалагдсан болон дамжуулагдсан өгөгдлийн бүтэц (блок, гүйлгээ)
  • Өгөгдлийн сан (блокчейн)
  • Зөвшилцөл
  • Овоолсон виртуал машин (xvm)
  • Туслах (крипто, төрөл) одоохондоо.

Энд github-ийн холбоос байна

Энэ бол боловсролын хувилбар бөгөөд үйл явц хоорондын харилцан үйлчлэл, хэд хэдэн туршилтын бүрэлдэхүүн хэсгүүд байхгүй боловч бүтэц нь хөгжүүлэлт хийгдэж буй бүтэцтэй тохирч байна. Хэрэв танд сэтгэгдэл дээр санал болгох зүйл байвал цаашдын хөгжилд анхааралдаа авахдаа баяртай байх болно. Одоо серверийн талаархи тайлбар болон протокол.

Эхлээд серверийг харцгаая.

Серверийн дэд програм нь протоколын багцаас өгөгдлийн бүтцийг ашиглан TCP протокол дээр ажилладаг өгөгдлийн серверийн үүргийг гүйцэтгэдэг.

Уг процедур нь дараах багцуудыг ашигладаг. сервер, протокол, төрөл. Багцанд нь өөрөө tcp_server.go өгөгдлийн бүтцийг агуулдаг Үйлчлэх.

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

Энэ нь дараах параметрүүдийг хүлээн авах боломжтой.

  • Мэдээлэл солилцох сүлжээний порт
  • JSON форматтай серверийн тохиргооны файл
  • Дибаг хийх горимд ажиллах дарцаг (хувийн блокчэйн)

Явц:

  • JSON файлаас тохиргоог уншина
  • Дибаг хийх горимын тугийг шалгасан: хэрэв тохируулсан бол сүлжээний синхрончлолын хуваарь гаргаагүй бөгөөд блокчейн ачаалагдаагүй байна.
  • Тохиргооны өгөгдлийн бүтцийг эхлүүлж, серверийг эхлүүлж байна

Сервер

  • Протоколын дагуу TCP сервер болон сүлжээний харилцан үйлчлэлийг эхлүүлдэг.
  • Энэ нь портын дугаар, буферийн хэмжээ, бүтцийн заагч зэргээс бүрдсэн Серв өгөгдлийн бүтэцтэй төрөл.Тохиргоо
  • Run арга нь сүлжээний харилцан үйлчлэлийг эхлүүлдэг (өгөгдсөн порт дээр ирж буй холболтуудыг сонсох, шинэ холболт хүлээн авах үед түүний боловсруулалтыг шинэ хэлхээнд хувийн бариулын арга руу шилжүүлдэг)
  • В зохицуулах холболтын өгөгдлийг буфер болгон уншиж, мөрийн дүрслэл болгон хувиргаж, дамжуулдаг протокол.Сонголт
  • протокол.Сонголт буцаж ирдэг үр дүн эсвэл алдаа гаргадаг. үр дүн дараа нь шилжүүлсэн протокол. Тайлбарлахаль нь буцаж ирдэг intrpr - төрлийн объект Өгөгдлийг тайлбарлах, эсвэл сонголтын үр дүнг боловсруулахад алдаа гардаг
  • Дараа нь шилжүүлэгчийг гүйцэтгэнэ intrpr.Commands[0] аль нэгийг нь шалгадаг: үр дүн, инв, алдаа мөн хэсэг байдаг Анхдагч байна
  • хэсэгт үр дүн шилжүүлэгчийг утгаараа олно intrpr.Commands[1] утгыг шалгадаг буфер урт и хувилбар (тохиолдол бүрт тохирох функцийг дууддаг)

Чиг үүрэг GetVersion и Буферийн урт файлд байна srvlib.go серверийн багц

GetVersion(conn net.Conn, version string)

Энэ нь зүгээр л консол руу хэвлэж, параметрт дамжуулсан хувилбарыг үйлчлүүлэгч рүү илгээдэг:

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

.
үйл ажиллагаа

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

блок, гүйлгээ эсвэл бусад тодорхой өгөгдлийг дараах байдлаар ачаална:

  • Протоколд заасан хүлээн авах шаардлагатай өгөгдлийн төрлийг консол дээр хэвлэнэ.
    fmt.Println("DataType:", intrpr.Commands[2])
  • Утгыг уншина intrpr.Body тоон хувьсагч руу buf_len
  • Буфер үүсгэдэг шинэ буф заасан хэмжээ:
    make([]byte, buf_len)
  • Зөв хариулт илгээнэ:
    conn.Write([]byte("result:ok"))
  • Унших урсгалаас буферийг бүрэн дүүргэнэ:
    io.ReadFull(conn, newbuf)

    .

  • Буферийн агуулгыг консол руу хэвлэнэ
    fmt.Println(string(newbuf))

    уншсан байтын тоо

    fmt.Println("Bytes length:", n)
  • Зөв хариулт илгээнэ:
    conn.Write([]byte("result:ok"))

Серверийн багцын аргууд нь багцын функцуудыг ашиглан хүлээн авсан өгөгдлийг боловсруулахаар тохируулагдсан байдаг протокол.

Протокол

Протокол нь сүлжээний солилцоонд өгөгдлийг илэрхийлэх хэрэгсэл болдог.

Сонголт(str мөр) (мөр, алдаа) серверээс хүлээн авсан өгөгдлийн анхан шатны боловсруулалтыг хийж, өгөгдлийн мөрийн дүрслэлийг оролт болгон хүлээн авч, бэлтгэсэн мөрийг буцаана. Орчуулагч:

  • Оролтын мөрийг ашиглан толгой ба бие гэж хуваагдана ReqParseN2(str)
  • толгойг элементүүдэд хувааж, ReqParseHead(head) ашиглан командын зүсмэлүүд рүү байрлуулна.
  • В солих(командууд[0]) хүлээн авсан командыг сонгоно уу (cmd, түлхүүр, хаяг эсвэл хэсэг идэвхжсэн байна Анхдагч байна)
  • 2 командыг cmd дээр шалгасан switch(командууд[1]) — урт и хувиралт.
  • урт нь өгөгдлийн төрлийг шалгана тушаалууд[2] мөн дотор нь хадгалдаг мэдээллийн төрөл
  • Үүнийг шалгадаг байгууллага мөрийн утгыг агуулна
    len(body) < 1
  • Хариултын мөрийг буцаана:
    "result:bufferlength:" + datatype + "/" + body
  • хувиралт мөрийг буцаана
    return "result:version/auto"

Орчуулагч

InterpreteData бүтцийг агуулсан бөгөөд буцаасан өгөгдлийн хоёрдогч боловсруулалтыг гүйцэтгэдэг сонголт мөр ба объект үүсэх Өгөгдлийг тайлбарлах.

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

үйл ажиллагаа

Interprete(str string) (*InterpreteData, error)

мөрийг хүлээн авдаг үр дүн мөн объектын лавлагааг үүсгэж буцаана Өгөгдлийг тайлбарлах.

Явц:

  • Үүнтэй адил сонголт ашиглан толгой ба биеийг гаргаж авдаг ReqParseN2(str)
  • толгойг ашиглан элементүүдэд хуваагдана ReqParseHead(толгой)
  • Объектыг эхлүүлсэн Өгөгдлийг тайлбарлах мөн түүн рүү заагч буцаж ирдэг:

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

Энэ объектыг ашиглаж байна server.go үндсэн багц.

Клиент

Үйлчлүүлэгчийн багц нь функцуудыг агуулдаг TCPConnect и TCPResponseData.

үйл ажиллагаа

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

дараах байдлаар ажилладаг:

  • Дамжуулсан тохиргооны объектод заасан холболттой холболт хийгдсэн
    net.Dial("tcp", s.Host + ":" + s.Port)
  • Өгөгдлийн параметрт дамжуулагдсан өгөгдлийг дараах байдлаар дамжуулна.
    conn.Write(data)
  • Хариултыг уншсан
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    болон консол дээр хэвлэсэн

    fmt.Println(string(resp[:n]))
  • Хэрэв шилжүүлсэн бол даацтай дараа нь дамжуулдаг
    conn.Write(payload)

    мөн серверийн хариуг уншиж, консол дээр хэвлэдэг

үйл ажиллагаа

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

заасан хэмжээтэй буфер үүсгэж, тэнд серверийн хариуг уншиж, энэ буфер болон уншсан байтын тоо, алдааны объектыг буцаана.

Үйлчлүүлэгчийн дэд програм

Зангилааны серверүүд рүү тушаал илгээх, мөн товч статистик мэдээлэл авах, тест хийх үйлчилгээ үзүүлдэг.

Дараах параметрүүдийг хүлээн авах боломжтой: JSON форматын тохиргооны файл, сервер рүү стринг хэлбэрээр илгээгдэх өгөгдөл, ачааллыг илгээх файлын зам, зангилаа төлөвлөгчийн эмуляцийн туг, тоон утга болгон шилжүүлсэн өгөгдлийн төрөл.

  • Тохиргоог авч байна
    st := types.ParseConfig(*config)
  • Хэрэв emu тугийг дамжуулсан бол эхэлнэ sheduler
  • Хэрэв файлд хүрэх замыг заасан f туг байгаа бол бид түүний өгөгдлийг ачаална fdb мөн агуулгыг сервер рүү илгээдэг
    client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
  • Хэрэв файлыг заагаагүй бол тугны өгөгдлийг зүгээр л илгээнэ -d:
    client.TCPConnect(st, []byte(*data), nil)

Энэ бүхэн нь протоколын бүтцийг харуулсан хялбаршуулсан дүрслэл юм. Хөгжлийн явцад шаардлагатай функцийг түүний бүтцэд нэмж оруулсан болно.

Хоёрдахь хэсэгт би блок, гүйлгээний өгөгдлийн бүтцийн талаар, 3-т JavaScript-ээс холбогдох WebSocket серверийн талаар, 4-т синхрончлолын хуваарьлагчийг, дараа нь оролт, гаралтаас байт кодыг боловсруулдаг стек машин, криптограф болон гаралтын цөөрөм.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх