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  }