github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/vm/analysis.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 //版权所有2014 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 vm 26 27 import ( 28 "math/big" 29 30 "github.com/ethereum/go-ethereum/common" 31 ) 32 33 //目的地为每个契约存储一个映射(由代码散列键控)。 34 //地图包含JumpDest的每个位置的条目。 35 //指令。 36 type destinations map[common.Hash]bitvec 37 38 //检查代码在dest是否有JumpDest。 39 func (d destinations) has(codehash common.Hash, code []byte, dest *big.Int) bool { 40 //PC不能超过len(code),当然不能超过63位。 41 //在这种情况下,不要费心检查Jumpdest。 42 udest := dest.Uint64() 43 if dest.BitLen() >= 63 || udest >= uint64(len(code)) { 44 return false 45 } 46 47 m, analysed := d[codehash] 48 if !analysed { 49 m = codeBitmap(code) 50 d[codehash] = m 51 } 52 return OpCode(code[udest]) == JUMPDEST && m.codeSegment(udest) 53 } 54 55 //bitvec是一个位向量,它映射程序中的字节。 56 //未设置位表示字节为操作码,设置位表示 57 //这是数据(即pushxx的参数)。 58 type bitvec []byte 59 60 func (bits *bitvec) set(pos uint64) { 61 (*bits)[pos/8] |= 0x80 >> (pos % 8) 62 } 63 func (bits *bitvec) set8(pos uint64) { 64 (*bits)[pos/8] |= 0xFF >> (pos % 8) 65 (*bits)[pos/8+1] |= ^(0xFF >> (pos % 8)) 66 } 67 68 //代码段检查位置是否在代码段中。 69 func (bits *bitvec) codeSegment(pos uint64) bool { 70 return ((*bits)[pos/8] & (0x80 >> (pos % 8))) == 0 71 } 72 73 //codeBitmap以代码的形式收集数据位置。 74 func codeBitmap(code []byte) bitvec { 75 //如果代码 76 //以push32结束,算法将把0推到 77 //位向量超出了实际代码的边界。 78 bits := make(bitvec, len(code)/8+1+4) 79 for pc := uint64(0); pc < uint64(len(code)); { 80 op := OpCode(code[pc]) 81 82 if op >= PUSH1 && op <= PUSH32 { 83 numbits := op - PUSH1 + 1 84 pc++ 85 for ; numbits >= 8; numbits -= 8 { 86 bits.set8(pc) //八 87 pc += 8 88 } 89 for ; numbits > 0; numbits-- { 90 bits.set(pc) 91 pc++ 92 } 93 } else { 94 pc++ 95 } 96 } 97 return bits 98 }