Skip to content

fix: refactoring code #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions internal/blockchain/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,38 @@ import (
"bytes"
"crypto/sha256"
"strconv"
"time"
)

type Block struct {
Timestamp int64
Data []byte // Transactions
prevBlockHash []byte
PrevBlockHash []byte
Hash []byte
Counter int // Nonce
}

func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.prevBlockHash, b.Data, timestamp}, []byte{})
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
b.Hash = hash[:]
}

// NewBlock creates and returns a new block.
func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{
Timestamp: 0,
Timestamp: time.Now().Unix(),
Data: []byte(data),
prevBlockHash: prevBlockHash,
PrevBlockHash: prevBlockHash,
Hash: []byte{},
Counter: 0,
}

block.SetHash()
pow := NewProofOfWork(block)
hash, nonce := pow.Run()
block.Hash = hash[:]
block.Counter = nonce

return block
}
27 changes: 24 additions & 3 deletions internal/blockchain/blockchain.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package blockchain

import "bytes"

type Blockchain struct {
blocks []*Block
Blocks []*Block
}

func (bc *Blockchain) AddBlock(data string) {
prevBlock := bc.blocks[len(bc.blocks)-1]
prevBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := NewBlock(data, prevBlock.Hash)
bc.blocks = append(bc.blocks, newBlock)
bc.Blocks = append(bc.Blocks, newBlock)
}

