#区块的定义和操作
#链的定义和操作
#工作量证明
//main.gopackage mainimport "fmt"func main(){fmt.Println("=======================")bc := NewBlockChain()t1 := Transactions{[]byte("111"),[]byte("a send b 1 BTC")}t2 := Transactions{[]byte("222"),[]byte("b send c 1 BTC")}bc.AddBlock(&t1)bc.AddBlock(&t2)fmt.Println()bc.Print()}
//chain.gopackage mainimport "fmt"type BlockChain struct{blocks []*Block}func NewBlockChain() *BlockChain{block := NewGenesisBlock()chain := BlockChain{blocks:[]*Block{block},}return &chain}func (chain *BlockChain) AddBlock(body *Transactions){prevBlockHash := chain.blocks[len(chain.blocks)-1].Hashblock := NewBlock(string(body.Coinbase),string(body.Data),prevBlockHash)chain.blocks = append(chain.blocks,block)}func (chain *BlockChain) Print(){for _,data := range chain.blocks{fmt.Printf("Version %d\n",data.Version)fmt.Printf("PrevBlockHash %x\n",string(data.PrevBlockHash))fmt.Printf("MerKelRoot %x\n",string(data.MerKelRoot))fmt.Printf("TimeStamp %d\n",data.TimeStamp)fmt.Printf("Bits %d\n",data.Bits)fmt.Printf("Nonce %d\n",data.Nonce)fmt.Printf("Hash %x\n",string(data.Hash))fmt.Printf("Coinbase %s\n",string(data.Coinbase))fmt.Printf("Data %s\n",string(data.Data))fmt.Printf("IsValid %v\n",NewProofWork(data).IsValid())fmt.Println("\r\n")}}
//block.gopackage mainimport "time"//定义区块头结构体type BlockHeader struct{//版本//区块版本号,表示本区块遵守的验证规则Version int64//前一区块的哈希值//SHA256PrevBlockHash[]byte//梅克尔根//该区块中交易的梅克尔树根的哈希值 SHA256MerKelRoot[]byte//时间戳//区块生成时间TimeStampint64//难度值//该区块工作量证明的难度目标Bits int64//随机值//挖矿找到的满足难度目标的随机值Nonce int64//*当前区块哈希值//实际上,区块不存储哈希值,节点接收区块后独立计算并存储在本地Hash []byte}//定义区块体结构体type Transactions struct{//第一条交易 矿工挖矿奖励Coinbase[]byte//普通交易信息//每笔交易包括(付款方、收款方、金额、手续费等)Data[]byte}//定义区块结构体type Block struct{BlockHeaderTransactions}//创建区块func NewBlock(coinbase,data string,prevBlockHash []byte) *Block{var block Blockblock.Version = 1block.PrevBlockHash = prevBlockHashblock.MerKelRoot = []byte{}block.TimeStamp = time.Now().Unix()block.Bits = TargetBitsblock.Coinbase = []byte(coinbase)block.Data = []byte(data)pow := NewProofWork(&block)nonce,hash := pow.Run()block.Nonce = nonceblock.Hash = hashreturn &block}//创建创世块func NewGenesisBlock() *Block{return NewBlock("Genesis Block","",[]byte{})}
//pow.gopackage mainimport ("bytes""crypto/sha256""fmt""math""math/big""time")const TargetBits = 24//定义工作量证明结构type ProofOfWork struct{block *Block//目标值target *big.Int}//创建POW(PROOF OF WORK)的函数func NewProofWork(block *Block) *ProofOfWork{//0x000000000000...01target := big.NewInt(1)//0x000000100000...00target.Lsh(target,256-uint(block.Bits))return &ProofOfWork{block,target}}//寻找随机数 计算哈希func (pow *ProofOfWork)Run()(int64,[]byte){fmt.Println("开始挖矿...")fmt.Printf("target < hash: [ %x]\n",pow.target.Bytes())var nonce int64 = 0var hash [32]bytevar hashInt big.Intfor nonce < math.MaxInt64{data := pow.prepare(nonce)hash = sha256.Sum256(data)hashInt.SetBytes(hash[:])if hashInt.Cmp(pow.target) == -1{fmt.Printf("found nonce // [%x] %d\n",hash,nonce)break}else{nonce++}}//返回找到的随机数nonce和算出的哈希return nonce,hash[:]}//校验计算结果func (pow *ProofOfWork)IsValid() bool{data := pow.prepare(pow.block.Nonce)hash := sha256.Sum256(data)var hashInt big.InthashInt.SetBytes(hash[:])if hashInt.Cmp(pow.target) == -1{fmt.Printf("%x",hash[:])return true}else{return false}}func (pow *ProofOfWork)prepare(nonce int64) []byte{pow.block.TimeStamp = time.Now().Unix()block := pow.blocktmp := [][]byte{Int2Bytes(block.Version),block.PrevBlockHash,block.MerKelRoot,Int2Bytes(block.TimeStamp),Int2Bytes(TargetBits),Int2Bytes(nonce),block.Coinbase,block.Data,}data := bytes.Join(tmp,[]byte{})return data}
//utils.gopackage mainimport ("bytes""encoding/binary")func Int2Bytes(i int64) []byte{var buf bytes.Buffererr := binary.Write(&buf,binary.BigEndian,i)if err != nil{panic(-1)}return buf.Bytes()}