Skip to content

Commit

Permalink
feat:Private network support shanghai cancun fork
Browse files Browse the repository at this point in the history
  • Loading branch information
lochjin authored and dindinw committed Aug 28, 2024
1 parent 0e247f2 commit b76b9a1
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 79 deletions.
142 changes: 80 additions & 62 deletions meerevm/meer/consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,28 @@ package consensus
import (
"errors"
"fmt"
"github.com/Qitmeer/qng/consensus/forks"
qtypes "github.com/Qitmeer/qng/core/types"
qcommon "github.com/Qitmeer/qng/meerevm/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
"math/big"
"runtime"
)

var (
errUnclesUnsupported = errors.New("uncles unsupported")
errOlderBlockTime = errors.New("timestamp older than parent")
)

func (me *MeerEngine) Author(header *types.Header) (common.Address, error) {
Expand Down Expand Up @@ -52,70 +56,31 @@ func (me *MeerEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
}
return abort, results
}
abort := make(chan struct{})
results := make(chan error, len(headers))

// 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{})
)
for i := 0; i < workers; i++ {
go func() {
for index := range inputs {
errors[index] = me.verifyHeaderWorker(chain, headers, index)
done <- index
}
}()
}

errorsOut := make(chan error, len(headers))
go func() {
defer close(inputs)
var (
in, out = 0, 0
checked = make([]bool, len(headers))
inputs = inputs
)
for {
for i, header := range headers {
var parent *types.Header
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 = me.verifyHeader(chain, header, parent)
}
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:
return
case results <- err:
}
}
}()
return abort, errorsOut
}

func (me *MeerEngine) verifyHeaderWorker(chain consensus.ChainHeaderReader, headers []*types.Header, index int) 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 me.verifyHeader(chain, headers[index], parent)
return abort, results
}

func (me *MeerEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
Expand All @@ -126,21 +91,32 @@ func (me *MeerEngine) VerifyUncles(chain consensus.ChainReader, block *types.Blo
}

func (me *MeerEngine) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header) error {
if header.Time <= parent.Time {
return errOlderBlockTime
}
// Verify that the gas limit is <= 2^63-1
cap := uint64(0x7fffffffffffffff)
if header.GasLimit > cap {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
if header.GasLimit > params.MaxGasLimit {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit)
}
// Verify that the gasUsed is <= gasLimit
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}

// Verify the block's gas usage and (if applicable) verify the base fee.
if !chain.Config().IsLondon(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee)
}
if !forks.NeedFixedGasLimit(parent.Number.Int64(), chain.Config().ChainID.Int64()) {
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
}
} else if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil {
// Verify the header's EIP-1559 attributes.
return err
}
// Verify that the block number is parent's +1
if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
Expand All @@ -150,6 +126,34 @@ func (me *MeerEngine) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil {
return err
}

// Verify existence / non-existence of withdrawalsHash.
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
if shanghai && header.WithdrawalsHash == nil {
return errors.New("missing withdrawalsHash")
}
if !shanghai && header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
// Verify the existence / non-existence of cancun-specific header fields
cancun := chain.Config().IsCancun(header.Number, header.Time)
if !cancun {
switch {
case header.ExcessBlobGas != nil:
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
case header.BlobGasUsed != nil:
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
case header.ParentBeaconRoot != nil:
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
}
} else {
if header.ParentBeaconRoot == nil {
return errors.New("header is missing beaconRoot")
}
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
return err
}
}
return nil
}

Expand All @@ -167,13 +171,27 @@ func (me *MeerEngine) Finalize(chain consensus.ChainHeaderReader, header *types.
if me.StateChange != nil {
me.StateChange(header, state, body)
}
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
}

func (me *MeerEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
if shanghai {
// All blocks after Shanghai must include a withdrawals root.
if body.Withdrawals == nil {
body.Withdrawals = make([]*types.Withdrawal, 0)
}
} else {
if len(body.Withdrawals) > 0 {
return nil, errors.New("withdrawals set before Shanghai activation")
}
}
// Finalize and assemble the block.
me.Finalize(chain, header, state, body)

// Header seems complete, assemble into a block and return
// Assign the final state root to header.
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Assemble and return the final block.
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
}

