Przeglądaj źródła

Merge pull request #14959 from karalabe/metropolis-precompiles

core/vm: metropolis precompiles
Péter Szilágyi 8 lat temu
rodzic
commit
9facf6423d

+ 15 - 1
core/vm/common.go

@@ -34,7 +34,21 @@ func calcMemSize(off, l *big.Int) *big.Int {
 
 // getData returns a slice from the data based on the start and size and pads
 // up to size with zero's. This function is overflow safe.
-func getData(data []byte, start, size *big.Int) []byte {
+func getData(data []byte, start uint64, size uint64) []byte {
+	length := uint64(len(data))
+	if start > length {
+		start = length
+	}
+	end := start + size
+	if end > length {
+		end = length
+	}
+	return common.RightPadBytes(data[start:end], int(size))
+}
+
+// getDataBig returns a slice from the data based on the start and size and pads
+// up to size with zero's. This function is overflow safe.
+func getDataBig(data []byte, start *big.Int, size *big.Int) []byte {
 	dlen := big.NewInt(int64(len(data)))
 
 	s := math.BigMin(start, dlen)

+ 272 - 28
core/vm/contracts.go

@@ -22,14 +22,14 @@ import (
 	"math/big"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/math"
 	"github.com/ethereum/go-ethereum/crypto"
+	"github.com/ethereum/go-ethereum/crypto/bn256"
 	"github.com/ethereum/go-ethereum/params"
 	"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
+// PrecompiledContract 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 {
@@ -37,48 +37,61 @@ type PrecompiledContract interface {
 	Run(input []byte) ([]byte, error) // Run runs the precompiled contract
 }
 
-// PrecompiledContracts contains the default set of ethereum contracts
-var PrecompiledContracts = map[common.Address]PrecompiledContract{
+// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
+// contracts used in the Frontier and Homestead releases.
+var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
 	common.BytesToAddress([]byte{1}): &ecrecover{},
 	common.BytesToAddress([]byte{2}): &sha256hash{},
 	common.BytesToAddress([]byte{3}): &ripemd160hash{},
 	common.BytesToAddress([]byte{4}): &dataCopy{},
 }
 
-// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
+// PrecompiledContractsMetropolis contains the default set of pre-compiled Ethereum
+// contracts used in the Metropolis release.
+var PrecompiledContractsMetropolis = map[common.Address]PrecompiledContract{
+	common.BytesToAddress([]byte{1}): &ecrecover{},
+	common.BytesToAddress([]byte{2}): &sha256hash{},
+	common.BytesToAddress([]byte{3}): &ripemd160hash{},
+	common.BytesToAddress([]byte{4}): &dataCopy{},
+	common.BytesToAddress([]byte{5}): &bigModExp{},
+	common.BytesToAddress([]byte{6}): &bn256Add{},
+	common.BytesToAddress([]byte{7}): &bn256ScalarMul{},
+	common.BytesToAddress([]byte{8}): &bn256Pairing{},
+}
+
+// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
 func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
 	gas := p.RequiredGas(input)
 	if contract.UseGas(gas) {
 		return p.Run(input)
-	} else {
-		return nil, ErrOutOfGas
 	}
+	return nil, ErrOutOfGas
 }
 
-// ECRECOVER implemented as a native contract
+// ECRECOVER implemented as a native contract.
 type ecrecover struct{}
 
 func (c *ecrecover) RequiredGas(input []byte) uint64 {
 	return params.EcrecoverGas
 }
 
-func (c *ecrecover) Run(in []byte) ([]byte, error) {
+func (c *ecrecover) Run(input []byte) ([]byte, error) {
 	const ecRecoverInputLength = 128
 
-	in = common.RightPadBytes(in, ecRecoverInputLength)
-	// "in" is (hash, v, r, s), each 32 bytes
+	input = common.RightPadBytes(input, ecRecoverInputLength)
+	// "input" is (hash, v, r, s), each 32 bytes
 	// but for ecrecover we want (r, s, v)
 
-	r := new(big.Int).SetBytes(in[64:96])
-	s := new(big.Int).SetBytes(in[96:128])
-	v := in[63] - 27
+	r := new(big.Int).SetBytes(input[64:96])
+	s := new(big.Int).SetBytes(input[96:128])
+	v := input[63] - 27
 
-	// tighter sig s values in homestead only apply to tx sigs
-	if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
+	// tighter sig s values input homestead only apply to tx sigs
+	if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
 		return nil, nil
 	}
 	// v needs to be at the end for libsecp256k1
-	pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v))
+	pubKey, err := crypto.Ecrecover(input[:32], append(input[64:128], v))
 	// make sure the public key is a valid one
 	if err != nil {
 		return nil, nil
@@ -88,7 +101,7 @@ func (c *ecrecover) Run(in []byte) ([]byte, error) {
 	return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
 }
 
-// SHA256 implemented as a native contract
+// SHA256 implemented as a native contract.
 type sha256hash struct{}
 
 // RequiredGas returns the gas required to execute the pre-compiled contract.
@@ -96,14 +109,14 @@ 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(input []byte) uint64 {
-	return uint64(len(input)+31)/32*params.Sha256WordGas + params.Sha256Gas
+	return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
 }
-func (c *sha256hash) Run(in []byte) ([]byte, error) {
-	h := sha256.Sum256(in)
+func (c *sha256hash) Run(input []byte) ([]byte, error) {
+	h := sha256.Sum256(input)
 	return h[:], nil
 }
 
-// RIPMED160 implemented as a native contract
+// RIPMED160 implemented as a native contract.
 type ripemd160hash struct{}
 
 // RequiredGas returns the gas required to execute the pre-compiled contract.
@@ -111,15 +124,15 @@ 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(input []byte) uint64 {
-	return uint64(len(input)+31)/32*params.Ripemd160WordGas + params.Ripemd160Gas
+	return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
 }
-func (c *ripemd160hash) Run(in []byte) ([]byte, error) {
+func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
 	ripemd := ripemd160.New()
-	ripemd.Write(in)
+	ripemd.Write(input)
 	return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
 }
 
-// data copy implemented as a native contract
+// data copy implemented as a native contract.
 type dataCopy struct{}
 
 // RequiredGas returns the gas required to execute the pre-compiled contract.
@@ -127,8 +140,239 @@ 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(input []byte) uint64 {
-	return uint64(len(input)+31)/32*params.IdentityWordGas + params.IdentityGas
+	return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
 }
 func (c *dataCopy) Run(in []byte) ([]byte, error) {
 	return in, nil
 }
+
+// bigModExp implements a native big integer exponential modular operation.
+type bigModExp struct{}
+
+var (
+	big1      = big.NewInt(1)
+	big4      = big.NewInt(4)
+	big8      = big.NewInt(8)
+	big16     = big.NewInt(16)
+	big32     = big.NewInt(32)
+	big64     = big.NewInt(64)
+	big96     = big.NewInt(96)
+	big480    = big.NewInt(480)
+	big1024   = big.NewInt(1024)
+	big3072   = big.NewInt(3072)
+	big199680 = big.NewInt(199680)
+)
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bigModExp) RequiredGas(input []byte) uint64 {
+	var (
+		baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
+		expLen  = new(big.Int).SetBytes(getData(input, 32, 32))
+		modLen  = new(big.Int).SetBytes(getData(input, 64, 32))
+	)
+	if len(input) > 96 {
+		input = input[96:]
+	} else {
+		input = input[:0]
+	}
+	// Retrieve the head 32 bytes of exp for the adjusted exponent length
+	var expHead *big.Int
+	if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
+		expHead = new(big.Int)
+	} else {
+		if expLen.Cmp(big32) > 0 {
+			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
+		} else {
+			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
+		}
+	}
+	// Calculate the adjusted exponent length
+	var msb int
+	if bitlen := expHead.BitLen(); bitlen > 0 {
+		msb = bitlen - 1
+	}
+	adjExpLen := new(big.Int)
+	if expLen.Cmp(big32) > 0 {
+		adjExpLen.Sub(expLen, big32)
+		adjExpLen.Mul(big8, adjExpLen)
+	}
+	adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
+
+	// Calculate the gas cost of the operation
+	gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
+	switch {
+	case gas.Cmp(big64) <= 0:
+		gas.Mul(gas, gas)
+	case gas.Cmp(big1024) <= 0:
+		gas = new(big.Int).Add(
+			new(big.Int).Div(new(big.Int).Mul(gas, gas), big4),
+			new(big.Int).Sub(new(big.Int).Mul(big96, gas), big3072),
+		)
+	default:
+		gas = new(big.Int).Add(
+			new(big.Int).Div(new(big.Int).Mul(gas, gas), big16),
+			new(big.Int).Sub(new(big.Int).Mul(big480, gas), big199680),
+		)
+	}
+	gas.Mul(gas, math.BigMax(adjExpLen, big1))
+	gas.Div(gas, new(big.Int).SetUint64(params.ModExpQuadCoeffDiv))
+
+	if gas.BitLen() > 64 {
+		return math.MaxUint64
+	}
+	return gas.Uint64()
+}
+
+func (c *bigModExp) Run(input []byte) ([]byte, error) {
+	var (
+		baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
+		expLen  = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
+		modLen  = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64()
+	)
+	if len(input) > 96 {
+		input = input[96:]
+	} else {
+		input = input[:0]
+	}
+	// Handle a special case when both the base and mod length is zero
+	if baseLen == 0 && modLen == 0 {
+		return []byte{}, nil
+	}
+	// Retrieve the operands and execute the exponentiation
+	var (
+		base = new(big.Int).SetBytes(getData(input, 0, baseLen))
+		exp  = new(big.Int).SetBytes(getData(input, baseLen, expLen))
+		mod  = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
+	)
+	if mod.BitLen() == 0 {
+		// Modulo 0 is undefined, return zero
+		return common.LeftPadBytes([]byte{}, int(modLen)), nil
+	}
+	return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil
+}
+
+var (
+	// errNotOnCurve is returned if a point being unmarshalled as a bn256 elliptic
+	// curve point is not on the curve.
+	errNotOnCurve = errors.New("point not on elliptic curve")
+
+	// errInvalidCurvePoint is returned if a point being unmarshalled as a bn256
+	// elliptic curve point is invalid.
+	errInvalidCurvePoint = errors.New("invalid elliptic curve point")
+)
+
+// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
+// returning it, or an error if the point is invalid.
+func newCurvePoint(blob []byte) (*bn256.G1, error) {
+	p, onCurve := new(bn256.G1).Unmarshal(blob)
+	if !onCurve {
+		return nil, errNotOnCurve
+	}
+	gx, gy, _, _ := p.CurvePoints()
+	if gx.Cmp(bn256.P) >= 0 || gy.Cmp(bn256.P) >= 0 {
+		return nil, errInvalidCurvePoint
+	}
+	return p, nil
+}
+
+// newTwistPoint unmarshals a binary blob into a bn256 elliptic curve point,
+// returning it, or an error if the point is invalid.
+func newTwistPoint(blob []byte) (*bn256.G2, error) {
+	p, onCurve := new(bn256.G2).Unmarshal(blob)
+	if !onCurve {
+		return nil, errNotOnCurve
+	}
+	x2, y2, _, _ := p.CurvePoints()
+	if x2.Real().Cmp(bn256.P) >= 0 || x2.Imag().Cmp(bn256.P) >= 0 ||
+		y2.Real().Cmp(bn256.P) >= 0 || y2.Imag().Cmp(bn256.P) >= 0 {
+		return nil, errInvalidCurvePoint
+	}
+	return p, nil
+}
+
+// bn256Add implements a native elliptic curve point addition.
+type bn256Add struct{}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256Add) RequiredGas(input []byte) uint64 {
+	return params.Bn256AddGas
+}
+
+func (c *bn256Add) Run(input []byte) ([]byte, error) {
+	x, err := newCurvePoint(getData(input, 0, 64))
+	if err != nil {
+		return nil, err
+	}
+	y, err := newCurvePoint(getData(input, 64, 64))
+	if err != nil {
+		return nil, err
+	}
+	x.Add(x, y)
+	return x.Marshal(), nil
+}
+
+// bn256ScalarMul implements a native elliptic curve scalar multiplication.
+type bn256ScalarMul struct{}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
+	return params.Bn256ScalarMulGas
+}
+
+func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
+	p, err := newCurvePoint(getData(input, 0, 64))
+	if err != nil {
+		return nil, err
+	}
+	p.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32)))
+	return p.Marshal(), nil
+}
+
+var (
+	// true32Byte is returned if the bn256 pairing check succeeds.
+	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}
+
+	// false32Byte is returned if the bn256 pairing check fails.
+	false32Byte = make([]byte, 32)
+
+	// errBadPairingInput is returned if the bn256 pairing input is invalid.
+	errBadPairingInput = errors.New("bad elliptic curve pairing size")
+)
+
+// bn256Pairing implements a pairing pre-compile for the bn256 curve
+type bn256Pairing struct{}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256Pairing) RequiredGas(input []byte) uint64 {
+	return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas
+}
+
+func (c *bn256Pairing) Run(input []byte) ([]byte, error) {
+	// Handle some corner cases cheaply
+	if len(input)%192 > 0 {
+		return nil, errBadPairingInput
+	}
+	// Convert the input into a set of coordinates
+	var (
+		cs []*bn256.G1
+		ts []*bn256.G2
+	)
+	for i := 0; i < len(input); i += 192 {
+		c, err := newCurvePoint(input[i : i+64])
+		if err != nil {
+			return nil, err
+		}
+		t, err := newTwistPoint(input[i+64 : i+192])
+		if err != nil {
+			return nil, err
+		}
+		cs = append(cs, c)
+		ts = append(ts, t)
+	}
+	// Execute the pairing checks and return the results
+	ok := bn256.PairingCheck(cs, ts)
+	if ok {
+		return true32Byte, nil
+	}
+	return false32Byte, nil
+}

