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