bitcoin
Posted on
如果有时光机的话,我要做的第一件事情肯定就是穿梭回过去买比特币:),算了,不意淫了,还是学习要紧,虽然再也不能靠买比特币一夜暴富了,但是自己按照比特币实现一个山寨比特币的能力还是有的,比特币可以说是现在大红大紫的区块链的始祖,要全部了解它的原理可能还是要埋头啃个几个月的(并不简单)。
虽然比特币交易确认时间长,消耗资源多,但依旧无法掩盖其作为区块链始祖的光环。

Block & BlockChain
比特币中有两个重要的基本概念,区块和区块链,如果将区块想象成珍珠,那么区块链就是将这些珍珠都串起来的珍珠项链,这个珍珠项链没有尽头,新加入的珍珠和次新的珍珠彼此靠近,并通过某种关系紧密联系在一起,牢不可破。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| type Block struct { idx int timestamp string hash string prevHash string difficulty int nonce string }
type BlockChain struct { sync.Mutex blocks []Block }
func (bc *BlockChain) AddBlock(block Block) { bc.Lock() defer bc.Unlock() bc.blocks = append(bc.blocks, block) }
var blockchain BlockChain
|
Proof of Work
生成区块的过程就相当于打磨珍珠的过程,只有符合要求的珍珠才能最终被加入到珍珠项链中去,那么话说回来生成区块的过程是怎么样的呢,对于一个特定的区块,需要不断改变其中一个值(nonce),这里的 nonce 值从0开始逐渐递增,然后计算特定 nonce 对应的区块哈希值,只有哈希值符合相应的要求之后,才能说这个区块是有效的,才能被加入到区块链中,生成区块的过程也被叫做挖矿。
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
| func generateBlock(oldBlock Block, difficulty int) Block { var newBlock Block
newBlock.idx = oldBlock.idx + 1 newBlock.timestamp = time.Now().String() newBlock.prevHash = oldBlock.hash newBlock.difficulty = diff
for i := 0; ; i++ { hex := fmt.Sprintf("%x", i) newBlock.nonce = hex if !isHashValid(calculateHash(newBlock), newBlock.difficulty) { continue } else { fmt.Println(calculateHash(newBlock), " work done!") newBlock.Hash = calculateHash(newBlock) break } } return newBlock }
func calculateHash(block Block) string { record := strconv.Itoa(block.idx) + block.timestamp + block.prevHash + block.difficulty + block.nonce h := sha256.New() h.Write([]byte(record)) hashed := h.Sum(nil) return hex.EncodeToString(hashed) }
|
那么什么样的区块才是有效的呢,简单来说就是对于一个哈希值,其开头部分都是0就可以了(0越多,难度越高)。像这种,找到答案很困难但验证答案却非常轻松的算法就是 Proof of Work 的精髓。
1 2 3 4
| func isHashValid(hash string, difficulty int) bool { prefix := strings.Repeat("0", difficulty) return strings.HasPrefix(hash, prefix) }
|
一个难度逐渐递增的区块链
下面实现了一个难度逐渐递增的区块链,运行时就会发现产生区块的时间间隔越来越长,因为 CPU 需要经过更多的计算才能找到符合条件的哈希值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| func main() { difficulty := 1 genesisBlock := Block{} genesisBlock = Block{ idx: 0, timestamp: time.Now().String(), hash: calculateHash(genesisBlock), prevHash: "", difficulty: difficulty, nonce: "", } blockchain.AddBlock(genesisBlock)
var block Block block = genesisBlock for { block = generateBlock(block, diff) difficulty++ blockchain.AddBlock(block) } }
|