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