Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Xây dựng blockchain đơn giản với golang. P1 - Cấu trúc cơ bản
XIn chào mọi người.
Thời gian gần đây mình có tìm hiểu về blockchain và golang. Mình viết bài viết này với mục đích chia sẻ và tổng hợp những kiến thức đã thu nạp được.
Mình dự định sẽ viết khoảng 5 phần. Ở mỗi phần mình dự định sẽ trình bày những tính chất của blockchain gắn với implement tương ứng. Đây là bài viết đầu tiên trong số đó.
Mình cũng là nhập môn với golang và blockchain, rất vui nếu nhận được góp ý từ mọi người.
Lời nói đầu
Mình nghĩ điều này có thể hữu ích với những ai nhập môn với blockchain, nên trước khi vào bài viết mình xin chia sẻ 1 lưu ý nhỏ như sau :
Hiện nay khi ta nói là muốn xây dựng 1 ứng dụng blockchain, theo mình thì sẽ có 2 hướng đó là :
Xây dựng từ đầu đến cuối
Khi theo hướng này, ta sẽ cần viết code từ đầu đến cuối, từ hello world cho đến viết cấu hình để nó chạy ổn định trên 1 server nào đó. Theo hướng này ta sẽ khá tốn công sức. (Hoặc nếu làm về tiền ảo thì ta có thể fork từ 1 repo có sẵn trên github rồi tùy biến nó - sẽ tốn ít công sức hơn).Xây dựng dựa trên các nền tảng về blockchain
Khi theo hướng này, ta sẽ xây dựng ứng dụng blockchain dựa trên hoặc dùng 1 nền tảng blockchain sẵn có. Với ethereum thì mình nghĩ có thể hình tượng bằng việc ta xây dựng ứng dụng với blockchain thuê từ họ. Các bạn có thể tham khảo các nền tảng sau : Ethereum và Hyperledger, Eos
Vì mục đích tìm hiểu nên bài viết của mình sẽ đi theo hướng thứ nhất . Trong thực tế có thể bạn sẽ muốn đi theo hướng thứ 2, có thể sẽ giảm chi phí và phù hợp hơn.
Kết thúc chuỗi bài viết này, mình hi vọng thể hiện được các đặc điểm sau của blockchain :
- Cấu trúc block
- Network
- Proof of work
- Address
- Transaction
- Persistent
Dữ liệu mà blockchain của mình lưu sẽ mang chủ đề về tiền ảo - dữ liệu được lưu là các transactions.
Giới thiệu
Có lẽ blockchain đã là khái niệm quen thuộc với mọi người. Các bạn có thể tham khảo định nghĩa theo wikipedia
Trong bài viết này mình sẽ tập trung vào phần implement lên các tính chất của blockchain, về mặt lý thuyết mình sẽ đề cập qua khi đề cập đến các phần tương ứng.
Xây dựng
1. Cấu trúc Blockchain
Blockchain là cấu trúc chuỗi các block. Trong cấu trúc dữ liệu giải thuật có thể bạn đã làm quen với singly linked list hoặc stack. 2 cấu trúc này có thể nói là tập hợp các phần tử, mà mỗi phần tử chứa liên kết đến phần tử tiếp theo nó. Blockchain có thể nói là 1 singly linked list mà mỗi block là một phần tử.
Vậy mình sẽ implement blockchain với 1 struct tương ứng, và là ... array.
type Blockchain struct {
blocks []*Block
}
Ở bài viết này với mục đích trình bày thật đơn giản 1 blockchain thì mình nghĩ array là phù hợp. Trong thực tế, blockchain có thể được lưu trong database hoặc file (và mỗi block tương ứng với 1 file, 1.dat, 2.dat chẳng hạn), nên cấu trúc sẽ cần điều chỉnh để phù hợp với cấu trúc lưu trữ.
Ở bài đầu tiên này mình định sẽ định nghĩa thật đơn giản cỡ hello world, và sẽ định nghĩa đầy đủ hơn ở các bài viết sau.
Bạn có thể sẽ muốn tham khảo cấu trúc blockchain của ethereum ở đây
2. Cấu trúc Block
Block là phần tử cơ bản của 1 blockchain. Mình mô hình hóa bằng cấu trúc sau :
type Block struct {
Hash []byte
PrevBlockHash []byte
Data []byte
Timestamp int64
}
Các trường dữ liệu lưu trong 1 block :
- Hash : Giá trị dùng để "chứng nhận" 1 block. 1 giá trị hash sẽ tương ứng với 1 bộ dữ liệu của block. Khi 1 bit trong block thay đổi thì giá trị hash tính ra được sẽ thay đổi theo.
- PrevBlockHash : Giá trị hash của block trước nó. (Block đầu tiên sẽ có giá trị bằng 0)
- Data : Dữ liệu lưu trong block. (Thực tế thường là transaction đối với tiền ảo)
- Timestamp : Thời gian block được sinh ra.
Block đầu tiên thường được gọi là Genesis block.
3. Hàm
Mình sẽ trình bày từ hàm main() như sau :
main.go
func main() {
bc := InitBlockchain() // Khởi tạo blockchain
bc.AddBlock("Doraemon send 1 btc to batman") // Thêm block
bc.AddBlock("Batman send 2 btc to superman") // Thêm block
bc.AddBlock("Batman send 1 btc to girls") // Thêm block
fmt.Println()
// Duyệt và in thông tin các blocks
for _, block := range bc.blocks {
fmt.Printf("Hash : %x\n", block.Hash)
fmt.Printf("Data : %s\n", block.Data)
fmt.Printf("Timestamp : %x\n", block.Timestamp)
fmt.Printf("Previous Hash : %x\n", block.PrevBlockHash)
fmt.Println()
}
}
Ý đồ của mình rất đơn giản : khởi tạo 1 blockchain, thêm các block, và in ra chúng. Ý nghĩa các hàm như sau ;
blockchain.go
func InitBlockchain() *Blockchain {
once.Do(func() {
instantiated = &Blockchain{[]*Block{NewGenesisBlock("Genesis block")}}
})
return instantiated
}
InitBlockchain() khởi tạo 1 blockchain. Với block ban đầu được khởi tạo bằng NewGenesisBlock()
block.go
func NewGenesisBlock(starting string) *Block {
return NewBlock(starting, []byte{})
}
....
func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{[]byte{}, prevBlockHash, []byte(data), time.Now().Unix()}
block.SetHash()
return block
}
NewGenesisBlock() tham chiếu đến hàm khởi tạo 1 block là NewBlock(). NewBlock() khởi tạo 1 block mới. (Ta có thể bỏ qua không dùng NewGenesisBlock() ở đây, nhưng ở các bài viết sau genesisblock có thể sẽ đặc biệt hơn block thường nên ta sẽ để 1 hàm riêng)
block.go
func (b *Block) SetHash() {
bTimeStamp := []byte(strconv.FormatInt(b.Timestamp, 10))
blockAsBytes := bytes.Join([][]byte{b.PrevBlockHash, b.Data, bTimeStamp}, []byte{})
hash := sha256.Sum256(blockAsBytes)
b.Hash = hash[:]
}
SetHash() đặt giá trị hash cho block. Ta sẽ cần các giá trị khác được khai báo trước khi SetHash() được gọi.
Thuật toán sha256 mình dùng là thuật toán mã hóa dùng nhiều trong bitcoin, nhưng ta cũng có thể dùng thuật toán khác.
Cụ thể hơn các bạn có thể tham khảo tại source code mình đã chuẩn bị ở đây
Chạy
$ ./make # hoặc go build .
$ ./simplebc # (tên file thực thi)
Hash : e853230d005fc53266564f214ab070be12cef7e69e7379d8df825e796d8fabe3
Data : Genesis block
Timestamp : 5a538edf
Previous Hash :
Hash : 0fd24c200dda690cde7c684e9132bf8282f5ddcde81592322a3817c127edeead
Data : Doraemon send 1 btc to batman
Timestamp : 5a538edf
Previous Hash : e853230d005fc53266564f214ab070be12cef7e69e7379d8df825e796d8fabe3
Hash : 8f3edc23d5f78a57b6e6ff8484e82f56b7a7509f543df7be3cca2d57587b5349
Data : Batman send 2 btc to superman
Timestamp : 5a538edf
Previous Hash : 0fd24c200dda690cde7c684e9132bf8282f5ddcde81592322a3817c127edeead
Hash : 45d12c451a618a825c123bbfc8cc9b8a31f605579063ad0d02be2b03c7957315
Data : Batman send 1 btc to girls
Timestamp : 5a538edf
Previous Hash : 8f3edc23d5f78a57b6e6ff8484e82f56b7a7509f543df7be3cca2d57587b5349
Khi chạy terminal sẽ in ra các blocks đi kèm với các thông tin của chúng.
Nội dung phần 1 của mình kết thúc tại đây
Chi tiết cách build và cấu trúc files các bạn có thể tham khảo source code ở đây
Tổng kết
Ở phần này mình đã xây dựng 1 cấu trúc đơn giản về Blockchain và Block. Ở bài viết tiếp theo mình dự định sẽ xây dựng 1 mạng lưới mà trong đó các node có khả năng chia sẻ (1 cách rất đơn giản) blockchain của nhau.
Tham khảo
https://jeiwan.cc/posts/building-blockchain-in-go-part-1/
TranMy 30-11-2017






