github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/state/state_object.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:35</date> 10 //</624450080396546048> 11 12 13 package state 14 15 import ( 16 "bytes" 17 "fmt" 18 "io" 19 "math/big" 20 21 "github.com/ethereum/go-ethereum/common" 22 "github.com/ethereum/go-ethereum/crypto" 23 "github.com/ethereum/go-ethereum/rlp" 24 ) 25 26 var emptyCodeHash = crypto.Keccak256(nil) 27 28 type Code []byte 29 30 func (self Code) String() string { 31 return string(self) //strings.join(反汇编(self),“”) 32 } 33 34 type Storage map[common.Hash]common.Hash 35 36 func (self Storage) String() (str string) { 37 for key, value := range self { 38 str += fmt.Sprintf("%X : %X\n", key, value) 39 } 40 41 return 42 } 43 44 func (self Storage) Copy() Storage { 45 cpy := make(Storage) 46 for key, value := range self { 47 cpy[key] = value 48 } 49 50 return cpy 51 } 52 53 //StateObject表示正在修改的以太坊帐户。 54 // 55 //使用模式如下: 56 //首先需要获取一个状态对象。 57 //可以通过对象访问和修改帐户值。 58 //最后,调用committrie将修改后的存储trie写入数据库。 59 type stateObject struct { 60 address common.Address 61 addrHash common.Hash //帐户的以太坊地址哈希 62 data Account 63 db *StateDB 64 65 //数据库错误。 66 //状态对象由共识核心和虚拟机使用,它们是 67 //无法处理数据库级错误。发生的任何错误 68 //在数据库读取过程中,将在此处记忆并最终返回 69 //按statedb.commit。 70 dbErr error 71 72 //编写高速缓存。 73 trie Trie //存储trie,在第一次访问时变为非nil 74 code Code //契约字节码,在加载代码时设置 75 76 originStorage Storage //Storage cache of original entries to dedup rewrites 77 dirtyStorage Storage //需要刷新到磁盘的存储项 78 79 //缓存标志。 80 //当一个对象被标记为自杀时,它将从trie中删除。 81 //在状态转换的“更新”阶段。 82 dirtyCode bool //如果代码已更新,则为true 83 suicided bool 84 deleted bool 85 } 86 87 //empty返回帐户是否被视为空。 88 func (s *stateObject) empty() bool { 89 return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) 90 } 91 92 //账户是账户的以太坊共识代表。 93 //这些对象存储在主帐户trie中。 94 type Account struct { 95 Nonce uint64 96 Balance *big.Int 97 Root common.Hash //merkle root of the storage trie 98 CodeHash []byte 99 } 100 101 //NewObject创建一个状态对象。 102 func newObject(db *StateDB, address common.Address, data Account) *stateObject { 103 if data.Balance == nil { 104 data.Balance = new(big.Int) 105 } 106 if data.CodeHash == nil { 107 data.CodeHash = emptyCodeHash 108 } 109 return &stateObject{ 110 db: db, 111 address: address, 112 addrHash: crypto.Keccak256Hash(address[:]), 113 data: data, 114 originStorage: make(Storage), 115 dirtyStorage: make(Storage), 116 } 117 } 118 119 //encoderlp实现rlp.encoder。 120 func (c *stateObject) EncodeRLP(w io.Writer) error { 121 return rlp.Encode(w, c.data) 122 } 123 124 //setError记住调用它时使用的第一个非零错误。 125 func (self *stateObject) setError(err error) { 126 if self.dbErr == nil { 127 self.dbErr = err 128 } 129 } 130 131 func (self *stateObject) markSuicided() { 132 self.suicided = true 133 } 134 135 func (c *stateObject) touch() { 136 c.db.journal.append(touchChange{ 137 account: &c.address, 138 }) 139 if c.address == ripemd { 140 //显式地将其放入脏缓存中,否则将从 141 //扁平轴颈。 142 c.db.journal.dirty(c.address) 143 } 144 } 145 146 func (c *stateObject) getTrie(db Database) Trie { 147 if c.trie == nil { 148 var err error 149 c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root) 150 if err != nil { 151 c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{}) 152 c.setError(fmt.Errorf("can't create storage trie: %v", err)) 153 } 154 } 155 return c.trie 156 } 157 158 //GetState从帐户存储检索值。 159 func (self *stateObject) GetState(db Database, key common.Hash) common.Hash { 160 //如果此状态项有一个脏值,请返回它 161 value, dirty := self.dirtyStorage[key] 162 if dirty { 163 return value 164 } 165 //否则返回条目的原始值 166 return self.GetCommittedState(db, key) 167 } 168 169 //getcommittedState从提交的帐户存储trie中检索值。 170 func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { 171 //如果缓存了原始值,则返回 172 value, cached := self.originStorage[key] 173 if cached { 174 return value 175 } 176 //否则从数据库加载值 177 enc, err := self.getTrie(db).TryGet(key[:]) 178 if err != nil { 179 self.setError(err) 180 return common.Hash{} 181 } 182 if len(enc) > 0 { 183 _, content, _, err := rlp.Split(enc) 184 if err != nil { 185 self.setError(err) 186 } 187 value.SetBytes(content) 188 } 189 self.originStorage[key] = value 190 return value 191 } 192 193 //setstate更新帐户存储中的值。 194 func (self *stateObject) SetState(db Database, key, value common.Hash) { 195 //如果新值与旧值相同,则不要设置 196 prev := self.GetState(db, key) 197 if prev == value { 198 return 199 } 200 //新值不同,更新并记录更改 201 self.db.journal.append(storageChange{ 202 account: &self.address, 203 key: key, 204 prevalue: prev, 205 }) 206 self.setState(key, value) 207 } 208 209 func (self *stateObject) setState(key, value common.Hash) { 210 self.dirtyStorage[key] = value 211 } 212 213 //updatetrie将缓存的存储修改写入对象的存储trie。 214 func (self *stateObject) updateTrie(db Database) Trie { 215 tr := self.getTrie(db) 216 for key, value := range self.dirtyStorage { 217 delete(self.dirtyStorage, key) 218 219 //跳过noop更改,保留实际更改 220 if value == self.originStorage[key] { 221 continue 222 } 223 self.originStorage[key] = value 224 225 if (value == common.Hash{}) { 226 self.setError(tr.TryDelete(key[:])) 227 continue 228 } 229 //编码[]字节不能失败,可以忽略错误。 230 v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) 231 self.setError(tr.TryUpdate(key[:], v)) 232 } 233 return tr 234 } 235 236 //UpdateRoot sets the trie root to the current root hash of 237 func (self *stateObject) updateRoot(db Database) { 238 self.updateTrie(db) 239 self.data.Root = self.trie.Hash() 240 } 241 242 //将对象的存储trie提交给db。 243 //这将更新trie根目录。 244 func (self *stateObject) CommitTrie(db Database) error { 245 self.updateTrie(db) 246 if self.dbErr != nil { 247 return self.dbErr 248 } 249 root, err := self.trie.Commit(nil) 250 if err == nil { 251 self.data.Root = root 252 } 253 return err 254 } 255 256 //AddBalance从C的余额中删除金额。 257 //它用于将资金添加到转账的目的地帐户。 258 func (c *stateObject) AddBalance(amount *big.Int) { 259 //EIP158:我们必须检查对象的空性,以便帐户 260 //清除(0,0,0个对象)可以生效。 261 if amount.Sign() == 0 { 262 if c.empty() { 263 c.touch() 264 } 265 266 return 267 } 268 c.SetBalance(new(big.Int).Add(c.Balance(), amount)) 269 } 270 271 //次平衡从C的平衡中除去了数量。 272 //它用于从转账的原始账户中取出资金。 273 func (c *stateObject) SubBalance(amount *big.Int) { 274 if amount.Sign() == 0 { 275 return 276 } 277 c.SetBalance(new(big.Int).Sub(c.Balance(), amount)) 278 } 279 280 func (self *stateObject) SetBalance(amount *big.Int) { 281 self.db.journal.append(balanceChange{ 282 account: &self.address, 283 prev: new(big.Int).Set(self.data.Balance), 284 }) 285 self.setBalance(amount) 286 } 287 288 func (self *stateObject) setBalance(amount *big.Int) { 289 self.data.Balance = amount 290 } 291 292 //将气体返回原点。由虚拟机或闭包使用 293 func (c *stateObject) ReturnGas(gas *big.Int) {} 294 295 func (self *stateObject) deepCopy(db *StateDB) *stateObject { 296 stateObject := newObject(db, self.address, self.data) 297 if self.trie != nil { 298 stateObject.trie = db.db.CopyTrie(self.trie) 299 } 300 stateObject.code = self.code 301 stateObject.dirtyStorage = self.dirtyStorage.Copy() 302 stateObject.originStorage = self.originStorage.Copy() 303 stateObject.suicided = self.suicided 304 stateObject.dirtyCode = self.dirtyCode 305 stateObject.deleted = self.deleted 306 return stateObject 307 } 308 309 // 310 //属性访问器 311 // 312 313 //返回合同/帐户的地址 314 func (c *stateObject) Address() common.Address { 315 return c.address 316 } 317 318 //代码返回与此对象关联的合同代码(如果有)。 319 func (self *stateObject) Code(db Database) []byte { 320 if self.code != nil { 321 return self.code 322 } 323 if bytes.Equal(self.CodeHash(), emptyCodeHash) { 324 return nil 325 } 326 code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash())) 327 if err != nil { 328 self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) 329 } 330 self.code = code 331 return code 332 } 333 334 func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { 335 prevcode := self.Code(self.db.db) 336 self.db.journal.append(codeChange{ 337 account: &self.address, 338 prevhash: self.CodeHash(), 339 prevcode: prevcode, 340 }) 341 self.setCode(codeHash, code) 342 } 343 344 func (self *stateObject) setCode(codeHash common.Hash, code []byte) { 345 self.code = code 346 self.data.CodeHash = codeHash[:] 347 self.dirtyCode = true 348 } 349 350 func (self *stateObject) SetNonce(nonce uint64) { 351 self.db.journal.append(nonceChange{ 352 account: &self.address, 353 prev: self.data.Nonce, 354 }) 355 self.setNonce(nonce) 356 } 357 358 func (self *stateObject) setNonce(nonce uint64) { 359 self.data.Nonce = nonce 360 } 361 362 func (self *stateObject) CodeHash() []byte { 363 return self.data.CodeHash 364 } 365 366 func (self *stateObject) Balance() *big.Int { 367 return self.data.Balance 368 } 369 370 func (self *stateObject) Nonce() uint64 { 371 return self.data.Nonce 372 } 373 374 //从未调用,但必须存在才能使用StateObject 375 //作为一个也满足vm.contractRef的vm.account接口 376 //接口。界面很棒。 377 func (self *stateObject) Value() *big.Int { 378 panic("Value on stateObject should never be called") 379 } 380