Plik diff jest za duży
+ 72 - 0
core/vm/contracts_test.go


+ 12 - 7
core/vm/evm.go

@@ -36,12 +36,14 @@ type (
 // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
 func run(evm *EVM, snapshot int, contract *Contract, input []byte) ([]byte, error) {
 	if contract.CodeAddr != nil {
-		precompiledContracts := PrecompiledContracts
-		if p := precompiledContracts[*contract.CodeAddr]; p != nil {
+		precompiles := PrecompiledContractsHomestead
+		if evm.ChainConfig().IsMetropolis(evm.BlockNumber) {
+			precompiles = PrecompiledContractsMetropolis
+		}
+		if p := precompiles[*contract.CodeAddr]; p != nil {
 			return RunPrecompiledContract(p, input, contract)
 		}
 	}
-
 	return evm.interpreter.Run(snapshot, contract, input)
 }
 
@@ -100,8 +102,8 @@ type EVM struct {
 	abort int32
 }
 
-// NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe
-// and should only ever be used *once*.
+// NewEVM retutrns a new EVM . The returned EVM is not thread safe and should
+// only ever be used *once*.
 func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
 	evm := &EVM{
 		Context:     ctx,
@@ -143,10 +145,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 		snapshot = evm.StateDB.Snapshot()
 	)
 	if !evm.StateDB.Exist(addr) {
-		if PrecompiledContracts[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
+		precompiles := PrecompiledContractsHomestead
+		if evm.ChainConfig().IsMetropolis(evm.BlockNumber) {
+			precompiles = PrecompiledContractsMetropolis
+		}
+		if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
 			return nil, gas, nil
 		}
-
 		evm.StateDB.CreateAccount(addr)
 	}
 	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)

+ 4 - 4
core/vm/instructions.go

@@ -337,7 +337,7 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
 }
 
 func opCalldataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
