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 ~~~~~