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