### 二、本例中的一些数据结构

type Block struct {
Index     int
TimeStamp string
BPM       int
HashCode  string
PrevHash  string
Validator string
}

var Blockchain []Block
var tempBlocks []Block

var candidateBlocks = make(chan Block)

var announcements = make(chan string)

var validators = make(map[string]int)

### 三、生成区块和计算哈希

func generateBlock(oldBlock Block, BPM int, address string) Block {
var newBlock Block
newBlock.Index = oldBlock.Index + 1
newBlock.TimeStamp = time.Now().String()
newBlock.BPM = BPM
newBlock.PrevHash = oldBlock.HashCode
newBlock.HashCode = GenerateHashValue(newBlock)
return newBlock
}

func GenerateHashValue(block Block) string {
var hashcode = block.PrevHash +
block.TimeStamp + block.Validator +
strconv.Itoa(block.BPM) + strconv.Itoa(block.Index)
return calculateHash(hashcode)
}

func calculateHash(s string) string {
var sha = sha256.New()
sha.Write([]byte(s))
hashed := sha.Sum(nil)
return hex.EncodeToString(hashed)
}

### 四、主逻辑

func main() {
if err != nil {
log.Fatal(err)
}

genesisBlock := Block{}
genesisBlock = Block{0, time.Now().String(), 0,
GenerateHashValue(genesisBlock), "", ""}
spew.Dump(genesisBlock)

Blockchain = append(Blockchain, genesisBlock)

port := os.Getenv("PORT")

server, err := net.Listen("tcp", ":"+port)
if err != nil {
log.Fatal(err)
}

log.Println("HTTP Server Listening on port :", port)

defer server.Close()

go func() {
for cadidate := range candidateBlocks {

mutex.Lock()

mutex.Unlock()
}
}()

go func() {
for {

pickWinner()
}
}()

for {
conn, err := server.Accept()
if err != nil {
log.Fatal(err)
}
go handleConn(conn)
}
}

spew.Dump(genesisBlock)

Blockchain = append(Blockchain, genesisBlock)

port := os.Getenv("PORT")

defer server.Close()

### 五、获取记账权的节点

func pickWinner() {
time.Sleep(30 * time.Second)
mutex.Lock()
temp := tempBlocks
mutex.Unlock()

lotteryPool := []string{}
if len(temp) > 0 {
OUTER:
for _, block := range temp {
for _, node := range lotteryPool {
if block.Validator == node {
continue OUTER
}
}

mutex.Lock()

setValidators := validators
mutex.Unlock()

k, ok := setValidators[block.Validator]
if ok {

for i := 0; i < k; i++ {
lotteryPool = append(lotteryPool, block.Validator)
}
}
}

s := rand.NewSource(time.Now().Unix())
r := rand.New(s)

lotteryWinner := lotteryPool[r.Intn(len(lotteryPool))]

for _, block := range temp {
if block.Validator == lotteryWinner {
mutex.Lock()
Blockchain = append(Blockchain, block)
mutex.Unlock()
for _ = range validators {
announcements <- "\nvalidator:" + lotteryWinner + "\n"
}
break
}
}

}
mutex.Lock()
tempBlocks = []Block{}
mutex.Unlock()
}

### 六、处理命令行的请求

func handleConn(conn net.Conn) {

defer conn.Close()

go func() {
for {
msg := <-announcements
io.WriteString(conn, msg)
}
}()

io.WriteString(conn, "Enter token balance:")

scanBalance := bufio.NewScanner(conn)
for scanBalance.Scan() {

balance, err := strconv.Atoi(scanBalance.Text())
if err != nil {
log.Printf("%v not a number: %v", scanBalance.Text(), err)
return
}

fmt.Println(validators)
break
}

io.WriteString(conn, "\nEnter a new BPM:")

scanBPM := bufio.NewScanner(conn)
go func() {

for {
for scanBPM.Scan() {
bmp, err := strconv.Atoi(scanBPM.Text())
if err != nil {
log.Printf("%v not a number: %v", scanBPM.Text(), err)

conn.Close()
}

mutex.Lock()
oldLastIndex := Blockchain[len(Blockchain)-1]
mutex.Unlock()

if err != nil {
log.Println(err)
continue
}

if isBlockValid(newBlock, oldLastIndex) {

candidateBlocks <- newBlock
}
}
}
}()

for {
time.Sleep(time.Second * 20)
mutex.Lock()

output, err := json.Marshal(Blockchain)
mutex.Unlock()
if err != nil {
log.Fatal(err)
}

io.WriteString(conn, string(output)+"\n")
}

}

func isBlockValid(newBlock, oldBlock Block) bool {

if oldBlock.Index+1 != newBlock.Index {
return false
}

if oldBlock.HashCode != newBlock.PrevHash {
return false
}

if GenerateHashValue(newBlock) != newBlock.HashCode {
return false
}
return true
}

defer conn.Close()

address = calculateHash(time.Now().String())

delete(validators, address)
conn.Close()