Skip to content

Commit

Permalink
feat(config): dynamic config (#243)
Browse files Browse the repository at this point in the history
* feat(config): dynamic config

* fix(genesis): processAccount return correct root
  • Loading branch information
revitteth authored Apr 3, 2024
1 parent 99eb710 commit e0748e6
Show file tree
Hide file tree
Showing 15 changed files with 321 additions and 69 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ Current status of cdk-erigon's support for running various chains and fork ids:
- zkEVM mainnet — alpha support
- CDK Chains - experimental support (forkid.8 and above)

## Dynamic Chain Configuration
To use chains other than the defaults above, a set of configuration files can be supplied to run any chain.

1. Create a directory `~/dynamic-configs` (in the user home directory)
2. Ensure your chain name starts with the word `dynamic` e.g. `dynamic-mynetwork`
3. Create 3 files in dynamic configs (examples for Cardona in `zk/examples/dynamic-configs`):
- `dynamic-{network}-allocs.json` - the allocs file
- `dynamic-{network}-chainspec.json` - the chainspec file
- `dynamic-{network}-conf.json` - an additional configuration file
- Ensure to create a run configuration to set flags, with the network name beginning dynamic

This could be more concise, however we are attempting to retain upstream compatibility where possible.

Mount point for this folder on docker container: `~/dynamic-configs` (home directory of erigon user)

## Prereqs
In order to use the optimal vectorized poseidon hashing for the Sparse Merkle Tree, on x86 the following packages are required (for Apple silicon it will fall back to the iden3 library and as such these dependencies are not required in that case.

Expand All @@ -28,11 +43,11 @@ Using the Makefile command: `make build-libs` will install these for the relevan

Due to dependency requirements Go 1.19 is required to build.

## sequencer (WIP)
## Sequencer (WIP)

Enable Sequencer: `CDK_ERIGON_SEQUENCER=1 ./build/bin/cdk-erigon <flags>`

## zkevm-specific API Support
## zkEVM-specific API Support

In order to enable the zkevm_ namespace, please add 'zkevm' to the http.api flag (see the example config below).

Expand Down
3 changes: 3 additions & 0 deletions chain/chain_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ func (c *Config) CheckConfigForkOrder() error {
return zkchainconfig.CheckForkOrder()
}

// [dynamic fork]
return nil

var lastFork forkBlockNumber

for _, fork := range c.forkBlockNumbers() {
Expand Down
101 changes: 73 additions & 28 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ import (
"github.com/ledgerwatch/erigon/p2p/netutil"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/params/networkname"
"os"
"encoding/json"
"path"
)

// These are all the command line flags we support.
Expand Down Expand Up @@ -1544,6 +1547,13 @@ func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) {
}
}

type DynamicConfig struct {
Root string `json:"root"`
Timestamp uint64 `json:"timestamp"`
GasLimit uint64 `json:"gasLimit"`
Difficulty int64 `json:"difficulty"`
}

// CheckExclusive verifies that only a single instance of the provided flags was
// set by the user. Each flag might optionally be followed by a string type to
// specialize it further.
Expand Down Expand Up @@ -1677,41 +1687,76 @@ func SetEthConfig(ctx *cli.Context, nodeConfig *nodecfg.Config, cfg *ethconfig.C
}
// Override any default configs for hard coded networks.
chain := ctx.String(ChainFlag.Name)

switch chain {
default:
if strings.HasPrefix(chain, "dynamic") {
genesis := core.GenesisBlockByChainName(chain)
genesisHash := params.GenesisHashByChainName(chain)
if (genesis == nil) || (genesisHash == nil) {
Fatalf("ChainDB name is not recognized: %s", chain)
return
}
cfg.Genesis = genesis
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkID = params.NetworkIDByChainName(chain)

dConf := DynamicConfig{}

homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
SetDNSDiscoveryDefaults(cfg, *genesisHash)
case "":
if cfg.NetworkID == 1 {
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)

basePath := path.Join(homeDir, "dynamic-configs")
filename := path.Join(basePath, chain+"-conf.json")

if _, err := os.Stat(filename); err == nil {
dConfBytes, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
if err := json.Unmarshal(dConfBytes, &dConf); err != nil {
panic(err)
}
}
case networkname.DevChainName:

genesis.Timestamp = dConf.Timestamp
genesis.GasLimit = dConf.GasLimit
genesis.Difficulty = big.NewInt(dConf.Difficulty)

cfg.Genesis = genesis

genesisHash := libcommon.HexToHash(dConf.Root)
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkID = 1337
log.Warn("NetworkID is not set for dynamic chain", "chain", chain, "networkID", cfg.NetworkID)
}
SetDNSDiscoveryDefaults(cfg, genesisHash)
} else {
switch chain {
default:
genesis := core.GenesisBlockByChainName(chain)
genesisHash := params.GenesisHashByChainName(chain)
if (genesis == nil) || (genesisHash == nil) {
Fatalf("ChainDB name is not recognized: %s", chain)
return
}
cfg.Genesis = genesis
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkID = params.NetworkIDByChainName(chain)
}
SetDNSDiscoveryDefaults(cfg, *genesisHash)
case "":
if cfg.NetworkID == 1 {
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
}
case networkname.DevChainName:
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkID = 1337
}

// Create new developer account or reuse existing one
developer := cfg.Miner.Etherbase
if developer == (libcommon.Address{}) {
Fatalf("Please specify developer account address using --miner.etherbase")
}
log.Info("Using developer account", "address", developer)
// Create new developer account or reuse existing one
developer := cfg.Miner.Etherbase
if developer == (libcommon.Address{}) {
Fatalf("Please specify developer account address using --miner.etherbase")
}
log.Info("Using developer account", "address", developer)

// Create a new developer genesis block or reuse existing one
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), developer)
log.Info("Using custom developer period", "seconds", cfg.Genesis.Config.Clique.Period)
if !ctx.IsSet(MinerGasPriceFlag.Name) {
cfg.Miner.GasPrice = big.NewInt(1)
// Create a new developer genesis block or reuse existing one
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), developer)
log.Info("Using custom developer period", "seconds", cfg.Genesis.Config.Clique.Period)
if !ctx.IsSet(MinerGasPriceFlag.Name) {
cfg.Miner.GasPrice = big.NewInt(1)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/genesis_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,6 @@ func GenesisBlockByChainName(chain string) *types.Genesis {
case networkname.X1TestnetChainName:
return X1TestnetGenesisBlock()
default:
return nil
return DynamicGenesisBlock(chain)
}
}
43 changes: 40 additions & 3 deletions core/genesis_write_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/smt/pkg/smt"
"github.com/ledgerwatch/erigon/zkevm/hex"
"fmt"
"os"
"path"
"encoding/json"
)

