/* 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 . */ /** @file CachedAddressState.cpp * @author Gav Wood * @date 2014 */ #include "CachedAddressState.h" #include #include #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() : 0; } u256 CachedAddressState::nonce() const { return m_r ? m_s ? m_s->nonce() : m_r[0].toInt() : 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() : EmptySHA3; return h == EmptySHA3 ? bytes() : asBytes(m_o->lookup(h)); } std::map CachedAddressState::storage() const { std::map ret; if (m_r) { TrieDB memdb(const_cast(m_o), m_r[2].toHash()); // promise we won't alter the overlay! :) for (auto const& j: memdb) ret[j.first] = RLP(j.second).toInt(); } 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(exists(), _c.exists()); ret.balance = Diff(balance(), _c.balance()); ret.nonce = Diff(nonce(), _c.nonce()); ret.code = Diff(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(it->second, cit->second); else if (it != st.end() && (cit == cst.end() || it->first < cit->first) && it->second) ret.storage[it->first] = Diff(it->second, 0); else if (cit != cst.end() && (it == st.end() || it->first > cit->first) && cit->second) ret.storage[cit->first] = Diff(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; }