Արդյունաբերության համար բլոկչեյնի զարգացում՝ օգտագործելով Go: Մաս 1

Արդեն չորս ամիս է, ինչ ես աշխատում եմ նախագծի վրա, որը կոչվում է «Տվյալների պաշտպանության և կառավարման գործիքների մշակում պետական ​​և արդյունաբերական հատվածներում՝ հիմնված բլոկչեյնի վրա»։
Այժմ ես կցանկանայի ձեզ պատմել, թե ինչպես սկսեցի այս նախագիծը, իսկ այժմ մանրամասն նկարագրեմ ծրագրի կոդը։

Արդյունաբերության համար բլոկչեյնի զարգացում՝ օգտագործելով Go: Մաս 1

Սա հոդվածաշարի առաջին հոդվածն է։ Այստեղ ես նկարագրում եմ սերվերը և արձանագրությունը: Փաստորեն, ընթերցողը կարող է նույնիսկ գրել այս բլոկչեյն տարրերի իր տարբերակները:

Եվ ահա երկրորդ մասը — բլոկչեյնի և գործարքների տվյալների կառուցվածքների, ինչպես նաև տվյալների բազայի հետ փոխգործակցություն իրականացնող փաթեթի մասին։

Անցյալ տարի «Digital Breakthrough» հաքաթոնում նրանք հանդես եկան արդյունաբերության և թվային տնտեսության համար օգտակար համակարգ ստեղծելու գաղափարով՝ օգտագործելով բաշխված գրքույկ տեխնոլոգիա; զարգացման համար դրամաշնորհ է տրամադրվել նաև Innovation Assistance Fund-ի կողմից (ես պետք է առանձին գրեմ: հոդված դրամաշնորհի մասին, նրանց համար, ովքեր նոր են սկսում ստարտափներ ), և այժմ՝ ըստ կարգի:

Զարգացումը տեղի է ունենում Go լեզվով, և տվյալների բազան, որտեղ պահվում են բլոկները, LevelDB է:
Հիմնական մասերն են արձանագրությունը, սերվերը (որն աշխատում է TCP-ն և WebSocket-ը՝ առաջինը՝ բլոկչեյնը համաժամեցնելու համար, երկրորդը՝ հաճախորդներին միացնելու, գործարքներ և հրամաններ ուղարկելու համար, օրինակ՝ JavaScript-ից։

Ինչպես նշվեց, այս բլոկչեյնն առաջին հերթին անհրաժեշտ է մատակարարների և հաճախորդների միջև ապրանքների փոխանակումն ավտոմատացնելու և պաշտպանելու համար, կամ երկուսն էլ մեկ անձի մեջ: Այս մարդիկ չեն շտապում վստահել միմյանց։ Բայց խնդիրը միայն ներկառուցված հաշվիչով «ստուգագիր» ստեղծելը չէ, այլ համակարգ, որն ավտոմատացնում է սովորական առաջադրանքների մեծ մասը, որոնք առաջանում են արտադրանքի կյանքի ցիկլի հետ աշխատելիս: Բայթկոդը, որը պատասխանատու է այս հարցի համար, ինչպես ընդունված է բլոկչեյնների դեպքում, պահվում է գործարքների մուտքերում և ելքերում (գործարքներն իրենք պահվում են բլոկներում, LevelDB-ի բլոկները նախապես կոդավորված են GOB ձևաչափով): Նախ, եկեք խոսենք արձանագրության և սերվերի մասին (aka node):

Արձանագրությունը բարդ չէ, դրա ամբողջ իմաստը որոշ տվյալների բեռնման ռեժիմին անցնելն է, սովորաբար բլոկի կամ գործարքի, ի պատասխան հրամանի հատուկ տողի, և դա անհրաժեշտ է նաև գույքագրման փոխանակման համար, որպեսզի հանգույցն իմանա, թե ով է այն: կապված է և ինչպես են նրանք անելիքներ ունեն (համաժամացման նիստի համար միացված հանգույցները կոչվում են նաև «հարևան», քանի որ նրանց IP-ն հայտնի է, և նրանց վիճակի տվյալները պահվում են հիշողության մեջ):

Թղթապանակները (դիրեկտորիաները, ինչպես դրանք անվանում է Linux-ը) Go ծրագրավորողների հասկացության մեջ կոչվում են փաթեթներ, ուստի այս գրացուցակից Go կոդով յուրաքանչյուր ֆայլի սկզբում նրանք գրում են փաթեթ folder_name_where_this_file is located: Հակառակ դեպքում, դուք չեք կարողանա փաթեթը փոխանցել կոմպիլյատորին: Դե, սա գաղտնիք չէ նրանց համար, ովքեր գիտեն այս լեզուն։ Սրանք փաթեթներ են.

  • Ցանցային հաղորդակցություն (սերվեր, հաճախորդ, արձանագրություն)
  • Պահված և փոխանցված տվյալների կառուցվածքները (բլոկ, գործարք)
  • Տվյալների բազա (բլոկչեյն)
  • Համաձայնություն
  • Խցանված վիրտուալ մեքենա (xvm)
  • Օժանդակ (կրիպտո, տեսակներ) այսքանը առայժմ:

Ահա github-ի հղումը

Սա կրթական տարբերակ է, զուրկ է միջգործընթացային փոխազդեցությունից և մի քանի փորձարարական բաղադրիչներից, սակայն կառուցվածքը համապատասխանում է նրան, որի վրա իրականացվում է մշակում։ Եթե ​​դուք ինչ-որ բան ունեք առաջարկելու մեկնաբանություններում, ես ուրախ կլինեմ հաշվի առնել այն հետագա մշակման ժամանակ: Իսկ հիմա սերվերի բացատրության համար և արձանագրություն.

Եկեք նախ նայենք սերվերին:

Սերվերի ենթակարգը գործում է որպես տվյալների սերվեր, որն աշխատում է TCP արձանագրության վերևում՝ օգտագործելով արձանագրության փաթեթի տվյալների կառուցվածքները:

Առօրյան օգտագործում է հետևյալ փաթեթները. սերվեր, արձանագրություն, տեսակները. Ինքն փաթեթում tcp_server.go պարունակում է տվյալների կառուցվածք Ծառայել.

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

Այն կարող է ընդունել հետևյալ պարամետրերը.

  • Ցանցային նավահանգիստ, որի միջոցով կփոխանակվեն տվյալները
  • Սերվերի կազմաձևման ֆայլ JSON ձևաչափով
  • Դրոշ՝ վրիպազերծման ռեժիմում աշխատելու համար (մասնավոր բլոկչեյն)

Առաջընթաց:

  • Կարդում է կազմաձևումը JSON ֆայլից
  • Վրիպազերծման ռեժիմի դրոշակը ստուգված է. եթե այն սահմանված է, ցանցի համաժամացման ժամանակացույցը չի գործարկվում, և բլոկչեյնը չի բեռնվում:
  • Կազմաձևման տվյալների կառուցվածքի սկզբնավորում և սերվերի գործարկում

Server

  • Իրականացնում է TCP սերվերի և ցանցային փոխազդեցության գործարկումը՝ համաձայն արձանագրության:
  • Այն ունի Serve տվյալների կառուցվածք, որը բաղկացած է պորտի համարից, բուֆերի չափից և կառուցվածքի ցուցիչից տեսակները.Կարգավորումներ
  • Run մեթոդը սկսում է ցանցային փոխազդեցությունը (լսելով մուտքային կապերը տվյալ նավահանգստում, երբ նոր կապ է ստացվում, դրա մշակումը փոխանցվում է մասնավոր բռնակի մեթոդին նոր շղթայում)
  • В բռնակ կապից ստացված տվյալները կարդացվում են բուֆերի մեջ, վերածվում լարային ներկայացման և փոխանցվում արձանագրություն.Ընտրություն
  • արձանագրություն.Ընտրություն վերադարձ արդյունք կամ առաջացնում է սխալ: արդյունք այնուհետև փոխանցվել է արձանագրություն.Մեկնաբանելորը վերադառնում է intrpr - տիպի օբյեկտ InterpreteData, կամ սխալ է առաջացնում ընտրության արդյունքի մշակման ժամանակ
  • Այնուհետև անջատիչը կատարվում է intrpr.Commands[0] որը ստուգում է. արդյունք, inv, սխալ և կա մի հատված անհոգություն
  • Բաժնում արդյունք անջատիչը հայտնաբերվում է արժեքով 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
  • Ստեղծում է բուֆեր newbuf նշված չափը:
    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 string) (տող, սխալ) կատարում է սերվերի կողմից ստացված տվյալների առաջնային մշակումը, որպես մուտքագրում ստանում է տվյալների տողային ներկայացում և վերադարձնում է դրա համար պատրաստված տողը. Թարգմանիչ:

  • Մուտքային տողը բաժանվում է գլխի և մարմնի՝ օգտագործելով ReqParseN2 (փող.)
  • գլուխը բաժանվում է տարրերի և տեղադրվում հրամանների հատվածում՝ օգտագործելով ReqParseHead (գլուխ)
  • В անջատիչ (հրամաններ[0]) ընտրեք ստացված հրամանը (cmd, բանալի, հասցե կամ հատվածը գործարկվում է անհոգություն)
  • cmd-ում ստուգվում է 2 հրաման անջատիչ (հրամաններ[1]) - երկարություն и վերափոխում.
  • երկարություն ստուգում է տվյալների տեսակը հրամաններ[2] և պահպանում է այն datatype
  • Ստուգում է դա մարմին պարունակում է լարային արժեք
    len(body) < 1
  • Վերադարձնում է պատասխանի տողը.
    "result:bufferlength:" + datatype + "/" + body
  • վերափոխում վերադարձնում է տող
    return "result:version/auto"

