Browse Source

Draft of new LOG/bloom/headers/block format.

cl-refactor
Gav Wood 10 years ago
parent
commit
2c193627ed
  1. 19
      libdevcore/FixedHash.h
  2. 1
      libdevcrypto/SHA3.cpp
  3. 1
      libdevcrypto/SHA3.h
  4. 3
      libdevcrypto/TrieDB.cpp
  5. 1
      libdevcrypto/TrieDB.h
  6. 26
      libethcore/BlockInfo.cpp
  7. 11
      libethcore/BlockInfo.h
  8. 5
      libethereum/BlockChain.cpp
  9. 2
      libethereum/BlockDetails.h
  10. 2
      libethereum/Client.cpp
  11. 4
      libethereum/Executive.cpp
  12. 4
      libethereum/Manifest.cpp
  13. 2
      libethereum/Manifest.h
  14. 4
      libethereum/MessageFilter.cpp
  15. 2
      libethereum/MessageFilter.h
  16. 61
      libethereum/State.cpp
  17. 59
      libethereum/State.h
  18. 2
      libethereum/Transaction.cpp
  19. 8
      libethereum/Transaction.h
  20. 25
      libevm/ExtVMFace.h
  21. 17
      libevm/VM.h
  22. 4
      liblll/Assembly.cpp
  23. 6
      liblll/Assembly.h
  24. 2
      libwhisper/Common.cpp
  25. 2
      libwhisper/Common.h
  26. 6
      libwhisper/Message.h
  27. 4
      libwhisper/WhisperHost.cpp
  28. 2
      test/main.cpp

19
libdevcore/FixedHash.h

