github.com/core-coin/go-core/v2@v2.0.6/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 if chainConfig != nil && 52 blockNum != nil && 53 blockNum.Int64() <= params.DevinOldEcrecoverBlockNum && 54 chainConfig.NetworkID.Int64() == common.Devin { 55 contracts[common.BytesToAddress([]byte{1})] = &ecrecoverOldDevin{} 56 } else { 57 contracts[common.BytesToAddress([]byte{1})] = &ecrecover{} 58 } 59 contracts[common.BytesToAddress([]byte{2})] = &sha256hash{} 60 contracts[common.BytesToAddress([]byte{3})] = &ripemd160hash{} 61 contracts[common.BytesToAddress([]byte{4})] = &dataCopy{} 62 contracts[common.BytesToAddress([]byte{5})] = &bigModExp{} 63 contracts[common.BytesToAddress([]byte{6})] = &bn256Add{} 64 contracts[common.BytesToAddress([]byte{7})] = &bn256ScalarMul{} 65 contracts[common.BytesToAddress([]byte{8})] = &bn256Pairing{} 66 contracts[common.BytesToAddress([]byte{9})] = &blake2F{} 67 68 return contracts 69 } 70 71 // RunPrecompiledContract runs and evaluates the output of a precompiled contract. 72 // It returns 73 // - the returned bytes, 74 // - the _remaining_ energy, 75 // - any error that occurred 76 func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedEnergy uint64) (ret []byte, remainingEnergy uint64, err error) { 77 energyCost := p.RequiredEnergy(input) 78 if suppliedEnergy < energyCost { 79 return nil, 0, ErrOutOfEnergy 80 } 81 suppliedEnergy -= energyCost 82 output, err := p.Run(input) 83 return output, suppliedEnergy, err 84 } 85 86 // ECRECOVER implemented as a native contract. 87 type ecrecover struct{} 88 89 func (c *ecrecover) RequiredEnergy(input []byte) uint64 { 90 return params.EcrecoverEnergy 91 } 92 93 func (c *ecrecover) Run(input []byte) ([]byte, error) { 94 var ecRecoverInputLength = sha3.New256().Size() + crypto.ExtendedSignatureLength // 32 + 171 95 96 input = common.RightPadBytes(input, ecRecoverInputLength) 97 98 pubKey, err := crypto.Ecrecover(input[:32], input[96:267]) 99 // make sure the public key is a valid one 100 if err != nil { 101 return nil, err 102 } 103 if pubKey != nil { 104 pub, err := crypto.UnmarshalPubKey(pubKey) 105 if err != nil { 106 return nil, err 107 } 108 return common.LeftPadBytes(crypto.PubkeyToAddress(pub).Bytes(), 32), nil 109 } 110 return nil, errors.New("invalid signature") 111 } 112 113 // ECRECOVER implemented as a native contract. 114 type ecrecoverOldDevin struct{} 115 116 func (c *ecrecoverOldDevin) RequiredEnergy(input []byte) uint64 { 117 return params.EcrecoverEnergy 118 } 119 120 func (c *ecrecoverOldDevin) Run(input []byte) ([]byte, error) { 121 var ecRecoverInputLength = sha3.New256().Size() + crypto.ExtendedSignatureLength // 32 + 171 122 123 input = common.RightPadBytes(input, ecRecoverInputLength) 124 125 pubKey, err := crypto.Ecrecover(input[:32], input[96:267]) 126 // make sure the public key is a valid one 127 if err != nil { 128 return nil, nil 129 } 130 if pubKey != nil { 131 pub, err := crypto.UnmarshalPubKey(pubKey) 132 if err != nil { 133 return nil, err 134 } 135 return common.LeftPadBytes(crypto.PubkeyToAddress(pub).Bytes(), 32), nil 136 } 137 return nil, errors.New("invalid signature") 138 } 139 140 // SHA256 implemented as a native contract. 141 type sha256hash struct{} 142 143 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 144 // 145 // This method does not require any overflow checking as the input size energy costs 146 // required for anything significant is so high it's impossible to pay for. 147 func (c *sha256hash) RequiredEnergy(input []byte) uint64 { 148 return uint64(len(input)+31)/32*params.Sha256PerWordEnergy + params.Sha256BaseEnergy 149 } 150 func (c *sha256hash) Run(input []byte) ([]byte, error) { 151 h := sha256.Sum256(input) 152 return h[:], nil 153 } 154 155 // RIPEMD160 implemented as a native contract. 156 type ripemd160hash struct{} 157 158 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 159 // 160 // This method does not require any overflow checking as the input size energy costs 161 // required for anything significant is so high it's impossible to pay for. 162 func (c *ripemd160hash) RequiredEnergy(input []byte) uint64 { 163 return uint64(len(input)+31)/32*params.Ripemd160PerWordEnergy + params.Ripemd160BaseEnergy 164 } 165 func (c *ripemd160hash) Run(input []byte) ([]byte, error) { 166 ripemd := ripemd160.New() 167 ripemd.Write(input) 168 return common.LeftPadBytes(ripemd.Sum(nil), 32), nil 169 } 170 171 // data copy implemented as a native contract. 172 type dataCopy struct{} 173 174 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 175 // 176 // This method does not require any overflow checking as the input size energy costs 177 // required for anything significant is so high it's impossible to pay for. 178 func (c *dataCopy) RequiredEnergy(input []byte) uint64 { 179 return uint64(len(input)+31)/32*params.IdentityPerWordEnergy + params.IdentityBaseEnergy 180 } 181 func (c *dataCopy) Run(in []byte) ([]byte, error) { 182 return in, nil 183 } 184 185 // bigModExp implements a native big integer exponential modular operation. 186 type bigModExp struct { 187 } 188 189 var ( 190 big0 = big.NewInt(0) 191 big1 = big.NewInt(1) 192 big3 = big.NewInt(3) 193 big4 = big.NewInt(4) 194 big7 = big.NewInt(7) 195 big8 = big.NewInt(8) 196 big16 = big.NewInt(16) 197 big20 = big.NewInt(20) 198 big32 = big.NewInt(32) 199 big64 = big.NewInt(64) 200 big96 = big.NewInt(96) 201 big480 = big.NewInt(480) 202 big1024 = big.NewInt(1024) 203 big3072 = big.NewInt(3072) 204 big199680 = big.NewInt(199680) 205 ) 206 207 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 208 func (c *bigModExp) RequiredEnergy(input []byte) uint64 { 209 var ( 210 baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) 211 expLen = new(big.Int).SetBytes(getData(input, 32, 32)) 212 modLen = new(big.Int).SetBytes(getData(input, 64, 32)) 213 ) 214 if len(input) > 96 { 215 input = input[96:] 216 } else { 217 input = input[:0] 218 } 219 // Retrieve the head 32 bytes of exp for the adjusted exponent length 220 var expHead *big.Int 221 if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 { 222 expHead = new(big.Int) 223 } else { 224 if expLen.Cmp(big32) > 0 { 225 expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32)) 226 } else { 227 expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64())) 228 } 229 } 230 // Calculate the adjusted exponent length 231 var msb int 232 if bitlen := expHead.BitLen(); bitlen > 0 { 233 msb = bitlen - 1 234 } 235 adjExpLen := new(big.Int) 236 if expLen.Cmp(big32) > 0 { 237 adjExpLen.Sub(expLen, big32) 238 adjExpLen.Mul(big8, adjExpLen) 239 } 240 adjExpLen.Add(adjExpLen, big.NewInt(int64(msb))) 241 242 // Calculate the energy cost of the operation 243 energy := new(big.Int).Set(math.BigMax(modLen, baseLen)) 244 switch { 245 case energy.Cmp(big64) <= 0: 246 energy.Mul(energy, energy) 247 case energy.Cmp(big1024) <= 0: 248 energy = new(big.Int).Add( 249 new(big.Int).Div(new(big.Int).Mul(energy, energy), big4), 250 new(big.Int).Sub(new(big.Int).Mul(big96, energy), big3072), 251 ) 252 default: 253 energy = new(big.Int).Add( 254 new(big.Int).Div(new(big.Int).Mul(energy, energy), big16), 255 new(big.Int).Sub(new(big.Int).Mul(big480, energy), big199680), 256 ) 257 } 258 energy.Mul(energy, math.BigMax(adjExpLen, big1)) 259 energy.Div(energy, new(big.Int).SetUint64(params.ModExpQuadCoeffDiv)) 260 261 if energy.BitLen() > 64 { 262 return math.MaxUint64 263 } 264 return energy.Uint64() 265 } 266 267 func (c *bigModExp) Run(input []byte) ([]byte, error) { 268 var ( 269 baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() 270 expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() 271 modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64() 272 ) 273 if len(input) > 96 { 274 input = input[96:] 275 } else { 276 input = input[:0] 277 } 278 // Handle a special case when both the base and mod length is zero 279 if baseLen == 0 && modLen == 0 { 280 return []byte{}, nil 281 } 282 // Retrieve the operands and execute the exponentiation 283 var ( 284 base = new(big.Int).SetBytes(getData(input, 0, baseLen)) 285 exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) 286 mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) 287 ) 288 if mod.BitLen() == 0 { 289 // Modulo 0 is undefined, return zero 290 return common.LeftPadBytes([]byte{}, int(modLen)), nil 291 } 292 return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil 293 } 294 295 // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point, 296 // returning it, or an error if the point is invalid. 297 func newCurvePoint(blob []byte) (*bn256.G1, error) { 298 p := new(bn256.G1) 299 if _, err := p.Unmarshal(blob); err != nil { 300 return nil, err 301 } 302 return p, nil 303 } 304 305 // newTwistPoint unmarshals a binary blob into a bn256 elliptic curve point, 306 // returning it, or an error if the point is invalid. 307 func newTwistPoint(blob []byte) (*bn256.G2, error) { 308 p := new(bn256.G2) 309 if _, err := p.Unmarshal(blob); err != nil { 310 return nil, err 311 } 312 return p, nil 313 } 314 315 // bn256Add implements a native elliptic curve point addition conforming to 316 // consensus rules. 317 type bn256Add struct{} 318 319 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 320 func (c *bn256Add) RequiredEnergy(input []byte) uint64 { 321 return params.Bn256AddEnergy 322 } 323 324 func (c *bn256Add) Run(input []byte) ([]byte, error) { 325 x, err := newCurvePoint(getData(input, 0, 64)) 326 if err != nil { 327 return nil, err 328 } 329 y, err := newCurvePoint(getData(input, 64, 64)) 330 if err != nil { 331 return nil, err 332 } 333 res := new(bn256.G1) 334 res.Add(x, y) 335 return res.Marshal(), nil 336 } 337 338 // bn256ScalarMul implements a native elliptic curve scalar 339 // multiplication conforming to consensus rules. 340 type bn256ScalarMul struct{} 341 342 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 343 func (c *bn256ScalarMul) RequiredEnergy(input []byte) uint64 { 344 return params.Bn256ScalarMulEnergy 345 } 346 347 func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) { 348 p, err := newCurvePoint(getData(input, 0, 64)) 349 if err != nil { 350 return nil, err 351 } 352 res := new(bn256.G1) 353 res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32))) 354 return res.Marshal(), nil 355 } 356 357 var ( 358 // true32Byte is returned if the bn256 pairing check succeeds. 359 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} 360 361 // false32Byte is returned if the bn256 pairing check fails. 362 false32Byte = make([]byte, 32) 363 364 // errBadPairingInput is returned if the bn256 pairing input is invalid. 365 errBadPairingInput = errors.New("bad elliptic curve pairing size") 366 ) 367 368 // bn256Pairing implements a pairing pre-compile for the bn256 curve 369 // conforming to consensus rules. 370 type bn256Pairing struct{} 371 372 // RequiredEnergy returns the energy required to execute the pre-compiled contract. 373 func (c *bn256Pairing) RequiredEnergy(input []byte) uint64 { 374 return params.Bn256PairingBaseEnergy + uint64(len(input)/192)*params.Bn256PairingPerPointEnergy 375 } 376 377 func (c *bn256Pairing) Run(input []byte) ([]byte, error) { 378 // Handle some corner cases cheaply 379 if len(input)%192 > 0 { 380 return nil, errBadPairingInput 381 } 382 // Convert the input into a set of coordinates 383 var ( 384 cs []*bn256.G1 385 ts []*bn256.G2 386 ) 387 for i := 0; i < len(input); i += 192 { 388 c, err := newCurvePoint(input[i : i+64]) 389 if err != nil { 390 return nil, err 391 } 392 t, err := newTwistPoint(input[i+64 : i+192]) 393 if err != nil { 394 return nil, err 395 } 396 cs = append(cs, c) 397 ts = append(ts, t) 398 } 399 // Execute the pairing checks and return the results 400 if bn256.PairingCheck(cs, ts) { 401 return true32Byte, nil 402 } 403 return false32Byte, nil 404 } 405 406 type blake2F struct{} 407 408 func (c *blake2F) RequiredEnergy(input []byte) uint64 { 409 // If the input is malformed, we can't calculate the energy, return 0 and let the 410 // actual call choke and fault. 411 if len(input) != blake2FInputLength { 412 return 0 413 } 414 return uint64(binary.BigEndian.Uint32(input[0:4])) 415 } 416 417 const ( 418 blake2FInputLength = 213 419 blake2FFinalBlockBytes = byte(1) 420 blake2FNonFinalBlockBytes = byte(0) 421 ) 422 423 var ( 424 errBlake2FInvalidInputLength = errors.New("invalid input length") 425 errBlake2FInvalidFinalFlag = errors.New("invalid final flag") 426 ) 427 428 func (c *blake2F) Run(input []byte) ([]byte, error) { 429 // Make sure the input is valid (correct length and final flag) 430 if len(input) != blake2FInputLength { 431 return nil, errBlake2FInvalidInputLength 432 } 433 if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes { 434 return nil, errBlake2FInvalidFinalFlag 435 } 436 // Parse the input into the Blake2b call parameters 437 var ( 438 rounds = binary.BigEndian.Uint32(input[0:4]) 439 final = (input[212] == blake2FFinalBlockBytes) 440 441 h [8]uint64 442 m [16]uint64 443 t [2]uint64 444 ) 445 for i := 0; i < 8; i++ { 446 offset := 4 + i*8 447 h[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) 448 } 449 for i := 0; i < 16; i++ { 450 offset := 68 + i*8 451 m[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) 452 } 453 t[0] = binary.LittleEndian.Uint64(input[196:204]) 454 t[1] = binary.LittleEndian.Uint64(input[204:212]) 455 456 // Execute the compression function, extract and return the result 457 blake2b.F(&h, m, t, final, rounds) 458 459 output := make([]byte, 64) 460 for i := 0; i < 8; i++ { 461 offset := i * 8 462 binary.LittleEndian.PutUint64(output[offset:offset+8], h[i]) 463 } 464 return output, nil 465 }