github.com/klaytn/klaytn@v1.12.1/blockchain/types/account/account.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 account
    18  
    19  import (
    20  	"errors"
    21  	"io"
    22  	"math/big"
    23  
    24  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    25  	"github.com/klaytn/klaytn/common"
    26  	"github.com/klaytn/klaytn/crypto"
    27  	"github.com/klaytn/klaytn/log"
    28  	"github.com/klaytn/klaytn/params"
    29  )
    30  
    31  type AccountType uint8
    32  
    33  const (
    34  	LegacyAccountType AccountType = iota
    35  	ExternallyOwnedAccountType
    36  	SmartContractAccountType
    37  )
    38  
    39  type AccountValueKeyType uint
    40  
    41  const (
    42  	AccountValueKeyNonce AccountValueKeyType = iota
    43  	AccountValueKeyBalance
    44  	AccountValueKeyStorageRoot
    45  	AccountValueKeyCodeHash
    46  	AccountValueKeyHumanReadable
    47  	AccountValueKeyAccountKey
    48  	AccountValueKeyCodeInfo
    49  )
    50  
    51  func (a AccountType) String() string {
    52  	switch a {
    53  	case LegacyAccountType:
    54  		return "LegacyAccountType"
    55  	case ExternallyOwnedAccountType:
    56  		return "ExternallyOwnedAccount"
    57  	case SmartContractAccountType:
    58  		return "SmartContractAccount"
    59  	}
    60  	return "UndefinedAccountType"
    61  }
    62  
    63  var (
    64  	ErrUndefinedAccountType    = errors.New("undefined account type")
    65  	ErrAccountKeyNotModifiable = errors.New("account key is not modifiable")
    66  )
    67  
    68  var (
    69  	// TODO-Klaytn-Accounts: make one single instance emptyCodeHash. It is placed in several locations for now.
    70  	emptyCodeHash = crypto.Keccak256(nil)
    71  
    72  	logger = log.NewModuleLogger(log.BlockchainState)
    73  )
    74  
    75  // Account is the Klaytn consensus representation of accounts.
    76  // These objects are stored in the main account trie.
    77  type Account interface {
    78  	Type() AccountType
    79  
    80  	GetNonce() uint64
    81  	GetBalance() *big.Int
    82  	GetHumanReadable() bool
    83  
    84  	SetNonce(n uint64)
    85  	SetBalance(b *big.Int)
    86  	SetHumanReadable(b bool)
    87  
    88  	// UpdateKey updates the account's key with the given key.
    89  	UpdateKey(newKey accountkey.AccountKey, currentBlockNumber uint64) error
    90  
    91  	// Empty returns whether the account is considered empty.
    92  	// The "empty" account may be defined differently depending on the actual account type.
    93  	// An example of an empty account could be described as the one that satisfies the following conditions:
    94  	// - nonce is zero
    95  	// - balance is zero
    96  	// - codeHash is the same as emptyCodeHash
    97  	Empty() bool
    98  
    99  	// Equal returns true if all the attributes are exactly same. Otherwise, returns false.
   100  	Equal(Account) bool
   101  
   102  	// DeepCopy copies all the attributes.
   103  	DeepCopy() Account
   104  
   105  	// String returns all attributes of this object as a string.
   106  	String() string
   107  }
   108  
   109  // ProgramAccount is an interface of an account having a program (code + storage).
   110  // This interface is implemented by LegacyAccount and SmartContractAccount.
   111  type ProgramAccount interface {
   112  	Account
   113  
   114  	GetStorageRoot() common.ExtHash
   115  	GetCodeHash() []byte
   116  	GetCodeFormat() params.CodeFormat
   117  	GetVmVersion() params.VmVersion
   118  
   119  	SetStorageRoot(h common.ExtHash)
   120  	SetCodeHash(h []byte)
   121  	SetCodeInfo(codeInfo params.CodeInfo)
   122  
   123  	// A variant of EncodeRLP that preserves ExtHash fields as-is.
   124  	// In contrast, vanilla EncodeRLP must unextend ExtHash when encoding.
   125  	EncodeRLPExt(w io.Writer) error
   126  }
   127  
   128  type AccountWithKey interface {
   129  	Account
   130  
   131  	GetKey() accountkey.AccountKey
   132  	SetKey(key accountkey.AccountKey)
   133  }
   134  
   135  // NewAccountWithType creates an Account object with the given type.
   136  func NewAccountWithType(t AccountType) (Account, error) {
   137  	switch t {
   138  	case LegacyAccountType:
   139  		return newLegacyAccount(), nil
   140  	case ExternallyOwnedAccountType:
   141  		return newExternallyOwnedAccount(), nil
   142  	case SmartContractAccountType:
   143  		return newSmartContractAccount(), nil
   144  	}
   145  
   146  	return nil, ErrUndefinedAccountType
   147  }
   148  
   149  // NewAccountWithType creates an Account object initialized with the given map.
   150  func NewAccountWithMap(t AccountType, values map[AccountValueKeyType]interface{}) (Account, error) {
   151  	switch t {
   152  	case LegacyAccountType:
   153  		return newLegacyAccountWithMap(values), nil
   154  	case ExternallyOwnedAccountType:
   155  		return newExternallyOwnedAccountWithMap(values), nil
   156  	case SmartContractAccountType:
   157  		return newSmartContractAccountWithMap(values), nil
   158  	}
   159  
   160  	return nil, ErrUndefinedAccountType
   161  }
   162  
   163  func GetProgramAccount(a Account) ProgramAccount {
   164  	if pa, ok := a.(ProgramAccount); ok {
   165  		return pa
   166  	}
   167  
   168  	return nil
   169  }
   170  
   171  func GetAccountWithKey(a Account) AccountWithKey {
   172  	if ak, ok := a.(AccountWithKey); ok {
   173  		return ak
   174  	}
   175  
   176  	return nil
   177  }