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

EIP-2046 independent activation #5741

Merged
merged 7 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [1.8.0] - Unreleased

- Added: [#5699](https://github.com/ethereum/aleth/pull/5699) EIP 2046: Reduced gas cost for static calls made to precompiles.
- Added: [#5741](https://github.com/ethereum/aleth/pull/5741) Support for individual EIP activation to facilitate EIP-centric network upgrade process.
- Added: [#5752](https://github.com/ethereum/aleth/pull/5752) [#5753](https://github.com/ethereum/aleth/pull/5753) Implement EIP1380 (reduced gas costs for call-to-self).
- Removed: [#5760](https://github.com/ethereum/aleth/pull/5760) Official support for Visual Studio 2015 has been dropped. Compilation with this compiler is expected to stop working after migration to C++14.
- Fixed: [#5792](https://github.com/ethereum/aleth/pull/5792) Faster and cheaper execution of RPC functions which query blockchain state (e.g. getBalance).
Expand Down
11 changes: 10 additions & 1 deletion libethcore/ChainOperationParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@


#include "ChainOperationParams.h"
#include <libdevcore/Log.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/Log.h>

using namespace std;
using namespace dev;
using namespace eth;
Expand Down Expand Up @@ -35,6 +36,14 @@ ChainOperationParams::ChainOperationParams():
}

EVMSchedule const& ChainOperationParams::scheduleForBlockNumber(u256 const& _blockNumber) const
{
if (_blockNumber >= lastForkBlock)
return lastForkWithAdditionalEIPsSchedule;
else
return forkScheduleForBlockNumber(_blockNumber);
}

EVMSchedule const& ChainOperationParams::forkScheduleForBlockNumber(u256 const& _blockNumber) const
{
if (_blockNumber >= experimentalForkBlock)
return ExperimentalSchedule;
Expand Down
29 changes: 28 additions & 1 deletion libethcore/ChainOperationParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
#pragma once

#include <libdevcore/Common.h>
#include <libethcore/EVMSchedule.h>
#include <libethcore/Precompiled.h>

#include "Common.h"
#include "EVMSchedule.h"

namespace dev
{
namespace eth
{
struct EVMSchedule;

class PrecompiledContract
{
Expand Down Expand Up @@ -53,6 +54,11 @@ class PrecompiledContract

constexpr int64_t c_infiniteBlockNumber = std::numeric_limits<int64_t>::max();

struct AdditionalEIPs
{
bool eip2046 = false;
};

struct ChainOperationParams
{
ChainOperationParams();
Expand All @@ -62,11 +68,28 @@ struct ChainOperationParams
/// The chain sealer name: e.g. Ethash, NoProof, BasicAuthority
std::string sealEngineName = "NoProof";

// Example of how to check EIP activation from outside of EVM:
halfalicious marked this conversation as resolved.
Show resolved Hide resolved
// bool isEIP2046Enabled(u256 const& _blockNumber) const
// {
// return _blockNumber >= lastForkBlock && lastForkAdditionalEIPs.eip2046;
// }
// After hard fork finalization this is changed to:
// bool isEIP2046Enabled(u256 const& _blockNumber) const
// {
// return _blockNumber >= berlinForkBlock;
// }

/// General chain params.
private:
u256 m_blockReward;

public:
// returns schedule for the fork active at the given block
// may include additional individually activated EIPs on top of the last fork block
EVMSchedule const& scheduleForBlockNumber(u256 const& _blockNumber) const;
// returns schedule according to the the fork rules active at the given block
// doesn't include additional individually activated EIPs
EVMSchedule const& forkScheduleForBlockNumber(u256 const& _blockNumber) const;
u256 blockReward(EVMSchedule const& _schedule) const;
void setBlockReward(u256 const& _newBlockReward);
u256 maximumExtraDataSize = 32;
Expand All @@ -86,6 +109,8 @@ struct ChainOperationParams
u256 experimentalForkBlock = c_infiniteBlockNumber;
u256 istanbulForkBlock = c_infiniteBlockNumber;
u256 berlinForkBlock = c_infiniteBlockNumber;
u256 lastForkBlock = c_infiniteBlockNumber;
AdditionalEIPs lastForkAdditionalEIPs;
int chainID = 0; // Distinguishes different chains (mainnet, Ropsten, etc).
int networkID = 0; // Distinguishes different sub protocols.

Expand All @@ -96,6 +121,8 @@ struct ChainOperationParams

/// Precompiled contracts as specified in the chain params.
std::unordered_map<Address, PrecompiledContract> precompiled;

EVMSchedule lastForkWithAdditionalEIPsSchedule;
};

}
Expand Down
19 changes: 19 additions & 0 deletions libethcore/EVMSchedule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/// Aleth: Ethereum C++ client, tools and libraries.
// Copyright 2019 Aleth Authors.
// Licensed under the GNU General Public License, Version 3.

#include "EVMSchedule.h"
#include <libethcore/ChainOperationParams.h>

namespace dev
{
namespace eth
{
EVMSchedule::EVMSchedule(EVMSchedule const& _schedule, AdditionalEIPs const& _eips)
: EVMSchedule(_schedule)
{
if (_eips.eip2046)
precompileStaticCallGas = 40;
}
} // namespace eth
} // namespace dev
8 changes: 6 additions & 2 deletions libethcore/EVMSchedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@

#pragma once

#include <array>
#include <libdevcore/Common.h>
#include <libethcore/Common.h>
#include <boost/optional.hpp>
#include <array>

namespace dev
{
namespace eth
{
struct AdditionalEIPs;

struct EVMSchedule
{
EVMSchedule(): tierStepGas(std::array<unsigned, 8>{{0, 2, 3, 5, 8, 10, 20, 0}}) {}
EVMSchedule(bool _efcd, bool _hdc, unsigned const& _txCreateGas): exceptionalFailedCodeDeposit(_efcd), haveDelegateCall(_hdc), tierStepGas(std::array<unsigned, 8>{{0, 2, 3, 5, 8, 10, 20, 0}}), txCreateGas(_txCreateGas) {}
// construct schedule with additional EIPs on top
EVMSchedule(EVMSchedule const& _schedule, AdditionalEIPs const& _eips);
unsigned accountVersion = 0;
bool exceptionalFailedCodeDeposit = true;
bool haveDelegateCall = true;
Expand Down Expand Up @@ -155,7 +160,6 @@ static const EVMSchedule IstanbulSchedule = [] {

static const EVMSchedule BerlinSchedule = [] {
EVMSchedule schedule = IstanbulSchedule;
schedule.precompileStaticCallGas = 40;
schedule.callSelfGas = 40;
return schedule;
}();
Expand Down
39 changes: 38 additions & 1 deletion libethereum/ChainParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,35 @@
#include <libethcore/BlockHeader.h>
#include <libethcore/Precompiled.h>
#include <libethcore/SealEngine.h>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace dev;
using namespace eth;
using namespace eth::validation;
namespace js = json_spirit;

namespace
{
u256 findMaxForkBlockNumber(js::mObject const& _params)
{
u256 maxForkBlockNumber = 0;
for (auto const& paramKeyValue : _params)
{
auto const& key = paramKeyValue.first;
if (boost::algorithm::ends_with(key, c_forkBlockSuffix))
{
auto const& value = paramKeyValue.second;
auto const blockNumber = fromBigEndian<u256>(fromHex(value.get_str()));
if (blockNumber < c_infiniteBlockNumber && blockNumber > maxForkBlockNumber)
maxForkBlockNumber = blockNumber;
}
}

return maxForkBlockNumber;
}
} // namespace

ChainParams::ChainParams()
{
for (unsigned i = 1; i <= 4; ++i)
Expand All @@ -37,6 +59,16 @@ ChainParams::ChainParams(string const& _json, h256 const& _stateRoot)
*this = loadConfig(_json, _stateRoot);
}

ChainParams::ChainParams(std::string const& _configJson, AdditionalEIPs const& _additionalEIPs)
: ChainParams(_configJson)
{
lastForkAdditionalEIPs = _additionalEIPs;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Nit) Can we initialize this as a part of the initializers list?


// create EVM schedule
EVMSchedule const& lastForkSchedule = forkScheduleForBlockNumber(lastForkBlock);
lastForkWithAdditionalEIPsSchedule = EVMSchedule{lastForkSchedule, _additionalEIPs};
}

ChainParams ChainParams::loadConfig(
string const& _json, h256 const& _stateRoot, const boost::filesystem::path& _configPath) const
{
Expand Down Expand Up @@ -83,7 +115,9 @@ ChainParams ChainParams::loadConfig(
setOptionalU256Parameter(cp.minGasLimit, c_minGasLimit);
setOptionalU256Parameter(cp.maxGasLimit, c_maxGasLimit);
setOptionalU256Parameter(cp.gasLimitBoundDivisor, c_gasLimitBoundDivisor);

setOptionalU256Parameter(cp.homesteadForkBlock, c_homesteadForkBlock);
setOptionalU256Parameter(cp.daoHardforkBlock, c_daoHardforkBlock);
setOptionalU256Parameter(cp.EIP150ForkBlock, c_EIP150ForkBlock);
setOptionalU256Parameter(cp.EIP158ForkBlock, c_EIP158ForkBlock);
setOptionalU256Parameter(cp.byzantiumForkBlock, c_byzantiumForkBlock);
Expand All @@ -92,8 +126,11 @@ ChainParams ChainParams::loadConfig(
setOptionalU256Parameter(cp.constantinopleFixForkBlock, c_constantinopleFixForkBlock);
setOptionalU256Parameter(cp.istanbulForkBlock, c_istanbulForkBlock);
setOptionalU256Parameter(cp.berlinForkBlock, c_berlinForkBlock);
setOptionalU256Parameter(cp.daoHardforkBlock, c_daoHardforkBlock);
setOptionalU256Parameter(cp.experimentalForkBlock, c_experimentalForkBlock);

cp.lastForkBlock = findMaxForkBlockNumber(params);
cp.lastForkWithAdditionalEIPsSchedule = cp.forkScheduleForBlockNumber(cp.lastForkBlock);

setOptionalU256Parameter(cp.minimumDifficulty, c_minimumDifficulty);
setOptionalU256Parameter(cp.difficultyBoundDivisor, c_difficultyBoundDivisor);
setOptionalU256Parameter(cp.durationLimit, c_durationLimit);
Expand Down
15 changes: 12 additions & 3 deletions libethereum/ChainParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,18 @@ struct ChainParams: public ChainOperationParams
{
ChainParams();
ChainParams(ChainParams const& /*_org*/) = default;
ChainParams(std::string const& _s, h256 const& _stateRoot = h256());
ChainParams(bytes const& _genesisRLP, AccountMap const& _state) { populateFromGenesis(_genesisRLP, _state); }
ChainParams(std::string const& _json, bytes const& _genesisRLP, AccountMap const& _state): ChainParams(_json) { populateFromGenesis(_genesisRLP, _state); }
ChainParams(std::string const& _configJson, h256 const& _stateRoot = h256());
/// params with additional EIPs activated on top of the last fork block
ChainParams(std::string const& _configJson, AdditionalEIPs const& _additionalEIPs);
ChainParams(bytes const& _genesisRLP, AccountMap const& _state)
{
populateFromGenesis(_genesisRLP, _state);
}
ChainParams(std::string const& _json, bytes const& _genesisRLP, AccountMap const& _state)
: ChainParams(_json)
{
populateFromGenesis(_genesisRLP, _state);
}

SealEngineFace* createSealEngine();

Expand Down
9 changes: 5 additions & 4 deletions libethereum/Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@

#pragma once

#include "BlockDetails.h"
#include "GasPricer.h"
#include "LogFilter.h"
#include "Transaction.h"
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/Guards.h>
#include <libdevcrypto/Common.h>
#include <libethcore/EVMSchedule.h>
#include <libethcore/SealEngine.h>
#include "GasPricer.h"
#include "LogFilter.h"
#include "Transaction.h"
#include "BlockDetails.h"

namespace dev
{
Expand Down
1 change: 1 addition & 0 deletions libethereum/ValidationSchemes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ string const c_shouldnotexist = "shouldnotexist";
string const c_minGasLimit = "minGasLimit";
string const c_maxGasLimit = "maxGasLimit";
string const c_gasLimitBoundDivisor = "gasLimitBoundDivisor";
string const c_forkBlockSuffix = "ForkBlock";
string const c_homesteadForkBlock = "homesteadForkBlock";
string const c_daoHardforkBlock = "daoHardforkBlock";
string const c_EIP150ForkBlock = "EIP150ForkBlock";
Expand Down
1 change: 1 addition & 0 deletions libethereum/ValidationSchemes.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern std::string const c_shouldnotexist;
extern std::string const c_minGasLimit;
extern std::string const c_maxGasLimit;
extern std::string const c_gasLimitBoundDivisor;
extern std::string const c_forkBlockSuffix;
extern std::string const c_homesteadForkBlock;
extern std::string const c_daoHardforkBlock;
extern std::string const c_EIP150ForkBlock;
Expand Down
1 change: 1 addition & 0 deletions libevm/ExtVMFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <libethcore/BlockHeader.h>
#include <libethcore/ChainOperationParams.h>
#include <libethcore/Common.h>
#include <libethcore/EVMSchedule.h>
#include <libethcore/LogEntry.h>

#include <evmc/evmc.hpp>
Expand Down
15 changes: 8 additions & 7 deletions test/tools/jsontests/BlockChainTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,18 @@ json_spirit::mValue doBCTest(
if (_fillin)
{
BOOST_REQUIRE(inputTest.count("expect") > 0);
set<eth::Network> allnetworks = ImportTest::getAllNetworksFromExpectSections(
inputTest.at("expect").get_array(), ImportTest::testType::BlockchainTest);
set<std::string> allnetworks = ImportTest::getAllNetworksFromExpectSections(
inputTest.at("expect").get_array(), ImportTest::testType::BlockchainTest);

//create a blockchain test for each network
for (auto& network : allnetworks)
{
if (!Options::get().singleTestNet.empty() && Options::get().singleTestNet != test::netIdToString(network))
if (!Options::get().singleTestNet.empty() &&
Options::get().singleTestNet != network)
continue;

dev::test::TestBlockChain::s_sealEngineNetwork = network;
string newtestname = testname + "_" + test::netIdToString(network);
dev::test::TestBlockChain::s_sealEngineNetwork = stringToNetId(network);
string newtestname = testname + "_" + network;

json_spirit::mObject jObjOutput = inputTest;
// prepare the corresponding expect section for the test
Expand All @@ -92,7 +93,7 @@ json_spirit::mValue doBCTest(
json_spirit::mObject const& expectObj = expect.get_obj();
ImportTest::parseJsonStrValueIntoSet(expectObj.at("network"), netlist);
netlist = test::translateNetworks(netlist);
if (netlist.count(test::netIdToString(network)) || netlist.count("ALL"))
if (netlist.count(network) || netlist.count("ALL"))
{
jObjOutput["expect"] = expectObj.at("result");
found = true;
Expand All @@ -107,7 +108,7 @@ json_spirit::mValue doBCTest(

TestOutputHelper::get().setCurrentTestName(newtestname);
jObjOutput = fillBCTest(jObjOutput, _allowInvalidBlocks);
jObjOutput["network"] = test::netIdToString(network);
jObjOutput["network"] = network;
if (inputTest.count("_info"))
jObjOutput["_info"] = inputTest.at("_info");
tests[newtestname] = jObjOutput;
Expand Down
Loading