github.com/klaytn/klaytn@v1.10.2/tests/hard_fork_test.go (about) 1 // Copyright 2019 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 tests 18 19 import ( 20 "crypto/ecdsa" 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "math/big" 25 "os" 26 "strings" 27 "testing" 28 "time" 29 30 "github.com/klaytn/klaytn/blockchain" 31 "github.com/klaytn/klaytn/blockchain/types" 32 "github.com/klaytn/klaytn/blockchain/vm" 33 "github.com/klaytn/klaytn/common" 34 "github.com/klaytn/klaytn/common/hexutil" 35 "github.com/klaytn/klaytn/common/profile" 36 "github.com/klaytn/klaytn/consensus/istanbul" 37 "github.com/klaytn/klaytn/crypto" 38 "github.com/klaytn/klaytn/governance" 39 "github.com/klaytn/klaytn/log" 40 "github.com/klaytn/klaytn/params" 41 "github.com/klaytn/klaytn/rlp" 42 "github.com/klaytn/klaytn/storage/database" 43 "github.com/stretchr/testify/assert" 44 "github.com/stretchr/testify/require" 45 46 istanbulBackend "github.com/klaytn/klaytn/consensus/istanbul/backend" 47 ) 48 49 // TestHardForkBlock tests whether the change incurs a hard fork or not. 50 // genesis.json, b1.rlp, and b2.rlp has raw data of genesis, and consecutive two blocks after the genesis block. 51 // If anything is failed, it can be considered that a hard fork occurs. 52 func TestHardForkBlock(t *testing.T) { 53 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 54 var genesis blockchain.Genesis 55 56 // If you uncomment the below, you can find this test failed with an error "!!!!!HARD FORK DETECTED!!!!!" 57 //fork.UpdateHardForkConfig(&fork.HardForkConfig{ 58 //}) 59 60 // If you print out b1.rlp and b2.rlp, uncomment below. 61 // `genBlocks` could be failed sometimes depends on the order of transaction in a block. Just try again. 62 // genBlocks(t) 63 // return 64 65 // load raw data from files. 66 genesisJson, err := ioutil.ReadFile("genesis.json") 67 require.Equal(t, nil, err) 68 rawb1, err := ioutil.ReadFile("b1.rlp") 69 require.Equal(t, nil, err) 70 rawb2, err := ioutil.ReadFile("b2.rlp") 71 require.Equal(t, nil, err) 72 73 err = json.Unmarshal([]byte(genesisJson), &genesis) 74 require.Equal(t, nil, err) 75 76 genesisKey, err := crypto.HexToECDSA("42eb1412d77987043716f425964b1c8d4c27ce9fb3e9a5b9ab243bc9882fe731") 77 require.Equal(t, nil, err) 78 79 var genesisAddr common.Address 80 for addr := range genesis.Alloc { 81 genesisAddr = addr 82 break 83 } 84 85 dir := "chaindata-hardfork" 86 os.RemoveAll(dir) 87 88 chainDb := NewDatabase(dir, database.LevelDB) 89 defer func() { 90 os.RemoveAll(dir) 91 }() 92 93 gov := generateGovernaceDataForTest() 94 chainConfig, _, err := blockchain.SetupGenesisBlock(chainDb, &genesis, params.UnusedNetworkId, false, false) 95 governance.AddGovernanceCacheForTest(gov, 0, genesis.Config) 96 engine := istanbulBackend.New(genesisAddr, istanbul.DefaultConfig, genesisKey, chainDb, gov, common.CONSENSUSNODE) 97 chain, err := blockchain.NewBlockChain(chainDb, nil, chainConfig, engine, vm.Config{}) 98 99 r1, err := hexutil.Decode(string(rawb1)) 100 require.Equal(t, nil, err) 101 r2, err := hexutil.Decode(string(rawb2)) 102 require.Equal(t, nil, err) 103 rawBlocks := [...][]byte{r1, r2} 104 105 var blocks types.Blocks 106 for _, raw := range rawBlocks { 107 var blk types.Block 108 109 err := rlp.DecodeBytes(raw, &blk) 110 require.Equal(t, nil, err) 111 112 blocks = append(blocks, &blk) 113 } 114 115 idx, err := chain.InsertChain(blocks) 116 require.Equalf(t, nil, err, "!!!!!HARD FORK DETECTED!!!!!") 117 require.Equal(t, 0, idx) 118 } 119 120 // genBlock generates two blocks including transactions utilizing all transaction types and account types. 121 func genBlocks(t *testing.T) { 122 testFunctions := []struct { 123 Name string 124 genTx genTransaction 125 }{ 126 {"LegacyTransaction", genLegacyTransaction}, 127 {"ValueTransfer", genValueTransfer}, 128 {"ValueTransferWithMemo", genValueTransferWithMemo}, 129 {"AccountUpdate", genAccountUpdateIdem}, 130 {"SmartContractExecution", genSmartContractExecution}, 131 {"Cancel", genCancel}, 132 {"ChainDataAnchoring", genChainDataAnchoring}, 133 {"FeeDelegatedValueTransfer", genFeeDelegatedValueTransfer}, 134 {"FeeDelegatedValueTransferWithMemo", genFeeDelegatedValueTransferWithMemo}, 135 {"FeeDelegatedAccountUpdate", genFeeDelegatedAccountUpdateIdem}, 136 {"FeeDelegatedSmartContractExecution", genFeeDelegatedSmartContractExecution}, 137 {"FeeDelegatedCancel", genFeeDelegatedCancel}, 138 {"FeeDelegatedWithRatioValueTransfer", genFeeDelegatedWithRatioValueTransfer}, 139 {"FeeDelegatedWithRatioValueTransferWithMemo", genFeeDelegatedWithRatioValueTransferWithMemo}, 140 {"FeeDelegatedWithRatioAccountUpdate", genFeeDelegatedWithRatioAccountUpdateIdem}, 141 {"FeeDelegatedWithRatioSmartContractExecution", genFeeDelegatedWithRatioSmartContractExecution}, 142 {"FeeDelegatedWithRatioCancel", genFeeDelegatedWithRatioCancel}, 143 } 144 145 accountTypes := []struct { 146 Type string 147 account TestAccount 148 }{ 149 {"KlaytnLegacy", genKlaytnLegacyAccount(t)}, 150 {"Public", genPublicAccount(t)}, 151 {"MultiSig", genMultiSigAccount(t)}, 152 {"RoleBasedWithPublic", genRoleBasedWithPublicAccount(t)}, 153 {"RoleBasedWithMultiSig", genRoleBasedWithMultiSigAccount(t)}, 154 } 155 156 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 157 prof := profile.NewProfiler() 158 159 // Initialize blockchain 160 start := time.Now() 161 bcdata, err := NewBCData(6, 4) 162 assert.Equal(t, nil, err) 163 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 164 165 b, err := json.Marshal(bcdata.genesis) 166 ioutil.WriteFile("genesis.json", b, 0o755) 167 168 defer bcdata.Shutdown() 169 170 // Initialize address-balance map for verification 171 start = time.Now() 172 accountMap := NewAccountMap() 173 if err := accountMap.Initialize(bcdata); err != nil { 174 t.Fatal(err) 175 } 176 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 177 178 // reservoir account 179 var reservoir TestAccount 180 reservoir = &TestAccountType{ 181 Addr: *bcdata.addrs[0], 182 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 183 Nonce: uint64(0), 184 } 185 186 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 187 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 188 189 // For smart contract 190 contract, err := createAnonymousAccount("ed34b0cf47a0021e9897760f0a904a69260c2f638e0bcc805facb745ec3ff9ab") 191 assert.Equal(t, nil, err) 192 193 // Preparing step 194 { 195 var txs types.Transactions 196 // Preparing step. Send KLAY to LegacyAccount. 197 { 198 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 199 tx := types.NewTransaction(reservoir.GetNonce(), 200 accountTypes[0].account.GetAddr(), amount, gasLimit, gasPrice, []byte{}) 201 202 err := tx.SignWithKeys(signer, reservoir.GetTxKeys()) 203 assert.Equal(t, nil, err) 204 205 txs = append(txs, tx) 206 207 reservoir.AddNonce() 208 } 209 210 // Preparing step. Send KLAY to KlaytnAcounts. 211 for i := 1; i < len(accountTypes); i++ { 212 // create an account which account key will be replaced to one of account key types. 213 anon, err := createAnonymousAccount(getRandomPrivateKeyString(t)) 214 assert.Equal(t, nil, err) 215 216 accountTypes[i].account.SetAddr(anon.Addr) 217 218 { 219 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 220 tx := types.NewTransaction(reservoir.GetNonce(), 221 accountTypes[i].account.GetAddr(), amount, gasLimit, gasPrice, []byte{}) 222 223 err := tx.SignWithKeys(signer, reservoir.GetTxKeys()) 224 assert.Equal(t, nil, err) 225 txs = append(txs, tx) 226 227 reservoir.AddNonce() 228 } 229 230 // update the account's key 231 { 232 values := map[types.TxValueKeyType]interface{}{ 233 types.TxValueKeyNonce: accountTypes[i].account.GetNonce(), 234 types.TxValueKeyFrom: accountTypes[i].account.GetAddr(), 235 types.TxValueKeyGasLimit: gasLimit, 236 types.TxValueKeyGasPrice: gasPrice, 237 types.TxValueKeyAccountKey: accountTypes[i].account.GetAccKey(), 238 } 239 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 240 assert.Equal(t, nil, err) 241 242 err = tx.SignWithKeys(signer, anon.Keys) 243 assert.Equal(t, nil, err) 244 245 txs = append(txs, tx) 246 247 accountTypes[i].account.AddNonce() 248 } 249 } 250 251 { 252 amount := new(big.Int).SetUint64(0) 253 254 values := map[types.TxValueKeyType]interface{}{ 255 types.TxValueKeyNonce: reservoir.GetNonce(), 256 types.TxValueKeyFrom: reservoir.GetAddr(), 257 types.TxValueKeyTo: (*common.Address)(nil), 258 types.TxValueKeyAmount: amount, 259 types.TxValueKeyGasLimit: gasLimit, 260 types.TxValueKeyGasPrice: gasPrice, 261 types.TxValueKeyHumanReadable: false, 262 types.TxValueKeyData: common.FromHex(code), 263 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 264 } 265 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 266 assert.Equal(t, nil, err) 267 268 err = tx.SignWithKeys(signer, reservoir.GetTxKeys()) 269 assert.Equal(t, nil, err) 270 271 txs = append(txs, tx) 272 273 contract.Addr = crypto.CreateAddress(reservoir.GetAddr(), reservoir.GetNonce()) 274 275 reservoir.AddNonce() 276 } 277 { 278 amount := new(big.Int).SetUint64(0) 279 280 values := map[types.TxValueKeyType]interface{}{ 281 types.TxValueKeyNonce: reservoir.GetNonce(), 282 types.TxValueKeyFrom: reservoir.GetAddr(), 283 types.TxValueKeyTo: (*common.Address)(nil), 284 types.TxValueKeyAmount: amount, 285 types.TxValueKeyGasLimit: gasLimit, 286 types.TxValueKeyGasPrice: gasPrice, 287 types.TxValueKeyHumanReadable: false, 288 types.TxValueKeyData: common.FromHex(code), 289 types.TxValueKeyFeePayer: reservoir.GetAddr(), 290 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 291 } 292 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeploy, values) 293 assert.Equal(t, nil, err) 294 295 err = tx.SignWithKeys(signer, reservoir.GetTxKeys()) 296 assert.Equal(t, nil, err) 297 298 err = tx.SignFeePayerWithKeys(signer, reservoir.GetFeeKeys()) 299 assert.Equal(t, nil, err) 300 301 txs = append(txs, tx) 302 303 reservoir.AddNonce() 304 } 305 { 306 amount := new(big.Int).SetUint64(0) 307 308 values := map[types.TxValueKeyType]interface{}{ 309 types.TxValueKeyNonce: reservoir.GetNonce(), 310 types.TxValueKeyFrom: reservoir.GetAddr(), 311 types.TxValueKeyTo: (*common.Address)(nil), 312 types.TxValueKeyAmount: amount, 313 types.TxValueKeyGasLimit: gasLimit, 314 types.TxValueKeyGasPrice: gasPrice, 315 types.TxValueKeyHumanReadable: false, 316 types.TxValueKeyData: common.FromHex(code), 317 types.TxValueKeyFeePayer: reservoir.GetAddr(), 318 types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(20), 319 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 320 } 321 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeployWithRatio, values) 322 assert.Equal(t, nil, err) 323 324 err = tx.SignWithKeys(signer, reservoir.GetTxKeys()) 325 assert.Equal(t, nil, err) 326 327 err = tx.SignFeePayerWithKeys(signer, reservoir.GetFeeKeys()) 328 assert.Equal(t, nil, err) 329 330 txs = append(txs, tx) 331 332 reservoir.AddNonce() 333 } 334 335 // SmartContractDeploy with Nil Recipient. 336 { 337 amount := new(big.Int).SetUint64(0) 338 339 values := map[types.TxValueKeyType]interface{}{ 340 types.TxValueKeyNonce: reservoir.GetNonce(), 341 types.TxValueKeyFrom: reservoir.GetAddr(), 342 types.TxValueKeyTo: (*common.Address)(nil), 343 types.TxValueKeyAmount: amount, 344 types.TxValueKeyGasLimit: gasLimit, 345 types.TxValueKeyGasPrice: gasPrice, 346 types.TxValueKeyHumanReadable: false, 347 types.TxValueKeyData: common.FromHex(code), 348 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 349 } 350 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 351 assert.Equal(t, nil, err) 352 353 err = tx.SignWithKeys(signer, reservoir.GetTxKeys()) 354 assert.Equal(t, nil, err) 355 356 txs = append(txs, tx) 357 358 reservoir.AddNonce() 359 } 360 { 361 amount := new(big.Int).SetUint64(0) 362 363 values := map[types.TxValueKeyType]interface{}{ 364 types.TxValueKeyNonce: reservoir.GetNonce(), 365 types.TxValueKeyFrom: reservoir.GetAddr(), 366 types.TxValueKeyTo: (*common.Address)(nil), 367 types.TxValueKeyAmount: amount, 368 types.TxValueKeyGasLimit: gasLimit, 369 types.TxValueKeyGasPrice: gasPrice, 370 types.TxValueKeyHumanReadable: false, 371 types.TxValueKeyData: common.FromHex(code), 372 types.TxValueKeyFeePayer: reservoir.GetAddr(), 373 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 374 } 375 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeploy, values) 376 assert.Equal(t, nil, err) 377 378 err = tx.SignWithKeys(signer, reservoir.GetTxKeys()) 379 assert.Equal(t, nil, err) 380 381 err = tx.SignFeePayerWithKeys(signer, reservoir.GetFeeKeys()) 382 assert.Equal(t, nil, err) 383 384 txs = append(txs, tx) 385 386 reservoir.AddNonce() 387 } 388 { 389 amount := new(big.Int).SetUint64(0) 390 391 values := map[types.TxValueKeyType]interface{}{ 392 types.TxValueKeyNonce: reservoir.GetNonce(), 393 types.TxValueKeyFrom: reservoir.GetAddr(), 394 types.TxValueKeyTo: (*common.Address)(nil), 395 types.TxValueKeyAmount: amount, 396 types.TxValueKeyGasLimit: gasLimit, 397 types.TxValueKeyGasPrice: gasPrice, 398 types.TxValueKeyHumanReadable: false, 399 types.TxValueKeyData: common.FromHex(code), 400 types.TxValueKeyFeePayer: reservoir.GetAddr(), 401 types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(20), 402 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 403 } 404 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeployWithRatio, values) 405 assert.Equal(t, nil, err) 406 407 err = tx.SignWithKeys(signer, reservoir.GetTxKeys()) 408 assert.Equal(t, nil, err) 409 410 err = tx.SignFeePayerWithKeys(signer, reservoir.GetFeeKeys()) 411 assert.Equal(t, nil, err) 412 413 txs = append(txs, tx) 414 415 reservoir.AddNonce() 416 } 417 418 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 419 t.Fatal(err) 420 } 421 } 422 423 var txs types.Transactions 424 425 for _, f := range testFunctions { 426 for _, sender := range accountTypes { 427 toAccount := reservoir 428 429 // LegacyTransaction can be used only with LegacyAccount and KlaytnAccount with AccountKeyLegacy. 430 if !strings.Contains(sender.Type, "Legacy") && strings.Contains(f.Name, "Legacy") { 431 continue 432 } 433 434 // Sender can't be a LegacyAccount with AccountUpdate 435 if sender.Type == "Legacy" && strings.Contains(f.Name, "AccountUpdate") { 436 continue 437 } 438 439 gasPriceLocal := gasPrice 440 // Set contract's address with SmartContractExecution 441 if strings.Contains(f.Name, "SmartContractExecution") { 442 toAccount = contract 443 gasPriceLocal = big.NewInt(0) 444 } 445 446 if !strings.Contains(f.Name, "FeeDelegated") { 447 // For NonFeeDelegated Transactions 448 tx, _ := f.genTx(t, signer, sender.account, toAccount, nil, gasPriceLocal) 449 txs = append(txs, tx) 450 sender.account.AddNonce() 451 } else { 452 // For FeeDelegated(WithRatio) Transactions 453 for _, payer := range accountTypes { 454 tx, _ := f.genTx(t, signer, sender.account, toAccount, payer.account, gasPriceLocal) 455 txs = append(txs, tx) 456 sender.account.AddNonce() 457 } 458 } 459 } 460 } 461 462 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 463 t.Fatal(err) 464 } 465 466 lastBlock := bcdata.bc.CurrentBlock().NumberU64() 467 for i := uint64(0); i <= lastBlock; i++ { 468 blk := bcdata.bc.GetBlockByNumber(i) 469 b, err := rlp.EncodeToBytes(blk) 470 require.Equal(t, nil, err) 471 472 // fmt.Println(blk.String()) 473 // fmt.Println("encoded===") 474 // fmt.Println((hexutil.Bytes)(b)) 475 476 filename := fmt.Sprintf("b%d.rlp", i) 477 f, err := os.Create(filename) 478 require.Equal(t, nil, err) 479 480 _, err = f.WriteString(hexutil.Encode(b)) 481 require.Equal(t, nil, err) 482 483 err = f.Close() 484 require.Equal(t, nil, err) 485 } 486 } 487 488 func genAccountUpdateIdem(t *testing.T, signer types.Signer, from TestAccount, to TestAccount, payer TestAccount, gasPrice *big.Int) (*types.Transaction, uint64) { 489 values, intrinsic := genMapForUpdate(from, to, gasPrice, from.GetAccKey(), types.TxTypeAccountUpdate) 490 491 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 492 assert.Equal(t, nil, err) 493 494 err = tx.SignWithKeys(signer, from.GetUpdateKeys()) 495 assert.Equal(t, nil, err) 496 497 return tx, intrinsic 498 } 499 500 func genFeeDelegatedAccountUpdateIdem(t *testing.T, signer types.Signer, from TestAccount, to TestAccount, payer TestAccount, gasPrice *big.Int) (*types.Transaction, uint64) { 501 values, intrinsic := genMapForUpdate(from, to, gasPrice, from.GetAccKey(), types.TxTypeFeeDelegatedAccountUpdate) 502 values[types.TxValueKeyFeePayer] = payer.GetAddr() 503 504 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedAccountUpdate, values) 505 assert.Equal(t, nil, err) 506 507 err = tx.SignWithKeys(signer, from.GetUpdateKeys()) 508 assert.Equal(t, nil, err) 509 510 err = tx.SignFeePayerWithKeys(signer, payer.GetFeeKeys()) 511 assert.Equal(t, nil, err) 512 513 return tx, intrinsic 514 } 515 516 func genFeeDelegatedWithRatioAccountUpdateIdem(t *testing.T, signer types.Signer, from TestAccount, to TestAccount, payer TestAccount, gasPrice *big.Int) (*types.Transaction, uint64) { 517 values, intrinsic := genMapForUpdate(from, to, gasPrice, from.GetAccKey(), types.TxTypeFeeDelegatedAccountUpdateWithRatio) 518 values[types.TxValueKeyFeePayer] = payer.GetAddr() 519 values[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(30) 520 521 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedAccountUpdateWithRatio, values) 522 assert.Equal(t, nil, err) 523 524 err = tx.SignWithKeys(signer, from.GetUpdateKeys()) 525 assert.Equal(t, nil, err) 526 527 err = tx.SignFeePayerWithKeys(signer, payer.GetFeeKeys()) 528 assert.Equal(t, nil, err) 529 530 return tx, intrinsic 531 }