all: swap out the C++ ethash to the pure Go one (mining todo)

This commit is contained in:
Péter Szilágyi 2017-03-05 20:00:01 +02:00 committed by Felix Lange
parent 3b00a77de5
commit 567d41d936
31 changed files with 1348 additions and 1156 deletions

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -62,7 +63,7 @@ type SimulatedBackend struct {
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend { func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
database, _ := ethdb.NewMemDatabase() database, _ := ethdb.NewMemDatabase()
core.WriteGenesisBlockForTesting(database, accounts...) core.WriteGenesisBlockForTesting(database, accounts...)
blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux), vm.Config{}) blockchain, _ := core.NewBlockChain(database, chainConfig, new(pow.FakePow), new(event.TypeMux), vm.Config{})
backend := &SimulatedBackend{database: database, blockchain: blockchain} backend := &SimulatedBackend{database: database, blockchain: blockchain}
backend.rollback() backend.rollback()
return backend return backend

@ -28,7 +28,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -922,11 +921,11 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
} }
chainConfig := MakeChainConfigFromDb(ctx, chainDb) chainConfig := MakeChainConfigFromDb(ctx, chainDb)
pow := pow.PoW(core.FakePow{}) seal := pow.PoW(pow.FakePow{})
if !ctx.GlobalBool(FakePoWFlag.Name) { if !ctx.GlobalBool(FakePoWFlag.Name) {
pow = ethash.New() seal = pow.NewFullEthash("", "")
} }
chain, err = core.NewBlockChain(chainDb, chainConfig, pow, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}) chain, err = core.NewBlockChain(chainDb, chainConfig, seal, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)})
if err != nil { if err != nil {
Fatalf("Could not start chainmanager: %v", err) Fatalf("Could not start chainmanager: %v", err)
} }

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
func BenchmarkInsertChain_empty_memdb(b *testing.B) { func BenchmarkInsertChain_empty_memdb(b *testing.B) {
@ -171,7 +172,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Time the insertion of the new chain. // Time the insertion of the new chain.
// State and blocks are stored in the same DB. // State and blocks are stored in the same DB.
evmux := new(event.TypeMux) evmux := new(event.TypeMux)
chainman, _ := NewBlockChain(db, &params.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux, vm.Config{}) chainman, _ := NewBlockChain(db, &params.ChainConfig{HomesteadBlock: new(big.Int)}, pow.FakePow{}, evmux, vm.Config{})
defer chainman.Stop() defer chainman.Stop()
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
@ -281,7 +282,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil { if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err) b.Fatalf("error opening database at %v: %v", dir, err)
} }
chain, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) chain, err := NewBlockChain(db, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
if err != nil { if err != nil {
b.Fatalf("error creating chain: %v", err) b.Fatalf("error creating chain: %v", err)
} }

@ -244,7 +244,7 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade
if checkPow { if checkPow {
// Verify the nonce of the header. Return an error if it's not valid // Verify the nonce of the header. Return an error if it's not valid
if !pow.Verify(types.NewBlockWithHeader(header)) { if err := pow.Verify(types.NewBlockWithHeader(header)); err != nil {
return &BlockNonceErr{header.Number, header.Hash(), header.Nonce.Uint64()} return &BlockNonceErr{header.Number, header.Hash(), header.Nonce.Uint64()}
} }
} }

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
func testChainConfig() *params.ChainConfig { func testChainConfig() *params.ChainConfig {
@ -40,7 +41,7 @@ func proc() (Validator, *BlockChain) {
var mux event.TypeMux var mux event.TypeMux
WriteTestNetGenesisBlock(db) WriteTestNetGenesisBlock(db)
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux, vm.Config{}) blockchain, err := NewBlockChain(db, testChainConfig(), pow.NewTestEthash(), &mux, vm.Config{})
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
@ -54,13 +55,13 @@ func TestNumber(t *testing.T) {
cfg := testChainConfig() cfg := testChainConfig()
header := makeHeader(cfg, chain.Genesis(), statedb) header := makeHeader(cfg, chain.Genesis(), statedb)
header.Number = big.NewInt(3) header.Number = big.NewInt(3)
err := ValidateHeader(cfg, FakePow{}, header, chain.Genesis().Header(), false, false) err := ValidateHeader(cfg, pow.FakePow{}, header, chain.Genesis().Header(), false, false)
if err != BlockNumberErr { if err != BlockNumberErr {
t.Errorf("expected block number error, got %q", err) t.Errorf("expected block number error, got %q", err)
} }
header = makeHeader(cfg, chain.Genesis(), statedb) header = makeHeader(cfg, chain.Genesis(), statedb)
err = ValidateHeader(cfg, FakePow{}, header, chain.Genesis().Header(), false, false) err = ValidateHeader(cfg, pow.FakePow{}, header, chain.Genesis().Header(), false, false)
if err == BlockNumberErr { if err == BlockNumberErr {
t.Errorf("didn't expect block number error") t.Errorf("didn't expect block number error")
} }

@ -223,6 +223,9 @@ func (self *BlockChain) loadLastState() error {
log.Info("Loaded most recent local full block", "number", self.currentBlock.Number(), "hash", self.currentBlock.Hash(), "td", blockTd) log.Info("Loaded most recent local full block", "number", self.currentBlock.Number(), "hash", self.currentBlock.Hash(), "td", blockTd)
log.Info("Loaded most recent local fast block", "number", self.currentFastBlock.Number(), "hash", self.currentFastBlock.Hash(), "td", fastTd) log.Info("Loaded most recent local fast block", "number", self.currentFastBlock.Number(), "hash", self.currentFastBlock.Hash(), "td", fastTd)
// Try to be smart and issue a pow verification for the head to pre-generate caches
go self.pow.Verify(types.NewBlockWithHeader(currentHeader))
return nil return nil
} }

@ -27,7 +27,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -45,15 +44,10 @@ func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
} }
func thePow() pow.PoW {
pow, _ := ethash.NewForTesting()
return pow
}
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain { func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
var eventMux event.TypeMux var eventMux event.TypeMux
WriteTestNetGenesisBlock(db) WriteTestNetGenesisBlock(db)
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux, vm.Config{}) blockchain, err := NewBlockChain(db, testChainConfig(), pow.NewTestEthash(), &eventMux, vm.Config{})
if err != nil { if err != nil {
t.Error("failed creating blockchain:", err) t.Error("failed creating blockchain:", err)
t.FailNow() t.FailNow()
@ -476,7 +470,7 @@ func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
chainDb: db, chainDb: db,
genesisBlock: genesis, genesisBlock: genesis,
eventMux: &eventMux, eventMux: &eventMux,
pow: FakePow{}, pow: pow.FakePow{},
config: testChainConfig(), config: testChainConfig(),
} }
valFn := func() HeaderValidator { return bc.Validator() } valFn := func() HeaderValidator { return bc.Validator() }
@ -615,7 +609,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
defer func() { delete(BadHashes, headers[3].Hash()) }() defer func() { delete(BadHashes, headers[3].Hash()) }()
} }
// Create a new chain manager and check it rolled back the state // Create a new chain manager and check it rolled back the state
ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) ncm, err := NewBlockChain(db, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
if err != nil { if err != nil {
t.Fatalf("failed to create new chain manager: %v", err) t.Fatalf("failed to create new chain manager: %v", err)
} }
@ -736,7 +730,7 @@ func TestFastVsFullChains(t *testing.T) {
archiveDb, _ := ethdb.NewMemDatabase() archiveDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds}) WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) archive, _ := NewBlockChain(archiveDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
if n, err := archive.InsertChain(blocks); err != nil { if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err) t.Fatalf("failed to process block %d: %v", n, err)
@ -744,7 +738,7 @@ func TestFastVsFullChains(t *testing.T) {
// Fast import the chain as a non-archive node to test // Fast import the chain as a non-archive node to test
fastDb, _ := ethdb.NewMemDatabase() fastDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds}) WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) fast, _ := NewBlockChain(fastDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
for i, block := range blocks { for i, block := range blocks {
@ -820,7 +814,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveDb, _ := ethdb.NewMemDatabase() archiveDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds}) WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) archive, _ := NewBlockChain(archiveDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
if n, err := archive.InsertChain(blocks); err != nil { if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err) t.Fatalf("failed to process block %d: %v", n, err)
@ -832,7 +826,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated // Import the chain as a non-archive node and ensure all pointers are updated
fastDb, _ := ethdb.NewMemDatabase() fastDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds}) WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) fast, _ := NewBlockChain(fastDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
for i, block := range blocks { for i, block := range blocks {
@ -851,7 +845,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a light node and ensure all pointers are updated // Import the chain as a light node and ensure all pointers are updated
lightDb, _ := ethdb.NewMemDatabase() lightDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds}) WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{}) light, _ := NewBlockChain(lightDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
if n, err := light.InsertHeaderChain(headers, 1); err != nil { if n, err := light.InsertHeaderChain(headers, 1); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
@ -917,7 +911,7 @@ func TestChainTxReorgs(t *testing.T) {
}) })
// Import the chain. This runs all block validation rules. // Import the chain. This runs all block validation rules.
evmux := &event.TypeMux{} evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{}) blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
if i, err := blockchain.InsertChain(chain); err != nil { if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err) t.Fatalf("failed to insert original chain[%d]: %v", i, err)
} }
@ -991,7 +985,7 @@ func TestLogReorgs(t *testing.T) {
) )
evmux := &event.TypeMux{} evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{}) blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
subs := evmux.Subscribe(RemovedLogsEvent{}) subs := evmux.Subscribe(RemovedLogsEvent{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) { chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
@ -1028,7 +1022,7 @@ func TestReorgSideEvent(t *testing.T) {
) )
evmux := &event.TypeMux{} evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{}) blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {}) chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil { if _, err := blockchain.InsertChain(chain); err != nil {
@ -1104,7 +1098,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
) )
evmux := &event.TypeMux{} evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{}) blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {}) chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
@ -1147,7 +1141,7 @@ func TestEIP155Transition(t *testing.T) {
mux event.TypeMux mux event.TypeMux
) )
blockchain, _ := NewBlockChain(db, config, FakePow{}, &mux, vm.Config{}) blockchain, _ := NewBlockChain(db, config, pow.FakePow{}, &mux, vm.Config{})
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) { blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
var ( var (
tx *types.Transaction tx *types.Transaction
@ -1251,7 +1245,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
} }
mux event.TypeMux mux event.TypeMux
blockchain, _ = NewBlockChain(db, config, FakePow{}, &mux, vm.Config{}) blockchain, _ = NewBlockChain(db, config, pow.FakePow{}, &mux, vm.Config{})
) )
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) { blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
var ( var (

@ -43,17 +43,6 @@ func MakeChainConfig() *params.ChainConfig {
} }
} }
// FakePow is a non-validating proof of work implementation.
// It returns true from Verify for any block.
type FakePow struct{}
func (f FakePow) Search(block pow.Block, stop <-chan struct{}, index int) (uint64, []byte) {
return 0, 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 // So we can deterministically seed different blockchains
var ( var (
canonicalSeed = 1 canonicalSeed = 1
@ -256,7 +245,7 @@ func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
// Initialize a fresh chain with only a genesis block // Initialize a fresh chain with only a genesis block
genesis, _ := WriteTestNetGenesisBlock(db) genesis, _ := WriteTestNetGenesisBlock(db)
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux, vm.Config{}) blockchain, _ := NewBlockChain(db, MakeChainConfig(), pow.FakePow{}, evmux, vm.Config{})
// Create and inject the requested chain // Create and inject the requested chain
if n == 0 { if n == 0 {
return db, blockchain, nil return db, blockchain, nil

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
func ExampleGenerateChain() { func ExampleGenerateChain() {
@ -82,7 +83,7 @@ func ExampleGenerateChain() {
// Import the chain. This runs all block validation rules. // Import the chain. This runs all block validation rules.
evmux := &event.TypeMux{} evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, chainConfig, FakePow{}, evmux, vm.Config{}) blockchain, _ := NewBlockChain(db, chainConfig, pow.FakePow{}, evmux, vm.Config{})
if i, err := blockchain.InsertChain(chain); err != nil { if i, err := blockchain.InsertChain(chain); err != nil {
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err) fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
return return

@ -65,7 +65,7 @@ func verifyNonces(checker pow.PoW, items []pow.Block) (chan<- struct{}, <-chan n
for i := 0; i < workers; i++ { for i := 0; i < workers; i++ {
go func() { go func() {
for index := range tasks { for index := range tasks {
results <- nonceCheckResult{index: index, valid: checker.Verify(items[index])} results <- nonceCheckResult{index: index, valid: checker.Verify(items[index]) == nil}
} }
}() }()
} }

@ -17,6 +17,7 @@
package core package core
import ( import (
"errors"
"math/big" "math/big"
"runtime" "runtime"
"testing" "testing"
@ -35,12 +36,16 @@ type failPow struct {
failing uint64 failing uint64
} }
func (pow failPow) Search(pow.Block, <-chan struct{}, int) (uint64, []byte) { func (pow failPow) Search(pow.Block, <-chan struct{}) (uint64, []byte) {
return 0, nil return 0, nil
} }
func (pow failPow) Verify(block pow.Block) bool { return block.NumberU64() != pow.failing } func (pow failPow) Verify(block pow.Block) error {
func (pow failPow) GetHashrate() int64 { return 0 } if block.NumberU64() == pow.failing {
func (pow failPow) Turbo(bool) {} return errors.New("failed")
}
return nil
}
func (pow failPow) Hashrate() float64 { return 0 }
// delayedPow is a non-validating proof of work implementation, that returns true // delayedPow is a non-validating proof of work implementation, that returns true
// from Verify for all blocks, but delays them the configured amount of time. // from Verify for all blocks, but delays them the configured amount of time.
@ -48,12 +53,11 @@ type delayedPow struct {
delay time.Duration delay time.Duration
} }
func (pow delayedPow) Search(pow.Block, <-chan struct{}, int) (uint64, []byte) { func (pow delayedPow) Search(pow.Block, <-chan struct{}) (uint64, []byte) {
return 0, nil return 0, nil
} }
func (pow delayedPow) Verify(block pow.Block) bool { time.Sleep(pow.delay); return true } func (pow delayedPow) Verify(block pow.Block) error { time.Sleep(pow.delay); return nil }
func (pow delayedPow) GetHashrate() int64 { return 0 } func (pow delayedPow) Hashrate() float64 { return 0 }
func (pow delayedPow) Turbo(bool) {}
// Tests that simple POW verification works, for both good and bad blocks. // Tests that simple POW verification works, for both good and bad blocks.
func TestPowVerification(t *testing.T) { func TestPowVerification(t *testing.T) {
@ -75,11 +79,11 @@ func TestPowVerification(t *testing.T) {
switch { switch {
case full && valid: case full && valid:
_, results = verifyNoncesFromBlocks(FakePow{}, []*types.Block{blocks[i]}) _, results = verifyNoncesFromBlocks(pow.FakePow{}, []*types.Block{blocks[i]})
case full && !valid: case full && !valid:
_, results = verifyNoncesFromBlocks(failPow{blocks[i].NumberU64()}, []*types.Block{blocks[i]}) _, results = verifyNoncesFromBlocks(failPow{blocks[i].NumberU64()}, []*types.Block{blocks[i]})
case !full && valid: case !full && valid:
_, results = verifyNoncesFromHeaders(FakePow{}, []*types.Header{headers[i]}) _, results = verifyNoncesFromHeaders(pow.FakePow{}, []*types.Header{headers[i]})
case !full && !valid: case !full && !valid:
_, results = verifyNoncesFromHeaders(failPow{headers[i].Number.Uint64()}, []*types.Header{headers[i]}) _, results = verifyNoncesFromHeaders(failPow{headers[i].Number.Uint64()}, []*types.Header{headers[i]})
} }
@ -134,11 +138,11 @@ func testPowConcurrentVerification(t *testing.T, threads int) {
switch { switch {
case full && valid: case full && valid:
_, results = verifyNoncesFromBlocks(FakePow{}, blocks) _, results = verifyNoncesFromBlocks(pow.FakePow{}, blocks)
case full && !valid: case full && !valid:
_, results = verifyNoncesFromBlocks(failPow{uint64(len(blocks) - 1)}, blocks) _, results = verifyNoncesFromBlocks(failPow{uint64(len(blocks) - 1)}, blocks)
case !full && valid: case !full && valid:
_, results = verifyNoncesFromHeaders(FakePow{}, headers) _, results = verifyNoncesFromHeaders(pow.FakePow{}, headers)
case !full && !valid: case !full && !valid:
_, results = verifyNoncesFromHeaders(failPow{uint64(len(headers) - 1)}, headers) _, results = verifyNoncesFromHeaders(failPow{uint64(len(headers) - 1)}, headers)
} }

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
// Tests that DAO-fork enabled clients can properly filter out fork-commencing // Tests that DAO-fork enabled clients can properly filter out fork-commencing
@ -40,12 +41,12 @@ func TestDAOForkRangeExtradata(t *testing.T) {
proDb, _ := ethdb.NewMemDatabase() proDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(proDb) WriteGenesisBlockForTesting(proDb)
proConf := &params.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true} proConf := &params.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux), vm.Config{}) proBc, _ := NewBlockChain(proDb, proConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
conDb, _ := ethdb.NewMemDatabase() conDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(conDb) WriteGenesisBlockForTesting(conDb)
conConf := &params.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false} conConf := &params.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux), vm.Config{}) conBc, _ := NewBlockChain(conDb, conConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
if _, err := proBc.InsertChain(prefix); err != nil { if _, err := proBc.InsertChain(prefix); err != nil {
t.Fatalf("pro-fork: failed to import chain prefix: %v", err) t.Fatalf("pro-fork: failed to import chain prefix: %v", err)
@ -58,7 +59,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a pro-fork block, and try to feed into the no-fork chain // Create a pro-fork block, and try to feed into the no-fork chain
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(db) WriteGenesisBlockForTesting(db)
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux), vm.Config{}) bc, _ := NewBlockChain(db, conConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1)) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
@ -79,7 +80,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a no-fork block, and try to feed into the pro-fork chain // Create a no-fork block, and try to feed into the pro-fork chain
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(db) WriteGenesisBlockForTesting(db)
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux), vm.Config{}) bc, _ = NewBlockChain(db, proConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1)) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
@ -101,7 +102,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes // Verify that contra-forkers accept pro-fork extra-datas after forking finishes
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(db) WriteGenesisBlockForTesting(db)
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux), vm.Config{}) bc, _ := NewBlockChain(db, conConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1)) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
@ -117,7 +118,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes // Verify that pro-forkers accept contra-fork extra-datas after forking finishes
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(db) WriteGenesisBlockForTesting(db)
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux), vm.Config{}) bc, _ = NewBlockChain(db, proConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1)) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {

@ -288,15 +288,15 @@ func CreatePoW(config *Config) (pow.PoW, error) {
switch { switch {
case config.PowFake: case config.PowFake:
log.Warn("Ethash used in fake mode") log.Warn("Ethash used in fake mode")
return pow.PoW(core.FakePow{}), nil return pow.FakePow{}, nil
case config.PowTest: case config.PowTest:
log.Warn("Ethash used in test mode") log.Warn("Ethash used in test mode")
return ethash.NewForTesting() return pow.NewTestEthash(), nil
case config.PowShared: case config.PowShared:
log.Warn("Ethash used in shared mode") log.Warn("Ethash used in shared mode")
return ethash.NewShared(), nil return pow.NewSharedEthash(), nil
default: default:
return ethash.New(), nil return pow.NewFullEthash("", ""), nil
} }
} }

