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 }