aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/admin.go6
-rw-r--r--cmd/geth/js_test.go2
-rw-r--r--cmd/geth/main.go45
-rw-r--r--cmd/utils/cmd.go52
-rw-r--r--cmd/utils/flags.go2
-rw-r--r--core/block_processor.go14
-rw-r--r--core/block_processor_test.go6
-rw-r--r--core/chain_makers.go2
-rw-r--r--core/chain_manager.go99
-rw-r--r--core/chain_manager_test.go15
-rw-r--r--eth/backend.go4
-rw-r--r--miner/agent.go25
-rw-r--r--miner/worker.go8
-rw-r--r--rpc/http.go3
-rw-r--r--xeth/xeth.go2
15 files changed, 211 insertions, 74 deletions
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index ebdf3512a..53dd0e6ad 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -383,7 +383,7 @@ func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
var passphrase string
if arg.IsUndefined() {
fmt.Println("Please enter a passphrase now.")
- passphrase, err = readPassword("Passphrase: ", true)
+ passphrase, err = utils.PromptPassword("Passphrase: ", true)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
@@ -410,12 +410,12 @@ func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
if arg.IsUndefined() {
fmt.Println("The new account will be encrypted with a passphrase.")
fmt.Println("Please enter a passphrase now.")
- auth, err := readPassword("Passphrase: ", true)
+ auth, err := utils.PromptPassword("Passphrase: ", true)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
- confirm, err := readPassword("Repeat Passphrase: ", false)
+ confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index e02e8f704..6368efbfc 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -172,6 +172,8 @@ func TestBlockChain(t *testing.T) {
tmpfile := filepath.Join(extmp, "export.chain")
tmpfileq := strconv.Quote(tmpfile)
+ ethereum.ChainManager().Reset()
+
checkEvalJSON(t, repl, `admin.export(`+tmpfileq+`)`, `true`)
if _, err := os.Stat(tmpfile); err != nil {
t.Fatal(err)
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index b0970212e..df0af3e79 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -21,7 +21,6 @@
package main
import (
- "bufio"
"fmt"
"io"
"io/ioutil"
@@ -44,7 +43,6 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
- "github.com/peterh/liner"
)
import _ "net/http/pprof"
@@ -230,6 +228,11 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
Name: "upgradedb",
Usage: "upgrade chainblock database",
},
+ {
+ Action: removeDb,
+ Name: "removedb",
+ Usage: "Remove blockchain and state databases",
+ },
}
app.Flags = []cli.Flag{
utils.IdentityFlag,
@@ -421,12 +424,12 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
if len(passfile) == 0 {
fmt.Println(desc)
- auth, err := readPassword("Passphrase: ", true)
+ auth, err := utils.PromptPassword("Passphrase: ", true)
if err != nil {
utils.Fatalf("%v", err)
}
if confirmation {
- confirm, err := readPassword("Repeat Passphrase: ", false)
+ confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
@@ -543,6 +546,25 @@ func exportchain(ctx *cli.Context) {
return
}
+func removeDb(ctx *cli.Context) {
+ confirm, err := utils.PromptConfirm("Remove local databases?")
+ if err != nil {
+ utils.Fatalf("%v", err)
+ }
+
+ if confirm {
+ fmt.Println("Removing chain and state databases...")
+ start := time.Now()
+
+ os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain"))
+ os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state"))
+
+ fmt.Printf("Removed in %v\n", time.Since(start))
+ } else {
+ fmt.Println("Operation aborted")
+ }
+}
+
func upgradeDb(ctx *cli.Context) {
fmt.Println("Upgrade blockchain DB")
@@ -666,18 +688,3 @@ func hashish(x string) bool {
_, err := strconv.Atoi(x)
return err != nil
}
-
-func readPassword(prompt string, warnTerm bool) (string, error) {
- if liner.TerminalSupported() {
- lr := liner.NewLiner()
- defer lr.Close()
- return lr.PasswordPrompt(prompt)
- }
- if warnTerm {
- fmt.Println("!! Unsupported terminal, password will be echoed.")
- }
- fmt.Print(prompt)
- input, err := bufio.NewReader(os.Stdin).ReadString('\n')
- fmt.Println()
- return input, err
-}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index fb55a64af..39b4e46da 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -22,11 +22,13 @@
package utils
import (
+ "bufio"
"fmt"
"io"
"os"
"os/signal"
"regexp"
+ "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@@ -35,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/peterh/liner"
)
var interruptCallbacks = []func(os.Signal){}
@@ -71,18 +74,45 @@ func openLogFile(Datadir string, filename string) *os.File {
return file
}
-func confirm(message string) bool {
- fmt.Println(message, "Are you sure? (y/n)")
- var r string
- fmt.Scanln(&r)
- for ; ; fmt.Scanln(&r) {
- if r == "n" || r == "y" {
- break
- } else {
- fmt.Printf("Yes or no? (%s)", r)
- }
+func PromptConfirm(prompt string) (bool, error) {
+ var (
+ input string
+ err error
+ )
+ prompt = prompt + " [y/N] "
+
+ if liner.TerminalSupported() {
+ lr := liner.NewLiner()
+ defer lr.Close()
+ input, err = lr.Prompt(prompt)
+ } else {
+ fmt.Print(prompt)
+ input, err = bufio.NewReader(os.Stdin).ReadString('\n')
+ fmt.Println()
+ }
+
+ if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" {
+ return true, nil
+ } else {
+ return false, nil
+ }
+
+ return false, err
+}
+
+func PromptPassword(prompt string, warnTerm bool) (string, error) {
+ if liner.TerminalSupported() {
+ lr := liner.NewLiner()
+ defer lr.Close()
+ return lr.PasswordPrompt(prompt)
+ }
+ if warnTerm {
+ fmt.Println("!! Unsupported terminal, password will be echoed.")
}
- return r == "y"
+ fmt.Print(prompt)
+ input, err := bufio.NewReader(os.Stdin).ReadString('\n')
+ fmt.Println()
+ return input, err
}
func initDataDir(Datadir string) {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 6ec4fdc55..f646e4fcc 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -336,8 +336,8 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
}
eventMux := new(event.TypeMux)
- chainManager := core.NewChainManager(blockDb, stateDb, eventMux)
pow := ethash.New()
+ chainManager := core.NewChainManager(blockDb, stateDb, pow, eventMux)
txPool := core.NewTxPool(eventMux, chainManager.State, chainManager.GasLimit)
blockProcessor := core.NewBlockProcessor(stateDb, extraDb, pow, txPool, chainManager, eventMux)
chainManager.SetProcessor(blockProcessor)
diff --git a/core/block_processor.go b/core/block_processor.go
index 0652d217f..20e6722a4 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -188,7 +188,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
state := state.New(parent.Root(), sm.db)
// Block validation
- if err = sm.ValidateHeader(block.Header(), parent.Header()); err != nil {
+ if err = sm.ValidateHeader(block.Header(), parent.Header(), false); err != nil {
return
}
@@ -268,7 +268,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
// Validates the current block. Returns an error if the block was invalid,
// an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult)
-func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
+func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error {
if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
}
@@ -299,9 +299,11 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
}
- // Verify the nonce of the block. Return an error if it's not valid
- if !sm.Pow.Verify(types.NewBlockWithHeader(block)) {
- return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
+ if checkPow {
+ // Verify the nonce of the block. Return an error if it's not valid
+ if !sm.Pow.Verify(types.NewBlockWithHeader(block)) {
+ return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
+ }
}
return nil
@@ -375,7 +377,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
return UncleError("uncle[%d](%x)'s parent unknown (%x)", i, hash[:4], uncle.ParentHash[0:4])
}
- if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash]); err != nil {
+ if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash], true); err != nil {
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
}
}
diff --git a/core/block_processor_test.go b/core/block_processor_test.go
index 02524a4c1..e0aa5fb4c 100644
--- a/core/block_processor_test.go
+++ b/core/block_processor_test.go
@@ -14,7 +14,7 @@ func proc() (*BlockProcessor, *ChainManager) {
db, _ := ethdb.NewMemDatabase()
var mux event.TypeMux
- chainMan := NewChainManager(db, db, &mux)
+ chainMan := NewChainManager(db, db, thePow(), &mux)
return NewBlockProcessor(db, db, ezp.New(), nil, chainMan, &mux), chainMan
}
@@ -24,13 +24,13 @@ func TestNumber(t *testing.T) {
block1.Header().Number = big.NewInt(3)
block1.Header().Time--
- err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header())
+ err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false)
if err != BlockNumberErr {
t.Errorf("expected block number error %v", err)
}
block1 = chain.NewBlock(common.Address{})
- err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header())
+ err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false)
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index acf7b39cc..44f17cc33 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -109,7 +109,7 @@ func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Dat
// Effectively a fork factory
func newChainManager(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager {
genesis := GenesisBlock(db)
- bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux}
+ bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux, pow: FakePow{}}
bc.txState = state.ManageState(state.New(genesis.Root(), db))
bc.futureBlocks = NewBlockCache(1000)
if block == nil {
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 62e518ca0..4fb7506e5 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"math/big"
+ "runtime"
"sync"
"time"
@@ -15,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -100,9 +102,11 @@ type ChainManager struct {
quit chan struct{}
wg sync.WaitGroup
+
+ pow pow.PoW
}
-func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *ChainManager {
+func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.TypeMux) *ChainManager {
bc := &ChainManager{
blockDb: blockDb,
stateDb: stateDb,
@@ -110,6 +114,7 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai
eventMux: mux,
quit: make(chan struct{}),
cache: NewBlockCache(blockCacheLimit),
+ pow: pow,
}
bc.setLastState()
@@ -343,7 +348,7 @@ func (self *ChainManager) Export(w io.Writer) error {
last := self.currentBlock.NumberU64()
- for nr := uint64(0); nr <= last; nr++ {
+ for nr := uint64(1); nr <= last; nr++ {
block := self.GetBlockByNumber(nr)
if block == nil {
return fmt.Errorf("export failed on #%d: not found", nr)
@@ -407,9 +412,11 @@ func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (
}
func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
- if block := self.cache.Get(hash); block != nil {
- return block
- }
+ /*
+ if block := self.cache.Get(hash); block != nil {
+ return block
+ }
+ */
data, _ := self.blockDb.Get(append(blockHashPre, hash[:]...))
if len(data) == 0 {
@@ -529,10 +536,19 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
stats struct{ queued, processed, ignored int }
tstart = time.Now()
)
+
+ // check the nonce in parallel to the block processing
+ // this speeds catching up significantly
+ nonceErrCh := make(chan error)
+ go func() {
+ nonceErrCh <- verifyNonces(self.pow, chain)
+ }()
+
for i, block := range chain {
if block == nil {
continue
}
+
// Setting block.Td regardless of error (known for example) prevents errors down the line
// in the protocol handler
block.Td = new(big.Int).Set(CalcTD(block, self.GetBlock(block.ParentHash())))
@@ -562,11 +578,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
continue
}
- h := block.Header()
-
- glog.V(logger.Error).Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes())
- glog.V(logger.Error).Infoln(err)
- glog.V(logger.Debug).Infoln(block)
+ blockErr(block, err)
return i, err
}
@@ -620,6 +632,13 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
}
+ // check and wait for the nonce error channel and
+ // make sure no nonce error was thrown in the process
+ err := <-nonceErrCh
+ if err != nil {
+ return 0, err
+ }
+
if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) {
tend := time.Since(tstart)
start, end := chain[0], chain[len(chain)-1]
@@ -718,3 +737,63 @@ out:
}
}
}
+
+func blockErr(block *types.Block, err error) {
+ h := block.Header()
+ glog.V(logger.Error).Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes())
+ glog.V(logger.Error).Infoln(err)
+ glog.V(logger.Debug).Infoln(block)
+}
+
+// verifyNonces verifies nonces of the given blocks in parallel and returns
+// an error if one of the blocks nonce verifications failed.
+func verifyNonces(pow pow.PoW, blocks []*types.Block) error {
+ // Spawn a few workers. They listen for blocks on the in channel
+ // and send results on done. The workers will exit in the
+ // background when in is closed.
+ var (
+ in = make(chan *types.Block)
+ done = make(chan error, runtime.GOMAXPROCS(0))
+ )
+ defer close(in)
+ for i := 0; i < cap(done); i++ {
+ go verifyNonce(pow, in, done)
+ }
+ // Feed blocks to the workers, aborting at the first invalid nonce.
+ var (
+ running, i int
+ block *types.Block
+ sendin = in
+ )
+ for i < len(blocks) || running > 0 {
+ if i == len(blocks) {
+ // Disable sending to in.
+ sendin = nil
+ } else {
+ block = blocks[i]
+ i++
+ }
+ select {
+ case sendin <- block:
+ running++
+ case err := <-done:
+ running--
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// verifyNonce is a worker for the verifyNonces method. It will run until
+// in is closed.
+func verifyNonce(pow pow.PoW, in <-chan *types.Block, done chan<- error) {
+ for block := range in {
+ if !pow.Verify(block) {
+ done <- ValidationError("Block(#%v) nonce is invalid (= %x)", block.Number(), block.Nonce)
+ } else {
+ done <- nil
+ }
+ }
+}
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index b5155e223..56bef24f3 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -9,11 +9,13 @@ import (
"strconv"
"testing"
+ "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -21,6 +23,11 @@ func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
}
+func thePow() pow.PoW {
+ pow, _ := ethash.NewForTesting()
+ return pow
+}
+
// 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)) {
// switch databases to process the new chain
@@ -259,7 +266,7 @@ func TestChainInsertions(t *testing.T) {
}
var eventMux event.TypeMux
- chainMan := NewChainManager(db, db, &eventMux)
+ chainMan := NewChainManager(db, db, thePow(), &eventMux)
txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) })
blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux)
chainMan.SetProcessor(blockMan)
@@ -305,7 +312,7 @@ func TestChainMultipleInsertions(t *testing.T) {
}
}
var eventMux event.TypeMux
- chainMan := NewChainManager(db, db, &eventMux)
+ chainMan := NewChainManager(db, db, thePow(), &eventMux)
txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) })
blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux)
chainMan.SetProcessor(blockMan)
@@ -334,7 +341,7 @@ func TestGetAncestors(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
var eventMux event.TypeMux
- chainMan := NewChainManager(db, db, &eventMux)
+ chainMan := NewChainManager(db, db, thePow(), &eventMux)
chain, err := loadChain("valid1", t)
if err != nil {
fmt.Println(err)
@@ -372,7 +379,7 @@ func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block
func chm(genesis *types.Block, db common.Database) *ChainManager {
var eventMux event.TypeMux
- bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux}
+ bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}}
bc.cache = NewBlockCache(100)
bc.futureBlocks = NewBlockCache(100)
bc.processor = bproc{}
diff --git a/eth/backend.go b/eth/backend.go
index a7107f8d8..519a4c410 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -266,9 +266,9 @@ func New(config *Config) (*Ethereum, error) {
MinerThreads: config.MinerThreads,
}
- eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.EventMux())
- eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
eth.pow = ethash.New()
+ eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.pow, eth.EventMux())
+ eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
eth.chainManager.SetProcessor(eth.blockProcessor)
diff --git a/miner/agent.go b/miner/agent.go
index da2a2008d..3ed3ba839 100644
--- a/miner/agent.go
+++ b/miner/agent.go
@@ -40,7 +40,6 @@ func (self *CpuAgent) Stop() {
defer self.mu.Unlock()
close(self.quit)
- close(self.quitCurrentOp)
}
func (self *CpuAgent) Start() {
@@ -50,7 +49,6 @@ func (self *CpuAgent) Start() {
self.quit = make(chan struct{})
// creating current op ch makes sure we're not closing a nil ch
// later on
- self.quitCurrentOp = make(chan struct{})
self.workCh = make(chan *types.Block, 1)
go self.update()
@@ -62,11 +60,19 @@ out:
select {
case block := <-self.workCh:
self.mu.Lock()
- close(self.quitCurrentOp)
+ if self.quitCurrentOp != nil {
+ close(self.quitCurrentOp)
+ }
+ self.quitCurrentOp = make(chan struct{})
+ go self.mine(block, self.quitCurrentOp)
self.mu.Unlock()
-
- go self.mine(block)
case <-self.quit:
+ self.mu.Lock()
+ if self.quitCurrentOp != nil {
+ close(self.quitCurrentOp)
+ self.quitCurrentOp = nil
+ }
+ self.mu.Unlock()
break out
}
}
@@ -84,16 +90,11 @@ done:
}
}
-func (self *CpuAgent) mine(block *types.Block) {
+func (self *CpuAgent) mine(block *types.Block, stop <- chan struct{}) {
glog.V(logger.Debug).Infof("(re)started agent[%d]. mining...\n", self.index)
- // Reset the channel
- self.mu.Lock()
- self.quitCurrentOp = make(chan struct{})
- self.mu.Unlock()
-
// Mine
- nonce, mixDigest := self.pow.Search(block, self.quitCurrentOp)
+ nonce, mixDigest := self.pow.Search(block, stop)
if nonce != 0 {
block.SetNonce(nonce)
block.Header().MixDigest = common.BytesToHash(mixDigest)
diff --git a/miner/worker.go b/miner/worker.go
index d5f9dd8c5..5fa5d3777 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -224,7 +224,13 @@ func (self *worker) wait() {
}
self.mux.Post(core.NewMinedBlockEvent{block})
- glog.V(logger.Info).Infof("🔨 Mined block #%v", block.Number())
+ var stale string
+ canonBlock := self.chain.GetBlockByNumber(block.NumberU64())
+ if canonBlock != nil && canonBlock.Hash() != block.Hash() {
+ stale = "stale-"
+ }
+
+ glog.V(logger.Info).Infof("🔨 Mined %sblock #%v (%x)", stale, block.Number(), block.Hash().Bytes()[:4])
jsonlogger.LogJson(&logger.EthMinerNewBlock{
BlockHash: block.Hash().Hex(),
diff --git a/rpc/http.go b/rpc/http.go
index 9b3fa5142..f37e102f5 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -6,6 +6,7 @@ import (
"io"
"io/ioutil"
"net/http"
+ "strings"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
@@ -39,7 +40,7 @@ func Start(pipe *xeth.XEth, config RpcConfig) error {
if len(config.CorsDomain) > 0 {
var opts cors.Options
opts.AllowedMethods = []string{"POST"}
- opts.AllowedOrigins = []string{config.CorsDomain}
+ opts.AllowedOrigins = strings.Split(config.CorsDomain, " ")
c := cors.New(opts)
handler = newStoppableHandler(c.Handler(JSONRPC(pipe)), l.stop)
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 2d01bc681..7de3e31be 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -927,9 +927,11 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
tx.SetNonce(nonce)
if err := self.sign(tx, from, false); err != nil {
+ state.RemoveNonce(from, tx.Nonce())
return "", err
}
if err := self.backend.TxPool().Add(tx); err != nil {
+ state.RemoveNonce(from, tx.Nonce())
return "", err
}