Principle of DPOS

DPOS is the full name of Delegated Proof of Stake.

It can be understood that there are many nodes in the whole blockchain network, and we need to select some nodes as representatives to maintain the whole blockchain network. These representatives need to ensure the security and performance of the blockchain, no need to compete through POS computing power, and save energy.

Rules of DPOS

They can produce blocks and be kicked off the list of representatives if they are incompetent and run for re-election. Elections here require at least half the nodes of the entire network to pass, proving that decentralized voting is effective.

The DPOS algorithm requires randomly specifying the order of the list of representatives. Blocks that are not generated in order are invalid. The cards will be reshuffled once every cycle, disrupting the original order. There is no contention between representatives and blocks will not be omitted. A block will appear regularly, which greatly reduces the time period for consensus, which is also the advantage of POS and POW.

DPOS reward system

Because DPOS can process and confirm several orders of magnitude more transactions per second than POW and POS, a portion of the transactions will be awarded to network maintenance nodes and voters as a reward for representing election maintenance, allowing more nodes to participate.

Golang implements the DPOS algorithm

Package introduced

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math/rand"
	"sort"
	"time"
)
Copy the code

Block structure definition

type Block struct {
	Index int
	TimeStamp string
	BPM int
	Hash string
	PrevHash string
	Delegate string
}
Copy the code

Create a new block

func generateBlock(oldBlock Block, _BMP int , address string)(Block, error){
	var newBlock Block
	t := time.Now()

	newBlock.Index = oldBlock.Index + 1
	newBlock.TimeStamp = t.String()
	newBlock.BPM = _BMP
	newBlock.PrevHash = oldBlock.Hash
	newBlock.Hash = createBlockHash(newBlock)
	newBlock.Delegate = address
	fmt.Println("NewBlock: ", newBlock)
	return newBlock, nil
}
Copy the code

Generates the hash of the block


func createBlockHash(block Block) string{
   record := string(block.Index) + block.TimeStamp + string(block.BPM) + block.PrevHash
   sha3 := sha256.New()
   sha3.Write([] byte(record))
   hash := sha3.Sum(nil)
   fmt.Println("NewHash: ",hex.EncodeToString(hash))
   return hex.EncodeToString(hash)
}
Copy the code

Check if the new block is valid

func isBlockValid(newBlock, oldBlock Block) bool{
   ifoldBlock.Index + 1 ! = newBlock.Index{ fmt.Println("Failure!! The index of illegal")
   	return false
   }
   ifnewBlock.PrevHash ! = oldBlock.Hash{ fmt.Println("Failure!! PrevHash illegal")
   	return false
   }
   fmt.Println("Legal")
   return true
}
Copy the code

Define blockchain, delegate, delegate list

var blockChain []Block
type Trustee struct{
   name string
   votes int
}

type trusteeList [] Trustee
Copy the code

On behalf of the sort

func (_trusteeList trusteeList) Len() int{
   return len(_trusteeList)
}

func (_trusteeList trusteeList) Swap(i,j int){
   _trusteeList[i],_trusteeList[j] = _trusteeList[j],_trusteeList[i]
}

func (_trusteeList trusteeList) Less(i,j int) bool{
   return _trusteeList[j].votes < _trusteeList[i].votes
}
Copy the code

Delegate list generation


func selecTrustee()([]Trustee){
   _trusteeList := []Trustee{
   	{"node1", rand.Intn(100)},
   	{"node2", rand.Intn(100)},
   	{"node3", rand.Intn(100)},
   	{"node4", rand.Intn(100)},
   	{"node5", rand.Intn(100)},
   	{"node6", rand.Intn(100)},
   	{"node7", rand.Intn(100)},
   	{"node8", rand.Intn(100)},
   	{"node9", rand.Intn(100)},
   	{"node10", rand.Intn(100)},
   	{"node11", rand.Intn(100)},
   	{"node12", rand.Intn(100)},
   }
   sort.Sort(trusteeList(_trusteeList))
   result := _trusteeList[:5]
   _trusteeList = result[1:]
   _trusteeList = append(_trusteeList, result[0])
   fmt.Println("The current supernode delegate list is:",_trusteeList)
   return _trusteeList
}
Copy the code

Main function section

func mainGenesisBlock := Block{0, t. tring(),0,createBlockHash(Block{}),"".""} 
   fmt.Println(Genesis Block:, genesisBlock)
   blockChain = append(blockChain, genesisBlock)
   var trustee Trustee
   for _, trustee = range selecTrustee(){
   	_BPM := rand.Intn(100)
   	blockHeight := len(blockChain)
   	oldBlock := blockChain[blockHeight-1]
   	newBlock,err := generateBlock(oldBlock, _BPM, trustee.name)
   	iferr! =nil{ fmt.Println("New block generation failed:",err)
   		continue
   	}
   	if isBlockValid(newBlock, oldBlock){
   		blockChain = append(blockChain, newBlock)
   		fmt.Println("The current operating block node is:", trustee.name)
   		fmt.Println("Current block number:", len(blockChain))
   		fmt.Println("Current block information:", blockChain[len(blockChain)-1])
   	}
   }
}
Copy the code

Run a screenshot

At the end

We can also try, block chain is still very interesting ~~~~~