Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Eip86 CREATE #4046

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4167f7c
Improve ccache usage
chfast Apr 14, 2017
f2b1b1a
change create tx
yann300 Apr 18, 2017
26b2f33
eip86_create
yann300 Apr 19, 2017
52422f5
thrown if address already used
yann300 Apr 19, 2017
88df551
move transaction verification checks to sealEngine
Apr 11, 2017
8201381
use BlockHeader in EnvInfo
winsvega Apr 18, 2017
d4b41c0
fixes
winsvega Apr 19, 2017
e4db842
json tests
winsvega Apr 19, 2017
d0d8fc3
MetropolisFakeExtVM
yann300 Apr 19, 2017
c348678
Merge pull request #4039 from winsvega/develop
winsvega Apr 19, 2017
de767ca
remove blockHash tests from stateTests
winsvega Apr 19, 2017
09f8b94
jsontests
winsvega Apr 19, 2017
995dbdb
remove (void)var
yann300 Apr 19, 2017
e95fdbb
check already used address only if after metropolis
yann300 Apr 19, 2017
231394a
Merge pull request #4047 from winsvega/remhash
winsvega Apr 19, 2017
6c30f3c
properly implement CREATE_PSH
yann300 Apr 19, 2017
ca3f062
remove MetropolisFakeExtVM
yann300 Apr 19, 2017
cf0bb90
fix build (evmjit)
yann300 Apr 20, 2017
d491c9d
Merge pull request #4042 from ethereum/ccache
chfast Apr 20, 2017
98b2371
change create tx
yann300 Apr 18, 2017
9931b85
eip86_create
yann300 Apr 19, 2017
8eeeace
thrown if address already used
yann300 Apr 19, 2017
22bae65
MetropolisFakeExtVM
yann300 Apr 19, 2017
406e4fd
remove (void)var
yann300 Apr 19, 2017
1fa7213
check already used address only if after metropolis
yann300 Apr 19, 2017
ffc5996
properly implement CREATE_PSH
yann300 Apr 19, 2017
4b2f69a
remove MetropolisFakeExtVM
yann300 Apr 19, 2017
99768e2
fix build (evmjit)
yann300 Apr 20, 2017
a0b8dbe
rename CREATE_PSH => CREATE_P2SH
yann300 Apr 21, 2017
dc795fd
Merge branch 'eip86_create' of github.com:ethereum/cpp-ethereum into …
yann300 Apr 21, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,13 @@ cache:
# Cache whole deps dir hoping you will not need to download and
# build external dependencies next build.
- $TRAVIS_BUILD_DIR/deps
before_install:
# Install ccache on osx
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ccache; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./scripts/install_cmake.sh; fi
- ./scripts/install_deps.sh
before_script:
- ccache -s
- ./scripts/prepare_ccache.sh
- ./scripts/build.sh $TRAVIS_BUILD_TYPE $TRAVIS_TESTS
- ccache -s
- ./scripts/cleanup_ccache.sh
script:
- cd $TRAVIS_BUILD_DIR/build && ../scripts/tests.sh $TRAVIS_TESTS
after_success:
Expand Down
11 changes: 6 additions & 5 deletions cmake/EthCompilerSettings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
#
# These settings then end up spanning all POSIX platforms (Linux, OS X, BSD, etc)

# Use ccache if available
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
# Setup ccache.
# ccache is auto-enabled if the tool is found. To disable set -DCCACHE=Off option.
find_program(CCACHE ccache)
if(CCACHE)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
message("Using ccache")
endif(CCACHE_FOUND)
message(STATUS "ccache enabled (${CCACHE})")
endif()

if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
# Enables all the warnings about constructions that some users consider questionable,
Expand Down
2 changes: 1 addition & 1 deletion ethvm/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ int main(int argc, char** argv)
if (!code.empty())
executive.call(contractDestination, sender, value, gasPrice, &data, gas);
else
executive.create(sender, value, gasPrice, gas, &data, origin);
executive.create(sender, value, gasPrice, gas, &data, origin, Instruction::CREATE);

Timer timer;
if ((mode == Mode::Statistics || mode == Mode::Trace) && vmKind == VMKind::Interpreter)
Expand Down
5 changes: 5 additions & 0 deletions libethashseal/Ethash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ void Ethash::verifyTransaction(ImportRequirements::value _ir, TransactionBase co
}
if (_ir & ImportRequirements::TransactionBasic && _t.baseGasRequired(evmSchedule(_env)) > _t.gas())
BOOST_THROW_EXCEPTION(OutOfGasIntrinsic());

// Avoid transactions that would take us beyond the block gas limit.
u256 startGasUsed = _env.gasUsed();
if (startGasUsed + (bigint)_t.gas() > _env.gasLimit())
BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(_env.gasLimit() - startGasUsed), (bigint)_t.gas()));
}