@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
var bigTxGas = new(big.Int).SetUint64(params.TxGas) var bigTxGas = new(big.Int).SetUint64(params.TxGas)
@ -468,7 +469,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
// Create a DAO aware protocol manager // Create a DAO aware protocol manager
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = new(core.FakePow) pow = new(pow.FakePow)
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(db) genesis = core.WriteGenesisBlockForTesting(db)
config = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked} config = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}

@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
var ( var (
@ -53,7 +54,7 @@ var (
func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, error) { func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, error) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = new(core.FakePow) pow = new(pow.FakePow)
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(db, testBank) genesis = core.WriteGenesisBlockForTesting(db, testBank)
chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker

@ -25,7 +25,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -39,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
@ -1378,11 +1378,7 @@ func (api *PublicDebugAPI) SeedHash(ctx context.Context, number uint64) (string,
if block == nil { if block == nil {
return "", fmt.Errorf("block #%d not found", number) return "", fmt.Errorf("block #%d not found", number)
} }
hash, err := ethash.GetSeedHash(number) return fmt.Sprintf("0x%x", pow.EthashSeedHash(number)), nil
if err != nil {
return "", err
}
return fmt.Sprintf("0x%x", hash), nil
} }
// PrivateDebugAPI is the collection of Etheruem APIs exposed over the private // PrivateDebugAPI is the collection of Etheruem APIs exposed over the private

@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
) )
var ( var (
@ -134,7 +135,7 @@ func testRCL() RequestCostList {
func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *core.BlockGen)) (*ProtocolManager, ethdb.Database, *LesOdr, error) { func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *core.BlockGen)) (*ProtocolManager, ethdb.Database, *LesOdr, error) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = new(core.FakePow) pow = new(pow.FakePow)
db, _ = ethdb.NewMemDatabase() db, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds}) genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker

@ -169,6 +169,9 @@ func (self *LightChain) loadLastState() error {
headerTd := self.GetTd(header.Hash(), header.Number.Uint64()) headerTd := self.GetTd(header.Hash(), header.Number.Uint64())
log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd) log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd)
// Try to be smart and issue a pow verification for the head to pre-generate caches
go self.pow.Verify(types.NewBlockWithHeader(header))
return nil return nil
} }

@ -22,7 +22,6 @@ import (
"runtime" "runtime"
"testing" "testing"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -67,7 +66,7 @@ func newCanonical(n int) (ethdb.Database, *LightChain, error) {
// Initialize a fresh chain with only a genesis block // Initialize a fresh chain with only a genesis block
genesis, _ := core.WriteTestNetGenesisBlock(db) genesis, _ := core.WriteTestNetGenesisBlock(db)
blockchain, _ := NewLightChain(&dummyOdr{db: db}, testChainConfig(), core.FakePow{}, evmux) blockchain, _ := NewLightChain(&dummyOdr{db: db}, testChainConfig(), pow.FakePow{}, evmux)
// Create and inject the requested chain // Create and inject the requested chain
if n == 0 { if n == 0 {
return db, blockchain, nil return db, blockchain, nil
@ -82,15 +81,10 @@ func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
} }
func thePow() pow.PoW {
pow, _ := ethash.NewForTesting()
return pow
}
func theLightChain(db ethdb.Database, t *testing.T) *LightChain { func theLightChain(db ethdb.Database, t *testing.T) *LightChain {
var eventMux event.TypeMux var eventMux event.TypeMux
core.WriteTestNetGenesisBlock(db) core.WriteTestNetGenesisBlock(db)
LightChain, err := NewLightChain(&dummyOdr{db: db}, testChainConfig(), thePow(), &eventMux) LightChain, err := NewLightChain(&dummyOdr{db: db}, testChainConfig(), pow.NewTestEthash(), &eventMux)
if err != nil { if err != nil {
t.Error("failed creating LightChain:", err) t.Error("failed creating LightChain:", err)
t.FailNow() t.FailNow()
@ -311,7 +305,7 @@ func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error {
func chm(genesis *types.Block, db ethdb.Database) *LightChain { func chm(genesis *types.Block, db ethdb.Database) *LightChain {
odr := &dummyOdr{db: db} odr := &dummyOdr{db: db}
var eventMux event.TypeMux var eventMux event.TypeMux
bc := &LightChain{odr: odr, chainDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: core.FakePow{}} bc := &LightChain{odr: odr, chainDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: pow.FakePow{}}
bc.hc, _ = core.NewHeaderChain(db, testChainConfig(), bc.Validator, bc.getProcInterrupt) bc.hc, _ = core.NewHeaderChain(db, testChainConfig(), bc.Validator, bc.getProcInterrupt)
bc.bodyCache, _ = lru.New(100) bc.bodyCache, _ = lru.New(100)
bc.bodyRLPCache, _ = lru.New(100) bc.bodyRLPCache, _ = lru.New(100)
@ -394,7 +388,7 @@ func TestReorgBadHeaderHashes(t *testing.T) {
core.BadHashes[headers[3].Hash()] = true core.BadHashes[headers[3].Hash()] = true
defer func() { delete(core.BadHashes, headers[3].Hash()) }() defer func() { delete(core.BadHashes, headers[3].Hash()) }()
// Create a new chain manager and check it rolled back the state // Create a new chain manager and check it rolled back the state
ncm, err := NewLightChain(&dummyOdr{db: db}, testChainConfig(), core.FakePow{}, new(event.TypeMux)) ncm, err := NewLightChain(&dummyOdr{db: db}, testChainConfig(), pow.FakePow{}, new(event.TypeMux))
if err != nil { if err != nil {
t.Fatalf("failed to create new chain manager: %v", err) t.Fatalf("failed to create new chain manager: %v", err)
} }

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -247,7 +248,7 @@ func testChainGen(i int, block *core.BlockGen) {
func testChainOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) { func testChainOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = new(core.FakePow) pow = new(pow.FakePow)
sdb, _ = ethdb.NewMemDatabase() sdb, _ = ethdb.NewMemDatabase()
ldb, _ = ethdb.NewMemDatabase() ldb, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(sdb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds}) genesis = core.WriteGenesisBlockForTesting(sdb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -82,7 +83,7 @@ func TestTxPool(t *testing.T) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = new(core.FakePow) pow = new(pow.FakePow)
sdb, _ = ethdb.NewMemDatabase() sdb, _ = ethdb.NewMemDatabase()
ldb, _ = ethdb.NewMemDatabase() ldb, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(sdb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds}) genesis = core.WriteGenesisBlockForTesting(sdb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})

@ -23,7 +23,6 @@ const (
// locationTrims are trimmed for display to avoid unwieldy log lines. // locationTrims are trimmed for display to avoid unwieldy log lines.
var locationTrims = []string{ var locationTrims = []string{
"github.com/ethereum/go-ethereum/", "github.com/ethereum/go-ethereum/",
"github.com/ethereum/ethash/",
} }
// PrintOrigins sets or unsets log location (file:line) printing for terminal // PrintOrigins sets or unsets log location (file:line) printing for terminal

@ -111,7 +111,7 @@ func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
log.Debug(fmt.Sprintf("(re)started agent[%d]. mining...\n", self.index)) log.Debug(fmt.Sprintf("(re)started agent[%d]. mining...\n", self.index))
// Mine // Mine
nonce, mixDigest := self.pow.Search(work.Block, stop, self.index) nonce, mixDigest := self.pow.Search(work.Block, stop)
if nonce != 0 { if nonce != 0 {
block := work.Block.WithMiningResult(types.EncodeNonce(nonce), common.BytesToHash(mixDigest)) block := work.Block.WithMiningResult(types.EncodeNonce(nonce), common.BytesToHash(mixDigest))
self.returnCh <- &Result{work, block} self.returnCh <- &Result{work, block}
@ -121,5 +121,5 @@ func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
} }
func (self *CpuAgent) GetHashRate() int64 { func (self *CpuAgent) GetHashRate() int64 {
return self.pow.GetHashrate() return int64(self.pow.Hashrate())
} }

@ -159,7 +159,7 @@ func (self *Miner) Mining() bool {
} }
func (self *Miner) HashRate() (tot int64) { func (self *Miner) HashRate() (tot int64) {
tot += self.pow.GetHashrate() tot += int64(self.pow.Hashrate())
// do we care this might race? is it worth we're rewriting some // do we care this might race? is it worth we're rewriting some
// aspects of the worker/locking up agents so we can get an accurate // aspects of the worker/locking up agents so we can get an accurate
// hashrate? // hashrate?

@ -24,7 +24,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -115,7 +114,7 @@ func (a *RemoteAgent) GetWork() ([3]string, error) {
block := a.currentWork.Block block := a.currentWork.Block
res[0] = block.HashNoNonce().Hex() res[0] = block.HashNoNonce().Hex()
seedHash, _ := ethash.GetSeedHash(block.NumberU64()) seedHash := pow.EthashSeedHash(block.NumberU64())
res[1] = common.BytesToHash(seedHash).Hex() res[1] = common.BytesToHash(seedHash).Hex()
// Calculate the "target" to be returned to the external miner // Calculate the "target" to be returned to the external miner
n := big.NewInt(1) n := big.NewInt(1)
@ -145,8 +144,8 @@ func (a *RemoteAgent) SubmitWork(nonce types.BlockNonce, mixDigest, hash common.
} }
// Make sure the PoW solutions is indeed valid // Make sure the PoW solutions is indeed valid
block := work.Block.WithMiningResult(nonce, mixDigest) block := work.Block.WithMiningResult(nonce, mixDigest)
if !a.pow.Verify(block) { if err := a.pow.Verify(block); err != nil {
log.Warn(fmt.Sprintf("Invalid PoW submitted for %x", hash)) log.Warn(fmt.Sprintf("Invalid PoW submitted for %x: %v", hash, err))
return false return false
} }
// Solutions seems to be valid, return to the miner and notify acceptance // Solutions seems to be valid, return to the miner and notify acceptance

@ -1,37 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package pow
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type Block interface {
Difficulty() *big.Int
HashNoNonce() common.Hash
Nonce() uint64
MixDigest() common.Hash
NumberU64() uint64
}
type ChainManager interface {
GetBlockByNumber(uint64) *types.Block
CurrentBlock() *types.Block
}

File diff suppressed because it is too large Load Diff

1071
pow/ethash_algo.go Normal file

File diff suppressed because it is too large Load Diff

@ -675,14 +675,14 @@ func TestHashimoto(t *testing.T) {
} }
} }
// Becnhmarks the cache generation performance. // Benchmarks the cache generation performance.
func BenchmarkCacheGeneration(b *testing.B) { func BenchmarkCacheGeneration(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
generateCache(cacheSize(1), make([]byte, 32)) generateCache(cacheSize(1), make([]byte, 32))
} }
} }
// Becnhmarks the dataset (small) generation performance. // Benchmarks the dataset (small) generation performance.
func BenchmarkSmallDatasetGeneration(b *testing.B) { func BenchmarkSmallDatasetGeneration(b *testing.B) {
rawCache := generateCache(65536, make([]byte, 32)) rawCache := generateCache(65536, make([]byte, 32))
cache := prepare(uint64(len(rawCache)), bytes.NewReader(rawCache)) cache := prepare(uint64(len(rawCache)), bytes.NewReader(rawCache))
@ -693,7 +693,7 @@ func BenchmarkSmallDatasetGeneration(b *testing.B) {
} }
} }
// Becnhmarks the light verification performace. // Benchmarks the light verification performance.
func BenchmarkHashimotoLight(b *testing.B) { func BenchmarkHashimotoLight(b *testing.B) {
var ( var (
rawCache = generateCache(cacheSize(1), make([]byte, 32)) rawCache = generateCache(cacheSize(1), make([]byte, 32))
@ -706,7 +706,7 @@ func BenchmarkHashimotoLight(b *testing.B) {
} }
} }
// Becnhmarks the full (small) verification performace. // Benchmarks the full (small) verification performance.
func BenchmarkHashimotoFullSmall(b *testing.B) { func BenchmarkHashimotoFullSmall(b *testing.B) {
var ( var (
rawCache = generateCache(65536, make([]byte, 32)) rawCache = generateCache(65536, make([]byte, 32))

@ -16,9 +16,43 @@
package pow package pow
type PoW interface { import (
Search(block Block, stop <-chan struct{}, index int) (uint64, []byte) "math/big"
Verify(block Block) bool
GetHashrate() int64 "github.com/ethereum/go-ethereum/common"
Turbo(bool) "github.com/ethereum/go-ethereum/core/types"
)
type Block interface {
Difficulty() *big.Int
HashNoNonce() common.Hash
Nonce() uint64
MixDigest() common.Hash
NumberU64() uint64
} }
type ChainManager interface {
GetBlockByNumber(uint64) *types.Block
CurrentBlock() *types.Block
}
type PoW interface {
Verify(block Block) error
Search(block Block, stop <-chan struct{}) (uint64, []byte)
Hashrate() float64
}
// FakePow is a non-validating proof of work implementation.
// It returns true from Verify for any block.
type FakePow struct{}
// Verify implements PoW, returning a success for an input.
func (pow FakePow) Verify(block Block) error { return nil }
// Search implements PoW, returning the nonce 0 for any call.
func (pow FakePow) Search(block Block, stop <-chan struct{}) (uint64, []byte) {
return 0, nil
}
// Hashrate implements PoW, returning 0.
func (pow FakePow) Hashrate() float64 { return 0 }

@ -26,7 +26,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
@ -36,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -172,7 +172,7 @@ func runBlockTest(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, test *Blo
core.WriteHeadBlockHash(db, test.Genesis.Hash()) core.WriteHeadBlockHash(db, test.Genesis.Hash())
evmux := new(event.TypeMux) evmux := new(event.TypeMux)
config := &params.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork} config := &params.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork}
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux, vm.Config{}) chain, err := core.NewBlockChain(db, config, pow.NewSharedEthash(), evmux, vm.Config{})
if err != nil { if err != nil {
return err return err
} }