github.com/core-coin/go-core/v2@v2.1.9/core/vm/contracts.go (about) 1 // Copyright 2014 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "crypto/sha256" 21 "encoding/binary" 22 "errors" 23 "math/big" 24 25 "golang.org/x/crypto/sha3" 26 27 "github.com/core-coin/go-core/v2/common" 28 "github.com/core-coin/go-core/v2/common/math" 29 "github.com/core-coin/go-core/v2/crypto" 30 "github.com/core-coin/go-core/v2/crypto/blake2b" 31 "github.com/core-coin/go-core/v2/crypto/bn256" 32 "github.com/core-coin/go-core/v2/params" 33 34 //lint:ignore SA1019 Needed for precompile 35 "golang.org/x/crypto/ripemd160" 36 ) 37 38 // PrecompiledContract is the basic interface for native Go contracts. The implementation 39 // requires a deterministic energy count based on the input size of the Run method of the 40 // contract. 41 type PrecompiledContract interface { 42 RequiredEnergy(input []byte) uint64 // RequiredPrice calculates the contract energy use 43 Run(input []byte) ([]byte, error) // Run runs the precompiled contract 44 } 45 46 // PrecompiledContracts contains the default set of pre-compiled Core 47 // contracts used in the release. 48 func PrecompiledContracts(chainConfig *params.ChainConfig, blockNum *big.Int) map[common.Address]PrecompiledContract { 49 contracts := map[common.Address]PrecompiledContract{} 50 51 contracts[common.BytesToAddress([]byte{1})] = &ecrecover{} 52 contracts[common.BytesToAddress([]byte{2})] = &sha256hash{} 53 contracts[common.BytesToAddress([]byte{3})] = &ripemd160hash{} 54 contracts[common.BytesToAddress([]byte{4})] = &dataCopy{} 55 contracts[common.BytesToAddress([]byte{5})] = &bigModExp{} 56 contracts[common.BytesToAddress([]byte{6})] = &bn256Add{} 57 contracts[common.BytesToAddress([]byte{7})] = &bn256ScalarMul{} 58 contracts[common.BytesToAddress([]byte{8})] = &bn256Pairing{} 59 contracts[common.BytesToAddress([]byte{9})] = &blake2F{} 60 61 return contracts 62 } 63 64 // RunPrecompiledContract runs and evaluates the output of a precompiled contract. 65 // It returns 66 // - the returned bytes, 67 // - the _remaining_ energy, 68 // - any error that occurred 69 func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedEnergy uint64) (ret []byte, remainingEnergy uint64, err error) { 70 energyCost := p.RequiredEnergy(input) 71 if suppliedEnergy < energyCost { 72 return nil, 0, ErrOutOfEnergy 73 } 74 suppliedEnergy -= energyCost 75 output, err := p.Run(input) 76 return output, suppliedEnergy, err 77 } 78 79 // ECRECOVER implemented as a native contract. 80 type ecrecover struct{} 81 82 func (c *ecrecover) RequiredEnergy(input []byte) uint64 { 83 return params.EcrecoverEnergy 84 } 85 86 func (c *ecrecover) Run(input []byte) ([]byte, error) { 87 var ecRecoverInputLength = sha3.New256().Size() + crypto.ExtendedSignatureLength // 32 + 171 88 89 input = common.RightPadBytes(input, ecRecoverInputLength) 90 91 pubKey, err := crypto.Ecrecover(input[:32], input[96:267]) 92 // make sure the public key is a valid one 93 if err != nil { 94 return nil, err 95 } 96 if pubKey != nil { 97 pub, err := crypto.UnmarshalPubKey(pubKey) 98 if err != nil { 99 return nil, err 100 } 101 return common.LeftPadBytes(crypto.PubkeyToAddress(pub).Bytes(), 32), nil 102 } 103 return nil, errors.New("invalid signature") 104 } 105 106 // SHA256 implemented as a native contract. 107 type sha256hash struct{} 108 109 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 110 // 111 // This method does not require any overflow checking as the input size energy costs 112 // required for anything significant is so high it's impossible to pay for. 113 func (c *sha256hash) RequiredEnergy(input []byte) uint64 { 114 return uint64(len(input)+31)/32*params.Sha256PerWordEnergy + params.Sha256BaseEnergy 115 } 116 func (c *sha256hash) Run(input []byte) ([]byte, error) { 117 h := sha256.Sum256(input) 118 return h[:], nil 119 } 120 121 // RIPEMD160 implemented as a native contract. 122 type ripemd160hash struct{} 123 124 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 125 // 126 // This method does not require any overflow checking as the input size energy costs 127 // required for anything significant is so high it's impossible to pay for. 128 func (c *ripemd160hash) RequiredEnergy(input []byte) uint64 { 129 return uint64(len(input)+31)/32*params.Ripemd160PerWordEnergy + params.Ripemd160BaseEnergy 130 } 131 func (c *ripemd160hash) Run(input []byte) ([]byte, error) { 132 ripemd := ripemd160.New() 133 ripemd.Write(input) 134 return common.LeftPadBytes(ripemd.Sum(nil), 32), nil 135 } 136 137 // data copy implemented as a native contract. 138 type dataCopy struct{} 139 140 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 141 // 142 // This method does not require any overflow checking as the input size energy costs 143 // required for anything significant is so high it's impossible to pay for. 144 func (c *dataCopy) RequiredEnergy(input []byte) uint64 { 145 return uint64(len(input)+31)/32*params.IdentityPerWordEnergy + params.IdentityBaseEnergy 146 } 147 func (c *dataCopy) Run(in []byte) ([]byte, error) { 148 return in, nil 149 } 150 151 // bigModExp implements a native big integer exponential modular operation. 152 type bigModExp struct { 153 } 154 155 var ( 156 big0 = big.NewInt(0) 157 big1 = big.NewInt(1) 158 big3 = big.NewInt(3) 159 big4 = big.NewInt(4) 160 big7 = big.NewInt(7) 161 big8 = big.NewInt(8) 162 big16 = big.NewInt(16) 163 big20 = big.NewInt(20) 164 big32 = big.NewInt(32) 165 big64 = big.NewInt(64) 166 big96 = big.NewInt(96) 167 big480 = big.NewInt(480) 168 big1024 = big.NewInt(1024) 169 big3072 = big.NewInt(3072) 170 big199680 = big.NewInt(199680) 171 ) 172 173 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 174 func (c *bigModExp) RequiredEnergy(input []byte) uint64 { 175 var ( 176 baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) 177 expLen = new(big.Int).SetBytes(getData(input, 32, 32)) 178 modLen = new(big.Int).SetBytes(getData(input, 64, 32)) 179 ) 180 if len(input) > 96 { 181 input = input[96:] 182 } else { 183 input = input[:0] 184 } 185 // Retrieve the head 32 bytes of exp for the adjusted exponent length 186 var expHead *big.Int 187 if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 { 188 expHead = new(big.Int) 189 } else { 190 if expLen.Cmp(big32) > 0 { 191 expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32)) 192 } else { 193 expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64())) 194 } 195 } 196 // Calculate the adjusted exponent length 197 var msb int 198 if bitlen := expHead.BitLen(); bitlen > 0 { 199 msb = bitlen - 1 200 } 201 adjExpLen := new(big.Int) 202 if expLen.Cmp(big32) > 0 { 203 adjExpLen.Sub(expLen, big32) 204 adjExpLen.Mul(big8, adjExpLen) 205 } 206 adjExpLen.Add(adjExpLen, big.NewInt(int64(msb))) 207 208 // Calculate the energy cost of the operation 209 energy := new(big.Int).Set(math.BigMax(modLen, baseLen)) 210 switch { 211 case energy.Cmp(big64) <= 0: 212 energy.Mul(energy, energy) 213 case energy.Cmp(big1024) <= 0: 214 energy = new(big.Int).Add( 215 new(big.Int).Div(new(big.Int).Mul(energy, energy), big4), 216 new(big.Int).Sub(new(big.Int).Mul(big96, energy), big3072), 217 ) 218 default: 219 energy = new(big.Int).Add( 220 new(big.Int).Div(new(big.Int).Mul(energy, energy), big16), 221 new(big.Int).Sub(new(big.Int).Mul(big480, energy), big199680), 222 ) 223 } 224 energy.Mul(energy, math.BigMax(adjExpLen, big1)) 225 energy.Div(energy, new(big.Int).SetUint64(params.ModExpQuadCoeffDiv)) 226 227 if energy.BitLen() > 64 { 228 return math.MaxUint64 229 } 230 return energy.Uint64() 231 } 232 233 func (c *bigModExp) Run(input []byte) ([]byte, error) { 234 var ( 235 baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() 236 expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() 237 modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64() 238 ) 239 if len(input) > 96 { 240 input = input[96:] 241 } else { 242 input = input[:0] 243 } 244 // Handle a special case when both the base and mod length is zero 245 if baseLen == 0 && modLen == 0 { 246 return []byte{}, nil 247 } 248 // Retrieve the operands and execute the exponentiation 249 var ( 250 base = new(big.Int).SetBytes(getData(input, 0, baseLen)) 251 exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) 252 mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) 253 ) 254 if mod.BitLen() == 0 { 255 // Modulo 0 is undefined, return zero 256 return common.LeftPadBytes([]byte{}, int(modLen)), nil 257 } 258 return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil 259 } 260 261 // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point, 262 // returning it, or an error if the point is invalid. 263 func newCurvePoint(blob []byte) (*bn256.G1, error) { 264 p := new(bn256.G1) 265 if _, err := p.Unmarshal(blob); err != nil { 266 return nil, err 267 } 268 return p, nil 269 } 270 271 // newTwistPoint unmarshals a binary blob into a bn256 elliptic curve point, 272 // returning it, or an error if the point is invalid. 273 func newTwistPoint(blob []byte) (*bn256.G2, error) { 274 p := new(bn256.G2) 275 if _, err := p.Unmarshal(blob); err != nil { 276 return nil, err 277 } 278 return p, nil 279 } 280 281 // bn256Add implements a native elliptic curve point addition conforming to 282 // consensus rules. 283 type bn256Add struct{} 284 285 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 286 func (c *bn256Add) RequiredEnergy(input []byte) uint64 { 287 return params.Bn256AddEnergy 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 implements a native elliptic curve scalar 305 // multiplication conforming to consensus rules. 306 type bn256ScalarMul struct{} 307 308 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 309 func (c *bn256ScalarMul) RequiredEnergy(input []byte) uint64 { 310 return params.Bn256ScalarMulEnergy 311 } 312 313 func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) { 314 p, err := newCurvePoint(getData(input, 0, 64)) 315 if err != nil { 316 return nil, err 317 } 318 res := new(bn256.G1) 319 res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32))) 320 return res.Marshal(), nil 321 } 322 323 var ( 324 // true32Byte is returned if the bn256 pairing check succeeds. 325 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} 326 327 // false32Byte is returned if the bn256 pairing check fails. 328 false32Byte = make([]byte, 32) 329 330 // errBadPairingInput is returned if the bn256 pairing input is invalid. 331 errBadPairingInput = errors.New("bad elliptic curve pairing size") 332 ) 333 334 // bn256Pairing implements a pairing pre-compile for the bn256 curve 335 // conforming to consensus rules. 336 type bn256Pairing struct{} 337 338 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 339 func (c *bn256Pairing) RequiredEnergy(input []byte) uint64 { 340 return params.Bn256PairingBaseEnergy + uint64(len(input)/192)*params.Bn256PairingPerPointEnergy 341 } 342 343 func (c *bn256Pairing) Run(input []byte) ([]byte, error) { 344 // Handle some corner cases cheaply 345 if len(input)%192 > 0 { 346 return nil, errBadPairingInput 347 } 348 // Convert the input into a set of coordinates 349 var ( 350 cs []*bn256.G1 351 ts []*bn256.G2 352 ) 353 for i := 0; i < len(input); i += 192 { 354 c, err := newCurvePoint(input[i : i+64]) 355 if err != nil { 356 return nil, err 357 } 358 t, err := newTwistPoint(input[i+64 : i+192]) 359 if err != nil { 360 return nil, err 361 } 362 cs = append(cs, c) 363 ts = append(ts, t) 364 } 365 // Execute the pairing checks and return the results 366 if bn256.PairingCheck(cs, ts) { 367 return true32Byte, nil 368 } 369 return false32Byte, nil 370 } 371 372 type blake2F struct{} 373 374 func (c *blake2F) RequiredEnergy(input []byte) uint64 { 375 // If the input is malformed, we can't calculate the energy, return 0 and let the 376 // actual call choke and fault. 377 if len(input) != blake2FInputLength { 378 return 0 379 } 380 return uint64(binary.BigEndian.Uint32(input[0:4])) 381 } 382 383 const ( 384 blake2FInputLength = 213 385 blake2FFinalBlockBytes = byte(1) 386 blake2FNonFinalBlockBytes = byte(0) 387 ) 388 389 var ( 390 errBlake2FInvalidInputLength = errors.New("invalid input length") 391 errBlake2FInvalidFinalFlag = errors.New("invalid final flag") 392 ) 393 394 func (c *blake2F) Run(input []byte) ([]byte, error) { 395 // Make sure the input is valid (correct length and final flag) 396 if len(input) != blake2FInputLength { 397 return nil, errBlake2FInvalidInputLength 398 } 399 if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes { 400 return nil, errBlake2FInvalidFinalFlag 401 } 402 // Parse the input into the Blake2b call parameters 403 var ( 404 rounds = binary.BigEndian.Uint32(input[0:4]) 405 final = (input[212] == blake2FFinalBlockBytes) 406 407 h [8]uint64 408 m [16]uint64 409 t [2]uint64 410 ) 411 for i := 0; i < 8; i++ { 412 offset := 4 + i*8 413 h[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) 414 } 415 for i := 0; i < 16; i++ { 416 offset := 68 + i*8 417 m[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) 418 } 419 t[0] = binary.LittleEndian.Uint64(input[196:204]) 420 t[1] = binary.LittleEndian.Uint64(input[204:212]) 421 422 // Execute the compression function, extract and return the result 423 blake2b.F(&h, m, t, final, rounds) 424 425 output := make([]byte, 64) 426 for i := 0; i < 8; i++ { 427 offset := i * 8 428 binary.LittleEndian.PutUint64(output[offset:offset+8], h[i]) 429 } 430 return output, nil 431 }