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

Commit

Permalink
Merge pull request #3381 from ethereum/eip158
Browse files Browse the repository at this point in the history
EIP 158 + 160 protocol update
  • Loading branch information
chriseth authored Nov 23, 2016
2 parents d50f7f7 + 8c40a2c commit f01958b
Show file tree
Hide file tree
Showing 69 changed files with 54,992 additions and 481 deletions.
18 changes: 15 additions & 3 deletions libethashseal/Ethash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ StringHashMap Ethash::jsInfo(BlockHeader const& _bi) const

EVMSchedule const& Ethash::evmSchedule(EnvInfo const& _envInfo) const
{
if (_envInfo.number() >= chainParams().u256Param("EIP150ForkBlock"))
if (_envInfo.number() >= chainParams().u256Param("EIP158ForkBlock"))
return EIP158Schedule;
else if (_envInfo.number() >= chainParams().u256Param("EIP150ForkBlock"))
return EIP150Schedule;
else if (_envInfo.number() >= chainParams().u256Param("homsteadForkBlock"))
return HomesteadSchedule;
Expand Down Expand Up @@ -165,8 +167,18 @@ void Ethash::verify(Strictness _s, BlockHeader const& _bi, BlockHeader const& _p

void Ethash::verifyTransaction(ImportRequirements::value _ir, TransactionBase const& _t, BlockHeader const& _bi) const
{
if (_ir & ImportRequirements::TransactionSignatures && _bi.number() >= chainParams().u256Param("homsteadForkBlock"))
_t.checkLowS();
if (_ir & ImportRequirements::TransactionSignatures)
{
if (_bi.number() >= chainParams().u256Param("homsteadForkBlock"))
_t.checkLowS();
if (_bi.number() >= chainParams().u256Param("EIP158ForkBlock"))
{
int chainID(chainParams().u256Param("chainID"));
_t.checkChainId(chainID);
}
else
_t.checkChainId(-4);
}
// Unneeded as it's checked again in Executive. Keep it here since tests assume it's checked.
if (_ir & ImportRequirements::TransactionBasic && _t.gasRequired(evmSchedule(EnvInfo(_bi))) > _t.gas())
BOOST_THROW_EXCEPTION(OutOfGasIntrinsic());
Expand Down
37 changes: 24 additions & 13 deletions libethashseal/GenesisInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ R"ETHEREUM(
"durationLimit": "0x08",
"blockReward": "0x14D1120D7B160000",
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
"networkID" : "0x0"
"networkID" : "0x00"
},
"genesis": {
"nonce": "0x000000000000002a",
Expand Down Expand Up @@ -88,7 +88,8 @@ R"ETHEREUM(
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar": "",
"networkID" : "0x2"
"networkID" : "0x02",
"chainID": "0x02"
},
"genesis": {
"nonce": "0x00006d6f7264656e",
Expand Down Expand Up @@ -120,6 +121,9 @@ R"E(
"homsteadForkBlock": "0xffffffffffffffff",
"daoHardforkBlock": "0xfffffffffffffff",
"EIP150ForkBlock": "0xfffffffffffffff",
"EIP158ForkBlock": "0xfffffffffffffff",
"networkID" : "0x01",
"chainID": "0x01",
"maximumExtraDataSize": "0x20",
"tieBreakingGas": false,
"minGasLimit": "0x1388",
Expand All @@ -129,8 +133,7 @@ R"E(
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"networkID" : "0x1"
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down Expand Up @@ -161,6 +164,9 @@ R"E(
"homsteadForkBlock": "0x05",
"daoHardforkBlock": "0x08",
"EIP150ForkBlock": "0x0a",
"EIP158ForkBlock": "0x0e",
"networkID" : "0x01",
"chainID": "0x01",
"maximumExtraDataSize": "0x20",
"tieBreakingGas": false,
"minGasLimit": "0x1388",
Expand All @@ -170,8 +176,7 @@ R"E(
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"networkID" : "0x1"
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down Expand Up @@ -202,6 +207,9 @@ R"E(
"maximumExtraDataSize": "0x20",
"daoHardforkBlock": "0x1d4c00",
"EIP150ForkBlock": "0x259518",
"EIP158ForkBlock": "0x28d138",
"networkID" : "0x01",
"chainID": "0x01",
"minGasLimit": "0x1388",
"maxGasLimit": "7fffffffffffffff",
"tieBreakingGas": false,
Expand All @@ -210,8 +218,7 @@ R"E(
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"networkID" : "0x1"
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down Expand Up @@ -240,8 +247,11 @@ R"E(
"params": {
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"daoHardforkBlock": "0xfffffff",
"daoHardforkBlock": "0xfffffffffffffff",
"EIP150ForkBlock": "0x00",
"EIP158ForkBlock": "0xfffffffffffffff",
"networkID" : "0x01",
"chainID": "0x01",
"minGasLimit": "0x1388",
"maxGasLimit": "7fffffffffffffff",
"tieBreakingGas": false,
Expand All @@ -250,8 +260,7 @@ R"E(
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"networkID" : "0x1"
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down Expand Up @@ -282,6 +291,9 @@ R"E(
"homsteadForkBlock": "0x118c30",
"daoHardforkBlock": "0x1d4c00",
"EIP150ForkBlock": "0xfffffffffffffff",
"EIP158ForkBlock": "0xfffffffffffffff",
"networkID" : "0x01",
"chainID": "0x01",
"maximumExtraDataSize": "0x20",
"tieBreakingGas": false,
"minGasLimit": "0x1388",
Expand All @@ -291,8 +303,7 @@ R"E(
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"networkID" : "0x1"
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down
44 changes: 40 additions & 4 deletions libethcore/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,20 @@ TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _check
BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction data RLP must be an array"));

m_data = rlp[field = 5].toBytes();
byte v = rlp[field = 6].toInt<byte>() - 27;

byte v = rlp[field = 6].toInt<byte>();
h256 r = rlp[field = 7].toInt<u256>();
h256 s = rlp[field = 8].toInt<u256>();

if (v > 36)
m_chainId = (v - 35) / 2;
else if (v == 27 || v == 28)
m_chainId = -4;
else
BOOST_THROW_EXCEPTION(InvalidSignature());

v = v - (m_chainId * 2 + 35);

if (rlp.itemCount() > 9)
BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP"));

Expand Down Expand Up @@ -116,19 +126,26 @@ void TransactionBase::sign(Secret const& _priv)
m_vrs = sigStruct;
}

void TransactionBase::streamRLP(RLPStream& _s, IncludeSignature _sig) const
void TransactionBase::streamRLP(RLPStream& _s, IncludeSignature _sig, bool _forEip155hash) const
{
if (m_type == NullTransaction)
return;
_s.appendList((_sig ? 3 : 0) + 6);

_s.appendList((_sig || _forEip155hash ? 3 : 0) + 6);
_s << m_nonce << m_gasPrice << m_gas;
if (m_type == MessageCall)
_s << m_receiveAddress;
else
_s << "";
_s << m_value << m_data;

if (_sig)
_s << (m_vrs.v + 27) << (u256)m_vrs.r << (u256)m_vrs.s;
{
int vOffset = m_chainId*2 + 35;
_s << (m_vrs.v + vOffset) << (u256)m_vrs.r << (u256)m_vrs.s;
}
else if (_forEip155hash)
_s << m_chainId << 0 << 0;
}

static const u256 c_secp256k1n("115792089237316195423570985008687907852837564279074904382605163141518161494337");
Expand All @@ -139,6 +156,12 @@ void TransactionBase::checkLowS() const
BOOST_THROW_EXCEPTION(InvalidSignature());
}

void TransactionBase::checkChainId(int chainId) const
{
if (m_chainId != chainId && m_chainId != -4)
BOOST_THROW_EXCEPTION(InvalidSignature());
}

bigint TransactionBase::gasRequired(bool _contractCreation, bytesConstRef _data, EVMSchedule const& _es, u256 const& _gas)
{
bigint ret = (_contractCreation ? _es.txCreateGas : _es.txGas) + _gas;
Expand All @@ -147,3 +170,16 @@ bigint TransactionBase::gasRequired(bool _contractCreation, bytesConstRef _data,
return ret;
}

h256 TransactionBase::sha3(IncludeSignature _sig) const
{
if (_sig == WithSignature && m_hashWith)
return m_hashWith;

RLPStream s;
streamRLP(s, _sig, m_chainId > 0 && _sig == WithoutSignature);

auto ret = dev::sha3(s.out());
if (_sig == WithSignature)
m_hashWith = ret;
return ret;
}
10 changes: 8 additions & 2 deletions libethcore/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ class TransactionBase
/// @throws InvalidSValue if the signature has an invalid S value.
void checkLowS() const;

/// @throws InvalidSValue if the chain id is neither -4 nor equal to @a chainId
/// Note that "-4" is the chain ID of the pre-155 rules, which should also be considered valid
/// after EIP155
void checkChainId(int chainId = -4) const;

/// @returns true if transaction is non-null.
explicit operator bool() const { return m_type != NullTransaction; }

Expand All @@ -99,13 +104,13 @@ class TransactionBase
bool isMessageCall() const { return m_type == MessageCall; }

/// Serialises this transaction to an RLPStream.
void streamRLP(RLPStream& _s, IncludeSignature _sig = WithSignature) const;
void streamRLP(RLPStream& _s, IncludeSignature _sig = WithSignature, bool _forEip155hash = false) const;

/// @returns the RLP serialisation of this transaction.
bytes rlp(IncludeSignature _sig = WithSignature) const { RLPStream s; streamRLP(s, _sig); return s.out(); }

/// @returns the SHA3 hash of the RLP serialisation of this transaction.
h256 sha3(IncludeSignature _sig = WithSignature) const { if (_sig == WithSignature && m_hashWith) return m_hashWith; RLPStream s; streamRLP(s, _sig); auto ret = dev::sha3(s.out()); if (_sig == WithSignature) m_hashWith = ret; return ret; }
h256 sha3(IncludeSignature _sig = WithSignature) const;

/// @returns the amount of ETH to be transferred by this (message-call) transaction, in Wei. Synonym for endowment().
u256 value() const { return m_value; }
Expand Down Expand Up @@ -169,6 +174,7 @@ class TransactionBase
u256 m_gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender.
int m_chainId = -4; ///< EIP155 value for calculating transaction hash https://github.com/ethereum/EIPs/issues/155

mutable h256 m_hashWith; ///< Cached hash of transaction with signature.
mutable Address m_sender; ///< Cached sender, determined from signature.
Expand Down
5 changes: 4 additions & 1 deletion libethereum/Account.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ class Account
/// @returns true if the account is unchanged from creation.
bool isDirty() const { return !m_isUnchanged; }

/// @returns true if the nonce, balance and code is zero / empty. Code is considered empty
/// during creation phase.
bool isEmpty() const { return nonce() == 0 && balance() == 0 && (isFreshCode() ? code().empty() : codeHash() == EmptySHA3); }

/// @returns the balance of this account. Can be altered in place.
u256& balance() { return m_balance; }
Expand All @@ -119,7 +122,7 @@ class Account
u256 const& balance() const { return m_balance; }

/// Increments the balance of this account by the given amount. It's a bigint, so can be negative.
void addBalance(bigint _i) { if (!_i) return; m_balance = (u256)((bigint)m_balance + _i); changed(); }
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); changed(); }

/// @returns the nonce of the account. Can be altered in place.
u256& nonce() { return m_nonce; }
Expand Down
9 changes: 6 additions & 3 deletions libethereum/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,9 @@ u256 Block::enact(VerifiedBlockRef const& _block, BlockChain const& _bc)
applyRewards(rewarded, _bc.chainParams().blockReward);

// Commit all cached state changes to the state trie.
bool removeEmptyAccounts = m_currentBlock.number() >= _bc.chainParams().u256Param("EIP158ForkBlock");
DEV_TIMED_ABOVE("commit", 500)
m_state.commit();
m_state.commit(removeEmptyAccounts ? State::CommitBehaviour::RemoveEmptyAccounts : State::CommitBehaviour::KeepEmptyAccounts);

// Hash the state trie and check against the state_root hash in m_currentBlock.
if (m_currentBlock.stateRoot() != m_previousBlock.stateRoot() && m_currentBlock.stateRoot() != rootHash())
Expand Down Expand Up @@ -688,7 +689,7 @@ void Block::performIrregularModifications()
Addresses allDAOs = childDaos();
for (Address const& dao: allDAOs)
m_state.transferBalance(dao, recipient, m_state.balance(dao));
m_state.commit();
m_state.commit(State::CommitBehaviour::KeepEmptyAccounts);
}
}

