Skip to content

Commit

Permalink
Agharta/eip1014 create2 (#5)
Browse files Browse the repository at this point in the history
* Created branch & added new opcode into opcode.go file

* Added create2 function

* Implemented create function for Create2 contracts

* Created branch & added new opcode into opcode.go file

* Added create2 function

* Implemented create function for Create2 contracts

* Finished Create2 opcode & cleaned up comments

* Created branch & added new opcode into opcode.go file

* Added create2 function

* Atlantis config (#50)

* Added Atlantis fork in builtin mainnet and morden config

* Fixed difficulty test at 10_000_000 block (Atlantis)

* Added tests for Atlantis difficulty transition

* cmd/geth rename client (#52)

* Added error handling for precompiles and removed skipped tests (#54)

* Makefile and README updates (#49)

* wip makefile updates

* Fixed makefile and updated README

* Fixed readme changes

* Added go module documentation and fixed wiki links to EP

* Added go modules on for makefile commands and documentation

* makefile: fix version string (#57)

* Dockerfile configuration (#56)

* Added Dockerfile setup

* Added Dockerfile setup

* Fixed build command

* Removed private repo authentication in Dockerfile

* Enforced go modules on for every part of the test command (#60)

* docs: update readme (#59)

* docs: update readme

* Update README.md

* Update README.md

* ci: prepare assets for release (#64)

* ci: prepare assets for release

* ci: fix indentation

* ci: fix indentation

* ci: fix indentation

* ci: fix indentation

* ci: release in build step

* ci: calculate sha256sums

* ci: store artifacts

* ci: do a reverse copy

* ci: fix bash syntax

* ci: indicate os in release

* ci: pushd and pop'd ;)

* Receipt fixes and state trie clearing detail (#62)

* receipt and state trie clearing changes

* Fixed receipt storage and added backward compatible decoding

* Implemented create function for Create2 contracts

* Created branch & added new opcode into opcode.go file

* Added create2 function

* Implemented create function for Create2 contracts

* Finished Create2 opcode & cleaned up comments

* Created branch & added new opcode into opcode.go file

* Added create2 function

* Atlantis config (#50)

* Added Atlantis fork in builtin mainnet and morden config

* Fixed difficulty test at 10_000_000 block (Atlantis)

* Added tests for Atlantis difficulty transition

* cmd/geth rename client (#52)

* Added error handling for precompiles and removed skipped tests (#54)

* Makefile and README updates (#49)

* wip makefile updates

* Fixed makefile and updated README

* Fixed readme changes

* Added go module documentation and fixed wiki links to EP

* Added go modules on for makefile commands and documentation

* makefile: fix version string (#57)

* Dockerfile configuration (#56)

* Added Dockerfile setup

* Added Dockerfile setup

* Fixed build command

* Removed private repo authentication in Dockerfile

* Enforced go modules on for every part of the test command (#60)

* docs: update readme (#59)

* docs: update readme

* Update README.md

* Update README.md

* ci: prepare assets for release (#64)

* ci: prepare assets for release

* ci: fix indentation

* ci: fix indentation

* ci: fix indentation

* ci: fix indentation

* ci: release in build step

* ci: calculate sha256sums

* ci: store artifacts

* ci: do a reverse copy

* ci: fix bash syntax

* ci: indicate os in release

* ci: pushd and pop'd ;)

* Receipt fixes and state trie clearing detail (#62)

* receipt and state trie clearing changes

* Fixed receipt storage and added backward compatible decoding

* Implemented create function for Create2 contracts

* Created branch & added new opcode into opcode.go file

* Added create2 function

* Implemented create function for Create2 contracts

* Finished Create2 opcode & cleaned up comments

* Created branch & added new opcode into opcode.go file

* Added create2 function

* Added error handling for precompiles and removed skipped tests (#54)

* Created branch & added new opcode into opcode.go file

* Implemented create function for Create2 contracts

* Added create2 function

* Implemented create function for Create2 contracts

* Rebased with development 2nd

* Cleaned up code/comments & removed print statements.

* Cleaned up comments & reverted go.mod & go.sum to original

* Removed Constantinople tests & some tests involving non-implemented opcodes (EIP 145/1052) to pass CI.

* Fixed removal of stBugs, stShift & stExtCodeHash tests

* Fixed instructions_test salt parameter passed to CreateAddress2.

* Changed local vars to camel case

* Fixed error refactor.

* Cleaned up comments. Skipped tests involving EIP684 (Collision).

* Fixed error checking for evm.Run().
  • Loading branch information
dziabko committed Sep 24, 2019
1 parent b485f00 commit e0f5a28
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 7 deletions.
89 changes: 85 additions & 4 deletions core/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ var (
maxCodeSize = 24576
errMaxCodeSizeExceeded = fmt.Errorf("Max Code Size exceeded (%d)", maxCodeSize)

errCodeStoreOutOfGas = errors.New("contract creation code storage out of gas")
errContractAddressCollision = errors.New("contract address collision")
)

Expand Down Expand Up @@ -225,35 +226,115 @@ func StaticCall(env vm.Environment, caller vm.ContractRef, addr common.Address,
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
nonce := env.Db().GetNonce(caller.Address())
addr := crypto.CreateAddress(caller.Address(), nonce)
ret, address, err = create(env, caller, addr, code, gas, gasPrice, value)
ret, address, err = create(env, caller, &addr, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value, false)
// Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE

//if there's an error we return nothing
if err != nil && err != vm.ErrRevert {
return nil, address, err
}
return ret, address, err
}

// Create2 creates a new contract with the given code
func Create2(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, salt, value *big.Int) (ret []byte, address common.Address, err error) {
addr := crypto.CreateAddress2(caller.Address(), common.BigToHash(salt).Bytes(), crypto.Keccak256(code))
ret, address, err = create(env, caller, addr, code, gas, gasPrice, value)
ret, address, err = create(env, caller, &addr, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value, false)
// Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE

//if there's an error we return nothing
if err != nil && err != vm.ErrRevert {
return nil, address, err
}
return ret, address, err
}

// create creates a new contract using code as deployment code.
//Replace codeHash w/ crypto.Keccak256Hash
func create(env vm.Environment, caller vm.ContractRef, address common.Address, code []byte, gas, gasPrice, value *big.Int) ([]byte, common.Address, error) {
func create(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int, readOnly bool) ([]byte, common.Address, error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)

return nil, common.Address{}, errCallCreateDepth
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)

return nil, common.Address{}, ErrInsufficientFunds
}
nonce := env.Db().GetNonce(caller.Address())
env.Db().SetNonce(caller.Address(), nonce+1)

// Create a new account on the state
snapshot := env.SnapshotDatabase()

//Create account with address
to := env.Db().CreateAccount(*address)

if env.RuleSet().IsAtlantis(env.BlockNumber()) {
env.Db().SetNonce(*address, 1)
}

env.Transfer(env.Db().GetAccount(caller.Address()), to, value)

// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise()

ret, err := evm.Run(contract, input, readOnly)

// check whether the max code size has been exceeded
maxCodeSizeExceeded := len(ret) > maxCodeSize && env.RuleSet().IsAtlantis(env.BlockNumber())
// if the contract creation ran successfully and no errors were returned
// calculate the gas required to store the code. If the code could not
// be stored due to not enough gas set an error and let it be handled
// by the error checking condition below.
if err == nil && !maxCodeSizeExceeded {
createDataGas := big.NewInt(int64(len(ret)))
createDataGas.Mul(createDataGas, big.NewInt(200))
if contract.UseGas(createDataGas) {
env.Db().SetCode(*address, ret)
} else {
err = vm.CodeStoreOutOfGasError
}
}

// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if maxCodeSizeExceeded || (err != nil && (env.RuleSet().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError)) {
env.RevertToSnapshot(snapshot)
if err != vm.ErrRevert {
contract.UseGas(contract.Gas)
}
}
// Assign err if contract code size exceeds the max while the err is still empty.
if maxCodeSizeExceeded && err == nil {
err = errMaxCodeSizeExceeded
}

return ret, *address, err

}

func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int, readOnly bool) (ret []byte, addr common.Address, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)

return nil, common.Address{}, errCallCreateDepth
}

if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)

Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,4 @@ require (
gopkg.in/fatih/set.v0 v0.1.0
gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951
gopkg.in/urfave/cli.v1 v1.17.0
)

replace github.com/eth-classic/go-ethereum/accounts/abi/bind v0.0.0-20190521151733-fe17e9e1e2ce => ./accounts/abi/bind
)
1 change: 1 addition & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var (
DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.

MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
Sha3WordGas = big.NewInt(6) // Once per word of the SHA3 operation's data.
CreateDataGas = big.NewInt(200)
Sha3WordGas = big.NewInt(6) // Once per word of the SHA3 operation's data.
)

0 comments on commit e0f5a28

Please sign in to comment.