gr601_buial 4 lat temu
rodzic
commit
42cdd99606
3 zmienionych plików z 153 dodań i 0 usunięć
  1. 37 0
      blockchain/block.go
  2. 88 0
      blockchain/proof.go
  3. 28 0
      main.go

+ 37 - 0
blockchain/block.go

@@ -0,0 +1,37 @@
+package blockchain
+
+type BlockChain struct {
+	Blocks []*Block
+}
+
+type Block struct {
+	Hash     []byte
+	Data     []byte
+	PrevHash []byte
+	Nonce    int
+}
+
+func CreateBlock(data string, prevHash []byte) *Block {
+	block := &Block{[]byte{}, []byte(data), prevHash, 0}
+	pow := NewProof(block)
+	nonce, hash := pow.Run()
+
+	block.Hash = hash[:]
+	block.Nonce = nonce
+
+	return block
+}
+
+func (chain *BlockChain) AddBlock(data string) {
+	prevBlock := chain.Blocks[len(chain.Blocks)-1]
+	new := CreateBlock(data, prevBlock.Hash)
+	chain.Blocks = append(chain.Blocks, new)
+}
+
+func Genesis() *Block {
+	return CreateBlock("Genesis", []byte{})
+}
+
+func InitBlockChain() *BlockChain {
+	return &BlockChain{[]*Block{Genesis()}}
+}

+ 88 - 0
blockchain/proof.go

@@ -0,0 +1,88 @@
+package blockchain
+
+import (
+	"bytes"
+	"crypto/sha256"
+	"encoding/binary"
+	"fmt"
+	"log"
+	"math"
+	"math/big"
+)
+
+const Difficulty = 18
+
+type ProofOfWork struct {
+	Block  *Block
+	Target *big.Int
+}
+
+func NewProof(b *Block) *ProofOfWork {
+	target := big.NewInt(1)
+	target.Lsh(target, uint(256-Difficulty))
+
+	pow := &ProofOfWork{b, target}
+
+	return pow
+}
+
+func (pow *ProofOfWork) InitData(nonce int) []byte {
+	data := bytes.Join(
+		[][]byte{
+			pow.Block.PrevHash,
+			pow.Block.Data,
+			ToHex(int64(nonce)),
+			ToHex(int64(Difficulty)),
+		},
+		[]byte{},
+	)
+
+	return data
+}
+
+func (pow *ProofOfWork) Run() (int, []byte) {
+	var intHash big.Int
+	var hash [32]byte
+
+	nonce := 0
+
+	for nonce < math.MaxInt64 {
+		data := pow.InitData(nonce)
+		hash = sha256.Sum256(data)
+
+		fmt.Printf("\r%x", hash)
+		intHash.SetBytes(hash[:])
+
+		if intHash.Cmp(pow.Target) == -1 {
+			break
+		} else {
+			nonce++
+		}
+
+	}
+	fmt.Println()
+
+	return nonce, hash[:]
+}
+
+func (pow *ProofOfWork) Validate() bool {
+	var intHash big.Int
+
+	data := pow.InitData(pow.Block.Nonce)
+
+	hash := sha256.Sum256(data)
+	intHash.SetBytes(hash[:])
+
+	return intHash.Cmp(pow.Target) == -1
+}
+
+func ToHex(num int64) []byte {
+	buff := new(bytes.Buffer)
+	err := binary.Write(buff, binary.BigEndian, num)
+	if err != nil {
+		log.Panic(err)
+
+	}
+
+	return buff.Bytes()
+}

+ 28 - 0
main.go

@@ -0,0 +1,28 @@
+package main
+
+import (
+	"fmt"
+	"strconv"
+
+	"./blockchain"
+)
+
+func main() {
+	chain := blockchain.InitBlockChain()
+
+	chain.AddBlock("First Block after Genesis")
+	chain.AddBlock("Second Block after Genesis")
+	chain.AddBlock("Third Block after Genesis")
+
+	for _, block := range chain.Blocks {
+
+		fmt.Printf("Previous Hash: %x\n", block.PrevHash)
+		fmt.Printf("Data in Block: %s\n", block.Data)
+		fmt.Printf("Hash: %x\n", block.Hash)
+
+		pow := blockchain.NewProof(block)
+		fmt.Printf("PoW: %s\n", strconv.FormatBool(pow.Validate()))
+		fmt.Println()
+
+	}
+}