diff options
Diffstat (limited to 'core/vm')
-rw-r--r-- | core/vm/contracts.go | 125 | ||||
-rw-r--r-- | core/vm/evm.go | 6 |
2 files changed, 105 insertions, 26 deletions
diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 20b741f8f..0e4fe0198 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -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 *bn256AddIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256AddGasIstanbul +} + +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 *bn256ScalarMul) RequiredGas(input []byte) uint64 { - return params.Bn256ScalarMulGas +func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256AddGasByzantium +} + +func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) { + return runBn256Add(input) } -func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) { +// 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) +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 030f0c789..98d9e31fb 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -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 { |