mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
params, core/vm: implement EIP-1108
Old gas costs for elliptic curve operations are given the PreIstanbul prefix, while current gas costs retain the unprefixed names. The actual precompile implementations are the same, so they are factored out into common functions that are called by the pre-Istanbul and current precompile structs. Finally, an Istanbul precompile list is added that references the new precompile structs, which in turn reference the new gas costs.
This commit is contained in:
parent
36060173e0
commit
8dca6f1760
3 changed files with 123 additions and 38 deletions
|
|
@ -54,9 +54,22 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
|||
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{},
|
||||
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
||||
}
|
||||
|
||||
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
|
||||
// contracts used in the Istanbul release.
|
||||
var PrecompiledContractsIstanbul = 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}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
}
|
||||
|
||||
// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
|
||||
|
|
@ -271,15 +284,9 @@ func newTwistPoint(blob []byte) (*bn256.G2, error) {
|
|||
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) {
|
||||
// runBn256Add implements the Bn256Add precompile, referenced by both
|
||||
// Byzantium and Istanbul operations.
|
||||
func runBn256Add(input []byte) ([]byte, error) {
|
||||
x, err := newCurvePoint(getData(input, 0, 64))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -293,15 +300,35 @@ func (c *bn256Add) Run(input []byte) ([]byte, error) {
|
|||
return res.Marshal(), nil
|
||||
}
|
||||
|
||||
// bn256ScalarMul implements a native elliptic curve scalar multiplication.
|
||||
type bn256ScalarMul struct{}
|
||||
// bn256Add implements a native elliptic curve point addition conforming to
|
||||
// Istanbul consensus rules.
|
||||
type bn256AddIstanbul struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256ScalarMulGas
|
||||
func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256AddGasIstanbul
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
|
||||
return runBn256Add(input)
|
||||
}
|
||||
|
||||
// bn256AddByzantium implements a native elliptic curve point addition
|
||||
// conforming to Byzantium consensus rules.
|
||||
type bn256AddByzantium struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256AddGasByzantium
|
||||
}
|
||||
|
||||
func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) {
|
||||
return runBn256Add(input)
|
||||
}
|
||||
|
||||
// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
|
||||
// both Byzantium and Istanbul operations.
|
||||
func runBn256ScalarMul(input []byte) ([]byte, error) {
|
||||
p, err := newCurvePoint(getData(input, 0, 64))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -311,6 +338,32 @@ func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
|
|||
return res.Marshal(), nil
|
||||
}
|
||||
|
||||
// bn256ScalarMulIstanbul implements a native elliptic curve scalar
|
||||
// multiplication conforming to Istanbul consensus rules.
|
||||
type bn256ScalarMulIstanbul struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256ScalarMulGasIstanbul
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
|
||||
return runBn256ScalarMul(input)
|
||||
}
|
||||
|
||||
// bn256ScalarMulByzantium implements a native elliptic curve scalar
|
||||
// multiplication conforming to Byzantium consensus rules.
|
||||
type bn256ScalarMulByzantium struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256ScalarMulGasByzantium
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) {
|
||||
return runBn256ScalarMul(input)
|
||||
}
|
||||
|
||||
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}
|
||||
|
|
@ -322,15 +375,9 @@ var (
|
|||
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) {
|
||||
// runBn256Pairing implements the Bn256Pairing precompile, referenced by both
|
||||
// Byzantium and Istanbul operations.
|
||||
func runBn256Pairing(input []byte) ([]byte, error) {
|
||||
// Handle some corner cases cheaply
|
||||
if len(input)%192 > 0 {
|
||||
return nil, errBadPairingInput
|
||||
|
|
@ -358,3 +405,29 @@ func (c *bn256Pairing) Run(input []byte) ([]byte, error) {
|
|||
}
|
||||
return false32Byte, nil
|
||||
}
|
||||
|
||||
// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
|
||||
// conforming to Istanbul consensus rules.
|
||||
type bn256PairingIstanbul struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
|
||||
}
|
||||
|
||||
func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
|
||||
return runBn256Pairing(input)
|
||||
}
|
||||
|
||||
// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve
|
||||
// conforming to Byzantium consensus rules.
|
||||
type bn256PairingByzantium struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
|
||||
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
|
||||
}
|
||||
|
||||
func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) {
|
||||
return runBn256Pairing(input)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
|
|||
if evm.chainRules.IsByzantium {
|
||||
precompiles = PrecompiledContractsByzantium
|
||||
}
|
||||
if evm.chainRules.IsIstanbul {
|
||||
precompiles = PrecompiledContractsIstanbul
|
||||
}
|
||||
if p := precompiles[*contract.CodeAddr]; p != nil {
|
||||
return RunPrecompiledContract(p, input, contract)
|
||||
}
|
||||
|
|
@ -206,6 +209,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
if evm.chainRules.IsByzantium {
|
||||
precompiles = PrecompiledContractsByzantium
|
||||
}
|
||||
if evm.chainRules.IsIstanbul {
|
||||
precompiles = PrecompiledContractsIstanbul
|
||||
}
|
||||
if precompiles[addr] == nil && evm.chainRules.IsEIP158 && value.Sign() == 0 {
|
||||
// Calling a non existing account, don't do anything, but ping the tracer
|
||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||
|
|
|
|||
|
|
@ -99,18 +99,24 @@ const (
|
|||
|
||||
// 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 = 20 // Divisor for the quadratic particle of the big int modular exponentiation
|
||||
Bn256AddGas uint64 = 500 // Gas needed for an elliptic curve addition
|
||||
Bn256ScalarMulGas uint64 = 40000 // 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
|
||||
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 = 20 // Divisor for the quadratic particle of the big int modular exponentiation
|
||||
// Byzantium precompiled elliptic curve contract gas prices
|
||||
Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition
|
||||
Bn256ScalarMulGasByzantium uint64 = 40000 // Byzantium gas needed for an elliptic curve scalar multiplication
|
||||
Bn256PairingBaseGasByzantium uint64 = 100000 // Byzantium base price for an elliptic curve pairing check
|
||||
Bn256PairingPerPointGasByzantium uint64 = 80000 // Byzantium per-point price for an elliptic curve pairing check
|
||||
// Precompiled elliptic curve contract gas prices were reduced in Istanbul via EIP-1108
|
||||
Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition
|
||||
Bn256ScalarMulGasIstanbul uint64 = 6000 // Gas needed for an elliptic curve scalar multiplication
|
||||
Bn256PairingBaseGasIstanbul uint64 = 45000 // Base price for an elliptic curve pairing check
|
||||
Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
Loading…
Reference in a new issue