Changed parallel universe HF to Cancun HF and some important fixes (#1132)

* changed parallel universe HF to napoli HF

* integration-tests: update ipc path on ci tests (#1127)

* integration-tests: update ipc path on ci tests

* added devnetBorFlags in matic-cli-config.yml

---------

Co-authored-by: Pratik Patil <pratikspatil024@gmail.com>

* Revert "integration-tests: update ipc path on ci tests (#1127)"

This reverts commit 0660fac39b.

* using cancun for block-stm metadata instead of napoli

* added a check to verify tx dependencies and test cases

* fix in snapshot.chainConfig

* removed snapshot.*params.BorConfig using snapshot.chainConfig.Bor instead

* removed unnecessary if statement in ParallelStateProcessor.Process

* addressed comment

* small fix in commitTransactions

* dependency calculation bug fix in miner/worker.go

---------

Co-authored-by: Manav Darji <manavdarji.india@gmail.com>
Co-authored-by: Arpit Temani <temaniarpit27@gmail.com>
This commit is contained in:
Pratik Patil 2024-01-23 10:52:00 +05:30 committed by GitHub
parent c559619c80
commit f1e0b1d926
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 148 additions and 138 deletions

View file

@ -17,7 +17,6 @@
"bor": {
"jaipurBlock": 23850000,
"delhiBlock": 38189056,
"parallelUniverseBlock": 0,
"indoreBlock": 44934656,
"stateSyncConfirmationDelay": {
"44934656": 128

View file

@ -17,7 +17,6 @@
"bor": {
"jaipurBlock": 22770000,
"delhiBlock": 29638656,
"parallelUniverseBlock": 0,
"indoreBlock": 37075456,
"stateSyncConfirmationDelay": {
"37075456": 128

View file

@ -353,7 +353,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
isSprintEnd := IsSprintStart(number+1, c.config.CalculateSprint(number))
// Ensure that the extra-data contains a signer list on checkpoint, but none otherwise
signersBytes := len(header.GetValidatorBytes(c.config))
signersBytes := len(header.GetValidatorBytes(c.chainConfig))
if !isSprintEnd && signersBytes != 0 {
return errExtraValidators
@ -472,7 +472,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
sort.Sort(valset.ValidatorsByAddress(newValidators))
headerVals, err := valset.ParseValidators(header.GetValidatorBytes(c.config))
headerVals, err := valset.ParseValidators(header.GetValidatorBytes(c.chainConfig))
if err != nil {
return err
}
@ -490,7 +490,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
// verify the validator list in the last sprint block
if IsSprintStart(number, c.config.CalculateSprint(number)) {
parentValidatorBytes := parent.GetValidatorBytes(c.config)
parentValidatorBytes := parent.GetValidatorBytes(c.chainConfig)
validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength)
currentValidators := snap.ValidatorSet.Copy().Validators
@ -521,7 +521,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
val := valset.NewValidator(signer, 1000)
validatorset := valset.NewValidatorSet([]*valset.Validator{val})
snapshot := newSnapshot(c.config, c.signatures, number, hash, validatorset.Validators)
snapshot := newSnapshot(c.chainConfig, c.signatures, number, hash, validatorset.Validators)
return snapshot, nil
}
@ -541,7 +541,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
// If an on-disk checkpoint snapshot can be found, use that
if number%checkpointInterval == 0 {
if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil {
if s, err := loadSnapshot(c.chainConfig, c.config, c.signatures, c.db, hash); err == nil {
log.Trace("Loaded snapshot from disk", "number", number, "hash", hash)
snap = s
@ -570,7 +570,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
}
// new snap shot
snap = newSnapshot(c.config, c.signatures, number, hash, validators)
snap = newSnapshot(c.chainConfig, c.signatures, number, hash, validators)
if err := snap.store(c.db); err != nil {
return nil, err
}
@ -742,7 +742,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
// sort validator by address
sort.Sort(valset.ValidatorsByAddress(newValidators))
if c.config.IsParallelUniverse(header.Number) {
if c.chainConfig.IsCancun(header.Number) {
var tempValidatorBytes []byte
for _, validator := range newValidators {
@ -766,7 +766,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
header.Extra = append(header.Extra, validator.HeaderBytes()...)
}
}
} else if c.config.IsParallelUniverse(header.Number) {
} else if c.chainConfig.IsCancun(header.Number) {
blockExtraData := &types.BlockExtraData{
ValidatorBytes: nil,
TxDependency: nil,

View file

@ -15,7 +15,8 @@ import (
// Snapshot is the state of the authorization voting at a given point in time.
type Snapshot struct {
config *params.BorConfig // Consensus engine parameters to fine tune behavior
chainConfig *params.ChainConfig
sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
Number uint64 `json:"number"` // Block number where the snapshot was created
@ -28,14 +29,14 @@ type Snapshot struct {
// method does not initialize the set of recent signers, so only ever use if for
// the genesis block.
func newSnapshot(
config *params.BorConfig,
chainConfig *params.ChainConfig,
sigcache *lru.ARCCache,
number uint64,
hash common.Hash,
validators []*valset.Validator,
) *Snapshot {
snap := &Snapshot{
config: config,
chainConfig: chainConfig,
sigcache: sigcache,
Number: number,
Hash: hash,
@ -47,7 +48,7 @@ func newSnapshot(
}
// loadSnapshot loads an existing snapshot from the database.
func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
func loadSnapshot(chainConfig *params.ChainConfig, config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
blob, err := db.Get(append([]byte("bor-"), hash[:]...))
if err != nil {
return nil, err
@ -61,7 +62,7 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat
snap.ValidatorSet.UpdateValidatorMap()
snap.config = config
snap.chainConfig = chainConfig
snap.sigcache = sigcache
// update total voting power
@ -85,7 +86,7 @@ func (s *Snapshot) store(db ethdb.Database) error {
// copy creates a deep copy of the snapshot, though not the individual votes.
func (s *Snapshot) copy() *Snapshot {
cpy := &Snapshot{
config: s.config,
chainConfig: s.chainConfig,
sigcache: s.sigcache,
Number: s.Number,
Hash: s.Hash,
@ -122,12 +123,12 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
number := header.Number.Uint64()
// Delete the oldest signer from the recent list to allow it signing again
if number >= s.config.CalculateSprint(number) {
delete(snap.Recents, number-s.config.CalculateSprint(number))
if number >= s.chainConfig.Bor.CalculateSprint(number) {
delete(snap.Recents, number-s.chainConfig.Bor.CalculateSprint(number))
}
// Resolve the authorization key and check against signers
signer, err := ecrecover(header, s.sigcache, s.config)
signer, err := ecrecover(header, s.sigcache, s.chainConfig.Bor)
if err != nil {
return nil, err
}
@ -145,12 +146,12 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
snap.Recents[number] = signer
// change validator set and change proposer
if number > 0 && (number+1)%s.config.CalculateSprint(number) == 0 {
if number > 0 && (number+1)%s.chainConfig.Bor.CalculateSprint(number) == 0 {
if err := validateHeaderExtraField(header.Extra); err != nil {
return nil, err
}
validatorBytes := header.GetValidatorBytes(s.config)
validatorBytes := header.GetValidatorBytes(s.chainConfig)
// get validators from headers and use that for new validator set
newVals, _ := valset.ParseValidators(validatorBytes)

View file

@ -288,6 +288,11 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
deps := GetDeps(blockTxDependency)
if !VerifyDeps(deps) || len(blockTxDependency) != len(block.Transactions()) {
blockTxDependency = nil
deps = make(map[int][]int)
}
if blockTxDependency != nil {
metadata = true
}
@ -308,7 +313,6 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
shouldDelayFeeCal = false
}
if len(blockTxDependency) != len(block.Transactions()) {
task := &ExecutionTask{
msg: *msg,
config: p.config,
@ -333,32 +337,6 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
}
tasks = append(tasks, task)
} else {
task := &ExecutionTask{
msg: *msg,
config: p.config,
gasLimit: block.GasLimit(),
blockNumber: blockNumber,
blockHash: blockHash,
tx: tx,
index: i,
cleanStateDB: cleansdb,
finalStateDB: statedb,
blockChain: p.bc,
header: header,
evmConfig: cfg,
shouldDelayFeeCal: &shouldDelayFeeCal,
sender: msg.From,
totalUsedGas: usedGas,
receipts: &receipts,
allLogs: &allLogs,
dependencies: nil,
coinbase: coinbase,
blockContext: blockContext,
}
tasks = append(tasks, task)
}
}
backupStateDB := statedb.Copy()
@ -427,3 +405,21 @@ func GetDeps(txDependency [][]uint64) map[int][]int {
return deps
}
// returns true if dependencies are correct
func VerifyDeps(deps map[int][]int) bool {
// number of transactions in the block
n := len(deps)
// Handle out-of-range and circular dependency problem
for i := 0; i <= n-1; i++ {
val := deps[i]
for _, depTx := range val {
if depTx >= n || depTx >= i {
return false
}
}
}
return true
}

View file

@ -0,0 +1,30 @@
package core
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMetadata(t *testing.T) {
t.Parallel()
correctTxDependency := [][]uint64{{}, {0}, {}, {1}, {3}, {}, {0, 2}, {5}, {}, {8}}
wrongTxDependency := [][]uint64{{0}}
wrongTxDependencyCircular := [][]uint64{{}, {2}, {1}}
wrongTxDependencyOutOfRange := [][]uint64{{}, {}, {3}}
var temp map[int][]int
temp = GetDeps(correctTxDependency)
assert.Equal(t, true, VerifyDeps(temp))
temp = GetDeps(wrongTxDependency)
assert.Equal(t, false, VerifyDeps(temp))
temp = GetDeps(wrongTxDependencyCircular)
assert.Equal(t, false, VerifyDeps(temp))
temp = GetDeps(wrongTxDependencyOutOfRange)
assert.Equal(t, false, VerifyDeps(temp))
}

View file

@ -456,8 +456,8 @@ func (b *Block) GetTxDependency() [][]uint64 {
return blockExtraData.TxDependency
}
func (h *Header) GetValidatorBytes(config *params.BorConfig) []byte {
if !config.IsParallelUniverse(h.Number) {
func (h *Header) GetValidatorBytes(chainConfig *params.ChainConfig) []byte {
if !chainConfig.IsCancun(h.Number) {
return h.Extra[ExtraVanityLength : len(h.Extra)-ExtraSealLength]
}

View file

@ -74,7 +74,6 @@ func TestBlockEncoding(t *testing.T) {
}
// This is a replica of `(h *Header) GetValidatorBytes` function
// This was needed because currently, `IsParallelUniverse` will always return false.
func GetValidatorBytesTest(h *Header) []byte {
if len(h.Extra) < ExtraVanityLength+ExtraSealLength {
log.Error("length of extra less is than vanity and seal")

View file

@ -31,7 +31,6 @@ var mainnetBor = &Chain{
Bor: &params.BorConfig{
JaipurBlock: big.NewInt(23850000),
DelhiBlock: big.NewInt(38189056),
ParallelUniverseBlock: big.NewInt(0),
IndoreBlock: big.NewInt(44934656),
StateSyncConfirmationDelay: map[string]uint64{
"44934656": 128,

View file

@ -31,7 +31,6 @@ var mumbaiTestnet = &Chain{
Bor: &params.BorConfig{
JaipurBlock: big.NewInt(22770000),
DelhiBlock: big.NewInt(29638656),
ParallelUniverseBlock: big.NewInt(0),
IndoreBlock: big.NewInt(37075456),
StateSyncConfirmationDelay: map[string]uint64{
"37075456": 128,

View file

@ -57,7 +57,6 @@
},
"jaipurBlock": 22770000,
"delhiBlock": 29638656,
"parallelUniverseBlock": 0,
"indoreBlock": 37075456,
"stateSyncConfirmationDelay": {
"37075456": 128

View file

@ -59,7 +59,6 @@
},
"jaipurBlock":22770000,
"delhiBlock": 29638656,
"parallelUniverseBlock": 0,
"indoreBlock": 37075456,
"stateSyncConfirmationDelay": {
"37075456": 128

View file

@ -109,6 +109,9 @@ type environment struct {
header *types.Header
txs []*types.Transaction
receipts []*types.Receipt
depsMVFullWriteList [][]blockstm.WriteDescriptor
mvReadMapList []map[blockstm.Key]blockstm.ReadDescriptor
}
// copy creates a deep copy of environment.
@ -120,6 +123,8 @@ func (env *environment) copy() *environment {
coinbase: env.coinbase,
header: types.CopyHeader(env.header),
receipts: copyReceipts(env.receipts),
depsMVFullWriteList: env.depsMVFullWriteList,
mvReadMapList: env.mvReadMapList,
}
if env.gasPool != nil {
@ -854,6 +859,9 @@ func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase co
// Keep track of transactions which return errors so they can be removed
env.tcount = 0
env.depsMVFullWriteList = [][]blockstm.WriteDescriptor{}
env.mvReadMapList = []map[blockstm.Key]blockstm.ReadDescriptor{}
return env, nil
}
@ -903,36 +911,20 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
var coalescedLogs []*types.Log
var depsMVReadList [][]blockstm.ReadDescriptor
var depsMVFullWriteList [][]blockstm.WriteDescriptor
var mvReadMapList []map[blockstm.Key]blockstm.ReadDescriptor
var deps map[int]map[int]bool
chDeps := make(chan blockstm.TxDep)
var count int
var depsWg sync.WaitGroup
EnableMVHashMap := w.chainConfig.Bor.IsParallelUniverse(env.header.Number)
EnableMVHashMap := w.chainConfig.IsCancun(env.header.Number)
// create and add empty mvHashMap in statedb
if EnableMVHashMap {
depsMVReadList = [][]blockstm.ReadDescriptor{}
depsMVFullWriteList = [][]blockstm.WriteDescriptor{}
mvReadMapList = []map[blockstm.Key]blockstm.ReadDescriptor{}
deps = map[int]map[int]bool{}
chDeps = make(chan blockstm.TxDep)
count = 0
depsWg.Add(1)
go func(chDeps chan blockstm.TxDep) {
@ -1064,18 +1056,20 @@ mainloop:
env.tcount++
if EnableMVHashMap {
depsMVReadList = append(depsMVReadList, env.state.MVReadList())
depsMVFullWriteList = append(depsMVFullWriteList, env.state.MVFullWriteList())
mvReadMapList = append(mvReadMapList, env.state.MVReadMap())
env.depsMVFullWriteList = append(env.depsMVFullWriteList, env.state.MVFullWriteList())
env.mvReadMapList = append(env.mvReadMapList, env.state.MVReadMap())
if env.tcount > len(env.depsMVFullWriteList) {
log.Warn("blockstm - env.tcount > len(env.depsMVFullWriteList)", "env.tcount", env.tcount, "len(depsMVFullWriteList)", len(env.depsMVFullWriteList))
}
temp := blockstm.TxDep{
Index: env.tcount - 1,
ReadList: depsMVReadList[count],
FullWriteList: depsMVFullWriteList,
ReadList: env.state.MVReadList(),
FullWriteList: env.depsMVFullWriteList,
}
chDeps <- temp
count++
}
txs.Shift()
@ -1107,8 +1101,8 @@ mainloop:
tempVanity := env.header.Extra[:types.ExtraVanityLength]
tempSeal := env.header.Extra[len(env.header.Extra)-types.ExtraSealLength:]
if len(mvReadMapList) > 0 {
tempDeps := make([][]uint64, len(mvReadMapList))
if len(env.mvReadMapList) > 0 {
tempDeps := make([][]uint64, len(env.mvReadMapList))
for j := range deps[0] {
tempDeps[0] = append(tempDeps[0], uint64(j))
@ -1116,8 +1110,8 @@ mainloop:
delayFlag := true
for i := 1; i <= len(mvReadMapList)-1; i++ {
reads := mvReadMapList[i-1]
for i := 1; i <= len(env.mvReadMapList)-1; i++ {
reads := env.mvReadMapList[i-1]
_, ok1 := reads[blockstm.NewSubpathKey(env.coinbase, state.BalancePath)]
_, ok2 := reads[blockstm.NewSubpathKey(common.HexToAddress(w.chainConfig.Bor.CalculateBurntContract(env.header.Number.Uint64())), state.BalancePath)]

View file

@ -909,7 +909,7 @@ func BenchmarkBorMining(b *testing.B) {
}
// uses core.NewParallelBlockChain to use the dependencies present in the block header
// params.BorUnittestChainConfig contains the ParallelUniverseBlock ad big.NewInt(5), so the first 4 blocks will not have metadata.
// params.BorUnittestChainConfig contains the NapoliBlock as big.NewInt(5), so the first 4 blocks will not have metadata.
// nolint: gocognit
func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) {
chainConfig := params.BorUnittestChainConfig

View file

@ -159,7 +159,6 @@ var (
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Bor: &BorConfig{
ParallelUniverseBlock: big.NewInt(5),
Period: map[string]uint64{
"0": 1,
},
@ -200,7 +199,6 @@ var (
Bor: &BorConfig{
JaipurBlock: big.NewInt(22770000),
DelhiBlock: big.NewInt(29638656),
ParallelUniverseBlock: big.NewInt(0),
IndoreBlock: big.NewInt(37075456),
StateSyncConfirmationDelay: map[string]uint64{
"37075456": 128,
@ -266,7 +264,6 @@ var (
Bor: &BorConfig{
JaipurBlock: big.NewInt(23850000),
DelhiBlock: big.NewInt(38189056),
ParallelUniverseBlock: big.NewInt(0),
IndoreBlock: big.NewInt(44934656),
StateSyncConfirmationDelay: map[string]uint64{
"44934656": 128,
@ -567,7 +564,6 @@ type BorConfig struct {
BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork
JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur)
DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi)
ParallelUniverseBlock *big.Int `json:"parallelUniverseBlock"` // TODO: update all occurrence, change name and finalize number (hardfork for block-stm related changes)
IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore)
StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to`
}
@ -609,16 +605,16 @@ func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 {
return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number)
}
// TODO: modify this function once the block number is finalized
func (c *BorConfig) IsParallelUniverse(number *big.Int) bool {
if c.ParallelUniverseBlock != nil {
if c.ParallelUniverseBlock.Cmp(big.NewInt(0)) == 0 {
return false
}
}
// // TODO: modify this function once the block number is finalized
// func (c *BorConfig) IsNapoli(number *big.Int) bool {
// if c.NapoliBlock != nil {
// if c.NapoliBlock.Cmp(big.NewInt(0)) == 0 {
// return false
// }
// }
return isBlockForked(c.ParallelUniverseBlock, number)
}
// return isBlockForked(c.NapoliBlock, number)
// }
func (c *BorConfig) IsSprintStart(number uint64) bool {
return number%c.CalculateSprint(number) == 0