Skip to content

Commit

Permalink
Makes tests faster by using smaller mining difficulty.
Browse files Browse the repository at this point in the history
  • Loading branch information
web3coach committed Jun 6, 2021
1 parent 04aeb9a commit 421951b
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 57 deletions.
6 changes: 4 additions & 2 deletions cmd/tbb/balances.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package main

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/web3coach/the-blockchain-bar/database"
"os"
"github.com/web3coach/the-blockchain-bar/node"
)

func balancesCmd() *cobra.Command {
Expand All @@ -43,7 +45,7 @@ func balancesListCmd() *cobra.Command {
Use: "list",
Short: "Lists all balances.",
Run: func(cmd *cobra.Command, args []string) {
state, err := database.NewStateFromDisk(getDataDirFromCmd(cmd))
state, err := database.NewStateFromDisk(getDataDirFromCmd(cmd), node.DefaultMiningDifficulty)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
Expand Down
2 changes: 1 addition & 1 deletion cmd/tbb/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func runCmd() *cobra.Command {
}

version := fmt.Sprintf("%s.%s.%s-alpha %s %s", Major, Minor, Fix, shortGitCommit(GitCommit), Verbal)
n := node.New(getDataDirFromCmd(cmd), ip, port, database.NewAccount(miner), bootstrap, version)
n := node.New(getDataDirFromCmd(cmd), ip, port, database.NewAccount(miner), bootstrap, version, node.DefaultMiningDifficulty)
err := n.Run(context.Background(), isSSLDisabled, sslEmail)
if err != nil {
fmt.Println(err)
Expand Down
20 changes: 15 additions & 5 deletions database/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"

"github.com/ethereum/go-ethereum/common"
)

Expand Down Expand Up @@ -78,9 +79,18 @@ func (b Block) Hash() (Hash, error) {
return sha256.Sum256(blockJson), nil
}

func IsBlockHashValid(hash Hash) bool {
return fmt.Sprintf("%x", hash[0]) == "0" &&
fmt.Sprintf("%x", hash[1]) == "0" &&
fmt.Sprintf("%x", hash[2]) == "0" &&
fmt.Sprintf("%x", hash[3]) != "0"
func IsBlockHashValid(hash Hash, miningDifficulty uint) bool {
zeroesCount := uint(0)

for i := uint(0); i < miningDifficulty; i++ {
if fmt.Sprintf("%x", hash[i]) == "0" {
zeroesCount++
}
}

if fmt.Sprintf("%x", hash[miningDifficulty]) == "0" {
return false
}

return zeroesCount == miningDifficulty
}
21 changes: 15 additions & 6 deletions database/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import (
"bufio"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/common"
"os"
"reflect"
"sort"

"github.com/ethereum/go-ethereum/common"
)

const TxFee = uint(50)
Expand All @@ -36,9 +37,11 @@ type State struct {
latestBlock Block
latestBlockHash Hash
hasGenesisBlock bool

miningDifficulty uint
}

func NewStateFromDisk(dataDir string) (*State, error) {
func NewStateFromDisk(dataDir string, miningDifficulty uint) (*State, error) {
err := InitDataDirIfNotExists(dataDir, []byte(genesisJson))
if err != nil {
return nil, err
Expand All @@ -64,7 +67,7 @@ func NewStateFromDisk(dataDir string) (*State, error) {

scanner := bufio.NewScanner(f)

state := &State{balances, account2nonce, f, Block{}, Hash{}, false}
state := &State{balances, account2nonce, f, Block{}, Hash{}, false, miningDifficulty}

for scanner.Scan() {
if err := scanner.Err(); err != nil {
Expand Down Expand Up @@ -140,6 +143,7 @@ func (s *State) AddBlock(b Block) (Hash, error) {
s.latestBlockHash = blockHash
s.latestBlock = b
s.hasGenesisBlock = true
s.miningDifficulty = pendingState.miningDifficulty

return blockHash, nil
}
Expand All @@ -164,8 +168,8 @@ func (s *State) GetNextAccountNonce(account common.Address) uint {
return s.Account2Nonce[account] + 1
}

func (s *State) Close() error {
return s.dbFile.Close()
func (c *State) ChangeMiningDifficulty(newDifficulty uint) {
c.miningDifficulty = newDifficulty
}

func (s *State) Copy() State {
Expand All @@ -175,6 +179,7 @@ func (s *State) Copy() State {
c.latestBlockHash = s.latestBlockHash
c.Balances = make(map[common.Address]uint)
c.Account2Nonce = make(map[common.Address]uint)
c.miningDifficulty = s.miningDifficulty

for acc, balance := range s.Balances {
c.Balances[acc] = balance
Expand All @@ -187,6 +192,10 @@ func (s *State) Copy() State {
return c
}

func (s *State) Close() error {
return s.dbFile.Close()
}

// applyBlock verifies if block can be added to the blockchain.
//
// Block metadata are verified as well as transactions within (sufficient balances, etc).
Expand All @@ -206,7 +215,7 @@ func applyBlock(b Block, s *State) error {
return err
}

if !IsBlockHashValid(hash) {
if !IsBlockHashValid(hash, s.miningDifficulty) {
return fmt.Errorf("invalid block hash %x", hash)
}

Expand Down
9 changes: 5 additions & 4 deletions node/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ package node
import (
"context"
"fmt"
"math/rand"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/web3coach/the-blockchain-bar/database"
"github.com/web3coach/the-blockchain-bar/fs"
"math/rand"
"time"
)

type PendingBlock struct {
Expand All @@ -37,7 +38,7 @@ func NewPendingBlock(parent database.Hash, number uint64, miner common.Address,
return PendingBlock{parent, number, uint64(time.Now().Unix()), miner, txs}
}

func Mine(ctx context.Context, pb PendingBlock) (database.Block, error) {
func Mine(ctx context.Context, pb PendingBlock, miningDifficulty uint) (database.Block, error) {
if len(pb.txs) == 0 {
return database.Block{}, fmt.Errorf("mining empty blocks is not allowed")
}
Expand All @@ -48,7 +49,7 @@ func Mine(ctx context.Context, pb PendingBlock) (database.Block, error) {
var hash database.Hash
var nonce uint32

for !database.IsBlockHashValid(hash) {
for !database.IsBlockHashValid(hash, miningDifficulty) {
select {
case <-ctx.Done():
fmt.Println("Mining cancelled!")
Expand Down
23 changes: 13 additions & 10 deletions node/miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,36 @@ import (
"crypto/elliptic"
"crypto/rand"
"encoding/hex"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/web3coach/the-blockchain-bar/database"
"github.com/web3coach/the-blockchain-bar/wallet"
"testing"
"time"
)

const defaultTestMiningDifficulty = 2

func TestValidBlockHash(t *testing.T) {
hexHash := "000000fa04f8160395c387277f8b2f14837603383d33809a4db586086168edfa"
hexHash := "0000fa04f8160395c387277f8b2f14837603383d33809a4db586086168edfa"
var hash = database.Hash{}

hex.Decode(hash[:], []byte(hexHash))

isValid := database.IsBlockHashValid(hash)
isValid := database.IsBlockHashValid(hash, defaultTestMiningDifficulty)
if !isValid {
t.Fatalf("hash '%s' starting with 6 zeroes is suppose to be valid", hexHash)
t.Fatalf("hash '%s' starting with 4 zeroes is suppose to be valid", hexHash)
}
}

func TestInvalidBlockHash(t *testing.T) {
hexHash := "000001fa04f8160395c387277f8b2f14837603383d33809a4db586086168edfa"
hexHash := "0001fa04f8160395c387277f8b2f14837603383d33809a4db586086168edfa"
var hash = database.Hash{}

hex.Decode(hash[:], []byte(hexHash))

isValid := database.IsBlockHashValid(hash)
isValid := database.IsBlockHashValid(hash, defaultTestMiningDifficulty)
if isValid {
t.Fatal("hash is not suppose to be valid")
}
Expand All @@ -66,7 +69,7 @@ func TestMine(t *testing.T) {

ctx := context.Background()

minedBlock, err := Mine(ctx, pendingBlock)
minedBlock, err := Mine(ctx, pendingBlock, defaultTestMiningDifficulty)
if err != nil {
t.Fatal(err)
}
Expand All @@ -76,7 +79,7 @@ func TestMine(t *testing.T) {
t.Fatal(err)
}

if !database.IsBlockHashValid(minedBlockHash) {
if !database.IsBlockHashValid(minedBlockHash, defaultTestMiningDifficulty) {
t.Fatal()
}

Expand All @@ -98,7 +101,7 @@ func TestMineWithTimeout(t *testing.T) {

ctx, _ := context.WithTimeout(context.Background(), time.Microsecond*100)

_, err = Mine(ctx, pendingBlock)
_, err = Mine(ctx, pendingBlock, defaultTestMiningDifficulty)
if err == nil {
t.Fatal(err)
}
Expand Down
36 changes: 23 additions & 13 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const endpointAddPeerQueryKeyMiner = "miner"
const endpointAddPeerQueryKeyVersion = "version"

const miningIntervalSeconds = 10
const DefaultMiningDifficulty = 3

type PeerNode struct {
IP string `json:"ip"`
Expand Down Expand Up @@ -86,23 +87,27 @@ type Node struct {
archivedTXs map[string]database.SignedTx
newSyncedBlocks chan database.Block
newPendingTXs chan database.SignedTx
isMining bool
nodeVersion string

// Number of zeroes the hash must start with to be considered valid. Default 3
miningDifficulty uint
isMining bool
}

func New(dataDir string, ip string, port uint64, acc common.Address, bootstrap PeerNode, version string) *Node {
func New(dataDir string, ip string, port uint64, acc common.Address, bootstrap PeerNode, version string, miningDifficulty uint) *Node {
knownPeers := make(map[string]PeerNode)

n := &Node{
dataDir: dataDir,
info: NewPeerNode(ip, port, false, acc, true, version),
knownPeers: knownPeers,
pendingTXs: make(map[string]database.SignedTx),
archivedTXs: make(map[string]database.SignedTx),
newSyncedBlocks: make(chan database.Block),
newPendingTXs: make(chan database.SignedTx, 10000),
isMining: false,
nodeVersion: version,
dataDir: dataDir,
info: NewPeerNode(ip, port, false, acc, true, version),
knownPeers: knownPeers,
pendingTXs: make(map[string]database.SignedTx),
archivedTXs: make(map[string]database.SignedTx),
newSyncedBlocks: make(chan database.Block),
newPendingTXs: make(chan database.SignedTx, 10000),
nodeVersion: version,
isMining: false,
miningDifficulty: miningDifficulty,
}

n.AddPeer(bootstrap)
Expand All @@ -117,7 +122,7 @@ func NewPeerNode(ip string, port uint64, isBootstrap bool, acc common.Address, c
func (n *Node) Run(ctx context.Context, isSSLDisabled bool, sslEmail string) error {
fmt.Println(fmt.Sprintf("Listening on: %s:%d", n.info.IP, n.info.Port))

state, err := database.NewStateFromDisk(n.dataDir)
state, err := database.NewStateFromDisk(n.dataDir, n.miningDifficulty)
if err != nil {
return err
}
Expand Down Expand Up @@ -234,7 +239,7 @@ func (n *Node) minePendingTXs(ctx context.Context) error {
n.getPendingTXsAsArray(),
)

minedBlock, err := Mine(ctx, blockToMine)
minedBlock, err := Mine(ctx, blockToMine, n.miningDifficulty)
if err != nil {
return err
}
Expand Down Expand Up @@ -265,6 +270,11 @@ func (n *Node) removeMinedPendingTXs(block database.Block) {
}
}

func (n *Node) ChangeMiningDifficulty(newDifficulty uint) {
n.miningDifficulty = newDifficulty
n.state.ChangeMiningDifficulty(newDifficulty)
}

func (n *Node) AddPeer(peer PeerNode) {
n.knownPeers[peer.TcpAddress()] = peer
}
Expand Down
Loading

0 comments on commit 421951b

Please sign in to comment.