diff --git a/consensus/etc/engine.go b/consensus/etc/engine.go
index 6866d3f29..128b87bda 100644
--- a/consensus/etc/engine.go
+++ b/consensus/etc/engine.go
@@ -23,6 +23,7 @@
package etc
import (
+ "context"
"errors"
"fmt"
"math/big"
@@ -41,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
@@ -54,14 +56,16 @@ type ETCEngine struct {
// New creates a new ETC consensus engine with the given ethash configuration.
// The ethash engine is configured with ECIP-1099 block from the chain config.
-func New(config *params.ChainConfig, ethashConfig ethash.Config) *ETCEngine {
+// notify URLs receive remote miner work packets and noverify disables remote
+// solution verification; both are forwarded to the underlying ethash engine.
+func New(config *params.ChainConfig, ethashConfig ethash.Config, notify []string, noverify bool) *ETCEngine {
// Configure ECIP1099Block from ChainConfig
if config.ECIP1099Block != nil {
block := config.ECIP1099Block.Uint64()
ethashConfig.ECIP1099Block = &block
}
return &ETCEngine{
- inner: ethash.New(ethashConfig, nil, false),
+ inner: ethash.New(ethashConfig, notify, noverify),
config: config,
}
}
@@ -161,7 +165,6 @@ func (e *ETCEngine) verifyHeader(chain consensus.ChainHeaderReader, header, pare
return nil
}
-// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers concurrently.
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
// concurrently. Adapted from pre-purge ethash.VerifyHeaders (dde2da0ef~1)
// which spawns GOMAXPROCS workers for parallel verification.
@@ -334,6 +337,10 @@ func (e *ETCEngine) verifyUncleHeader(chain consensus.ChainHeaderReader, header,
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
+ // ETC-specific: London (Mystique) does NOT include EIP-1559; BaseFee must be nil
+ if header.BaseFee != nil {
+ return fmt.Errorf("invalid baseFee: ETC does not support EIP-1559, have %d, expected nil", header.BaseFee)
+ }
// Verify gas limit follows the standard rules
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
@@ -342,6 +349,19 @@ func (e *ETCEngine) verifyUncleHeader(chain consensus.ChainHeaderReader, header,
if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
return consensus.ErrInvalidNumber
}
+ // Verify the non-existence of post-merge fields (ETC is perpetual PoW)
+ if header.WithdrawalsHash != nil {
+ return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
+ }
+ if header.ExcessBlobGas != nil {
+ return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
+ }
+ if header.BlobGasUsed != nil {
+ return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
+ }
+ if header.ParentBeaconRoot != nil {
+ return fmt.Errorf("invalid parentBeaconRoot: have %x, expected nil", header.ParentBeaconRoot)
+ }
return nil
}
@@ -363,7 +383,7 @@ func (e *ETCEngine) Finalize(chain consensus.ChainHeaderReader, header *types.He
// FinalizeAndAssemble implements consensus.Engine, running post-transaction
// state modifications and assembling the final block.
-func (e *ETCEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, stateDB *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
+func (e *ETCEngine) FinalizeAndAssemble(_ context.Context, chain consensus.ChainHeaderReader, header *types.Header, stateDB *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("ETC does not support withdrawals")
}
@@ -420,6 +440,30 @@ func (e *ETCEngine) Close() error {
return e.inner.Close()
}
+// APIs returns the RPC APIs exposed by the underlying ethash engine, so
+// callers that probe the engine for an APIs(chain) method (e.g. eth.Ethereum
+// registering eth_getWork / eth_submitWork) reach the inner implementation.
+func (e *ETCEngine) APIs(chain consensus.ChainHeaderReader) []rpc.API {
+ return e.inner.APIs(chain)
+}
+
+// SetThreads delegates the mining thread count to the inner ethash engine.
+func (e *ETCEngine) SetThreads(threads int) {
+ e.inner.SetThreads(threads)
+}
+
+// Threads reports the mining thread count from the inner ethash engine.
+func (e *ETCEngine) Threads() int {
+ return e.inner.Threads()
+}
+
+// Hashrate reports the measured search invocation rate from the inner ethash
+// engine. The return type matches ethash.Hashrate (float64); callers that
+// expose this over JSON-RPC truncate to uint64 at the boundary.
+func (e *ETCEngine) Hashrate() float64 {
+ return e.inner.Hashrate()
+}
+
// Constants for difficulty calculation
var (
big1 = big.NewInt(1)