aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/admin.go25
-rw-r--r--cmd/geth/main.go14
-rw-r--r--core/block_processor.go11
-rw-r--r--miner/worker.go59
4 files changed, 96 insertions, 13 deletions
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index 28786553c..8f9a009d7 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -88,6 +88,7 @@ func (js *jsre) adminBindings() {
debug.Set("getBlockRlp", js.getBlockRlp)
debug.Set("setHead", js.setHead)
debug.Set("processBlock", js.debugBlock)
+ debug.Set("seedhash", js.seedHash)
// undocumented temporary
debug.Set("waitForBlocks", js.waitForBlocks)
}
@@ -118,6 +119,27 @@ func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
return block, nil
}
+func (js *jsre) seedHash(call otto.FunctionCall) otto.Value {
+ if len(call.ArgumentList) > 0 {
+ if call.Argument(0).IsNumber() {
+ num, _ := call.Argument(0).ToInteger()
+ hash, err := ethash.GetSeedHash(uint64(num))
+ if err != nil {
+ fmt.Println(err)
+ return otto.UndefinedValue()
+ }
+ v, _ := call.Otto.ToValue(fmt.Sprintf("0x%x", hash))
+ return v
+ } else {
+ fmt.Println("arg not a number")
+ }
+ } else {
+ fmt.Println("requires number argument")
+ }
+
+ return otto.UndefinedValue()
+}
+
func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
txs := js.ethereum.TxPool().GetTransactions()
@@ -220,10 +242,11 @@ func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
vm.Debug = true
_, err = js.ethereum.BlockProcessor().RetryProcess(block)
if err != nil {
- glog.Infoln(err)
+ fmt.Println(err)
}
vm.Debug = old
+ fmt.Println("ok")
return otto.UndefinedValue()
}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 9d935efbd..0cbf8e41a 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -48,7 +48,7 @@ import _ "net/http/pprof"
const (
ClientIdentifier = "Geth"
- Version = "0.9.24"
+ Version = "0.9.25"
)
var (
@@ -533,9 +533,9 @@ func importchain(ctx *cli.Context) {
}
// force database flush
- ethereum.BlockDb().Close()
- ethereum.StateDb().Close()
- ethereum.ExtraDb().Close()
+ ethereum.BlockDb().Flush()
+ ethereum.StateDb().Flush()
+ ethereum.ExtraDb().Flush()
fmt.Printf("Import done in %v", time.Since(start))
@@ -630,9 +630,9 @@ func upgradeDb(ctx *cli.Context) {
}
// force database flush
- ethereum.BlockDb().Close()
- ethereum.StateDb().Close()
- ethereum.ExtraDb().Close()
+ ethereum.BlockDb().Flush()
+ ethereum.StateDb().Flush()
+ ethereum.ExtraDb().Flush()
os.Remove(exportFile)
diff --git a/core/block_processor.go b/core/block_processor.go
index 3f10e5efd..e064cdd80 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -21,7 +21,7 @@ import (
const (
// must be bumped when consensus algorithm is changed, this forces the upgradedb
// command to be run (forces the blocks to be imported again using the new algorithm)
- BlockChainVersion = 2
+ BlockChainVersion = 3
)
var receiptsPre = []byte("receipts-")
@@ -159,6 +159,9 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err
return nil, ParentError(header.ParentHash)
}
parent := sm.bc.GetBlock(header.ParentHash)
+ if !sm.Pow.Verify(block) {
+ return nil, ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
+ }
return sm.processWithParent(block, parent)
}
@@ -282,9 +285,8 @@ func (self *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.
}
-// 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)
+// See YP section 4.3.4. "Block Header Validity"
+// Validates a block. Returns an error if the block is invalid.
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))
@@ -295,7 +297,6 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow b
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
}
- // block.gasLimit - parent.gasLimit <= parent.gasLimit / GasLimitBoundDivisor
a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
a.Abs(a)
b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor)
diff --git a/miner/worker.go b/miner/worker.go
index 5e4ff7510..12ed65626 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -38,6 +38,13 @@ type Agent interface {
GetHashRate() int64
}
+const miningLogAtDepth = 5
+
+type uint64RingBuffer struct {
+ ints []uint64 //array of all integers in buffer
+ next int //where is the next insertion? assert 0 <= next < len(ints)
+}
+
// environment is the workers current environment and holds
// all of the current state information
type environment struct {
@@ -54,6 +61,7 @@ type environment struct {
lowGasTransactors *set.Set
ownedAccounts *set.Set
lowGasTxs types.Transactions
+ localMinedBlocks *uint64RingBuffer // the most recent block numbers that were mined locally (used to check block inclusion)
}
// env returns a new environment for the current cycle
@@ -209,6 +217,18 @@ out:
events.Unsubscribe()
}
+func newLocalMinedBlock(blockNumber uint64, prevMinedBlocks *uint64RingBuffer) (minedBlocks *uint64RingBuffer) {
+ if prevMinedBlocks == nil {
+ minedBlocks = &uint64RingBuffer{next: 0, ints: make([]uint64, miningLogAtDepth + 1)}
+ } else {
+ minedBlocks = prevMinedBlocks
+ }
+
+ minedBlocks.ints[minedBlocks.next] = blockNumber
+ minedBlocks.next = (minedBlocks.next + 1) % len(minedBlocks.ints)
+ return minedBlocks
+}
+
func (self *worker) wait() {
for {
for block := range self.recv {
@@ -228,6 +248,8 @@ func (self *worker) wait() {
canonBlock := self.chain.GetBlockByNumber(block.NumberU64())
if canonBlock != nil && canonBlock.Hash() != block.Hash() {
stale = "stale-"
+ } else {
+ self.current.localMinedBlocks = newLocalMinedBlock(block.Number().Uint64(), self.current.localMinedBlocks)
}
glog.V(logger.Info).Infof("🔨 Mined %sblock #%v (%x)", stale, block.Number(), block.Hash().Bytes()[:4])
@@ -286,6 +308,9 @@ func (self *worker) makeCurrent() {
current.ignoredTransactors = set.New()
current.lowGasTransactors = set.New()
current.ownedAccounts = accountAddressesSet(accounts)
+ if self.current != nil {
+ current.localMinedBlocks = self.current.localMinedBlocks
+ }
parent := self.chain.GetBlock(current.block.ParentHash())
current.coinbase.SetGasPool(core.CalcGasLimit(parent))
@@ -304,6 +329,38 @@ func (w *worker) setGasPrice(p *big.Int) {
w.mux.Post(core.GasPriceChanged{w.gasPrice})
}
+func (self *worker) isBlockLocallyMined(deepBlockNum uint64) bool {
+ //Did this instance mine a block at {deepBlockNum} ?
+ var isLocal = false
+ for idx, blockNum := range self.current.localMinedBlocks.ints {
+ if deepBlockNum == blockNum {
+ isLocal = true
+ self.current.localMinedBlocks.ints[idx] = 0 //prevent showing duplicate logs
+ break
+ }
+ }
+ //Short-circuit on false, because the previous and following tests must both be true
+ if !isLocal {
+ return false
+ }
+
+ //Does the block at {deepBlockNum} send earnings to my coinbase?
+ var block = self.chain.GetBlockByNumber(deepBlockNum)
+ return block.Header().Coinbase == self.coinbase
+}
+
+func (self *worker) logLocalMinedBlocks(previous *environment) {
+ if previous != nil && self.current.localMinedBlocks != nil {
+ nextBlockNum := self.current.block.Number().Uint64()
+ for checkBlockNum := previous.block.Number().Uint64(); checkBlockNum < nextBlockNum; checkBlockNum++ {
+ inspectBlockNum := checkBlockNum - miningLogAtDepth
+ if self.isBlockLocallyMined(inspectBlockNum) {
+ glog.V(logger.Info).Infof("🔨 🔗 Mined %d blocks back: block #%v", miningLogAtDepth, inspectBlockNum)
+ }
+ }
+ }
+}
+
func (self *worker) commitNewWork() {
self.mu.Lock()
defer self.mu.Unlock()
@@ -312,6 +369,7 @@ func (self *worker) commitNewWork() {
self.currentMu.Lock()
defer self.currentMu.Unlock()
+ previous := self.current
self.makeCurrent()
current := self.current
@@ -347,6 +405,7 @@ func (self *worker) commitNewWork() {
// We only care about logging if we're actually mining
if atomic.LoadInt32(&self.mining) == 1 {
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles\n", current.block.Number(), current.tcount, len(uncles))
+ self.logLocalMinedBlocks(previous)
}
for _, hash := range badUncles {