func HermezMainnetGenesisBlock() *types.Genesis {
Expand Down Expand Up @@ -93,7 +97,7 @@ func X1TestnetGenesisBlock() *types.Genesis {
func processAccount(s *smt.SMT, root *big.Int, a *types.GenesisAccount, addr libcommon.Address) (*big.Int, error) {

// store the account balance and nonce
r, err := s.SetAccountState(addr.String(), a.Balance, new(big.Int).SetUint64(a.Nonce))
_, err := s.SetAccountState(addr.String(), a.Balance, new(big.Int).SetUint64(a.Nonce))
if err != nil {
return nil, err
}
Expand All @@ -114,10 +118,43 @@ func processAccount(s *smt.SMT, root *big.Int, a *types.GenesisAccount, addr lib

// store the account storage
if len(sm) > 0 {
r, err = s.SetContractStorage(addr.String(), sm, nil)
_, err = s.SetContractStorage(addr.String(), sm, nil)
if err != nil {
return nil, err
}
}
return r, nil
return s.LastRoot(), nil
}

func DynamicGenesisBlock(chain string) *types.Genesis {
return &types.Genesis{
Config: params.DynamicChainConfig(chain),
Timestamp: 0x0,
GasLimit: 0x0,
Difficulty: big.NewInt(0x0),
Alloc: dynamicPrealloc(chain),
}
}

func dynamicPrealloc(ch string) types.GenesisAlloc {
homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}

basePath := path.Join(homeDir, "dynamic-configs")
filename := path.Join(basePath, ch+"-allocs.json")

f, err := os.Open(filename)
if err != nil {
panic(fmt.Sprintf("could not open alloc for %s: %v", filename, err))
}
defer f.Close()
decoder := json.NewDecoder(f)
alloc := make(types.GenesisAlloc)
err = decoder.Decode(&alloc)
if err != nil {
panic(fmt.Sprintf("could not parse alloc for %s: %v", filename, err))
}
return alloc
}
7 changes: 4 additions & 3 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ import (
"sync"
"time"

"github.com/holiman/uint256"
erigonchain "github.com/gateway-fm/cdk-erigon-lib/chain"
"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon/zk/sequencer"
"github.com/ledgerwatch/log/v3"
"golang.org/x/exp/slices"
Expand Down Expand Up @@ -748,7 +748,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {

// entering ZK territory!
cfg := backend.config.Zk
backend.etherMan = newEtherMan(cfg)
backend.etherMan = newEtherMan(cfg, chainConfig.ChainName)

isSequencer := sequencer.IsSequencer()
var l1Topics [][]libcommon.Hash
Expand Down Expand Up @@ -884,11 +884,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}

// creates an EtherMan instance with default parameters
func newEtherMan(cfg *ethconfig.Zk) *etherman.Client {
func newEtherMan(cfg *ethconfig.Zk, l2ChainName string) *etherman.Client {
ethmanConf := etherman.Config{
URL: cfg.L1RpcUrl,
L1ChainID: cfg.L1ChainId,
L2ChainID: cfg.L2ChainId,
L2ChainName: l2ChainName,
PoEAddr: cfg.AddressRollup,
MaticAddr: cfg.L1MaticContractAddress,
GlobalExitRootManagerAddr: cfg.AddressGerManager,
Expand Down
2 changes: 1 addition & 1 deletion params/chainspecs/hermez-bali.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"ChainName": "bali",
"ChainName": "hermez-bali",
"chainId": 2440,
"consensus": "ethash",
"homesteadBlock": 0,
Expand Down
2 changes: 1 addition & 1 deletion params/chainspecs/hermez-cardona.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"ChainName": "devnet",
"ChainName": "hermez-cardona",
"chainId": 2442,
"consensus": "ethash",
"homesteadBlock": 0,
Expand Down
31 changes: 27 additions & 4 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/ledgerwatch/erigon/chain"
"github.com/ledgerwatch/erigon/common/paths"
"github.com/ledgerwatch/erigon/params/networkname"
"os"
)

//go:embed chainspecs
Expand Down Expand Up @@ -65,8 +66,8 @@ var (
HermezESTestGenesisHash = libcommon.HexToHash("0x8c630b598fab24a99b59cdd8257f41b35d0aca992f13cd381c7591f5e89eec58")
HermezCardonaGenesisHash = libcommon.HexToHash("0x676c1a76a6c5855a32bdf7c61977a0d1510088a4eeac1330466453b3d08b60b9")
HermezCardonaInternalGenesisHash = libcommon.HexToHash("0x7311011ce6ab98ef0a15e44fe29f7680909588322534d1736361daa678543038")
X1TestnetGenesisHash = libcommon.HexToHash("0x0ffb92e130f1acaabd8b12aa1bb409b46561ef7568cb8aa7eb8d102a6ab76566")
HermezEtrogGenesisHash = libcommon.HexToHash("0xccfed260e3ef666b058dcd577551de8e00c743c47774a39ca7dbcd9214ba370a")
X1TestnetGenesisHash = libcommon.HexToHash("0x22a8085892b367833bd7431fa5a90ff6b5d3769167cdaa29ce8571d07bc8f866")
HermezEtrogGenesisHash = libcommon.HexToHash("0x5e14aefe391fafa040ee0a0fff6afbc1c230853b9684afb9363f3af081db0192")
)

var (
Expand Down Expand Up @@ -200,6 +201,29 @@ type ConsensusSnapshotConfig struct {

const cliquePath = "clique"

func DynamicChainConfig(ch string) *chain.Config {
homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}

basePath := path.Join(homeDir, "dynamic-configs")
filename := path.Join(basePath, ch+"-chainspec.json")

f, err := os.Open(filename)
if err != nil {
panic(fmt.Sprintf("could not open chainspec for %s: %v", filename, err))
}
defer f.Close()
decoder := json.NewDecoder(f)
spec := &chain.Config{}
err = decoder.Decode(&spec)
if err != nil {
panic(fmt.Sprintf("could not parse chainspec for %s: %v", filename, err))
}
return spec
}

func NewSnapshotConfig(checkpointInterval uint64, inmemorySnapshots int, inmemorySignatures int, inmemory bool, dbPath string) *ConsensusSnapshotConfig {
if len(dbPath) == 0 {
dbPath = paths.DefaultDataDir()
Expand Down Expand Up @@ -251,7 +275,7 @@ func ChainConfigByChainName(chain string) *chain.Config {
case networkname.X1TestnetChainName:
return X1TestnetChainConfig
default:
return nil
return DynamicChainConfig(chain)
}
}

Expand Down Expand Up @@ -329,7 +353,6 @@ func ChainConfigByGenesisHash(genesisHash libcommon.Hash) *chain.Config {
case genesisHash == HermezCardonaInternalGenesisHash:
return HermezBaliChainConfig
default:
panic(fmt.Sprintf("Unknown genesis hash: %s", genesisHash.Hex()))
return nil
}
}
Expand Down
Loading

0 comments on commit e0748e6

Please sign in to comment.