Blockchain combat

byte field instructions
4 version The block version number, which represents the validation rules that the block complies with
32 Parent header hash The Merkle root hash of the previous block is also calculated using SHA256
32 Merkle root The hashes of Merkle roots traded in this block are also calculated using SHA256
4 The time stamp The approximate time of the block, a UNIX timestamp accurate to the second, must be strictly greater than the median of the first 11 blocks, and the entire node will reject any block with a timestamp longer than two hours
4 Difficult goals The block workload proves that the difficulty target of the algorithm has been encoded using a specific algorithm
4 Nonce In the future, we will find a random number that meets the difficulty goal. In order to solve the problem that 32 is not enough for the random number when the computing power is skyrocketing, we will change the timestamp and coinbase transaction information to expand the number of bits of the Nonce

** Note: The ** block does not store the hash value. The node accepts the block and computes it independently and stores it locally.

Version 1

Block related:

1. Define a Block structure

A. Block header: six fields B. Block body: a string representing dataCopy the code
  1. Provides a method for creating blocks

    NewBlock (parameters)

Blockchain related

  1. Define a BlockChain structure BlockChain

    Block array

  2. Provides a method to create BlockChain()

    ​ NewBlockChain()

  3. Provides a way to add blocks

    AddBlock (parameters)

Block. Go file

package main

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

A. Block header: 6 fields b. Block body: The string represents data */
/ / block
type Block struct {
	Version int64   / / version
	PerBlockHash []byte // The hash value of the previous block
	Hash []byte // The hash value of the current block is used to simplify the code
	MerKelRoot []byte  // Meckelgen
	TimeStamp int64  / / time
	Bits int64  / / difficulty value
	Nonce int64 / / random value

/ / block
	Data []byte  // Transaction information
}

/* Provides a method to create blocks NewBlock(parameter) */
func NewBlock(data string ,prevBlockHash []byte) *Block {
	var block Block
	block = Block{
		Version:      1,
		PerBlockHash: prevBlockHash,
		//Hash: []byte{}, // The block does not store the Hash value. The node accepts the block and calculates it independently and stores it locally.
		MerKelRoot:   []byte{},
		TimeStamp:    time.Now().Unix(),
		Bits:         1,
		Nonce:        1,
		Data:         []byte(data),
	}
	block.SetHash()  / / fill the Hash
	return &block
}

func (block *Block) SetHash(a) {
	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{})    // Then calculate the hash
	hash := sha256.Sum256(data)
	block.Hash = hash[:]  / / variable section
}


/ / founding block
func NewGensisBlock(a) *Block{
	return NewBlock("Genesis Block!"And []byte{})}Copy the code

BlockChain. Go file

package main


/* 1. Define a BlockChain structure BlockChain Block array */
type BlockChain struct {
   blocks []*Block
}

/* 2. Provide a way to create BlockChain() NewBlockChain() */
func NewBlockChain(a) *BlockChain {
   block := NewGensisBlock()
   return &BlockChain{blocks:[]*Block{block}}  // Create a blockchain with only one element and initialize it
}
/* 3. Provide a method to add blocks AddBlock(parameter) */

func (bc *BlockChain)AddBlock(data string)  {
   PerBlockHash := bc.blocks[len(bc.blocks)- 1].Hash  // The hash of this block is the hash of the previous block
   block := NewBlock(data,PerBlockHash)
   bc.blocks = append(bc.blocks,block)
}
Copy the code

Utils. Go file

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) {
   iferr ! =nil {
      fmt.Println("error ,pos:",position,err)
      os.Exit(1)}}Copy the code

The main. Go file

package main

import "fmt"

func main(a) {
   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)
   }
}
Copy the code

The execution result