-	stack.push(new(big.Int).SetBytes(getData(contract.Input, stack.pop(), common.Big32)))
+	stack.push(new(big.Int).SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
 	return nil, nil
 }
 
@@ -352,7 +352,7 @@ func opCalldataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
 		cOff = stack.pop()
 		l    = stack.pop()
 	)
-	memory.Set(mOff.Uint64(), l.Uint64(), getData(contract.Input, cOff, l))
+	memory.Set(mOff.Uint64(), l.Uint64(), getDataBig(contract.Input, cOff, l))
 
 	evm.interpreter.intPool.put(mOff, cOff, l)
 	return nil, nil
@@ -380,7 +380,7 @@ func opCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
 		cOff = stack.pop()
 		l    = stack.pop()
 	)
-	codeCopy := getData(contract.Code, cOff, l)
+	codeCopy := getDataBig(contract.Code, cOff, l)
 
 	memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
 
@@ -395,7 +395,7 @@ func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta
 		cOff = stack.pop()
 		l    = stack.pop()
 	)
-	codeCopy := getData(evm.StateDB.GetCode(addr), cOff, l)
+	codeCopy := getDataBig(evm.StateDB.GetCode(addr), cOff, l)
 
 	memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
 

+ 60 - 99
core/vm/instructions_test.go

@@ -1,7 +1,6 @@
 package vm
 
 import (
-	"fmt"
 	"math/big"
 	"testing"
 
@@ -64,197 +63,169 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contr
 	}
 }
 
-func precompiledBenchmark(addr, input, expected string, gas uint64, bench *testing.B) {
+func BenchmarkOpAdd64(b *testing.B) {
+	x := "ffffffff"
+	y := "fd37f3e2bba2c4f"
 
-	contract := NewContract(AccountRef(common.HexToAddress("1337")),
-		nil, new(big.Int), gas)
-
-	p := PrecompiledContracts[common.HexToAddress(addr)]
-	in := common.Hex2Bytes(input)
-	var (
-		res []byte
-		err error
-	)
-	data := make([]byte, len(in))
-	bench.ResetTimer()
-	for i := 0; i < bench.N; i++ {
-		contract.Gas = gas
-		copy(data, in)
-		res, err = RunPrecompiledContract(p, data, contract)
-	}
-	bench.StopTimer()
-	//Check if it is correct
-	if err != nil {
-		bench.Error(err)
-		return
-	}
-	if common.Bytes2Hex(res) != expected {
-		bench.Error(fmt.Sprintf("Expected %v, got %v", expected, common.Bytes2Hex(res)))
-		return
-	}
+	opBenchmark(b, opAdd, x, y)
 }
 
-func BenchmarkPrecompiledEcdsa(bench *testing.B) {
-	var (
-		addr = "01"
-		inp  = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02"
-		exp  = "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d"
-		gas  = uint64(4000000)
-	)
-	precompiledBenchmark(addr, inp, exp, gas, bench)
-}
-func BenchmarkPrecompiledSha256(bench *testing.B) {
-	var (
-		addr = "02"
-		inp  = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02"
-		exp  = "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d"
-		gas  = uint64(4000000)
-	)
-	precompiledBenchmark(addr, inp, exp, gas, bench)
-}
-func BenchmarkPrecompiledRipeMD(bench *testing.B) {
-	var (
-		addr = "03"
-		inp  = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02"
-		exp  = "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6"
-		gas  = uint64(4000000)
-	)
-	precompiledBenchmark(addr, inp, exp, gas, bench)
-}
-func BenchmarkPrecompiledIdentity(bench *testing.B) {
-	var (
-		addr = "04"
-		inp  = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02"
-		exp  = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02"
-		gas  = uint64(4000000)
-	)
-	precompiledBenchmark(addr, inp, exp, gas, bench)
+func BenchmarkOpAdd128(b *testing.B) {
+	x := "ffffffffffffffff"
+	y := "f5470b43c6549b016288e9a65629687"
+
+	opBenchmark(b, opAdd, x, y)
 }
-func BenchmarkOpAdd(b *testing.B) {
-	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
-	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
+
+func BenchmarkOpAdd256(b *testing.B) {
+	x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
+	y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
 
 	opBenchmark(b, opAdd, x, y)
+}
+
+func BenchmarkOpSub64(b *testing.B) {
+	x := "51022b6317003a9d"
+	y := "a20456c62e00753a"
 
+	opBenchmark(b, opSub, x, y)
 }
-func BenchmarkOpSub(b *testing.B) {
-	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
-	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
+
+func BenchmarkOpSub128(b *testing.B) {
+	x := "4dde30faaacdc14d00327aac314e915d"
+	y := "9bbc61f5559b829a0064f558629d22ba"
 
 	opBenchmark(b, opSub, x, y)
+}
 
+func BenchmarkOpSub256(b *testing.B) {
+	x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
+	y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
+
+	opBenchmark(b, opSub, x, y)
 }
+
 func BenchmarkOpMul(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opMul, x, y)
+}
 
+func BenchmarkOpDiv256(b *testing.B) {
+	x := "ff3f9014f20db29ae04af2c2d265de17"
+	y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
+	opBenchmark(b, opDiv, x, y)
 }
-func BenchmarkOpDiv(b *testing.B) {
-	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
-	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
+func BenchmarkOpDiv128(b *testing.B) {
+	x := "fdedc7f10142ff97"
+	y := "fbdfda0e2ce356173d1993d5f70a2b11"
 	opBenchmark(b, opDiv, x, y)
+}
 
+func BenchmarkOpDiv64(b *testing.B) {
+	x := "fcb34eb3"
+	y := "f97180878e839129"
+	opBenchmark(b, opDiv, x, y)
 }
+
 func BenchmarkOpSdiv(b *testing.B) {
-	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
-	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
+	x := "ff3f9014f20db29ae04af2c2d265de17"
+	y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
 
 	opBenchmark(b, opSdiv, x, y)
-
 }
+
 func BenchmarkOpMod(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opMod, x, y)
-
 }
+
 func BenchmarkOpSmod(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opSmod, x, y)
-
 }
+
 func BenchmarkOpExp(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opExp, x, y)
-
 }
+
 func BenchmarkOpSignExtend(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opSignExtend, x, y)
-
 }
+
 func BenchmarkOpLt(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opLt, x, y)
-
 }
+
 func BenchmarkOpGt(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opGt, x, y)
-
 }
+
 func BenchmarkOpSlt(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opSlt, x, y)
-
 }
+
 func BenchmarkOpSgt(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opSgt, x, y)
-
 }
+
 func BenchmarkOpEq(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opEq, x, y)
-
 }
+
 func BenchmarkOpAnd(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opAnd, x, y)
-
 }
+
 func BenchmarkOpOr(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opOr, x, y)
-
 }
+
 func BenchmarkOpXor(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opXor, x, y)
-
 }
+
 func BenchmarkOpByte(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opByte, x, y)
-
 }
 
 func BenchmarkOpAddmod(b *testing.B) {
@@ -263,22 +234,12 @@ func BenchmarkOpAddmod(b *testing.B) {
 	z := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opAddmod, x, y, z)
-
 }
+
 func BenchmarkOpMulmod(b *testing.B) {
 	x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 	z := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
 
 	opBenchmark(b, opMulmod, x, y, z)
-
 }
-
-//func BenchmarkOpSha3(b *testing.B) {
-//	x := "0"
-//	y := "32"
-//
-//	opBenchmark(b,opSha3, x, y)
-//
-//
-//}

