Вивчення блокчейну на мові Go
Блокчейн - це децентралізована технологія зберігання даних у вигляді ланцюжка пов’язаних блоків. Вона забезпечує прозоре та захищене зберігання цифрових записів. Наприклад, у банківській справі, де зміна попередніх транзакцій неприпустима, можна використовувати блокчейн.
Блок
Блок - це основний елемент блокчейну. Він зберігає інформацію разом з метаданими, такими як час, хеш і хеш попереднього блоку. Блоки можуть зберігати будь-яку інформацію, але в нашому випадку ця інформація буде представляти собою текст, що містить деталі транзакції. Давайте створимо просту структуру на Go для представлення блоку:
type Block struct {
Timestamp int64
Data []byte
PrevHash []byte
Hash []byte
}
Зверніть увагу, що хеш блоку - це контрольна сума всього блоку, включаючи хеш попереднього блоку. Хешування - це одна з тих речей, що робить блокчейн прозорим.
Щоб створити новий блок, давайте визначимо цю допоміжну функцію.
func NewBlock(data []byte, prevHash []byte) *Block {
block := &Block{
Timestamp: time.Now().Unix(),
Data: data,
PrevHash: prevHash,
Hash: []byte{},
}
return block
}
Однією з основних компонентів блокчейну є використовуваний алгоритм хешування для обчислення хешу кожного блоку. В нашій реалізації ми використовуємо алгоритм SHA-256 для обчислення хешу на основі часового мітки, даних і хешу попереднього блоку. Давайте визначимо його:
func (b *Block) CalculateHash() []byte {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
return hash[:]
}
Давайте також визначимо цей зручний метод для друку блоку.
func (b *Block) Print() {
fmt.Printf("Попередній хеш : %x\n", b.PrevHash)
fmt.Printf("Дані : %s\n", b.Data)
fmt.Printf("Хеш : %x\n", b.Hash)
}
Блокчейн
Тепер давайте перейдемо до самого блокчейну. В Go ми представляємо блокчейн за допомогою структури, яка містить зріз блоків:
type Blockchain struct {
Blocks []*Block
}
Щоб створити новий блокчейн, ми використовуємо функцію NewBlockchain:
func NewBlockchain() *Blockchain {
var genesisBlock = NewBlock([]byte("Genesis Block"), []byte{})
genesisBlock.Hash = genesisBlock.CalculateHash()
return &Blockchain{[]*Block{genesisBlock}}
}
Ця функція створює новий блокчейн з блоком-генезисом, який є першим блоком у ланцюжку.
Щоб додати новий блок до блокчейну, у нас є метод AddBlock:
func (bc *Blockchain) AddBlock(data string) {
prevBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := NewBlock([]byte(data), prevBlock.Hash)
newBlock.Hash = newBlock.CalculateHash()
bc.Blocks = append(bc.Blocks, newBlock)
}
Цей метод приймає дані для нового блоку, отримує хеш попереднього блоку, створює новий блок, обчислює його хеш і додає його до блокчейну.
Однією з важливих особливостей блокчейну є його здатність виявляти підробки. Ми можемо перевірити, чи дійсний блокчейн, використовуючи метод IsValid:
func (bc *Blockchain) IsValid() bool {
for i := 1; i < len(bc.Blocks); i++ {
block := bc.Blocks[i]
prevBlock := bc.Blocks[i-1]
if !bytes.Equal(block.Hash, block.CalculateHash()) {
return false
}
if !bytes.Equal(block.PrevHash, prevBlock.Hash) {
return false
}
}
return true
}
Цей метод проходить через кожен блок у ланцюжку і перевіряє, чи правильні хеші і зв’язки між блоками. Якщо знайдено будь-яке невідповідність, це означає, що блокчейн був підроблений.
Нам також потрібно визначити метод для друку всього блокчейну:
func (bc *Blockchain) Print(label string) {
print("\n==============================================\n\n")
fmt.Printf("Label: %s\n", label)
fmt.Printf("Valid: %t\n", bc.IsValid())
println()
for _, block := range bc.Blocks {
block.Print()
println()
}
}
І ось і все на сьогодні. Давайте спробуємо використовувати ці визначення в нашому коді, щоб побачити, про що йде мова в блокчейні більш детально.
В цьому прикладі коду ми створюємо новий блокчейн, додаємо кілька блоків, що представляють транзакції, і друкуємо оригінальний блокчейн. Потім ми намагаємося підробити дані блоку і друкуємо підроблений блокчейн. Метод IsValid виявляє підробку, показуючи, що блокчейн більше не дійсний.
func main() {
bc := NewBlockchain()
// Оригінал
bc.AddBlock("Steve відправив $250 Бобу")
bc.AddBlock("Alex відправив $30 Барбарі")
bc.Print("Оригінальний Блокчейн")
// Підробка
bc.Blocks[1].Data = []byte("Steve відправив Alex $1000")
bc.Print("Підроблений Блокчейн")
}
Блокчейн має потенціал змінити багато галузей, надаючи безпечний і прозорий спосіб запису транзакцій.
У цьому блозі ми дослідили базову реалізацію блокчейну на Go, дізналися, як створюються блоки, обчислюються хеші і перевіряється цілісність ланцюжка. Є ще багато чого, що можна вивчити, наприклад, алгоритми консенсусу і розумні контракти.
Я сподіваюся, що цей пост дав вам гарне розуміння того, як працює блокчейн і як його можна реалізувати.