- Proof of work established
This commit is contained in:
Brian Buller 2017-09-22 11:48:05 -05:00
parent 7ffe75002c
commit 72004f2396
3 changed files with 95 additions and 14 deletions

View File

@ -1,31 +1,35 @@
package main package main
import ( import (
"bytes" "math"
"crypto/sha256"
"strconv"
"time" "time"
) )
var (
maxNonce = math.MaxInt64
)
type Block struct { type Block struct {
Timestamp int64 Timestamp int64
Data []byte Data []byte
PrevBlockHash []byte PrevBlockHash []byte
Hash []byte Hash []byte
Nonce int
} }
// NewBlock returns a new block, ready to be added to the chain // NewBlock returns a new block, ready to be added to the chain
func NewBlock(data string, prevBlockHash []byte) *Block { func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}} block := &Block{
block.SetHash() Timestamp: time.Now().Unix(),
Data: []byte(data),
PrevBlockHash: prevBlockHash,
Hash: []byte{},
}
pow := NewProofOfWork(block)
nonce, hash := pow.Run()
block.Hash = hash[:]
block.Nonce = nonce
return block return block
} }
// SetHash creates the block hash
func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
b.Hash = hash[:]
}

60
proof.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"bytes"
"crypto/sha256"
"fmt"
"math/big"
)
const proofTargetBits = 16
type ProofOfWork struct {
block *Block
target *big.Int
}
func NewProofOfWork(b *Block) *ProofOfWork {
target := big.NewInt(1)
target.Lsh(target, uint(256-proofTargetBits))
pow := &ProofOfWork{b, target}
return pow
}
func (pow *ProofOfWork) prepareData(nonce int) []byte {
data := bytes.Join(
[][]byte{
pow.block.PrevBlockHash,
pow.block.Data,
IntToHex(pow.block.Timestamp),
IntToHex(int64(proofTargetBits)),
IntToHex(int64(nonce)),
},
[]byte{},
)
return data
}
func (pow *ProofOfWork) Run() (int, []byte) {
var hashInt big.Int
var hash [32]byte
nonce := 0
fmt.Printf("Mining the block containing \"%s\"\n", pow.block.Data)
for nonce < maxNonce {
data := pow.prepareData(nonce)
hash = sha256.Sum256(data)
fmt.Printf("\r%x", hash)
hashInt.SetBytes(hash[:])
if hashInt.Cmp(pow.target) == -1 {
break
} else {
nonce++
}
}
fmt.Print("\n\n")
return nonce, hash[:]
}

17
utils.go Normal file
View File

@ -0,0 +1,17 @@
package main
import (
"bytes"
"encoding/binary"
"log"
)
// IntToHex converts an int64 to a byte array
func IntToHex(num int64) []byte {
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, num)
if err != nil {
log.Panic(err)
}
return buf.Bytes()
}