Skip to content
This repository has been archived by the owner on Aug 13, 2019. It is now read-only.

Commit

Permalink
Added error handling for precompiles and removed skipped tests (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
austinabell authored and noot committed Jun 12, 2019
1 parent 6299b56 commit 6c6454e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 38 deletions.
61 changes: 31 additions & 30 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package vm

import (
"errors"
"math/big"

"github.com/eth-classic/go-ethereum/common"
Expand Down Expand Up @@ -59,11 +60,11 @@ const (
// PrecompiledAccount represents a native ethereum contract
type PrecompiledAccount struct {
Gas func(in []byte) *big.Int
fn func(in []byte) []byte
fn func(in []byte) ([]byte, error)
}

// Call calls the native function
func (self PrecompiledAccount) Call(in []byte) []byte {
func (self PrecompiledAccount) Call(in []byte) ([]byte, error) {
return self.fn(in)
}

Expand Down Expand Up @@ -201,15 +202,15 @@ func PrecompiledContractsAtlantis() map[string]*PrecompiledAccount {
}
}

func sha256Func(in []byte) []byte {
return crypto.Sha256(in)
func sha256Func(in []byte) ([]byte, error) {
return crypto.Sha256(in), nil
}

func ripemd160Func(in []byte) []byte {
return common.LeftPadBytes(crypto.Ripemd160(in), 32)
func ripemd160Func(in []byte) ([]byte, error) {
return common.LeftPadBytes(crypto.Ripemd160(in), 32), nil
}

func ecrecoverFunc(in []byte) []byte {
func ecrecoverFunc(in []byte) ([]byte, error) {
in = common.RightPadBytes(in, 128)
// "in" is (hash, v, r, s), each 32 bytes
// but for ecrecover we want (r, s, v)
Expand All @@ -223,7 +224,7 @@ func ecrecoverFunc(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) {
glog.V(logger.Detail).Infof("ECRECOVER error: v, r or s value invalid")
return nil
return nil, nil
}

// v needs to be at the end and normalized for libsecp256k1
Expand All @@ -234,18 +235,18 @@ func ecrecoverFunc(in []byte) []byte {
// make sure the public key is a valid one
if err != nil {
glog.V(logger.Detail).Infoln("ECRECOVER error: ", 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
}

func memCpy(in []byte) []byte {
return in
func memCpy(in []byte) ([]byte, error) {
return in, nil
}

func bigModExp(in []byte) []byte {
func bigModExp(in []byte) ([]byte, error) {
var (
baseLen = new(big.Int).SetBytes(getData(in, big0, big32))
expLen = new(big.Int).SetBytes(getData(in, big32, big32))
Expand All @@ -260,7 +261,7 @@ func bigModExp(in []byte) []byte {

// Handle a special case when both the base and mod length is zero
if baseLen.Cmp(big0) == 0 && modLen.Cmp(big0) == 0 {
return []byte{}
return []byte{}, nil
}
// Retrieve the operands and execute the exponentiation
var (
Expand All @@ -270,9 +271,9 @@ func bigModExp(in []byte) []byte {
)
if mod.BitLen() == 0 {
// Modulo 0 is undefined, return zero
return common.LeftPadBytes([]byte{}, int(modLen.Int64()))
return common.LeftPadBytes([]byte{}, int(modLen.Int64())), nil
}
return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen.Int64()))
return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen.Int64())), nil
}

var (
Expand All @@ -283,7 +284,7 @@ var (
false32Byte = make([]byte, 32)

// errBadPairingInput is returned if the bn256 pairing input is invalid.
//errBadPairingInput = errors.New("bad elliptic curve pairing size")
errBadPairingInput = errors.New("bad elliptic curve pairing size")
)

// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
Expand All @@ -306,34 +307,34 @@ func newTwistPoint(blob []byte) (*bn256.G2, error) {
return p, nil
}

func bn256Add(in []byte) []byte {
func bn256Add(in []byte) ([]byte, error) {
x, err := newCurvePoint(getData(in, big.NewInt(0), big.NewInt(64)))
if err != nil {
return nil
return nil, err
}
y, err := newCurvePoint(getData(in, big.NewInt(64), big.NewInt(64)))
if err != nil {
return nil
return nil, err
}
res := new(bn256.G1)
res.Add(x, y)
return res.Marshal()
return res.Marshal(), nil
}

func bn256ScalarMul(in []byte) []byte {
func bn256ScalarMul(in []byte) ([]byte, error) {
p, err := newCurvePoint(getData(in, big.NewInt(0), big.NewInt(64)))
if err != nil {
return nil
return nil, err
}
res := new(bn256.G1)
res.ScalarMult(p, new(big.Int).SetBytes(getData(in, big.NewInt(64), big.NewInt(32))))
return res.Marshal()
return res.Marshal(), nil
}

func bn256Pairing(in []byte) []byte {
func bn256Pairing(in []byte) ([]byte, error) {
// Handle some corner cases cheaply
if len(in)%192 > 0 {
return nil
return nil, errBadPairingInput
}
// Convert the input into a set of coordinates
var (
Expand All @@ -343,18 +344,18 @@ func bn256Pairing(in []byte) []byte {
for i := 0; i < len(in); i += 192 {
c, err := newCurvePoint(in[i : i+64])
if err != nil {
return nil
return nil, err
}
t, err := newTwistPoint(in[i+64 : i+192])
if err != nil {
return nil
return nil, err
}
cs = append(cs, c)
ts = append(ts, t)
}
// Execute the pairing checks and return the results
if bn256.PairingCheck(cs, ts) {
return true32Byte
return true32Byte, nil
}
return false32Byte
return false32Byte, nil
}
4 changes: 1 addition & 3 deletions core/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,7 @@ func calculateGasAndSize(gasTable *GasTable, env Environment, contract *Contract
func (evm *EVM) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Contract) (ret []byte, err error) {
gas := p.Gas(input)
if contract.UseGas(gas) {
ret = p.Call(input)

return ret, nil
return p.Call(input)
} else {
return nil, OutOfGasError
}
Expand Down
6 changes: 1 addition & 5 deletions tests/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,8 +698,7 @@ func TestAllETH(t *testing.T) {
skipTests["createJS_ExampleContract.json"] = "Not Implemented"
skipTests["RevertDepthCreateAddressCollision.json"] = "Not Implemented"

// Random Test failures (REVISIT)
skipTests["randomStatetest642.json"] = "random unimplemented"
// Random Test failures
skipTests["randomStatetest644.json"] = "random unimplemented"
skipTests["randomStatetest645.json"] = "random unimplemented"

Expand All @@ -708,11 +707,8 @@ func TestAllETH(t *testing.T) {
skipTests["FailedCreateRevertsDeletion.json"] = "State trie clearing unimplemented"

unsupportedDirs := map[string]bool{
"stStaticCall": true,
"stZeroKnowledge": true,
"stZeroKnowledge2": true,
"stReturnDataTest": true,
"stCodeSizeLimit": true,
"stCreate2": true,
}

Expand Down

0 comments on commit 6c6454e

Please sign in to comment.