github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/state/iterator.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 //</624450079884840960> 11 12 13 package state 14 15 import ( 16 "bytes" 17 "fmt" 18 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/rlp" 21 "github.com/ethereum/go-ethereum/trie" 22 ) 23 24 //nodeiterator是遍历整个状态trie post顺序的迭代器, 25 //including all of the contract code and contract state tries. 26 type NodeIterator struct { 27 state *StateDB //正在迭代的状态 28 29 stateIt trie.NodeIterator //全局状态trie的主迭代器 30 dataIt trie.NodeIterator //Secondary iterator for the data trie of a contract 31 32 accountHash common.Hash //包含帐户的节点的哈希 33 codeHash common.Hash //合同源代码的哈希 34 code []byte //与合同相关的源代码 35 36 Hash common.Hash //正在迭代的当前条目的哈希(如果不是独立的,则为零) 37 Parent common.Hash //第一个完整祖先节点的哈希(如果当前是根节点,则为零) 38 39 Error error //迭代器中出现内部错误时的故障集 40 } 41 42 //newnodeiterator创建一个后序状态节点迭代器。 43 func NewNodeIterator(state *StateDB) *NodeIterator { 44 return &NodeIterator{ 45 state: state, 46 } 47 } 48 49 //next将迭代器移动到下一个节点,返回是否存在 50 //进一步的节点。如果出现内部错误,此方法将返回false,并且 51 //将错误字段设置为遇到的故障。 52 func (it *NodeIterator) Next() bool { 53 //如果迭代器以前失败,则不要执行任何操作 54 if it.Error != nil { 55 return false 56 } 57 //否则,使用迭代器前进并报告任何错误 58 if err := it.step(); err != nil { 59 it.Error = err 60 return false 61 } 62 return it.retrieve() 63 } 64 65 //步骤将迭代器移动到状态trie的下一个条目。 66 func (it *NodeIterator) step() error { 67 //如果到达迭代结束,则中止 68 if it.state == nil { 69 return nil 70 } 71 //如果我们刚开始初始化迭代器 72 if it.stateIt == nil { 73 it.stateIt = it.state.trie.NodeIterator(nil) 74 } 75 //如果我们以前有数据节点,那么我们肯定至少有状态节点 76 if it.dataIt != nil { 77 if cont := it.dataIt.Next(true); !cont { 78 if it.dataIt.Error() != nil { 79 return it.dataIt.Error() 80 } 81 it.dataIt = nil 82 } 83 return nil 84 } 85 //If we had source code previously, discard that 86 if it.code != nil { 87 it.code = nil 88 return nil 89 } 90 //进入下一个状态trie节点,如果节点用完则终止 91 if cont := it.stateIt.Next(true); !cont { 92 if it.stateIt.Error() != nil { 93 return it.stateIt.Error() 94 } 95 it.state, it.stateIt = nil, nil 96 return nil 97 } 98 //如果状态trie节点是内部条目,则保持原样 99 if !it.stateIt.Leaf() { 100 return nil 101 } 102 //否则,我们将到达一个帐户节点,开始数据迭代 103 var account Account 104 if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil { 105 return err 106 } 107 dataTrie, err := it.state.db.OpenStorageTrie(common.BytesToHash(it.stateIt.LeafKey()), account.Root) 108 if err != nil { 109 return err 110 } 111 it.dataIt = dataTrie.NodeIterator(nil) 112 if !it.dataIt.Next(true) { 113 it.dataIt = nil 114 } 115 if !bytes.Equal(account.CodeHash, emptyCodeHash) { 116 it.codeHash = common.BytesToHash(account.CodeHash) 117 addrHash := common.BytesToHash(it.stateIt.LeafKey()) 118 it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash)) 119 if err != nil { 120 return fmt.Errorf("code %x: %v", account.CodeHash, err) 121 } 122 } 123 it.accountHash = it.stateIt.Parent() 124 return nil 125 } 126 127 //检索拉取和缓存迭代器正在遍历的当前状态条目。 128 //该方法返回是否还有其他数据要检查。 129 func (it *NodeIterator) retrieve() bool { 130 //清除任何预先设置的值 131 it.Hash = common.Hash{} 132 133 //如果迭代完成,则不返回可用数据 134 if it.state == nil { 135 return false 136 } 137 //否则检索当前条目 138 switch { 139 case it.dataIt != nil: 140 it.Hash, it.Parent = it.dataIt.Hash(), it.dataIt.Parent() 141 if it.Parent == (common.Hash{}) { 142 it.Parent = it.accountHash 143 } 144 case it.code != nil: 145 it.Hash, it.Parent = it.codeHash, it.accountHash 146 case it.stateIt != nil: 147 it.Hash, it.Parent = it.stateIt.Hash(), it.stateIt.Parent() 148 } 149 return true 150 } 151