+ 16 - 8
params/protocol_params.go

@@ -31,23 +31,16 @@ const (
 	SstoreSetGas          uint64 = 20000 // Once per SLOAD operation.
 	LogDataGas            uint64 = 8     // Per byte in a LOG* operation's data.
 	CallStipend           uint64 = 2300  // Free gas given at beginning of call.
-	EcrecoverGas          uint64 = 3000  //
-	Sha256WordGas         uint64 = 12    //
 
 	Sha3Gas          uint64 = 30    // Once per SHA3 operation.
-	Sha256Gas        uint64 = 60    //
-	IdentityWordGas  uint64 = 3     //
 	Sha3WordGas      uint64 = 6     // Once per word of the SHA3 operation's data.
 	SstoreResetGas   uint64 = 5000  // Once per SSTORE operation if the zeroness changes from zero.
 	SstoreClearGas   uint64 = 5000  // Once per SSTORE operation if the zeroness doesn't change.
 	SstoreRefundGas  uint64 = 15000 // Once per SSTORE operation if the zeroness changes to zero.
 	JumpdestGas      uint64 = 1     // Refunded gas, once per SSTORE operation if the zeroness changes to zero.
-	IdentityGas      uint64 = 15    //
 	EpochDuration    uint64 = 30000 // Duration between proof-of-work epochs.
 	CallGas          uint64 = 40    // Once per CALL operation & message call transaction.
 	CreateDataGas    uint64 = 200   //
-	Ripemd160Gas     uint64 = 600   //
-	Ripemd160WordGas uint64 = 120   //
 	CallCreateDepth  uint64 = 1024  // Maximum depth of call/create stack.
 	ExpGas           uint64 = 10    // Once per EXP instruction
 	LogGas           uint64 = 375   // Per LOG* operation.
@@ -60,7 +53,22 @@ const (
 	MemoryGas        uint64 = 3     // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
 	TxDataNonZeroGas uint64 = 68    // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
 
-	MaxCodeSize = 24576
+	MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
+
+	// Precompiled contract gas prices
+
+	EcrecoverGas            uint64 = 3000   // Elliptic curve sender recovery gas price
+	Sha256BaseGas           uint64 = 60     // Base price for a SHA256 operation
+	Sha256PerWordGas        uint64 = 12     // Per-word price for a SHA256 operation
+	Ripemd160BaseGas        uint64 = 600    // Base price for a RIPEMD160 operation
+	Ripemd160PerWordGas     uint64 = 120    // Per-word price for a RIPEMD160 operation
+	IdentityBaseGas         uint64 = 15     // Base price for a data copy operation
+	IdentityPerWordGas      uint64 = 3      // Per-work price for a data copy operation
+	ModExpQuadCoeffDiv      uint64 = 100    // Divisor for the quadratic particle of the big int modular exponentiation
+	Bn256AddGas             uint64 = 500    // Gas needed for an elliptic curve addition
+	Bn256ScalarMulGas       uint64 = 2000   // Gas needed for an elliptic curve scalar multiplication
+	Bn256PairingBaseGas     uint64 = 100000 // Base price for an elliptic curve pairing check
+	Bn256PairingPerPointGas uint64 = 80000  // Per-point price for an elliptic curve pairing check
 )
 
 var (

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików