Skip to content

miner/stress/ethash

Source (upstream pre-purge) Current
File miner/stress/ethash/main.go main.go
Symbol (entire file) (entire file)
Ref dde2da0ef~1 etc/v1.17.3-full-node

Standalone stress test: spins up 4 PoW nodes with ModeFake, interconnects them, starts mining, and bombards with transactions. Adapted from pre-purge3 with updated log API, TxPool.Add, legacypool.DefaultConfig, and minimal PoW genesis.

3-way merge — purge → getc ← upstream

pre-purgecore-geth≈ adapted (origin inferred by similarity)fork-only
// 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/>.
// This file contains a miner stress test based on the Ethash consensus engine.
package main
import (
"crypto/ecdsa"
"math/big"
"math/rand"
"os"
"os/signal"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
)
func main() {
glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, true))
glogger.Verbosity(log.LevelInfo)
log.SetDefault(log.NewLogger(glogger))
fdlimit.Raise(2048)
// Generate a batch of accounts to seal and fund with
faucets := make([]*ecdsa.PrivateKey, 128)
for i := 0; i < len(faucets); i++ {
faucets[i], _ = crypto.GenerateKey()
}
// Create an Ethash network
genesis := makeGenesis(faucets)
// Handle interrupts.
interruptCh := make(chan os.Signal, 5)
signal.Notify(interruptCh, os.Interrupt)
var (
stacks []*node.Node
nodes []*eth.Ethereum
enodes []*enode.Node
)
for i := 0; i < 4; i++ {
// Start the node and wait until it's up
stack, ethBackend, err := makeMiner(genesis)
if err != nil {
panic(err)
}
defer stack.Close()
for stack.Server().NodeInfo().Ports.Listener == 0 {
time.Sleep(250 * time.Millisecond)
}
// Connect the node to all the previous ones
for _, n := range enodes {
stack.Server().AddPeer(n)
}
// Start tracking the node and its enode
stacks = append(stacks, stack)
nodes = append(nodes, ethBackend)
enodes = append(enodes, stack.Server().Self())
}
// Iterate over all the nodes and start mining
time.Sleep(3 * time.Second)
for _, node := range nodes {
node.SetEtherbase(common.Address{1})
if err := node.StartMining(1); err != nil {
panic(err)
}
}
time.Sleep(3 * time.Second)
// Start injecting transactions from the faucets like crazy
nonces := make([]uint64, len(faucets))
for {
// Stop when interrupted.
select {
case <-interruptCh:
for _, node := range stacks {
node.Close()
}
return
default:
}
// Pick a random mining node
index := rand.Intn(len(faucets))
backend := nodes[index%len(nodes)]
// Create a self transaction and inject into the pool
tx, err := types.SignTx(types.NewTransaction(nonces[index], crypto.PubkeyToAddress(faucets[index].PublicKey), new(big.Int), 21000, big.NewInt(100000000000+rand.Int63n(65536)), nil), types.HomesteadSigner{}, faucets[index])
if err != nil {
panic(err)
}
if errs := backend.TxPool().Add([]*types.Transaction{tx}, true); errs[0] != nil {
panic(errs[0])
}
nonces[index]++
// Wait if we're too saturated
if pend, _ := backend.TxPool().Stats(); pend > 2048 {
time.Sleep(100 * time.Millisecond)
}
}
}
// makeGenesis creates a custom Ethash genesis block based on some pre-defined
// faucet accounts.
func makeGenesis(faucets []*ecdsa.PrivateKey) *core.Genesis {
genesis := &core.Genesis{
Config: &params.ChainConfig{
ChainID: big.NewInt(18),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
Ethash: new(params.EthashConfig),
},
Difficulty: params.MinimumDifficulty,
GasLimit: 25000000,
Alloc: core.GenesisAlloc{},
}
for _, faucet := range faucets {
genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = core.GenesisAccount{
Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil),
}
}
return genesis
}
func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
// Define the basic configurations for the Ethereum node
datadir, _ := os.MkdirTemp("", "")
config := &node.Config{
Name: "geth",
Version: version.WithMeta,
DataDir: datadir,
P2P: p2p.Config{
ListenAddr: "0.0.0.0:0",
NoDiscovery: true,
MaxPeers: 25,
},
UseLightweightKDF: true,
}
// Create the node and configure a full Ethereum node on it
stack, err := node.New(config)
if err != nil {
return nil, nil, err
}
ethBackend, err := eth.New(stack, &ethconfig.Config{
Genesis: genesis,
NetworkId: genesis.Config.ChainID.Uint64(),
SyncMode: ethconfig.FullSync,
DatabaseCache: 256,
DatabaseHandles: 256,
TxPool: legacypool.DefaultConfig,
GPO: ethconfig.Defaults.GPO,
Ethash: ethash.Config{
PowMode: ethash.ModeFake,
},
Miner: miner.Config{
Etherbase: common.Address{1},
GasCeil: genesis.GasLimit * 11 / 10,
GasPrice: big.NewInt(1),
Recommit: time.Second,
},
})
if err != nil {
return nil, nil, err
}
err = stack.Start()
return stack, ethBackend, err
}
core-geth validation — +35 -26 | | | |---|---| | File | [`main.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/miner/stress/ethash/main.go) | | Symbol | `` | | Ref | `v1.12.20` |
--- a/core-geth/miner/stress/ethash/main.go
+++ b/etc/miner/stress/ethash/main.go
@@ -25,28 +25,28 @@
    "os/signal"
    "time"

-   "golang.org/x/exp/slog"
-
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/common/fdlimit"
    "github.com/ethereum/go-ethereum/consensus/ethash"
+   "github.com/ethereum/go-ethereum/core"
    "github.com/ethereum/go-ethereum/core/txpool/legacypool"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/eth"
-   "github.com/ethereum/go-ethereum/eth/downloader"
    "github.com/ethereum/go-ethereum/eth/ethconfig"
+   "github.com/ethereum/go-ethereum/internal/version"
+   "github.com/ethereum/go-ethereum/log"
    "github.com/ethereum/go-ethereum/miner"
    "github.com/ethereum/go-ethereum/node"
    "github.com/ethereum/go-ethereum/p2p"
    "github.com/ethereum/go-ethereum/p2p/enode"
    "github.com/ethereum/go-ethereum/params"
-   "github.com/ethereum/go-ethereum/params/types/genesisT"
-   "github.com/ethereum/go-ethereum/params/vars"
 )

 func main() {
-   slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo})))
+   glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, true))
+   glogger.Verbosity(log.LevelInfo)
+   log.SetDefault(log.NewLogger(glogger))
    fdlimit.Raise(2048)

    // Generate a batch of accounts to seal and fund with
@@ -54,9 +54,6 @@
    for i := 0; i < len(faucets); i++ {
        faucets[i], _ = crypto.GenerateKey()
    }
-   // Pre-generate the ethash mining DAG so we don't race
-   ethash.MakeDataset(1, ethash.CalcEpochLength(0, nil), ethconfig.Defaults.Ethash.DatasetDir)
-
    // Create an Ethash network
    genesis := makeGenesis(faucets)

@@ -93,6 +90,7 @@
    // Iterate over all the nodes and start mining
    time.Sleep(3 * time.Second)
    for _, node := range nodes {
+       node.SetEtherbase(common.Address{1})
        if err := node.StartMining(1); err != nil {
            panic(err)
        }
@@ -121,8 +119,8 @@
        if err != nil {
            panic(err)
        }
-       if err := backend.TxPool().Add([]*types.Transaction{tx}, true, false); err != nil {
-           panic(err)
+       if errs := backend.TxPool().Add([]*types.Transaction{tx}, true); errs[0] != nil {
+           panic(errs[0])
        }
        nonces[index]++

@@ -135,30 +133,39 @@

 // makeGenesis creates a custom Ethash genesis block based on some pre-defined
 // faucet accounts.
-func makeGenesis(faucets []*ecdsa.PrivateKey) *genesisT.Genesis {
-   genesis := params.DefaultGenesisBlock()
-   genesis.Difficulty = vars.MinimumDifficulty
-   genesis.GasLimit = 25000000
-
-   genesis.SetChainID(big.NewInt(18))
-   // genesis.Config.EIP150Hash = common.Hash{}
-
-   genesis.Alloc = genesisT.GenesisAlloc{}
+func makeGenesis(faucets []*ecdsa.PrivateKey) *core.Genesis {
+   genesis := &core.Genesis{
+       Config: &params.ChainConfig{
+           ChainID:             big.NewInt(18),
+           HomesteadBlock:      big.NewInt(0),
+           EIP150Block:         big.NewInt(0),
+           EIP155Block:         big.NewInt(0),
+           EIP158Block:         big.NewInt(0),
+           ByzantiumBlock:      big.NewInt(0),
+           ConstantinopleBlock: big.NewInt(0),
+           PetersburgBlock:     big.NewInt(0),
+           IstanbulBlock:       big.NewInt(0),
+           Ethash:              new(params.EthashConfig),
+       },
+       Difficulty: params.MinimumDifficulty,
+       GasLimit:   25000000,
+       Alloc:      core.GenesisAlloc{},
+   }
    for _, faucet := range faucets {
-       genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = genesisT.GenesisAccount{
+       genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = core.GenesisAccount{
            Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil),
        }
    }
    return genesis
 }

-func makeMiner(genesis *genesisT.Genesis) (*node.Node, *eth.Ethereum, error) {
+func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
    // Define the basic configurations for the Ethereum node
    datadir, _ := os.MkdirTemp("", "")

    config := &node.Config{
        Name:    "geth",
-       Version: params.Version,
+       Version: version.WithMeta,
        DataDir: datadir,
        P2P: p2p.Config{
            ListenAddr:  "0.0.0.0:0",
@@ -174,13 +181,15 @@
    }
    ethBackend, err := eth.New(stack, &ethconfig.Config{
        Genesis:         genesis,
-       NetworkId:       genesis.Config.GetChainID().Uint64(),
-       SyncMode:        downloader.FullSync,
+       NetworkId:       genesis.Config.ChainID.Uint64(),
+       SyncMode:        ethconfig.FullSync,
        DatabaseCache:   256,
        DatabaseHandles: 256,
        TxPool:          legacypool.DefaultConfig,
        GPO:             ethconfig.Defaults.GPO,
-       Ethash:          ethconfig.Defaults.Ethash,
+       Ethash: ethash.Config{
+           PowMode: ethash.ModeFake,
+       },
        Miner: miner.Config{
            Etherbase: common.Address{1},
            GasCeil:   genesis.GasLimit * 11 / 10,

← Miner