Go көмегімен өнеркәсіп үшін блокчейнді дамыту. 1 бөлім

Төрт ай бойы мен «Блокчейн негізінде мемлекеттік және өнеркәсіптік секторларда деректерді қорғау және басқару құралдарын әзірлеу» жобасымен жұмыс істеп жатырмын.
Енді мен бұл жобаны қалай бастағанымды айтқым келеді, енді мен бағдарлама кодын егжей-тегжейлі сипаттаймын.

Go көмегімен өнеркәсіп үшін блокчейнді дамыту. 1 бөлім

Бұл мақалалар топтамасының бірінші мақаласы. Мұнда мен сервер мен протоколды сипаттаймын. Шын мәнінде, оқырман тіпті осы блокчейн элементтерінің өз нұсқаларын жаза алады.

Міне, екінші бөлім — блокчейн және транзакция деректерінің құрылымдары туралы, сондай-ақ деректер қорымен өзара әрекеттесуді жүзеге асыратын пакет туралы.

Өткен жылы Digital Breakthrough хакатонында олар үлестірмелі кітап технологиясын қолдана отырып, өнеркәсіп пен цифрлық экономика үшін пайдалы жүйе жасау идеясын ұсынды; Инновацияларға көмек көрсету қоры дамытуға грант бөлді (мен бөлек жазу керек) грант туралы мақала, стартаптарды енді бастағандар үшін ) және қазір тәртіпте.

Әзірлеу Go тілінде жүреді, ал блоктар сақталатын дерекқор LevelDB болып табылады.
Негізгі бөліктер протокол, сервер (TCP және WebSocket-ті іске қосады - біріншісі блокчейнді синхрондау үшін, екіншісі клиенттерді қосу, транзакциялар мен JavaScript пәрмендерін жіберу үшін, мысалы.

Жоғарыда айтылғандай, бұл блокчейн ең алдымен жеткізушілер мен тұтынушылар арасындағы немесе екеуі де бір адамда өнім алмасуды автоматтандыру және қорғау үшін қажет. Бұл адамдар бір-біріне сенуге асықпайды. Бірақ міндет кірістірілген калькуляторы бар «тексеру кітапшасын» жасау ғана емес, өнімнің өмірлік циклімен жұмыс істеу кезінде туындайтын күнделікті тапсырмалардың көпшілігін автоматтандыратын жүйе. Бұл мәселеге жауапты байт-код, әдеттегідей, блокчейндерде, транзакциялардың кірістерінде және шығыстарында сақталады (транзакциялардың өзі блоктарда сақталады, LevelDB блоктары GOB пішімінде алдын ала кодталған). Алдымен, протокол мен сервер туралы сөйлесейік (ағылшынша түйін).

Протокол күрделі емес, оның барлық мәні арнайы пәрмен жолына жауап ретінде кейбір деректерді, әдетте блокты немесе транзакцияны жүктеу режиміне ауысу болып табылады, сонымен қатар түйін кім екенін білуі үшін түгендеумен алмасу үшін қажет. қосылған және олардың жұмыс істеу жолы бар (синхрондау сеансына қосылған түйіндер «көрші» деп те аталады, себебі олардың IP мекенжайы белгілі және олардың күй деректері жадта сақталады).

Қалталар (Linux оларды атайтын каталогтар) Go бағдарламасында бағдарламашылар пакеттер деп аталады, сондықтан осы каталогтан Go коды бар әрбір файлдың басында олар буманың папкасының_аты_қайда_осы_файл орналасқанын жазады. Әйтпесе, пакетті компиляторға жібере алмайсыз. Жарайды, бұл тілді білетіндер үшін құпия емес. Бұл пакеттер:

  • Желілік байланыс (сервер, клиент, протокол)
  • Сақталған және жіберілетін деректердің құрылымы (блок, транзакция)
  • Деректер базасы (блокчейн)
  • Консенсус
  • Жинақталған виртуалды машина (xvm)
  • Көмекші (крипто, түрлер) бәрі әзірше.

Мұнда github сілтемесі берілген

Бұл білім беру нұсқасы, онда процессаралық өзара әрекеттестік және бірнеше эксперименттік құрамдас бөліктер жоқ, бірақ құрылымы әзірлеу жүргізіліп жатқанға сәйкес келеді. Түсініктемелерде ұсынатын бірдеңе болса, мен оны әрі қарай дамытуда ескеруге қуаныштымын. Ал енді серверді түсіндіру үшін және Хаттама.

Алдымен серверді қарастырайық.

Сервердің ішкі бағдарламасы хаттамалар бумасындағы деректер құрылымдарын пайдаланып TCP протоколының үстінде жұмыс істейтін деректер сервері ретінде әрекет етеді.

Реттеу келесі пакеттерді пайдаланады: сервер, Хаттама, түрлері. Пакеттің өзінде tcp_server.go деректер құрылымын қамтиды Қызмет көрсетіңіз.

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

Ол келесі параметрлерді қабылдай алады:

  • Деректер алмасуға болатын желілік порт
  • JSON пішіміндегі сервер конфигурация файлы
  • Түзету режимінде іске қосу жалаушасы (жеке блокчейн)

Барысы:

  • JSON файлынан конфигурацияны оқиды
  • Түзету режимінің жалаушасы тексеріледі: ол орнатылған болса, желіні синхрондау жоспарлаушысы іске қосылмайды және блокчейн жүктелмейді.
  • Конфигурация деректерінің құрылымын инициализациялау және серверді іске қосу

Сервер

  • TCP серверін іске қосуды және хаттамаға сәйкес желілік өзара әрекеттесуді жүзеге асырады.
  • Оның порт нөмірінен, буфер өлшемінен және құрылымға көрсеткіштен тұратын қызмет көрсету деректер құрылымы бар түрлері.Параметрлер
  • Run әдісі желілік өзара әрекеттесуді бастайды (берілген порттағы кіріс қосылымдарын тыңдау, жаңа қосылым қабылданған кезде оны өңдеу жаңа ағындағы жеке өңдеу әдісіне тасымалданады)
  • В тұтқа қосылым деректері буферге оқылады, жол көрінісіне түрлендіріледі және жіберіледі протокол. Таңдау
  • протокол. Таңдау қайтарады нәтиже немесе қатені тудырады. нәтиже кейін аударылады протокол. интерпретациялауқайтып оралады intrpr - типтік объект InterpreteData, немесе таңдау нәтижесін өңдеу кезінде қатені тудырады
  • Содан кейін коммутатор орындалады 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(commands[1]) — ұзындық и алу.
  • ұзындық деректер түрін тексереді пәрмендер[2] және оны сақтайды деректер түрі
  • Мұны тексереді дене жол мәнін қамтиды
    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(str)
  • көмегімен басы элементтерге бөлінеді 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]))
  • Ауыстырылса Пайдалы жүктеме содан кейін оны береді
    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-те синхрондау жоспарлаушысын, содан кейін кірістер мен шығыстардан байт кодты өңдейтін стек машинасын, криптографияны және шығыстарға арналған пулдар.

Ақпарат көзі: www.habr.com

пікір қалдыру