first commit

This commit is contained in:
SowinskiBraeden committed 2022-11-28 09:22:26 -08:00
commit 93685f2ed7
7 files changed
+441

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
package blockchain
import (
"bytes"
"encoding/gob"
"log"
)
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 Genesis() *Block {
return CreateBlock("Genesis", []byte{})
}
func (b *Block) Serialize() []byte {
var res bytes.Buffer
encoder := gob.NewEncoder(&res)
err := encoder.Encode(b)
Handle(err)
return res.Bytes()
}
func Deserialize(data []byte) *Block {
var block Block
decoder := gob.NewDecoder(bytes.NewReader(data))
err := decoder.Decode(&block)
Handle(err)
return &block
}
func Handle(err error) {
if err != nil {
log.Panic(err)
}
}
+105
View File
@@ -0,0 +1,105 @@
package blockchain
import (
"fmt"
"github.com/dgraph-io/badger"
)
const (
dbPath = "./tmp/blocks"
)
type BlockChain struct {
LastHash []byte
Database *badger.DB
}
type BlockChainIterator struct {
CurrentHash []byte
Database *badger.DB
}
func InitBlockChain() *BlockChain {
var lastHash []byte
opts := badger.DefaultOptions(dbPath)
opts.Logger = nil
db, err := badger.Open(opts)
Handle(err)
err = db.Update(func(txn *badger.Txn) error {
if _, err := txn.Get([]byte("lh")); err == badger.ErrKeyNotFound {
fmt.Println("No existing blockchain found")
genesis := Genesis()
fmt.Println("Genesis proved")
err = txn.Set(genesis.Hash, genesis.Serialize())
Handle(err)
err = txn.Set([]byte("lh"), genesis.Hash)
lastHash = genesis.Hash
return err
} else {
item, err := txn.Get([]byte("lh"))
Handle(err)
lastHash, err = item.ValueCopy(nil)
return err
}
})
Handle(err)
blockchain := BlockChain{lastHash, db}
return &blockchain
}
func (chain *BlockChain) AddBlock(data string) {
var lastHash []byte
err := chain.Database.View(func(txn *badger.Txn) error {
item, err := txn.Get([]byte("lh"))
Handle(err)
lastHash, err = item.ValueCopy(nil)
return err
})
Handle(err)
newBlock := CreateBlock(data, lastHash)
err = chain.Database.Update(func(txn *badger.Txn) error {
err := txn.Set(newBlock.Hash, newBlock.Serialize())
Handle(err)
err = txn.Set([]byte("lh"), newBlock.Hash)
chain.LastHash = newBlock.Hash
return err
})
Handle(err)
}
func (chain *BlockChain) Iterator() *BlockChainIterator {
iter := &BlockChainIterator{chain.LastHash, chain.Database}
return iter
}
func (iter *BlockChainIterator) Next() *Block {
var block *Block
err := iter.Database.View(func(txn *badger.Txn) error {
item, err := txn.Get(iter.CurrentHash)
Handle(err)
encodedBlock, err := item.ValueCopy(nil)
block = Deserialize(encodedBlock)
return err
})
Handle(err)
iter.CurrentHash = block.PrevHash
return block
}
+97
View File
@@ -0,0 +1,97 @@
package blockchain
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"log"
"math"
"math/big"
)
// Take the data from the block
// Create a counter (nonce) which starts at 0
// Create a hash of the data plus the counter
// Check the hash to see if it meets a set of requireents
// Requirements:
// The first few bytes must contain 0s
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()
}