u256 Ethash::childGasLimit(BlockHeader const& _bi, u256 const& _gasFloorTarget) const
Expand Down
1 change: 1 addition & 0 deletions libethcore/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ DEV_SIMPLE_EXCEPTION(InvalidNumber);
DEV_SIMPLE_EXCEPTION(InvalidZeroSignatureTransaction);
DEV_SIMPLE_EXCEPTION(BlockNotFound);
DEV_SIMPLE_EXCEPTION(UnknownParent);
DEV_SIMPLE_EXCEPTION(AddressAlreadyUsed);

DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen);
DEV_SIMPLE_EXCEPTION(DAGCreationFailure);
Expand Down
41 changes: 18 additions & 23 deletions libethereum/Executive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,35 +179,17 @@ void Executive::accrueSubState(SubState& _parentContext)
void Executive::initialize(Transaction const& _transaction)
{
m_t = _transaction;

m_baseGasRequired = m_t.baseGasRequired(m_sealEngine.evmSchedule(m_envInfo));
try
{
m_sealEngine.verifyTransaction(ImportRequirements::Everything, _transaction, m_envInfo);
m_sealEngine.verifyTransaction(ImportRequirements::Everything, m_t, m_envInfo);
}
catch (Exception const& ex)
{
m_excepted = toTransactionException(ex);
throw;
}

// Avoid transactions that would take us beyond the block gas limit.
u256 startGasUsed = m_envInfo.gasUsed();
if (startGasUsed + (bigint)m_t.gas() > m_envInfo.gasLimit())
{
clog(ExecutiveWarnChannel) << "Cannot fit tx in block" << m_envInfo.number() << ": Require <" << (m_envInfo.gasLimit() - startGasUsed) << " Got" << m_t.gas();
m_excepted = TransactionException::BlockGasLimitReached;
BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_envInfo.gasLimit() - startGasUsed), (bigint)m_t.gas()));
}

// Check gas cost is enough.
m_baseGasRequired = m_t.baseGasRequired(m_sealEngine.evmSchedule(m_envInfo));
if (m_baseGasRequired > m_t.gas())
{
clog(ExecutiveWarnChannel) << "Not enough gas to pay for the transaction: Require >" << m_baseGasRequired << " Got" << m_t.gas();
m_excepted = TransactionException::OutOfGasBase;
BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError((bigint)m_baseGasRequired, (bigint)m_t.gas()));
}

if (!m_t.hasZeroSignature())
{
// Avoid invalid transactions.
Expand Down Expand Up @@ -251,7 +233,7 @@ bool Executive::execute()
m_s.subBalance(m_t.sender(), m_gasCost);

if (m_t.isCreation())
return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_baseGasRequired, &m_t.data(), m_t.sender());
return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_baseGasRequired, &m_t.data(), m_t.sender(), Instruction::CREATE);
else
return call(m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_baseGasRequired);
}
Expand Down Expand Up @@ -324,7 +306,7 @@ bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address co
return !m_ext;
}

bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin)
bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin, Instruction _creationType)
{
u256 nonce = m_s.getNonce(_sender);
if (_sender != MaxAddress) // EIP86
Expand All @@ -336,7 +318,17 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g

// We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since
// we delete it explicitly if we decide we need to revert.
m_newAddress = right160(sha3(rlpList(_sender, nonce)));
if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("metropolisForkBlock"))
{
// EIP86
Address pushedAddress = MaxAddress;
if (_creationType == Instruction::CREATE_P2SH)
pushedAddress = _sender;
m_newAddress = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes()));
}
else
m_newAddress = right160(sha3(rlpList(_sender, nonce)));

m_gas = _gas;

// Transfer ether before deploying the code. This will also create new
Expand Down Expand Up @@ -391,6 +383,9 @@ bool Executive::go(OnOpFunc const& _onOp)
auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create();
if (m_isCreation)
{
if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("metropolisForkBlock") && m_s.addressHasCode(m_newAddress))
BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); // EIP86

auto out = vm->exec(m_gas, *m_ext, _onOp);
if (m_res)
{
Expand Down
2 changes: 1 addition & 1 deletion libethereum/Executive.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class Executive

/// Set up the executive for evaluating a bare CREATE (contract-creation) operation.
/// @returns false iff go() must be called (and thus a VM execution in required).
bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress);
bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress, Instruction _creationType);
/// Set up the executive for evaluating a bare CALL (message call) operation.
/// @returns false iff go() must be called (and thus a VM execution in required).
bool call(Address _receiveAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas);
Expand Down
4 changes: 2 additions & 2 deletions libethereum/ExtVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ void ExtVM::setStore(u256 _n, u256 _v)
m_s.setStorage(myAddress, _n, _v);
}

