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 }