Expand Down
2 changes: 1 addition & 1 deletion meerevm/meer/genesis_hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ package meer

const MainNetGenesisHash = "0x6cff8746d87573e2667d0784ea8753c7ee1dfc67cdb24971fe5f34743b0208fc"
const TestNetGenesisHash = "0x1c67a198c1a593b9f85bca881cbf5cbe047ab44d08a3571f66473adbe889f1f7"
const PrivNetGenesisHash = "0x528b2448923b0d08dc20c692eeb5f42d758e28804c6d341bfb3de9f452290db4"
const PrivNetGenesisHash = "0xf422ee34950d4a96701f83818360819643f6689c786a786f47816dc5b76f848d"
const MixNetGenesisHash = "0x8e9755f323ddcdaf2bc1c010ddb895450d1a23eef67ed98287bcade4c8a0d959"
29 changes: 28 additions & 1 deletion meerevm/meer/meerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,35 @@ func (b *MeerChain) ConnectBlock(block *mmeer.Block) (uint64, error) {
mbh := qcommon.ToEVMHash(block.ID())
//
log.Debug(fmt.Sprintf("MeerEVM Block:number=%d hash=%s txs=%d => blockHash(%s) txs=%d", mblock.Number().Uint64(), mblock.Hash().String(), len(mblock.Transactions()), mbh.String(), len(block.Transactions())))
return mblock.NumberU64(), b.finalized(mblock)
}

func (b *MeerChain) finalized(block *types.Block) error {
number := block.Number().Uint64()
var finalizedNumber uint64
epochLength := uint64(params.ActiveNetParams.CoinbaseMaturity)
var cnumber uint64
if number <= epochLength {
cnumber = 0
} else {
cnumber = number - epochLength
}
if cnumber <= 0 {
finalizedNumber = 0
} else {
if cnumber%epochLength == 0 {
finalizedNumber = cnumber
} else {
finalizedNumber = (cnumber - 1) / epochLength * epochLength
}
}

return mblock.NumberU64(), nil
h := b.chain.Ether().BlockChain().GetHeaderByNumber(finalizedNumber)
if h == nil {
return nil
}
b.chain.Ether().BlockChain().SetFinalized(h)
return nil
}

func (b *MeerChain) buildBlock(parent *types.Header, qtxs []model.Tx, timestamp int64) (*types.Block, types.Receipts, *state.StateDB, error) {
Expand Down
15 changes: 15 additions & 0 deletions meerevm/meer/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
qtypes "github.com/Qitmeer/qng/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -36,6 +37,20 @@ func makeHeader(cfg *ethconfig.Config, parent *types.Block, state *state.StateDB
header.GasLimit = core.CalcGasLimit(parentGasLimit, parentGasLimit)
}
}
if cfg.Genesis.Config.IsCancun(header.Number, header.Time) {
var (
parentExcessBlobGas uint64
parentBlobGasUsed uint64
)
if parent.ExcessBlobGas() != nil {
parentExcessBlobGas = *parent.ExcessBlobGas()
parentBlobGasUsed = *parent.BlobGasUsed()
}
excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
header.ExcessBlobGas = &excessBlobGas
header.BlobGasUsed = new(uint64)
header.ParentBeaconRoot = new(common.Hash)
}
return header
}

Expand Down
37 changes: 22 additions & 15 deletions meerevm/params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"math/big"
)

func newUint64(val uint64) *uint64 { return &val }

var (
// QNG
QngMainnetChainConfig = &eparams.ChainConfig{
Expand Down Expand Up @@ -62,21 +64,26 @@ var (
}

QngPrivnetChainConfig = &eparams.ChainConfig{
ChainID: eparams.QngPrivnetChainConfig.ChainID,
HomesteadBlock: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
DAOForkSupport: false,
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),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Ethash: new(eparams.EthashConfig),
ChainID: eparams.QngPrivnetChainConfig.ChainID,
HomesteadBlock: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
DAOForkSupport: false,
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),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
ShanghaiTime: newUint64(0),
CancunTime: newUint64(0),
}

// Amana
Expand Down

0 comments on commit b76b9a1

Please sign in to comment.