forked from dreamerjackson/BuildingBlockChain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblockchain.go
143 lines (106 loc) · 2.65 KB
/
blockchain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"log"
"github.com/boltdb/bolt"
"os"
"fmt"
)
const dbFile = "blockchain_%s.db"
const blocksBucket = "blocks"
const genesisCoinbaseData = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
// Blockchain keeps a sequence of Blocks
//区块链,保存了最近的区块的hash以及数据库对象
type Blockchain struct {
tip []byte
db *bolt.DB
}
// AddBlock saves provided data as a block in the blockchain
//增加一个区块
func (bc *Blockchain) AddBlock(block *Block) {
err := bc.db.Update(func(tx *bolt.Tx) error {
//添加的区块在数据库中不存在
b := tx.Bucket([]byte(blocksBucket))
blockInDb := b.Get(block.Hash)
if blockInDb != nil {
return nil
}
//直接blockHash->blockSerialize放入数据库
blockData := block.Serialize()
err := b.Put(block.Hash, blockData)
if err != nil {
log.Panic(err)
}
//判断高度,如果高度更高的话,将其添加到 l ->blockHash->blockSerialize
lastHash := b.Get([]byte("l"))
lastBlockData := b.Get(lastHash)
lastBlock := DeserializeBlock(lastBlockData)
if block.Height > lastBlock.Height {
err = b.Put([]byte("l"), block.Hash)
if err != nil {
log.Panic(err)
}
bc.tip = block.Hash
}
return nil
})
if err != nil {
log.Panic(err)
}
}
//数据库是否存在
//func dbExists() bool {
// if _, err := os.Stat(dbFile); os.IsNotExist(err) {
// return false
// }
//
// return true
//}
func dbExists(dbFile string) bool {
if _, err := os.Stat(dbFile); os.IsNotExist(err) {
return false
}
return true
}
// MineBlock mines a new block with the provided transactions
//根据提供的交易,开始挖矿MineBlock()
func (bc *Blockchain) MineBlock(transactions []*Transaction) *Block {
var lastHash []byte
var lastHeight int
//验证交易是有效的
for _, tx := range transactions {
if bc.VerifyTransaction(tx) != true {
log.Panic("ERROR: Invalid transaction")
}else{
fmt.Println("verify success")
}
}
err := bc.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(blocksBucket))
lastHash = b.Get([]byte("l"))
blockData := b.Get(lastHash)
block := DeserializeBlock(blockData)
lastHeight = block.Height
return nil
})
if err != nil {
log.Panic(err)
}
newBlock := NewBlock(transactions, lastHash, lastHeight+1)
err = bc.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(blocksBucket))
err := b.Put(newBlock.Hash, newBlock.Serialize())
if err != nil {
log.Panic(err)
}
err = b.Put([]byte("l"), newBlock.Hash)
if err != nil {
log.Panic(err)
}
bc.tip = newBlock.Hash
return nil
})
if err != nil {
log.Panic(err)
}
return newBlock
}