mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
Merge 42c6c4f5f7 into 7841f0cc09
This commit is contained in:
commit
36791039ab
3 changed files with 111 additions and 3 deletions
|
|
@ -46,6 +46,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
"github.com/ethereum/go-ethereum/pow/multipow"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/whisper"
|
||||
)
|
||||
|
|
@ -759,7 +761,7 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
|
|||
}
|
||||
|
||||
eventMux := new(event.TypeMux)
|
||||
pow := ethash.New()
|
||||
pow := multipow.New(func() pow.PoW { return ethash.New() }, 3)
|
||||
//genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
|
||||
chain, err = core.NewBlockChain(chainDb, pow, eventMux)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
"github.com/ethereum/go-ethereum/pow/multipow"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
|
@ -105,7 +107,7 @@ type Ethereum struct {
|
|||
txPool *core.TxPool
|
||||
blockchain *core.BlockChain
|
||||
accountManager *accounts.Manager
|
||||
pow *ethash.Ethash
|
||||
pow pow.PoW
|
||||
protocolManager *ProtocolManager
|
||||
SolcPath string
|
||||
solc *compiler.Solidity
|
||||
|
|
@ -219,7 +221,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
return nil, err
|
||||
}
|
||||
} else {
|
||||
eth.pow = ethash.New()
|
||||
eth.pow = multipow.New(func() pow.PoW { return ethash.New() }, 5)
|
||||
}
|
||||
//genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb)
|
||||
eth.blockchain, err = core.NewBlockChain(chainDb, eth.pow, eth.EventMux())
|
||||
|
|
|
|||
104
pow/multipow/multipow.go
Normal file
104
pow/multipow/multipow.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2016 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 multipow is a cached PoW using multiple instances internally.
|
||||
package multipow
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// singlePoW is a proof-of-work instance with an associated time value of when it
|
||||
// was last used for verification.
|
||||
type singlePoW struct {
|
||||
pow pow.PoW
|
||||
used time.Time
|
||||
}
|
||||
|
||||
// multiPoW is a proof-of-work implementation that uses multiple underlying PoW
|
||||
// calculators to verify and mine blocks. This allows a higher level caching of
|
||||
// PoW data structures, enabling reusing implementations that otherwise do not
|
||||
// support multiple epoch caching.
|
||||
//
|
||||
// This is particularly important because ethash can only work with a single
|
||||
// verification DAG, and will generate a new one whenever a PoW from a different
|
||||
// epoch is requested. This causes huge cache trashes during epoch transitions
|
||||
// as block/uncle is in different epochs, whilst parallel PoW verifications yet
|
||||
// further wrosten the situation.
|
||||
type multiPoW struct {
|
||||
miner pow.PoW // PoW implementation used solely for mining
|
||||
verifiers map[int]*singlePoW // Set of PoW verifiers by epoch cache
|
||||
lock sync.RWMutex // Mutex protecting the verifier cache
|
||||
}
|
||||
|
||||
// New creates a new proof-of-work caching layer, which creates and maintains
|
||||
// mutliple PoW implementations for handling epoch transitions gracefully.
|
||||
func New(newpow func() pow.PoW, epochs int) pow.PoW {
|
||||
mp := &multiPoW{
|
||||
miner: newpow(),
|
||||
verifiers: make(map[int]*singlePoW),
|
||||
}
|
||||
for i := 0; i < epochs; i++ {
|
||||
mp.verifiers[i] = &singlePoW{
|
||||
pow: newpow(),
|
||||
used: time.Now(),
|
||||
}
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
// Verify delegates a verification request to the PoW with the appropriate
|
||||
// epoch cached. If no such exists, the smallest is used.
|
||||
func (mp *multiPoW) Verify(block pow.Block) bool {
|
||||
// Calculate the epoch required
|
||||
epoch := int(block.NumberU64() / params.EpochDuration.Uint64())
|
||||
|
||||
// If we have a PoW for that epoch, use that
|
||||
mp.lock.Lock()
|
||||
|
||||
cached := mp.verifiers[epoch]
|
||||
if cached == nil {
|
||||
// No cached verifier, reallocate the least recently used
|
||||
evict := 0
|
||||
for old, verifier := range mp.verifiers {
|
||||
if cached == nil || cached.used.After(verifier.used) {
|
||||
evict, cached = old, verifier
|
||||
}
|
||||
}
|
||||
glog.V(logger.Debug).Infof("Replacing epoch %d proof-of-work with epoch %d", evict, epoch)
|
||||
delete(mp.verifiers, evict)
|
||||
mp.verifiers[epoch] = cached
|
||||
}
|
||||
cached.used = time.Now()
|
||||
|
||||
// Release the cache lock and verify the block
|
||||
mp.lock.Unlock()
|
||||
|
||||
return cached.pow.Verify(block)
|
||||
}
|
||||
|
||||
// Mining related operations simply delegate to the underlying miner PoW.
|
||||
func (mp *multiPoW) Search(block pow.Block, stop <-chan struct{}, index int) (uint64, []byte) {
|
||||
return mp.miner.Search(block, stop, index)
|
||||
}
|
||||
func (mp *multiPoW) GetHashrate() int64 { return mp.miner.GetHashrate() }
|
||||
func (mp *multiPoW) Turbo(enable bool) { mp.miner.Turbo(enable) }
|
||||
Loading…
Reference in a new issue