@ -158,6 +158,25 @@ public:
return ret; return ret;
} }
template <unsigned P, unsigned M> inline FixedHash& shiftBloom(FixedHash<M> const& _h) { return (*this |= _h.nbloom<P, N>()); }
template <unsigned P, unsigned M> inline FixedHash<M> nbloom() const
{
static const unsigned c_bloomBytes = (M + 7) / 8;
unsigned mask = (1 << c_bloomBytes) - 1;
FixedHash<M> ret;
byte const* p = data();
for (unsigned i = 0; i < P; ++i)
{
unsigned index = 0;
for (unsigned j = 0; j < c_bloomBytes; ++j, ++p)
index = (index << 8) | *p;
index &= mask;
ret[N - 1 - index / 8] |= (1 << (index % 8));
}
return ret;
}
/// Returns the index of the first bit set to one, or size() * 8 if no bits are set. /// Returns the index of the first bit set to one, or size() * 8 if no bits are set.
inline unsigned firstBitSet() const inline unsigned firstBitSet() const
{ {

1
libdevcrypto/SHA3.cpp

@ -30,7 +30,6 @@ namespace dev
{ {
h256 EmptySHA3 = sha3(bytesConstRef()); h256 EmptySHA3 = sha3(bytesConstRef());
h256 ZeroRLPSHA3 = sha3(rlp(bytesConstRef()));
std::string sha3(std::string const& _input, bool _hex) std::string sha3(std::string const& _input, bool _hex)
{ {

1
libdevcrypto/SHA3.h

@ -57,7 +57,6 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu
inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
extern h256 EmptySHA3; extern h256 EmptySHA3;
extern h256 ZeroRLPSHA3;
// Other crypto convenience routines // Other crypto convenience routines

3
libdevcrypto/TrieDB.cpp

@ -26,6 +26,7 @@ using namespace dev;
#if !ETH_LANGUAGES #if !ETH_LANGUAGES
const h256 dev::c_shaNull = sha3(rlp("")); h256 const dev::c_shaNull = sha3(rlp(""));
h256 const dev::EmptyTrie = c_shaNull;
#endif #endif

1
libdevcrypto/TrieDB.h

@ -45,6 +45,7 @@ struct TrieDBChannel: public LogChannel { static const char* name() { return "-
struct InvalidTrie: virtual dev::Exception {}; struct InvalidTrie: virtual dev::Exception {};
extern const h256 c_shaNull; extern const h256 c_shaNull;
extern const h256 EmptyTrie;
/** /**
* @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree.

26
libethcore/BlockInfo.cpp

@ -52,16 +52,16 @@ BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
h256 BlockInfo::headerHashWithoutNonce() const h256 BlockInfo::headerHashWithoutNonce() const
{ {
RLPStream s; RLPStream s;
fillStream(s, false); streamRLP(s, false);
return sha3(s.out()); return sha3(s.out());
} }
auto static const c_sha3EmptyList = sha3(RLPEmptyList); auto static const c_sha3EmptyList = sha3(RLPEmptyList);
void BlockInfo::fillStream(RLPStream& _s, bool _nonce) const void BlockInfo::streamRLP(RLPStream& _s, bool _nonce) const
{ {
_s.appendList(_nonce ? 13 : 12) _s.appendList(_nonce ? 15 : 14)
<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
<< difficulty << number << minGasPrice << gasLimit << gasUsed << timestamp << extraData; << difficulty << number << minGasPrice << gasLimit << gasUsed << timestamp << extraData;
if (_nonce) if (_nonce)
_s << nonce; _s << nonce;
@ -84,14 +84,16 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
coinbaseAddress = _header[field = 2].toHash<Address>(); coinbaseAddress = _header[field = 2].toHash<Address>();
stateRoot = _header[field = 3].toHash<h256>(); stateRoot = _header[field = 3].toHash<h256>();
transactionsRoot = _header[field = 4].toHash<h256>(); transactionsRoot = _header[field = 4].toHash<h256>();
difficulty = _header[field = 5].toInt<u256>(); receiptsRoot = _header[field = 5].toHash<h256>();
number = _header[field = 6].toInt<u256>(); logBloom = _header[field = 6].toHash<h512>();
minGasPrice = _header[field = 7].toInt<u256>(); difficulty = _header[field = 7].toInt<u256>();
gasLimit = _header[field = 8].toInt<u256>(); number = _header[field = 8].toInt<u256>();
gasUsed = _header[field = 9].toInt<u256>(); minGasPrice = _header[field = 9].toInt<u256>();
timestamp = _header[field = 10].toInt<u256>(); gasLimit = _header[field = 10].toInt<u256>();
extraData = _header[field = 11].toBytes(); gasUsed = _header[field = 11].toInt<u256>();
nonce = _header[field = 12].toHash<h256>(); timestamp = _header[field = 12].toInt<u256>();
extraData = _header[field = 13].toBytes();
nonce = _header[field = 14].toHash<h256>();
} }
catch (Exception & _e) catch (Exception & _e)

11
libethcore/BlockInfo.h

@ -47,7 +47,7 @@ extern u256 c_genesisDifficulty;
* corresponding RLP block created with createGenesisBlock(). * corresponding RLP block created with createGenesisBlock().
* *
* The difficulty and gas-limit derivations may be calculated with the calculateDifficulty() * The difficulty and gas-limit derivations may be calculated with the calculateDifficulty()
* and calculateGasLimit() and the object serialised to RLP with fillStream. To determine the * and calculateGasLimit() and the object serialised to RLP with streamRLP. To determine the
* header hash without the nonce (for mining), the method headerHashWithoutNonce() is provided. * header hash without the nonce (for mining), the method headerHashWithoutNonce() is provided.
* *
* The default constructor creates an empty object, which can be tested against with the boolean * The default constructor creates an empty object, which can be tested against with the boolean
@ -62,6 +62,8 @@ public:
Address coinbaseAddress; Address coinbaseAddress;
h256 stateRoot; h256 stateRoot;
h256 transactionsRoot; h256 transactionsRoot;
h256 receiptsRoot;
h512 logBloom; // TODO LogBloom - get include
u256 difficulty; u256 difficulty;
u256 number; u256 number;
u256 minGasPrice; u256 minGasPrice;
@ -89,6 +91,8 @@ public:
coinbaseAddress == _cmp.coinbaseAddress && coinbaseAddress == _cmp.coinbaseAddress &&
stateRoot == _cmp.stateRoot && stateRoot == _cmp.stateRoot &&
transactionsRoot == _cmp.transactionsRoot && transactionsRoot == _cmp.transactionsRoot &&
receiptsRoot == _cmp.receiptsRoot &&
logBloom == _cmp.logBloom &&
difficulty == _cmp.difficulty && difficulty == _cmp.difficulty &&
number == _cmp.number && number == _cmp.number &&
minGasPrice == _cmp.minGasPrice && minGasPrice == _cmp.minGasPrice &&
@ -112,13 +116,14 @@ public:
/// No-nonce sha3 of the header only. /// No-nonce sha3 of the header only.
h256 headerHashWithoutNonce() const; h256 headerHashWithoutNonce() const;
void fillStream(RLPStream& _s, bool _nonce) const; void streamRLP(RLPStream& _s, bool _nonce) const;
}; };
inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi) inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)
{ {
_out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " << _out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " <<
_bi.difficulty << " " << _bi.number << " " << _bi.minGasPrice << " " << _bi.gasLimit << " " << _bi.gasUsed << " " << _bi.timestamp << " " << _bi.nonce; _bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.minGasPrice << " " << _bi.gasLimit << " " <<
_bi.gasUsed << " " << _bi.timestamp << " " << _bi.nonce;
return _out; return _out;
} }

5
libethereum/BlockChain.cpp

@ -102,7 +102,8 @@ bytes BlockChain::createGenesisBlock()
} }
block.appendList(13) block.appendList(13)
<< h256() << c_shaNull << h160() << stateRoot << c_shaNull << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42)); // TODO: maybe make logbloom correct?
<< h256() << EmptySHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42));
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
return block.out(); return block.out();
@ -305,7 +306,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
// Get total difficulty increase and update state, checking it. // Get total difficulty increase and update state, checking it.
State s(bi.coinbaseAddress, _db); State s(bi.coinbaseAddress, _db);
auto tdIncrease = s.enactOn(&_block, bi, *this); auto tdIncrease = s.enactOn(&_block, bi, *this);
auto b = s.bloom(); auto b = s.oldBloom();
BlockBlooms bb; BlockBlooms bb;
BlockTraces bt; BlockTraces bt;
for (unsigned i = 0; i < s.pending().size(); ++i) for (unsigned i = 0; i < s.pending().size(); ++i)

2
libethereum/BlockDetails.h

@ -66,7 +66,7 @@ struct BlockTraces
{ {
BlockTraces() {} BlockTraces() {}
BlockTraces(RLP const& _r) { for (auto const& i: _r) traces.emplace_back(i.data()); } BlockTraces(RLP const& _r) { for (auto const& i: _r) traces.emplace_back(i.data()); }
bytes rlp() const { RLPStream s(traces.size()); for (auto const& i: traces) i.streamOut(s); return s.out(); } bytes rlp() const { RLPStream s(traces.size()); for (auto const& i: traces) i.streamRLP(s); return s.out(); }
Manifests traces; Manifests traces;
}; };

2
libethereum/Client.cpp

@ -159,7 +159,7 @@ void Client::clearPending()
if (!m_postMine.pending().size()) if (!m_postMine.pending().size())
return; return;
for (unsigned i = 0; i < m_postMine.pending().size(); ++i) for (unsigned i = 0; i < m_postMine.pending().size(); ++i)
appendFromNewPending(m_postMine.bloom(i), changeds); appendFromNewPending(m_postMine.oldBloom(i), changeds);
changeds.insert(PendingChangedFilter); changeds.insert(PendingChangedFilter);
m_postMine = m_preMine; m_postMine = m_preMine;
} }

4
libethereum/Executive.cpp

@ -123,7 +123,11 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms); m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms);
} }
else else
{
m_endGas = _gas; m_endGas = _gas;
if (m_ext)
m_ext->sub.logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes()));
}
return !m_ext; return !m_ext;
} }

4
libethereum/Manifest.cpp

@ -37,10 +37,10 @@ Manifest::Manifest(bytesConstRef _r)
internal.emplace_back(i.data()); internal.emplace_back(i.data());
} }
void Manifest::streamOut(RLPStream& _s) const void Manifest::streamRLP(RLPStream& _s) const
{ {
_s.appendList(7) << from << to << value << altered << input << output; _s.appendList(7) << from << to << value << altered << input << output;
_s.appendList(internal.size()); _s.appendList(internal.size());
for (auto const& i: internal) for (auto const& i: internal)
i.streamOut(_s); i.streamRLP(_s);
} }

2
libethereum/Manifest.h

@ -41,7 +41,7 @@ struct Manifest
{ {
Manifest() {} Manifest() {}
Manifest(bytesConstRef _r); Manifest(bytesConstRef _r);
void streamOut(RLPStream& _s) const; void streamRLP(RLPStream& _s) const;
h256 bloom() const { h256 ret = from.bloom() | to.bloom(); for (auto const& i: internal) ret |= i.bloom(); for (auto const& i: altered) ret |= h256(i).bloom(); return ret; } h256 bloom() const { h256 ret = from.bloom() | to.bloom(); for (auto const& i: internal) ret |= i.bloom(); for (auto const& i: altered) ret |= h256(i).bloom(); return ret; }

4
libethereum/MessageFilter.cpp

@ -27,7 +27,7 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
void MessageFilter::fillStream(RLPStream& _s) const void MessageFilter::streamRLP(RLPStream& _s) const
{ {
_s.appendList(8) << m_from << m_to << m_stateAltered << m_altered << m_earliest << m_latest << m_max << m_skip; _s.appendList(8) << m_from << m_to << m_stateAltered << m_altered << m_earliest << m_latest << m_max << m_skip;
} }
@ -35,7 +35,7 @@ void MessageFilter::fillStream(RLPStream& _s) const
h256 MessageFilter::sha3() const h256 MessageFilter::sha3() const
{ {
RLPStream s; RLPStream s;
fillStream(s); streamRLP(s);
return dev::sha3(s.out()); return dev::sha3(s.out());
} }

2
libethereum/MessageFilter.h

@ -39,7 +39,7 @@ class MessageFilter
public: public:
MessageFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} MessageFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {}
void fillStream(RLPStream& _s) const; void streamRLP(RLPStream& _s) const;
h256 sha3() const; h256 sha3() const;
int earliest() const { return m_earliest; } int earliest() const { return m_earliest; }

61
libethereum/State.cpp

@ -161,6 +161,7 @@ State::State(State const& _s):
m_db(_s.m_db), m_db(_s.m_db),
m_state(&m_db, _s.m_state.root()), m_state(&m_db, _s.m_state.root()),
m_transactions(_s.m_transactions), m_transactions(_s.m_transactions),
m_receipts(_s.m_receipts),
m_transactionSet(_s.m_transactionSet), m_transactionSet(_s.m_transactionSet),
m_cache(_s.m_cache), m_cache(_s.m_cache),
m_previousBlock(_s.m_previousBlock), m_previousBlock(_s.m_previousBlock),
@ -192,6 +193,7 @@ State& State::operator=(State const& _s)
m_db = _s.m_db; m_db = _s.m_db;
m_state.open(&m_db, _s.m_state.root()); m_state.open(&m_db, _s.m_state.root());
m_transactions = _s.m_transactions; m_transactions = _s.m_transactions;
m_receipts = _s.m_receipts;
m_transactionSet = _s.m_transactionSet; m_transactionSet = _s.m_transactionSet;
m_cache = _s.m_cache; m_cache = _s.m_cache;
m_previousBlock = _s.m_previousBlock; m_previousBlock = _s.m_previousBlock;
@ -353,7 +355,7 @@ void State::ensureCached(std::map<Address, AddressState>& _cache, Address _a, bo
RLP state(stateBack); RLP state(stateBack);
AddressState s; AddressState s;
if (state.isNull()) if (state.isNull())
s = AddressState(0, 0, ZeroRLPSHA3, EmptySHA3); s = AddressState(0, 0, EmptyTrie, EmptySHA3);
else else
s = AddressState(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>()); s = AddressState(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>());
bool ok; bool ok;
@ -484,6 +486,7 @@ map<Address, u256> State::addresses() const
void State::resetCurrent() void State::resetCurrent()
{ {
m_transactions.clear(); m_transactions.clear();
m_receipts.clear();
m_transactionSet.clear(); m_transactionSet.clear();
m_cache.clear(); m_cache.clear();
m_currentBlock = BlockInfo(); m_currentBlock = BlockInfo();
@ -547,7 +550,7 @@ h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged)
{ {
uncommitToMine(); uncommitToMine();
execute(i.second); execute(i.second);
ret.push_back(m_transactions.back().changes.bloom()); ret.push_back(m_receipts.back().changes().bloom());
_tq.noteGood(i); _tq.noteGood(i);
++goodTxs; ++goodTxs;
} }
@ -713,7 +716,7 @@ void State::uncommitToMine()
if (!m_transactions.size()) if (!m_transactions.size())
m_state.setRoot(m_previousBlock.stateRoot); m_state.setRoot(m_previousBlock.stateRoot);
else else
m_state.setRoot(m_transactions[m_transactions.size() - 1].stateRoot); m_state.setRoot(m_receipts[m_receipts.size() - 1].stateRoot());
m_db = m_lastTx; m_db = m_lastTx;
paranoia("Uncommited to mine", true); paranoia("Uncommited to mine", true);
m_currentBlock.sha3Uncles = h256(); m_currentBlock.sha3Uncles = h256();
@ -730,7 +733,7 @@ bool State::amIJustParanoid(BlockChain const& _bc)
// Compile block: // Compile block:
RLPStream block; RLPStream block;
block.appendList(3); block.appendList(3);
m_currentBlock.fillStream(block, true); m_currentBlock.streamRLP(block, true);
block.appendRaw(m_currentTxs); block.appendRaw(m_currentTxs);
block.appendRaw(m_currentUncles); block.appendRaw(m_currentUncles);
@ -757,11 +760,20 @@ bool State::amIJustParanoid(BlockChain const& _bc)
return false; return false;
} }
h256 State::bloom() const h256 State::oldBloom() const
{ {
h256 ret = m_currentBlock.coinbaseAddress.bloom(); h256 ret = m_currentBlock.coinbaseAddress.bloom();
for (auto const& i: m_transactions) for (auto const& i: m_receipts)
ret |= i.changes.bloom(); ret |= i.changes().bloom();
return ret;
}
LogBloom State::logBloom() const
{
LogBloom ret;
ret.shiftBloom<3>(sha3(m_currentBlock.coinbaseAddress.ref()));
for (TransactionReceipt const& i: m_receipts)
ret |= i.bloom();
return ret; return ret;
} }
@ -797,7 +809,7 @@ void State::commitToMine(BlockChain const& _bc)
if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about. if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about.
{ {
BlockInfo ubi(_bc.block(u)); BlockInfo ubi(_bc.block(u));
ubi.fillStream(unclesData, true); ubi.streamRLP(unclesData, true);
++unclesCount; ++unclesCount;
uncleAddresses.push_back(ubi.coinbaseAddress); uncleAddresses.push_back(ubi.coinbaseAddress);
} }
@ -805,8 +817,8 @@ void State::commitToMine(BlockChain const& _bc)
} }
MemoryDB tm; MemoryDB tm;
GenericTrieDB<MemoryDB> transactionReceipts(&tm); GenericTrieDB<MemoryDB> receipts(&tm);
transactionReceipts.init(); receipts.init();
RLPStream txs; RLPStream txs;
txs.appendList(m_transactions.size()); txs.appendList(m_transactions.size());
@ -816,16 +828,20 @@ void State::commitToMine(BlockChain const& _bc)
RLPStream k; RLPStream k;
k << i; k << i;
RLPStream v; RLPStream v;
m_transactions[i].fillStream(v); m_receipts[i].streamRLP(v);
transactionReceipts.insert(&k.out(), &v.out()); receipts.insert(&k.out(), &v.out());
txs.appendRaw(v.out());
RLPStream txrlp;
m_transactions[i].streamRLP(txrlp);
txs.appendRaw(txrlp.out());
} }
txs.swapOut(m_currentTxs); txs.swapOut(m_currentTxs);
RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles);
m_currentBlock.transactionsRoot = transactionReceipts.root(); m_currentBlock.receiptsRoot = receipts.root();
m_currentBlock.logBloom = logBloom();
m_currentBlock.sha3Uncles = sha3(m_currentUncles); m_currentBlock.sha3Uncles = sha3(m_currentUncles);
// Apply rewards last of all. // Apply rewards last of all.
@ -865,7 +881,7 @@ void State::completeMine()
// Compile block: // Compile block:
RLPStream ret; RLPStream ret;
ret.appendList(3); ret.appendList(3);
m_currentBlock.fillStream(ret, true); m_currentBlock.streamRLP(ret, true);
ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentTxs);
ret.appendRaw(m_currentUncles); ret.appendRaw(m_currentUncles);
ret.swapOut(m_currentBytes); ret.swapOut(m_currentBytes);
@ -875,6 +891,7 @@ void State::completeMine()
// Quickly reset the transactions. // Quickly reset the transactions.
// TODO: Leave this in a better state than this limbo, or at least record that it's in limbo. // TODO: Leave this in a better state than this limbo, or at least record that it's in limbo.
m_transactions.clear(); m_transactions.clear();
m_receipts.clear();
m_transactionSet.clear(); m_transactionSet.clear();
m_lastTx = m_db; m_lastTx = m_db;
} }
@ -1114,7 +1131,8 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
// TODO: CHECK TRIE after level DB flush to make sure exactly the same. // TODO: CHECK TRIE after level DB flush to make sure exactly the same.
// Add to the user-originated transactions that we've executed. // Add to the user-originated transactions that we've executed.
m_transactions.push_back(TransactionReceipt(e.t(), rootHash(), startGasUsed + e.gasUsed(), ms, e.logs())); m_transactions.push_back(e.t());
m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs(), ms));
m_transactionSet.insert(e.t().sha3()); m_transactionSet.insert(e.t().sha3());
return e.gasUsed(); return e.gasUsed();
} }
@ -1185,6 +1203,12 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA
return !revert; return !revert;
} }
else
{
// non-contract call
if (o_sub)
o_sub->logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes()));
}
return true; return true;
} }
@ -1261,11 +1285,12 @@ State State::fromPending(unsigned _i) const
if (!_i) if (!_i)
ret.m_state.setRoot(m_previousBlock.stateRoot); ret.m_state.setRoot(m_previousBlock.stateRoot);
else else
ret.m_state.setRoot(m_transactions[_i - 1].stateRoot); ret.m_state.setRoot(m_receipts[_i - 1].stateRoot());
while (ret.m_transactions.size() > _i) while (ret.m_transactions.size() > _i)
{ {
ret.m_transactionSet.erase(ret.m_transactions.back().transaction.sha3()); ret.m_transactionSet.erase(ret.m_transactions.back().sha3());
ret.m_transactions.pop_back(); ret.m_transactions.pop_back();
ret.m_receipts.pop_back();
} }
return ret; return ret;
} }

59
libethereum/State.h

@ -52,26 +52,37 @@ struct StateChat: public LogChannel { static const char* name() { return "-S-";
struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; }; struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; };
struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; };
struct TransactionReceipt class TransactionReceipt
{ {
TransactionReceipt(Transaction const& _t, h256 _root, u256 _gasUsed, Manifest const& _ms, LogEntries const& _logs): transaction(_t), stateRoot(_root), gasUsed(_gasUsed), changes(_ms), logs(_logs) {} public:
TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries const& _log, Manifest const& _ms): m_stateRoot(_root), m_gasUsed(_gasUsed), m_bloom(eth::bloom(_log)), m_log(_log), m_changes(_ms) {}
Manifest const& changes() const { return m_changes; }
// Manifest const& changes() const { return changes; } h256 const& stateRoot() const { return m_stateRoot; }
u256 const& gasUsed() const { return m_gasUsed; }
LogBloom const& bloom() const { return m_bloom; }
LogEntries const& log() const { return m_log; }
void fillStream(RLPStream& _s) const void streamRLP(RLPStream& _s) const
{ {
_s.appendList(3); _s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom;
transaction.fillStream(_s); _s.appendList(m_log.size());
_s.append(stateRoot, false, true) << gasUsed; for (LogEntry const& l: m_log)
l.streamRLP(_s);
} }
Transaction transaction; private:
h256 stateRoot; h256 m_stateRoot;
u256 gasUsed; u256 m_gasUsed;
Manifest changes; LogBloom m_bloom;
LogEntries logs; LogEntries m_log;
Manifest m_changes; ///< TODO: PoC-7: KILL
}; };
using TransactionReceipts = std::vector<TransactionReceipt>;
struct PrecompiledAddress struct PrecompiledAddress
{ {
unsigned gas; unsigned gas;
@ -227,16 +238,25 @@ public:
h256 rootHash() const { return m_state.root(); } h256 rootHash() const { return m_state.root(); }
/// Get the list of pending transactions. /// Get the list of pending transactions.
Transactions pending() const { Transactions ret; for (auto const& t: m_transactions) ret.push_back(t.transaction); return ret; } Transactions const& pending() const { return m_transactions; }
/// Get the list of pending transactions. TODO: PoC-7: KILL
Manifest changesFromPending(unsigned _i) const { return m_receipts[_i].changes(); }
/// Get the bloom filter of all changes happened in the block. TODO: PoC-7: KILL
h256 oldBloom() const;
/// Get the bloom filter of a particular transaction that happened in the block. TODO: PoC-7: KILL
h256 oldBloom(unsigned _i) const { return m_receipts[_i].changes().bloom(); }
/// Get the list of pending transactions. /// Get the list of pending transactions.
Manifest changesFromPending(unsigned _i) const { return m_transactions[_i].changes; } LogEntries const& log(unsigned _i) const { return m_receipts[_i].log(); }
/// Get the bloom filter of all changes happened in the block. /// Get the bloom filter of all logs that happened in the block.
h256 bloom() const; LogBloom logBloom() const;
/// Get the bloom filter of a particular transaction that happened in the block. /// Get the bloom filter of a particular transaction that happened in the block.
h256 bloom(unsigned _i) const { return m_transactions[_i].changes.bloom(); } LogBloom const& logBloom(unsigned _i) const { return m_receipts[_i].bloom(); }
/// Get the State immediately after the given number of pending transactions have been applied. /// Get the State immediately after the given number of pending transactions have been applied.
/// If (_i == 0) returns the initial state of the block. /// If (_i == 0) returns the initial state of the block.
@ -305,14 +325,15 @@ private:
void refreshManifest(RLPStream* _txs = nullptr); void refreshManifest(RLPStream* _txs = nullptr);
/// @returns gas used by transactions thus far executed. /// @returns gas used by transactions thus far executed.
u256 gasUsed() const { return m_transactions.size() ? m_transactions.back().gasUsed : 0; } u256 gasUsed() const { return m_receipts.size() ? m_receipts.back().gasUsed() : 0; }
bool isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const; bool isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const;
void paranoia(std::string const& _when, bool _enforceRefs = false) const; void paranoia(std::string const& _when, bool _enforceRefs = false) const;
OverlayDB m_db; ///< Our overlay for the state tree. OverlayDB m_db; ///< Our overlay for the state tree.
TrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB. TrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB.
std::vector<TransactionReceipt> m_transactions; ///< The current list of transactions that we've included in the state. Transactions m_transactions; ///< The current list of transactions that we've included in the state.
TransactionReceipts m_receipts; ///< The corresponding list of transaction receipts.
std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state. std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state.
OverlayDB m_lastTx; OverlayDB m_lastTx;

2
libethereum/Transaction.cpp

@ -85,7 +85,7 @@ void Transaction::sign(Secret _priv)
vrs = *(SignatureStruct const*)&sig; vrs = *(SignatureStruct const*)&sig;
} }
void Transaction::fillStream(RLPStream& _s, bool _sig) const void Transaction::streamRLP(RLPStream& _s, bool _sig) const
{ {
_s.appendList((_sig ? 3 : 0) + 6); _s.appendList((_sig ? 3 : 0) + 6);
_s << nonce << gasPrice << gas; _s << nonce << gasPrice << gas;

8
libethereum/Transaction.h

@ -64,11 +64,11 @@ struct Transaction
static h256 kFromMessage(h256 _msg, h256 _priv); static h256 kFromMessage(h256 _msg, h256 _priv);
void fillStream(RLPStream& _s, bool _sig = true) const; void streamRLP(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); } bytes rlp(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); } std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); }
h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3(s.out()); } h256 sha3(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3Bytes(s.out()); } bytes sha3Bytes(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3Bytes(s.out()); }
private: private:
mutable Address m_sender; mutable Address m_sender;

25
libevm/ExtVMFace.h

@ -25,6 +25,8 @@
#include <functional> #include <functional>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h>
#include <libevmface/Instruction.h> #include <libevmface/Instruction.h>
#include <libethcore/CommonEth.h> #include <libethcore/CommonEth.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
@ -34,10 +36,25 @@ namespace dev
namespace eth namespace eth
{ {
using LogBloom = h512;
struct LogEntry struct LogEntry
{ {
LogEntry() {} LogEntry() {}
LogEntry(RLP const& _r) { from = (Address)_r[0]; topics = (h256s)_r[1]; data = (bytes)_r[2]; }
LogEntry(Address const& _f, h256s&& _ts, bytes&& _d): from(_f), topics(std::move(_ts)), data(std::move(_d)) {} LogEntry(Address const& _f, h256s&& _ts, bytes&& _d): from(_f), topics(std::move(_ts)), data(std::move(_d)) {}
void streamRLP(RLPStream& _s) const { _s.appendList(3) << from << topics << data; }
LogBloom bloom() const
{
LogBloom ret;
ret.shiftBloom<3, 32>(sha3(from.ref()));
for (auto t: topics)
ret.shiftBloom<3, 32>(sha3(t.ref()));
return ret;
}
Address from; Address from;
h256s topics; h256s topics;
bytes data; bytes data;
@ -45,6 +62,14 @@ struct LogEntry
using LogEntries = std::vector<LogEntry>; using LogEntries = std::vector<LogEntry>;
inline LogBloom bloom(LogEntries const& _logs)
{
LogBloom ret;
for (auto const& l: _logs)
ret |= l.bloom();
return ret;
}
struct SubState struct SubState
{ {
std::set<Address> suicides; ///< Any accounts that have suicided. std::set<Address> suicides; ///< Any accounts that have suicided.

17
libevm/VM.h

@ -703,7 +703,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::JUMPDEST: case Instruction::JUMPDEST:
break; break;
case Instruction::LOG0: /* case Instruction::LOG0:
_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break; break;
case Instruction::LOG1: case Instruction::LOG1:
@ -717,6 +717,21 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::LOG4: case Instruction::LOG4:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6])); _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6]));
break;*/
case Instruction::LOG0:
_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break;
case Instruction::LOG1:
_ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break;
case Instruction::LOG2:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break;
case Instruction::LOG3:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break;
case Instruction::LOG4:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break; break;
case Instruction::CREATE: case Instruction::CREATE:
{ {

4
liblll/Assembly.cpp

@ -147,7 +147,7 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i)
return _out; return _out;
} }
ostream& Assembly::streamOut(ostream& _out, string const& _prefix) const ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) const
{ {
_out << _prefix << ".code:" << endl; _out << _prefix << ".code:" << endl;
for (AssemblyItem const& i: m_items) for (AssemblyItem const& i: m_items)
@ -189,7 +189,7 @@ ostream& Assembly::streamOut(ostream& _out, string const& _prefix) const
for (auto const& i: m_subs) for (auto const& i: m_subs)
{ {
_out << _prefix << " " << hex << (unsigned)(u256)i.first << ": " << endl; _out << _prefix << " " << hex << (unsigned)(u256)i.first << ": " << endl;
i.second.streamOut(_out, _prefix + " "); i.second.streamRLP(_out, _prefix + " ");
} }
} }
return _out; return _out;

6
liblll/Assembly.h

@ -104,11 +104,11 @@ public:
void injectStart(AssemblyItem const& _i); void injectStart(AssemblyItem const& _i);
std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); } std::string out() const { std::stringstream ret; streamRLP(ret); return ret.str(); }
int deposit() const { return m_deposit; } int deposit() const { return m_deposit; }
bytes assemble() const; bytes assemble() const;
Assembly& optimise(bool _enable); Assembly& optimise(bool _enable);
std::ostream& streamOut(std::ostream& _out, std::string const& _prefix = "") const; std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "") const;
private: private:
void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
@ -127,7 +127,7 @@ private:
inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)
{ {
_a.streamOut(_out); _a.streamRLP(_out);
return _out; return _out;
} }

2
libwhisper/Common.cpp

@ -36,7 +36,7 @@ BuildTopic& BuildTopic::shiftBytes(bytes const& _b)
h256 TopicFilter::sha3() const h256 TopicFilter::sha3() const
{ {
RLPStream s; RLPStream s;
fillStream(s); streamRLP(s);
return dev::sha3(s.out()); return dev::sha3(s.out());
} }

2
libwhisper/Common.h

@ -92,7 +92,7 @@ public:
TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {} TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
TopicFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {} TopicFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
void fillStream(RLPStream& _s) const { _s << m_topicMasks; } void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
h256 sha3() const; h256 sha3() const;
bool matches(Envelope const& _m) const; bool matches(Envelope const& _m) const;

6
libwhisper/Message.h

@ -55,9 +55,9 @@ public:
operator bool() const { return !!m_expiry; } operator bool() const { return !!m_expiry; }
void streamOut(RLPStream& _s, bool _withNonce) const { _s.appendList(_withNonce ? 5 : 4) << m_expiry << m_ttl << m_topic << m_data; if (_withNonce) _s << m_nonce; } void streamRLP(RLPStream& _s, bool _withNonce) const { _s.appendList(_withNonce ? 5 : 4) << m_expiry << m_ttl << m_topic << m_data; if (_withNonce) _s << m_nonce; }
h256 sha3() const { RLPStream s; streamOut(s, true); return dev::sha3(s.out()); } h256 sha3() const { RLPStream s; streamRLP(s, true); return dev::sha3(s.out()); }
h256 sha3NoNonce() const { RLPStream s; streamOut(s, false); return dev::sha3(s.out()); } h256 sha3NoNonce() const { RLPStream s; streamRLP(s, false); return dev::sha3(s.out()); }
unsigned sent() const { return m_expiry - m_ttl; } unsigned sent() const { return m_expiry - m_ttl; }
unsigned expiry() const { return m_expiry; } unsigned expiry() const { return m_expiry; }

4
libwhisper/WhisperHost.cpp

@ -48,8 +48,8 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const
{ {
UpgradeGuard ll(l); UpgradeGuard ll(l);
auto const& m = m_messages.at(_m); auto const& m = m_messages.at(_m);
cnote << "streamOut: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data()); cnote << "streamRLP: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data());
m.streamOut(_s, true); m.streamRLP(_s, true);
} }
} }

2
test/main.cpp

@ -44,7 +44,7 @@ using namespace dev::eth;
BOOST_AUTO_TEST_CASE(basic_tests) BOOST_AUTO_TEST_CASE(basic_tests)
{ {
/* RLPStream s; /* RLPStream s;
BlockInfo::genesis().fillStream(s, false); BlockInfo::genesis().streamRLP(s, false);
std::cout << RLP(s.out()) << std::endl; std::cout << RLP(s.out()) << std::endl;
std::cout << toHex(s.out()) << std::endl; std::cout << toHex(s.out()) << std::endl;
std::cout << sha3(s.out()) << std::endl;*/ std::cout << sha3(s.out()) << std::endl;*/

Loading…
Cancel
Save