github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/state/iterator.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2015 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package state 26 27 import ( 28 "bytes" 29 "fmt" 30 31 "github.com/ethereum/go-ethereum/common" 32 "github.com/ethereum/go-ethereum/rlp" 33 "github.com/ethereum/go-ethereum/trie" 34 ) 35 36 //nodeiterator是遍历整个状态trie post顺序的迭代器, 37 //包括所有合同代码和合同状态尝试。 38 type NodeIterator struct { 39 state *StateDB //正在迭代的状态 40 41 stateIt trie.NodeIterator //全局状态trie的主迭代器 42 dataIt trie.NodeIterator //合同数据检索的辅助迭代器 43 44 accountHash common.Hash //包含帐户的节点的哈希 45 codeHash common.Hash //合同源代码的哈希 46 code []byte //与合同相关的源代码 47 48 Hash common.Hash //正在迭代的当前条目的哈希(如果不是独立的,则为零) 49 Parent common.Hash //第一个完整祖先节点的哈希(如果当前是根节点,则为零) 50 51 Error error //迭代器中出现内部错误时的故障集 52 } 53 54 //newnodeiterator创建一个后序状态节点迭代器。 55 func NewNodeIterator(state *StateDB) *NodeIterator { 56 return &NodeIterator{ 57 state: state, 58 } 59 } 60 61 //next将迭代器移动到下一个节点,返回是否存在 62 //进一步的节点。如果出现内部错误,此方法将返回false,并且 63 //将错误字段设置为遇到的故障。 64 func (it *NodeIterator) Next() bool { 65 //如果迭代器以前失败,则不要执行任何操作 66 if it.Error != nil { 67 return false 68 } 69 //否则,使用迭代器前进并报告任何错误 70 if err := it.step(); err != nil { 71 it.Error = err 72 return false 73 } 74 return it.retrieve() 75 } 76 77 //步骤将迭代器移动到状态trie的下一个条目。 78 func (it *NodeIterator) step() error { 79 //如果到达迭代结束,则中止 80 if it.state == nil { 81 return nil 82 } 83 //如果我们刚开始初始化迭代器 84 if it.stateIt == nil { 85 it.stateIt = it.state.trie.NodeIterator(nil) 86 } 87 //如果我们以前有数据节点,那么我们肯定至少有状态节点 88 if it.dataIt != nil { 89 if cont := it.dataIt.Next(true); !cont { 90 if it.dataIt.Error() != nil { 91 return it.dataIt.Error() 92 } 93 it.dataIt = nil 94 } 95 return nil 96 } 97 //如果我们以前有源代码,就放弃它 98 if it.code != nil { 99 it.code = nil 100 return nil 101 } 102 //进入下一个状态trie节点,如果节点用完则终止 103 if cont := it.stateIt.Next(true); !cont { 104 if it.stateIt.Error() != nil { 105 return it.stateIt.Error() 106 } 107 it.state, it.stateIt = nil, nil 108 return nil 109 } 110 //如果状态trie节点是内部条目,则保持原样 111 if !it.stateIt.Leaf() { 112 return nil 113 } 114 //否则,我们将到达一个帐户节点,开始数据迭代 115 var account Account 116 if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil { 117 return err 118 } 119 dataTrie, err := it.state.db.OpenStorageTrie(common.BytesToHash(it.stateIt.LeafKey()), account.Root) 120 if err != nil { 121 return err 122 } 123 it.dataIt = dataTrie.NodeIterator(nil) 124 if !it.dataIt.Next(true) { 125 it.dataIt = nil 126 } 127 if !bytes.Equal(account.CodeHash, emptyCodeHash) { 128 it.codeHash = common.BytesToHash(account.CodeHash) 129 addrHash := common.BytesToHash(it.stateIt.LeafKey()) 130 it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash)) 131 if err != nil { 132 return fmt.Errorf("code %x: %v", account.CodeHash, err) 133 } 134 } 135 it.accountHash = it.stateIt.Parent() 136 return nil 137 } 138 139 //检索拉取和缓存迭代器正在遍历的当前状态条目。 140 //该方法返回是否还有其他数据要检查。 141 func (it *NodeIterator) retrieve() bool { 142 //清除任何预先设置的值 143 it.Hash = common.Hash{} 144 145 //如果迭代完成,则不返回可用数据 146 if it.state == nil { 147 return false 148 } 149 //否则检索当前条目 150 switch { 151 case it.dataIt != nil: 152 it.Hash, it.Parent = it.dataIt.Hash(), it.dataIt.Parent() 153 if it.Parent == (common.Hash{}) { 154 it.Parent = it.accountHash 155 } 156 case it.code != nil: 157 it.Hash, it.Parent = it.codeHash, it.accountHash 158 case it.stateIt != nil: 159 it.Hash, it.Parent = it.stateIt.Hash(), it.stateIt.Parent() 160 } 161 return true 162 }