Expand Down Expand Up @@ -768,7 +769,9 @@ void Block::commitToSeal(BlockChain const& _bc, bytes const& _extraData)
applyRewards(uncleBlockHeaders, _bc.chainParams().blockReward);

// Commit any and all changes to the trie that are in the cache, then update the state root accordingly.
m_state.commit();
bool removeEmptyAccounts = m_currentBlock.number() >= _bc.chainParams().u256Param("EIP158ForkBlock");
DEV_TIMED_ABOVE("commit", 500)
m_state.commit(removeEmptyAccounts ? State::CommitBehaviour::RemoveEmptyAccounts : State::CommitBehaviour::KeepEmptyAccounts);

clog(StateDetail) << "Post-reward stateRoot:" << m_state.rootHash();
clog(StateDetail) << m_state;
Expand Down
7 changes: 5 additions & 2 deletions libethereum/Executive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
if (!_init.empty())
m_ext = make_shared<ExtVM>(m_s, m_envInfo, m_sealEngine, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, sha3(_init), m_depth);

m_s.createContract(m_newAddress);
bool incrementNonce = m_envInfo.number() >= m_sealEngine.chainParams().u256Param("EIP158ForkBlock");
m_s.createContract(m_newAddress, incrementNonce);
m_s.transferBalance(_sender, m_newAddress, _endowment);

