基于指標陣列實作簡單的區塊鏈 day(1)
- 一、位元幣的基礎知識
- 1.1 位元幣
- 1.2 區塊
- 1.3 區塊鏈
- 1.4 記賬
- 1. 5 錢包
- 1.6 節點
- 1.7 挖礦
- 1.8出塊時間
- 1.9 出塊獎勵
- 1.10 位元幣總量
- 1.11 區塊容量
- 1.12 每秒成交量
- 1.13 單位
- 二、其他基礎知識
- 2.1 挖礦(作業量證明)
- 2.2 go演示挖礦
- 2.3 地址生成規則
- 2.4 base64
- 2.5 交易
- 三、模擬簡單的區塊鏈
- 3.1 創建簡單的區塊
- 3.2 創建簡單的區塊鏈
- 3.3 創建創世塊
- 3.4 向區塊鏈中添加區塊
- 四、模擬復雜的區塊鏈
- 4.1 將unit64轉換成byte型別
- 4.2 bytes.Join()
- 4.3 挖礦演示
- 五、git命令
- 5.1 git pull
- 5.2 git push
- 5.3 git push --set-upstream origin v2
一、位元幣的基礎知識
1.1 位元幣
一個軟體系統,每個人都可以下載使用,使用者之間不斷進行交易,產生資料
1.2 區塊
位元幣系統使用者之間交易的資料以資料塊的形式存盤,最終存盤在資料庫中,這個包含交易資料的資料塊我們稱之為區塊,
1.3 區塊鏈
保存上述所有區塊的資料庫我們稱之為區塊鏈,
1.4 記賬
將系統中的交易資料寫到資料庫中我們稱之為記賬
1. 5 錢包
- 創建私鑰公鑰,保存公鑰,相當于錢包,可以存放多個地址
- 地址類似銀行卡,私鑰類似銀行卡密碼
- 錢包會便利賬本的交易資訊,來得知有沒有錢
- 一個地址對應一個私鑰
1.6 節點
每一個運行區塊鏈挖礦軟體的人都會便成為一個區塊鏈網路的節點,
1.7 挖礦
節點之間競爭記賬的權利就稱之為挖礦,
1.8出塊時間
大約10分鐘出一個位元幣
1.9 出塊獎勵
1.10 位元幣總量
1.11 區塊容量
1M大約容納4000筆交易
1.12 每秒成交量
1.13 單位
sat(聰)
二、其他基礎知識
2.1 挖礦(作業量證明)
sha256(區塊資料+隨機資料)<目標的哈希值
2.2 go演示挖礦
import (
"crypto/sha256"
"fmt"
)
func main(){
data := "helloWord"
for i:=0; i < 100; i++{
res := sha256.Sum256([]byte(data + string(i)))
fmt.Printf("%x", res[:])
fmt.Println()
}
}
2.3 地址生成規則
私鑰經過橢圓曲線相乘生成公鑰,在通過哈希演算法得到位元幣地址,
2.4 base64
0-9,a-z,A-Z,+,-
2.5 交易
- 挖礦交易
- 普通交易
三、模擬簡單的區塊鏈
3.1 創建簡單的區塊
type Block struct{
PreBlockHash []byte
Hash []byte
Data []byte
}
//創建block
func createBlock(preBlockHash []byte, data string) *Block{
block := Block{
PreBlockHash: preBlockHash,
Data: []byte(data),
Hash: []byte{},
}
block.SetHash()
return &block
}
// SetHash 計算當前區塊的hash
func (block *Block)SetHash(){
//...的作用是把data陣列打散,一個個裝進preBlockHash切片中
blockInfo := append(block.PreBlockHash,block.Data...)
//hash是一個位元組陣列
Hash := sha256.Sum256(blockInfo)
//block.Hash作為Hash的切片
block.Hash = Hash[:]
}
func main() {
//創建一個區塊
var block *Block = createBlock([]byte{}, "第一個區塊")
fmt.Printf("上一區塊的hash值%x:",block.PreBlockHash)
fmt.Println()
fmt.Printf("當前區塊的hash值%x:",block.Hash)
fmt.Println()
fmt.Println("當前區塊的資料",string(block.Data))
}
結果:
前面區塊的hash值 []
當前區塊的hash值328fffe02f9e57c15508352cb145aa68abcf83da69a059e975d2171b1e7f8f92
當前區塊的資料 第一個區塊
3.2 創建簡單的區塊鏈
- 本質上是用一個區塊指標型別的陣列構成的區塊鏈
// BlockChain 區塊鏈結構體
//本質上是區塊指標型別的陣列
type BlockChain struct {
blockChain []*Block
}
// CreateBlockChain 創建帶有一個創世塊的區塊鏈
func CreateBlockChain() *BlockChain{
blockChain := BlockChain{
blockChain: []*Block{GenesisBlock()},
}
return &blockChain
}
3.3 創建創世塊
// GenesisBlock 創建創世塊,即第一個區塊
func GenesisBlock() *Block{
genesisBlock := CreateBlock([]byte{},"第一個創世塊,牛逼")
return genesisBlock
}
3.4 向區塊鏈中添加區塊
// AddBlock 當前區塊的前一區塊哈希值欄位從區塊鏈中獲取
func (bc *BlockChain)AddBlock(data string){
preHash := bc.blockChain[len(bc.blockChain)-1].Hash
block := CreateBlock(preHash, data)
bc.blockChain = append(bc.blockChain, block)
}
四、模擬復雜的區塊鏈
4.1 將unit64轉換成byte型別
// Uint64ConvertByte 將uint64型別轉換為[]byte{}型別
func Uint64ConvertByte(data uint64)[]byte{
var buffer bytes.Buffer
err := binary.Write(&buffer, binary.BigEndian,data)
if err != nil {
log.Panicln(err)
}
return buffer.Bytes()
}
4.2 bytes.Join()
- 將二維byte陣列連接成一個一維byte陣列
func (block *Block)SetHash(){
var blockInfo []byte
//...的作用是把data陣列打散,一個個裝進preBlockHash切片中
//blockInfo = append(blockInfo, Uint64ConvertByte(block.Version)...)
//blockInfo = append(blockInfo, block.PreBlockHash...)
//blockInfo = append(blockInfo, block.MerkelRoot...)
//blockInfo = append(blockInfo, Uint64ConvertByte(block.TimeStamp)...)
//blockInfo = append(blockInfo, Uint64ConvertByte(block.Difficulty)...)
//blockInfo = append(blockInfo, Uint64ConvertByte(block.Nonce)...)
//blockInfo = append(blockInfo, block.Data...)
// 創建一個二維陣列
tem := [][]byte{
Uint64ConvertByte(block.Version),
block.PreBlockHash,
block.MerkelRoot,
Uint64ConvertByte(block.TimeStamp),
Uint64ConvertByte(block.Difficulty),
Uint64ConvertByte(block.Nonce),
block.Data,
}
//將二維byte陣列連接成一維byte陣列
bytes.Join(tem, []byte{})
//hash是一個位元組陣列
Hash := sha256.Sum256(blockInfo)
//block.Hash作為Hash的切片
block.Hash = Hash[:]
}
4.3 挖礦演示
type ProofOfWork struct {
block *Block
target *big.Int
}
//CreatePOW 創建ProofOfWork
func CreatePOW(block *Block) *ProofOfWork{
pow := ProofOfWork{
block: block,
}
target := "0000100000000000000000000000000000000000000000000000000000000000"
bigNum := big.Int{}
//res是指標型別的
res, _ := bigNum.SetString(target, 16)
pow.target = res
return &pow
}
//Run 回傳一個Hash值和亂數
func (pow *ProofOfWork) Run()([]byte, uint64){
tmpBigInt := &big.Int{}
//與給定的目標哈希值進行比較,小于則挖礦成功
var nonce uint64 = 0
var hash [32]byte
for{
block := pow.block
tem := [][]byte{
Uint64ConvertByte(block.Version),
block.PreBlockHash,
block.MerkelRoot,
Uint64ConvertByte(block.TimeStamp),
Uint64ConvertByte(block.Difficulty),
Uint64ConvertByte(nonce),
block.Data,
}
// blockInfo 拼裝好的資料
blockInfo := bytes.Join(tem, []byte(""))
hash = sha256.Sum256(blockInfo)
tmpBigInt.SetBytes(hash[:])
res := tmpBigInt.Cmp(pow.target)
if res == -1{
break
}
nonce ++
}
return hash[:],nonce
}
五、git命令
5.1 git pull
將遠程主機 origin 的 master 分支拉取過來,與本地的 brantest 分支合并,
git pull origin master:brantest
5.2 git push
git push 命用于從將本地的分支版本上傳到遠程并合并,
命令格式如下:
git push <遠程主機名> <本地分支名>:<遠程分支名>
如果本地分支名與遠程分支名相同,則可以省略冒號:
git push <遠程主機名> <本地分支名>
5.3 git push --set-upstream origin v2
- 設定本地分支追蹤遠程分支
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/303102.html
標籤:區塊鏈
