Browse Source

Better uncle building.

Repotting.
cl-refactor
Gav Wood 10 years ago
parent
commit
1078681ccb
  1. 5
      libethcore/BlockInfo.cpp
  2. 3
      libethcore/BlockInfo.h
  3. 77
      libethereum/AccountDiff.cpp
  4. 73
      libethereum/AccountDiff.h
  5. 83
      libethereum/State.cpp
  6. 41
      libethereum/State.h

5
libethcore/BlockInfo.cpp

@ -64,6 +64,11 @@ void BlockInfo::fillStream(RLPStream& _s, bool _nonce) const
_s << nonce;
}
h256 BlockInfo::headerHash(bytesConstRef _block)
{
return sha3(RLP(_block)[0].data());
}
void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
int field = 0;

3
libethcore/BlockInfo.h

@ -73,6 +73,9 @@ public:
explicit BlockInfo(bytes const& _block): BlockInfo(&_block) {}
explicit BlockInfo(bytesConstRef _block);
static h256 headerHash(bytes const& _block) { return headerHash(&_block); }
static h256 headerHash(bytesConstRef _block);
static BlockInfo fromHeader(bytesConstRef _block);
explicit operator bool() const { return timestamp != Invalid256; }

77
libethereum/AccountDiff.cpp

@ -0,0 +1,77 @@
/*
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 AccountDiff.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "AccountDiff.h"
#include <libethential/CommonIO.h>
using namespace std;
using namespace eth;
AccountChange AccountDiff::changeType() const
{
bool bn = (balance || nonce);
bool sc = (!storage.empty() || code);
return exist ? exist.from() ? AccountChange::Deletion : AccountChange::Creation : (bn && sc) ? AccountChange::All : bn ? AccountChange::Intrinsic: sc ? AccountChange::CodeStorage : AccountChange::None;
}
char const* AccountDiff::lead() const
{
bool bn = (balance || nonce);
bool sc = (!storage.empty() || code);
return exist ? exist.from() ? "XXX" : "+++" : (bn && sc) ? "***" : bn ? " * " : sc ? "* *" : " ";
}
std::ostream& eth::operator<<(std::ostream& _out, AccountDiff const& _s)
{
if (!_s.exist.to())
return _out;
if (_s.nonce)
{
_out << std::dec << "#" << _s.nonce.to() << " ";
if (_s.nonce.from())
_out << "(" << std::showpos << (((bigint)_s.nonce.to()) - ((bigint)_s.nonce.from())) << std::noshowpos << ") ";
}
if (_s.balance)
{
_out << std::dec << _s.balance.to() << " ";
if (_s.balance.from())
_out << "(" << std::showpos << (((bigint)_s.balance.to()) - ((bigint)_s.balance.from())) << std::noshowpos << ") ";
}
if (_s.code)
_out << "$" << std::hex << nouppercase << _s.code.to() << " (" << _s.code.from() << ") ";
for (pair<u256, Diff<u256>> const& i: _s.storage)
if (!i.second.from())
_out << endl << " + " << (h256)i.first << ": " << std::hex << nouppercase << i.second.to();
else if (!i.second.to())
_out << endl << "XXX " << (h256)i.first << " (" << std::hex << nouppercase << i.second.from() << ")";
else
_out << endl << " * " << (h256)i.first << ": " << std::hex << nouppercase << i.second.to() << " (" << i.second.from() << ")";
return _out;
}
std::ostream& eth::operator<<(std::ostream& _out, StateDiff const& _s)
{
_out << _s.accounts.size() << " accounts changed:" << endl;
for (auto const& i: _s.accounts)
_out << i.second.lead() << " " << i.first << ": " << i.second << endl;
return _out;
}

73
libethereum/AccountDiff.h

@ -0,0 +1,73 @@
/*
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 AccountDiff.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <libethential/Common.h>
#include <libethcore/CommonEth.h>
namespace eth
{
enum class ExistDiff { Same, New, Dead };
template <class T>
class Diff
{
public:
Diff() {}
Diff(T _from, T _to): m_from(_from), m_to(_to) {}
T const& from() const { return m_from; }
T const& to() const { return m_to; }
explicit operator bool() const { return m_from != m_to; }
private:
T m_from;
T m_to;
};
enum class AccountChange { None, Creation, Deletion, Intrinsic, CodeStorage, All };
struct AccountDiff
{
inline bool changed() const { return storage.size() || code || nonce || balance || exist; }
char const* lead() const;
AccountChange changeType() const;
Diff<bool> exist;
Diff<u256> balance;
Diff<u256> nonce;
std::map<u256, Diff<u256>> storage;
Diff<bytes> code;
};
struct StateDiff
{
std::map<Address, AccountDiff> accounts;
};
std::ostream& operator<<(std::ostream& _out, StateDiff const& _s);
std::ostream& operator<<(std::ostream& _out, AccountDiff const& _s);
}

83
libethereum/State.cpp

@ -567,9 +567,9 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce)
if (_bc)
{
BlockInfo uncleParent(_bc->block(uncle.parentHash));
if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6) // TODO: check 6. might be 7 or something...
if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6)
throw UncleTooOld();
if (knownUncles.count(uncle.hash))
if (knownUncles.count(sha3(i.data())))
throw UncleInChain();
uncle.verifyParent(uncleParent);
}
@ -699,19 +699,23 @@ void State::commitToMine(BlockChain const& _bc)
if (m_previousBlock != BlockChain::genesis())
{
// TODO: find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations.
// Find uncles if we're not a direct child of the genesis.
// Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations.
// cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl;
auto us = _bc.details(m_previousBlock.parentHash).children;
assert(us.size() >= 1); // must be at least 1 child of our grandparent - it's our own parent!
uncles.appendList(us.size() - 1); // one fewer - uncles precludes our parent from the list of grandparent's children.
for (auto const& u: us)
if (u != m_previousBlock.hash) // ignore our own parent - it's not an uncle.
{
BlockInfo ubi(_bc.block(u));
ubi.fillStream(uncles, true);
uncleAddresses.push_back(ubi.coinbaseAddress);
}
set<h256> knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash);
auto p = m_previousBlock.parentHash;
for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash(); ++gen, p = _bc.details(p).parent)
{
auto us = _bc.details(p).children;
assert(us.size() >= 1); // must be at least 1 child of our grandparent - it's our own parent!
uncles.appendList(us.size() - 1); // one fewer - uncles precludes our parent from the list of grandparent's children.
for (auto const& u: us)
if (!knownUncles.count(BlockInfo::headerHash(_bc.block(u)))) // ignore any uncles/mainline blocks that we know about. We use header-hash for this.
{
BlockInfo ubi(_bc.block(u));
ubi.fillStream(uncles, true);
uncleAddresses.push_back(ubi.coinbaseAddress);
}
}
}
else
uncles.appendList(0);
@ -1268,54 +1272,3 @@ std::ostream& eth::operator<<(std::ostream& _out, State const& _s)
}
return _out;
}
AccountChange AccountDiff::changeType() const
{
bool bn = (balance || nonce);
bool sc = (!storage.empty() || code);
return exist ? exist.from() ? AccountChange::Deletion : AccountChange::Creation : (bn && sc) ? AccountChange::All : bn ? AccountChange::Intrinsic: sc ? AccountChange::CodeStorage : AccountChange::None;
}
char const* AccountDiff::lead() const
{
bool bn = (balance || nonce);
bool sc = (!storage.empty() || code);
return exist ? exist.from() ? "XXX" : "+++" : (bn && sc) ? "***" : bn ? " * " : sc ? "* *" : " ";
}
std::ostream& eth::operator<<(std::ostream& _out, AccountDiff const& _s)
{
if (!_s.exist.to())
return _out;
if (_s.nonce)
{
_out << std::dec << "#" << _s.nonce.to() << " ";
if (_s.nonce.from())
_out << "(" << std::showpos << (((bigint)_s.nonce.to()) - ((bigint)_s.nonce.from())) << std::noshowpos << ") ";
}
if (_s.balance)
{
_out << std::dec << _s.balance.to() << " ";
if (_s.balance.from())
_out << "(" << std::showpos << (((bigint)_s.balance.to()) - ((bigint)_s.balance.from())) << std::noshowpos << ") ";
}
if (_s.code)
_out << "$" << std::hex << nouppercase << _s.code.to() << " (" << _s.code.from() << ") ";
for (pair<u256, Diff<u256>> const& i: _s.storage)
if (!i.second.from())
_out << endl << " + " << (h256)i.first << ": " << std::hex << nouppercase << i.second.to();
else if (!i.second.to())
_out << endl << "XXX " << (h256)i.first << " (" << std::hex << nouppercase << i.second.from() << ")";
else
_out << endl << " * " << (h256)i.first << ": " << std::hex << nouppercase << i.second.to() << " (" << i.second.from() << ")";
return _out;
}
std::ostream& eth::operator<<(std::ostream& _out, StateDiff const& _s)
{
_out << _s.accounts.size() << " accounts changed:" << endl;
for (auto const& i: _s.accounts)
_out << i.second.lead() << " " << i.first << ": " << i.second << endl;
return _out;
}

41
libethereum/State.h

@ -36,6 +36,7 @@
#include "AddressState.h"
#include "Transaction.h"
#include "Executive.h"
#include "AccountDiff.h"
namespace eth
{
@ -64,44 +65,6 @@ struct TransactionReceipt
Manifest changes;
};
enum class ExistDiff { Same, New, Dead };
template <class T>
class Diff
{
public:
Diff() {}
Diff(T _from, T _to): m_from(_from), m_to(_to) {}
T const& from() const { return m_from; }
T const& to() const { return m_to; }
explicit operator bool() const { return m_from != m_to; }
private:
T m_from;
T m_to;
};
enum class AccountChange { None, Creation, Deletion, Intrinsic, CodeStorage, All };
struct AccountDiff
{
inline bool changed() const { return storage.size() || code || nonce || balance || exist; }
char const* lead() const;
AccountChange changeType() const;
Diff<bool> exist;
Diff<u256> balance;
Diff<u256> nonce;
std::map<u256, Diff<u256>> storage;
Diff<bytes> code;
};
struct StateDiff
{
std::map<Address, AccountDiff> accounts;
};
/**
* @brief Model of the current state of the ledger.
* Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block).
@ -355,8 +318,6 @@ private:
};
std::ostream& operator<<(std::ostream& _out, State const& _s);
std::ostream& operator<<(std::ostream& _out, StateDiff const& _s);
std::ostream& operator<<(std::ostream& _out, AccountDiff const& _s);
template <class DB>
void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Address, DB>& _state)

Loading…
Cancel
Save