github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/vm/contracts.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  	"crypto/sha256"
    29  	"errors"
    30  	"math/big"
    31  
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/common/math"
    34  	"github.com/ethereum/go-ethereum/crypto"
    35  	"github.com/ethereum/go-ethereum/crypto/bn256"
    36  	"github.com/ethereum/go-ethereum/params"
    37  	"golang.org/x/crypto/ripemd160"
    38  )
    39  
    40  //预编译契约是本地Go契约的基本接口。实施
    41  //需要基于运行方法的输入大小确定的气体计数
    42  //合同。
    43  type PrecompiledContract interface {
    44  RequiredGas(input []byte) uint64  //所需价格计算合同用气
    45  Run(input []byte) ([]byte, error) //运行运行预编译合同
    46  }
    47  
    48  //预编译的ContractShomestead包含预编译的ethereum的默认集
    49  //边境地区使用的合同和宅基地释放。
    50  var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
    51  	common.BytesToAddress([]byte{1}): &ecrecover{},
    52  	common.BytesToAddress([]byte{2}): &sha256hash{},
    53  	common.BytesToAddress([]byte{3}): &ripemd160hash{},
    54  	common.BytesToAddress([]byte{4}): &dataCopy{},
    55  }
    56  
    57  //PrecompiledContractsByzantium包含预编译的ethereum的默认集
    58  //拜占庭协议中使用的合同。
    59  var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
    60  	common.BytesToAddress([]byte{1}): &ecrecover{},
    61  	common.BytesToAddress([]byte{2}): &sha256hash{},
    62  	common.BytesToAddress([]byte{3}): &ripemd160hash{},
    63  	common.BytesToAddress([]byte{4}): &dataCopy{},
    64  	common.BytesToAddress([]byte{5}): &bigModExp{},
    65  	common.BytesToAddress([]byte{6}): &bn256Add{},
    66  	common.BytesToAddress([]byte{7}): &bn256ScalarMul{},
    67  	common.BytesToAddress([]byte{8}): &bn256Pairing{},
    68  }
    69  
    70  //runPrecompiledContract运行并评估预编译合同的输出。
    71  func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
    72  	gas := p.RequiredGas(input)
    73  	if contract.UseGas(gas) {
    74  		return p.Run(input)
    75  	}
    76  	return nil, ErrOutOfGas
    77  }
    78  
    79  //ecrecover作为本机合同实现。
    80  type ecrecover struct{}
    81  
    82  func (c *ecrecover) RequiredGas(input []byte) uint64 {
    83  	return params.EcrecoverGas
    84  }
    85  
    86  func (c *ecrecover) Run(input []byte) ([]byte, error) {
    87  	const ecRecoverInputLength = 128
    88  
    89  	input = common.RightPadBytes(input, ecRecoverInputLength)
    90  //“input”是(hash、v、r、s),每个32字节
    91  //但对于ecrecover,我们需要(r,s,v)
    92  
    93  	r := new(big.Int).SetBytes(input[64:96])
    94  	s := new(big.Int).SetBytes(input[96:128])
    95  	v := input[63] - 27
    96  
    97  //更紧密的sig s值输入homestead仅适用于tx sig s
    98  	if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
    99  		return nil, nil
   100  	}
   101  //对于libsecp256k1,v必须在末尾
   102  	pubKey, err := crypto.Ecrecover(input[:32], append(input[64:128], v))
   103  //确保公钥是有效的。
   104  	if err != nil {
   105  		return nil, nil
   106  	}
   107  
   108  //pubkey的第一个字节是比特币遗产
   109  	return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
   110  }
   111  
   112  //sha256作为本地合同实施。
   113  type sha256hash struct{}
   114  
   115  //Requiredgas返回执行预编译合同所需的气体。
   116  //
   117  //这种方法不需要任何溢出检查作为输入尺寸的气体成本。
   118  //任何重要的事情都需要如此之高的代价。
   119  func (c *sha256hash) RequiredGas(input []byte) uint64 {
   120  	return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
   121  }
   122  func (c *sha256hash) Run(input []byte) ([]byte, error) {
   123  	h := sha256.Sum256(input)
   124  	return h[:], nil
   125  }
   126  
   127  //ripemd160作为本地合同实施。
   128  type ripemd160hash struct{}
   129  
   130  //Requiredgas返回执行预编译合同所需的气体。
   131  //
   132  //这种方法不需要任何溢出检查作为输入尺寸的气体成本。
   133  //任何重要的事情都需要如此之高的代价。
   134  func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
   135  	return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
   136  }
   137  func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
   138  	ripemd := ripemd160.New()
   139  	ripemd.Write(input)
   140  	return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
   141  }
   142  
   143  //数据复制作为本机协定实现。
   144  type dataCopy struct{}
   145  
   146  //Requiredgas返回执行预编译合同所需的气体。
   147  //
   148  //这种方法不需要任何溢出检查作为输入尺寸的气体成本。
   149  //任何重要的事情都需要如此之高的代价。
   150  func (c *dataCopy) RequiredGas(input []byte) uint64 {
   151  	return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
   152  }
   153  func (c *dataCopy) Run(in []byte) ([]byte, error) {
   154  	return in, nil
   155  }
   156  
   157  //bigmodexp实现了本机的大整数指数模块化操作。
   158  type bigModExp struct{}
   159  
   160  var (
   161  	big1      = big.NewInt(1)
   162  	big4      = big.NewInt(4)
   163  	big8      = big.NewInt(8)
   164  	big16     = big.NewInt(16)
   165  	big32     = big.NewInt(32)
   166  	big64     = big.NewInt(64)
   167  	big96     = big.NewInt(96)
   168  	big480    = big.NewInt(480)
   169  	big1024   = big.NewInt(1024)
   170  	big3072   = big.NewInt(3072)
   171  	big199680 = big.NewInt(199680)
   172  )
   173  
   174  //Requiredgas返回执行预编译合同所需的气体。
   175  func (c *bigModExp) RequiredGas(input []byte) uint64 {
   176  	var (
   177  		baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
   178  		expLen  = new(big.Int).SetBytes(getData(input, 32, 32))
   179  		modLen  = new(big.Int).SetBytes(getData(input, 64, 32))
   180  	)
   181  	if len(input) > 96 {
   182  		input = input[96:]
   183  	} else {
   184  		input = input[:0]
   185  	}
   186  //为调整后的指数长度检索exp的头32字节
   187  	var expHead *big.Int
   188  	if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
   189  		expHead = new(big.Int)
   190  	} else {
   191  		if expLen.Cmp(big32) > 0 {
   192  			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
   193  		} else {
   194  			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
   195  		}
   196  	}
   197  //计算调整后的指数长度
   198  	var msb int
   199  	if bitlen := expHead.BitLen(); bitlen > 0 {
   200  		msb = bitlen - 1
   201  	}
   202  	adjExpLen := new(big.Int)
   203  	if expLen.Cmp(big32) > 0 {
   204  		adjExpLen.Sub(expLen, big32)
   205  		adjExpLen.Mul(big8, adjExpLen)
   206  	}
   207  	adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
   208  
   209  //计算操作的燃气成本
   210  	gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
   211  	switch {
   212  	case gas.Cmp(big64) <= 0:
   213  		gas.Mul(gas, gas)
   214  	case gas.Cmp(big1024) <= 0:
   215  		gas = new(big.Int).Add(
   216  			new(big.Int).Div(new(big.Int).Mul(gas, gas), big4),
   217  			new(big.Int).Sub(new(big.Int).Mul(big96, gas), big3072),
   218  		)
   219  	default:
   220  		gas = new(big.Int).Add(
   221  			new(big.Int).Div(new(big.Int).Mul(gas, gas), big16),
   222  			new(big.Int).Sub(new(big.Int).Mul(big480, gas), big199680),
   223  		)
   224  	}
   225  	gas.Mul(gas, math.BigMax(adjExpLen, big1))
   226  	gas.Div(gas, new(big.Int).SetUint64(params.ModExpQuadCoeffDiv))
   227  
   228  	if gas.BitLen() > 64 {
   229  		return math.MaxUint64
   230  	}
   231  	return gas.Uint64()
   232  }
   233  
   234  func (c *bigModExp) Run(input []byte) ([]byte, error) {
   235  	var (
   236  		baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
   237  		expLen  = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
   238  		modLen  = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64()
   239  	)
   240  	if len(input) > 96 {
   241  		input = input[96:]
   242  	} else {
   243  		input = input[:0]
   244  	}
   245  //当基本长度和模长都为零时处理特殊情况
   246  	if baseLen == 0 && modLen == 0 {
   247  		return []byte{}, nil
   248  	}
   249  //检索操作数并执行求幂
   250  	var (
   251  		base = new(big.Int).SetBytes(getData(input, 0, baseLen))
   252  		exp  = new(big.Int).SetBytes(getData(input, baseLen, expLen))
   253  		mod  = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
   254  	)
   255  	if mod.BitLen() == 0 {
   256  //模0未定义,返回零
   257  		return common.LeftPadBytes([]byte{}, int(modLen)), nil
   258  	}
   259  	return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil
   260  }
   261  
   262  //newcurvepoint将二进制blob解封为bn256椭圆曲线点,
   263  //返回它,或者如果点无效则返回错误。
   264  func newCurvePoint(blob []byte) (*bn256.G1, error) {
   265  	p := new(bn256.G1)
   266  	if _, err := p.Unmarshal(blob); err != nil {
   267  		return nil, err
   268  	}
   269  	return p, nil
   270  }
   271  
   272  //newTwistpoint将二进制斑点解组为bn256椭圆曲线点,
   273  //返回它,或者如果点无效则返回错误。
   274  func newTwistPoint(blob []byte) (*bn256.G2, error) {
   275  	p := new(bn256.G2)
   276  	if _, err := p.Unmarshal(blob); err != nil {
   277  		return nil, err
   278  	}
   279  	return p, nil
   280  }
   281  
   282  //bn256add实现本机椭圆曲线点加法。
   283  type bn256Add struct{}
   284  
   285  //Requiredgas返回执行预编译合同所需的气体。
   286  func (c *bn256Add) RequiredGas(input []byte) uint64 {
   287  	return params.Bn256AddGas
   288  }
   289  
   290  func (c *bn256Add) Run(input []byte) ([]byte, error) {
   291  	x, err := newCurvePoint(getData(input, 0, 64))
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  	y, err := newCurvePoint(getData(input, 64, 64))
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  	res := new(bn256.G1)
   300  	res.Add(x, y)
   301  	return res.Marshal(), nil
   302  }
   303  
   304  //bn256scalarmul实现本机椭圆曲线标量乘法。
   305  type bn256ScalarMul struct{}
   306  
   307  //Requiredgas返回执行预编译合同所需的气体。
   308  func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
   309  	return params.Bn256ScalarMulGas
   310  }
   311  
   312  func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
   313  	p, err := newCurvePoint(getData(input, 0, 64))
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	res := new(bn256.G1)
   318  	res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32)))
   319  	return res.Marshal(), nil
   320  }
   321  
   322  var (
   323  //如果bn256配对检查成功,则返回true32字节。
   324  	true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
   325  
   326  //如果bn256配对检查失败,则返回假32byte。
   327  	false32Byte = make([]byte, 32)
   328  
   329  //如果bn256配对输入无效,则返回errbadpairinginput。
   330  	errBadPairingInput = errors.New("bad elliptic curve pairing size")
   331  )
   332  
   333  //bn256配对为bn256曲线执行配对预编译
   334  type bn256Pairing struct{}
   335  
   336  //Requiredgas返回执行预编译合同所需的气体。
   337  func (c *bn256Pairing) RequiredGas(input []byte) uint64 {
   338  	return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas
   339  }
   340  
   341  func (c *bn256Pairing) Run(input []byte) ([]byte, error) {
   342  //便宜处理一些角箱
   343  	if len(input)%192 > 0 {
   344  		return nil, errBadPairingInput
   345  	}
   346  //将输入转换为一组坐标
   347  	var (
   348  		cs []*bn256.G1
   349  		ts []*bn256.G2
   350  	)
   351  	for i := 0; i < len(input); i += 192 {
   352  		c, err := newCurvePoint(input[i : i+64])
   353  		if err != nil {
   354  			return nil, err
   355  		}
   356  		t, err := newTwistPoint(input[i+64 : i+192])
   357  		if err != nil {
   358  			return nil, err
   359  		}
   360  		cs = append(cs, c)
   361  		ts = append(ts, t)
   362  	}
   363  //执行配对检查并返回结果
   364  	if bn256.PairingCheck(cs, ts) {
   365  		return true32Byte, nil
   366  	}
   367  	return false32Byte, nil
   368  }