Pengembangan Blockchain untuk industri menggunakan Go. Bagian 1

Selama empat bulan sekarang saya telah mengerjakan sebuah proyek yang disebut “Pengembangan alat perlindungan dan manajemen data di sektor pemerintahan dan industri berdasarkan blockchain.”
Sekarang saya ingin bercerita tentang bagaimana saya memulai proyek ini, dan sekarang saya akan menjelaskan kode program secara detail.

Pengembangan Blockchain untuk industri menggunakan Go. Bagian 1

Ini adalah artikel pertama dari serangkaian artikel. Disini saya menjelaskan server dan protokolnya. Faktanya, pembaca bahkan dapat menulis versinya sendiri dari elemen blockchain ini.

Dan inilah bagian kedua — tentang blockchain dan struktur data transaksi, serta tentang paket yang mengimplementasikan interaksi dengan database.

Tahun lalu, di hackathon Terobosan Digital, mereka mendapatkan ide untuk membuat sistem yang berguna bagi industri dan ekonomi digital menggunakan teknologi buku besar terdistribusi; hibah juga dikeluarkan untuk pengembangan oleh Dana Bantuan Inovasi (saya harus menulis artikel terpisah artikel tentang hibah, bagi yang baru memulai startup ), dan sekarang secara urut.

Pengembangan dilakukan dalam bahasa Go, dan database tempat blok disimpan adalah LevelDB.
Bagian utamanya adalah protokol, server (yang menjalankan TCP dan WebSocket - yang pertama untuk menyinkronkan blockchain, yang kedua untuk menghubungkan klien, mengirim transaksi dan perintah dari JavaScript, misalnya.

Seperti yang telah disebutkan, blockchain ini diperlukan terutama untuk mengotomatisasi dan melindungi pertukaran produk antara pemasok dan pelanggan, atau keduanya dalam satu orang. Orang-orang ini tidak terburu-buru untuk mempercayai satu sama lain. Namun tugasnya bukan hanya membuat “buku cek” dengan kalkulator bawaan, tetapi juga sistem yang mengotomatiskan sebagian besar tugas rutin yang muncul saat bekerja dengan siklus hidup produk. Bytecode yang bertanggung jawab atas masalah ini, seperti biasa dengan blockchain, disimpan dalam input dan output transaksi (transaksi itu sendiri disimpan dalam blok, blok di LevelDB sudah dikodekan sebelumnya dalam format GOB). Pertama, mari kita bicara tentang protokol dan server (alias node).

Protokolnya tidak rumit, intinya adalah beralih ke mode memuat beberapa data, biasanya blok atau transaksi, sebagai respons terhadap baris perintah khusus, dan juga diperlukan untuk bertukar inventaris, sehingga node mengetahui siapa itu. terhubung dan bagaimana mereka melakukan urusannya (node ​​yang terhubung untuk sesi sinkronisasi juga disebut “tetangga” karena IP mereka diketahui dan data statusnya disimpan dalam memori).

Folder (direktori sebagaimana Linux menyebutnya) dalam pengertian programmer Go disebut paket, jadi di awal setiap file dengan kode Go dari direktori ini mereka menulis paket folder_name_where_this_file berada. Jika tidak, Anda tidak akan dapat memasukkan paket ke kompiler. Nah, ini bukan rahasia lagi bagi mereka yang mengetahui bahasa ini. Ini dia paket-paketnya:

  • Komunikasi jaringan (server, klien, protokol)
  • Struktur data yang disimpan dan dikirimkan (blok, transaksi)
  • Basis data (rantai blok)
  • Konsensus
  • Mesin virtual bertumpuk (xvm)
  • Tambahan (kripto, tipe) itu saja untuk saat ini.

Ini tautan ke github

Ini adalah versi pendidikan, tidak ada interaksi antar proses dan beberapa komponen eksperimental, tetapi strukturnya sesuai dengan yang sedang dikembangkan. Jika Anda memiliki saran di komentar, saya akan dengan senang hati mempertimbangkannya dalam pengembangan lebih lanjut. Dan sekarang untuk penjelasan server dan protokol.

Mari kita lihat servernya dulu.

Subrutin server bertindak sebagai server data yang berjalan di atas protokol TCP menggunakan struktur data dari paket protokol.

Rutinitas menggunakan paket-paket berikut: Server, protokol, jenis. Di dalam paket itu sendiri tcp_server.pergi berisi struktur data Melayani.

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

Itu dapat menerima parameter berikut:

  • Port jaringan tempat pertukaran data akan dilakukan
  • File konfigurasi server dalam format JSON
  • Tandai untuk berjalan dalam mode debug (blockchain pribadi)

Kemajuan:

  • Membaca konfigurasi dari file JSON
  • Bendera mode debug dicentang: jika disetel, penjadwal sinkronisasi jaringan tidak diluncurkan dan blockchain tidak dimuat
  • Inisialisasi struktur data konfigurasi dan memulai server

Server

  • Melaksanakan peluncuran server TCP dan interaksi jaringan sesuai dengan protokol.
  • Ia memiliki struktur data Serve yang terdiri dari nomor port, ukuran buffer, dan penunjuk ke struktur tersebut jenis.Pengaturan
  • Metode Run memulai interaksi jaringan (mendengarkan koneksi masuk pada port tertentu, ketika koneksi baru diterima, pemrosesannya ditransfer ke metode pegangan pribadi di thread baru)
  • В menangani data dari koneksi dibaca ke dalam buffer, diubah menjadi representasi string dan diteruskan ke protokol. Pilihan
  • protokol. Pilihan kembali mengakibatkan atau menyebabkan kesalahan. mengakibatkan kemudian ditransfer ke protokol.Menafsirkanyang kembali intrpr - objek tipe MenafsirkanData, atau menyebabkan kesalahan dalam pemrosesan hasil seleksi
  • Kemudian saklar dijalankan intrpr.Perintah[0] yang memeriksa salah satu dari: hasil, inv, kesalahan dan ada bagian kegagalan
  • Di bagian mengakibatkan saklar ditemukan berdasarkan nilai intrpr.Perintah[1] yang memeriksa nilainya panjang penyangga и versi (dalam setiap kasus, fungsi yang sesuai dipanggil)

Fungsi DapatkanVersi и Panjang Penyangga ada di dalam file srvlib.pergi paket server

GetVersion(conn net.Conn, version string)

itu hanya mencetak ke konsol dan mengirimkan versi yang diteruskan dalam parameter ke klien:

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

.
Fungsi

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

memuat blok, transaksi, atau data spesifik lainnya sebagai berikut:

  • Mencetak ke konsol jenis data yang ditentukan dalam protokol yang perlu diterima:
    fmt.Println("DataType:", intrpr.Commands[2])
  • Membaca nilainya intrpr.Tubuh ke variabel numerik buf_len
  • Membuat penyangga newbuf ukuran yang ditentukan:
    make([]byte, buf_len)
  • Mengirimkan respons oke:
    conn.Write([]byte("result:ok"))
  • Mengisi sepenuhnya buffer dari aliran baca:
    io.ReadFull(conn, newbuf)

    .

  • Mencetak konten buffer ke konsol
    fmt.Println(string(newbuf))

    dan jumlah byte yang dibaca

    fmt.Println("Bytes length:", n)
  • Mengirimkan respons oke:
    conn.Write([]byte("result:ok"))

Metode dari paket server dikonfigurasikan untuk memproses data yang diterima menggunakan fungsi dari paket protokol.

Protokol

Protokol berfungsi sebagai sarana yang mewakili data dalam pertukaran jaringan.

Pilihan(str string) (string, kesalahan) melakukan pemrosesan utama data yang diterima oleh server, menerima representasi string dari data sebagai input dan mengembalikan string yang disiapkan Penerjemah:

  • String input dibagi menjadi head dan body menggunakan PersyaratanParseN2(str)
  • head dipecah menjadi beberapa elemen dan ditempatkan ke dalam potongan perintah menggunakan ReqParseHead(head)
  • В beralih(perintah[0]) pilih perintah yang diterima (cmd, kunci, alamat atau bagian tersebut dipicu kegagalan)
  • 2 perintah diperiksa di cmd switch(perintah[1]) — panjang и dapatkan versi.
  • panjangnya memeriksa tipe data yang masuk perintah[2] dan menyimpannya tipe data
  • Periksa itu tubuh berisi nilai string
    len(body) < 1
  • Mengembalikan string respons:
    "result:bufferlength:" + datatype + "/" + body
  • dapatkan versi mengembalikan sebuah string
    return "result:version/auto"

Penerjemah

Berisi struktur InterpreteData dan melakukan pemrosesan sekunder atas data yang dikembalikan Pilihan string dan pembentukan objek MenafsirkanData.

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

Fungsi

Interprete(str string) (*InterpreteData, error)

menerima string mengakibatkan dan membuat serta mengembalikan referensi ke objek MenafsirkanData.

Kemajuan:

  • Demikian pula Pilihan kepala dan tubuh diekstraksi menggunakan PersyaratanParseN2(str)
  • head dipecah menjadi beberapa elemen menggunakan ReqParseHead(kepala)
  • Objek diinisialisasi MenafsirkanData dan penunjuk ke sana dikembalikan:

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

Objek ini digunakan di server.pergi paket utama.

Pelanggan

Paket klien berisi fungsi TCPConnect и TCPResponseData.

Fungsi

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

bekerja sebagai berikut:

  • Koneksi dibuat ke koneksi yang ditentukan dalam objek pengaturan yang diteruskan
    net.Dial("tcp", s.Host + ":" + s.Port)
  • Data yang diteruskan dalam parameter data ditransmisikan:
    conn.Write(data)
  • Jawabannya dibaca
    resp, n, _ := TCPResponseData(conn, s.BufSize)

    dan dicetak di konsol

    fmt.Println(string(resp[:n]))
  • Jika ditransfer payload lalu menyebarkannya
    conn.Write(payload)

    dan juga membaca respons server, mencetaknya ke konsol

Fungsi

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

membuat buffer dengan ukuran yang ditentukan, membaca respons server di sana dan mengembalikan buffer ini dan jumlah byte yang dibaca, serta objek kesalahan.

Subrutin klien

Berfungsi untuk mengirimkan perintah ke server node, serta memperoleh statistik dan pengujian singkat.

Dapat menerima parameter berikut: file konfigurasi dalam format JSON, data yang akan dikirim ke server sebagai string, jalur ke file yang akan dikirim ke payload, tanda emulasi penjadwal simpul, jenis data yang ditransfer sebagai nilai numerik.

  • Mendapatkan konfigurasi
    st := types.ParseConfig(*config)
  • Jika bendera emu dilewati, maka dimulai penjadwal
  • Jika bendera f yang menunjukkan jalur ke file disediakan, maka kami memuat datanya ke dalamnya fdb dan konten dikirim ke server
    client.TCPConnect(st, []byte(CMD_BUFFER_LENGTH + ":" + strconv.Itoa(*t) + "/" + strconv.Itoa(fdblen)), fdb)
  • Jika file tidak ditentukan, maka data dari flag akan dikirim begitu saja -d:
    client.TCPConnect(st, []byte(*data), nil)

Semua ini adalah representasi sederhana yang menunjukkan struktur protokol. Selama pengembangan, fungsionalitas yang diperlukan ditambahkan ke strukturnya.

Pada bagian kedua saya akan berbicara tentang struktur data untuk blok dan transaksi, pada bagian 3 tentang server WebSocket untuk menghubungkan dari JavaScript, pada bagian 4 saya akan melihat penjadwal sinkronisasi, kemudian mesin tumpukan yang memproses bytecode dari input dan output, kriptografi dan kumpulan untuk keluaran.

Sumber: www.habr.com

Tambah komentar