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

Reset code to empty in rollback #5641

Merged
merged 3 commits into from
Jun 27, 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
7 changes: 7 additions & 0 deletions libethereum/Account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ void Account::setCode(bytes&& _code)
m_codeHash = sha3(m_codeCache);
}

void Account::resetCode()
{
m_codeCache.clear();
m_hasNewCode = false;
m_codeHash = EmptySHA3;
}

u256 Account::originalStorageValue(u256 const& _key, OverlayDB const& _db) const
{
auto it = m_storageOriginal.find(_key);
Expand Down
3 changes: 3 additions & 0 deletions libethereum/Account.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class Account
/// Sets the code of the account. Used by "create" messages.
void setCode(bytes&& _code);

/// Reset the code set by previous setCode
void resetCode();

/// Specify to the object what the actual code is for the account. @a _code must have a SHA3
/// equal to codeHash().
void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); }
Expand Down
7 changes: 5 additions & 2 deletions libethereum/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,10 @@ bytes const& State::code(Address const& _addr) const

void State::setCode(Address const& _address, bytes&& _code)
{
m_changeLog.emplace_back(_address, code(_address));
// rollback assumes that overwriting of the code never happens
// (not allowed in contract creation logic in Executive)
assert(!addressHasCode(_address));
m_changeLog.emplace_back(Change::Code, _address);
m_cache[_address].setCode(std::move(_code));
}

Expand Down Expand Up @@ -583,7 +586,7 @@ void State::rollback(size_t _savepoint)
m_cache.erase(change.address);
break;
case Change::Code:
account.setCode(std::move(change.oldCode));
account.resetCode();
break;
case Change::Touch:
account.untouch();
Expand Down
7 changes: 0 additions & 7 deletions libethereum/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,11 @@ struct Change
Address address; ///< Changed account address.
u256 value; ///< Change value, e.g. balance, storage and nonce.
u256 key; ///< Storage key. Last because used only in one case.
bytes oldCode; ///< Code overwritten by CREATE, empty except in case of address collision.

/// Helper constructor to make change log update more readable.
Change(Kind _kind, Address const& _addr, u256 const& _value = 0):
kind(_kind), address(_addr), value(_value)
{
assert(_kind != Code); // For this the special constructor needs to be used.
}

/// Helper constructor especially for storage change log.
Expand All @@ -134,11 +132,6 @@ struct Change
Change(Address const& _addr, u256 const& _value):
kind(Nonce), address(_addr), value(_value)
{}

/// Helper constructor especially for new code change log.
Change(Address const& _addr, bytes const& _oldCode):
kind(Code), address(_addr), oldCode(_oldCode)
{}
};

using ChangeLog = std::vector<Change>;
Expand Down
14 changes: 14 additions & 0 deletions test/unittests/libethereum/StateUnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ BOOST_AUTO_TEST_CASE(LoadAccountCode)
));
}

BOOST_AUTO_TEST_CASE(RollbackSetCode)
{
Address addr{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"};
State s{0};
auto savepoint = s.savepoint();
s.createContract(addr);
uint8_t codeData[] = {'c', 'o', 'd', 'e'};
s.setCode(addr, {std::begin(codeData), std::end(codeData)});
s.rollback(savepoint);

BOOST_CHECK(!s.addressHasCode(addr));
BOOST_CHECK(!s.accountNonemptyAndExisting(addr));
}

class AddressRangeTestFixture : public TestOutputHelperFixture
{
public:
Expand Down