github.com/klaytn/klaytn@v1.12.1/cmd/homi/genesis/options.go (about)

     1  // Copyright 2018 The klaytn Authors
     2  // Copyright 2017 AMIS Technologies
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package genesis
    19  
    20  import (
    21  	"math/big"
    22  	"strings"
    23  
    24  	"github.com/klaytn/klaytn/blockchain/system"
    25  	"github.com/klaytn/klaytn/cmd/homi/extra"
    26  	"github.com/klaytn/klaytn/consensus/clique"
    27  	"github.com/klaytn/klaytn/contracts/reward/contract"
    28  	"github.com/klaytn/klaytn/log"
    29  	"github.com/klaytn/klaytn/params"
    30  
    31  	"github.com/klaytn/klaytn/blockchain"
    32  	"github.com/klaytn/klaytn/common"
    33  	"github.com/klaytn/klaytn/common/hexutil"
    34  )
    35  
    36  type Option func(*blockchain.Genesis)
    37  
    38  var logger = log.NewModuleLogger(log.CMDIstanbul)
    39  
    40  func Validators(addrs ...common.Address) Option {
    41  	return func(genesis *blockchain.Genesis) {
    42  		extraData, err := extra.Encode("0x00", addrs)
    43  		if err != nil {
    44  			logger.Error("Failed to encode extra data", "err", err)
    45  			return
    46  		}
    47  		genesis.ExtraData = hexutil.MustDecode(extraData)
    48  	}
    49  }
    50  
    51  func ValidatorsOfClique(signers ...common.Address) Option {
    52  	return func(genesis *blockchain.Genesis) {
    53  		genesis.ExtraData = make([]byte, clique.ExtraVanity+len(signers)*common.AddressLength+clique.ExtraSeal)
    54  		for i, signer := range signers {
    55  			copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:])
    56  		}
    57  	}
    58  }
    59  
    60  func makeGenesisAccount(addrs []common.Address, balance *big.Int) map[common.Address]blockchain.GenesisAccount {
    61  	alloc := make(map[common.Address]blockchain.GenesisAccount)
    62  	for _, addr := range addrs {
    63  		alloc[addr] = blockchain.GenesisAccount{Balance: balance}
    64  	}
    65  	return alloc
    66  }
    67  
    68  func Alloc(addrs []common.Address, balance *big.Int) Option {
    69  	return func(genesis *blockchain.Genesis) {
    70  		alloc := makeGenesisAccount(addrs, balance)
    71  		genesis.Alloc = alloc
    72  	}
    73  }
    74  
    75  func AllocWithPrecypressContract(addrs []common.Address, balance *big.Int) Option {
    76  	return func(genesis *blockchain.Genesis) {
    77  		alloc := makeGenesisAccount(addrs, balance)
    78  		alloc[common.HexToAddress(contract.CypressCreditContractAddress)] = blockchain.GenesisAccount{
    79  			Code:    common.FromHex(CypressCreditBin),
    80  			Balance: big.NewInt(0),
    81  		}
    82  		alloc[common.HexToAddress(contract.AddressBookContractAddress)] = blockchain.GenesisAccount{
    83  			Code:    common.FromHex(PreCypressAddressBookBin),
    84  			Balance: big.NewInt(0),
    85  		}
    86  		genesis.Alloc = alloc
    87  	}
    88  }
    89  
    90  func AllocWithCypressContract(addrs []common.Address, balance *big.Int) Option {
    91  	return func(genesis *blockchain.Genesis) {
    92  		alloc := makeGenesisAccount(addrs, balance)
    93  		alloc[common.HexToAddress(contract.CypressCreditContractAddress)] = blockchain.GenesisAccount{
    94  			Code:    common.FromHex(CypressCreditBin),
    95  			Balance: big.NewInt(0),
    96  		}
    97  		alloc[common.HexToAddress(contract.AddressBookContractAddress)] = blockchain.GenesisAccount{
    98  			Code:    common.FromHex(CypressAddressBookBin),
    99  			Balance: big.NewInt(0),
   100  		}
   101  		genesis.Alloc = alloc
   102  	}
   103  }
   104  
   105  func AllocWithPrebaobabContract(addrs []common.Address, balance *big.Int) Option {
   106  	return func(genesis *blockchain.Genesis) {
   107  		alloc := makeGenesisAccount(addrs, balance)
   108  		alloc[common.HexToAddress(contract.AddressBookContractAddress)] = blockchain.GenesisAccount{
   109  			Code:    common.FromHex(PrebaobabAddressBookBin),
   110  			Balance: big.NewInt(0),
   111  		}
   112  		genesis.Alloc = alloc
   113  	}
   114  }
   115  
   116  func AllocWithBaobabContract(addrs []common.Address, balance *big.Int) Option {
   117  	return func(genesis *blockchain.Genesis) {
   118  		alloc := makeGenesisAccount(addrs, balance)
   119  		alloc[common.HexToAddress(contract.AddressBookContractAddress)] = blockchain.GenesisAccount{
   120  			Code:    common.FromHex(BaobabAddressBookBin),
   121  			Balance: big.NewInt(0),
   122  		}
   123  		genesis.Alloc = alloc
   124  	}
   125  }
   126  
   127  // Patch the hardcoded line in AddressBook.sol:constructContract().
   128  func PatchAddressBook(addr common.Address) Option {
   129  	return func(genesis *blockchain.Genesis) {
   130  		contractAddr := common.HexToAddress(contract.AddressBookContractAddress)
   131  		contractAccount, ok := genesis.Alloc[contractAddr]
   132  		if !ok {
   133  			log.Fatalf("No AddressBook to patch")
   134  		}
   135  
   136  		codeHex := hexutil.Encode(contractAccount.Code)
   137  		var oldAddr string
   138  		switch codeHex {
   139  		case CypressAddressBookBin:
   140  			oldAddr = "854ca8508c8be2bb1f3c244045786410cb7d5d0a"
   141  		case BaobabAddressBookBin:
   142  			oldAddr = "88bb3838aa0a140acb73eeb3d4b25a8d3afd58d4"
   143  		case PreCypressAddressBookBin, PrebaobabAddressBookBin:
   144  			oldAddr = "fe1ffd5293fc94857a33dcd284fe82bc106be4c7"
   145  		}
   146  
   147  		// The hardcoded address appears exactly once, hence Replace(.., 1)
   148  		newAddr := strings.ToLower(addr.Hex()[2:])
   149  		codeHex = strings.Replace(codeHex, oldAddr, newAddr, 1)
   150  
   151  		genesis.Alloc[contractAddr] = blockchain.GenesisAccount{
   152  			Code:    common.FromHex(codeHex),
   153  			Balance: contractAccount.Balance,
   154  		}
   155  	}
   156  }
   157  
   158  func AddressBookMock() Option {
   159  	return func(genesis *blockchain.Genesis) {
   160  		contractAddr := common.HexToAddress(contract.AddressBookContractAddress)
   161  		contractAccount, ok := genesis.Alloc[contractAddr]
   162  		if !ok {
   163  			log.Fatalf("No AddressBook to patch")
   164  		}
   165  
   166  		code := contract.AddressBookMockBinRuntime
   167  		genesis.Alloc[contractAddr] = blockchain.GenesisAccount{
   168  			Code:    common.FromHex(code),
   169  			Balance: contractAccount.Balance,
   170  		}
   171  	}
   172  }
   173  
   174  func AllocateRegistry(storage map[common.Hash]common.Hash) Option {
   175  	return func(genesis *blockchain.Genesis) {
   176  		registryCode := system.RegistryCode
   177  		registryAddr := system.RegistryAddr
   178  
   179  		genesis.Alloc[registryAddr] = blockchain.GenesisAccount{
   180  			Code:    registryCode,
   181  			Storage: storage,
   182  			Balance: big.NewInt(0),
   183  		}
   184  	}
   185  }
   186  
   187  func RegistryMock() Option {
   188  	return func(genesis *blockchain.Genesis) {
   189  		registryMockCode := system.RegistryMockCode
   190  		registryAddr := system.RegistryAddr
   191  
   192  		registry, ok := genesis.Alloc[registryAddr]
   193  		if !ok {
   194  			log.Fatalf("No registry to patch")
   195  		}
   196  
   197  		genesis.Alloc[registryAddr] = blockchain.GenesisAccount{
   198  			Code:    registryMockCode,
   199  			Storage: registry.Storage,
   200  			Balance: big.NewInt(0),
   201  		}
   202  	}
   203  }
   204  
   205  func AllocateKip113(kip113ProxyAddr, kip113LogicAddr common.Address, proxyStorage, logicStorage map[common.Hash]common.Hash) Option {
   206  	return func(genesis *blockchain.Genesis) {
   207  		proxyCode := system.ERC1967ProxyCode
   208  		logicCode := system.Kip113Code
   209  
   210  		genesis.Alloc[kip113ProxyAddr] = blockchain.GenesisAccount{
   211  			Code:    proxyCode,
   212  			Storage: proxyStorage,
   213  			Balance: big.NewInt(0),
   214  		}
   215  		genesis.Alloc[kip113LogicAddr] = blockchain.GenesisAccount{
   216  			Code:    logicCode,
   217  			Storage: logicStorage,
   218  			Balance: big.NewInt(0),
   219  		}
   220  	}
   221  }
   222  
   223  func Kip113Mock(kip113LogicAddr common.Address) Option {
   224  	return func(genesis *blockchain.Genesis) {
   225  		kip113MockCode := system.Kip113MockCode
   226  
   227  		_, ok := genesis.Alloc[kip113LogicAddr]
   228  		if !ok {
   229  			log.Fatalf("No kip113 to patch")
   230  		}
   231  
   232  		genesis.Alloc[kip113LogicAddr] = blockchain.GenesisAccount{
   233  			Code:    kip113MockCode,
   234  			Balance: big.NewInt(0),
   235  		}
   236  	}
   237  }
   238  
   239  func ChainID(chainID *big.Int) Option {
   240  	return func(genesis *blockchain.Genesis) {
   241  		genesis.Config.ChainID = chainID
   242  	}
   243  }
   244  
   245  func UnitPrice(price uint64) Option {
   246  	return func(genesis *blockchain.Genesis) {
   247  		genesis.Config.UnitPrice = price
   248  	}
   249  }
   250  
   251  func Istanbul(config *params.IstanbulConfig) Option {
   252  	return func(genesis *blockchain.Genesis) {
   253  		genesis.Config.Istanbul = config
   254  	}
   255  }
   256  
   257  func DeriveShaImpl(impl int) Option {
   258  	return func(genesis *blockchain.Genesis) {
   259  		genesis.Config.DeriveShaImpl = impl
   260  	}
   261  }
   262  
   263  func Governance(config *params.GovernanceConfig) Option {
   264  	return func(genesis *blockchain.Genesis) {
   265  		genesis.Config.Governance = config
   266  	}
   267  }
   268  
   269  func Clique(config *params.CliqueConfig) Option {
   270  	return func(genesis *blockchain.Genesis) {
   271  		genesis.Config.Clique = config
   272  	}
   273  }
   274  
   275  func StakingInterval(interval uint64) Option {
   276  	return func(genesis *blockchain.Genesis) {
   277  		genesis.Config.Governance.Reward.StakingUpdateInterval = interval
   278  	}
   279  }
   280  
   281  func ProposerInterval(interval uint64) Option {
   282  	return func(genesis *blockchain.Genesis) {
   283  		genesis.Config.Governance.Reward.ProposerUpdateInterval = interval
   284  	}
   285  }