github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/core/state/statedb.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 12:09:34</date> 10 //</624342617986961408> 11 12 13 //包状态在以太坊状态trie上提供一个缓存层。 14 package state 15 16 import ( 17 "fmt" 18 "math/big" 19 "sort" 20 "sync" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/core/types" 24 "github.com/ethereum/go-ethereum/crypto" 25 "github.com/ethereum/go-ethereum/log" 26 "github.com/ethereum/go-ethereum/rlp" 27 "github.com/ethereum/go-ethereum/trie" 28 ) 29 30 type revision struct { 31 id int 32 journalIndex int 33 } 34 35 var ( 36 //EmptyState是空状态trie项的已知哈希。 37 emptyState = crypto.Keccak256Hash(nil) 38 39 //emptycode是空EVM字节码的已知哈希。 40 emptyCode = crypto.Keccak256Hash(nil) 41 ) 42 43 //以太坊协议中的statedbs用于存储任何内容 44 //在梅克尔特里亚。statedbs负责缓存和存储 45 //嵌套状态。它是要检索的常规查询接口: 46 //*合同 47 //*帐户 48 type StateDB struct { 49 db Database 50 trie Trie 51 52 //此映射包含“活动”对象,在处理状态转换时将对其进行修改。 53 stateObjects map[common.Address]*stateObject 54 stateObjectsDirty map[common.Address]struct{} 55 56 //数据库错误。 57 //状态对象由共识核心和虚拟机使用,它们是 58 //无法处理数据库级错误。发生的任何错误 59 //在数据库读取过程中,将在此处记忆并最终返回 60 //按statedb.commit。 61 dbErr error 62 63 //退款柜台,也用于州过渡。 64 refund uint64 65 66 thash, bhash common.Hash 67 txIndex int 68 logs map[common.Hash][]*types.Log 69 logSize uint 70 71 preimages map[common.Hash][]byte 72 73 //国家修改杂志。这是 74 //快照并还原为快照。 75 journal *journal 76 validRevisions []revision 77 nextRevisionId int 78 79 lock sync.Mutex 80 } 81 82 //从给定的trie创建新状态。 83 func New(root common.Hash, db Database) (*StateDB, error) { 84 tr, err := db.OpenTrie(root) 85 if err != nil { 86 return nil, err 87 } 88 return &StateDB{ 89 db: db, 90 trie: tr, 91 stateObjects: make(map[common.Address]*stateObject), 92 stateObjectsDirty: make(map[common.Address]struct{}), 93 logs: make(map[common.Hash][]*types.Log), 94 preimages: make(map[common.Hash][]byte), 95 journal: newJournal(), 96 }, nil 97 } 98 99 //setError记住调用它时使用的第一个非零错误。 100 func (self *StateDB) setError(err error) { 101 if self.dbErr == nil { 102 self.dbErr = err 103 } 104 } 105 106 func (self *StateDB) Error() error { 107 return self.dbErr 108 } 109 110 //重置从状态数据库中清除所有短暂状态对象,但保留 111 //基础状态将尝试避免为下一个操作重新加载数据。 112 func (self *StateDB) Reset(root common.Hash) error { 113 tr, err := self.db.OpenTrie(root) 114 if err != nil { 115 return err 116 } 117 self.trie = tr 118 self.stateObjects = make(map[common.Address]*stateObject) 119 self.stateObjectsDirty = make(map[common.Address]struct{}) 120 self.thash = common.Hash{} 121 self.bhash = common.Hash{} 122 self.txIndex = 0 123 self.logs = make(map[common.Hash][]*types.Log) 124 self.logSize = 0 125 self.preimages = make(map[common.Hash][]byte) 126 self.clearJournalAndRefund() 127 return nil 128 } 129 130 func (self *StateDB) AddLog(log *types.Log) { 131 self.journal.append(addLogChange{txhash: self.thash}) 132 133 log.TxHash = self.thash 134 log.BlockHash = self.bhash 135 log.TxIndex = uint(self.txIndex) 136 log.Index = self.logSize 137 self.logs[self.thash] = append(self.logs[self.thash], log) 138 self.logSize++ 139 } 140 141 func (self *StateDB) GetLogs(hash common.Hash) []*types.Log { 142 return self.logs[hash] 143 } 144 145 func (self *StateDB) Logs() []*types.Log { 146 var logs []*types.Log 147 for _, lgs := range self.logs { 148 logs = append(logs, lgs...) 149 } 150 return logs 151 } 152 153 //AdvPrimI图记录由VM看到的Sa3预图像。 154 func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) { 155 if _, ok := self.preimages[hash]; !ok { 156 self.journal.append(addPreimageChange{hash: hash}) 157 pi := make([]byte, len(preimage)) 158 copy(pi, preimage) 159 self.preimages[hash] = pi 160 } 161 } 162 163 //preimages返回已提交的sha3 preimages列表。 164 func (self *StateDB) Preimages() map[common.Hash][]byte { 165 return self.preimages 166 } 167 168 func (self *StateDB) AddRefund(gas uint64) { 169 self.journal.append(refundChange{prev: self.refund}) 170 self.refund += gas 171 } 172 173 //exist报告给定帐户地址是否存在于状态中。 174 //值得注意的是,对于自杀账户,这也会返回真值。 175 func (self *StateDB) Exist(addr common.Address) bool { 176 return self.getStateObject(addr) != nil 177 } 178 179 //空返回状态对象是否不存在 180 //或根据EIP161规范为空(余额=nonce=代码=0) 181 func (self *StateDB) Empty(addr common.Address) bool { 182 so := self.getStateObject(addr) 183 return so == nil || so.empty() 184 } 185 186 //从给定地址检索余额,如果找不到对象,则检索0 187 func (self *StateDB) GetBalance(addr common.Address) *big.Int { 188 stateObject := self.getStateObject(addr) 189 if stateObject != nil { 190 return stateObject.Balance() 191 } 192 return common.Big0 193 } 194 195 func (self *StateDB) GetNonce(addr common.Address) uint64 { 196 stateObject := self.getStateObject(addr) 197 if stateObject != nil { 198 return stateObject.Nonce() 199 } 200 201 return 0 202 } 203 204 func (self *StateDB) GetCode(addr common.Address) []byte { 205 stateObject := self.getStateObject(addr) 206 if stateObject != nil { 207 return stateObject.Code(self.db) 208 } 209 return nil 210 } 211 212 func (self *StateDB) GetCodeSize(addr common.Address) int { 213 stateObject := self.getStateObject(addr) 214 if stateObject == nil { 215 return 0 216 } 217 if stateObject.code != nil { 218 return len(stateObject.code) 219 } 220 size, err := self.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash())) 221 if err != nil { 222 self.setError(err) 223 } 224 return size 225 } 226 227 func (self *StateDB) GetCodeHash(addr common.Address) common.Hash { 228 stateObject := self.getStateObject(addr) 229 if stateObject == nil { 230 return common.Hash{} 231 } 232 return common.BytesToHash(stateObject.CodeHash()) 233 } 234 235 func (self *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash { 236 stateObject := self.getStateObject(addr) 237 if stateObject != nil { 238 return stateObject.GetState(self.db, bhash) 239 } 240 return common.Hash{} 241 } 242 243 //数据库检索支持低级trie操作的低级数据库。 244 func (self *StateDB) Database() Database { 245 return self.db 246 } 247 248 //storage trie返回帐户的存储trie。 249 //返回值是副本,对于不存在的帐户为零。 250 func (self *StateDB) StorageTrie(addr common.Address) Trie { 251 stateObject := self.getStateObject(addr) 252 if stateObject == nil { 253 return nil 254 } 255 cpy := stateObject.deepCopy(self) 256 return cpy.updateTrie(self.db) 257 } 258 259 func (self *StateDB) HasSuicided(addr common.Address) bool { 260 stateObject := self.getStateObject(addr) 261 if stateObject != nil { 262 return stateObject.suicided 263 } 264 return false 265 } 266 267 /* 268 *设定器 269 **/ 270 271 272 //addbalance将金额添加到与addr关联的帐户。 273 func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { 274 stateObject := self.GetOrNewStateObject(addr) 275 if stateObject != nil { 276 stateObject.AddBalance(amount) 277 } 278 } 279 280 //子余额从与addr关联的帐户中减去金额。 281 func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { 282 stateObject := self.GetOrNewStateObject(addr) 283 if stateObject != nil { 284 stateObject.SubBalance(amount) 285 } 286 } 287 288 func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) { 289 stateObject := self.GetOrNewStateObject(addr) 290 if stateObject != nil { 291 stateObject.SetBalance(amount) 292 } 293 } 294 295 func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { 296 stateObject := self.GetOrNewStateObject(addr) 297 if stateObject != nil { 298 stateObject.SetNonce(nonce) 299 } 300 } 301 302 func (self *StateDB) SetCode(addr common.Address, code []byte) { 303 stateObject := self.GetOrNewStateObject(addr) 304 if stateObject != nil { 305 stateObject.SetCode(crypto.Keccak256Hash(code), code) 306 } 307 } 308 309 func (self *StateDB) SetState(addr common.Address, key, value common.Hash) { 310 stateObject := self.GetOrNewStateObject(addr) 311 if stateObject != nil { 312 stateObject.SetState(self.db, key, value) 313 } 314 } 315 316 //自杀将指定帐户标记为自杀。 317 //这将清除帐户余额。 318 // 319 //在提交状态之前,帐户的状态对象仍然可用, 320 //GetStateObject将在自杀后返回非零帐户。 321 func (self *StateDB) Suicide(addr common.Address) bool { 322 stateObject := self.getStateObject(addr) 323 if stateObject == nil { 324 return false 325 } 326 self.journal.append(suicideChange{ 327 account: &addr, 328 prev: stateObject.suicided, 329 prevbalance: new(big.Int).Set(stateObject.Balance()), 330 }) 331 stateObject.markSuicided() 332 stateObject.data.Balance = new(big.Int) 333 334 return true 335 } 336 337 // 338 //设置、更新和删除状态对象方法。 339 // 340 341 //updateStateObject将给定对象写入trie。 342 func (self *StateDB) updateStateObject(stateObject *stateObject) { 343 addr := stateObject.Address() 344 data, err := rlp.EncodeToBytes(stateObject) 345 if err != nil { 346 panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) 347 } 348 self.setError(self.trie.TryUpdate(addr[:], data)) 349 } 350 351 //DeleteStateObject从状态trie中删除给定的对象。 352 func (self *StateDB) deleteStateObject(stateObject *stateObject) { 353 stateObject.deleted = true 354 addr := stateObject.Address() 355 self.setError(self.trie.TryDelete(addr[:])) 356 } 357 358 //检索由地址给定的状态对象。如果未找到,则返回nil。 359 func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { 360 //喜欢“活”的对象。 361 if obj := self.stateObjects[addr]; obj != nil { 362 if obj.deleted { 363 return nil 364 } 365 return obj 366 } 367 368 //从数据库加载对象。 369 enc, err := self.trie.TryGet(addr[:]) 370 if len(enc) == 0 { 371 self.setError(err) 372 return nil 373 } 374 var data Account 375 if err := rlp.DecodeBytes(enc, &data); err != nil { 376 log.Error("Failed to decode state object", "addr", addr, "err", err) 377 return nil 378 } 379 //插入到实况集。 380 obj := newObject(self, addr, data) 381 self.setStateObject(obj) 382 return obj 383 } 384 385 func (self *StateDB) setStateObject(object *stateObject) { 386 self.stateObjects[object.Address()] = object 387 } 388 389 //检索状态对象或创建新的状态对象(如果为零)。 390 func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { 391 stateObject := self.getStateObject(addr) 392 if stateObject == nil || stateObject.deleted { 393 stateObject, _ = self.createObject(addr) 394 } 395 return stateObject 396 } 397 398 //CreateObject创建新的状态对象。如果有现有帐户 399 //给定的地址,将被覆盖并作为第二个返回值返回。 400 func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { 401 prev = self.getStateObject(addr) 402 newobj = newObject(self, addr, Account{}) 403 newobj.setNonce(0) //将对象设置为脏 404 if prev == nil { 405 self.journal.append(createObjectChange{account: &addr}) 406 } else { 407 self.journal.append(resetObjectChange{prev: prev}) 408 } 409 self.setStateObject(newobj) 410 return newobj, prev 411 } 412 413 //CreateCount显式创建状态对象。如果有地址的状态对象 414 //已存在余额转入新账户。 415 // 416 //在EVM创建操作期间调用CreateCount。可能出现的情况是 417 //合同执行以下操作: 418 // 419 //1。将资金发送到sha(account++(nonce+1))。 420 //2。tx_create(sha(account++nonce))(注意,这会得到1的地址) 421 // 422 //保持平衡可确保乙醚不会消失。 423 func (self *StateDB) CreateAccount(addr common.Address) { 424 new, prev := self.createObject(addr) 425 if prev != nil { 426 new.setBalance(prev.data.Balance) 427 } 428 } 429 430 func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) { 431 so := db.getStateObject(addr) 432 if so == nil { 433 return 434 } 435 436 //在对存储进行迭代时,首先检查缓存 437 for h, value := range so.cachedStorage { 438 cb(h, value) 439 } 440 441 it := trie.NewIterator(so.getTrie(db.db).NodeIterator(nil)) 442 for it.Next() { 443 //忽略缓存值 444 key := common.BytesToHash(db.trie.GetKey(it.Key)) 445 if _, ok := so.cachedStorage[key]; !ok { 446 cb(key, common.BytesToHash(it.Value)) 447 } 448 } 449 } 450 451 //复制创建状态的深度独立副本。 452 //复制状态的快照无法应用于该副本。 453 func (self *StateDB) Copy() *StateDB { 454 self.lock.Lock() 455 defer self.lock.Unlock() 456 457 //复制所有基本字段,初始化内存字段 458 state := &StateDB{ 459 db: self.db, 460 trie: self.db.CopyTrie(self.trie), 461 stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), 462 stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), 463 refund: self.refund, 464 logs: make(map[common.Hash][]*types.Log, len(self.logs)), 465 logSize: self.logSize, 466 preimages: make(map[common.Hash][]byte), 467 journal: newJournal(), 468 } 469 //复制脏状态、日志和预映像 470 for addr := range self.journal.dirties { 471 //如文件所述[此处](https://github.com/ethereum/go-ethereum/pull/16485 issuecomment-380438527) 472 //在定稿方法中,有一种情况是对象在日志中,而不是 473 //在StateObjects中:oog在拜占庭之前接触到ripemd。因此,我们需要检查 474 //零 475 if object, exist := self.stateObjects[addr]; exist { 476 state.stateObjects[addr] = object.deepCopy(state) 477 state.stateObjectsDirty[addr] = struct{}{} 478 } 479 } 480 //上面,我们不复制实际的日记。这意味着,如果复制副本, 481 //上面的循环将是无操作,因为副本的日志是空的。 482 //因此,这里我们迭代StateObjects,以启用副本的副本 483 for addr := range self.stateObjectsDirty { 484 if _, exist := state.stateObjects[addr]; !exist { 485 state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) 486 state.stateObjectsDirty[addr] = struct{}{} 487 } 488 } 489 490 for hash, logs := range self.logs { 491 state.logs[hash] = make([]*types.Log, len(logs)) 492 copy(state.logs[hash], logs) 493 } 494 for hash, preimage := range self.preimages { 495 state.preimages[hash] = preimage 496 } 497 return state 498 } 499 500 //快照返回状态的当前修订版的标识符。 501 func (self *StateDB) Snapshot() int { 502 id := self.nextRevisionId 503 self.nextRevisionId++ 504 self.validRevisions = append(self.validRevisions, revision{id, self.journal.length()}) 505 return id 506 } 507 508 //RevertToSnapshot恢复自给定修订之后所做的所有状态更改。 509 func (self *StateDB) RevertToSnapshot(revid int) { 510 //在有效快照的堆栈中查找快照。 511 idx := sort.Search(len(self.validRevisions), func(i int) bool { 512 return self.validRevisions[i].id >= revid 513 }) 514 if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid { 515 panic(fmt.Errorf("revision id %v cannot be reverted", revid)) 516 } 517 snapshot := self.validRevisions[idx].journalIndex 518 519 //重播日志以撤消更改并删除失效的快照 520 self.journal.revert(self, snapshot) 521 self.validRevisions = self.validRevisions[:idx] 522 } 523 524 //GetRefund返回退款计数器的当前值。 525 func (self *StateDB) GetRefund() uint64 { 526 return self.refund 527 } 528 529 //通过移除自毁对象最终确定状态 530 //清除日记账和退款。 531 func (s *StateDB) Finalise(deleteEmptyObjects bool) { 532 for addr := range s.journal.dirties { 533 stateObject, exist := s.stateObjects[addr] 534 if !exist { 535 //ripemd在德克萨斯州的1714175号区块“接触”,邮编:0x1237F737031E40BCDE4A8B7E717B2D15E3ECADFE49BB1BC71EE9DEB09C6FCF2 536 //Tx耗尽了气体,尽管“触摸”的概念在那里并不存在,但是 537 //触摸事件仍将记录在日志中。因为瑞普米德是一片特殊的雪花, 538 //即使日志被还原,它仍将在日志中保留。在这种特殊情况下, 539 //它可能存在于's.journal.dirties'中,但不存在于's.stateobjects'中。 540 //因此,我们可以在这里安全地忽略它 541 continue 542 } 543 544 if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { 545 s.deleteStateObject(stateObject) 546 } else { 547 stateObject.updateRoot(s.db) 548 s.updateStateObject(stateObject) 549 } 550 s.stateObjectsDirty[addr] = struct{}{} 551 } 552 //使日记帐无效,因为不允许跨交易记录还原。 553 s.clearJournalAndRefund() 554 } 555 556 //IntermediateRoot计算状态trie的当前根哈希。 557 //它在事务之间调用,以获取 558 //进入交易记录收据。 559 func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { 560 s.Finalise(deleteEmptyObjects) 561 return s.trie.Hash() 562 } 563 564 //准备设置当前事务哈希、索引和块哈希,即 565 //在EVM发出新状态日志时使用。 566 func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { 567 self.thash = thash 568 self.bhash = bhash 569 self.txIndex = ti 570 } 571 572 func (s *StateDB) clearJournalAndRefund() { 573 s.journal = newJournal() 574 s.validRevisions = s.validRevisions[:0] 575 s.refund = 0 576 } 577 578 //commit将状态写入内存中的基础trie数据库。 579 func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) { 580 defer s.clearJournalAndRefund() 581 582 for addr := range s.journal.dirties { 583 s.stateObjectsDirty[addr] = struct{}{} 584 } 585 //将对象提交到trie。 586 for addr, stateObject := range s.stateObjects { 587 _, isDirty := s.stateObjectsDirty[addr] 588 switch { 589 case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()): 590 //如果对象已被删除,请不要麻烦同步它。 591 //只需在trie中标记为删除即可。 592 s.deleteStateObject(stateObject) 593 case isDirty: 594 //编写与状态对象关联的任何合同代码 595 if stateObject.code != nil && stateObject.dirtyCode { 596 s.db.TrieDB().InsertBlob(common.BytesToHash(stateObject.CodeHash()), stateObject.code) 597 stateObject.dirtyCode = false 598 } 599 //将状态对象中的任何存储更改写入其存储trie。 600 if err := stateObject.CommitTrie(s.db); err != nil { 601 return common.Hash{}, err 602 } 603 //更新主帐户trie中的对象。 604 s.updateStateObject(stateObject) 605 } 606 delete(s.stateObjectsDirty, addr) 607 } 608 //写入trie更改。 609 root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error { 610 var account Account 611 if err := rlp.DecodeBytes(leaf, &account); err != nil { 612 return nil 613 } 614 if account.Root != emptyState { 615 s.db.TrieDB().Reference(account.Root, parent) 616 } 617 code := common.BytesToHash(account.CodeHash) 618 if code != emptyCode { 619 s.db.TrieDB().Reference(code, parent) 620 } 621 return nil 622 }) 623 log.Debug("Trie cache stats after commit", "misses", trie.CacheMisses(), "unloads", trie.CacheUnloads()) 624 return root, err 625 } 626