Թարգմանիչ

Պարունակում է InterpreteData կառուցվածքը և իրականացնում է վերադարձված տվյալների երկրորդական մշակում Ընտրություն լարերի և օբյեկտների ձևավորում InterpreteData.

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

Ֆունկցիա

Interprete(str string) (*InterpreteData, error)

ընդունում է տող արդյունք և ստեղծում և վերադարձնում է հղում օբյեկտին InterpreteData.

Առաջընթաց:

  • Նմանապես, Ընտրություն գլուխը և մարմինը արդյունահանվում են օգտագործելով ReqParseN2 (փող.)
  • գլուխը բաժանվում է տարրերի, օգտագործելով ReqParseHead (գլուխ)
  • Օբյեկտը սկզբնավորվում է InterpreteData և դրա ցուցիչը վերադարձվում է.

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]))
  • Եթե ​​փոխանցվի payload ապա փոխանցում է այն
    conn.Write(payload)

    և նաև կարդում է սերվերի պատասխանը՝ այն տպելով վահանակի վրա

Ֆունկցիա

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

ստեղծում է նշված չափի բուֆեր, այնտեղ կարդում է սերվերի պատասխանը և վերադարձնում այս բուֆերը և կարդացված բայթերի քանակը, ինչպես նաև սխալի օբյեկտ:

Հաճախորդի ենթածրագր

Ծառայում է հանգույցների սերվերներին հրամաններ ուղարկելու, ինչպես նաև համառոտ վիճակագրություն և թեստավորում ստանալու համար:

Կարող է ընդունել հետևյալ պարամետրերը՝ կազմաձևման ֆայլ JSON ձևաչափով, տվյալներ սերվերին որպես տող ուղարկելու, ուղի դեպի ֆայլ, որը պետք է ուղարկվի ծանրաբեռնվածություն, հանգույցի ժամանակացույցի էմուլյացիայի դրոշակ, տվյալների տեսակը, որը փոխանցվում է որպես թվային արժեք:

  • Ստանալով կոնֆիգուրացիա
    st := types.ParseConfig(*config)
  • Եթե ​​էմուի դրոշը փոխանցվում է, այն սկսվում է աշտարակ
  • Եթե ​​ֆայլի ուղին ցույց տվող 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-ում կանդրադառնամ համաժամացման ժամանակացույցին, այնուհետև ստեկ մեքենան, որը մշակում է բայթային ծածկագիրը մուտքերից և ելքերից, կրիպտոգրաֆիա և լողավազաններ ելքերի համար:

Source: www.habr.com

Добавить комментарий