github.com/klaytn/klaytn@v1.12.1/tests/role_based_account_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 "fmt" 22 "math/big" 23 "testing" 24 "time" 25 26 "github.com/klaytn/klaytn/blockchain/types" 27 "github.com/klaytn/klaytn/blockchain/types/accountkey" 28 "github.com/klaytn/klaytn/common" 29 "github.com/klaytn/klaytn/common/profile" 30 "github.com/klaytn/klaytn/crypto" 31 "github.com/klaytn/klaytn/kerrors" 32 "github.com/klaytn/klaytn/log" 33 "github.com/klaytn/klaytn/params" 34 "github.com/stretchr/testify/assert" 35 ) 36 37 type TestRoleBasedAccountType struct { 38 Addr common.Address 39 TxKeys []*ecdsa.PrivateKey 40 UpdateKeys []*ecdsa.PrivateKey 41 FeeKeys []*ecdsa.PrivateKey 42 Nonce uint64 43 AccKey accountkey.AccountKey 44 } 45 46 func genTestKeys(len int) []*ecdsa.PrivateKey { 47 keys := make([]*ecdsa.PrivateKey, len) 48 49 for i := 0; i < len; i++ { 50 keys[i], _ = crypto.GenerateKey() 51 } 52 53 return keys 54 } 55 56 // TestRoleBasedAccount executes transactions to test accounts having a role-based key. 57 // The scenario is the following: 58 // 1. Update an account `colin` with a role-key. 59 // 2. Transfer value using colin.TxKeys. 60 // 3. Pay tx fee using colin.FeeKeys. 61 // 4. Update tx key using colin.UpdateKeys. 62 // 5. Transfer value using updated colin.TxKeys. 63 func TestRoleBasedAccount(t *testing.T) { 64 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 65 prof := profile.NewProfiler() 66 67 // Initialize blockchain 68 start := time.Now() 69 bcdata, err := NewBCData(6, 4) 70 if err != nil { 71 t.Fatal(err) 72 } 73 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 74 defer bcdata.Shutdown() 75 76 // Initialize address-balance map for verification 77 start = time.Now() 78 accountMap := NewAccountMap() 79 if err := accountMap.Initialize(bcdata); err != nil { 80 t.Fatal(err) 81 } 82 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 83 84 // reservoir account 85 reservoir := &TestRoleBasedAccountType{ 86 Addr: *bcdata.addrs[0], 87 TxKeys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 88 UpdateKeys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 89 FeeKeys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 90 Nonce: uint64(0), 91 } 92 93 // colinInitial has a initial key pair of colin before the account key update 94 colinInitial, err := createAnonymousAccount(getRandomPrivateKeyString(t)) 95 assert.Equal(t, nil, err) 96 97 keys := genTestKeys(3) 98 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 99 accountkey.NewAccountKeyPublicWithValue(&keys[0].PublicKey), 100 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 101 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 102 }) 103 colin := &TestRoleBasedAccountType{ 104 Addr: colinInitial.Addr, 105 TxKeys: []*ecdsa.PrivateKey{keys[0]}, 106 UpdateKeys: []*ecdsa.PrivateKey{keys[1]}, 107 FeeKeys: []*ecdsa.PrivateKey{keys[2]}, 108 Nonce: uint64(0), 109 AccKey: accKey, 110 } 111 112 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 113 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 114 115 // 0. Transfer (reservoir -> `colin`) using a legacy transaction. 116 { 117 var txs types.Transactions 118 119 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 120 tx := types.NewTransaction(reservoir.Nonce, 121 colin.Addr, amount, gasLimit, gasPrice, []byte{}) 122 123 err := tx.SignWithKeys(signer, reservoir.TxKeys) 124 assert.Equal(t, nil, err) 125 txs = append(txs, tx) 126 127 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 128 t.Fatal(err) 129 } 130 reservoir.Nonce += 1 131 } 132 133 // 1. Update the account `colin` with a role-key. 134 { 135 var txs types.Transactions 136 137 values := map[types.TxValueKeyType]interface{}{ 138 types.TxValueKeyNonce: colin.Nonce, 139 types.TxValueKeyFrom: colin.Addr, 140 types.TxValueKeyGasLimit: gasLimit, 141 types.TxValueKeyGasPrice: gasPrice, 142 types.TxValueKeyAccountKey: colin.AccKey, 143 } 144 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 145 assert.Equal(t, nil, err) 146 147 err = tx.SignWithKeys(signer, colinInitial.Keys) 148 assert.Equal(t, nil, err) 149 150 txs = append(txs, tx) 151 152 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 153 t.Fatal(err) 154 } 155 colin.Nonce += 1 156 } 157 158 // 2. Transfer value using colin.TxKeys. 159 { 160 var txs types.Transactions 161 162 amount := new(big.Int).SetUint64(10000) 163 values := map[types.TxValueKeyType]interface{}{ 164 types.TxValueKeyNonce: colin.Nonce, 165 types.TxValueKeyFrom: colin.Addr, 166 types.TxValueKeyTo: reservoir.Addr, 167 types.TxValueKeyAmount: amount, 168 types.TxValueKeyGasLimit: gasLimit, 169 types.TxValueKeyGasPrice: gasPrice, 170 } 171 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 172 assert.Equal(t, nil, err) 173 174 err = tx.SignWithKeys(signer, colin.TxKeys) 175 assert.Equal(t, nil, err) 176 177 txs = append(txs, tx) 178 179 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 180 t.Fatal(err) 181 } 182 colin.Nonce += 1 183 } 184 185 // 3. Pay tx fee using colin.FeeKeys. 186 { 187 var txs types.Transactions 188 189 amount := new(big.Int).SetUint64(10000) 190 values := map[types.TxValueKeyType]interface{}{ 191 types.TxValueKeyNonce: colin.Nonce, 192 types.TxValueKeyFrom: colin.Addr, 193 types.TxValueKeyFeePayer: colin.Addr, 194 types.TxValueKeyTo: reservoir.Addr, 195 types.TxValueKeyAmount: amount, 196 types.TxValueKeyGasLimit: gasLimit, 197 types.TxValueKeyGasPrice: gasPrice, 198 } 199 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, values) 200 assert.Equal(t, nil, err) 201 202 err = tx.SignWithKeys(signer, colin.TxKeys) 203 assert.Equal(t, nil, err) 204 205 err = tx.SignFeePayerWithKeys(signer, colin.FeeKeys) 206 assert.Equal(t, nil, err) 207 208 txs = append(txs, tx) 209 210 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 211 t.Fatal(err) 212 } 213 colin.Nonce += 1 214 } 215 216 // 4. Update tx key using colin.UpdateKeys. 217 { 218 var txs types.Transactions 219 220 newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867") 221 if err != nil { 222 t.Fatal(err) 223 } 224 225 values := map[types.TxValueKeyType]interface{}{ 226 types.TxValueKeyNonce: colin.Nonce, 227 types.TxValueKeyFrom: colin.Addr, 228 types.TxValueKeyGasLimit: gasLimit, 229 types.TxValueKeyGasPrice: gasPrice, 230 types.TxValueKeyAccountKey: accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 231 accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey), 232 accountkey.NewAccountKeyNil(), 233 }), 234 } 235 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 236 assert.Equal(t, nil, err) 237 238 err = tx.SignWithKeys(signer, colin.UpdateKeys) 239 assert.Equal(t, nil, err) 240 241 txs = append(txs, tx) 242 243 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 244 t.Fatal(err) 245 } 246 colin.Nonce += 1 247 248 colin.TxKeys = []*ecdsa.PrivateKey{newKey} 249 } 250 251 // 5. Transfer value using updated colin.TxKeys. 252 { 253 var txs types.Transactions 254 255 amount := new(big.Int).SetUint64(10000) 256 values := map[types.TxValueKeyType]interface{}{ 257 types.TxValueKeyNonce: colin.Nonce, 258 types.TxValueKeyFrom: colin.Addr, 259 types.TxValueKeyTo: reservoir.Addr, 260 types.TxValueKeyAmount: amount, 261 types.TxValueKeyGasLimit: gasLimit, 262 types.TxValueKeyGasPrice: gasPrice, 263 } 264 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 265 assert.Equal(t, nil, err) 266 267 err = tx.SignWithKeys(signer, colin.TxKeys) 268 assert.Equal(t, nil, err) 269 270 txs = append(txs, tx) 271 272 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 273 t.Fatal(err) 274 } 275 colin.Nonce += 1 276 } 277 278 if testing.Verbose() { 279 prof.PrintProfileInfo() 280 } 281 } 282 283 // TestAccountUpdateRoleBasedNil tests TxInternalDataAccountUpdate with the following scenario: 284 // 1. Create an account colin using TxTypeValueTransfer. 285 // 2. Update key to RoleBasedKey. If anyone is AccountKeyNil, it should fail. First nil key. 286 // 3. Update key to RoleBasedKey. If anyone is AccountKeyNil, it should fail. Second nil key. 287 func TestAccountUpdateRoleBasedNil(t *testing.T) { 288 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 289 prof := profile.NewProfiler() 290 291 // Initialize blockchain 292 start := time.Now() 293 bcdata, err := NewBCData(6, 4) 294 if err != nil { 295 t.Fatal(err) 296 } 297 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 298 defer bcdata.Shutdown() 299 300 // Initialize address-balance map for verification 301 start = time.Now() 302 accountMap := NewAccountMap() 303 if err := accountMap.Initialize(bcdata); err != nil { 304 t.Fatal(err) 305 } 306 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 307 308 // reservoir account 309 reservoir := &TestAccountType{ 310 Addr: *bcdata.addrs[0], 311 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 312 Nonce: uint64(0), 313 } 314 315 colin, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20") 316 assert.Equal(t, nil, err) 317 318 if testing.Verbose() { 319 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 320 fmt.Println("colinAddr = ", colin.Addr.String()) 321 } 322 323 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 324 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 325 326 // 1. Create an account colin using TxTypeValueTransfer. 327 { 328 var txs types.Transactions 329 330 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 331 values := map[types.TxValueKeyType]interface{}{ 332 types.TxValueKeyNonce: reservoir.Nonce, 333 types.TxValueKeyFrom: reservoir.Addr, 334 types.TxValueKeyTo: colin.Addr, 335 types.TxValueKeyAmount: amount, 336 types.TxValueKeyGasLimit: gasLimit, 337 types.TxValueKeyGasPrice: gasPrice, 338 } 339 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 340 assert.Equal(t, nil, err) 341 342 err = tx.SignWithKeys(signer, reservoir.Keys) 343 assert.Equal(t, nil, err) 344 345 txs = append(txs, tx) 346 347 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 348 t.Fatal(err) 349 } 350 reservoir.Nonce += 1 351 } 352 353 // 2. Update key to RoleBasedKey. If anyone is AccountKeyNil, it should fail. First nil key. 354 { 355 keys := genTestKeys(3) 356 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 357 accountkey.NewAccountKeyNil(), 358 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 359 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 360 }) 361 362 values := map[types.TxValueKeyType]interface{}{ 363 types.TxValueKeyNonce: colin.Nonce, 364 types.TxValueKeyFrom: colin.Addr, 365 types.TxValueKeyGasLimit: gasLimit, 366 types.TxValueKeyGasPrice: gasPrice, 367 types.TxValueKeyAccountKey: accKey, 368 } 369 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 370 assert.Equal(t, nil, err) 371 372 err = tx.SignWithKeys(signer, colin.Keys) 373 assert.Equal(t, nil, err) 374 375 receipt, err := applyTransaction(t, bcdata, tx) 376 assert.Equal(t, (*types.Receipt)(nil), receipt) 377 assert.Equal(t, kerrors.ErrAccountKeyNilUninitializable, err) 378 } 379 380 // 3. Update key to RoleBasedKey. If anyone is AccountKeyNil, it should fail. Second nil key. 381 { 382 keys := genTestKeys(3) 383 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 384 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 385 accountkey.NewAccountKeyNil(), 386 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 387 }) 388 389 values := map[types.TxValueKeyType]interface{}{ 390 types.TxValueKeyNonce: colin.Nonce, 391 types.TxValueKeyFrom: colin.Addr, 392 types.TxValueKeyGasLimit: gasLimit, 393 types.TxValueKeyGasPrice: gasPrice, 394 types.TxValueKeyAccountKey: accKey, 395 } 396 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 397 assert.Equal(t, nil, err) 398 399 err = tx.SignWithKeys(signer, colin.Keys) 400 assert.Equal(t, nil, err) 401 402 receipt, err := applyTransaction(t, bcdata, tx) 403 assert.Equal(t, (*types.Receipt)(nil), receipt) 404 assert.Equal(t, kerrors.ErrAccountKeyNilUninitializable, err) 405 } 406 } 407 408 // TestAccountUpdateRoleBasedLegacy tests TxInternalDataAccountUpdate with the following scenario: 409 // 1. Update key to RoleBasedKey having a LegacyKey for all roles 410 // 2. Test RoleTransfer of the RoleBasedKey 411 // 3-1. Test RoleUpdate of the RoleBasedKey 412 // 3-2. Recover the updated account key to the previously used RoleBasedKey 413 // 4. Test RoleFeePayer of the RoleBasedKey 414 // 5. Test RoleTransfer of the RoleBasedKey with invalid signature 415 // 6. Test RoleTransfer of the RoleBasedKey with invalid number of signatures 416 func TestAccountUpdateRoleBasedLegacy(t *testing.T) { 417 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 418 prof := profile.NewProfiler() 419 420 // Initialize blockchain 421 start := time.Now() 422 bcdata, err := NewBCData(6, 4) 423 if err != nil { 424 t.Fatal(err) 425 } 426 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 427 defer bcdata.Shutdown() 428 429 // Initialize address-balance map for verification 430 start = time.Now() 431 accountMap := NewAccountMap() 432 if err := accountMap.Initialize(bcdata); err != nil { 433 t.Fatal(err) 434 } 435 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 436 437 // reservoir account 438 reservoir := &TestAccountType{ 439 Addr: *bcdata.addrs[0], 440 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 441 Nonce: uint64(0), 442 } 443 444 anon, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20") 445 assert.Equal(t, nil, err) 446 447 if testing.Verbose() { 448 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 449 fmt.Println("anonAddr = ", anon.Addr.String()) 450 } 451 452 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 453 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 454 455 // RoleBasedKey having LegacyKeys for all roles 456 roleBasedKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 457 accountkey.NewAccountKeyLegacy(), 458 accountkey.NewAccountKeyLegacy(), 459 accountkey.NewAccountKeyLegacy(), 460 }) 461 462 // 1. Update key to RoleBasedKey having a LegacyKey for all roles 463 { 464 values := map[types.TxValueKeyType]interface{}{ 465 types.TxValueKeyNonce: reservoir.Nonce, 466 types.TxValueKeyFrom: reservoir.Addr, 467 types.TxValueKeyGasLimit: gasLimit, 468 types.TxValueKeyGasPrice: gasPrice, 469 types.TxValueKeyAccountKey: roleBasedKey, 470 } 471 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 472 assert.Equal(t, nil, err) 473 474 err = tx.SignWithKeys(signer, reservoir.Keys) 475 assert.Equal(t, nil, err) 476 477 if err := bcdata.GenABlockWithTransactions(accountMap, types.Transactions{tx}, prof); err != nil { 478 t.Fatal(err) 479 } 480 reservoir.Nonce += 1 481 } 482 483 // 2. Test RoleTransfer of the RoleBasedKey 484 { 485 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 486 values := map[types.TxValueKeyType]interface{}{ 487 types.TxValueKeyNonce: reservoir.Nonce, 488 types.TxValueKeyFrom: reservoir.Addr, 489 types.TxValueKeyTo: anon.Addr, 490 types.TxValueKeyAmount: amount, 491 types.TxValueKeyGasLimit: gasLimit, 492 types.TxValueKeyGasPrice: gasPrice, 493 } 494 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 495 assert.Equal(t, nil, err) 496 497 err = tx.SignWithKeys(signer, reservoir.Keys) 498 assert.Equal(t, nil, err) 499 500 if err := bcdata.GenABlockWithTransactions(accountMap, types.Transactions{tx}, prof); err != nil { 501 t.Fatal(err) 502 } 503 reservoir.Nonce += 1 504 } 505 506 // 3-1. Test RoleUpdate of the RoleBasedKey 507 { 508 values := map[types.TxValueKeyType]interface{}{ 509 types.TxValueKeyNonce: reservoir.Nonce, 510 types.TxValueKeyFrom: reservoir.Addr, 511 types.TxValueKeyGasLimit: gasLimit, 512 types.TxValueKeyGasPrice: gasPrice, 513 types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&anon.Keys[0].PublicKey), 514 } 515 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 516 assert.Equal(t, nil, err) 517 518 err = tx.SignWithKeys(signer, reservoir.Keys) 519 assert.Equal(t, nil, err) 520 521 if err := bcdata.GenABlockWithTransactions(accountMap, types.Transactions{tx}, prof); err != nil { 522 t.Fatal(err) 523 } 524 reservoir.Nonce += 1 525 } 526 527 // 3-2. Recover the updated account key to the previously used RoleBasedKey 528 { 529 values := map[types.TxValueKeyType]interface{}{ 530 types.TxValueKeyNonce: reservoir.Nonce, 531 types.TxValueKeyFrom: reservoir.Addr, 532 types.TxValueKeyGasLimit: gasLimit, 533 types.TxValueKeyGasPrice: gasPrice, 534 types.TxValueKeyAccountKey: roleBasedKey, 535 } 536 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 537 assert.Equal(t, nil, err) 538 539 err = tx.SignWithKeys(signer, anon.Keys) 540 assert.Equal(t, nil, err) 541 542 if err := bcdata.GenABlockWithTransactions(accountMap, types.Transactions{tx}, prof); err != nil { 543 t.Fatal(err) 544 } 545 reservoir.Nonce += 1 546 } 547 548 // 4. Test RoleFeePayer of the RoleBasedKey 549 { 550 values := map[types.TxValueKeyType]interface{}{ 551 types.TxValueKeyNonce: anon.Nonce, 552 types.TxValueKeyFrom: anon.Addr, 553 types.TxValueKeyTo: reservoir.Addr, 554 types.TxValueKeyAmount: new(big.Int).SetUint64(0), 555 types.TxValueKeyGasLimit: gasLimit, 556 types.TxValueKeyGasPrice: gasPrice, 557 types.TxValueKeyFeePayer: reservoir.Addr, 558 } 559 tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, values) 560 assert.Equal(t, nil, err) 561 562 err = tx.SignWithKeys(signer, anon.Keys) 563 assert.Equal(t, nil, err) 564 565 err = tx.SignFeePayerWithKeys(signer, reservoir.Keys) 566 assert.Equal(t, nil, err) 567 568 if err := bcdata.GenABlockWithTransactions(accountMap, types.Transactions{tx}, prof); err != nil { 569 t.Fatal(err) 570 } 571 anon.Nonce += 1 572 } 573 574 // 5. Test RoleTransfer of the RoleBasedKey with invalid signature 575 { 576 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 577 values := map[types.TxValueKeyType]interface{}{ 578 types.TxValueKeyNonce: reservoir.Nonce, 579 types.TxValueKeyFrom: reservoir.Addr, 580 types.TxValueKeyTo: anon.Addr, 581 types.TxValueKeyAmount: amount, 582 types.TxValueKeyGasLimit: gasLimit, 583 types.TxValueKeyGasPrice: gasPrice, 584 } 585 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 586 assert.Equal(t, nil, err) 587 588 err = tx.SignWithKeys(signer, anon.Keys) // Sign with an invalid key 589 assert.Equal(t, nil, err) 590 591 receipt, err := applyTransaction(t, bcdata, tx) 592 assert.Equal(t, (*types.Receipt)(nil), receipt) 593 assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err) 594 } 595 596 // 6. Test RoleTransfer of the RoleBasedKey with invalid number of signatures 597 { 598 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 599 values := map[types.TxValueKeyType]interface{}{ 600 types.TxValueKeyNonce: reservoir.Nonce, 601 types.TxValueKeyFrom: reservoir.Addr, 602 types.TxValueKeyTo: anon.Addr, 603 types.TxValueKeyAmount: amount, 604 types.TxValueKeyGasLimit: gasLimit, 605 types.TxValueKeyGasPrice: gasPrice, 606 } 607 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 608 assert.Equal(t, nil, err) 609 610 err = tx.SignWithKeys(signer, reservoir.Keys) 611 assert.Equal(t, nil, err) 612 613 // invalid number of signatures 614 tx.SetSignature(types.TxSignatures{tx.RawSignatureValues()[0], tx.RawSignatureValues()[0]}) 615 616 receipt, err := applyTransaction(t, bcdata, tx) 617 assert.Equal(t, (*types.Receipt)(nil), receipt) 618 assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err) 619 } 620 } 621 622 // TestAccountUpdateRoleBasedWrongLength tests if the role-based key having wrong length. 623 // It tests the following scenario: 624 // 1. Create an account colin using TxTypeValueTransfer. 625 // 2. Update key to RoleBasedKey with four roles. It should fail. 626 // 3. Update key to RoleBasedKey with zero role. It should fail. 627 func TestAccountUpdateRoleBasedWrongLength(t *testing.T) { 628 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 629 prof := profile.NewProfiler() 630 631 // Initialize blockchain 632 start := time.Now() 633 bcdata, err := NewBCData(6, 4) 634 if err != nil { 635 t.Fatal(err) 636 } 637 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 638 defer bcdata.Shutdown() 639 640 // Initialize address-balance map for verification 641 start = time.Now() 642 accountMap := NewAccountMap() 643 if err := accountMap.Initialize(bcdata); err != nil { 644 t.Fatal(err) 645 } 646 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 647 648 // reservoir account 649 reservoir := &TestAccountType{ 650 Addr: *bcdata.addrs[0], 651 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 652 Nonce: uint64(0), 653 } 654 655 colin, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20") 656 assert.Equal(t, nil, err) 657 658 if testing.Verbose() { 659 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 660 fmt.Println("colinAddr = ", colin.Addr.String()) 661 } 662 663 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 664 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 665 666 // 1. Create an account colin using TxTypeValueTransfer. 667 { 668 var txs types.Transactions 669 670 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 671 values := map[types.TxValueKeyType]interface{}{ 672 types.TxValueKeyNonce: reservoir.Nonce, 673 types.TxValueKeyFrom: reservoir.Addr, 674 types.TxValueKeyTo: colin.Addr, 675 types.TxValueKeyAmount: amount, 676 types.TxValueKeyGasLimit: gasLimit, 677 types.TxValueKeyGasPrice: gasPrice, 678 } 679 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 680 assert.Equal(t, nil, err) 681 682 err = tx.SignWithKeys(signer, reservoir.Keys) 683 assert.Equal(t, nil, err) 684 685 txs = append(txs, tx) 686 687 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 688 t.Fatal(err) 689 } 690 reservoir.Nonce += 1 691 } 692 693 // 2. Update key to RoleBasedKey with four roles. It should fail. 694 { 695 keys := genTestKeys(4) 696 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 697 accountkey.NewAccountKeyPublicWithValue(&keys[0].PublicKey), 698 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 699 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 700 accountkey.NewAccountKeyPublicWithValue(&keys[3].PublicKey), 701 }) 702 703 values := map[types.TxValueKeyType]interface{}{ 704 types.TxValueKeyNonce: colin.Nonce, 705 types.TxValueKeyFrom: colin.Addr, 706 types.TxValueKeyGasLimit: gasLimit, 707 types.TxValueKeyGasPrice: gasPrice, 708 types.TxValueKeyAccountKey: accKey, 709 } 710 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 711 assert.Equal(t, nil, err) 712 713 err = tx.SignWithKeys(signer, colin.Keys) 714 assert.Equal(t, nil, err) 715 716 receipt, err := applyTransaction(t, bcdata, tx) 717 assert.Equal(t, (*types.Receipt)(nil), receipt) 718 assert.Equal(t, kerrors.ErrLengthTooLong, err) 719 } 720 721 // 3. Update key to RoleBasedKey with zero role. It should fail. 722 { 723 accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{}) 724 725 values := map[types.TxValueKeyType]interface{}{ 726 types.TxValueKeyNonce: colin.Nonce, 727 types.TxValueKeyFrom: colin.Addr, 728 types.TxValueKeyGasLimit: gasLimit, 729 types.TxValueKeyGasPrice: gasPrice, 730 types.TxValueKeyAccountKey: accKey, 731 } 732 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 733 assert.Equal(t, nil, err) 734 735 err = tx.SignWithKeys(signer, colin.Keys) 736 assert.Equal(t, nil, err) 737 738 receipt, err := applyTransaction(t, bcdata, tx) 739 assert.Equal(t, (*types.Receipt)(nil), receipt) 740 assert.Equal(t, kerrors.ErrZeroLength, err) 741 } 742 } 743 744 // TestAccountUpdateRoleBasedTransition tests signature validation process of TxPool. 745 // It performs the following scenario: 746 // 1. Create an account colin using TxTypeValueTransfer. 747 // 2. Inserting a tx signed by old key into the pool. It should pass. 748 // 3. Inserting a tx signed by new key into the pool. It should fail. 749 // 4. Execute TxTypeAccountUpdate 750 // 5. Inserting a tx signed by old key into the pool. It should fail. 751 // 6. Inserting a tx signed by new key into the pool. It should pass. 752 func TestAccountUpdateRoleBasedTransition(t *testing.T) { 753 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 754 prof := profile.NewProfiler() 755 756 // Initialize blockchain 757 start := time.Now() 758 bcdata, err := NewBCData(6, 4) 759 if err != nil { 760 t.Fatal(err) 761 } 762 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 763 defer bcdata.Shutdown() 764 765 // Initialize address-balance map for verification 766 start = time.Now() 767 accountMap := NewAccountMap() 768 if err := accountMap.Initialize(bcdata); err != nil { 769 t.Fatal(err) 770 } 771 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 772 773 // reservoir account 774 reservoir := &TestAccountType{ 775 Addr: *bcdata.addrs[0], 776 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 777 Nonce: uint64(0), 778 } 779 780 colin, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20") 781 assert.Equal(t, nil, err) 782 783 if testing.Verbose() { 784 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 785 fmt.Println("colinAddr = ", colin.Addr.String()) 786 } 787 788 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 789 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 790 791 // 1. Create an account colin using TxTypeValueTransfer. 792 { 793 var txs types.Transactions 794 795 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 796 values := map[types.TxValueKeyType]interface{}{ 797 types.TxValueKeyNonce: reservoir.Nonce, 798 types.TxValueKeyFrom: reservoir.Addr, 799 types.TxValueKeyTo: colin.Addr, 800 types.TxValueKeyAmount: amount, 801 types.TxValueKeyGasLimit: gasLimit, 802 types.TxValueKeyGasPrice: gasPrice, 803 } 804 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 805 assert.Equal(t, nil, err) 806 807 err = tx.SignWithKeys(signer, reservoir.Keys) 808 assert.Equal(t, nil, err) 809 810 txs = append(txs, tx) 811 812 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 813 t.Fatal(err) 814 } 815 reservoir.Nonce += 1 816 } 817 818 keys := genTestKeys(3) 819 newKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 820 accountkey.NewAccountKeyPublicWithValue(&keys[0].PublicKey), 821 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 822 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 823 }) 824 825 // 2. Inserting a tx signed by old key into the pool. It should pass. 826 { 827 values := map[types.TxValueKeyType]interface{}{ 828 types.TxValueKeyNonce: colin.Nonce, 829 types.TxValueKeyFrom: colin.Addr, 830 types.TxValueKeyGasLimit: gasLimit, 831 types.TxValueKeyGasPrice: gasPrice, 832 types.TxValueKeyAccountKey: newKey, 833 } 834 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 835 assert.Equal(t, nil, err) 836 837 err = tx.SignWithKeys(signer, colin.Keys) 838 assert.Equal(t, nil, err) 839 840 txpool := makeTxPool(bcdata, 10) 841 err = txpool.AddRemote(tx) 842 assert.Equal(t, nil, err) 843 } 844 845 // 3. Inserting a tx signed by new key into the pool. It should fail. 846 { 847 values := map[types.TxValueKeyType]interface{}{ 848 types.TxValueKeyNonce: colin.Nonce, 849 types.TxValueKeyFrom: colin.Addr, 850 types.TxValueKeyGasLimit: gasLimit, 851 types.TxValueKeyGasPrice: gasPrice, 852 types.TxValueKeyAccountKey: newKey, 853 } 854 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 855 assert.Equal(t, nil, err) 856 857 err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{keys[accountkey.RoleAccountUpdate]}) 858 assert.Equal(t, nil, err) 859 860 txpool := makeTxPool(bcdata, 10) 861 err = txpool.AddRemote(tx) 862 assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err) 863 } 864 865 // 4. Execute TxTypeAccountUpdate 866 { 867 var txs types.Transactions 868 869 values := map[types.TxValueKeyType]interface{}{ 870 types.TxValueKeyNonce: colin.Nonce, 871 types.TxValueKeyFrom: colin.Addr, 872 types.TxValueKeyGasLimit: gasLimit, 873 types.TxValueKeyGasPrice: gasPrice, 874 types.TxValueKeyAccountKey: newKey, 875 } 876 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 877 assert.Equal(t, nil, err) 878 879 err = tx.SignWithKeys(signer, colin.Keys) 880 assert.Equal(t, nil, err) 881 882 txs = append(txs, tx) 883 884 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 885 t.Fatal(err) 886 } 887 colin.Nonce += 1 888 } 889 890 // 5. Inserting a tx signed by old key into the pool. It should fail. 891 { 892 values := map[types.TxValueKeyType]interface{}{ 893 types.TxValueKeyNonce: colin.Nonce, 894 types.TxValueKeyFrom: colin.Addr, 895 types.TxValueKeyGasLimit: gasLimit, 896 types.TxValueKeyGasPrice: gasPrice, 897 types.TxValueKeyAccountKey: newKey, 898 } 899 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 900 assert.Equal(t, nil, err) 901 902 err = tx.SignWithKeys(signer, colin.Keys) 903 assert.Equal(t, nil, err) 904 905 txpool := makeTxPool(bcdata, 10) 906 err = txpool.AddRemote(tx) 907 assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err) 908 } 909 910 // 6. Inserting a tx signed by new key into the pool. It should pass. 911 { 912 values := map[types.TxValueKeyType]interface{}{ 913 types.TxValueKeyNonce: colin.Nonce, 914 types.TxValueKeyFrom: colin.Addr, 915 types.TxValueKeyGasLimit: gasLimit, 916 types.TxValueKeyGasPrice: gasPrice, 917 types.TxValueKeyAccountKey: newKey, 918 } 919 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 920 assert.Equal(t, nil, err) 921 922 err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{keys[accountkey.RoleAccountUpdate]}) 923 assert.Equal(t, nil, err) 924 925 txpool := makeTxPool(bcdata, 10) 926 err = txpool.AddRemote(tx) 927 assert.Equal(t, nil, err) 928 } 929 } 930 931 // TestAccountUpdateToRoleBasedToPub tests updating key (oldKey -> newKey -> oldKey). 932 // It performs the following scenario: 933 // 1. Create an account colin using TxTypeValueTransfer. 934 // 2. Update to newKey using TxTypeAccountUpdate 935 // 3. Update back to oldKey using TxTypeAccountUpdate 936 func TestAccountUpdateToRoleBasedToPub(t *testing.T) { 937 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 938 prof := profile.NewProfiler() 939 940 // Initialize blockchain 941 start := time.Now() 942 bcdata, err := NewBCData(6, 4) 943 if err != nil { 944 t.Fatal(err) 945 } 946 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 947 defer bcdata.Shutdown() 948 949 // Initialize address-balance map for verification 950 start = time.Now() 951 accountMap := NewAccountMap() 952 if err := accountMap.Initialize(bcdata); err != nil { 953 t.Fatal(err) 954 } 955 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 956 957 // reservoir account 958 reservoir := &TestAccountType{ 959 Addr: *bcdata.addrs[0], 960 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 961 Nonce: uint64(0), 962 } 963 964 colin, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20") 965 assert.Equal(t, nil, err) 966 967 if testing.Verbose() { 968 fmt.Println("reservoirAddr = ", reservoir.Addr.String()) 969 fmt.Println("colinAddr = ", colin.Addr.String()) 970 } 971 972 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 973 gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice) 974 975 // 1. Create an account colin using TxTypeValueTransfer. 976 { 977 var txs types.Transactions 978 979 amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY)) 980 values := map[types.TxValueKeyType]interface{}{ 981 types.TxValueKeyNonce: reservoir.Nonce, 982 types.TxValueKeyFrom: reservoir.Addr, 983 types.TxValueKeyTo: colin.Addr, 984 types.TxValueKeyAmount: amount, 985 types.TxValueKeyGasLimit: gasLimit, 986 types.TxValueKeyGasPrice: gasPrice, 987 } 988 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 989 assert.Equal(t, nil, err) 990 991 err = tx.SignWithKeys(signer, reservoir.Keys) 992 assert.Equal(t, nil, err) 993 994 txs = append(txs, tx) 995 996 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 997 t.Fatal(err) 998 } 999 reservoir.Nonce += 1 1000 } 1001 1002 keys := genTestKeys(3) 1003 oldKey := colin.AccKey 1004 newKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{ 1005 accountkey.NewAccountKeyPublicWithValue(&keys[0].PublicKey), 1006 accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey), 1007 accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey), 1008 }) 1009 // 2. Update to newKey using TxTypeAccountUpdate 1010 { 1011 var txs types.Transactions 1012 1013 values := map[types.TxValueKeyType]interface{}{ 1014 types.TxValueKeyNonce: colin.Nonce, 1015 types.TxValueKeyFrom: colin.Addr, 1016 types.TxValueKeyGasLimit: gasLimit, 1017 types.TxValueKeyGasPrice: gasPrice, 1018 types.TxValueKeyAccountKey: newKey, 1019 } 1020 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 1021 assert.Equal(t, nil, err) 1022 1023 err = tx.SignWithKeys(signer, colin.Keys) 1024 assert.Equal(t, nil, err) 1025 1026 txs = append(txs, tx) 1027 1028 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1029 t.Fatal(err) 1030 } 1031 colin.Nonce += 1 1032 colin.AccKey = newKey 1033 } 1034 1035 // 3. Update back to oldKey using TxTypeAccountUpdate 1036 { 1037 var txs types.Transactions 1038 1039 values := map[types.TxValueKeyType]interface{}{ 1040 types.TxValueKeyNonce: colin.Nonce, 1041 types.TxValueKeyFrom: colin.Addr, 1042 types.TxValueKeyGasLimit: gasLimit, 1043 types.TxValueKeyGasPrice: gasPrice, 1044 types.TxValueKeyAccountKey: oldKey, 1045 } 1046 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values) 1047 assert.Equal(t, nil, err) 1048 1049 err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{keys[accountkey.RoleAccountUpdate]}) 1050 assert.Equal(t, nil, err) 1051 1052 txs = append(txs, tx) 1053 1054 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1055 t.Fatal(err) 1056 } 1057 colin.Nonce += 1 1058 colin.AccKey = oldKey 1059 } 1060 }