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

Etrog #48

Merged
merged 26 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e0ba190
add in start of etrog testnet changes
hexoscott Jan 2, 2024
1a05baf
genesis change for etrog
hexoscott Jan 4, 2024
39af408
feat(etrog): streamer block start updates
revitteth Jan 11, 2024
9631000
wip
revitteth Jan 11, 2024
ad2f39f
wip(etrog): limit stream, config
revitteth Jan 12, 2024
8076bf3
wip(etrog): implement backwards compatible stream sync
revitteth Jan 12, 2024
7b7d0de
wip(etrog): lxly 2x contracts support ver/seq
revitteth Jan 12, 2024
187297d
wip(etrog): remove l1 info root
revitteth Jan 12, 2024
42b7f0d
wip(etrog): ger
revitteth Jan 16, 2024
e05af77
wip(etrog): add l1inforoot from seq, fix db tests
revitteth Jan 19, 2024
6737f4a
fix(genesis): genesis_write missing var
revitteth Jan 24, 2024
cdf4fa0
Merge branch 'zkevm' into etrog
V-Staykov Jan 26, 2024
4605b01
rebase changes to _zkevm file
V-Staykov Jan 26, 2024
64825ca
fix compile
V-Staykov Jan 26, 2024
cb5eb59
added etrog state writes
V-Staykov Jan 29, 2024
1e5e21c
fix bugs
V-Staykov Jan 29, 2024
5f72f20
fixed pre etrog hashes
V-Staykov Jan 29, 2024
82ec2f3
Merge branch 'zkevm' into etrog
V-Staykov Jan 30, 2024
4a6dd1d
migrate fork checks
V-Staykov Jan 30, 2024
6e751dc
refactor and l1infoblocktree tests
V-Staykov Jan 30, 2024
03a0a88
finished block info tree impl
V-Staykov Feb 1, 2024
91cad32
merge zkevm
V-Staykov Feb 1, 2024
4790b1d
datastream update
V-Staykov Feb 1, 2024
bf83ee2
Merge branch 'zkevm' into etrog
V-Staykov Feb 2, 2024
67160e3
review comments fixes
V-Staykov Feb 2, 2024
38b2f74
Merge branch 'zkevm' into etrog
V-Staykov Feb 2, 2024
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
26 changes: 23 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,24 @@ var (
Usage: "Ethereum L1 RPC endpoint",
Value: "",
}
L1ContractAddressFlag = cli.StringFlag{
Name: "zkevm.l1-contract-address",
Usage: "Ethereum L1 contract address",
L1PolygonRollupManagerFlag = cli.StringFlag{
Name: "zkevm.l1-polygon-rollup-manager",
Usage: "Ethereum L1 Polygon Rollup Manager Address",
Value: "",
}
L1RollupFlag = cli.StringFlag{
Name: "zkevm.l1-rollup",
Usage: "Ethereum L1 Rollup Address",
Value: "",
}
L1TopicVerificationFlag = cli.StringFlag{
Name: "zkevm.l1-topic-verification",
Usage: "Ethereum L1 topic for verification",
Value: "",
}
L1TopicSequenceFlag = cli.StringFlag{
Name: "zkevm.l1-topic-sequence",
Usage: "Ethereum L1 topic for sequence",
Value: "",
}
L1BlockRangeFlag = cli.Uint64Flag{
Expand Down Expand Up @@ -412,6 +427,11 @@ var (
Usage: "RPC rate limit in requests per second.",
Value: 0,
}
DatastreamVersionFlag = cli.IntFlag{
Name: "zkevm.datastream-version",
Usage: "Stream version indicator 1: PreBigEndian, 2: BigEndian.",
Value: 1,
}
DataStreamPort = cli.UintFlag{
Name: "zkevm.data-stream-port",
Usage: "Define the port used for the zkevm data stream",
Expand Down
86 changes: 86 additions & 0 deletions core/allocs/hermez-etrog.json

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,6 @@ func ExecuteBlockEphemerally(
receipts = append(receipts, receipt)
}
}

// [zkevm] - set smt root hash in magic account
err = ibs.ScalableSetSmtRootHash(roHermezDb)
if err != nil {
return nil, err
}
}

receiptSha := types.DeriveSha(receipts)
Expand Down
280 changes: 280 additions & 0 deletions core/blockchain_zkevm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
// Copyright 2014 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/>.

// Package core implements the Ethereum consensus protocol.
package core

import (
"fmt"
"math/big"
"time"

libcommon "github.com/ledgerwatch/erigon-lib/common"

"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"
"github.com/ledgerwatch/erigon/consensus/misc"
"github.com/ledgerwatch/erigon/core/state"
"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,
blockHashFunc func(n uint64) libcommon.Hash,
engine consensus.Engine, block *types.Block,
stateReader state.StateReader,
stateWriter state.WriterWithChangeSets,
chainReader consensus.ChainHeaderReader,
getTracer func(txIndex int, txHash libcommon.Hash) (vm.EVMLogger, error),
dbTx kv.RwTx,
roHermezDb state.ReadOnlyHermezDb,
) (*EphemeralExecResult, error) {

defer BlockExecutionTimer.UpdateDuration(time.Now())
block.Uncles()
ibs := state.New(stateReader)
header := block.Header()

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

var (
rejectedTxs []*RejectedTx
includedTxs types.Transactions
receipts types.Receipts
)

var excessDataGas *big.Int
if chainReader != nil {
// TODO(eip-4844): understand why chainReader is sometimes nil (e.g. certain test cases)
ph := chainReader.GetHeaderByHash(block.ParentHash())
if ph != nil {
excessDataGas = ph.ExcessDataGas
}
}

if !vmConfig.ReadOnly {
if err := InitializeBlockExecution(engine, chainReader, block.Header(), block.Transactions(), block.Uncles(), chainConfig, ibs, excessDataGas); err != nil {
return nil, err
}
}

if chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number()) == 0 {
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 {
return nil, fmt.Errorf("failed to get last batch inserted: %v", err)
}

// write batches between last block and this if they exist
currentBatch, err := roHermezDb.GetBatchNoByL2Block(blockNum)
if err != nil {
return nil, err
}

//[zkevm] get batches between last block and this one
// plus this blocks ger
gersInBetween, err := roHermezDb.GetBatchGlobalExitRoots(lastBatchInserted, currentBatch)
if err != nil {
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, &stateRoot)

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
}

noop := state.NewNoopWriter()
cumulativeGasUsed := uint64(0)
logIndex := int64(0)
for txIndex, tx := range block.Transactions() {
ibs.Prepare(tx.Hash(), block.Hash(), txIndex)
writeTrace := false
if vmConfig.Debug && vmConfig.Tracer == nil {
tracer, err := getTracer(txIndex, tx.Hash())
if err != nil {
return nil, fmt.Errorf("could not obtain tracer: %w", err)
}
vmConfig.Tracer = tracer
writeTrace = true
}

gp.Reset(block.GasLimit())

effectiveGasPricePercentage, err := roHermezDb.GetEffectiveGasPricePercentage(tx.Hash())
if err != nil {
return nil, err
}

receipt, _, err := ApplyTransaction(chainConfig, blockHashFunc, engine, nil, gp, ibs, noop, header, tx, usedGas, *vmConfig, excessDataGas, effectiveGasPricePercentage)
if writeTrace {
if ftracer, ok := vmConfig.Tracer.(vm.FlushableTracer); ok {
ftracer.Flush(tx)
}

vmConfig.Tracer = nil
}

if err != nil {
if !vmConfig.StatelessExec {
return nil, fmt.Errorf("could not apply tx %d from block %d [%v]: %w", txIndex, block.NumberU64(), tx.Hash().Hex(), err)
}
rejectedTxs = append(rejectedTxs, &RejectedTx{txIndex, err.Error()})
} else {
includedTxs = append(includedTxs, tx)
if !vmConfig.NoReceipts {
receipts = append(receipts, receipt)
}
}
if !chainConfig.IsForkID7Etrog(block.NumberU64()) {
ibs.ScalableSetSmtRootHash(roHermezDb)
}

//block info tree
cumulativeGasUsed += receipt.GasUsed
_, err = blockInfoTree.SetBlockTx(
txIndex,
receipt,
logIndex,
cumulativeGasUsed,
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
}
l1InfoRoot := libcommon.BigToHash(root)
ibs.PostExecuteStateSet(chainConfig, block.NumberU64(), &l1InfoRoot, &stateRoot)

receiptSha := types.DeriveSha(receipts)
// [zkevm] todo
//if !vmConfig.StatelessExec && chainConfig.IsByzantium(header.Number.Uint64()) && !vmConfig.NoReceipts && receiptSha != block.ReceiptHash() {
// return nil, fmt.Errorf("mismatched receipt headers for block %d (%s != %s)", block.NumberU64(), receiptSha.Hex(), block.ReceiptHash().Hex())
//}

// in zkEVM we don't have headers to check GasUsed against
//if !vmConfig.StatelessExec && *usedGas != header.GasUsed && header.GasUsed > 0 {
// return nil, fmt.Errorf("gas used by execution: %d, in header: %d", *usedGas, header.GasUsed)
//}

var bloom types.Bloom
if !vmConfig.NoReceipts {
bloom = types.CreateBloom(receipts)
// [zkevm] todo
//if !vmConfig.StatelessExec && bloom != header.Bloom {
// return nil, fmt.Errorf("bloom computed by execution: %x, in header: %x", bloom, header.Bloom)
//}
}
if !vmConfig.ReadOnly {
txs := block.Transactions()
if _, _, _, err := FinalizeBlockExecution(engine, stateReader, block.Header(), txs, block.Uncles(), stateWriter, chainConfig, ibs, receipts, block.Withdrawals(), chainReader, false, excessDataGas); err != nil {
return nil, err
}
}
blockLogs := ibs.Logs()
execRs := &EphemeralExecResult{
TxRoot: types.DeriveSha(includedTxs),
ReceiptRoot: receiptSha,
Bloom: bloom,
LogsHash: rlpHash(blockLogs),
Receipts: receipts,
Difficulty: (*math.HexOrDecimal256)(header.Difficulty),
GasUsed: math.HexOrDecimal64(*usedGas),
Rejected: rejectedTxs,
}

return execRs, nil
}
3 changes: 2 additions & 1 deletion core/genesis_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,6 @@ func ChiadoGenesisBlock() *types.Genesis {
var DevnetSignPrivateKey, _ = crypto.HexToECDSA("26e86e45f6fc45ec6e2ecd128cec80fa1d1505e5507dcd2ae58c3130a7a97b48")
var DevnetEtherbase = libcommon.HexToAddress("67b1d87101671b127f5f8714789c7192f7ad340e")

// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(period uint64, faucet libcommon.Address) *types.Genesis {
// Override the default period to the user requested one
config := *params.AllCliqueProtocolChanges
Expand Down Expand Up @@ -656,6 +655,8 @@ func GenesisBlockByChainName(chain string) *types.Genesis {
return HermezTestnetGenesisBlock()
case networkname.HermezBlueberryChainName:
return HermezBlueberryGenesisBlock()
case networkname.HermezEtrogChainName:
return HermezEtrogGenesisBlock()
case networkname.HermezCardonaChainName:
return HermezCardonaGenesisBlock()
case networkname.HermezCardonaInternalChainName:
Expand Down
16 changes: 13 additions & 3 deletions core/genesis_write_zkevm.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package core

import (
"math/big"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/core/types"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/smt/pkg/smt"
"github.com/ledgerwatch/erigon/zkevm/hex"
"math/big"
)

func HermezMainnetGenesisBlock() *types.Genesis {
Expand Down Expand Up @@ -39,6 +39,16 @@ func HermezBlueberryGenesisBlock() *types.Genesis {
}
}

func HermezEtrogGenesisBlock() *types.Genesis {
return &types.Genesis{
Config: params.HermezEtrogChainConfig,
Timestamp: 1703260380,
GasLimit: 0x0,
Difficulty: big.NewInt(0x0),
Alloc: readPrealloc("allocs/hermez-etrog.json"),
}
}

func HermezCardonaGenesisBlock() *types.Genesis {
return &types.Genesis{
Config: params.HermezCardonaChainConfig,
Expand Down
Loading