diff options
-rw-r--r-- | cmd/geth/admin.go | 25 | ||||
-rw-r--r-- | cmd/geth/main.go | 14 | ||||
-rw-r--r-- | core/block_processor.go | 11 | ||||
-rw-r--r-- | miner/worker.go | 59 |
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 { |