h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp)
h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _creationType, OnOpFunc const& _onOp)
{
Executive e{m_s, envInfo(), m_sealEngine, depth + 1};
if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin))
if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin, _creationType))
{
go(depth, e, _onOp);
e.accrueSubState(sub);
Expand Down
2 changes: 1 addition & 1 deletion libethereum/ExtVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ExtVM: public ExtVMFace
virtual size_t codeSizeAt(Address _a) override final;

/// Create a new contract.
virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}) override final;
virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _creationType, OnOpFunc const& _onOp = {}) override final;

/// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller.
/// @returns success flag and output data, if any.
Expand Down
50 changes: 13 additions & 37 deletions libevm/ExtVMFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,52 +209,28 @@ class EnvInfo
public:
EnvInfo() {}
EnvInfo(BlockHeader const& _current, LastHashes const& _lh = LastHashes(), u256 const& _gasUsed = u256()):
m_number(_current.number()),
m_author(_current.author()),
m_timestamp(_current.timestamp()),
m_difficulty(_current.difficulty()),
// Trim gas limit to int64. convert_to used explicitly instead of
// static_cast to be noticed when BlockHeader::gasLimit() will be
// changed to int64 too.
m_gasLimit(_current.gasLimit().convert_to<int64_t>()),
m_headerInfo(_current),
m_lastHashes(_lh),
m_gasUsed(_gasUsed)
{}

EnvInfo(BlockHeader const& _current, LastHashes&& _lh, u256 const& _gasUsed = u256()):
m_number(_current.number()),
m_author(_current.author()),
m_timestamp(_current.timestamp()),
m_difficulty(_current.difficulty()),
// Trim gas limit to int64. convert_to used explicitly instead of
// static_cast to be noticed when BlockHeader::gasLimit() will be
// changed to int64 too.
m_gasLimit(_current.gasLimit().convert_to<int64_t>()),
m_lastHashes(_lh),
m_gasUsed(_gasUsed)
{}

u256 const& number() const { return m_number; }
Address const& author() const { return m_author; }
u256 const& timestamp() const { return m_timestamp; }
u256 const& difficulty() const { return m_difficulty; }
int64_t gasLimit() const { return m_gasLimit; }
u256 const& number() const { return m_headerInfo.number(); }
Address const& author() const { return m_headerInfo.author(); }
u256 const& timestamp() const { return m_headerInfo.timestamp(); }
u256 const& difficulty() const { return m_headerInfo.difficulty(); }
u256 const& gasLimit() const { return m_headerInfo.gasLimit(); }
LastHashes const& lastHashes() const { return m_lastHashes; }
u256 const& gasUsed() const { return m_gasUsed; }

void setNumber(u256 const& _v) { m_number = _v; }
void setAuthor(Address const& _v) { m_author = _v; }
void setTimestamp(u256 const& _v) { m_timestamp = _v; }
void setDifficulty(u256 const& _v) { m_difficulty = _v; }
void setGasLimit(int64_t _v) { m_gasLimit = _v; }
void setNumber(u256 const& _v) { m_headerInfo.setNumber(_v); }
void setAuthor(Address const& _v) { m_headerInfo.setAuthor(_v); }
void setTimestamp(u256 const& _v) { m_headerInfo.setTimestamp(_v); }
void setDifficulty(u256 const& _v) { m_headerInfo.setDifficulty(_v); }
void setGasLimit(u256 const& _v) { m_headerInfo.setGasLimit(_v); }
void setLastHashes(LastHashes&& _lh) { m_lastHashes = _lh; }

private:
u256 m_number;
Address m_author;
u256 m_timestamp;
u256 m_difficulty;
int64_t m_gasLimit;
BlockHeader m_headerInfo;
LastHashes m_lastHashes;
u256 m_gasUsed;
};
Expand Down Expand Up @@ -298,7 +274,7 @@ class ExtVMFace
virtual void suicide(Address) { sub.suicides.insert(myAddress); }

/// Create a new (contract) account.
virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); }
virtual h160 create(u256, u256&, bytesConstRef, Instruction, OnOpFunc const&) { return h160(); }

/// Make a new message call.
/// @returns success flag and output data, if any.
Expand Down
6 changes: 4 additions & 2 deletions libevm/JitVM.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "JitVM.h"

#include <libdevcore/Log.h>
#include <libevmcore/Instruction.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>

