You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
3.0 KiB
102 lines
3.0 KiB
10 years ago
|
/*
|
||
|
This file is part of cpp-ethereum.
|
||
|
|
||
|
cpp-ethereum is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
cpp-ethereum is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
/** @file CachedAddressState.cpp
|
||
|
* @author Gav Wood <i@gavwood.com>
|
||
|
* @date 2014
|
||
|
*/
|
||
|
|
||
|
#include "CachedAddressState.h"
|
||
|
|
||
|
#include <libdevcrypto/Common.h>
|
||
|
#include <libdevcrypto/TrieDB.h>
|
||
|
#include "Account.h"
|
||
|
using namespace std;
|
||
|
using namespace dev;
|
||
|
using namespace dev::eth;
|
||
|
|
||
|
bool CachedAddressState::exists() const
|
||
|
{
|
||
|
return (m_r && (!m_s || m_s->isAlive())) || (m_s && m_s->isAlive());
|
||
|
}
|
||
|
|
||
|
u256 CachedAddressState::balance() const
|
||
|
{
|
||
|
return m_r ? m_s ? m_s->balance() : m_r[1].toInt<u256>() : 0;
|
||
|
}
|
||
|
|
||
|
u256 CachedAddressState::nonce() const
|
||
|
{
|
||
|
return m_r ? m_s ? m_s->nonce() : m_r[0].toInt<u256>() : 0;
|
||
|
}
|
||
|
|
||
|
bytes CachedAddressState::code() const
|
||
|
{
|
||
|
if (m_s && m_s->codeCacheValid())
|
||
|
return m_s->code();
|
||
|
h256 h = m_r ? m_s ? m_s->codeHash() : m_r[3].toHash<h256>() : EmptySHA3;
|
||
|
return h == EmptySHA3 ? bytes() : asBytes(m_o->lookup(h));
|
||
|
}
|
||
|
|
||
|
std::map<u256, u256> CachedAddressState::storage() const
|
||
|
{
|
||
|
std::map<u256, u256> ret;
|
||
|
if (m_r)
|
||
|
{
|
||
|
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(m_o), m_r[2].toHash<h256>()); // promise we won't alter the overlay! :)
|
||
|
for (auto const& j: memdb)
|
||
|
ret[j.first] = RLP(j.second).toInt<u256>();
|
||
|
}
|
||
|
if (m_s)
|
||
|
for (auto const& j: m_s->storageOverlay())
|
||
|
if ((!ret.count(j.first) && j.second) || (ret.count(j.first) && ret.at(j.first) != j.second))
|
||
|
ret[j.first] = j.second;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
AccountDiff CachedAddressState::diff(CachedAddressState const& _c)
|
||
|
{
|
||
|
AccountDiff ret;
|
||
|
ret.exist = Diff<bool>(exists(), _c.exists());
|
||
|
ret.balance = Diff<u256>(balance(), _c.balance());
|
||
|
ret.nonce = Diff<u256>(nonce(), _c.nonce());
|
||
|
ret.code = Diff<bytes>(code(), _c.code());
|
||
|
auto st = storage();
|
||
|
auto cst = _c.storage();
|
||
|
auto it = st.begin();
|
||
|
auto cit = cst.begin();
|
||
|
while (it != st.end() || cit != cst.end())
|
||
|
{
|
||
|
if (it != st.end() && cit != cst.end() && it->first == cit->first && (it->second || cit->second) && (it->second != cit->second))
|
||
|
ret.storage[it->first] = Diff<u256>(it->second, cit->second);
|
||
|
else if (it != st.end() && (cit == cst.end() || it->first < cit->first) && it->second)
|
||
|
ret.storage[it->first] = Diff<u256>(it->second, 0);
|
||
|
else if (cit != cst.end() && (it == st.end() || it->first > cit->first) && cit->second)
|
||
|
ret.storage[cit->first] = Diff<u256>(0, cit->second);
|
||
|
if (it == st.end())
|
||
|
++cit;
|
||
|
else if (cit == cst.end())
|
||
|
++it;
|
||
|
else if (it->first < cit->first)
|
||
|
++it;
|
||
|
else if (it->first > cit->first)
|
||
|
++cit;
|
||
|
else
|
||
|
++it, ++cit;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|