aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/contracts.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/contracts.go')
-rw-r--r--core/vm/contracts.go49
1 files changed, 25 insertions, 24 deletions
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index e87640d02..90b2f913e 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -18,6 +18,7 @@ package vm
import (
"crypto/sha256"
+ "errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -27,15 +28,17 @@ import (
"golang.org/x/crypto/ripemd160"
)
+var errBadPrecompileInput = errors.New("bad pre compile input")
+
// Precompiled contract is the basic interface for native Go contracts. The implementation
// requires a deterministic gas count based on the input size of the Run method of the
// contract.
type PrecompiledContract interface {
- RequiredGas(inputSize int) uint64 // RequiredPrice calculates the contract gas use
- Run(input []byte) []byte // Run runs the precompiled contract
+ RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
+ Run(input []byte) ([]byte, error) // Run runs the precompiled contract
}
-// Precompiled contains the default set of ethereum contracts
+// PrecompiledContracts contains the default set of ethereum contracts
var PrecompiledContracts = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{},
@@ -45,11 +48,9 @@ var PrecompiledContracts = map[common.Address]PrecompiledContract{
// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
- gas := p.RequiredGas(len(input))
+ gas := p.RequiredGas(input)
if contract.UseGas(gas) {
- ret = p.Run(input)
-
- return ret, nil
+ return p.Run(input)
} else {
return nil, ErrOutOfGas
}
@@ -58,11 +59,11 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr
// ECRECOVER implemented as a native contract
type ecrecover struct{}
-func (c *ecrecover) RequiredGas(inputSize int) uint64 {
+func (c *ecrecover) RequiredGas(input []byte) uint64 {
return params.EcrecoverGas
}
-func (c *ecrecover) Run(in []byte) []byte {
+func (c *ecrecover) Run(in []byte) ([]byte, error) {
const ecRecoverInputLength = 128
in = common.RightPadBytes(in, ecRecoverInputLength)
@@ -76,18 +77,18 @@ func (c *ecrecover) Run(in []byte) []byte {
// tighter sig s values in homestead only apply to tx sigs
if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
log.Trace("ECRECOVER error: v, r or s value invalid")
- return nil
+ return nil, nil
}
// v needs to be at the end for libsecp256k1
pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v))
// make sure the public key is a valid one
if err != nil {
log.Trace("ECRECOVER failed", "err", err)
- return nil
+ return nil, nil
}
// the first byte of pubkey is bitcoin heritage
- return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32)
+ return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
}
// SHA256 implemented as a native contract
@@ -97,12 +98,12 @@ type sha256hash struct{}
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
-func (c *sha256hash) RequiredGas(inputSize int) uint64 {
- return uint64(inputSize+31)/32*params.Sha256WordGas + params.Sha256Gas
+func (c *sha256hash) RequiredGas(input []byte) uint64 {
+ return uint64(len(input)+31)/32*params.Sha256WordGas + params.Sha256Gas
}
-func (c *sha256hash) Run(in []byte) []byte {
+func (c *sha256hash) Run(in []byte) ([]byte, error) {
h := sha256.Sum256(in)
- return h[:]
+ return h[:], nil
}
// RIPMED160 implemented as a native contract
@@ -112,13 +113,13 @@ type ripemd160hash struct{}
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
-func (c *ripemd160hash) RequiredGas(inputSize int) uint64 {
- return uint64(inputSize+31)/32*params.Ripemd160WordGas + params.Ripemd160Gas
+func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
+ return uint64(len(input)+31)/32*params.Ripemd160WordGas + params.Ripemd160Gas
}
-func (c *ripemd160hash) Run(in []byte) []byte {
+func (c *ripemd160hash) Run(in []byte) ([]byte, error) {
ripemd := ripemd160.New()
ripemd.Write(in)
- return common.LeftPadBytes(ripemd.Sum(nil), 32)
+ return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
}
// data copy implemented as a native contract
@@ -128,9 +129,9 @@ type dataCopy struct{}
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
-func (c *dataCopy) RequiredGas(inputSize int) uint64 {
- return uint64(inputSize+31)/32*params.IdentityWordGas + params.IdentityGas
+func (c *dataCopy) RequiredGas(input []byte) uint64 {
+ return uint64(len(input)+31)/32*params.IdentityWordGas + params.IdentityGas
}
-func (c *dataCopy) Run(in []byte) []byte {
- return in
+func (c *dataCopy) Run(in []byte) ([]byte, error) {
+ return in, nil
}