Expand Down Expand Up @@ -73,7 +74,8 @@ void evm_query(
o_result->uint256be = toEvmC(env.envInfo().difficulty());
break;
case EVM_GAS_LIMIT:
o_result->int64 = env.envInfo().gasLimit();
// TODO: Handle overflow / exception
o_result->int64 = static_cast<int64_t>(env.envInfo().gasLimit());
break;
case EVM_NUMBER:
// TODO: Handle overflow / exception
Expand Down Expand Up @@ -179,7 +181,7 @@ int64_t evm_call(
{
assert(_outputSize == 20);
u256 gas = _gas;
auto addr = env.create(value, gas, input, {});
auto addr = env.create(value, gas, input, Instruction::CREATE, {});
auto gasLeft = static_cast<decltype(_gas)>(gas);
if (addr)
std::memcpy(_outputData, addr.data(), 20);
Expand Down
8 changes: 8 additions & 0 deletions libevm/VM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ void VM::interpretCases()
//
// Call-related instructions
//

CASE(CREATE_P2SH)
{
if (!m_schedule->haveCreatePsh)
throwBadInstruction();
m_bounce = &VM::caseCreate;
}
BREAK

CASE(CREATE)
{
Expand Down
2 changes: 1 addition & 1 deletion libevm/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class VM: public VMFace
void copyCode(int);
const void* const* c_jumpTable = 0;
bool m_caseInit = false;

typedef void (VM::*MemFnPtr)();
MemFnPtr m_bounce = 0;
MemFnPtr m_onFail = 0;
Expand Down
3 changes: 2 additions & 1 deletion libevm/VMCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ void VM::caseCreate()
if (!m_schedule->staticCallDepthLimit())
createGas -= createGas / 64;
u256 gas = createGas;
m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp);
m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_OP, m_onOp);

*m_io_gas_p -= (createGas - gas);
m_io_gas = uint64_t(*m_io_gas_p);
}
Expand Down
2 changes: 2 additions & 0 deletions libevmcore/EVMSchedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct EVMSchedule
bool eip150Mode = false;
bool eip158Mode = false;
bool haveRevert = false;
bool haveCreatePsh = false;
std::array<unsigned, 8> tierStepGas;
unsigned expGas = 10;
unsigned expByteGas = 10;
Expand Down Expand Up @@ -109,6 +110,7 @@ static const EVMSchedule MetropolisSchedule = []
{
EVMSchedule schedule = EIP158Schedule;
schedule.haveRevert = true;
schedule.haveCreatePsh = true;
return schedule;
}();

Expand Down
2 changes: 2 additions & 0 deletions libevmcore/Instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ const std::map<std::string, Instruction> dev::eth::c_instructions =
{ "LOG3", Instruction::LOG3 },
{ "LOG4", Instruction::LOG4 },
{ "CREATE", Instruction::CREATE },
{ "CREATE_P2SH", Instruction::CREATE_P2SH },
{ "CALL", Instruction::CALL },
{ "CALLCODE", Instruction::CALLCODE },
{ "RETURN", Instruction::RETURN },
Expand Down Expand Up @@ -313,6 +314,7 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } },
{ Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } },
{ Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } },
{ Instruction::CREATE_P2SH, { "CREATE_P2SH", 0, 3, 1, true, Tier::Special } },
{ Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } },
{ Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } },
{ Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } },
Expand Down
3 changes: 2 additions & 1 deletion libevmcore/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,12 @@ enum class Instruction: uint8_t
JUMPCI, ///< conditionally alter the program counter - pre-verified
BAD, ///< placed to force invalid instruction exception

CREATE = 0xf0, ///< create a new account with associated code
CREATE = 0xf0, ///< create a new account with associated code. (since EIP86: sha3((MaxAddress + sha3(code))
CALL, ///< message-call into an account
CALLCODE, ///< message-call with another account's code only
RETURN, ///< halt execution returning output data
DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender
CREATE_P2SH = 0xfb, ///< create a new account with associated code. sha3((sender + sha3(code))
REVERT = 0xfd, ///< stop execution and revert state changes, without consuming all provided gas
SUICIDE = 0xff ///< halt execution and register account for later deletion
};
Expand Down
6 changes: 6 additions & 0 deletions scripts/cleanup_ccache.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env sh

set -e

ccache --cleanup
ccache --show-stats
7 changes: 6 additions & 1 deletion scripts/install_deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,19 @@ Darwin)
;;
esac

if [ "$TRAVIS" ]; then
TRAVIS_PACKAGES="ccache"
fi

# Check for Homebrew install and abort if it is not installed.
brew -v > /dev/null 2>&1 || { echo >&2 "ERROR - cpp-ethereum requires a Homebrew install. See http://brew.sh."; exit 1; }

# And finally install all the external dependencies.
brew install \
leveldb \
libmicrohttpd \
miniupnpc
miniupnpc \
$TRAVIS_PACKAGES

;;

Expand Down
Loading