if (_init.empty())
Expand Down Expand Up @@ -358,7 +359,9 @@ bool Executive::go(OnOpFunc const& _onOp)
m_res->gasForDeposit = m_gas;
m_res->depositSize = out.size();
}
if (out.size() * m_ext->evmSchedule().createDataGas <= m_gas)
if (out.size() > m_ext->evmSchedule().maxCodeSize)
BOOST_THROW_EXCEPTION(OutOfGas());
else if (out.size() * m_ext->evmSchedule().createDataGas <= m_gas)
{
if (m_res)
m_res->codeDeposit = CodeDeposit::Success;
Expand Down
8 changes: 7 additions & 1 deletion libethereum/ExtVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,13 @@ class ExtVM: public ExtVMFace
virtual u256 balance(Address _a) override final { return m_s.balance(_a); }

/// Does the account exist?
virtual bool exists(Address _a) override final { return m_s.addressInUse(_a); }
virtual bool exists(Address _a) override final
{
if (evmSchedule().emptinessIsNonexistence())
return m_s.accountNonemptyAndExisting(_a);
else
return m_s.addressInUse(_a);
}

/// Suicide the associated contract to the given address.
virtual void suicide(Address _a) override final
Expand Down
Loading

0 comments on commit f01958b

Please sign in to comment.