github.com/klaytn/klaytn@v1.12.1/governance/contract_test.go (about) 1 // Copyright 2022 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package governance 18 19 import ( 20 "math/big" 21 "testing" 22 23 "github.com/klaytn/klaytn/accounts/abi/bind" 24 "github.com/klaytn/klaytn/accounts/abi/bind/backends" 25 "github.com/klaytn/klaytn/blockchain" 26 "github.com/klaytn/klaytn/blockchain/types" 27 "github.com/klaytn/klaytn/common" 28 govcontract "github.com/klaytn/klaytn/contracts/gov" 29 "github.com/klaytn/klaytn/crypto" 30 "github.com/klaytn/klaytn/params" 31 "github.com/klaytn/klaytn/storage/database" 32 "github.com/stretchr/testify/assert" 33 "github.com/stretchr/testify/require" 34 ) 35 36 func prepareSimulatedContract(t *testing.T) ([]*bind.TransactOpts, *backends.SimulatedBackend, common.Address, *govcontract.GovParam) { 37 // Create accounts and simulated blockchain 38 accounts := []*bind.TransactOpts{} 39 alloc := blockchain.GenesisAlloc{} 40 for i := 0; i < 1; i++ { 41 key, _ := crypto.GenerateKey() 42 account := bind.NewKeyedTransactor(key) 43 account.GasLimit = 10000000 44 accounts = append(accounts, account) 45 alloc[account.From] = blockchain.GenesisAccount{Balance: big.NewInt(params.KLAY)} 46 } 47 config := ¶ms.ChainConfig{} 48 config.SetDefaults() 49 config.UnitPrice = 25e9 50 config.IstanbulCompatibleBlock = common.Big0 51 config.LondonCompatibleBlock = common.Big0 52 config.EthTxTypeCompatibleBlock = common.Big0 53 config.MagmaCompatibleBlock = common.Big0 54 config.KoreCompatibleBlock = common.Big0 55 56 sim := backends.NewSimulatedBackendWithDatabase(database.NewMemoryDBManager(), alloc, config) 57 58 // Deploy contract 59 owner := accounts[0] 60 address, tx, contract, err := govcontract.DeployGovParam(owner, sim) 61 require.Nil(t, err) 62 sim.Commit() 63 64 receipt, _ := sim.TransactionReceipt(nil, tx.Hash()) 65 require.NotNil(t, receipt) 66 require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 67 68 return accounts, sim, address, contract 69 } 70 71 func prepareSimulatedContractWithParams(t *testing.T, params map[string][]byte) ([]*bind.TransactOpts, *backends.SimulatedBackend, common.Address, *govcontract.GovParam) { 72 // Create accounts and simulated blockchain 73 accounts, sim, address, contract := prepareSimulatedContract(t) 74 owner := accounts[0] 75 76 for name, val := range params { 77 tx, err := contract.SetParamIn(owner, name, true, val, big.NewInt(1)) 78 require.Nil(t, err) 79 sim.Commit() 80 81 // check tx success 82 receipt, _ := sim.TransactionReceipt(nil, tx.Hash()) 83 require.NotNil(t, receipt) 84 require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 85 } 86 87 ab := new(big.Int).Set(sim.BlockChain().CurrentHeader().Number) 88 ab = ab.Add(ab, big.NewInt(1)) 89 90 // check with govcontract 91 names, values, err := contract.GetAllParamsAt(nil, ab) 92 require.Nil(t, err) 93 require.Equal(t, len(params), len(names)) 94 require.Equal(t, len(params), len(values)) 95 96 returned := make(map[string][]byte) 97 for i := 0; i < len(names); i++ { 98 returned[names[i]] = values[i] 99 } 100 101 require.Equal(t, params, returned) 102 103 return accounts, sim, address, contract 104 } 105 106 func prepareContractEngine(t *testing.T, bc *blockchain.BlockChain, addr common.Address) *ContractEngine { 107 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 108 dbm.WriteGovernance(map[string]interface{}{ 109 "governance.govparamcontract": addr, 110 }, 0) 111 gov := NewGovernance(bc.Config(), dbm) 112 pset, err := gov.EffectiveParams(0) 113 require.Nil(t, err) 114 require.Equal(t, addr, pset.GovParamContract()) 115 116 gov.SetBlockchain(bc) 117 118 e := NewContractEngine(gov) 119 err = e.UpdateParams(bc.CurrentBlock().NumberU64()) 120 require.Nil(t, err) 121 122 return e 123 } 124 125 // TestContractEngine_Params tests if CurrentParams() returns the parameters required 126 // for generating the next block. That is, 127 // 128 // start setparam activation-1 end 129 // 130 // Block |---------------|---------------|---------------| 131 // 132 // ..............^ ^ ^ 133 // ..............t0 t1 t2 134 // 135 // At num = activation - 2, CurrentParams() = prev 136 // At num = activation - 1, CurrentParams() = next 137 // 138 // because next is for generating "activation" block 139 func TestContractEngine_Params(t *testing.T) { 140 initialParam := map[string][]byte{ 141 "istanbul.committeesize": {0xa}, 142 "governance.unitprice": {0xb}, 143 } 144 accounts, sim, addr, contract := prepareSimulatedContractWithParams(t, initialParam) 145 146 e := prepareContractEngine(t, sim.BlockChain(), addr) 147 148 var ( 149 start = sim.BlockChain().CurrentBlock().NumberU64() 150 setparam = start + 5 151 activation = setparam + 5 152 end = activation + 5 153 key = "governance.unitprice" 154 val = []byte{0xff, 0xff, 0xff, 0xff} 155 update, _ = params.NewGovParamSetBytesMap(map[string][]byte{ 156 key: val, 157 }) 158 psetPrev, _ = params.NewGovParamSetBytesMap(initialParam) // for t0 & t1 159 psetNext = params.NewGovParamSetMerged(psetPrev, update) // for t2 160 owner = accounts[0] 161 ) 162 163 for num := start; num < end; num++ { 164 if num == setparam { // setParam 165 contract.SetParam(owner, key, true, val, new(big.Int).SetUint64(activation)) 166 } 167 168 var expected *params.GovParamSet 169 170 if num < activation-1 { // t0 & t1 171 expected = psetPrev 172 } else { // t2 173 expected = psetNext 174 } 175 176 assert.Equal(t, expected, e.CurrentParams(), "CurrentParams() on block %d failed", num) 177 sim.Commit() 178 err := e.UpdateParams(sim.BlockChain().CurrentBlock().NumberU64()) 179 assert.Nil(t, err) 180 } 181 } 182 183 // TestContractEngine_ParamsAt tests if EffectiveParams(num) returns the parameters 184 // required for generating the "num" block. That is, 185 // 186 // start setparam activation end 187 // 188 // Block |---------------|---------------|---------------| 189 // 190 // ..............^ ^ ^ 191 // ..............t0 t1 t2 192 // 193 // EffectiveParams(activation - 1) = prev 194 // EffectiveParams(activation) = next 195 func TestContractEngine_ParamsAt(t *testing.T) { 196 initialParam := map[string][]byte{ 197 "istanbul.committeesize": {0xa}, 198 "governance.unitprice": {0xbb, 0xbb, 0xbb, 0xbb}, 199 } 200 accounts, sim, addr, contract := prepareSimulatedContractWithParams(t, initialParam) 201 202 e := prepareContractEngine(t, sim.BlockChain(), addr) 203 204 var ( 205 start = sim.BlockChain().CurrentBlock().NumberU64() 206 setparam = start + 5 207 activation = setparam + 5 208 end = activation + 5 209 key = "governance.unitprice" 210 val = []byte{0xff, 0xff, 0xff, 0xff} 211 update, _ = params.NewGovParamSetBytesMap(map[string][]byte{ 212 key: val, 213 }) 214 psetPrev, _ = params.NewGovParamSetBytesMap(initialParam) // for t0 & t1 215 psetNext = params.NewGovParamSetMerged(psetPrev, update) // for t2 216 owner = accounts[0] 217 ) 218 219 for num := start; num < end; num++ { 220 if num == setparam { // setParam 221 contract.SetParam(owner, key, true, val, new(big.Int).SetUint64(activation)) 222 } 223 224 for iter := start + 1; iter <= num; iter++ { 225 var expected *params.GovParamSet 226 227 if iter < activation { // t0 & t1 228 expected = psetPrev 229 } else { // t2 230 expected = psetNext 231 } 232 233 result, _ := e.EffectiveParams(iter) 234 assert.Equal(t, expected, result, "EffectiveParams(%d) on block %d failed", iter, num) 235 } 236 237 sim.Commit() 238 err := e.UpdateParams(sim.BlockChain().CurrentBlock().NumberU64()) 239 assert.Nil(t, err) 240 } 241 }