github.com/klaytn/klaytn@v1.12.1/tests/klay_scenario_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 "errors" 23 "fmt" 24 "math/big" 25 "math/rand" 26 "strings" 27 "testing" 28 "time" 29 30 "github.com/klaytn/klaytn/accounts/abi" 31 "github.com/klaytn/klaytn/blockchain/state" 32 "github.com/klaytn/klaytn/blockchain/types" 33 "github.com/klaytn/klaytn/blockchain/types/accountkey" 34 "github.com/klaytn/klaytn/blockchain/vm" 35 "github.com/klaytn/klaytn/common" 36 "github.com/klaytn/klaytn/common/compiler" 37 "github.com/klaytn/klaytn/common/profile" 38 "github.com/klaytn/klaytn/crypto" 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 ) 45 46 var ( 47 to = common.HexToAddress("7b65B75d204aBed71587c9E519a89277766EE1d0") 48 feePayer = common.HexToAddress("5A0043070275d9f6054307Ee7348bD660849D90f") 49 ) 50 51 const ( 52 nonce = uint64(1234) 53 gasLimit = uint64(100000000000) 54 ) 55 56 type TestAccountType struct { 57 Addr common.Address 58 Keys []*ecdsa.PrivateKey 59 Nonce uint64 60 AccKey accountkey.AccountKey 61 } 62 63 type TestCreateMultisigAccountParam struct { 64 Threshold uint 65 Weights []uint 66 PrvKeys []string 67 } 68 69 // createAnonymousAccount creates an account whose address is derived from the private key. 70 func createAnonymousAccount(prvKeyHex string) (*TestAccountType, error) { 71 key, err := crypto.HexToECDSA(prvKeyHex) 72 if err != nil { 73 return nil, err 74 } 75 76 addr := crypto.PubkeyToAddress(key.PublicKey) 77 78 return &TestAccountType{ 79 Addr: addr, 80 Keys: []*ecdsa.PrivateKey{key}, 81 Nonce: uint64(0), 82 AccKey: accountkey.NewAccountKeyLegacy(), 83 }, nil 84 } 85 86 // createDecoupledAccount creates an account whose address is decoupled with its private key. 87 func createDecoupledAccount(prvKeyHex string, addr common.Address) (*TestAccountType, error) { 88 key, err := crypto.HexToECDSA(prvKeyHex) 89 if err != nil { 90 return nil, err 91 } 92 93 return &TestAccountType{ 94 Addr: addr, 95 Keys: []*ecdsa.PrivateKey{key}, 96 Nonce: uint64(0), 97 AccKey: accountkey.NewAccountKeyPublicWithValue(&key.PublicKey), 98 }, nil 99 } 100 101 // 102 103 // createMultisigAccount creates an account having multiple of keys. 104 func createMultisigAccount(threshold uint, weights []uint, prvKeys []string, addr common.Address) (*TestAccountType, error) { 105 var err error 106 107 keys := make([]*ecdsa.PrivateKey, len(prvKeys)) 108 weightedKeys := make(accountkey.WeightedPublicKeys, len(prvKeys)) 109 110 for i, p := range prvKeys { 111 keys[i], err = crypto.HexToECDSA(p) 112 if err != nil { 113 return nil, err 114 } 115 weightedKeys[i] = accountkey.NewWeightedPublicKey(weights[i], (*accountkey.PublicKeySerializable)(&keys[i].PublicKey)) 116 } 117 118 return &TestAccountType{ 119 Addr: addr, 120 Keys: keys, 121 Nonce: uint64(0), 122 AccKey: accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, weightedKeys), 123 }, nil 124 } 125 126 // createRoleBasedAccountWithAccountKeyPublic creates an account having keys that have role with AccountKeyPublic. 127 func createRoleBasedAccountWithAccountKeyPublic(prvKeys []string, addr common.Address) (*TestRoleBasedAccountType, error) { 128 var err error 129 130 if len(prvKeys) != 3 { 131 return nil, errors.New("Need three key value for create role-based account") 132 } 133 134 keys := make([]*ecdsa.PrivateKey, len(prvKeys)) 135 136 for i, p := range prvKeys { 137 keys[i], err = crypto.HexToECDSA(p) 138 if err != nil { 139 return nil, err 140 } 141 } 142 143 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 144 accountkey.NewAccountKeyPublicWithValue(&keys[0].PublicKey), 145 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 146 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 147 }) 148 149 return &TestRoleBasedAccountType{ 150 Addr: addr, 151 TxKeys: []*ecdsa.PrivateKey{keys[0]}, 152 UpdateKeys: []*ecdsa.PrivateKey{keys[1]}, 153 FeeKeys: []*ecdsa.PrivateKey{keys[2]}, 154 Nonce: uint64(0), 155 AccKey: accKey, 156 }, nil 157 } 158 159 // createRoleBasedAccountWithAccountKeyWeightedMultisig creates an account having keys that have role with AccountKeyWeightedMultisig. 160 func createRoleBasedAccountWithAccountKeyWeightedMultiSig(multisigs []TestCreateMultisigAccountParam, addr common.Address) (*TestRoleBasedAccountType, error) { 161 var err error 162 163 if len(multisigs) != 3 { 164 return nil, errors.New("Need three key value for create role-based account") 165 } 166 167 prvKeys := make([][]*ecdsa.PrivateKey, len(multisigs)) 168 multisigKeys := make([]*accountkey.AccountKeyWeightedMultiSig, len(multisigs)) 169 170 for idx, multisig := range multisigs { 171 keys := make([]*ecdsa.PrivateKey, len(multisig.PrvKeys)) 172 weightedKeys := make(accountkey.WeightedPublicKeys, len(multisig.PrvKeys)) 173 174 for i, p := range multisig.PrvKeys { 175 keys[i], err = crypto.HexToECDSA(p) 176 if err != nil { 177 return nil, err 178 } 179 weightedKeys[i] = accountkey.NewWeightedPublicKey(multisig.Weights[i], (*accountkey.PublicKeySerializable)(&keys[i].PublicKey)) 180 } 181 prvKeys[idx] = keys 182 multisigKeys[idx] = accountkey.NewAccountKeyWeightedMultiSigWithValues(multisig.Threshold, weightedKeys) 183 } 184 185 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{multisigKeys[0], multisigKeys[1], multisigKeys[2]}) 186 187 return &TestRoleBasedAccountType{ 188 Addr: addr, 189 TxKeys: prvKeys[0], 190 UpdateKeys: prvKeys[1], 191 FeeKeys: prvKeys[2], 192 Nonce: uint64(0), 193 AccKey: accKey, 194 }, nil 195 } 196 197 // TestFeeDelegatedWithSmallBalance tests the case that an account having a small amount of tokens transfers 198 // all the tokens to another account with a fee payer. 199 // This kinds of transactions were discarded in TxPool.promoteExecutable() because the total cost of 200 // the transaction is larger than the amount of tokens the sender has. 201 // Since we provide fee-delegated transactions, it is not true in the above case. 202 // This test code should succeed. 203 func TestFeeDelegatedWithSmallBalance(t *testing.T) { 204 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 205 prof := profile.NewProfiler() 206 207 // Initialize blockchain 208 start := time.Now() 209 bcdata, err := NewBCData(6, 4) 210 if err != nil { 211 t.Fatal(err) 212 } 213 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 214 defer bcdata.Shutdown() 215 216 // Initialize address-balance map for verification 217 start = time.Now() 218 accountMap := NewAccountMap() 219 if err := accountMap.Initialize(bcdata); err != nil { 220 t.Fatal(err) 221 } 222 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 223 224 // reservoir account 225 reservoir := &TestAccountType{ 226 Addr: *bcdata.addrs[0], 227 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 228 Nonce: uint64(0), 229 } 230 231 // anonymous account 232 anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab") 233 assert.Equal(t, nil, err) 234 235 if testing.Verbose() { 236 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 237 fmt.Println("anonAddr = ", anon.Addr.String()) 238 } 239 240 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 241 gasPrice := big.NewInt(25 * params.Ston) 242 243 // 1. Transfer (reservoir -> anon) using a legacy transaction. 244 { 245 var txs types.Transactions 246 247 amount := new(big.Int).SetUint64(10000) 248 tx := types.NewTransaction(reservoir.Nonce, 249 anon.Addr, amount, gasLimit, gasPrice, []byte{}) 250 251 err := tx.SignWithKeys(signer, reservoir.Keys) 252 assert.Equal(t, nil, err) 253 txs = append(txs, tx) 254 255 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 256 t.Fatal(err) 257 } 258 reservoir.Nonce += 1 259 } 260 261 // 2. Transfer (anon -> reservoir) using a TxTypeFeeDelegatedValueTransfer 262 { 263 amount := new(big.Int).SetUint64(10000) 264 values := map[types.TxValueKeyType]interface{}{ 265 types.TxValueKeyNonce: anon.Nonce, 266 types.TxValueKeyFrom: anon.Addr, 267 types.TxValueKeyFeePayer: reservoir.Addr, 268 types.TxValueKeyTo: reservoir.Addr, 269 types.TxValueKeyAmount: amount, 270 types.TxValueKeyGasLimit: gasLimit, 271 types.TxValueKeyGasPrice: gasPrice, 272 } 273 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, values) 274 assert.Equal(t, nil, err) 275 276 err = tx.SignWithKeys(signer, anon.Keys) 277 assert.Equal(t, nil, err) 278 279 err = tx.SignFeePayerWithKeys(signer, reservoir.Keys) 280 assert.Equal(t, nil, err) 281 282 p := makeTxPool(bcdata, 10) 283 284 p.AddRemote(tx) 285 286 if err := bcdata.GenABlockWithTxpool(accountMap, p, prof); err != nil { 287 t.Fatal(err) 288 } 289 anon.Nonce += 1 290 } 291 292 state, err := bcdata.bc.State() 293 assert.Equal(t, nil, err) 294 assert.Equal(t, uint64(0), state.GetBalance(anon.Addr).Uint64()) 295 } 296 297 // TestSmartContractDeployAddress checks that the smart contract is deployed to the given address or not by 298 // checking receipt.ContractAddress. 299 func TestSmartContractDeployAddress(t *testing.T) { 300 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 301 prof := profile.NewProfiler() 302 303 // Initialize blockchain 304 start := time.Now() 305 bcdata, err := NewBCData(6, 4) 306 if err != nil { 307 t.Fatal(err) 308 } 309 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 310 defer bcdata.Shutdown() 311 312 // Initialize address-balance map for verification 313 start = time.Now() 314 accountMap := NewAccountMap() 315 if err := accountMap.Initialize(bcdata); err != nil { 316 t.Fatal(err) 317 } 318 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 319 320 // reservoir account 321 reservoir := &TestAccountType{ 322 Addr: *bcdata.addrs[0], 323 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 324 Nonce: uint64(0), 325 } 326 327 if testing.Verbose() { 328 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 329 } 330 331 contractAddr := common.Address{} 332 333 gasPrice := new(big.Int).SetUint64(0) 334 gasLimit := uint64(100000000000) 335 336 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 337 338 var code string 339 340 if isCompilerAvailable() { 341 filename := string("../contracts/reward/contract/KlaytnReward.sol") 342 codes, _ := compileSolidity(filename) 343 code = codes[0] 344 } else { 345 // Falling back to use compiled code. 346 code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029" 347 } 348 349 // 1. Deploy smart contract (reservoir -> contract) 350 { 351 amount := new(big.Int).SetUint64(0) 352 353 values := map[types.TxValueKeyType]interface{}{ 354 types.TxValueKeyNonce: reservoir.Nonce, 355 types.TxValueKeyFrom: reservoir.Addr, 356 types.TxValueKeyTo: (*common.Address)(nil), 357 types.TxValueKeyAmount: amount, 358 types.TxValueKeyGasLimit: gasLimit, 359 types.TxValueKeyGasPrice: gasPrice, 360 types.TxValueKeyHumanReadable: false, 361 types.TxValueKeyData: common.FromHex(code), 362 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 363 } 364 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 365 assert.Equal(t, nil, err) 366 367 err = tx.SignWithKeys(signer, reservoir.Keys) 368 assert.Equal(t, nil, err) 369 370 contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 371 372 // check receipt 373 receipt, err := applyTransaction(t, bcdata, tx) 374 assert.Equal(t, nil, err) 375 assert.Equal(t, contractAddr, receipt.ContractAddress) 376 } 377 } 378 379 // TestSmartContractScenario tests the following scenario: 380 // 1. Deploy smart contract (reservoir -> contract) 381 // 2. Check the smart contract is deployed well. 382 // 3. Execute "reward" function with amountToSend 383 // 4. Validate "reward" function is executed correctly by executing "balanceOf". 384 func TestSmartContractScenario(t *testing.T) { 385 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 386 prof := profile.NewProfiler() 387 388 // Initialize blockchain 389 start := time.Now() 390 bcdata, err := NewBCData(6, 4) 391 if err != nil { 392 t.Fatal(err) 393 } 394 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 395 defer bcdata.Shutdown() 396 397 // Initialize address-balance map for verification 398 start = time.Now() 399 accountMap := NewAccountMap() 400 if err := accountMap.Initialize(bcdata); err != nil { 401 t.Fatal(err) 402 } 403 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 404 405 // reservoir account 406 reservoir := &TestAccountType{ 407 Addr: *bcdata.addrs[0], 408 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 409 Nonce: uint64(0), 410 } 411 412 if testing.Verbose() { 413 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 414 } 415 416 contractAddr := common.Address{} 417 418 gasPrice := new(big.Int).SetUint64(0) 419 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 420 421 var abiStr string 422 var code string 423 424 if isCompilerAvailable() { 425 filename := string("../contracts/reward/contract/KlaytnReward.sol") 426 codes, abistrings := compileSolidity(filename) 427 code = codes[0] 428 abiStr = abistrings[0] 429 } else { 430 // Falling back to use compiled code. 431 code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029" 432 abiStr = `[{"constant":true,"inputs":[],"name":"totalAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"reward","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]` 433 } 434 435 // 1. Deploy smart contract (reservoir -> contract) 436 { 437 var txs types.Transactions 438 439 amount := new(big.Int).SetUint64(0) 440 441 values := map[types.TxValueKeyType]interface{}{ 442 types.TxValueKeyNonce: reservoir.Nonce, 443 types.TxValueKeyFrom: reservoir.Addr, 444 types.TxValueKeyTo: (*common.Address)(nil), 445 types.TxValueKeyAmount: amount, 446 types.TxValueKeyGasLimit: gasLimit, 447 types.TxValueKeyGasPrice: gasPrice, 448 types.TxValueKeyHumanReadable: false, 449 types.TxValueKeyData: common.FromHex(code), 450 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 451 } 452 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 453 assert.Equal(t, nil, err) 454 455 err = tx.SignWithKeys(signer, reservoir.Keys) 456 assert.Equal(t, nil, err) 457 458 txs = append(txs, tx) 459 460 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 461 t.Fatal(err) 462 } 463 464 contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 465 466 reservoir.Nonce += 1 467 } 468 469 // 2. Check the smart contract is deployed well. 470 { 471 statedb, err := bcdata.bc.State() 472 if err != nil { 473 t.Fatal(err) 474 } 475 code := statedb.GetCode(contractAddr) 476 assert.Equal(t, 478, len(code)) 477 } 478 479 // 3. Execute "reward" function with amountToSend 480 amountToSend := new(big.Int).SetUint64(10) 481 { 482 var txs types.Transactions 483 484 abii, err := abi.JSON(strings.NewReader(string(abiStr))) 485 assert.Equal(t, nil, err) 486 487 data, err := abii.Pack("reward", reservoir.Addr) 488 assert.Equal(t, nil, err) 489 490 values := map[types.TxValueKeyType]interface{}{ 491 types.TxValueKeyNonce: reservoir.Nonce, 492 types.TxValueKeyFrom: reservoir.Addr, 493 types.TxValueKeyTo: contractAddr, 494 types.TxValueKeyAmount: amountToSend, 495 types.TxValueKeyGasLimit: gasLimit, 496 types.TxValueKeyGasPrice: gasPrice, 497 types.TxValueKeyData: data, 498 } 499 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values) 500 assert.Equal(t, nil, err) 501 502 err = tx.SignWithKeys(signer, reservoir.Keys) 503 assert.Equal(t, nil, err) 504 505 txs = append(txs, tx) 506 507 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 508 t.Fatal(err) 509 } 510 reservoir.Nonce += 1 511 } 512 513 // 4. Validate "reward" function is executed correctly by executing "balanceOf". 514 { 515 amount := new(big.Int).SetUint64(0) 516 517 abii, err := abi.JSON(strings.NewReader(string(abiStr))) 518 assert.Equal(t, nil, err) 519 520 data, err := abii.Pack("balanceOf", reservoir.Addr) 521 assert.Equal(t, nil, err) 522 523 values := map[types.TxValueKeyType]interface{}{ 524 types.TxValueKeyNonce: reservoir.Nonce, 525 types.TxValueKeyFrom: reservoir.Addr, 526 types.TxValueKeyTo: contractAddr, 527 types.TxValueKeyAmount: amount, 528 types.TxValueKeyGasLimit: gasLimit, 529 types.TxValueKeyGasPrice: gasPrice, 530 types.TxValueKeyData: data, 531 } 532 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values) 533 assert.Equal(t, nil, err) 534 535 err = tx.SignWithKeys(signer, reservoir.Keys) 536 assert.Equal(t, nil, err) 537 538 ret, err := callContract(bcdata, tx) 539 assert.Equal(t, nil, err) 540 541 balance := new(big.Int) 542 abii.UnpackIntoInterface(&balance, "balanceOf", ret) 543 544 assert.Equal(t, amountToSend, balance) 545 reservoir.Nonce += 1 546 } 547 548 if testing.Verbose() { 549 prof.PrintProfileInfo() 550 } 551 } 552 553 // TestSmartContractSign tests value transfer and fee delegation of smart contract accounts. 554 // It performs the following scenario: 555 // 1. Deploy smart contract (reservoir -> contract) 556 // 2. Check the smart contract is deployed well. 557 // 3. Try value transfer. It should be failed. 558 // 4. Try fee delegation. It should be failed. 559 func TestSmartContractSign(t *testing.T) { 560 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 561 prof := profile.NewProfiler() 562 563 // Initialize blockchain 564 start := time.Now() 565 bcdata, err := NewBCData(6, 4) 566 if err != nil { 567 t.Fatal(err) 568 } 569 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 570 defer bcdata.Shutdown() 571 572 // Initialize address-balance map for verification 573 start = time.Now() 574 accountMap := NewAccountMap() 575 if err := accountMap.Initialize(bcdata); err != nil { 576 t.Fatal(err) 577 } 578 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 579 580 // reservoir account 581 reservoir := &TestAccountType{ 582 Addr: *bcdata.addrs[0], 583 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 584 Nonce: uint64(0), 585 } 586 587 reservoir2 := &TestAccountType{ 588 Addr: *bcdata.addrs[1], 589 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[1]}, 590 Nonce: uint64(0), 591 } 592 593 if testing.Verbose() { 594 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 595 } 596 597 contract, err := createAnonymousAccount("ed34b0cf47a0021e9897760f0a904a69260c2f638e0bcc805facb745ec3ff9ab") 598 assert.Equal(t, nil, err) 599 600 gasPrice := new(big.Int).SetUint64(0) 601 gasLimit := uint64(100000000000) 602 603 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 604 605 var code string 606 607 if isCompilerAvailable() { 608 filename := string("../contracts/reward/contract/KlaytnReward.sol") 609 codes, _ := compileSolidity(filename) 610 code = codes[0] 611 } else { 612 // Falling back to use compiled code. 613 code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029" 614 } 615 616 // 1. Deploy smart contract (reservoir -> contract) 617 { 618 var txs types.Transactions 619 620 amount := new(big.Int).SetUint64(0) 621 622 values := map[types.TxValueKeyType]interface{}{ 623 types.TxValueKeyNonce: reservoir.Nonce, 624 types.TxValueKeyFrom: reservoir.Addr, 625 types.TxValueKeyTo: (*common.Address)(nil), 626 types.TxValueKeyAmount: amount, 627 types.TxValueKeyGasLimit: gasLimit, 628 types.TxValueKeyGasPrice: gasPrice, 629 types.TxValueKeyHumanReadable: false, 630 types.TxValueKeyData: common.FromHex(code), 631 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 632 } 633 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 634 assert.Equal(t, nil, err) 635 636 err = tx.SignWithKeys(signer, reservoir.Keys) 637 assert.Equal(t, nil, err) 638 639 txs = append(txs, tx) 640 641 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 642 t.Fatal(err) 643 } 644 645 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 646 647 reservoir.Nonce += 1 648 } 649 650 // 2. Check the smart contract is deployed well. 651 { 652 statedb, err := bcdata.bc.State() 653 if err != nil { 654 t.Fatal(err) 655 } 656 code := statedb.GetCode(contract.Addr) 657 assert.Equal(t, 478, len(code)) 658 } 659 660 // 3. Try value transfer. It should be failed. 661 { 662 amount := new(big.Int).SetUint64(100000000000) 663 values := map[types.TxValueKeyType]interface{}{ 664 types.TxValueKeyNonce: contract.Nonce, 665 types.TxValueKeyFrom: contract.Addr, 666 types.TxValueKeyTo: reservoir.Addr, 667 types.TxValueKeyAmount: amount, 668 types.TxValueKeyGasLimit: gasLimit, 669 types.TxValueKeyGasPrice: gasPrice, 670 } 671 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 672 assert.Equal(t, nil, err) 673 err = tx.SignWithKeys(signer, contract.Keys) 674 assert.Equal(t, nil, err) 675 676 receipt, err := applyTransaction(t, bcdata, tx) 677 assert.Equal(t, (*types.Receipt)(nil), receipt) 678 assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err) 679 } 680 681 // 4. Try fee delegation. It should be failed. 682 { 683 amount := new(big.Int).SetUint64(1000) 684 values := map[types.TxValueKeyType]interface{}{ 685 types.TxValueKeyNonce: reservoir.Nonce, 686 types.TxValueKeyFrom: reservoir.Addr, 687 types.TxValueKeyTo: reservoir2.Addr, 688 types.TxValueKeyAmount: amount, 689 types.TxValueKeyGasLimit: gasLimit, 690 types.TxValueKeyGasPrice: gasPrice, 691 types.TxValueKeyFeePayer: contract.Addr, 692 } 693 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, values) 694 assert.Equal(t, nil, err) 695 696 err = tx.SignWithKeys(signer, reservoir.Keys) 697 assert.Equal(t, nil, err) 698 699 err = tx.SignFeePayerWithKeys(signer, contract.Keys) 700 assert.Equal(t, nil, err) 701 702 receipt, err := applyTransaction(t, bcdata, tx) 703 assert.Equal(t, (*types.Receipt)(nil), receipt) 704 assert.Equal(t, types.ErrFeePayer(types.ErrInvalidAccountKey), err) 705 } 706 } 707 708 // TestFeeDelegatedSmartContractScenario tests the following scenario: 709 // 1. Deploy smart contract (reservoir -> contract) with fee-delegation. 710 // 2. Check the smart contract is deployed well. 711 // 3. Execute "reward" function with amountToSend with fee-delegation. 712 // 4. Validate "reward" function is executed correctly by executing "balanceOf". 713 func TestFeeDelegatedSmartContractScenario(t *testing.T) { 714 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 715 prof := profile.NewProfiler() 716 717 // Initialize blockchain 718 start := time.Now() 719 bcdata, err := NewBCData(6, 4) 720 if err != nil { 721 t.Fatal(err) 722 } 723 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 724 defer bcdata.Shutdown() 725 726 // Initialize address-balance map for verification 727 start = time.Now() 728 accountMap := NewAccountMap() 729 if err := accountMap.Initialize(bcdata); err != nil { 730 t.Fatal(err) 731 } 732 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 733 734 // reservoir account 735 reservoir := &TestAccountType{ 736 Addr: *bcdata.addrs[0], 737 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 738 Nonce: uint64(0), 739 } 740 741 reservoir2 := &TestAccountType{ 742 Addr: *bcdata.addrs[1], 743 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[1]}, 744 Nonce: uint64(0), 745 } 746 747 if testing.Verbose() { 748 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 749 } 750 751 contractAddr := common.Address{} 752 753 gasPrice := new(big.Int).SetUint64(0) 754 gasLimit := uint64(100000000000) 755 756 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 757 758 var abiStr string 759 var code string 760 761 if isCompilerAvailable() { 762 filename := string("../contracts/reward/contract/KlaytnReward.sol") 763 codes, abistrings := compileSolidity(filename) 764 code = codes[0] 765 abiStr = abistrings[0] 766 } else { 767 // Falling back to use compiled code. 768 code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029" 769 abiStr = `[{"constant":true,"inputs":[],"name":"totalAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"reward","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]` 770 } 771 772 // 1. Deploy smart contract (reservoir -> contract) with fee-delegation. 773 { 774 var txs types.Transactions 775 776 amount := new(big.Int).SetUint64(0) 777 778 values := map[types.TxValueKeyType]interface{}{ 779 types.TxValueKeyNonce: reservoir.Nonce, 780 types.TxValueKeyFrom: reservoir.Addr, 781 types.TxValueKeyTo: (*common.Address)(nil), 782 types.TxValueKeyAmount: amount, 783 types.TxValueKeyGasLimit: gasLimit, 784 types.TxValueKeyGasPrice: gasPrice, 785 types.TxValueKeyHumanReadable: false, 786 types.TxValueKeyData: common.FromHex(code), 787 types.TxValueKeyFeePayer: reservoir2.Addr, 788 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 789 } 790 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeploy, values) 791 assert.Equal(t, nil, err) 792 793 err = tx.SignWithKeys(signer, reservoir.Keys) 794 assert.Equal(t, nil, err) 795 796 err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys) 797 assert.Equal(t, nil, err) 798 799 txs = append(txs, tx) 800 801 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 802 t.Fatal(err) 803 } 804 805 contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 806 807 reservoir.Nonce += 1 808 } 809 810 // 2. Check the smart contract is deployed well. 811 { 812 statedb, err := bcdata.bc.State() 813 if err != nil { 814 t.Fatal(err) 815 } 816 code := statedb.GetCode(contractAddr) 817 assert.Equal(t, 478, len(code)) 818 } 819 820 // 3. Execute "reward" function with amountToSend with fee-delegation. 821 amountToSend := new(big.Int).SetUint64(10) 822 { 823 var txs types.Transactions 824 825 abii, err := abi.JSON(strings.NewReader(string(abiStr))) 826 assert.Equal(t, nil, err) 827 828 data, err := abii.Pack("reward", reservoir.Addr) 829 assert.Equal(t, nil, err) 830 831 values := map[types.TxValueKeyType]interface{}{ 832 types.TxValueKeyNonce: reservoir.Nonce, 833 types.TxValueKeyFrom: reservoir.Addr, 834 types.TxValueKeyTo: contractAddr, 835 types.TxValueKeyAmount: amountToSend, 836 types.TxValueKeyGasLimit: gasLimit, 837 types.TxValueKeyGasPrice: gasPrice, 838 types.TxValueKeyData: data, 839 types.TxValueKeyFeePayer: reservoir2.Addr, 840 } 841 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractExecution, values) 842 assert.Equal(t, nil, err) 843 844 err = tx.SignWithKeys(signer, reservoir.Keys) 845 assert.Equal(t, nil, err) 846 847 err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys) 848 assert.Equal(t, nil, err) 849 850 txs = append(txs, tx) 851 852 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 853 t.Fatal(err) 854 } 855 reservoir.Nonce += 1 856 } 857 858 // 4. Validate "reward" function is executed correctly by executing "balanceOf". 859 { 860 amount := new(big.Int).SetUint64(0) 861 862 abii, err := abi.JSON(strings.NewReader(string(abiStr))) 863 assert.Equal(t, nil, err) 864 865 data, err := abii.Pack("balanceOf", reservoir.Addr) 866 assert.Equal(t, nil, err) 867 868 values := map[types.TxValueKeyType]interface{}{ 869 types.TxValueKeyNonce: reservoir.Nonce, 870 types.TxValueKeyFrom: reservoir.Addr, 871 types.TxValueKeyTo: contractAddr, 872 types.TxValueKeyAmount: amount, 873 types.TxValueKeyGasLimit: gasLimit, 874 types.TxValueKeyGasPrice: gasPrice, 875 types.TxValueKeyData: data, 876 } 877 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values) 878 assert.Equal(t, nil, err) 879 880 err = tx.SignWithKeys(signer, reservoir.Keys) 881 assert.Equal(t, nil, err) 882 883 ret, err := callContract(bcdata, tx) 884 assert.Equal(t, nil, err) 885 886 balance := new(big.Int) 887 abii.UnpackIntoInterface(&balance, "balanceOf", ret) 888 889 assert.Equal(t, amountToSend, balance) 890 reservoir.Nonce += 1 891 } 892 893 if testing.Verbose() { 894 prof.PrintProfileInfo() 895 } 896 } 897 898 // TestFeeDelegatedSmartContractScenarioWithRatio tests the following scenario: 899 // 1. Deploy smart contract (reservoir -> contract) with fee-delegation. 900 // 2. Check the smart contract is deployed well. 901 // 3. Execute "reward" function with amountToSend with fee-delegation. 902 // 4. Validate "reward" function is executed correctly by executing "balanceOf". 903 func TestFeeDelegatedSmartContractScenarioWithRatio(t *testing.T) { 904 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 905 prof := profile.NewProfiler() 906 907 // Initialize blockchain 908 start := time.Now() 909 bcdata, err := NewBCData(6, 4) 910 if err != nil { 911 t.Fatal(err) 912 } 913 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 914 defer bcdata.Shutdown() 915 916 // Initialize address-balance map for verification 917 start = time.Now() 918 accountMap := NewAccountMap() 919 if err := accountMap.Initialize(bcdata); err != nil { 920 t.Fatal(err) 921 } 922 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 923 924 // reservoir account 925 reservoir := &TestAccountType{ 926 Addr: *bcdata.addrs[0], 927 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 928 Nonce: uint64(0), 929 } 930 931 reservoir2 := &TestAccountType{ 932 Addr: *bcdata.addrs[1], 933 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[1]}, 934 Nonce: uint64(0), 935 } 936 937 if testing.Verbose() { 938 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 939 } 940 941 contractAddr := common.Address{} 942 943 gasPrice := new(big.Int).SetUint64(0) 944 gasLimit := uint64(100000000000) 945 946 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 947 948 var abiStr string 949 var code string 950 951 if isCompilerAvailable() { 952 filename := string("../contracts/reward/contract/KlaytnReward.sol") 953 codes, abistrings := compileSolidity(filename) 954 code = codes[0] 955 abiStr = abistrings[0] 956 } else { 957 // Falling back to use compiled code. 958 code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029" 959 abiStr = `[{"constant":true,"inputs":[],"name":"totalAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"reward","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]` 960 } 961 962 // 1. Deploy smart contract (reservoir -> contract) with fee-delegation. 963 { 964 var txs types.Transactions 965 966 amount := new(big.Int).SetUint64(0) 967 968 values := map[types.TxValueKeyType]interface{}{ 969 types.TxValueKeyNonce: reservoir.Nonce, 970 types.TxValueKeyFrom: reservoir.Addr, 971 types.TxValueKeyTo: (*common.Address)(nil), 972 types.TxValueKeyAmount: amount, 973 types.TxValueKeyGasLimit: gasLimit, 974 types.TxValueKeyGasPrice: gasPrice, 975 types.TxValueKeyHumanReadable: false, 976 types.TxValueKeyData: common.FromHex(code), 977 types.TxValueKeyFeePayer: reservoir2.Addr, 978 types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30), 979 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 980 } 981 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeployWithRatio, values) 982 assert.Equal(t, nil, err) 983 984 err = tx.SignWithKeys(signer, reservoir.Keys) 985 assert.Equal(t, nil, err) 986 987 err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys) 988 assert.Equal(t, nil, err) 989 990 txs = append(txs, tx) 991 992 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 993 t.Fatal(err) 994 } 995 996 contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 997 998 reservoir.Nonce += 1 999 } 1000 1001 // 2. Check the smart contract is deployed well. 1002 { 1003 statedb, err := bcdata.bc.State() 1004 if err != nil { 1005 t.Fatal(err) 1006 } 1007 code := statedb.GetCode(contractAddr) 1008 assert.Equal(t, 478, len(code)) 1009 } 1010 1011 // 3. Execute "reward" function with amountToSend with fee-delegation. 1012 amountToSend := new(big.Int).SetUint64(10) 1013 { 1014 var txs types.Transactions 1015 1016 abii, err := abi.JSON(strings.NewReader(string(abiStr))) 1017 assert.Equal(t, nil, err) 1018 1019 data, err := abii.Pack("reward", reservoir.Addr) 1020 assert.Equal(t, nil, err) 1021 1022 values := map[types.TxValueKeyType]interface{}{ 1023 types.TxValueKeyNonce: reservoir.Nonce, 1024 types.TxValueKeyFrom: reservoir.Addr, 1025 types.TxValueKeyTo: contractAddr, 1026 types.TxValueKeyAmount: amountToSend, 1027 types.TxValueKeyGasLimit: gasLimit, 1028 types.TxValueKeyGasPrice: gasPrice, 1029 types.TxValueKeyData: data, 1030 types.TxValueKeyFeePayer: reservoir2.Addr, 1031 types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30), 1032 } 1033 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractExecutionWithRatio, values) 1034 assert.Equal(t, nil, err) 1035 1036 err = tx.SignWithKeys(signer, reservoir.Keys) 1037 assert.Equal(t, nil, err) 1038 1039 err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys) 1040 assert.Equal(t, nil, err) 1041 1042 txs = append(txs, tx) 1043 1044 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1045 t.Fatal(err) 1046 } 1047 reservoir.Nonce += 1 1048 } 1049 1050 // 4. Validate "reward" function is executed correctly by executing "balanceOf". 1051 { 1052 amount := new(big.Int).SetUint64(0) 1053 1054 abii, err := abi.JSON(strings.NewReader(string(abiStr))) 1055 assert.Equal(t, nil, err) 1056 1057 data, err := abii.Pack("balanceOf", reservoir.Addr) 1058 assert.Equal(t, nil, err) 1059 1060 values := map[types.TxValueKeyType]interface{}{ 1061 types.TxValueKeyNonce: reservoir.Nonce, 1062 types.TxValueKeyFrom: reservoir.Addr, 1063 types.TxValueKeyTo: contractAddr, 1064 types.TxValueKeyAmount: amount, 1065 types.TxValueKeyGasLimit: gasLimit, 1066 types.TxValueKeyGasPrice: gasPrice, 1067 types.TxValueKeyData: data, 1068 } 1069 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values) 1070 assert.Equal(t, nil, err) 1071 1072 err = tx.SignWithKeys(signer, reservoir.Keys) 1073 assert.Equal(t, nil, err) 1074 1075 ret, err := callContract(bcdata, tx) 1076 assert.Equal(t, nil, err) 1077 1078 balance := new(big.Int) 1079 abii.UnpackIntoInterface(&balance, "balanceOf", ret) 1080 1081 assert.Equal(t, amountToSend, balance) 1082 reservoir.Nonce += 1 1083 } 1084 1085 if testing.Verbose() { 1086 prof.PrintProfileInfo() 1087 } 1088 } 1089 1090 // TestAccountUpdate tests a following scenario: 1091 // 1. Transfer (reservoir -> anon) using a legacy transaction. 1092 // 2. Key update of decoupled using AccountUpdate 1093 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1094 // 4. Key update of anon using AccountUpdate with multisig keys. 1095 // 5. Transfer (anon-> reservoir) using TxTypeValueTransfer. 1096 func TestAccountUpdate(t *testing.T) { 1097 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 1098 prof := profile.NewProfiler() 1099 1100 // Initialize blockchain 1101 start := time.Now() 1102 bcdata, err := NewBCData(6, 4) 1103 if err != nil { 1104 t.Fatal(err) 1105 } 1106 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 1107 defer bcdata.Shutdown() 1108 1109 // Initialize address-balance map for verification 1110 start = time.Now() 1111 accountMap := NewAccountMap() 1112 if err := accountMap.Initialize(bcdata); err != nil { 1113 t.Fatal(err) 1114 } 1115 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 1116 1117 // reservoir account 1118 reservoir := &TestAccountType{ 1119 Addr: *bcdata.addrs[0], 1120 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1121 Nonce: uint64(0), 1122 } 1123 1124 // anonymous account 1125 anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab") 1126 assert.Equal(t, nil, err) 1127 1128 if testing.Verbose() { 1129 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 1130 fmt.Println("anonAddr = ", anon.Addr.String()) 1131 } 1132 1133 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1134 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 1135 gasLimit := uint64(100000) 1136 1137 // 1. Transfer (reservoir -> anon) using a legacy transaction. 1138 { 1139 var txs types.Transactions 1140 1141 amount := new(big.Int).SetUint64(params.KLAY) 1142 tx := types.NewTransaction(reservoir.Nonce, 1143 anon.Addr, amount, gasLimit, gasPrice, []byte{}) 1144 1145 err := tx.SignWithKeys(signer, reservoir.Keys) 1146 assert.Equal(t, nil, err) 1147 txs = append(txs, tx) 1148 1149 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1150 t.Fatal(err) 1151 } 1152 reservoir.Nonce += 1 1153 } 1154 1155 // 2. Key update of anon using AccountUpdate 1156 { 1157 var txs types.Transactions 1158 1159 newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867") 1160 if err != nil { 1161 t.Fatal(err) 1162 } 1163 1164 values := map[types.TxValueKeyType]interface{}{ 1165 types.TxValueKeyNonce: anon.Nonce, 1166 types.TxValueKeyFrom: anon.Addr, 1167 types.TxValueKeyGasLimit: gasLimit, 1168 types.TxValueKeyGasPrice: gasPrice, 1169 types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey), 1170 } 1171 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 1172 assert.Equal(t, nil, err) 1173 1174 err = tx.SignWithKeys(signer, anon.Keys) 1175 assert.Equal(t, nil, err) 1176 1177 txs = append(txs, tx) 1178 1179 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1180 t.Fatal(err) 1181 } 1182 anon.Nonce += 1 1183 1184 anon.Keys = []*ecdsa.PrivateKey{newKey} 1185 } 1186 1187 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1188 { 1189 var txs types.Transactions 1190 1191 amount := new(big.Int).SetUint64(1000) 1192 values := map[types.TxValueKeyType]interface{}{ 1193 types.TxValueKeyNonce: anon.Nonce, 1194 types.TxValueKeyFrom: anon.Addr, 1195 types.TxValueKeyTo: reservoir.Addr, 1196 types.TxValueKeyAmount: amount, 1197 types.TxValueKeyGasLimit: gasLimit, 1198 types.TxValueKeyGasPrice: gasPrice, 1199 } 1200 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1201 assert.Equal(t, nil, err) 1202 1203 err = tx.SignWithKeys(signer, anon.Keys) 1204 assert.Equal(t, nil, err) 1205 1206 txs = append(txs, tx) 1207 1208 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1209 t.Fatal(err) 1210 } 1211 anon.Nonce += 1 1212 } 1213 1214 // 4. Key update of anon using AccountUpdate with multisig keys. 1215 { 1216 var txs types.Transactions 1217 1218 k1, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867") 1219 if err != nil { 1220 t.Fatal(err) 1221 } 1222 k2, err := crypto.HexToECDSA("c64f2cd1196e2a1791365b00c4bc07ab8f047b73152e4617c6ed06ac221a4b0c") 1223 if err != nil { 1224 panic(err) 1225 } 1226 threshold := uint(2) 1227 keys := accountkey.WeightedPublicKeys{ 1228 accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k1.PublicKey)), 1229 accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k2.PublicKey)), 1230 } 1231 newKey := accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, keys) 1232 1233 values := map[types.TxValueKeyType]interface{}{ 1234 types.TxValueKeyNonce: anon.Nonce, 1235 types.TxValueKeyFrom: anon.Addr, 1236 types.TxValueKeyGasLimit: gasLimit, 1237 types.TxValueKeyGasPrice: gasPrice, 1238 types.TxValueKeyAccountKey: newKey, 1239 } 1240 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 1241 assert.Equal(t, nil, err) 1242 1243 err = tx.SignWithKeys(signer, anon.Keys) 1244 assert.Equal(t, nil, err) 1245 1246 txs = append(txs, tx) 1247 1248 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1249 t.Fatal(err) 1250 } 1251 anon.Nonce += 1 1252 1253 anon.Keys = []*ecdsa.PrivateKey{k1, k2} 1254 anon.AccKey = newKey 1255 } 1256 1257 // 5. Transfer (anon-> reservoir) using TxTypeValueTransfer. 1258 { 1259 var txs types.Transactions 1260 1261 amount := new(big.Int).SetUint64(10000) 1262 values := map[types.TxValueKeyType]interface{}{ 1263 types.TxValueKeyNonce: anon.Nonce, 1264 types.TxValueKeyFrom: anon.Addr, 1265 types.TxValueKeyTo: reservoir.Addr, 1266 types.TxValueKeyAmount: amount, 1267 types.TxValueKeyGasLimit: gasLimit, 1268 types.TxValueKeyGasPrice: gasPrice, 1269 } 1270 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1271 assert.Equal(t, nil, err) 1272 1273 err = tx.SignWithKeys(signer, anon.Keys) 1274 assert.Equal(t, nil, err) 1275 1276 txs = append(txs, tx) 1277 1278 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1279 t.Fatal(err) 1280 } 1281 anon.Nonce += 1 1282 } 1283 1284 if testing.Verbose() { 1285 prof.PrintProfileInfo() 1286 } 1287 } 1288 1289 // TestFeeDelegatedAccountUpdate tests a following scenario: 1290 // 1. Transfer (reservoir -> anon) using a legacy transaction. 1291 // 2. Key update of anon using TxTypeFeeDelegatedAccountUpdate 1292 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1293 func TestFeeDelegatedAccountUpdate(t *testing.T) { 1294 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 1295 prof := profile.NewProfiler() 1296 1297 // Initialize blockchain 1298 start := time.Now() 1299 bcdata, err := NewBCData(6, 4) 1300 if err != nil { 1301 t.Fatal(err) 1302 } 1303 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 1304 defer bcdata.Shutdown() 1305 1306 // Initialize address-balance map for verification 1307 start = time.Now() 1308 accountMap := NewAccountMap() 1309 if err := accountMap.Initialize(bcdata); err != nil { 1310 t.Fatal(err) 1311 } 1312 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 1313 1314 // reservoir account 1315 reservoir := &TestAccountType{ 1316 Addr: *bcdata.addrs[0], 1317 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1318 Nonce: uint64(0), 1319 } 1320 1321 // anonymous account 1322 anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab") 1323 assert.Equal(t, nil, err) 1324 1325 if testing.Verbose() { 1326 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 1327 fmt.Println("anonAddr = ", anon.Addr.String()) 1328 } 1329 1330 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1331 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 1332 1333 // 1. Transfer (reservoir -> anon) using a legacy transaction. 1334 { 1335 var txs types.Transactions 1336 1337 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 1338 tx := types.NewTransaction(reservoir.Nonce, 1339 anon.Addr, amount, gasLimit, gasPrice, []byte{}) 1340 1341 err := tx.SignWithKeys(signer, reservoir.Keys) 1342 assert.Equal(t, nil, err) 1343 txs = append(txs, tx) 1344 1345 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1346 t.Fatal(err) 1347 } 1348 reservoir.Nonce += 1 1349 } 1350 1351 // 2. Key update of anon using TxTypeFeeDelegatedAccountUpdate 1352 { 1353 var txs types.Transactions 1354 1355 newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867") 1356 if err != nil { 1357 t.Fatal(err) 1358 } 1359 1360 values := map[types.TxValueKeyType]interface{}{ 1361 types.TxValueKeyNonce: anon.Nonce, 1362 types.TxValueKeyFrom: anon.Addr, 1363 types.TxValueKeyGasLimit: gasLimit, 1364 types.TxValueKeyGasPrice: gasPrice, 1365 types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey), 1366 types.TxValueKeyFeePayer: reservoir.Addr, 1367 } 1368 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedAccountUpdate, values) 1369 assert.Equal(t, nil, err) 1370 1371 err = tx.SignWithKeys(signer, anon.Keys) 1372 assert.Equal(t, nil, err) 1373 1374 err = tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1375 assert.Equal(t, nil, err) 1376 1377 txs = append(txs, tx) 1378 1379 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1380 t.Fatal(err) 1381 } 1382 anon.Nonce += 1 1383 1384 anon.Keys = []*ecdsa.PrivateKey{newKey} 1385 } 1386 1387 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1388 { 1389 var txs types.Transactions 1390 1391 amount := new(big.Int).SetUint64(1000) 1392 values := map[types.TxValueKeyType]interface{}{ 1393 types.TxValueKeyNonce: anon.Nonce, 1394 types.TxValueKeyFrom: anon.Addr, 1395 types.TxValueKeyTo: reservoir.Addr, 1396 types.TxValueKeyAmount: amount, 1397 types.TxValueKeyGasLimit: gasLimit, 1398 types.TxValueKeyGasPrice: gasPrice, 1399 } 1400 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1401 assert.Equal(t, nil, err) 1402 1403 err = tx.SignWithKeys(signer, anon.Keys) 1404 assert.Equal(t, nil, err) 1405 1406 txs = append(txs, tx) 1407 1408 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1409 t.Fatal(err) 1410 } 1411 anon.Nonce += 1 1412 } 1413 1414 if testing.Verbose() { 1415 prof.PrintProfileInfo() 1416 } 1417 } 1418 1419 // TestFeeDelegatedAccountUpdateWithRatio tests a following scenario: 1420 // 1. Transfer (reservoir -> anon) using a legacy transaction. 1421 // 2. Key update of anon using TxTypeFeeDelegatedAccountUpdateWithRatio. 1422 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1423 func TestFeeDelegatedAccountUpdateWithRatio(t *testing.T) { 1424 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 1425 prof := profile.NewProfiler() 1426 1427 // Initialize blockchain 1428 start := time.Now() 1429 bcdata, err := NewBCData(6, 4) 1430 if err != nil { 1431 t.Fatal(err) 1432 } 1433 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 1434 defer bcdata.Shutdown() 1435 1436 // Initialize address-balance map for verification 1437 start = time.Now() 1438 accountMap := NewAccountMap() 1439 if err := accountMap.Initialize(bcdata); err != nil { 1440 t.Fatal(err) 1441 } 1442 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 1443 1444 // reservoir account 1445 reservoir := &TestAccountType{ 1446 Addr: *bcdata.addrs[0], 1447 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1448 Nonce: uint64(0), 1449 } 1450 1451 // anonymous account 1452 anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab") 1453 assert.Equal(t, nil, err) 1454 1455 if testing.Verbose() { 1456 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 1457 fmt.Println("anonAddr = ", anon.Addr.String()) 1458 } 1459 1460 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1461 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 1462 1463 // 1. Transfer (reservoir -> anon) using a legacy transaction. 1464 { 1465 var txs types.Transactions 1466 1467 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 1468 tx := types.NewTransaction(reservoir.Nonce, 1469 anon.Addr, amount, gasLimit, gasPrice, []byte{}) 1470 1471 err := tx.SignWithKeys(signer, reservoir.Keys) 1472 assert.Equal(t, nil, err) 1473 txs = append(txs, tx) 1474 1475 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1476 t.Fatal(err) 1477 } 1478 reservoir.Nonce += 1 1479 } 1480 1481 // 2. Key update of decoupled using TxTypeFeeDelegatedAccountUpdateWithRatio. 1482 { 1483 var txs types.Transactions 1484 1485 newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867") 1486 if err != nil { 1487 t.Fatal(err) 1488 } 1489 1490 values := map[types.TxValueKeyType]interface{}{ 1491 types.TxValueKeyNonce: anon.Nonce, 1492 types.TxValueKeyFrom: anon.Addr, 1493 types.TxValueKeyGasLimit: gasLimit, 1494 types.TxValueKeyGasPrice: gasPrice, 1495 types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey), 1496 types.TxValueKeyFeePayer: reservoir.Addr, 1497 types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30), 1498 } 1499 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedAccountUpdateWithRatio, values) 1500 assert.Equal(t, nil, err) 1501 1502 err = tx.SignWithKeys(signer, anon.Keys) 1503 assert.Equal(t, nil, err) 1504 1505 err = tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1506 assert.Equal(t, nil, err) 1507 1508 txs = append(txs, tx) 1509 1510 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1511 t.Fatal(err) 1512 } 1513 anon.Nonce += 1 1514 1515 anon.Keys = []*ecdsa.PrivateKey{newKey} 1516 } 1517 1518 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1519 { 1520 var txs types.Transactions 1521 1522 amount := new(big.Int).SetUint64(1000) 1523 values := map[types.TxValueKeyType]interface{}{ 1524 types.TxValueKeyNonce: anon.Nonce, 1525 types.TxValueKeyFrom: anon.Addr, 1526 types.TxValueKeyTo: reservoir.Addr, 1527 types.TxValueKeyAmount: amount, 1528 types.TxValueKeyGasLimit: gasLimit, 1529 types.TxValueKeyGasPrice: gasPrice, 1530 } 1531 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1532 assert.Equal(t, nil, err) 1533 1534 err = tx.SignWithKeys(signer, anon.Keys) 1535 assert.Equal(t, nil, err) 1536 1537 txs = append(txs, tx) 1538 1539 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1540 t.Fatal(err) 1541 } 1542 anon.Nonce += 1 1543 } 1544 1545 if testing.Verbose() { 1546 prof.PrintProfileInfo() 1547 } 1548 } 1549 1550 // TestMultisigScenario tests a test case for a multi-sig accounts. 1551 // 1. Create an account anon using LegacyTransaction. 1552 // 2. Update the account with multisig key. 1553 // 2. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1554 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer with only two keys. 1555 // 4. FAILED-CASE: Transfer (anon -> reservoir) using TxTypeValueTransfer with only one key. 1556 func TestMultisigScenario(t *testing.T) { 1557 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 1558 prof := profile.NewProfiler() 1559 1560 // Initialize blockchain 1561 start := time.Now() 1562 bcdata, err := NewBCData(6, 4) 1563 if err != nil { 1564 t.Fatal(err) 1565 } 1566 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 1567 defer bcdata.Shutdown() 1568 1569 // Initialize address-balance map for verification 1570 start = time.Now() 1571 accountMap := NewAccountMap() 1572 if err := accountMap.Initialize(bcdata); err != nil { 1573 t.Fatal(err) 1574 } 1575 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 1576 1577 // reservoir account 1578 reservoir := &TestAccountType{ 1579 Addr: *bcdata.addrs[0], 1580 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1581 Nonce: uint64(0), 1582 } 1583 1584 // anonymous account 1585 anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab") 1586 assert.Equal(t, nil, err) 1587 1588 // multi-sig account 1589 multisig, err := createMultisigAccount(uint(2), 1590 []uint{1, 1, 1}, 1591 []string{ 1592 "bb113e82881499a7a361e8354a5b68f6c6885c7bcba09ea2b0891480396c322e", 1593 "a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989", 1594 "c32c471b732e2f56103e2f8e8cfd52792ef548f05f326e546a7d1fbf9d0419ec", 1595 }, 1596 common.HexToAddress("0xbbfa38050bf3167c887c086758f448ce067ea8ea")) 1597 1598 if testing.Verbose() { 1599 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 1600 fmt.Println("multisigAddr = ", multisig.Addr.String()) 1601 } 1602 1603 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1604 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 1605 1606 // 1. Create an account anon using LegacyTransaction. 1607 { 1608 var txs types.Transactions 1609 1610 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 1611 tx := types.NewTransaction(reservoir.Nonce, 1612 anon.Addr, amount, gasLimit, gasPrice, []byte{}) 1613 1614 err := tx.SignWithKeys(signer, reservoir.Keys) 1615 assert.Equal(t, nil, err) 1616 txs = append(txs, tx) 1617 1618 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1619 t.Fatal(err) 1620 } 1621 reservoir.Nonce += 1 1622 } 1623 1624 // 2. Update the account with multisig key. 1625 { 1626 var txs types.Transactions 1627 1628 values := map[types.TxValueKeyType]interface{}{ 1629 types.TxValueKeyNonce: anon.Nonce, 1630 types.TxValueKeyFrom: anon.Addr, 1631 types.TxValueKeyGasLimit: gasLimit, 1632 types.TxValueKeyGasPrice: gasPrice, 1633 types.TxValueKeyAccountKey: multisig.AccKey, 1634 } 1635 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 1636 assert.Equal(t, nil, err) 1637 1638 err = tx.SignWithKeys(signer, anon.Keys) 1639 assert.Equal(t, nil, err) 1640 1641 txs = append(txs, tx) 1642 1643 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1644 t.Fatal(err) 1645 } 1646 anon.Nonce += 1 1647 1648 anon.AccKey = multisig.AccKey 1649 anon.Keys = multisig.Keys 1650 } 1651 1652 // 2. Transfer (anon -> reservoir) using TxTypeValueTransfer. 1653 { 1654 var txs types.Transactions 1655 1656 amount := new(big.Int).SetUint64(1000) 1657 values := map[types.TxValueKeyType]interface{}{ 1658 types.TxValueKeyNonce: anon.Nonce, 1659 types.TxValueKeyFrom: anon.Addr, 1660 types.TxValueKeyTo: reservoir.Addr, 1661 types.TxValueKeyAmount: amount, 1662 types.TxValueKeyGasLimit: gasLimit, 1663 types.TxValueKeyGasPrice: gasPrice, 1664 } 1665 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1666 assert.Equal(t, nil, err) 1667 1668 err = tx.SignWithKeys(signer, anon.Keys) 1669 assert.Equal(t, nil, err) 1670 1671 txs = append(txs, tx) 1672 1673 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1674 t.Fatal(err) 1675 } 1676 anon.Nonce += 1 1677 } 1678 1679 // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer with only two keys. 1680 { 1681 var txs types.Transactions 1682 1683 amount := new(big.Int).SetUint64(1000) 1684 values := map[types.TxValueKeyType]interface{}{ 1685 types.TxValueKeyNonce: anon.Nonce, 1686 types.TxValueKeyFrom: anon.Addr, 1687 types.TxValueKeyTo: reservoir.Addr, 1688 types.TxValueKeyAmount: amount, 1689 types.TxValueKeyGasLimit: gasLimit, 1690 types.TxValueKeyGasPrice: gasPrice, 1691 } 1692 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1693 assert.Equal(t, nil, err) 1694 1695 err = tx.SignWithKeys(signer, anon.Keys[0:2]) 1696 assert.Equal(t, nil, err) 1697 1698 txs = append(txs, tx) 1699 1700 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1701 t.Fatal(err) 1702 } 1703 anon.Nonce += 1 1704 } 1705 1706 // 4. FAILED-CASE: Transfer (anon -> reservoir) using TxTypeValueTransfer with only one key. 1707 { 1708 amount := new(big.Int).SetUint64(1000) 1709 values := map[types.TxValueKeyType]interface{}{ 1710 types.TxValueKeyNonce: anon.Nonce, 1711 types.TxValueKeyFrom: anon.Addr, 1712 types.TxValueKeyTo: reservoir.Addr, 1713 types.TxValueKeyAmount: amount, 1714 types.TxValueKeyGasLimit: gasLimit, 1715 types.TxValueKeyGasPrice: gasPrice, 1716 } 1717 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 1718 assert.Equal(t, nil, err) 1719 1720 err = tx.SignWithKeys(signer, anon.Keys[:1]) 1721 assert.Equal(t, nil, err) 1722 1723 receipt, err := applyTransaction(t, bcdata, tx) 1724 assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err) 1725 assert.Equal(t, (*types.Receipt)(nil), receipt) 1726 } 1727 1728 if testing.Verbose() { 1729 prof.PrintProfileInfo() 1730 } 1731 } 1732 1733 // TestValidateSender tests ValidateSender with all transaction types. 1734 func TestValidateSender(t *testing.T) { 1735 // anonymous account 1736 anon, err := createAnonymousAccount("1da6dfcb52128060cdd2108edb786ca0aff4ef1fa537574286eeabe5c2ebd5ca") 1737 assert.Equal(t, nil, err) 1738 1739 // decoupled account 1740 decoupled, err := createDecoupledAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab", 1741 common.HexToAddress("0x5104711f7faa9e2dadf593e43db1577a2887636f")) 1742 assert.Equal(t, nil, err) 1743 1744 initialBalance := big.NewInt(1000000) 1745 1746 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil, nil) 1747 statedb.CreateEOA(anon.Addr, false, anon.AccKey) 1748 statedb.SetNonce(anon.Addr, nonce) 1749 statedb.SetBalance(anon.Addr, initialBalance) 1750 1751 statedb.CreateEOA(decoupled.Addr, false, decoupled.AccKey) 1752 statedb.SetNonce(decoupled.Addr, rand.Uint64()) 1753 statedb.SetBalance(decoupled.Addr, initialBalance) 1754 1755 signer := types.MakeSigner(params.BFTTestChainConfig, big.NewInt(32)) 1756 gasPrice := new(big.Int).SetUint64(0) 1757 gasLimit := uint64(100000000000) 1758 amount := new(big.Int).SetUint64(10000) 1759 1760 // LegacyTransaction 1761 { 1762 amount := new(big.Int).SetUint64(100000000000) 1763 tx := types.NewTransaction(anon.Nonce, 1764 decoupled.Addr, amount, gasLimit, gasPrice, []byte{}) 1765 1766 err := tx.SignWithKeys(signer, anon.Keys) 1767 assert.Equal(t, nil, err) 1768 1769 _, err = tx.ValidateSender(signer, statedb, 0) 1770 assert.Equal(t, nil, err) 1771 assert.Equal(t, anon.Addr, tx.ValidatedSender()) 1772 } 1773 1774 // TxTypeValueTransfer 1775 { 1776 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{ 1777 types.TxValueKeyNonce: nonce, 1778 types.TxValueKeyFrom: anon.Addr, 1779 types.TxValueKeyTo: decoupled.Addr, 1780 types.TxValueKeyAmount: amount, 1781 types.TxValueKeyGasLimit: gasLimit, 1782 types.TxValueKeyGasPrice: gasPrice, 1783 }) 1784 assert.Equal(t, nil, err) 1785 1786 err = tx.SignWithKeys(signer, anon.Keys) 1787 assert.Equal(t, nil, err) 1788 1789 _, err = tx.ValidateSender(signer, statedb, 0) 1790 assert.Equal(t, nil, err) 1791 assert.Equal(t, anon.Addr, tx.ValidatedSender()) 1792 } 1793 1794 // TxTypeValueTransfer 1795 { 1796 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{ 1797 types.TxValueKeyNonce: nonce, 1798 types.TxValueKeyFrom: decoupled.Addr, 1799 types.TxValueKeyTo: decoupled.Addr, 1800 types.TxValueKeyAmount: amount, 1801 types.TxValueKeyGasLimit: gasLimit, 1802 types.TxValueKeyGasPrice: gasPrice, 1803 }) 1804 assert.Equal(t, nil, err) 1805 1806 err = tx.SignWithKeys(signer, decoupled.Keys) 1807 assert.Equal(t, nil, err) 1808 1809 _, err = tx.ValidateSender(signer, statedb, 0) 1810 assert.Equal(t, nil, err) 1811 assert.Equal(t, decoupled.Addr, tx.ValidatedSender()) 1812 } 1813 1814 // TxTypeSmartContractDeploy 1815 { 1816 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, map[types.TxValueKeyType]interface{}{ 1817 types.TxValueKeyNonce: nonce, 1818 types.TxValueKeyFrom: decoupled.Addr, 1819 types.TxValueKeyTo: &anon.Addr, 1820 types.TxValueKeyAmount: amount, 1821 types.TxValueKeyGasLimit: gasLimit, 1822 types.TxValueKeyGasPrice: gasPrice, 1823 types.TxValueKeyHumanReadable: false, 1824 // The binary below is a compiled binary of contracts/reward/contract/KlaytnReward.sol. 1825 types.TxValueKeyData: common.Hex2Bytes("608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"), 1826 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 1827 }) 1828 assert.Equal(t, nil, err) 1829 1830 err = tx.SignWithKeys(signer, decoupled.Keys) 1831 assert.Equal(t, nil, err) 1832 1833 _, err = tx.ValidateSender(signer, statedb, 0) 1834 assert.Equal(t, nil, err) 1835 assert.Equal(t, decoupled.Addr, tx.ValidatedSender()) 1836 } 1837 1838 // TxTypeSmartContractExecution 1839 { 1840 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, map[types.TxValueKeyType]interface{}{ 1841 types.TxValueKeyNonce: nonce, 1842 types.TxValueKeyFrom: decoupled.Addr, 1843 types.TxValueKeyTo: anon.Addr, 1844 types.TxValueKeyAmount: amount, 1845 types.TxValueKeyGasLimit: gasLimit, 1846 types.TxValueKeyGasPrice: gasPrice, 1847 // A abi-packed bytes calling "reward" of contracts/reward/contract/KlaytnReward.sol with an address "bc5951f055a85f41a3b62fd6f68ab7de76d299b2". 1848 types.TxValueKeyData: common.Hex2Bytes("6353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2"), 1849 }) 1850 assert.Equal(t, nil, err) 1851 1852 err = tx.SignWithKeys(signer, decoupled.Keys) 1853 assert.Equal(t, nil, err) 1854 1855 _, err = tx.ValidateSender(signer, statedb, 0) 1856 assert.Equal(t, nil, err) 1857 assert.Equal(t, decoupled.Addr, tx.ValidatedSender()) 1858 } 1859 1860 // TxTypeChainDataAnchoring 1861 { 1862 dummyBlock := types.NewBlock(&types.Header{}, nil, nil) 1863 1864 scData, err := types.NewAnchoringDataType0(dummyBlock, 0, uint64(dummyBlock.Transactions().Len())) 1865 if err != nil { 1866 t.Fatal(err) 1867 } 1868 dataAnchoredRLP, _ := rlp.EncodeToBytes(scData) 1869 1870 values := map[types.TxValueKeyType]interface{}{ 1871 types.TxValueKeyNonce: anon.Nonce, 1872 types.TxValueKeyFrom: anon.Addr, 1873 types.TxValueKeyGasLimit: gasLimit, 1874 types.TxValueKeyGasPrice: gasPrice, 1875 types.TxValueKeyAnchoredData: dataAnchoredRLP, 1876 } 1877 tx, err := types.NewTransactionWithMap(types.TxTypeChainDataAnchoring, values) 1878 if err != nil { 1879 t.Fatal(err) 1880 } 1881 err = tx.SignWithKeys(signer, anon.Keys) 1882 assert.Equal(t, nil, err) 1883 1884 _, err = tx.ValidateSender(signer, statedb, 0) 1885 assert.Equal(t, nil, err) 1886 assert.Equal(t, anon.Addr, tx.ValidatedSender()) 1887 } 1888 1889 // TxTypeFeeDelegatedValueTransfer 1890 { 1891 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, map[types.TxValueKeyType]interface{}{ 1892 types.TxValueKeyNonce: nonce, 1893 types.TxValueKeyFrom: decoupled.Addr, 1894 types.TxValueKeyFeePayer: anon.Addr, 1895 types.TxValueKeyTo: decoupled.Addr, 1896 types.TxValueKeyAmount: amount, 1897 types.TxValueKeyGasLimit: gasLimit, 1898 types.TxValueKeyGasPrice: gasPrice, 1899 }) 1900 assert.Equal(t, nil, err) 1901 1902 err = tx.SignWithKeys(signer, decoupled.Keys) 1903 assert.Equal(t, nil, err) 1904 1905 err = tx.SignFeePayerWithKeys(signer, anon.Keys) 1906 assert.Equal(t, nil, err) 1907 1908 _, err = tx.ValidateSender(signer, statedb, 0) 1909 assert.Equal(t, nil, err) 1910 assert.Equal(t, decoupled.Addr, tx.ValidatedSender()) 1911 1912 _, err = tx.ValidateFeePayer(signer, statedb, 0) 1913 assert.Equal(t, nil, err) 1914 assert.Equal(t, anon.Addr, tx.ValidatedFeePayer()) 1915 } 1916 1917 // TxTypeFeeDelegatedValueTransferWithRatio 1918 { 1919 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransferWithRatio, map[types.TxValueKeyType]interface{}{ 1920 types.TxValueKeyNonce: nonce, 1921 types.TxValueKeyFrom: decoupled.Addr, 1922 types.TxValueKeyFeePayer: anon.Addr, 1923 types.TxValueKeyTo: decoupled.Addr, 1924 types.TxValueKeyAmount: amount, 1925 types.TxValueKeyGasLimit: gasLimit, 1926 types.TxValueKeyGasPrice: gasPrice, 1927 types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30), 1928 }) 1929 assert.Equal(t, nil, err) 1930 1931 err = tx.SignWithKeys(signer, decoupled.Keys) 1932 assert.Equal(t, nil, err) 1933 1934 err = tx.SignFeePayerWithKeys(signer, anon.Keys) 1935 assert.Equal(t, nil, err) 1936 1937 _, err = tx.ValidateSender(signer, statedb, 0) 1938 assert.Equal(t, nil, err) 1939 assert.Equal(t, decoupled.Addr, tx.ValidatedSender()) 1940 1941 _, err = tx.ValidateFeePayer(signer, statedb, 0) 1942 assert.Equal(t, nil, err) 1943 assert.Equal(t, anon.Addr, tx.ValidatedFeePayer()) 1944 } 1945 } 1946 1947 func isCompilerAvailable() bool { 1948 solc, err := compiler.SolidityVersion("") 1949 if err != nil { 1950 fmt.Println("Solidity version check failed. Skipping this test", err) 1951 return false 1952 } 1953 if solc.Version != "0.4.24" && solc.Version != "0.4.25" { 1954 if testing.Verbose() { 1955 fmt.Println("solc version mismatch. Supported versions are 0.4.24 and 0.4.25.", "version", solc.Version) 1956 } 1957 return false 1958 } 1959 1960 return true 1961 } 1962 1963 func compileSolidity(filename string) (code []string, abiStr []string) { 1964 contracts, err := compiler.CompileSolidity("", filename) 1965 if err != nil { 1966 panic(err) 1967 } 1968 1969 code = make([]string, 0, len(contracts)) 1970 abiStr = make([]string, 0, len(contracts)) 1971 1972 for _, c := range contracts { 1973 abiBytes, err := json.Marshal(c.Info.AbiDefinition) 1974 if err != nil { 1975 panic(err) 1976 } 1977 1978 code = append(code, c.Code) 1979 abiStr = append(abiStr, string(abiBytes)) 1980 } 1981 1982 return 1983 } 1984 1985 // applyTransaction setups variables to call block.ApplyTransaction() for tests. 1986 // It directly returns values from block.ApplyTransaction(). 1987 func applyTransaction(t *testing.T, bcdata *BCData, tx *types.Transaction) (*types.Receipt, error) { 1988 state, err := bcdata.bc.State() 1989 assert.Equal(t, nil, err) 1990 1991 vmConfig := &vm.Config{ 1992 JumpTable: vm.ConstantinopleInstructionSet, 1993 } 1994 parent := bcdata.bc.CurrentBlock() 1995 num := parent.Number() 1996 author := bcdata.addrs[0] 1997 header := &types.Header{ 1998 ParentHash: parent.Hash(), 1999 Number: num.Add(num, common.Big1), 2000 Extra: parent.Extra(), 2001 Time: new(big.Int).Add(parent.Time(), common.Big1), 2002 BlockScore: big.NewInt(0), 2003 } 2004 usedGas := uint64(0) 2005 receipt, _, err := bcdata.bc.ApplyTransaction(bcdata.bc.Config(), author, state, header, tx, &usedGas, vmConfig) 2006 return receipt, err 2007 }