2021年618京享红包 - 618大促主会场
九阳 Joyoung电磁炉 电陶炉 2200W大功率 家用火锅套装 旋转控温 红外光波加热 H22-x3 赠烤盘
凯迪仕电子锁618狂欢购
有健康 更热爱
美丽雅品牌会员周

区块链实战(一)实现简单的区块与区块链交易

千纸鹤 1月前   阅读数 34 0

区块链实战

字节 字段 说明
4 版本 区块版本号,表示本区块遵守的验证规则
32 父区块头哈希值 前一区块的Merkle树根的哈希值,同样采取SHA256计算
32 Merkle根 该区块中交易的Merkle树根的哈希值,同样采用SHA256计算
4 时间戳 该区块产生的近似时间,精确到秒的UNIX时间戳,必须严格大于前11各区块的时间的中值,同时全节点也会拒接那些超过自己两个小时的时间戳的区块
4 难度目标 该区块工作量证明算法的难度目标,已经使用特定算法编码
4 Nonce 未来找到满足难度目标所设定的随机数,为了解决32为随机数在算力飞升的情况下不够用的问题,规定时间戳和coinbase交易信息均改变,以此扩展nonce的位数

**注意:**区块不存储hash值,节点接受区块后独立计算并存储在本地。

Version 1

区块相关:

​ 1.定义一个区块的结构Block

​ a.区块头:6个字段

​ b.区块体:字符串表示data

  1. 提供一个创建区块的方法

    ​ NewBlock(参数)

区块链相关

  1. 定义一个区块链结构BlockChain

    ​ Block数组

    1. 提供一个创建BlockChain()的方法

    ​ NewBlockChain()

    1. 提供一个添加区块的方法

    ​ AddBlock(参数)

block.go文件

package main

import (
	"bytes"
	"crypto/sha256"
	"time"
)

/* 1.定义一个区块的结构Block ​a.区块头:6个字段 ​b.区块体:字符串表示data */
//区块
type Block struct {
     
	Version int64   //版本
	PerBlockHash []byte //前一个区块的hash值
	Hash []byte //当前区块的hash值,是为了简化代码
	MerKelRoot []byte  //梅克尔根
	TimeStamp int64  //时间抽
	Bits int64  //难度值
	Nonce int64 //随机值

//区块体
	Data []byte  //交易信息
}

/* 提供一个创建区块的方法 NewBlock(参数) */
func NewBlock(data string ,prevBlockHash []byte) *Block {
     
	var block Block
	block = Block{
     
		Version:      1,
		PerBlockHash: prevBlockHash,
		//Hash: []byte{}, //区块不存储hash值,节点接受区块后独立计算并存储在本地。
		MerKelRoot:   []byte{
     },
		TimeStamp:    time.Now().Unix(),
		Bits:         1,
		Nonce:        1,
		Data:         []byte(data),
	}
	block.SetHash()  //填充Hash
	return &block
}

func (block *Block) SetHash() {
     
	// 源码里面是要传二维切片 func Join(s [][]byte, sep []byte) []byte
	tmp :=[][]byte{
     
		IntToByte(block.Version),
		block.PerBlockHash,
		block.MerKelRoot,
		IntToByte(block.TimeStamp),
		IntToByte(block.Bits),
		IntToByte(block.Nonce),
	}
	data:=bytes.Join(tmp,[]byte{
     })    //之后再计算hash
	hash := sha256.Sum256(data)
	block.Hash = hash[:]  //变切片
}


//创始块
func NewGensisBlock() *Block{
     
	return NewBlock("Genesis Block!",[]byte{
     })
}

blockChain.go文件

package main


/* 1. 定义一个区块链结构BlockChain Block数组 */
type BlockChain struct {
     
   blocks []*Block
}

/* 2. 提供一个创建BlockChain()的方法 NewBlockChain() */
func NewBlockChain() *BlockChain {
     
   block := NewGensisBlock()
   return &BlockChain{
     blocks:[]*Block{
     block}}  //创建只有一个元素的区块链,初始化
}
/* 3. 提供一个添加区块的方法 AddBlock(参数) */

func (bc *BlockChain)AddBlock(data string)  {
     
   PerBlockHash := bc.blocks[len(bc.blocks)-1].Hash  //这一个区块的哈希是前一块的哈希值
   block := NewBlock(data,PerBlockHash)
   bc.blocks = append(bc.blocks,block)
}

utils.go文件

package main

import (
   "bytes"
   "encoding/binary"
   "fmt"
   "os"
)

func IntToByte(num int64) []byte {
     
   //func Write(w io.Writer, order ByteOrder, data interface{}) error {
     
   var buffer bytes.Buffer
   err := binary.Write(&buffer, binary.BigEndian, num)
   CheckErr("IntToByte",err)
   return buffer.Bytes()
}

func CheckErr(position string,err error) {
     
   if err != nil {
     
      fmt.Println("error ,pos:",position,err)
      os.Exit(1)
   }
}

main.go文件

package main

import "fmt"

func main() {
     
   bc := NewBlockChain()
   bc.AddBlock("A send B 1BTC")
   bc.AddBlock("B send C 1BTC")
   for _,block := range bc.blocks {
     
      fmt.Printf("Version : %d\n",block.Version)
      fmt.Printf("PerBlockHash : %x\n",block.PerBlockHash)
      fmt.Printf("Hash : %x\n",block.Hash)
      fmt.Printf("MerKelRoot : %x\n",block.MerKelRoot)
      fmt.Printf("TimeStamp : %d\n",block.TimeStamp)
      fmt.Printf("Bits : %d\n",block.Bits)
      fmt.Printf("Nonce : %d\n",block.Nonce)
      fmt.Printf("Data : %s\n",block.Data)
   }
}

执行结果


注意:本文归作者所有,未经作者允许,不得转载

全部评论: 0

    我有话说: