Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blockinfotree fix #114

Merged
merged 6 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/rpcdaemon/commands/zkevm_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ func (api *ZkEvmAPIImpl) getBlockRangeWitness(ctx context.Context, db kv.RoDB, s
return nil, err
}

err = batch.CreateBucket(hermez_db.GLOBAL_EXIT_ROOTS)
err = batch.CreateBucket(hermez_db.BLOCK_GLOBAL_EXIT_ROOTS)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -741,7 +741,7 @@ func getLatestSequencedBatchNo(tx kv.Tx) (uint64, error) {
}

func getGlobalExitRoot(tx kv.Tx, l2Block uint64) (common.Hash, error) {
d, err := tx.GetOne(hermez_db.GLOBAL_EXIT_ROOTS, hermez_db.Uint64ToBytes(l2Block))
d, err := tx.GetOne(hermez_db.BLOCK_GLOBAL_EXIT_ROOTS, hermez_db.Uint64ToBytes(l2Block))
if err != nil {
return common.Hash{}, err
}
Expand Down
130 changes: 51 additions & 79 deletions core/blockchain_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/ledgerwatch/erigon/chain"

"github.com/ledgerwatch/erigon-lib/kv"
dstypes "github.com/ledgerwatch/erigon/zk/datastream/types"

"github.com/ledgerwatch/erigon/common/math"
"github.com/ledgerwatch/erigon/consensus"
Expand All @@ -36,15 +35,17 @@ import (
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/smt/pkg/blockinfo"
"github.com/ledgerwatch/erigon/zk/utils"
)

// ExecuteBlockEphemerally runs a block from provided stateReader and
// writes the result to the provided stateWriter
func ExecuteBlockEphemerallyZk(
chainConfig *chain.Config, vmConfig *vm.Config,
chainConfig *chain.Config,
vmConfig *vm.Config,
blockHashFunc func(n uint64) libcommon.Hash,
engine consensus.Engine, block *types.Block,
engine consensus.Engine,
prevBlockHash *libcommon.Hash,
block *types.Block,
stateReader state.StateReader,
stateWriter state.WriterWithChangeSets,
chainReader consensus.ChainHeaderReader,
Expand All @@ -57,10 +58,10 @@ func ExecuteBlockEphemerallyZk(
block.Uncles()
ibs := state.New(stateReader)
header := block.Header()

usedGas := new(uint64)
blockTransaction := block.Transactions()
blockGasLimit := block.GasLimit()
gp := new(GasPool)
gp.AddGas(block.GasLimit())
gp.AddGas(blockGasLimit)

var (
rejectedTxs []*RejectedTx
Expand All @@ -78,7 +79,7 @@ func ExecuteBlockEphemerallyZk(
}

if !vmConfig.ReadOnly {
if err := InitializeBlockExecution(engine, chainReader, block.Header(), block.Transactions(), block.Uncles(), chainConfig, ibs, excessDataGas); err != nil {
if err := InitializeBlockExecution(engine, chainReader, header, blockTransaction, block.Uncles(), chainConfig, ibs, excessDataGas); err != nil {
return nil, err
}
}
Expand All @@ -87,17 +88,8 @@ func ExecuteBlockEphemerallyZk(
misc.ApplyDAOHardFork(ibs)
}

// the state root of the previous block is written into state
// this should be fine since we get block 0 from the datastream
stateRoot, err := roHermezDb.GetStateRoot(block.NumberU64() - 1)
if err != nil {
return nil, err
}

blockNum := block.NumberU64()

gers := []*dstypes.GerUpdate{}

//[zkevm] - get the last batch number so we can check for empty batches in between it and the new one
lastBatchInserted, err := roHermezDb.GetBatchNoByL2Block(blockNum - 1)
if err != nil {
Expand All @@ -117,60 +109,35 @@ func ExecuteBlockEphemerallyZk(
return nil, err
}

if gersInBetween != nil {
gers = append(gers, gersInBetween...)
}

blockGer, l1BlockHash, err := roHermezDb.GetBlockGlobalExitRoot(blockNum)
if err != nil {
return nil, err
}

blockGerUpdate := dstypes.GerUpdate{
GlobalExitRoot: blockGer,
Timestamp: header.Time,
}
gers = append(gers, &blockGerUpdate)

var emptyHash = libcommon.Hash{0}

for _, ger := range gers {
if ger.GlobalExitRoot == emptyHash {
// etrog - if l1blockhash is set, this is an etrog GER
if err := utils.WriteGlobalExitRootEtrog(stateWriter, ger.GlobalExitRoot); err != nil {
return nil, err
}
} else {
// [zkevm] - add GER if there is one for this batch
if err := utils.WriteGlobalExitRoot(stateReader, stateWriter, ger.GlobalExitRoot, ger.Timestamp); err != nil {
return nil, err
}
}
}

// [zkevm] - finished writing global exit root to state

ibs.PreExecuteStateSet(chainConfig, block.NumberU64(), block.Time(), &stateRoot)
blockTime := block.Time()
ibs.SyncerPreExecuteStateSet(chainConfig, blockNum, blockTime, prevBlockHash, &blockGer, &l1BlockHash, &gersInBetween)

blockInfoTree := blockinfo.NewBlockInfoTree()
parentHash := block.ParentHash()
coinbase := block.Coinbase()
if err := blockInfoTree.InitBlockHeader(
&parentHash,
&coinbase,
blockNum,
block.GasLimit(),
block.Time(),
&blockGer,
&l1BlockHash,
); err != nil {
return nil, err
if chainConfig.IsForkID7Etrog(blockNum) {
coinbase := block.Coinbase()

if err := blockInfoTree.InitBlockHeader(
prevBlockHash,
&coinbase,
blockNum,
blockGasLimit,
blockTime,
&blockGer,
&l1BlockHash,
); err != nil {
return nil, err
}
}

noop := state.NewNoopWriter()
cumulativeGasUsed := uint64(0)
logIndex := int64(0)
for txIndex, tx := range block.Transactions() {
usedGas := new(uint64)

for txIndex, tx := range blockTransaction {
ibs.Prepare(tx.Hash(), block.Hash(), txIndex)
writeTrace := false
if vmConfig.Debug && vmConfig.Tracer == nil {
Expand All @@ -182,7 +149,7 @@ func ExecuteBlockEphemerallyZk(
writeTrace = true
}

gp.Reset(block.GasLimit())
gp.Reset(blockGasLimit)

effectiveGasPricePercentage, err := roHermezDb.GetEffectiveGasPricePercentage(tx.Hash())
if err != nil {
Expand Down Expand Up @@ -213,30 +180,35 @@ func ExecuteBlockEphemerallyZk(
ibs.ScalableSetSmtRootHash(roHermezDb)
}

//block info tree
cumulativeGasUsed += receipt.GasUsed
_, err = blockInfoTree.SetBlockTx(
txIndex,
receipt,
logIndex,
cumulativeGasUsed,
effectiveGasPricePercentage,
)
if err != nil {
return nil, err
if chainConfig.IsForkID7Etrog(blockNum) {
//block info tree
_, err = blockInfoTree.SetBlockTx(
txIndex,
receipt,
logIndex,
*usedGas,
effectiveGasPricePercentage,
)
if err != nil {
return nil, err
}
}

// increment logIndex for next turn
// log idex counts all the logs in all txs in the block
logIndex += int64(len(receipt.Logs))
}

// [zkevm] - set the block info tree root
root, err := blockInfoTree.SetBlockGasUsed(cumulativeGasUsed)
if err != nil {
return nil, err
var l1InfoRoot libcommon.Hash
if chainConfig.IsForkID7Etrog(blockNum) {
// [zkevm] - set the block info tree root
root, err := blockInfoTree.SetBlockGasUsed(*usedGas)
if err != nil {
return nil, err
}
l1InfoRoot = libcommon.BigToHash(root)
}
l1InfoRoot := libcommon.BigToHash(root)

ibs.PostExecuteStateSet(chainConfig, block.NumberU64(), &l1InfoRoot)

receiptSha := types.DeriveSha(receipts)
Expand All @@ -259,7 +231,7 @@ func ExecuteBlockEphemerallyZk(
//}
}
if !vmConfig.ReadOnly {
txs := block.Transactions()
txs := blockTransaction
if _, _, _, err := FinalizeBlockExecution(engine, stateReader, block.Header(), txs, block.Uncles(), stateWriter, chainConfig, ibs, receipts, block.Withdrawals(), chainReader, false, excessDataGas); err != nil {
return nil, err
}
Expand Down
69 changes: 61 additions & 8 deletions core/state/intra_block_state_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import (
)

var (
LAST_BLOCK_STORAGE_POS = libcommon.HexToHash("0x0")
STATE_ROOT_STORAGE_POS = libcommon.HexToHash("0x1")
TIMESTAMP_STORAGE_POS = libcommon.HexToHash("0x2")
BLOCK_INFO_ROOT_STORAGE_POS = libcommon.HexToHash("0x3")
ADDRESS_SCALABLE_L2 = libcommon.HexToAddress("0x000000000000000000000000000000005ca1ab1e")
GER_MANAGER_ADDRESS = libcommon.HexToAddress("0xa40D5f56745a118D0906a34E69aeC8C0Db1cB8fA")
LAST_BLOCK_STORAGE_POS = libcommon.HexToHash("0x0")
STATE_ROOT_STORAGE_POS = libcommon.HexToHash("0x1")
TIMESTAMP_STORAGE_POS = libcommon.HexToHash("0x2")
BLOCK_INFO_ROOT_STORAGE_POS = libcommon.HexToHash("0x3")
ADDRESS_SCALABLE_L2 = libcommon.HexToAddress("0x000000000000000000000000000000005ca1ab1e")
GER_MANAGER_ADDRESS = libcommon.HexToAddress("0xa40D5f56745a118D0906a34E69aeC8C0Db1cB8fA")
GLOBAL_EXIT_ROOT_STORAGE_POS = libcommon.HexToHash("0x0")
)

type ReadOnlyHermezDb interface {
Expand Down Expand Up @@ -64,6 +65,49 @@ func (sdb *IntraBlockState) PreExecuteStateSet(chainConfig *chain.Config, blockN
}
}

func (sdb *IntraBlockState) SyncerPreExecuteStateSet(chainConfig *chain.Config, blockNumber uint64, blockTimestamp uint64, stateRoot, blockGer, l1BlockHash *libcommon.Hash, gerUpdates *[]*dstypes.GerUpdate) {
if !sdb.Exist(ADDRESS_SCALABLE_L2) {
// create account if not exists
sdb.CreateAccount(ADDRESS_SCALABLE_L2, true)
}

//save block number
sdb.scalableSetBlockNum(blockNumber)
emptyHash := libcommon.Hash{}

//ETROG
if chainConfig.IsForkID7Etrog(blockNumber) {
currentTimestamp := sdb.ScalableGetTimestamp()
if blockTimestamp > currentTimestamp {
sdb.ScalableSetTimestamp(blockTimestamp)
}

//save prev block hash
sdb.scalableSetBlockHash(blockNumber-1, stateRoot)

//save ger with l1blockhash
if blockGer != nil && *blockGer != emptyHash {
sdb.WriteGerManagerL1BlockHash(*blockGer, *l1BlockHash)
}
} else {
if blockGer != nil && *blockGer != emptyHash {
blockGerUpdate := dstypes.GerUpdate{
GlobalExitRoot: *blockGer,
Timestamp: blockTimestamp,
}
*gerUpdates = append(*gerUpdates, &blockGerUpdate)
}

for _, ger := range *gerUpdates {
//save ger
if ger != nil {
sdb.WriteGlobalExitRootTimestamp(ger.GlobalExitRoot, ger.Timestamp)
}
}

}
}

func (sdb *IntraBlockState) scalableSetBlockInfoRoot(l1InfoRoot *libcommon.Hash) {
l1InfoRootBigU := uint256.NewInt(0).SetBytes(l1InfoRoot.Bytes())

Expand Down Expand Up @@ -128,7 +172,7 @@ func (sdb *IntraBlockState) ScalableSetBlockNumberToHash(blockNumber uint64, rod

func (sdb *IntraBlockState) ReadGerManagerL1BlockHash(ger libcommon.Hash) libcommon.Hash {
d1 := common.LeftPadBytes(ger.Bytes(), 32)
d2 := common.LeftPadBytes(uint256.NewInt(0).Bytes(), 32)
d2 := common.LeftPadBytes(GLOBAL_EXIT_ROOT_STORAGE_POS.Bytes(), 32)
mapKey := keccak256.Hash(d1, d2)
mkh := libcommon.BytesToHash(mapKey)
key := uint256.NewInt(0)
Expand All @@ -141,13 +185,22 @@ func (sdb *IntraBlockState) ReadGerManagerL1BlockHash(ger libcommon.Hash) libcom

func (sdb *IntraBlockState) WriteGerManagerL1BlockHash(ger, l1BlockHash libcommon.Hash) {
d1 := common.LeftPadBytes(ger.Bytes(), 32)
d2 := common.LeftPadBytes(uint256.NewInt(0).Bytes(), 32)
d2 := common.LeftPadBytes(GLOBAL_EXIT_ROOT_STORAGE_POS.Bytes(), 32)
mapKey := keccak256.Hash(d1, d2)
mkh := libcommon.BytesToHash(mapKey)
val := uint256.NewInt(0).SetBytes(l1BlockHash.Bytes())
sdb.SetState(GER_MANAGER_ADDRESS, &mkh, *val)
}

func (sdb *IntraBlockState) WriteGlobalExitRootTimestamp(ger libcommon.Hash, timestamp uint64) {
d1 := common.LeftPadBytes(ger.Bytes(), 32)
d2 := common.LeftPadBytes(GLOBAL_EXIT_ROOT_STORAGE_POS.Bytes(), 32)
mapKey := keccak256.Hash(d1, d2)
mkh := libcommon.BytesToHash(mapKey)
val := uint256.NewInt(0).SetUint64(timestamp)
sdb.SetState(GER_MANAGER_ADDRESS, &mkh, *val)
}

func (sdb *IntraBlockState) ScalableGetTimestamp() uint64 {
timestamp := uint256.NewInt(0)

Expand Down
17 changes: 15 additions & 2 deletions eth/stagedsync/stage_execute_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ func SpawnExecuteBlocksStageZk(s *StageState, u Unwinder, tx kv.RwTx, toBlock ui

initialBlock := stageProgress + 1
eridb := erigon_db.NewErigonDb(tx)

prevheaderHash, err := rawdb.ReadCanonicalHash(tx, stageProgress)
if err != nil {
return err
}
header, err := cfg.blockReader.Header(ctx, tx, prevheaderHash, stageProgress)
if err != nil {
return err
}
prevBlockHash := header.Root
Loop:
for blockNum := stageProgress + 1; blockNum <= to; blockNum++ {
stageProgress = blockNum
Expand Down Expand Up @@ -165,7 +175,7 @@ Loop:
if err = updateZkEVMBlockCfg(&cfg, hermezDb, logPrefix); err != nil {
return err
}
if err = executeBlockZk(block, header, tx, batch, cfg, *cfg.vmConfig, writeChangeSets, writeReceipts, writeCallTraces, initialCycle, stateStream, hermezDb); err != nil {
if err = executeBlockZk(block, &prevBlockHash, header, tx, batch, cfg, *cfg.vmConfig, writeChangeSets, writeReceipts, writeCallTraces, initialCycle, stateStream, hermezDb); err != nil {
if !errors.Is(err, context.Canceled) {
log.Warn(fmt.Sprintf("[%s] Execution failed", logPrefix), "block", blockNum, "hash", block.Hash().String(), "err", err)
if cfg.hd != nil {
Expand Down Expand Up @@ -233,6 +243,8 @@ Loop:
later.
*/
headerHash := header.Hash()
prevBlockHash = headerHash

rawdb.WriteHeader(tx, header)
err = rawdb.WriteCanonicalHash(tx, headerHash, blockNum)
if err != nil {
Expand Down Expand Up @@ -300,6 +312,7 @@ Loop:

func executeBlockZk(
block *types.Block,
prevBlockHash *common.Hash,
header *types.Header,
tx kv.RwTx,
batch ethdb.Database,
Expand Down Expand Up @@ -339,7 +352,7 @@ func executeBlockZk(
var execRs *core.EphemeralExecResult
getHashFn := core.GetHashFn(block.Header(), getHeader)

execRs, err = core.ExecuteBlockEphemerallyZk(cfg.chainConfig, &vmConfig, getHashFn, cfg.engine, block, stateReader, stateWriter, ChainReaderImpl{config: cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}, getTracer, tx, roHermezDb)
execRs, err = core.ExecuteBlockEphemerallyZk(cfg.chainConfig, &vmConfig, getHashFn, cfg.engine, prevBlockHash, block, stateReader, stateWriter, ChainReaderImpl{config: cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}, getTracer, tx, roHermezDb)

if err != nil {
return err
Expand Down
Loading