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  }