Unverified Commit dde2da0e authored by Péter Szilágyi's avatar Péter Szilágyi Committed by GitHub

all: remove ethash pow, only retain shims needed for consensus and tests (#27178)

* all: remove ethash pow, only retain shims needed for consensus and tests

* all: thank you linter

* all: disallow launching Geth in legacy PoW mode

* cmd/env/internal/t8ntool: remove dangling ethash flag
parent ac3418de
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"eip155Block": 0, "eip155Block": 0,
"eip158Block": 0, "eip158Block": 0,
"byzantiumBlock": 0, "byzantiumBlock": 0,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
}, },
"nonce": "0xdeadbeefdeadbeef", "nonce": "0xdeadbeefdeadbeef",
......
...@@ -28,7 +28,6 @@ import ( ...@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -75,8 +74,6 @@ type bbInput struct { ...@@ -75,8 +74,6 @@ type bbInput struct {
Clique *cliqueInput `json:"clique,omitempty"` Clique *cliqueInput `json:"clique,omitempty"`
Ethash bool `json:"-"` Ethash bool `json:"-"`
EthashDir string `json:"-"`
PowMode ethash.Mode `json:"-"`
Txs []*types.Transaction `json:"-"` Txs []*types.Transaction `json:"-"`
Ommers []*types.Header `json:"-"` Ommers []*types.Header `json:"-"`
} }
...@@ -162,8 +159,6 @@ func (i *bbInput) ToBlock() *types.Block { ...@@ -162,8 +159,6 @@ func (i *bbInput) ToBlock() *types.Block {
// SealBlock seals the given block using the configured engine. // SealBlock seals the given block using the configured engine.
func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) { func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) {
switch { switch {
case i.Ethash:
return i.sealEthash(block)
case i.Clique != nil: case i.Clique != nil:
return i.sealClique(block) return i.sealClique(block)
default: default:
...@@ -171,33 +166,6 @@ func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) { ...@@ -171,33 +166,6 @@ func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) {
} }
} }
// sealEthash seals the given block using ethash.
func (i *bbInput) sealEthash(block *types.Block) (*types.Block, error) {
if i.Header.Nonce != nil {
return nil, NewError(ErrorConfig, fmt.Errorf("sealing with ethash will overwrite provided nonce"))
}
ethashConfig := ethash.Config{
PowMode: i.PowMode,
DatasetDir: i.EthashDir,
CacheDir: i.EthashDir,
DatasetsInMem: 1,
DatasetsOnDisk: 2,
CachesInMem: 2,
CachesOnDisk: 3,
}
engine := ethash.New(ethashConfig, nil, true)
defer engine.Close()
// Use a buffered chan for results.
// If the testmode is used, the sealer will return quickly, and complain
// "Sealing result is not read by miner" if it cannot write the result.
results := make(chan *types.Block, 1)
if err := engine.Seal(nil, block, results, nil); err != nil {
panic(fmt.Sprintf("failed to seal block: %v", err))
}
found := <-results
return block.WithSeal(found.Header()), nil
}
// sealClique seals the given block using clique. // sealClique seals the given block using clique.
func (i *bbInput) sealClique(block *types.Block) (*types.Block, error) { func (i *bbInput) sealClique(block *types.Block) (*types.Block, error) {
// If any clique value overwrites an explicit header value, fail // If any clique value overwrites an explicit header value, fail
...@@ -267,28 +235,8 @@ func readInput(ctx *cli.Context) (*bbInput, error) { ...@@ -267,28 +235,8 @@ func readInput(ctx *cli.Context) (*bbInput, error) {
withdrawalsStr = ctx.String(InputWithdrawalsFlag.Name) withdrawalsStr = ctx.String(InputWithdrawalsFlag.Name)
txsStr = ctx.String(InputTxsRlpFlag.Name) txsStr = ctx.String(InputTxsRlpFlag.Name)
cliqueStr = ctx.String(SealCliqueFlag.Name) cliqueStr = ctx.String(SealCliqueFlag.Name)
ethashOn = ctx.Bool(SealEthashFlag.Name)
ethashDir = ctx.String(SealEthashDirFlag.Name)
ethashMode = ctx.String(SealEthashModeFlag.Name)
inputData = &bbInput{} inputData = &bbInput{}
) )
if ethashOn && cliqueStr != "" {
return nil, NewError(ErrorConfig, fmt.Errorf("both ethash and clique sealing specified, only one may be chosen"))
}
if ethashOn {
inputData.Ethash = ethashOn
inputData.EthashDir = ethashDir
switch ethashMode {
case "normal":
inputData.PowMode = ethash.ModeNormal
case "test":
inputData.PowMode = ethash.ModeTest
case "fake":
inputData.PowMode = ethash.ModeFake
default:
return nil, NewError(ErrorConfig, fmt.Errorf("unknown pow mode: %s, supported modes: test, fake, normal", ethashMode))
}
}
if headerStr == stdinSelector || ommersStr == stdinSelector || txsStr == stdinSelector || cliqueStr == stdinSelector { if headerStr == stdinSelector || ommersStr == stdinSelector || txsStr == stdinSelector || cliqueStr == stdinSelector {
decoder := json.NewDecoder(os.Stdin) decoder := json.NewDecoder(os.Stdin)
if err := decoder.Decode(inputData); err != nil { if err := decoder.Decode(inputData); err != nil {
......
...@@ -125,19 +125,6 @@ var ( ...@@ -125,19 +125,6 @@ var (
Name: "seal.clique", Name: "seal.clique",
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.", Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",
} }
SealEthashFlag = &cli.BoolFlag{
Name: "seal.ethash",
Usage: "Seal block with ethash.",
}
SealEthashDirFlag = &cli.StringFlag{
Name: "seal.ethash.dir",
Usage: "Path to ethash DAG. If none exists, a new DAG will be generated.",
}
SealEthashModeFlag = &cli.StringFlag{
Name: "seal.ethash.mode",
Usage: "Defines the type and amount of PoW verification an ethash engine makes.",
Value: "normal",
}
RewardFlag = &cli.Int64Flag{ RewardFlag = &cli.Int64Flag{
Name: "state.reward", Name: "state.reward",
Usage: "Mining reward. Set to -1 to disable", Usage: "Mining reward. Set to -1 to disable",
......
...@@ -179,9 +179,6 @@ var blockBuilderCommand = &cli.Command{ ...@@ -179,9 +179,6 @@ var blockBuilderCommand = &cli.Command{
t8ntool.InputWithdrawalsFlag, t8ntool.InputWithdrawalsFlag,
t8ntool.InputTxsRlpFlag, t8ntool.InputTxsRlpFlag,
t8ntool.SealCliqueFlag, t8ntool.SealCliqueFlag,
t8ntool.SealEthashFlag,
t8ntool.SealEthashDirFlag,
t8ntool.SealEthashModeFlag,
t8ntool.VerbosityFlag, t8ntool.VerbosityFlag,
}, },
} }
......
...@@ -41,7 +41,9 @@ var customGenesisTests = []struct { ...@@ -41,7 +41,9 @@ var customGenesisTests = []struct {
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00", "timestamp" : "0x00",
"config" : {} "config" : {
"terminalTotalDifficultyPassed": true
}
}`, }`,
query: "eth.getBlock(0).nonce", query: "eth.getBlock(0).nonce",
result: "0x0000000000001338", result: "0x0000000000001338",
...@@ -61,7 +63,8 @@ var customGenesisTests = []struct { ...@@ -61,7 +63,8 @@ var customGenesisTests = []struct {
"config" : { "config" : {
"homesteadBlock" : 42, "homesteadBlock" : 42,
"daoForkBlock" : 141, "daoForkBlock" : 141,
"daoForkSupport" : true "daoForkSupport" : true,
"terminalTotalDifficultyPassed" : true
} }
}`, }`,
query: "eth.getBlock(0).nonce", query: "eth.getBlock(0).nonce",
...@@ -111,7 +114,9 @@ func TestCustomBackend(t *testing.T) { ...@@ -111,7 +114,9 @@ func TestCustomBackend(t *testing.T) {
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00", "timestamp" : "0x00",
"config" : {} "config" : {
"terminalTotalDifficultyPassed": true
}
}` }`
type backendTest struct { type backendTest struct {
initArgs []string initArgs []string
......
...@@ -66,14 +66,6 @@ var ( ...@@ -66,14 +66,6 @@ var (
utils.SmartCardDaemonPathFlag, utils.SmartCardDaemonPathFlag,
utils.OverrideCancun, utils.OverrideCancun,
utils.EnablePersonal, utils.EnablePersonal,
utils.EthashCacheDirFlag,
utils.EthashCachesInMemoryFlag,
utils.EthashCachesOnDiskFlag,
utils.EthashCachesLockMmapFlag,
utils.EthashDatasetDirFlag,
utils.EthashDatasetsInMemoryFlag,
utils.EthashDatasetsOnDiskFlag,
utils.EthashDatasetsLockMmapFlag,
utils.TxPoolLocalsFlag, utils.TxPoolLocalsFlag,
utils.TxPoolNoLocalsFlag, utils.TxPoolNoLocalsFlag,
utils.TxPoolJournalFlag, utils.TxPoolJournalFlag,
...@@ -120,14 +112,11 @@ var ( ...@@ -120,14 +112,11 @@ var (
utils.MaxPeersFlag, utils.MaxPeersFlag,
utils.MaxPendingPeersFlag, utils.MaxPendingPeersFlag,
utils.MiningEnabledFlag, utils.MiningEnabledFlag,
utils.MinerThreadsFlag,
utils.MinerNotifyFlag,
utils.MinerGasLimitFlag, utils.MinerGasLimitFlag,
utils.MinerGasPriceFlag, utils.MinerGasPriceFlag,
utils.MinerEtherbaseFlag, utils.MinerEtherbaseFlag,
utils.MinerExtraDataFlag, utils.MinerExtraDataFlag,
utils.MinerRecommitIntervalFlag, utils.MinerRecommitIntervalFlag,
utils.MinerNoVerifyFlag,
utils.MinerNewPayloadTimeout, utils.MinerNewPayloadTimeout,
utils.NATFlag, utils.NATFlag,
utils.NoDiscoverFlag, utils.NoDiscoverFlag,
...@@ -142,13 +131,11 @@ var ( ...@@ -142,13 +131,11 @@ var (
utils.VMEnableDebugFlag, utils.VMEnableDebugFlag,
utils.NetworkIdFlag, utils.NetworkIdFlag,
utils.EthStatsURLFlag, utils.EthStatsURLFlag,
utils.FakePoWFlag,
utils.NoCompactionFlag, utils.NoCompactionFlag,
utils.GpoBlocksFlag, utils.GpoBlocksFlag,
utils.GpoPercentileFlag, utils.GpoPercentileFlag,
utils.GpoMaxGasPriceFlag, utils.GpoMaxGasPriceFlag,
utils.GpoIgnoreGasPriceFlag, utils.GpoIgnoreGasPriceFlag,
utils.MinerNotifyFullFlag,
configFileFlag, configFileFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags) }, utils.NetworkFlags, utils.DatabasePathFlags)
...@@ -224,8 +211,6 @@ func init() { ...@@ -224,8 +211,6 @@ func init() {
attachCommand, attachCommand,
javascriptCommand, javascriptCommand,
// See misccmd.go: // See misccmd.go:
makecacheCommand,
makedagCommand,
versionCommand, versionCommand,
versionCheckCommand, versionCheckCommand,
licenseCommand, licenseCommand,
...@@ -438,9 +423,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon ...@@ -438,9 +423,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
// Set the gas price to the limits from the CLI and start mining // Set the gas price to the limits from the CLI and start mining
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
ethBackend.TxPool().SetGasPrice(gasprice) ethBackend.TxPool().SetGasPrice(gasprice)
// start mining if err := ethBackend.StartMining(); err != nil {
threads := ctx.Int(utils.MinerThreadsFlag.Name)
if err := ethBackend.StartMining(threads); err != nil {
utils.Fatalf("Failed to start mining: %v", err) utils.Fatalf("Failed to start mining: %v", err)
} }
} }
......
...@@ -20,11 +20,8 @@ import ( ...@@ -20,11 +20,8 @@ import (
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"strconv"
"strings" "strings"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/internal/version" "github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
...@@ -41,30 +38,6 @@ var ( ...@@ -41,30 +38,6 @@ var (
Usage: "Version to check", Usage: "Version to check",
Value: version.ClientName(clientIdentifier), Value: version.ClientName(clientIdentifier),
} }
makecacheCommand = &cli.Command{
Action: makecache,
Name: "makecache",
Usage: "Generate ethash verification cache (for testing)",
ArgsUsage: "<blockNum> <outputDir>",
Description: `
The makecache command generates an ethash cache in <outputDir>.
This command exists to support the system testing project.
Regular users do not need to execute it.
`,
}
makedagCommand = &cli.Command{
Action: makedag,
Name: "makedag",
Usage: "Generate ethash mining DAG (for testing)",
ArgsUsage: "<blockNum> <outputDir>",
Description: `
The makedag command generates an ethash DAG in <outputDir>.
This command exists to support the system testing project.
Regular users do not need to execute it.
`,
}
versionCommand = &cli.Command{ versionCommand = &cli.Command{
Action: printVersion, Action: printVersion,
Name: "version", Name: "version",
...@@ -96,36 +69,6 @@ and displays information about any security vulnerabilities that affect the curr ...@@ -96,36 +69,6 @@ and displays information about any security vulnerabilities that affect the curr
} }
) )
// makecache generates an ethash verification cache into the provided folder.
func makecache(ctx *cli.Context) error {
args := ctx.Args().Slice()
if len(args) != 2 {
utils.Fatalf(`Usage: geth makecache <block number> <outputdir>`)
}
block, err := strconv.ParseUint(args[0], 0, 64)
if err != nil {
utils.Fatalf("Invalid block number: %v", err)
}
ethash.MakeCache(block, args[1])
return nil
}
// makedag generates an ethash mining DAG into the provided folder.
func makedag(ctx *cli.Context) error {
args := ctx.Args().Slice()
if len(args) != 2 {
utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
}
block, err := strconv.ParseUint(args[0], 0, 64)
if err != nil {
utils.Fatalf("Invalid block number: %v", err)
}
ethash.MakeDataset(block, args[1])
return nil
}
func printVersion(ctx *cli.Context) error { func printVersion(ctx *cli.Context) error {
git, _ := version.VCS() git, _ := version.VCS()
......
...@@ -39,7 +39,6 @@ import ( ...@@ -39,7 +39,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool"
...@@ -325,54 +324,6 @@ var ( ...@@ -325,54 +324,6 @@ var (
Usage: "Enables serving light clients before syncing", Usage: "Enables serving light clients before syncing",
Category: flags.LightCategory, Category: flags.LightCategory,
} }
// Ethash settings
EthashCacheDirFlag = &flags.DirectoryFlag{
Name: "ethash.cachedir",
Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
Category: flags.EthashCategory,
}
EthashCachesInMemoryFlag = &cli.IntFlag{
Name: "ethash.cachesinmem",
Usage: "Number of recent ethash caches to keep in memory (16MB each)",
Value: ethconfig.Defaults.Ethash.CachesInMem,
Category: flags.EthashCategory,
}
EthashCachesOnDiskFlag = &cli.IntFlag{
Name: "ethash.cachesondisk",
Usage: "Number of recent ethash caches to keep on disk (16MB each)",
Value: ethconfig.Defaults.Ethash.CachesOnDisk,
Category: flags.EthashCategory,
}
EthashCachesLockMmapFlag = &cli.BoolFlag{
Name: "ethash.cacheslockmmap",
Usage: "Lock memory maps of recent ethash caches",
Category: flags.EthashCategory,
}
EthashDatasetDirFlag = &flags.DirectoryFlag{
Name: "ethash.dagdir",
Usage: "Directory to store the ethash mining DAGs",
Value: flags.DirectoryString(ethconfig.Defaults.Ethash.DatasetDir),
Category: flags.EthashCategory,
}
EthashDatasetsInMemoryFlag = &cli.IntFlag{
Name: "ethash.dagsinmem",
Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
Value: ethconfig.Defaults.Ethash.DatasetsInMem,
Category: flags.EthashCategory,
}
EthashDatasetsOnDiskFlag = &cli.IntFlag{
Name: "ethash.dagsondisk",
Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
Value: ethconfig.Defaults.Ethash.DatasetsOnDisk,
Category: flags.EthashCategory,
}
EthashDatasetsLockMmapFlag = &cli.BoolFlag{
Name: "ethash.dagslockmmap",
Usage: "Lock memory maps for recent ethash mining DAGs",
Category: flags.EthashCategory,
}
// Transaction pool settings // Transaction pool settings
TxPoolLocalsFlag = &cli.StringFlag{ TxPoolLocalsFlag = &cli.StringFlag{
Name: "txpool.locals", Name: "txpool.locals",
...@@ -510,22 +461,6 @@ var ( ...@@ -510,22 +461,6 @@ var (
Usage: "Enable mining", Usage: "Enable mining",
Category: flags.MinerCategory, Category: flags.MinerCategory,
} }
MinerThreadsFlag = &cli.IntFlag{
Name: "miner.threads",
Usage: "Number of CPU threads to use for mining",
Value: 0,
Category: flags.MinerCategory,
}
MinerNotifyFlag = &cli.StringFlag{
Name: "miner.notify",
Usage: "Comma separated HTTP URL list to notify of new work packages",
Category: flags.MinerCategory,
}
MinerNotifyFullFlag = &cli.BoolFlag{
Name: "miner.notify.full",
Usage: "Notify with pending block headers instead of work packages",
Category: flags.MinerCategory,
}
MinerGasLimitFlag = &cli.Uint64Flag{ MinerGasLimitFlag = &cli.Uint64Flag{
Name: "miner.gaslimit", Name: "miner.gaslimit",
Usage: "Target gas ceiling for mined blocks", Usage: "Target gas ceiling for mined blocks",
...@@ -554,11 +489,6 @@ var ( ...@@ -554,11 +489,6 @@ var (
Value: ethconfig.Defaults.Miner.Recommit, Value: ethconfig.Defaults.Miner.Recommit,
Category: flags.MinerCategory, Category: flags.MinerCategory,
} }
MinerNoVerifyFlag = &cli.BoolFlag{
Name: "miner.noverify",
Usage: "Disable remote sealing verification",
Category: flags.MinerCategory,
}
MinerNewPayloadTimeout = &cli.DurationFlag{ MinerNewPayloadTimeout = &cli.DurationFlag{
Name: "miner.newpayload-timeout", Name: "miner.newpayload-timeout",
Usage: "Specify the maximum time allowance for creating a new payload", Usage: "Specify the maximum time allowance for creating a new payload",
...@@ -648,11 +578,6 @@ var ( ...@@ -648,11 +578,6 @@ var (
Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
Category: flags.MetricsCategory, Category: flags.MetricsCategory,
} }
FakePoWFlag = &cli.BoolFlag{
Name: "fakepow",
Usage: "Disables proof-of-work verification",
Category: flags.LoggingCategory,
}
NoCompactionFlag = &cli.BoolFlag{ NoCompactionFlag = &cli.BoolFlag{
Name: "nocompaction", Name: "nocompaction",
Usage: "Disables db compaction after import", Usage: "Disables db compaction after import",
...@@ -1604,38 +1529,7 @@ func setTxPool(ctx *cli.Context, cfg *txpool.Config) { ...@@ -1604,38 +1529,7 @@ func setTxPool(ctx *cli.Context, cfg *txpool.Config) {
} }
} }
func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(EthashCacheDirFlag.Name) {
cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name)
}
if ctx.IsSet(EthashDatasetDirFlag.Name) {
cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name)
}
if ctx.IsSet(EthashCachesInMemoryFlag.Name) {
cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name)
}
if ctx.IsSet(EthashCachesOnDiskFlag.Name) {
cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name)
}
if ctx.IsSet(EthashCachesLockMmapFlag.Name) {
cfg.Ethash.CachesLockMmap = ctx.Bool(EthashCachesLockMmapFlag.Name)
}
if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) {
cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name)
}
if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) {
cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name)
}
if ctx.IsSet(EthashDatasetsLockMmapFlag.Name) {
cfg.Ethash.DatasetsLockMmap = ctx.Bool(EthashDatasetsLockMmapFlag.Name)
}
}
func setMiner(ctx *cli.Context, cfg *miner.Config) { func setMiner(ctx *cli.Context, cfg *miner.Config) {
if ctx.IsSet(MinerNotifyFlag.Name) {
cfg.Notify = strings.Split(ctx.String(MinerNotifyFlag.Name), ",")
}
cfg.NotifyFull = ctx.Bool(MinerNotifyFullFlag.Name)
if ctx.IsSet(MinerExtraDataFlag.Name) { if ctx.IsSet(MinerExtraDataFlag.Name) {
cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name)) cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name))
} }
...@@ -1648,9 +1542,6 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) { ...@@ -1648,9 +1542,6 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
if ctx.IsSet(MinerRecommitIntervalFlag.Name) { if ctx.IsSet(MinerRecommitIntervalFlag.Name) {
cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name) cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
} }
if ctx.IsSet(MinerNoVerifyFlag.Name) {
cfg.Noverify = ctx.Bool(MinerNoVerifyFlag.Name)
}
if ctx.IsSet(MinerNewPayloadTimeout.Name) { if ctx.IsSet(MinerNewPayloadTimeout.Name) {
cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name) cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name)
} }
...@@ -1741,7 +1632,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { ...@@ -1741,7 +1632,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
setEtherbase(ctx, cfg) setEtherbase(ctx, cfg)
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
setTxPool(ctx, &cfg.TxPool) setTxPool(ctx, &cfg.TxPool)
setEthash(ctx, cfg)
setMiner(ctx, &cfg.Miner) setMiner(ctx, &cfg.Miner)
setRequiredBlocks(ctx, cfg) setRequiredBlocks(ctx, cfg)
setLes(ctx, cfg) setLes(ctx, cfg)
...@@ -2226,15 +2116,14 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh ...@@ -2226,15 +2116,14 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
gspec = MakeGenesis(ctx) gspec = MakeGenesis(ctx)
chainDb = MakeChainDatabase(ctx, stack, readonly) chainDb = MakeChainDatabase(ctx, stack, readonly)
) )
cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec) config, err := core.LoadChainConfig(chainDb, gspec)
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
ethashConfig := ethconfig.Defaults.Ethash engine, err := ethconfig.CreateConsensusEngine(config, chainDb)
if ctx.Bool(FakePoWFlag.Name) { if err != nil {
ethashConfig.PowMode = ethash.ModeFake Fatalf("%v", err)
} }
engine := ethconfig.CreateConsensusEngine(stack, &ethashConfig, cliqueConfig, nil, false, chainDb)
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
......
...@@ -78,13 +78,13 @@ func (beacon *Beacon) Author(header *types.Header) (common.Address, error) { ...@@ -78,13 +78,13 @@ func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
// VerifyHeader checks whether a header conforms to the consensus rules of the // VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum consensus engine. // stock Ethereum consensus engine.
func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1) reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
if err != nil { if err != nil {
return err return err
} }
if !reached { if !reached {
return beacon.ethone.VerifyHeader(chain, header, seal) return beacon.ethone.VerifyHeader(chain, header)
} }
// Short circuit if the parent is not known // Short circuit if the parent is not known
parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
...@@ -149,13 +149,13 @@ func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers [] ...@@ -149,13 +149,13 @@ func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []
// concurrently. The method returns a quit channel to abort the operations and // concurrently. The method returns a quit channel to abort the operations and
// a results channel to retrieve the async verifications. // a results channel to retrieve the async verifications.
// VerifyHeaders expect the headers to be ordered and continuous. // VerifyHeaders expect the headers to be ordered and continuous.
func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
preHeaders, postHeaders, err := beacon.splitHeaders(chain, headers) preHeaders, postHeaders, err := beacon.splitHeaders(chain, headers)
if err != nil { if err != nil {
return make(chan struct{}), errOut(len(headers), err) return make(chan struct{}), errOut(len(headers), err)
} }
if len(postHeaders) == 0 { if len(postHeaders) == 0 {
return beacon.ethone.VerifyHeaders(chain, headers, seals) return beacon.ethone.VerifyHeaders(chain, headers)
} }
if len(preHeaders) == 0 { if len(preHeaders) == 0 {
return beacon.verifyHeaders(chain, headers, nil) return beacon.verifyHeaders(chain, headers, nil)
...@@ -171,7 +171,7 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [ ...@@ -171,7 +171,7 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
old, new, out = 0, len(preHeaders), 0 old, new, out = 0, len(preHeaders), 0
errors = make([]error, len(headers)) errors = make([]error, len(headers))
done = make([]bool, len(headers)) done = make([]bool, len(headers))
oldDone, oldResult = beacon.ethone.VerifyHeaders(chain, preHeaders, seals[:len(preHeaders)]) oldDone, oldResult = beacon.ethone.VerifyHeaders(chain, preHeaders)
newDone, newResult = beacon.verifyHeaders(chain, postHeaders, preHeaders[len(preHeaders)-1]) newDone, newResult = beacon.verifyHeaders(chain, postHeaders, preHeaders[len(preHeaders)-1])
) )
// Collect the results // Collect the results
......
...@@ -214,14 +214,14 @@ func (c *Clique) Author(header *types.Header) (common.Address, error) { ...@@ -214,14 +214,14 @@ func (c *Clique) Author(header *types.Header) (common.Address, error) {
} }
// VerifyHeader checks whether a header conforms to the consensus rules. // VerifyHeader checks whether a header conforms to the consensus rules.
func (c *Clique) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { func (c *Clique) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
return c.verifyHeader(chain, header, nil) return c.verifyHeader(chain, header, nil)
} }
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
// method returns a quit channel to abort the operations and a results channel to // method returns a quit channel to abort the operations and a results channel to
// retrieve the async verifications (the order is that of the input slice). // retrieve the async verifications (the order is that of the input slice).
func (c *Clique) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { func (c *Clique) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
abort := make(chan struct{}) abort := make(chan struct{})
results := make(chan error, len(headers)) results := make(chan error, len(headers))
......
...@@ -66,15 +66,14 @@ type Engine interface { ...@@ -66,15 +66,14 @@ type Engine interface {
Author(header *types.Header) (common.Address, error) Author(header *types.Header) (common.Address, error)
// VerifyHeader checks whether a header conforms to the consensus rules of a // VerifyHeader checks whether a header conforms to the consensus rules of a
// given engine. Verifying the seal may be done optionally here, or explicitly // given engine.
// via the VerifySeal method. VerifyHeader(chain ChainHeaderReader, header *types.Header) error
VerifyHeader(chain ChainHeaderReader, header *types.Header, seal bool) error
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
// concurrently. The method returns a quit channel to abort the operations and // concurrently. The method returns a quit channel to abort the operations and
// a results channel to retrieve the async verifications (the order is that of // a results channel to retrieve the async verifications (the order is that of
// the input slice). // the input slice).
VerifyHeaders(chain ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) VerifyHeaders(chain ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error)
// VerifyUncles verifies that the given block's uncles conform to the consensus // VerifyUncles verifies that the given block's uncles conform to the consensus
// rules of a given engine. // rules of a given engine.
......
This diff is collapsed.
This diff is collapsed.
// Copyright 2018 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 ethash
import (
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)
var errEthashStopped = errors.New("ethash stopped")
// API exposes ethash related methods for the RPC interface.
type API struct {
ethash *Ethash
}
// GetWork returns a work package for external miner.
//
// The work package consists of 3 strings:
//
// result[0] - 32 bytes hex encoded current block header pow-hash
// result[1] - 32 bytes hex encoded seed hash used for DAG
// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
// result[3] - hex encoded block number
func (api *API) GetWork() ([4]string, error) {
if api.ethash.remote == nil {
return [4]string{}, errors.New("not supported")
}
var (
workCh = make(chan [4]string, 1)
errc = make(chan error, 1)
)
select {
case api.ethash.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
case <-api.ethash.remote.exitCh:
return [4]string{}, errEthashStopped
}
select {
case work := <-workCh:
return work, nil
case err := <-errc:
return [4]string{}, err
}
}
// SubmitWork can be used by external miner to submit their POW solution.
// It returns an indication if the work was accepted.
// Note either an invalid solution, a stale work a non-existent work will return false.
func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) bool {
if api.ethash.remote == nil {
return false
}
var errc = make(chan error, 1)
select {
case api.ethash.remote.submitWorkCh <- &mineResult{
nonce: nonce,
mixDigest: digest,
hash: hash,
errc: errc,
}:
case <-api.ethash.remote.exitCh:
return false
}
err := <-errc
return err == nil
}
// SubmitHashrate can be used for remote miners to submit their hash rate.
// This enables the node to report the combined hash rate of all miners
// which submit work through this node.
//
// It accepts the miner hash rate and an identifier which must be unique
// between nodes.
func (api *API) SubmitHashrate(rate hexutil.Uint64, id common.Hash) bool {
if api.ethash.remote == nil {
return false
}
var done = make(chan struct{}, 1)
select {
case api.ethash.remote.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}:
case <-api.ethash.remote.exitCh:
return false
}
// Block until hash rate submitted successfully.
<-done
return true
}
// GetHashrate returns the current hashrate for local CPU miner and remote miner.
func (api *API) GetHashrate() uint64 {
return uint64(api.ethash.Hashrate())
}
...@@ -17,11 +17,9 @@ ...@@ -17,11 +17,9 @@
package ethash package ethash
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"runtime"
"time" "time"
mapset "github.com/deckarep/golang-set/v2" mapset "github.com/deckarep/golang-set/v2"
...@@ -89,9 +87,6 @@ var ( ...@@ -89,9 +87,6 @@ var (
errDuplicateUncle = errors.New("duplicate uncle") errDuplicateUncle = errors.New("duplicate uncle")
errUncleIsAncestor = errors.New("uncle is ancestor") errUncleIsAncestor = errors.New("uncle is ancestor")
errDanglingUncle = errors.New("uncle's parent is not ancestor") errDanglingUncle = errors.New("uncle's parent is not ancestor")
errInvalidDifficulty = errors.New("non-positive difficulty")
errInvalidMixDigest = errors.New("invalid mix digest")
errInvalidPoW = errors.New("invalid proof-of-work")
) )
// Author implements consensus.Engine, returning the header's coinbase as the // Author implements consensus.Engine, returning the header's coinbase as the
...@@ -102,11 +97,7 @@ func (ethash *Ethash) Author(header *types.Header) (common.Address, error) { ...@@ -102,11 +97,7 @@ func (ethash *Ethash) Author(header *types.Header) (common.Address, error) {
// VerifyHeader checks whether a header conforms to the consensus rules of the // VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum ethash engine. // stock Ethereum ethash engine.
func (ethash *Ethash) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { func (ethash *Ethash) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
// If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake {
return nil
}
// Short circuit if the header is known, or its parent not // Short circuit if the header is known, or its parent not
number := header.Number.Uint64() number := header.Number.Uint64()
if chain.GetHeader(header.Hash(), number) != nil { if chain.GetHeader(header.Hash(), number) != nil {
...@@ -117,93 +108,54 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainHeaderReader, header *ty ...@@ -117,93 +108,54 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainHeaderReader, header *ty
return consensus.ErrUnknownAncestor return consensus.ErrUnknownAncestor
} }
// Sanity checks passed, do a proper verification // Sanity checks passed, do a proper verification
return ethash.verifyHeader(chain, header, parent, false, seal, time.Now().Unix()) return ethash.verifyHeader(chain, header, parent, false, time.Now().Unix())
} }
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
// concurrently. The method returns a quit channel to abort the operations and // concurrently. The method returns a quit channel to abort the operations and
// a results channel to retrieve the async verifications. // a results channel to retrieve the async verifications.
func (ethash *Ethash) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { func (ethash *Ethash) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
// If we're running a full engine faking, accept any input as valid // If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake || len(headers) == 0 { if ethash.fakeFull || len(headers) == 0 {
abort, results := make(chan struct{}), make(chan error, len(headers)) abort, results := make(chan struct{}), make(chan error, len(headers))
for i := 0; i < len(headers); i++ { for i := 0; i < len(headers); i++ {
results <- nil results <- nil
} }
return abort, results return abort, results
} }
abort := make(chan struct{})
results := make(chan error, len(headers))
unixNow := time.Now().Unix()
// Spawn as many workers as allowed threads
workers := runtime.GOMAXPROCS(0)
if len(headers) < workers {
workers = len(headers)
}
// Create a task channel and spawn the verifiers
var (
inputs = make(chan int)
done = make(chan int, workers)
errors = make([]error, len(headers))
abort = make(chan struct{})
unixNow = time.Now().Unix()
)
for i := 0; i < workers; i++ {
go func() { go func() {
for index := range inputs { for i, header := range headers {
errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index, unixNow) var parent *types.Header
done <- index if i == 0 {
parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
} else if headers[i-1].Hash() == headers[i].ParentHash {
parent = headers[i-1]
} }
}() var err error
if parent == nil {
err = consensus.ErrUnknownAncestor
} else {
err = ethash.verifyHeader(chain, header, parent, false, unixNow)
} }
errorsOut := make(chan error, len(headers))
go func() {
defer close(inputs)
var (
in, out = 0, 0
checked = make([]bool, len(headers))
inputs = inputs
)
for {
select { select {
case inputs <- in:
if in++; in == len(headers) {
// Reached end of headers. Stop sending to workers.
inputs = nil
}
case index := <-done:
for checked[index] = true; checked[out]; out++ {
errorsOut <- errors[out]
if out == len(headers)-1 {
return
}
}
case <-abort: case <-abort:
return return
case results <- err:
} }
} }
}() }()
return abort, errorsOut return abort, results
}
func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, index int, unixNow int64) error {
var parent *types.Header
if index == 0 {
parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
} else if headers[index-1].Hash() == headers[index].ParentHash {
parent = headers[index-1]
}
if parent == nil {
return consensus.ErrUnknownAncestor
}
return ethash.verifyHeader(chain, headers[index], parent, false, seals[index], unixNow)
} }
// VerifyUncles verifies that the given block's uncles conform to the consensus // VerifyUncles verifies that the given block's uncles conform to the consensus
// rules of the stock Ethereum ethash engine. // rules of the stock Ethereum ethash engine.
func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
// If we're running a full engine faking, accept any input as valid // If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake { if ethash.fakeFull {
return nil return nil
} }
// Verify that there are at most 2 uncles included in this block // Verify that there are at most 2 uncles included in this block
...@@ -255,7 +207,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo ...@@ -255,7 +207,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
return errDanglingUncle return errDanglingUncle
} }
if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true, time.Now().Unix()); err != nil { if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, time.Now().Unix()); err != nil {
return err return err
} }
} }
...@@ -265,7 +217,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo ...@@ -265,7 +217,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
// verifyHeader checks whether a header conforms to the consensus rules of the // verifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum ethash engine. // stock Ethereum ethash engine.
// See YP section 4.3.4. "Block Header Validity" // See YP section 4.3.4. "Block Header Validity"
func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool, seal bool, unixNow int64) error { func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool, unixNow int64) error {
// Ensure that the header's extra-data section is of a reasonable size // Ensure that the header's extra-data section is of a reasonable size
if uint64(len(header.Extra)) > params.MaximumExtraDataSize { if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
...@@ -316,11 +268,12 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa ...@@ -316,11 +268,12 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if chain.Config().IsCancun(header.Time) { if chain.Config().IsCancun(header.Time) {
return fmt.Errorf("ethash does not support cancun fork") return fmt.Errorf("ethash does not support cancun fork")
} }
// Verify the engine specific seal securing the block // Add some fake checks for tests
if seal { if ethash.fakeDelay != nil {
if err := ethash.verifySeal(chain, header, false); err != nil { time.Sleep(*ethash.fakeDelay)
return err
} }
if ethash.fakeFail != nil && *ethash.fakeFail == header.Number.Uint64() {
return errors.New("invalid tester pow")
} }
// If all checks passed, validate any special fields for hard forks // If all checks passed, validate any special fields for hard forks
if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil { if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil {
...@@ -521,72 +474,6 @@ var FrontierDifficultyCalculator = calcDifficultyFrontier ...@@ -521,72 +474,6 @@ var FrontierDifficultyCalculator = calcDifficultyFrontier
var HomesteadDifficultyCalculator = calcDifficultyHomestead var HomesteadDifficultyCalculator = calcDifficultyHomestead
var DynamicDifficultyCalculator = makeDifficultyCalculator var DynamicDifficultyCalculator = makeDifficultyCalculator
// verifySeal checks whether a block satisfies the PoW difficulty requirements,
// either using the usual ethash cache for it, or alternatively using a full DAG
// to make remote mining fast.
func (ethash *Ethash) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, fulldag bool) error {
// If we're running a fake PoW, accept any seal as valid
if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake {
time.Sleep(ethash.fakeDelay)
if ethash.fakeFail == header.Number.Uint64() {
return errInvalidPoW
}
return nil
}
// If we're running a shared PoW, delegate verification to it
if ethash.shared != nil {
return ethash.shared.verifySeal(chain, header, fulldag)
}
// Ensure that we have a valid difficulty for the block
if header.Difficulty.Sign() <= 0 {
return errInvalidDifficulty
}
// Recompute the digest and PoW values
number := header.Number.Uint64()
var (
digest []byte
result []byte
)
// If fast-but-heavy PoW verification was requested, use an ethash dataset
if fulldag {
dataset := ethash.dataset(number, true)
if dataset.generated() {
digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64())
// Datasets are unmapped in a finalizer. Ensure that the dataset stays alive
// until after the call to hashimotoFull so it's not unmapped while being used.
runtime.KeepAlive(dataset)
} else {
// Dataset not yet generated, don't hang, use a cache instead
fulldag = false
}
}
// If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache
if !fulldag {
cache := ethash.cache(number)
size := datasetSize(number)
if ethash.config.PowMode == ModeTest {
size = 32 * 1024
}
digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64())
// Caches are unmapped in a finalizer. Ensure that the cache stays alive
// until after the call to hashimotoLight so it's not unmapped while being used.
runtime.KeepAlive(cache)
}
// Verify the calculated values against the ones provided in the header
if !bytes.Equal(header.MixDigest[:], digest) {
return errInvalidMixDigest
}
target := new(big.Int).Div(two256, header.Difficulty)
if new(big.Int).SetBytes(result).Cmp(target) > 0 {
return errInvalidPoW
}
return nil
}
// Prepare implements consensus.Engine, initializing the difficulty field of a // Prepare implements consensus.Engine, initializing the difficulty field of a
// header to conform to the ethash protocol. The changes are done inline. // header to conform to the ethash protocol. The changes are done inline.
func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
......
This diff is collapsed.
// Copyright 2017 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 ethash
import (
"math/big"
"math/rand"
"os"
"sync"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)
// Tests that ethash works correctly in test mode.
func TestTestMode(t *testing.T) {
header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)}
ethash := NewTester(nil, false)
defer ethash.Close()
results := make(chan *types.Block)
err := ethash.Seal(nil, types.NewBlockWithHeader(header), results, nil)
if err != nil {
t.Fatalf("failed to seal block: %v", err)
}
select {
case block := <-results:
header.Nonce = types.EncodeNonce(block.Nonce())
header.MixDigest = block.MixDigest()
if err := ethash.verifySeal(nil, header, false); err != nil {
t.Fatalf("unexpected verification error: %v", err)
}
case <-time.NewTimer(4 * time.Second).C:
t.Error("sealing result timeout")
}
}
// This test checks that cache lru logic doesn't crash under load.
// It reproduces https://github.com/ethereum/go-ethereum/issues/14943
func TestCacheFileEvict(t *testing.T) {
// TODO: t.TempDir fails to remove the directory on Windows
// \AppData\Local\Temp\1\TestCacheFileEvict2179435125\001\cache-R23-0000000000000000: Access is denied.
tmpdir, err := os.MkdirTemp("", "ethash-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
config := Config{
CachesInMem: 3,
CachesOnDisk: 10,
CacheDir: tmpdir,
PowMode: ModeTest,
}
e := New(config, nil, false)
defer e.Close()
workers := 8
epochs := 100
var wg sync.WaitGroup
wg.Add(workers)
for i := 0; i < workers; i++ {
go verifyTest(&wg, e, i, epochs)
}
wg.Wait()
}
func verifyTest(wg *sync.WaitGroup, e *Ethash, workerIndex, epochs int) {
defer wg.Done()
const wiggle = 4 * epochLength
r := rand.New(rand.NewSource(int64(workerIndex)))
for epoch := 0; epoch < epochs; epoch++ {
block := int64(epoch)*epochLength - wiggle/2 + r.Int63n(wiggle)
if block < 0 {
block = 0
}
header := &types.Header{Number: big.NewInt(block), Difficulty: big.NewInt(100)}
e.verifySeal(nil, header, false)
}
}
func TestRemoteSealer(t *testing.T) {
ethash := NewTester(nil, false)
defer ethash.Close()
api := &API{ethash}
if _, err := api.GetWork(); err != errNoMiningWork {
t.Error("expect to return an error indicate there is no mining work")
}
header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)}
block := types.NewBlockWithHeader(header)
sealhash := ethash.SealHash(header)
// Push new work.
results := make(chan *types.Block)
ethash.Seal(nil, block, results, nil)
var (
work [4]string
err error
)
if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() {
t.Error("expect to return a mining work has same hash")
}
if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res {
t.Error("expect to return false when submit a fake solution")
}
// Push new block with same block number to replace the original one.
header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)}
block = types.NewBlockWithHeader(header)
sealhash = ethash.SealHash(header)
ethash.Seal(nil, block, results, nil)
if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() {
t.Error("expect to return the latest pushed work")
}
}
func TestHashrate(t *testing.T) {
var (
hashrate = []hexutil.Uint64{100, 200, 300}
expect uint64
ids = []common.Hash{common.HexToHash("a"), common.HexToHash("b"), common.HexToHash("c")}
)
ethash := NewTester(nil, false)
defer ethash.Close()
if tot := ethash.Hashrate(); tot != 0 {
t.Error("expect the result should be zero")
}
api := &API{ethash}
for i := 0; i < len(hashrate); i += 1 {
if res := api.SubmitHashrate(hashrate[i], ids[i]); !res {
t.Error("remote miner submit hashrate failed")
}
expect += uint64(hashrate[i])
}
if tot := ethash.Hashrate(); tot != float64(expect) {
t.Error("expect total hashrate should be same")
}
}
func TestClosedRemoteSealer(t *testing.T) {
ethash := NewTester(nil, false)
time.Sleep(1 * time.Second) // ensure exit channel is listening
ethash.Close()
api := &API{ethash}
if _, err := api.GetWork(); err != errEthashStopped {
t.Error("expect to return an error to indicate ethash is stopped")
}
if res := api.SubmitHashrate(hexutil.Uint64(100), common.HexToHash("a")); res {
t.Error("expect to return false when submit hashrate to a stopped ethash")
}
}
// Copyright 2021 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/>.
//go:build linux
// +build linux
package ethash
import (
"os"
"golang.org/x/sys/unix"
)
// ensureSize expands the file to the given size. This is to prevent runtime
// errors later on, if the underlying file expands beyond the disk capacity,
// even though it ostensibly is already expanded, but due to being sparse
// does not actually occupy the full declared size on disk.
func ensureSize(f *os.File, size int64) error {
// Docs: https://www.man7.org/linux/man-pages/man2/fallocate.2.html
return unix.Fallocate(int(f.Fd()), 0, 0, size)
}
// Copyright 2021 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/>.
//go:build !linux
// +build !linux
package ethash
import (
"os"
)
// ensureSize expands the file to the given size. This is to prevent runtime
// errors later on, if the underlying file expands beyond the disk capacity,
// even though it ostensibly is already expanded, but due to being sparse
// does not actually occupy the full declared size on disk.
func ensureSize(f *os.File, size int64) error {
// On systems which do not support fallocate, we merely truncate it.
// More robust alternatives would be to
// - Use posix_fallocate, or
// - explicitly fill the file with zeroes.
return f.Truncate(size)
}
This diff is collapsed.
This diff is collapsed.
...@@ -26,7 +26,6 @@ import ( ...@@ -26,7 +26,6 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/console/prompt" "github.com/ethereum/go-ethereum/console/prompt"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
...@@ -99,9 +98,6 @@ func newTester(t *testing.T, confOverride func(*ethconfig.Config)) *tester { ...@@ -99,9 +98,6 @@ func newTester(t *testing.T, confOverride func(*ethconfig.Config)) *tester {
Miner: miner.Config{ Miner: miner.Config{
Etherbase: common.HexToAddress(testAddress), Etherbase: common.HexToAddress(testAddress),
}, },
Ethash: ethash.Config{
PowMode: ethash.ModeTest,
},
} }
if confOverride != nil { if confOverride != nil {
confOverride(ethConf) confOverride(ethConf)
......
...@@ -55,10 +55,10 @@ func TestHeaderVerification(t *testing.T) { ...@@ -55,10 +55,10 @@ func TestHeaderVerification(t *testing.T) {
if valid { if valid {
engine := ethash.NewFaker() engine := ethash.NewFaker()
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]})
} else { } else {
engine := ethash.NewFakeFailer(headers[i].Number.Uint64()) engine := ethash.NewFakeFailer(headers[i].Number.Uint64())
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]})
} }
// Wait for the verification result // Wait for the verification result
select { select {
...@@ -164,7 +164,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) { ...@@ -164,7 +164,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
// Verify the blocks before the merging // Verify the blocks before the merging
for i := 0; i < len(preBlocks); i++ { for i := 0; i < len(preBlocks); i++ {
_, results := engine.VerifyHeaders(chain, []*types.Header{preHeaders[i]}, []bool{true}) _, results := engine.VerifyHeaders(chain, []*types.Header{preHeaders[i]})
// Wait for the verification result // Wait for the verification result
select { select {
case result := <-results: case result := <-results:
...@@ -189,7 +189,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) { ...@@ -189,7 +189,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
// Verify the blocks after the merging // Verify the blocks after the merging
for i := 0; i < len(postBlocks); i++ { for i := 0; i < len(postBlocks); i++ {
_, results := engine.VerifyHeaders(chain, []*types.Header{postHeaders[i]}, []bool{true}) _, results := engine.VerifyHeaders(chain, []*types.Header{postHeaders[i]})
// Wait for the verification result // Wait for the verification result
select { select {
case result := <-results: case result := <-results:
...@@ -209,19 +209,14 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) { ...@@ -209,19 +209,14 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
} }
// Verify the blocks with pre-merge blocks and post-merge blocks // Verify the blocks with pre-merge blocks and post-merge blocks
var ( var headers []*types.Header
headers []*types.Header
seals []bool
)
for _, block := range preBlocks { for _, block := range preBlocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
seals = append(seals, true)
} }
for _, block := range postBlocks { for _, block := range postBlocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
seals = append(seals, true)
} }
_, results := engine.VerifyHeaders(chain, headers, seals) _, results := engine.VerifyHeaders(chain, headers)
for i := 0; i < len(headers); i++ { for i := 0; i < len(headers); i++ {
select { select {
case result := <-results: case result := <-results:
...@@ -252,11 +247,8 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) { ...@@ -252,11 +247,8 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
_, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 8, nil) _, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 8, nil)
) )
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
seals := make([]bool, len(blocks))
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
seals[i] = true
} }
// Set the number of threads to verify on // Set the number of threads to verify on
old := runtime.GOMAXPROCS(threads) old := runtime.GOMAXPROCS(threads)
...@@ -269,11 +261,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) { ...@@ -269,11 +261,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
if valid { if valid {
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals) _, results = chain.engine.VerifyHeaders(chain, headers)
chain.Stop() chain.Stop()
} else { } else {
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil) chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals) _, results = chain.engine.VerifyHeaders(chain, headers)
chain.Stop() chain.Stop()
} }
// Wait for all the verification results // Wait for all the verification results
...@@ -322,11 +314,8 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) { ...@@ -322,11 +314,8 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
_, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, nil) _, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, nil)
) )
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
seals := make([]bool, len(blocks))
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
seals[i] = true
} }
// Set the number of threads to verify on // Set the number of threads to verify on
old := runtime.GOMAXPROCS(threads) old := runtime.GOMAXPROCS(threads)
...@@ -336,7 +325,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) { ...@@ -336,7 +325,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil) chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
abort, results := chain.engine.VerifyHeaders(chain, headers, seals) abort, results := chain.engine.VerifyHeaders(chain, headers)
close(abort) close(abort)
// Deplete the results channel // Deplete the results channel
......
...@@ -365,7 +365,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis ...@@ -365,7 +365,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
// The first thing the node will do is reconstruct the verification data for // The first thing the node will do is reconstruct the verification data for
// the head block (ethash cache or clique voting snapshot). Might as well do // the head block (ethash cache or clique voting snapshot). Might as well do
// it in advance. // it in advance.
bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true) bc.engine.VerifyHeader(bc, bc.CurrentHeader())
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
for hash := range BadHashes { for hash := range BadHashes {
...@@ -1522,7 +1522,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { ...@@ -1522,7 +1522,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
return 0, errChainStopped return 0, errChainStopped
} }
defer bc.chainmu.Unlock() defer bc.chainmu.Unlock()
return bc.insertChain(chain, true, true) return bc.insertChain(chain, true)
} }
// insertChain is the internal implementation of InsertChain, which assumes that // insertChain is the internal implementation of InsertChain, which assumes that
...@@ -1533,7 +1533,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { ...@@ -1533,7 +1533,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
// racey behaviour. If a sidechain import is in progress, and the historic state // racey behaviour. If a sidechain import is in progress, and the historic state
// is imported, but then new canon-head is added before the actual sidechain // is imported, but then new canon-head is added before the actual sidechain
// completes, then the historic state could be pruned again // completes, then the historic state could be pruned again
func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) (int, error) { func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) {
// If the chain is terminating, don't even bother starting up. // If the chain is terminating, don't even bother starting up.
if bc.insertStopped() { if bc.insertStopped() {
return 0, nil return 0, nil
...@@ -1554,13 +1554,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) ...@@ -1554,13 +1554,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
}() }()
// Start the parallel header verifier // Start the parallel header verifier
headers := make([]*types.Header, len(chain)) headers := make([]*types.Header, len(chain))
seals := make([]bool, len(chain))
for i, block := range chain { for i, block := range chain {
headers[i] = block.Header() headers[i] = block.Header()
seals[i] = verifySeals
} }
abort, results := bc.engine.VerifyHeaders(bc, headers, seals) abort, results := bc.engine.VerifyHeaders(bc, headers)
defer close(abort) defer close(abort)
// Peek the error for the first block to decide the directing import logic // Peek the error for the first block to decide the directing import logic
...@@ -1981,7 +1978,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i ...@@ -1981,7 +1978,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
// memory here. // memory here.
if len(blocks) >= 2048 || memory > 64*1024*1024 { if len(blocks) >= 2048 || memory > 64*1024*1024 {
log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64()) log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
if _, err := bc.insertChain(blocks, false, true); err != nil { if _, err := bc.insertChain(blocks, true); err != nil {
return 0, err return 0, err
} }
blocks, memory = blocks[:0], 0 blocks, memory = blocks[:0], 0
...@@ -1995,7 +1992,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i ...@@ -1995,7 +1992,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
} }
if len(blocks) > 0 { if len(blocks) > 0 {
log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64()) log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
return bc.insertChain(blocks, false, true) return bc.insertChain(blocks, true)
} }
return 0, nil return 0, nil
} }
...@@ -2038,7 +2035,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error) ...@@ -2038,7 +2035,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
} else { } else {
b = bc.GetBlock(hashes[i], numbers[i]) b = bc.GetBlock(hashes[i], numbers[i])
} }
if _, err := bc.insertChain(types.Blocks{b}, false, false); err != nil { if _, err := bc.insertChain(types.Blocks{b}, false); err != nil {
return b.ParentHash(), err return b.ParentHash(), err
} }
} }
...@@ -2242,7 +2239,7 @@ func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error { ...@@ -2242,7 +2239,7 @@ func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error {
} }
defer bc.chainmu.Unlock() defer bc.chainmu.Unlock()
_, err := bc.insertChain(types.Blocks{block}, true, false) _, err := bc.insertChain(types.Blocks{block}, false)
return err return err
} }
...@@ -2462,17 +2459,12 @@ Receipts: %v ...@@ -2462,17 +2459,12 @@ Receipts: %v
// InsertHeaderChain attempts to insert the given header chain in to the local // InsertHeaderChain attempts to insert the given header chain in to the local
// chain, possibly creating a reorg. If an error is returned, it will return the // chain, possibly creating a reorg. If an error is returned, it will return the
// index number of the failing header as well an error describing what went wrong. // index number of the failing header as well an error describing what went wrong.
// func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
// The verify parameter can be used to fine tune whether nonce verification
// should be done or not. The reason behind the optional check is because some
// of the header retrieval mechanisms already need to verify nonces, as well as
// because nonces can be verified sparsely, not needing to check each.
func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
if len(chain) == 0 { if len(chain) == 0 {
return 0, nil return 0, nil
} }
start := time.Now() start := time.Now()
if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil { if i, err := bc.hc.ValidateHeaderChain(chain); err != nil {
return i, err return i, err
} }
......
...@@ -74,7 +74,7 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *G ...@@ -74,7 +74,7 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *G
} }
// Header-only chain requested // Header-only chain requested
genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed) genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed)
_, err := blockchain.InsertHeaderChain(headers, 1) _, err := blockchain.InsertHeaderChain(headers)
return genDb, genesis, blockchain, err return genDb, genesis, blockchain, err
} }
...@@ -115,7 +115,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara ...@@ -115,7 +115,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
} }
} else { } else {
headerChainB = makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed) headerChainB = makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed)
if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { if _, err := blockchain2.InsertHeaderChain(headerChainB); err != nil {
t.Fatalf("failed to insert forking chain: %v", err) t.Fatalf("failed to insert forking chain: %v", err)
} }
} }
...@@ -148,7 +148,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara ...@@ -148,7 +148,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
for _, block := range chain { for _, block := range chain {
// Try and process the block // Try and process the block
err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) err := blockchain.engine.VerifyHeader(blockchain, block.Header())
if err == nil { if err == nil {
err = blockchain.validator.ValidateBody(block) err = blockchain.validator.ValidateBody(block)
} }
...@@ -187,7 +187,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { ...@@ -187,7 +187,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error {
for _, header := range chain { for _, header := range chain {
// Try and validate the header // Try and validate the header
if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { if err := blockchain.engine.VerifyHeader(blockchain, header); err != nil {
return err return err
} }
// Manually insert the header into the database, but don't reorganise (allows subsequent testing) // Manually insert the header into the database, but don't reorganise (allows subsequent testing)
...@@ -252,7 +252,7 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b ...@@ -252,7 +252,7 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b
} }
} else { } else {
headerChainB := makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed) headerChainB := makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed)
if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { if _, err := blockchain2.InsertHeaderChain(headerChainB); err != nil {
t.Fatalf("failed to insert forking chain: %v", err) t.Fatalf("failed to insert forking chain: %v", err)
} }
if blockchain2.CurrentHeader().Number.Uint64() != headerChainB[len(headerChainB)-1].Number.Uint64() { if blockchain2.CurrentHeader().Number.Uint64() != headerChainB[len(headerChainB)-1].Number.Uint64() {
...@@ -549,10 +549,10 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) { ...@@ -549,10 +549,10 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) {
for i, block := range diffBlocks { for i, block := range diffBlocks {
diffHeaders[i] = block.Header() diffHeaders[i] = block.Header()
} }
if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { if _, err := blockchain.InsertHeaderChain(easyHeaders); err != nil {
t.Fatalf("failed to insert easy chain: %v", err) t.Fatalf("failed to insert easy chain: %v", err)
} }
if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { if _, err := blockchain.InsertHeaderChain(diffHeaders); err != nil {
t.Fatalf("failed to insert difficult chain: %v", err) t.Fatalf("failed to insert difficult chain: %v", err)
} }
} }
...@@ -613,7 +613,7 @@ func testBadHashes(t *testing.T, full bool) { ...@@ -613,7 +613,7 @@ func testBadHashes(t *testing.T, full bool) {
BadHashes[headers[2].Hash()] = true BadHashes[headers[2].Hash()] = true
defer func() { delete(BadHashes, headers[2].Hash()) }() defer func() { delete(BadHashes, headers[2].Hash()) }()
_, err = blockchain.InsertHeaderChain(headers, 1) _, err = blockchain.InsertHeaderChain(headers)
} }
if !errors.Is(err, ErrBannedHash) { if !errors.Is(err, ErrBannedHash) {
t.Errorf("error mismatch: have: %v, want: %v", err, ErrBannedHash) t.Errorf("error mismatch: have: %v, want: %v", err, ErrBannedHash)
...@@ -645,7 +645,7 @@ func testReorgBadHashes(t *testing.T, full bool) { ...@@ -645,7 +645,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
BadHashes[blocks[3].Header().Hash()] = true BadHashes[blocks[3].Header().Hash()] = true
defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() defer func() { delete(BadHashes, blocks[3].Header().Hash()) }()
} else { } else {
if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { if _, err = blockchain.InsertHeaderChain(headers); err != nil {
t.Errorf("failed to import headers: %v", err) t.Errorf("failed to import headers: %v", err)
} }
if blockchain.CurrentHeader().Hash() != headers[3].Hash() { if blockchain.CurrentHeader().Hash() != headers[3].Hash() {
...@@ -711,7 +711,7 @@ func testInsertNonceError(t *testing.T, full bool) { ...@@ -711,7 +711,7 @@ func testInsertNonceError(t *testing.T, full bool) {
blockchain.engine = ethash.NewFakeFailer(failNum) blockchain.engine = ethash.NewFakeFailer(failNum)
blockchain.hc.engine = blockchain.engine blockchain.hc.engine = blockchain.engine
failRes, err = blockchain.InsertHeaderChain(headers, 1) failRes, err = blockchain.InsertHeaderChain(headers)
} }
// Check that the returned error indicates the failure // Check that the returned error indicates the failure
if failRes != failAt { if failRes != failAt {
...@@ -785,7 +785,7 @@ func TestFastVsFullChains(t *testing.T) { ...@@ -785,7 +785,7 @@ func TestFastVsFullChains(t *testing.T) {
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
} }
if n, err := fast.InsertHeaderChain(headers, 1); err != nil { if n, err := fast.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil {
...@@ -800,7 +800,7 @@ func TestFastVsFullChains(t *testing.T) { ...@@ -800,7 +800,7 @@ func TestFastVsFullChains(t *testing.T) {
ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop() defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { if n, err := ancient.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil {
...@@ -931,7 +931,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { ...@@ -931,7 +931,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
} }
if n, err := fast.InsertHeaderChain(headers, 1); err != nil { if n, err := fast.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil {
...@@ -947,7 +947,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { ...@@ -947,7 +947,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop() defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { if n, err := ancient.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil {
...@@ -964,7 +964,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { ...@@ -964,7 +964,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
lightDb := makeDb() lightDb := makeDb()
defer lightDb.Close() defer lightDb.Close()
light, _ := NewBlockChain(lightDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) light, _ := NewBlockChain(lightDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := light.InsertHeaderChain(headers, 1); err != nil { if n, err := light.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
defer light.Stop() defer light.Stop()
...@@ -1781,7 +1781,7 @@ func TestBlockchainRecovery(t *testing.T) { ...@@ -1781,7 +1781,7 @@ func TestBlockchainRecovery(t *testing.T) {
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
} }
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { if n, err := ancient.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil {
...@@ -1850,7 +1850,7 @@ func TestInsertReceiptChainRollback(t *testing.T) { ...@@ -1850,7 +1850,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
for i, block := range canonblocks { for i, block := range canonblocks {
canonHeaders[i] = block.Header() canonHeaders[i] = block.Header()
} }
if _, err = ancientChain.InsertHeaderChain(canonHeaders, 1); err != nil { if _, err = ancientChain.InsertHeaderChain(canonHeaders); err != nil {
t.Fatal("can't import canon headers:", err) t.Fatal("can't import canon headers:", err)
} }
...@@ -2128,7 +2128,7 @@ func testInsertKnownChainData(t *testing.T, typ string) { ...@@ -2128,7 +2128,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
for _, block := range blocks { for _, block := range blocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
} }
_, err := chain.InsertHeaderChain(headers, 1) _, err := chain.InsertHeaderChain(headers)
return err return err
} }
asserter = func(t *testing.T, block *types.Block) { asserter = func(t *testing.T, block *types.Block) {
...@@ -2142,7 +2142,7 @@ func testInsertKnownChainData(t *testing.T, typ string) { ...@@ -2142,7 +2142,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
for _, block := range blocks { for _, block := range blocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
} }
_, err := chain.InsertHeaderChain(headers, 1) _, err := chain.InsertHeaderChain(headers)
if err != nil { if err != nil {
return err return err
} }
...@@ -2299,7 +2299,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i ...@@ -2299,7 +2299,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
for _, block := range blocks { for _, block := range blocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
} }
i, err := chain.InsertHeaderChain(headers, 1) i, err := chain.InsertHeaderChain(headers)
if err != nil { if err != nil {
return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err) return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err)
} }
...@@ -2316,7 +2316,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i ...@@ -2316,7 +2316,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
for _, block := range blocks { for _, block := range blocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
} }
i, err := chain.InsertHeaderChain(headers, 1) i, err := chain.InsertHeaderChain(headers)
if err != nil { if err != nil {
return fmt.Errorf("index %d: %w", i, err) return fmt.Errorf("index %d: %w", i, err)
} }
...@@ -2492,7 +2492,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { ...@@ -2492,7 +2492,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
for i, block := range canonblocks { for i, block := range canonblocks {
canonHeaders[i] = block.Header() canonHeaders[i] = block.Header()
} }
if n, err := chain.InsertHeaderChain(canonHeaders, 0); err != nil { if n, err := chain.InsertHeaderChain(canonHeaders); err != nil {
t.Fatalf("header %d: failed to insert into chain: %v", n, err) t.Fatalf("header %d: failed to insert into chain: %v", n, err)
} }
canonNum := chain.CurrentHeader().Number.Uint64() canonNum := chain.CurrentHeader().Number.Uint64()
...@@ -2501,7 +2501,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { ...@@ -2501,7 +2501,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
for i, block := range sideblocks { for i, block := range sideblocks {
sideHeaders[i] = block.Header() sideHeaders[i] = block.Header()
} }
if n, err := chain.InsertHeaderChain(sideHeaders, 0); err != nil { if n, err := chain.InsertHeaderChain(sideHeaders); err != nil {
t.Fatalf("header %d: failed to insert into chain: %v", n, err) t.Fatalf("header %d: failed to insert into chain: %v", n, err)
} }
head := chain.CurrentHeader() head := chain.CurrentHeader()
...@@ -2692,7 +2692,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) { ...@@ -2692,7 +2692,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
} }
if n, err := chain.InsertHeaderChain(headers, 0); err != nil { if n, err := chain.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
// The indices before ancient-N(32) should be ignored. After that all blocks should be indexed. // The indices before ancient-N(32) should be ignored. After that all blocks should be indexed.
......
...@@ -379,11 +379,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen ...@@ -379,11 +379,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
return newcfg, stored, nil return newcfg, stored, nil
} }
// LoadCliqueConfig loads the stored clique config if the chain config // LoadChainConfig loads the stored chain config if it is already present in
// is already present in database, otherwise, return the config in the // database, otherwise, return the config in the provided genesis specification.
// provided genesis specification. Note the returned clique config can func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, error) {
// be nil if we are not in the clique network.
func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig, error) {
// Load the stored chain config from the database. It can be nil // Load the stored chain config from the database. It can be nil
// in case the database is empty. Notably, we only care about the // in case the database is empty. Notably, we only care about the
// chain config corresponds to the canonical chain. // chain config corresponds to the canonical chain.
...@@ -391,10 +389,10 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig ...@@ -391,10 +389,10 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig
if stored != (common.Hash{}) { if stored != (common.Hash{}) {
storedcfg := rawdb.ReadChainConfig(db, stored) storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg != nil { if storedcfg != nil {
return storedcfg.Clique, nil return storedcfg, nil
} }
} }
// Load the clique config from the provided genesis specification. // Load the config from the provided genesis specification
if genesis != nil { if genesis != nil {
// Reject invalid genesis spec without valid chain config // Reject invalid genesis spec without valid chain config
if genesis.Config == nil { if genesis.Config == nil {
...@@ -407,12 +405,11 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig ...@@ -407,12 +405,11 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig
if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored { if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored {
return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()} return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()}
} }
return genesis.Config.Clique, nil return genesis.Config, nil
} }
// There is no stored chain config and no new config provided, // There is no stored chain config and no new config provided,
// In this case the default chain config(mainnet) will be used, // In this case the default chain config(mainnet) will be used
// namely ethash is the specified consensus engine, return nil. return params.MainnetChainConfig, nil
return nil, nil
} }
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
......
This diff is collapsed.
This diff is collapsed.
...@@ -397,8 +397,8 @@ func (b *EthAPIBackend) Miner() *miner.Miner { ...@@ -397,8 +397,8 @@ func (b *EthAPIBackend) Miner() *miner.Miner {
return b.eth.Miner() return b.eth.Miner()
} }
func (b *EthAPIBackend) StartMining(threads int) error { func (b *EthAPIBackend) StartMining() error {
return b.eth.StartMining(threads) return b.eth.StartMining()
} }
func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) {
......
This diff is collapsed.
...@@ -440,7 +440,7 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) ...@@ -440,7 +440,7 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block)
t.Fatal("can't create node:", err) t.Fatal("can't create node:", err)
} }
ethcfg := &ethconfig.Config{Genesis: genesis, Ethash: ethash.Config{PowMode: ethash.ModeFake}, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256} ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256}
ethservice, err := eth.New(n, ethcfg) ethservice, err := eth.New(n, ethcfg)
if err != nil { if err != nil {
t.Fatal("can't create eth service:", err) t.Fatal("can't create eth service:", err)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment