github.com/bamzi/go-ethereum@v1.6.7-0.20170704111104-138f26c93af1/core/vm/contracts.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"crypto/sha256"
    21  	"errors"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/ethereum/go-ethereum/log"
    27  	"github.com/ethereum/go-ethereum/params"
    28  	"golang.org/x/crypto/ripemd160"
    29  )
    30  
    31  var errBadPrecompileInput = errors.New("bad pre compile input")
    32  
    33  // Precompiled contract is the basic interface for native Go contracts. The implementation
    34  // requires a deterministic gas count based on the input size of the Run method of the
    35  // contract.
    36  type PrecompiledContract interface {
    37  	RequiredGas(input []byte) uint64  // RequiredPrice calculates the contract gas use
    38  	Run(input []byte) ([]byte, error) // Run runs the precompiled contract
    39  }
    40  
    41  // PrecompiledContracts contains the default set of ethereum contracts
    42  var PrecompiledContracts = map[common.Address]PrecompiledContract{
    43  	common.BytesToAddress([]byte{1}): &ecrecover{},
    44  	common.BytesToAddress([]byte{2}): &sha256hash{},
    45  	common.BytesToAddress([]byte{3}): &ripemd160hash{},
    46  	common.BytesToAddress([]byte{4}): &dataCopy{},
    47  }
    48  
    49  // RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
    50  func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
    51  	gas := p.RequiredGas(input)
    52  	if contract.UseGas(gas) {
    53  		return p.Run(input)
    54  	} else {
    55  		return nil, ErrOutOfGas
    56  	}
    57  }
    58  
    59  // ECRECOVER implemented as a native contract
    60  type ecrecover struct{}
    61  
    62  func (c *ecrecover) RequiredGas(input []byte) uint64 {
    63  	return params.EcrecoverGas
    64  }
    65  
    66  func (c *ecrecover) Run(in []byte) ([]byte, error) {
    67  	const ecRecoverInputLength = 128
    68  
    69  	in = common.RightPadBytes(in, ecRecoverInputLength)
    70  	// "in" is (hash, v, r, s), each 32 bytes
    71  	// but for ecrecover we want (r, s, v)
    72  
    73  	r := new(big.Int).SetBytes(in[64:96])
    74  	s := new(big.Int).SetBytes(in[96:128])
    75  	v := in[63] - 27
    76  
    77  	// tighter sig s values in homestead only apply to tx sigs
    78  	if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
    79  		log.Trace("ECRECOVER error: v, r or s value invalid")
    80  		return nil, nil
    81  	}
    82  	// v needs to be at the end for libsecp256k1
    83  	pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v))
    84  	// make sure the public key is a valid one
    85  	if err != nil {
    86  		log.Trace("ECRECOVER failed", "err", err)
    87  		return nil, nil
    88  	}
    89  
    90  	// the first byte of pubkey is bitcoin heritage
    91  	return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
    92  }
    93  
    94  // SHA256 implemented as a native contract
    95  type sha256hash struct{}
    96  
    97  // RequiredGas returns the gas required to execute the pre-compiled contract.
    98  //
    99  // This method does not require any overflow checking as the input size gas costs
   100  // required for anything significant is so high it's impossible to pay for.
   101  func (c *sha256hash) RequiredGas(input []byte) uint64 {
   102  	return uint64(len(input)+31)/32*params.Sha256WordGas + params.Sha256Gas
   103  }
   104  func (c *sha256hash) Run(in []byte) ([]byte, error) {
   105  	h := sha256.Sum256(in)
   106  	return h[:], nil
   107  }
   108  
   109  // RIPMED160 implemented as a native contract
   110  type ripemd160hash struct{}
   111  
   112  // RequiredGas returns the gas required to execute the pre-compiled contract.
   113  //
   114  // This method does not require any overflow checking as the input size gas costs
   115  // required for anything significant is so high it's impossible to pay for.
   116  func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
   117  	return uint64(len(input)+31)/32*params.Ripemd160WordGas + params.Ripemd160Gas
   118  }
   119  func (c *ripemd160hash) Run(in []byte) ([]byte, error) {
   120  	ripemd := ripemd160.New()
   121  	ripemd.Write(in)
   122  	return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
   123  }
   124  
   125  // data copy implemented as a native contract
   126  type dataCopy struct{}
   127  
   128  // RequiredGas returns the gas required to execute the pre-compiled contract.
   129  //
   130  // This method does not require any overflow checking as the input size gas costs
   131  // required for anything significant is so high it's impossible to pay for.
   132  func (c *dataCopy) RequiredGas(input []byte) uint64 {
   133  	return uint64(len(input)+31)/32*params.IdentityWordGas + params.IdentityGas
   134  }
   135  func (c *dataCopy) Run(in []byte) ([]byte, error) {
   136  	return in, nil
   137  }