I have a Proof-of-Authority private Ethereum network that has Byzantium EVM version and created by clique engine. I have a single miner that has Geth version: v1.8.27.

  "config": {
    "chainId": 23422,
    "homesteadBlock": 1,
    "eip150Block": 2,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 3,
    "eip158Block": 3,
    "byzantiumBlock": 4,
    "clique": {
      "period": 15,
      "epoch": 30000

Please see my configuration file: custom.json.

When I start geth I get following output:

INFO [07-10|13:46:36.647] Initialised chain configuration          
config="{ChainID: 23422 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2
EIP155: 3 EIP158: 3 Byzantium: 4 Constantinople: <nil>  
Petersburg: <nil> Engine: clique}"

I assume since Constantinople: <nil> in the configuration file and I cannot alter the custom configuration file there is no way I can hard fork the private chain.


The configuration is fixed via constants in the code (see ChainConfig). A custom configuration can be provided in genesis specification file, however, this is only applicable when setting up a new chain.

Hence, currently the only way to make a hard fork in a private network is to ensure that all participants shutdown/upgrade/restart in a predefined time slot.

// I have updated the geth version but in general I am not sure to check that whether the private chain is updated.

[Q] I was wondering, is it possible to hard fork a private chain that has different EVM version to Constantinople EVM?

1 Answer 1


Simply, we need to do the same things as ethereum do for their networks on your chain.

We have two options:

1. First is do like this answer

How to setup constantinople fork for private ethereum chain

2. Modify config in the source code as below step

Update the config as relevant with your config.json file in below file

Update config.go in https://github.com/ethereum/go-ethereum/blob/49a7ee460e839499ef41f5110b219ec8c8edc5e8/params/config.go#L66

In your case, the config.go should be like below

    // MainnetChainConfig is the chain parameters to run a node on the main network.
    MainnetChainConfig = &ChainConfig{
        ChainID:             big.NewInt(23422),
        HomesteadBlock:      big.NewInt(1),
        DAOForkBlock:        nil,
        DAOForkSupport:      true,
        EIP150Block:         big.NewInt(2),
        EIP150Hash:          common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
        EIP155Block:         big.NewInt(3),
        EIP158Block:         big.NewInt(3),
        ByzantiumBlock:      big.NewInt(4),
        ConstantinopleBlock: big.NewInt(xxxxxx),
        PetersburgBlock:     big.NewInt(xxxxxx),
        Clique: &CliqueConfig{
            Period: 15,
            Epoch:  30000,

xxxxxx is the future block number you want to do hardfork on your private chain.

Furthermore, PetersburgBlock is the Constantinople Fix due to a security hole of Constantinople found by chainsecurity details on below link


The upcoming Constantinople Upgrade for the ethereum network introduces cheaper gas cost for certain SSTORE operations. As an unwanted side effect, this enables reentrancy attacks when using address.transfer(...) or address.send(...) in Solidity smart contracts. Previously these functions were considered reentrancy-safe, which they aren’t any longer.

Then for the chain that still not enable Constantinople, the ConstantinopleBlock and PetersburgBlock will be the same block number.

And we need to create the genesis allocation constants in genesis_alloc.go also by running mkalloc like in the guide in below guidance.


Then modify the default genesis block on this below line also


you can do sanity check by looking into the output log; Constantinople and Petersburg must display the block number that we set on the config.go

INFO [07-10|13:46:36.647] Initialised chain configuration          
config="{ChainID: 23422 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2
EIP155: 3 EIP158: 3 Byzantium: 4 Constantinople: <xxxxxx>  
Petersburg: <xxxxxx> Engine: clique}"

Hope this will help!

  • Should I add ConstantinopleBlock: big.NewInt(<blockNumber>) into my custom.json file and re-run the signer nodes? But the configuration is fixed I cannot update it @Ha ĐANG
    – alper
    Commented Jul 13, 2019 at 13:14
  • Seems not, we can only use config file once time when running geth init
    – Tony Dang
    Commented Jul 13, 2019 at 13:28
  • 1
    the config in source code will overwrite the existing config then we dont need worry about that; even ethereum mainnet also need to do the same way
    – Tony Dang
    Commented Jul 13, 2019 at 13:31
  • Should only the signer nodes make this change on the go-ethereum/params/config.go file? or all the connected nodes to the private-network as well? @Ha ĐANG
    – alper
    Commented Jul 13, 2019 at 22:34
  • 1
    Totally right! By the way, the config was fixed when the hard fork number was decided. Then client only need to get the latest source code to run other than update the code by themselves
    – Tony Dang
    Commented Jul 14, 2019 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.