func NewGenesisBlock() *Block {
Expand All @@ -17,3 +19,22 @@ func NewGenesisBlock() *Block {
func NewBlockchain() *Blockchain {
return &Blockchain{[]*Block{NewGenesisBlock()}}
}

// IsValid validates the blockchain.
func (bc *Blockchain) IsValid() bool {
for i := 1; i < len(bc.Blocks); i++ {
currentBlock := bc.Blocks[i]
prevBlock := bc.Blocks[i-1]

if !bytes.Equal(currentBlock.PrevBlockHash, prevBlock.Hash) {
return false
}

pow := NewProofOfWork(currentBlock)
if !pow.Validate() {
return false
}
}

return true
}
47 changes: 25 additions & 22 deletions internal/blockchain/proof_of_work.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,34 @@ import (
"strconv"
)

const targetBits = 24
const Difficulty = 16

var maxNonce = math.MaxInt64

const Difficulty = 16

// ProofOfWork represents a proof-of-work.
type ProofOfWork struct {
block *Block
T big.Int
}

// Prepare pow data, this function hashes the data and returns it
// NewProofOfWork creates and returns a ProofOfWork.
func NewProofOfWork(b *Block) *ProofOfWork {
target := big.NewInt(1)
target.Lsh(target, uint(256-Difficulty))

pow := &ProofOfWork{b, *target}

return pow
}

// prepareData prepares data for hashing.
func (pow *ProofOfWork) prepareData(nonce int) []byte {
data := bytes.Join(
[][]byte{
pow.block.prevBlockHash,
pow.block.PrevBlockHash,
pow.block.Data,
[]byte(strconv.FormatInt(pow.block.Timestamp, 10)),
[]byte(strconv.FormatInt(targetBits, 10)),
[]byte(strconv.FormatInt(int64(Difficulty), 10)),
[]byte(strconv.FormatInt(int64(nonce), 10)),
},
[]byte{},
Expand All @@ -36,39 +44,34 @@ func (pow *ProofOfWork) prepareData(nonce int) []byte {
return data
}

func (pow *ProofOfWork) RunProofOfWork() (int, []byte) {
// Run performs the proof-of-work algorithm.
func (pow *ProofOfWork) Run() ([]byte, int) {
var hashInt big.Int
var hash [32]byte
nonce := 0

if pow.block == nil {
pow.block.Data = NewGenesisBlock().Data
} else {
temp_block := pow.block
temp_block.SetHash()
pow.block = temp_block
}

for nonce < maxNonce {
data := pow.prepareData(nonce)
hash = sha256.Sum256(data)

hashInt.SetBytes(hash[:])

if hashInt.Cmp(&pow.T) == -1 {
break
} else {
nonce++
}
}

return nonce, hash[:]
return hash[:], nonce
}

func NewProofOfWork(b *Block) *ProofOfWork {
target := big.NewInt(1)
target.Lsh(target, uint(256-Difficulty))
// Validate checks if the block's proof-of-work is valid.
func (pow *ProofOfWork) Validate() bool {
var hashInt big.Int
data := pow.prepareData(pow.block.Counter)

pow := &ProofOfWork{b, *target}
hash := sha256.Sum256(data)
hashInt.SetBytes(hash[:])

return pow
return hashInt.Cmp(&pow.T) == -1
}
110 changes: 55 additions & 55 deletions internal/blockchain/validantions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,100 +11,100 @@ import (
type Receive func() string
type Input func() string

// ValidateBlockPredicate validates a block using Proof of Work
func ValidateBlockPredicate(pow *ProofOfWork) bool {
var hashInt big.Int

data := pow.prepareData(pow.block.Counter)
hash := sha256.Sum256(data)
hashInt.SetBytes(hash[:])

validation := hashInt.Cmp(&pow.T) == -1
return validation
return hashInt.Cmp(&pow.T) == -1
}

// Simple Content Validation Predicate implementation from backbone protocol
func ContentValidatePredicate(x *Blockchain) bool {

if len(x.blocks) == 0 {
// ContentValidatePredicate validates the content of the blockchain
func ContentValidatePredicate(chain *Blockchain) bool {
if len(chain.Blocks) == 0 {
return false
}

for i := range x.blocks {
if i == 0 {
continue
}
if reflect.DeepEqual(x.blocks[i].Hash, x.blocks[i-1].Hash) {
for i := 1; i < len(chain.Blocks); i++ {
if reflect.DeepEqual(chain.Blocks[i].Hash, chain.Blocks[i-1].Hash) {
return false
}
}
return true
}

func InputContributionFunction(data []byte, cr *Blockchain, round int, input Input, receive Receive) {

input_data := input()
receive_data := receive()

concat_data := input_data + receive_data
// creating new block
// InputContributionFunction processes input and adds a new block to the blockchain
func InputContributionFunction(data []byte, chain *Blockchain, round int, input Input, receive Receive) {
inputData := input()
receiveData := receive()
concatData := inputData + receiveData

newBlock := &Block{
Timestamp: time.Now().Unix(),
Data: []byte(concatData),
PrevBlockHash: chain.Blocks[len(chain.Blocks)-1].Hash,
Counter: round,
}

newBlock := &Block{time.Now().Unix(), []byte(concat_data), cr.blocks[len(cr.blocks)-1].Hash, []byte{}, round}
cr.blocks = append(cr.blocks, newBlock)
chain.Blocks = append(chain.Blocks, newBlock)

if !ContentValidatePredicate(cr) {
if !ContentValidatePredicate(chain) {
fmt.Println("Content Validation Failed")
cr.blocks = cr.blocks[:len(cr.blocks)-1]
chain.Blocks = chain.Blocks[:len(chain.Blocks)-1]
} else {
fmt.Println("Content Validation Passed")
}
}

// Function to read the chain
func ChainReadFunction(c *Blockchain) string {
data := ""
for i := range c.blocks {
data += string(c.blocks[i].Data)
// ChainReadFunction returns the data of the blockchain as a string
func ChainReadFunction(chain *Blockchain) string {
var data string
for _, block := range chain.Blocks {
data += string(block.Data)
}
return data
}

// Function to validate the chain
func ChainValidationPredicate(c *Blockchain) bool {
b := ContentValidatePredicate(c)

if b {
temp_chain := c.blocks[len(c.blocks)-1]
s_ := sha256.Sum256(temp_chain.Data)
proof_ := &ProofOfWork{temp_chain, *big.NewInt(1)}

for i := true; i; b = false || c == nil {
if ValidateBlockPredicate(proof_) && reflect.DeepEqual(temp_chain.Hash, s_) {
s_ = [32]byte{}
copy(s_[:], temp_chain.Data)
c.blocks = c.blocks[:len(c.blocks)-1]
} else {
b = false
}
// ChainValidationPredicate validates the blockchain
func ChainValidationPredicate(chain *Blockchain) bool {
if !ContentValidatePredicate(chain) {
return false
}

for len(chain.Blocks) > 0 {
lastBlock := chain.Blocks[len(chain.Blocks)-1]
hash := sha256.Sum256(lastBlock.Data)
proof := &ProofOfWork{block: lastBlock, T: *big.NewInt(1)}

if !ValidateBlockPredicate(proof) || !reflect.DeepEqual(lastBlock.Hash, hash) {
return false
}

// Prepare the hash for the next iteration
hash = [32]byte{}
copy(hash[:], lastBlock.Data)
chain.Blocks = chain.Blocks[:len(chain.Blocks)-1]
}
return b
}

// Function to find the best chain
return true
}

func MaxChain(c [][]Blockchain) []*Block {
temp_chain := []*Block{}
// MaxChain finds the best chain among multiple chains
func MaxChain(chains [][]Blockchain) []*Block {
var bestChain []*Block

for i := 1; i < len(c); i++ {
if ChainValidationPredicate(&c[i][0]) {
temp_chain = maxBlocks(temp_chain, c[i][0].blocks)
for i := 1; i < len(chains); i++ {
if ChainValidationPredicate(&chains[i][0]) {
bestChain = maxBlocks(bestChain, chains[i][0].Blocks)
}
}

return temp_chain
return bestChain
}

// compare blockchains length
// maxBlocks returns the longer of two block slices
func maxBlocks(a, b []*Block) []*Block {
if len(a) > len(b) {
return a
Expand Down
Loading