aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorMatthew Wampler-Doty <matthew.wampler.doty@gmail.com>2015-03-01 03:58:37 +0800
committerMatthew Wampler-Doty <matthew.wampler.doty@gmail.com>2015-03-03 11:29:34 +0800
commitde9f79133faa1ff5dcd16fb4fd13d06b7799ded9 (patch)
treefcc9001d6b681ccdd1b3bbe516e3611e808341d7 /core
parent080823bdeebbab2bcffdaefad703896700ed2c30 (diff)
downloaddexon-de9f79133faa1ff5dcd16fb4fd13d06b7799ded9.tar.gz
dexon-de9f79133faa1ff5dcd16fb4fd13d06b7799ded9.tar.zst
dexon-de9f79133faa1ff5dcd16fb4fd13d06b7799ded9.zip
Introducing ethash
Diffstat (limited to 'core')
-rw-r--r--core/block_processor.go5
-rw-r--r--core/chain_makers.go47
-rw-r--r--core/chain_manager_test.go46
-rw-r--r--core/transaction_pool.go2
-rw-r--r--core/types/block.go15
5 files changed, 78 insertions, 37 deletions
diff --git a/core/block_processor.go b/core/block_processor.go
index aef53c940..3123511f9 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -7,12 +7,12 @@ import (
"sync"
"time"
+ "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/pow/ezp"
"github.com/ethereum/go-ethereum/state"
"gopkg.in/fatih/set.v0"
)
@@ -50,7 +50,7 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
sm := &BlockProcessor{
db: db,
mem: make(map[string]*big.Int),
- Pow: ezp.New(),
+ Pow: ethash.New(chainManager),
bc: chainManager,
eventMux: eventMux,
txpool: txpool,
@@ -255,6 +255,7 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
return fmt.Errorf("GasLimit check failed for block %v, %v", block.Header().GasLimit, expl)
}
+ // There can be at most one uncle
if len(block.Uncles()) > 1 {
return ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles()))
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index eb43f8aa0..2c36b892e 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -13,21 +13,31 @@ import (
// So we can generate blocks easily
type FakePow struct{}
-func (f FakePow) Search(block pow.Block, stop <-chan struct{}) []byte { return nil }
-func (f FakePow) Verify(block pow.Block) bool { return true }
-func (f FakePow) GetHashrate() int64 { return 0 }
-func (f FakePow) Turbo(bool) {}
+func (f FakePow) Search(block pow.Block, stop <-chan struct{}) ([]byte, []byte, []byte) {
+ return nil, nil, nil
+}
+func (f FakePow) Verify(block pow.Block) bool { return true }
+func (f FakePow) GetHashrate() int64 { return 0 }
+func (f FakePow) Turbo(bool) {}
+
+// So we can deterministically seed different blockchains
+var (
+ CanonicalSeed = 1
+ ForkSeed = 2
+)
+// Utility functions for making chains on the fly
+// Exposed for sake of testing from other packages (eg. go-ethash)
func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block {
return newBlockFromParent(addr, parent)
}
-func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block {
- return makeBlock(bman, parent, i, db)
+func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database, seed int) *types.Block {
+ return makeBlock(bman, parent, i, db, seed)
}
-func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks {
- return makeChain(bman, parent, max, db)
+func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database, seed int) types.Blocks {
+ return makeChain(bman, parent, max, db, seed)
}
func NewChainMan(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager {
@@ -42,9 +52,9 @@ func NewCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
return newCanonical(n, db)
}
+// block time is fixed at 10 seconds
func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
block := types.NewBlock(parent.Hash(), addr, parent.Root(), ethutil.BigPow(2, 32), nil, "")
-
block.SetUncles(nil)
block.SetTransactions(nil)
block.SetReceipts(nil)
@@ -52,6 +62,7 @@ func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
header := block.Header()
header.Difficulty = CalcDifficulty(block, parent)
header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1)
+ header.Time = parent.Header().Time + 10
header.GasLimit = CalcGasLimit(parent, block)
block.Td = parent.Td
@@ -60,8 +71,10 @@ func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
}
// Actually make a block by simulating what miner would do
-func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block {
+// we seed chains by the first byte of the coinbase
+func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database, seed int) *types.Block {
addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
+ addr[0] = byte(seed)
block := newBlockFromParent(addr, parent)
state := state.New(block.Root(), db)
cbase := state.GetOrNewStateObject(addr)
@@ -74,11 +87,11 @@ func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Data
// Make a chain with real blocks
// Runs ProcessWithParent to get proper state roots
-func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks {
+func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database, seed int) types.Blocks {
bman.bc.currentBlock = parent
blocks := make(types.Blocks, max)
for i := 0; i < max; i++ {
- block := makeBlock(bman, parent, i, db)
+ block := makeBlock(bman, parent, i, db, seed)
td, err := bman.processWithParent(block, parent)
if err != nil {
fmt.Println("process with parent failed", err)
@@ -87,9 +100,7 @@ func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Da
block.Td = td
blocks[i] = block
parent = block
- fmt.Printf("New Block: %x\n", block.Hash())
}
- fmt.Println("Done making chain")
return blocks
}
@@ -113,7 +124,7 @@ func newBlockProcessor(db ethutil.Database, txpool *TxPool, cman *ChainManager,
return bman
}
-// Make a new canonical chain by running InsertChain
+// Make a new, deterministic canonical chain by running InsertChain
// on result of makeChain
func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
eventMux := &event.TypeMux{}
@@ -125,7 +136,7 @@ func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
if n == 0 {
return bman, nil
}
- lchain := makeChain(bman, parent, n, db)
- bman.bc.InsertChain(lchain)
- return bman, nil
+ lchain := makeChain(bman, parent, n, db, CanonicalSeed)
+ err := bman.bc.InsertChain(lchain)
+ return bman, err
}
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index e6614212f..b562b677d 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -24,12 +24,6 @@ func init() {
// Test fork of length N starting from block i
func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) {
- fmt.Println("Testing Fork!")
- var b *types.Block = nil
- if i > 0 {
- b = bman.bc.GetBlockByNumber(uint64(i))
- }
- _ = b
// switch databases to process the new chain
db, err := ethdb.NewMemDatabase()
if err != nil {
@@ -40,13 +34,25 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
+ // asert the bmans have the same block at i
+ bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash()
+ bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash()
+ if bytes.Compare(bi1, bi2) != 0 {
+ t.Fatal("chains do not have the same hash at height", i)
+ }
+
bman2.bc.SetProcessor(bman2)
+ // extend the fork
parent := bman2.bc.CurrentBlock()
- chainB := makeChain(bman2, parent, N, db)
- bman2.bc.InsertChain(chainB)
+ chainB := makeChain(bman2, parent, N, db, ForkSeed)
+ err = bman2.bc.InsertChain(chainB)
+ if err != nil {
+ t.Fatal("Insert chain error for fork:", err)
+ }
tdpre := bman.bc.Td()
+ // Test the fork's blocks on the original chain
td, err := testChain(chainB, bman)
if err != nil {
t.Fatal("expected chainB not to give errors:", err)
@@ -55,6 +61,14 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big
f(tdpre, td)
}
+func printChain(bc *ChainManager) {
+ for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- {
+ b := bc.GetBlockByNumber(uint64(i))
+ fmt.Printf("\t%x\n", b.Hash())
+ }
+}
+
+// process blocks against a chain
func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
td := new(big.Int)
for _, block := range chainB {
@@ -102,12 +116,13 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *
}
func TestExtendCanonical(t *testing.T) {
+ CanonicalLength := 5
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
// make first chain starting from genesis
- bman, err := newCanonical(5, db)
+ bman, err := newCanonical(CanonicalLength, db)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
@@ -116,11 +131,11 @@ func TestExtendCanonical(t *testing.T) {
t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
}
}
- // Start fork from current height (5)
- testFork(t, bman, 5, 1, f)
- testFork(t, bman, 5, 2, f)
- testFork(t, bman, 5, 5, f)
- testFork(t, bman, 5, 10, f)
+ // Start fork from current height (CanonicalLength)
+ testFork(t, bman, CanonicalLength, 1, f)
+ testFork(t, bman, CanonicalLength, 2, f)
+ testFork(t, bman, CanonicalLength, 5, f)
+ testFork(t, bman, CanonicalLength, 10, f)
}
func TestShorterFork(t *testing.T) {
@@ -189,6 +204,7 @@ func TestEqualFork(t *testing.T) {
}
// Sum of numbers must be equal to 10
// for this to be an equal fork
+ testFork(t, bman, 0, 10, f)
testFork(t, bman, 1, 9, f)
testFork(t, bman, 2, 8, f)
testFork(t, bman, 5, 5, f)
@@ -215,7 +231,7 @@ func TestBrokenChain(t *testing.T) {
}
bman2.bc.SetProcessor(bman2)
parent := bman2.bc.CurrentBlock()
- chainB := makeChain(bman2, parent, 5, db2)
+ chainB := makeChain(bman2, parent, 5, db2, ForkSeed)
chainB = chainB[1:]
_, err = testChain(chainB, bman)
if err == nil {
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 860f57dc3..bd377f679 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -121,7 +121,7 @@ func (self *TxPool) add(tx *types.Transaction) error {
if len(tx.From()) > 0 {
from = ethutil.Bytes2Hex(tx.From()[:4])
} else {
- from = "INVALID"
+ return errors.New(fmt.Sprintf("FROM ADDRESS MUST BE POSITIVE (was %v)", tx.From()))
}
txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash())
diff --git a/core/types/block.go b/core/types/block.go
index f637b5c3b..a37038f73 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -48,7 +48,20 @@ type Header struct {
}
func (self *Header) rlpData(withNonce bool) []interface{} {
- fields := []interface{}{self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra}
+ fields := []interface{}{
+ self.ParentHash,
+ self.UncleHash,
+ self.Coinbase,
+ self.Root,
+ self.TxHash,
+ self.ReceiptHash,
+ self.Bloom,
+ self.Difficulty,
+ self.Number,
+ self.GasLimit,
+ self.GasUsed,
+ self.Time,
+ self.Extra}
if withNonce {
fields = append(fields, self.Nonce, self.MixDigest, self.SeedHash)
}