Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into mix_fix

cl-refactor
arkpar 10 years ago
parent
commit
f6456a702a
  1. 5
      libethash-cl/ethash_cl_miner.cpp
  2. 1
      libethash-cl/ethash_cl_miner.h
  3. 4
      libethereum/BlockChain.cpp
  4. 6
      libethereum/BlockChain.h
  5. 6
      libethereum/State.cpp
  6. 7
      libevmasm/CommonSubexpressionEliminator.cpp
  7. 51
      libevmasm/ControlFlowGraph.cpp
  8. 4
      libevmasm/ControlFlowGraph.h
  9. 10
      libevmasm/ExpressionClasses.cpp
  10. 6
      libevmasm/ExpressionClasses.h
  11. 92
      libevmasm/KnownState.cpp
  12. 19
      libevmasm/KnownState.h
  13. 6
      libp2p/Common.cpp
  14. 7
      libp2p/Common.h
  15. 12
      libp2p/Host.cpp
  16. 2
      libp2p/NodeTable.cpp
  17. 28
      libp2p/RLPxHandshake.cpp
  18. 6
      libsolidity/InterfaceHandler.cpp
  19. 2
      libsolidity/InterfaceHandler.h
  20. 35
      test/libethereum/blockchain.cpp
  21. 259
      test/libevm/VMTestsFiller/vmArithmeticTestFiller.json
  22. 7
      test/libevm/vm.cpp
  23. 45
      test/libsolidity/SolidityOptimizer.cpp

5
libethash-cl/ethash_cl_miner.cpp

@ -61,6 +61,11 @@ ethash_cl_miner::ethash_cl_miner()
{
}
ethash_cl_miner::~ethash_cl_miner()
{
finish();
}
std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId)
{
std::vector<cl::Platform> platforms;

1
libethash-cl/ethash_cl_miner.h

@ -30,6 +30,7 @@ public:
public:
ethash_cl_miner();
~ethash_cl_miner();
static unsigned get_num_platforms();
static unsigned get_num_devices(unsigned _platformId = 0);

4
libethereum/BlockChain.cpp

@ -981,13 +981,13 @@ vector<unsigned> BlockChain::withBlockBloom(LogBloom const& _b, unsigned _earlie
return ret;
}
h256Hash BlockChain::allUnclesFrom(h256 const& _parent) const
h256Hash BlockChain::allKinFrom(h256 const& _parent, unsigned _generations) const
{
// Get all uncles cited given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5).
h256 p = _parent;
h256Hash ret = { p };
// p and (details(p).parent: i == 5) is likely to be overkill, but can't hurt to be cautious.
for (unsigned i = 0; i < 6 && p != m_genesisHash; ++i, p = details(p).parent)
for (unsigned i = 0; i < _generations && p != m_genesisHash; ++i, p = details(p).parent)
{
ret.insert(details(p).parent);
auto b = block(p);

6
libethereum/BlockChain.h

@ -203,10 +203,10 @@ public:
/// Get the hash of the genesis block. Thread-safe.
h256 genesisHash() const { return m_genesisHash; }
/// Get all blocks not allowed as uncles given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5).
/// @returns set including the header-hash of every parent (including @a _parent) up to and including generation +5
/// Get all blocks not allowed as uncles given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + @a _generations).
/// @returns set including the header-hash of every parent (including @a _parent) up to and including generation + @a _generations
/// togther with all their quoted uncles.
h256Hash allUnclesFrom(h256 const& _parent) const;
h256Hash allKinFrom(h256 const& _parent, unsigned _generations) const;
/// Run through database and verify all blocks by reevaluating.
/// Will call _progress with the progress in this operation first param done, second total.

6
libethereum/State.cpp

@ -652,7 +652,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
BOOST_THROW_EXCEPTION(TooManyUncles());
vector<BlockInfo> rewarded;
h256Hash excluded = _bc.allUnclesFrom(m_currentBlock.parentHash);
h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6);
excluded.insert(m_currentBlock.hash());
for (auto const& i: rlp[2])
@ -816,14 +816,14 @@ void State::commitToMine(BlockChain const& _bc)
{
// 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;
h256Hash knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash);
h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6);
auto p = m_previousBlock.parentHash;
for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash() && unclesCount < 2; ++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!
for (auto const& u: us)
if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about.
if (!excluded.count(u)) // ignore any uncles/mainline blocks that we know about.
{
BlockInfo ubi(_bc.block(u));
ubi.streamRLP(unclesData, WithNonce);

7
libevmasm/CommonSubexpressionEliminator.cpp

@ -153,7 +153,9 @@ AssemblyItems CSECodeGenerator::generateCode(
assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, "");
if (m_classPositions[targetItem.second].count(targetItem.first))
continue;
SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation();
SourceLocation location;
if (m_expressionClasses.representative(targetItem.second).item)
location = m_expressionClasses.representative(targetItem.second).item->getLocation();
int position = classElementPosition(targetItem.second);
if (position < targetItem.first)
// it is already at its target, we need another copy
@ -197,7 +199,7 @@ void CSECodeGenerator::addDependencies(Id _c)
addDependencies(argument);
m_neededBy.insert(make_pair(argument, _c));
}
if (expr.item->type() == Operation && (
if (expr.item && expr.item->type() == Operation && (
expr.item->instruction() == Instruction::SLOAD ||
expr.item->instruction() == Instruction::MLOAD ||
expr.item->instruction() == Instruction::SHA3
@ -288,6 +290,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
OptimizerException,
"Sequence constrained operation requested out of sequence."
);
assertThrow(expr.item, OptimizerException, "Non-generated expression without item.");
vector<Id> const& arguments = expr.arguments;
for (Id arg: boost::adaptors::reverse(arguments))
generateClassElement(arg);

51
libevmasm/ControlFlowGraph.cpp

@ -24,6 +24,7 @@
#include <libevmasm/ControlFlowGraph.h>
#include <map>
#include <memory>
#include <algorithm>
#include <libevmasm/Exceptions.h>
#include <libevmasm/AssemblyItem.h>
#include <libevmasm/SemanticInformation.h>
@ -217,7 +218,6 @@ void ControlFlowGraph::gatherKnowledge()
// @todo actually we know that memory is filled with zeros at the beginning,
// we could make use of that.
KnownStatePointer emptyState = make_shared<KnownState>();
ExpressionClasses& expr = emptyState->expressionClasses();
bool unknownJumpEncountered = false;
vector<pair<BlockId, KnownStatePointer>> workQueue({make_pair(BlockId::initial(), emptyState->copy())});
@ -238,8 +238,6 @@ void ControlFlowGraph::gatherKnowledge()
}
block.startState = state->copy();
//@todo we might know the return address for the first pass, but not anymore for the second,
// -> store knowledge about tags as a union.
// Feed all items except for the final jump yet because it will erase the target tag.
unsigned pc = block.begin;
@ -254,22 +252,29 @@ void ControlFlowGraph::gatherKnowledge()
assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, "");
//@todo in the case of JUMPI, add knowledge about the condition to the state
// (for both values of the condition)
BlockId nextBlock = expressionClassToBlockId(
state->stackElement(state->stackHeight(), SourceLocation()),
expr
set<u256> tags = state->tagsInExpression(
state->stackElement(state->stackHeight(), SourceLocation())
);
state->feedItem(m_items.at(pc++));
if (nextBlock)
workQueue.push_back(make_pair(nextBlock, state->copy()));
else if (!unknownJumpEncountered)
if (tags.empty() || std::any_of(tags.begin(), tags.end(), [&](u256 const& _tag)
{
return !m_blocks.count(BlockId(_tag));
}))
{
// We do not know where this jump goes, so we have to reset the states of all
// JUMPDESTs.
unknownJumpEncountered = true;
for (auto const& it: m_blocks)
if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag)
workQueue.push_back(make_pair(it.first, emptyState->copy()));
if (!unknownJumpEncountered)
{
// We do not know the target of this jump, so we have to reset the states of all
// JUMPDESTs.
unknownJumpEncountered = true;
for (auto const& it: m_blocks)
if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag)
workQueue.push_back(make_pair(it.first, emptyState->copy()));
}
}
else
for (auto tag: tags)
workQueue.push_back(make_pair(BlockId(tag), state->copy()));
}
else if (block.begin <= pc && pc < block.end)
state->feedItem(m_items.at(pc++));
@ -329,7 +334,11 @@ BasicBlocks ControlFlowGraph::rebuildCode()
if (previousHandedOver && !pushes[blockId] && m_items[block.begin].type() == Tag)
++block.begin;
if (block.begin < block.end)
{
blocks.push_back(block);
blocks.back().startState->clearTagUnions();
blocks.back().endState->clearTagUnions();
}
previousHandedOver = (block.endType == BasicBlock::EndType::HANDOVER);
}
}
@ -337,18 +346,6 @@ BasicBlocks ControlFlowGraph::rebuildCode()
return blocks;
}
BlockId ControlFlowGraph::expressionClassToBlockId(
ExpressionClasses::Id _id,
ExpressionClasses& _exprClasses
)
{
ExpressionClasses::Expression expr = _exprClasses.representative(_id);
if (expr.item && expr.item->type() == PushTag)
return BlockId(expr.item->data());
else
return BlockId::invalid();
}
BlockId ControlFlowGraph::generateNewId()
{
BlockId id = BlockId(++m_lastUsedId);

4
libevmasm/ControlFlowGraph.h

@ -108,10 +108,6 @@ private:
void setPrevLinks();
BasicBlocks rebuildCode();
/// @returns the corresponding BlockId if _id is a pushed jump tag,
/// and an invalid BlockId otherwise.
BlockId expressionClassToBlockId(ExpressionClasses::Id _id, ExpressionClasses& _exprClasses);
BlockId generateNewId();
unsigned m_lastUsedId = 0;

10
libevmasm/ExpressionClasses.cpp

@ -82,6 +82,16 @@ ExpressionClasses::Id ExpressionClasses::find(
return exp.id;
}
ExpressionClasses::Id ExpressionClasses::newClass(SourceLocation const& _location)
{
Expression exp;
exp.id = m_representatives.size();
exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, _location));
m_representatives.push_back(exp);
m_expressions.insert(exp);
return exp.id;
}
bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
{
// Try to simplify "_a - _b" and return true iff the value is a non-zero constant.

6
libevmasm/ExpressionClasses.h

@ -52,7 +52,8 @@ public:
Id id;
AssemblyItem const* item = nullptr;
Ids arguments;
unsigned sequenceNumber; ///< Storage modification sequence, only used for SLOAD/SSTORE instructions.
/// Storage modification sequence, only used for storage and memory operations.
unsigned sequenceNumber = 0;
/// Behaves as if this was a tuple of (item->type(), item->data(), arguments, sequenceNumber).
bool operator<(Expression const& _other) const;
};
@ -73,6 +74,9 @@ public:
/// @returns the number of classes.
Id size() const { return m_representatives.size(); }
/// @returns the id of a new class which is different to all other classes.
Id newClass(SourceLocation const& _location);
/// @returns true if the values of the given classes are known to be different (on every input).
/// @note that this function might still return false for some different inputs.
bool knownToBeDifferent(Id _a, Id _b);

92
libevmasm/KnownState.cpp

@ -162,29 +162,41 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
/// Helper function for KnownState::reduceToCommonKnowledge, removes everything from
/// _this which is not in or not equal to the value in _other.
template <class _Mapping, class _KeyType> void intersect(
_Mapping& _this,
_Mapping const& _other,
function<_KeyType(_KeyType)> const& _keyTrans = [](_KeyType _k) { return _k; }
)
template <class _Mapping> void intersect(_Mapping& _this, _Mapping const& _other)
{
for (auto it = _this.begin(); it != _this.end();)
if (_other.count(_keyTrans(it->first)) && _other.at(_keyTrans(it->first)) == it->second)
if (_other.count(it->first) && _other.at(it->first) == it->second)
++it;
else
it = _this.erase(it);
}
template <class _Mapping> void intersect(_Mapping& _this, _Mapping const& _other)
{
intersect<_Mapping, ExpressionClasses::Id>(_this, _other, [](ExpressionClasses::Id _k) { return _k; });
}
void KnownState::reduceToCommonKnowledge(KnownState const& _other)
{
int stackDiff = m_stackHeight - _other.m_stackHeight;
function<int(int)> stackKeyTransform = [=](int _key) -> int { return _key - stackDiff; };
intersect(m_stackElements, _other.m_stackElements, stackKeyTransform);
for (auto it = m_stackElements.begin(); it != m_stackElements.end();)
if (_other.m_stackElements.count(it->first - stackDiff))
{
Id other = _other.m_stackElements.at(it->first - stackDiff);
if (it->second == other)
++it;
else
{
set<u256> theseTags = tagsInExpression(it->second);
set<u256> otherTags = tagsInExpression(other);
if (!theseTags.empty() && !otherTags.empty())
{
theseTags.insert(otherTags.begin(), otherTags.end());
it->second = tagUnion(theseTags);
++it;
}
else
it = m_stackElements.erase(it);
}
}
else
it = m_stackElements.erase(it);
// Use the smaller stack height. Essential to terminate in case of loops.
if (m_stackHeight > _other.m_stackHeight)
{
@ -201,10 +213,15 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other)
bool KnownState::operator==(const KnownState& _other) const
{
return m_storageContent == _other.m_storageContent &&
m_memoryContent == _other.m_memoryContent &&
m_stackHeight == _other.m_stackHeight &&
m_stackElements == _other.m_stackElements;
if (m_storageContent != _other.m_storageContent || m_memoryContent != _other.m_memoryContent)
return false;
int stackDiff = m_stackHeight - _other.m_stackHeight;
auto thisIt = m_stackElements.cbegin();
auto otherIt = _other.m_stackElements.cbegin();
for (; thisIt != m_stackElements.cend() && otherIt != _other.m_stackElements.cend(); ++thisIt, ++otherIt)
if (thisIt->first - stackDiff != otherIt->first || thisIt->second != otherIt->second)
return false;
return (thisIt == m_stackElements.cend() && otherIt == _other.m_stackElements.cend());
}
ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation const& _location)
@ -212,18 +229,17 @@ ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation
if (m_stackElements.count(_stackHeight))
return m_stackElements.at(_stackHeight);
// Stack element not found (not assigned yet), create new unknown equivalence class.
//@todo check that we do not infer incorrect equivalences when the stack is cleared partially
//in between.
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location);
return m_stackElements[_stackHeight] =
m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, _location));
}
ExpressionClasses::Id KnownState::initialStackElement(
int _stackHeight,
SourceLocation const& _location
)
void KnownState::clearTagUnions()
{
// This is a special assembly item that refers to elements pre-existing on the initial stack.
return m_expressionClasses->find(AssemblyItem(UndefinedItem, u256(_stackHeight), _location));
for (auto it = m_stackElements.begin(); it != m_stackElements.end();)
if (m_tagUnions.left.count(it->second))
it = m_stackElements.erase(it);
else
++it;
}
void KnownState::setStackElement(int _stackHeight, Id _class)
@ -352,3 +368,27 @@ KnownState::Id KnownState::applySha3(
return m_knownSha3Hashes[arguments] = v;
}
set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId)
{
if (m_tagUnions.left.count(_expressionId))
return m_tagUnions.left.at(_expressionId);
// Might be a tag, then return the set of itself.
ExpressionClasses::Expression expr = m_expressionClasses->representative(_expressionId);
if (expr.item && expr.item->type() == PushTag)
return set<u256>({expr.item->data()});
else
return set<u256>();
}
KnownState::Id KnownState::tagUnion(set<u256> _tags)
{
if (m_tagUnions.right.count(_tags))
return m_tagUnions.right.at(_tags);
else
{
Id id = m_expressionClasses->newClass(SourceLocation());
m_tagUnions.right.insert(make_pair(_tags, id));
return id;
}
}

19
libevmasm/KnownState.h

@ -29,6 +29,7 @@
#include <tuple>
#include <memory>
#include <ostream>
#include <boost/bimap.hpp>
#include <libdevcore/CommonIO.h>
#include <libdevcore/Exceptions.h>
#include <libevmasm/ExpressionClasses.h>
@ -107,15 +108,16 @@ public:
/// @returns true if the knowledge about the state of both objects is (known to be) equal.
bool operator==(KnownState const& _other) const;
///@todo the sequence numbers in two copies of this class should never be the same.
/// might be doable using two-dimensional sequence numbers, where the first value is incremented
/// for each copy
/// Retrieves the current equivalence class fo the given stack element (or generates a new
/// one if it does not exist yet).
Id stackElement(int _stackHeight, SourceLocation const& _location);
/// @returns the equivalence class id of the special initial stack element at the given height.
Id initialStackElement(int _stackHeight, SourceLocation const& _location);
/// @returns its set of tags if the given expression class is a known tag union; returns a set
/// containing the tag if it is a PushTag expression and the empty set otherwise.
std::set<u256> tagsInExpression(Id _expressionId);
/// During analysis, different tags on the stack are partially treated as the same class.
/// This removes such classes not to confuse later analyzers.
void clearTagUnions();
int stackHeight() const { return m_stackHeight; }
std::map<int, Id> const& stackElements() const { return m_stackElements; }
@ -142,6 +144,9 @@ private:
/// Finds or creates a new expression that applies the sha3 hash function to the contents in memory.
Id applySha3(Id _start, Id _length, SourceLocation const& _location);
/// @returns a new or already used Id representing the given set of tags.
Id tagUnion(std::set<u256> _tags);
/// Current stack height, can be negative.
int m_stackHeight = 0;
/// Current stack layout, mapping stack height -> equivalence class
@ -157,6 +162,8 @@ private:
std::map<std::vector<Id>, Id> m_knownSha3Hashes;
/// Structure containing the classes of equivalent expressions.
std::shared_ptr<ExpressionClasses> m_expressionClasses;
/// Container for unions of tags stored on the stack.
boost::bimap<Id, std::set<u256>> m_tagUnions;
};
}

6
libp2p/Common.cpp

@ -47,6 +47,9 @@ const char* NetTriviaDetail::name() { return EthYellow "N" EthCoal " 0"; }
const char* NetAllDetail::name() { return EthYellow "N" EthCoal " A"; }
const char* NetRight::name() { return EthYellow "N" EthGreen "->"; }
const char* NetLeft::name() { return EthYellow "N" EthNavy "<-"; }
const char* NetP2PWarn::name() { return EthYellow "N" EthRed " X"; }
const char* NetP2PNote::name() { return EthYellow "N" EthBlue " i"; }
const char* NetP2PConnect::name() { return EthYellow "N" EthYellow " C"; }
#else
const char* NetWarn::name() { return EthYellow "" EthRed ""; }
const char* NetImpolite::name() { return EthYellow "" EthRed " !"; }
@ -59,6 +62,9 @@ const char* NetTriviaDetail::name() { return EthYellow "⧎" EthCoal " ◍"; }
const char* NetAllDetail::name() { return EthYellow "" EthCoal ""; }
const char* NetRight::name() { return EthYellow "" EthGreen "▬▶"; }
const char* NetLeft::name() { return EthYellow "" EthNavy "◀▬"; }
const char* NetP2PWarn::name() { return EthYellow "" EthRed ""; }
const char* NetP2PNote::name() { return EthYellow "" EthBlue ""; }
const char* NetP2PConnect::name() { return EthYellow "" EthYellow ""; }
#endif
bool p2p::isPublicAddress(std::string const& _addressToCheck)

7
libp2p/Common.h

@ -78,8 +78,8 @@ struct InvalidHostIPAddress: virtual dev::Exception {};
struct NetWarn: public LogChannel { static const char* name(); static const int verbosity = 0; };
struct NetNote: public LogChannel { static const char* name(); static const int verbosity = 1; };
struct NetImpolite: public LogChannel { static const char* name(); static const int verbosity = 1; };
struct NetMessageSummary: public LogChannel { static const char* name(); static const int verbosity = 2; };
struct NetImpolite: public LogChannel { static const char* name(); static const int verbosity = 2; };
struct NetMessageSummary: public LogChannel { static const char* name(); static const int verbosity = 3; };
struct NetConnect: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NetMessageDetail: public LogChannel { static const char* name(); static const int verbosity = 5; };
struct NetTriviaSummary: public LogChannel { static const char* name(); static const int verbosity = 10; };
@ -87,6 +87,9 @@ struct NetTriviaDetail: public LogChannel { static const char* name(); static co
struct NetAllDetail: public LogChannel { static const char* name(); static const int verbosity = 13; };
struct NetRight: public LogChannel { static const char* name(); static const int verbosity = 14; };
struct NetLeft: public LogChannel { static const char* name(); static const int verbosity = 15; };
struct NetP2PWarn: public LogChannel { static const char* name(); static const int verbosity = 2; };
struct NetP2PNote: public LogChannel { static const char* name(); static const int verbosity = 6; };
struct NetP2PConnect: public LogChannel { static const char* name(); static const int verbosity = 10; };
enum PacketType
{

12
libp2p/Host.cpp

@ -244,7 +244,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io
m_sessions[_id] = ps;
}
clog(NetNote) << "p2p.host.peer.register" << _id;
clog(NetP2PNote) << "p2p.host.peer.register" << _id;
StructuredLogger::p2pConnected(_id.abridged(), ps->m_peer->endpoint, ps->m_peer->m_lastConnected, clientVersion, peerCount());
}
@ -252,7 +252,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
{
if (_e == NodeEntryAdded)
{
clog(NetNote) << "p2p.host.nodeTable.events.nodeEntryAdded " << _n;
clog(NetP2PNote) << "p2p.host.nodeTable.events.nodeEntryAdded " << _n;
// only add iff node is in node table
if (Node n = m_nodeTable->node(_n))
{
@ -268,7 +268,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
{
p.reset(new Peer(n));
m_peers[_n] = p;
clog(NetNote) << "p2p.host.peers.events.peerAdded " << _n << p->endpoint;
clog(NetP2PNote) << "p2p.host.peers.events.peerAdded " << _n << p->endpoint;
}
}
if (peerSlotsAvailable(Egress))
@ -277,7 +277,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
}
else if (_e == NodeEntryDropped)
{
clog(NetNote) << "p2p.host.nodeTable.events.NodeEntryDropped " << _n;
clog(NetP2PNote) << "p2p.host.nodeTable.events.NodeEntryDropped " << _n;
RecursiveGuard l(x_sessions);
m_peers.erase(_n);
}
@ -647,14 +647,14 @@ void Host::startedWorking()
runAcceptor();
}
else
clog(NetNote) << "p2p.start.notice id:" << id() << "TCP Listen port is invalid or unavailable.";
clog(NetP2PNote) << "p2p.start.notice id:" << id() << "TCP Listen port is invalid or unavailable.";
shared_ptr<NodeTable> nodeTable(new NodeTable(m_ioService, m_alias, NodeIPEndpoint(bi::address::from_string(listenAddress()), listenPort(), listenPort())));
nodeTable->setEventHandler(new HostNodeTableHandler(*this));
m_nodeTable = nodeTable;
restoreNetwork(&m_restoreNetwork);
clog(NetNote) << "p2p.started id:" << id();
clog(NetP2PNote) << "p2p.started id:" << id();
run(boost::system::error_code());
}

2
libp2p/NodeTable.cpp

@ -95,7 +95,7 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node, NodeRelation _relati
{
DEV_GUARDED(x_nodes)
clog(NodeTableConnect) << "Sending public key discovery Ping to" << (bi::udp::endpoint)_node.endpoint << "(Advertising:" << (bi::udp::endpoint)m_node.endpoint << ")";
DEV_GUARDED(x_pubkDiscoverPings);
DEV_GUARDED(x_pubkDiscoverPings)
m_pubkDiscoverPings[_node.endpoint.address] = std::chrono::steady_clock::now();
ping(_node.endpoint);
return move(shared_ptr<NodeEntry>());

28
libp2p/RLPxHandshake.cpp

@ -30,7 +30,7 @@ using namespace CryptoPP;
void RLPXHandshake::writeAuth()
{
clog(NetConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
bytesRef sig(&m_auth[0], Signature::size);
bytesRef hepubk(&m_auth[Signature::size], h256::size);
@ -56,7 +56,7 @@ void RLPXHandshake::writeAuth()
void RLPXHandshake::writeAck()
{
clog(NetConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
m_ack.resize(Public::size + h256::size + 1);
bytesRef epubk(&m_ack[0], Public::size);
bytesRef nonce(&m_ack[Public::size], h256::size);
@ -74,7 +74,7 @@ void RLPXHandshake::writeAck()
void RLPXHandshake::readAuth()
{
clog(NetConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
m_authCipher.resize(307);
auto self(shared_from_this());
ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
@ -95,13 +95,13 @@ void RLPXHandshake::readAuth()
m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);
if (sha3(m_remoteEphemeral) != *(h256*)hepubk.data())
clog(NetConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint();
transition();
}
else
{
clog(NetConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
m_nextState = Error;
transition();
}
@ -110,7 +110,7 @@ void RLPXHandshake::readAuth()
void RLPXHandshake::readAck()
{
clog(NetConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
m_ackCipher.resize(210);
auto self(shared_from_this());
ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
@ -125,7 +125,7 @@ void RLPXHandshake::readAck()
}
else
{
clog(NetConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
clog(NetP2PConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
m_nextState = Error;
transition();
}
@ -138,9 +138,9 @@ void RLPXHandshake::error()
auto connected = m_socket->isConnected();
if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
else
clog(NetConnect) << "Handshake Failed (Connection reset by peer)";
clog(NetP2PConnect) << "Handshake Failed (Connection reset by peer)";
m_socket->close();
if (m_io != nullptr)
@ -151,7 +151,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
{
if (_ech || m_nextState == Error || m_cancel)
{
clog(NetConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
clog(NetP2PConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
return error();
}
@ -175,7 +175,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
else if (m_nextState == WriteHello)
{
m_nextState = ReadHello;
clog(NetConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";
clog(NetP2PConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";
/// This pointer will be freed if there is an error otherwise
/// it will be passed to Host which will take ownership.
@ -220,7 +220,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
return;
}
clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";
clog(NetP2PNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";
/// check frame size
bytes& header = m_handshakeInBuffer;
@ -228,7 +228,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
if (frameSize > 1024)
{
// all future frames: 16777216
clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
clog(NetP2PWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
m_nextState = Error;
transition();
return;
@ -279,7 +279,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
if (!_ec)
{
if (!m_socket->remoteEndpoint().address().is_unspecified())
clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
cancel();
}
});

6
libsolidity/InterfaceHandler.cpp

@ -101,7 +101,7 @@ std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinitio
event["inputs"] = params;
abi.append(event);
}
return std::unique_ptr<std::string>(new std::string(m_writer.write(abi)));
return std::unique_ptr<std::string>(new std::string(Json::FastWriter().write(abi)));
}
unique_ptr<string> InterfaceHandler::getABISolidityInterface(ContractDefinition const& _contractDef)
@ -153,7 +153,7 @@ std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(ContractDefi
}
doc["methods"] = methods;
return std::unique_ptr<std::string>(new std::string(m_writer.write(doc)));
return std::unique_ptr<std::string>(new std::string(Json::FastWriter().write(doc)));
}
std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(ContractDefinition const& _contractDef)
@ -217,7 +217,7 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(ContractDefin
}
doc["methods"] = methods;
return std::unique_ptr<std::string>(new std::string(m_writer.write(doc)));
return std::unique_ptr<std::string>(new std::string(Json::FastWriter().write(doc)));
}
/* -- private -- */

2
libsolidity/InterfaceHandler.h

@ -108,8 +108,6 @@ private:
std::string const& _tag,
CommentOwner _owner);
Json::StyledWriter m_writer;
// internal state
DocTagType m_lastTag;
std::string m_notice;

35
test/libethereum/blockchain.cpp

@ -204,6 +204,20 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
blObj["transactions"] = writeTransactionsToJson(txList);
BlockInfo current_BlockHeader = state.info();
RLPStream uncleStream;
uncleStream.appendList(vBiUncles.size());
for (unsigned i = 0; i < vBiUncles.size(); ++i)
{
RLPStream uncleRlp;
vBiUncles[i].streamRLP(uncleRlp, WithNonce);
uncleStream.appendRaw(uncleRlp.out());
}
// update unclehash in case of invalid uncles
current_BlockHeader.sha3Uncles = sha3(uncleStream.out());
updatePoW(current_BlockHeader);
if (blObj.count("blockHeader"))
overwriteBlockHeader(current_BlockHeader, blObj);
@ -223,15 +237,6 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
txStream.appendRaw(txrlp.out());
}
RLPStream uncleStream;
uncleStream.appendList(vBiUncles.size());
for (unsigned i = 0; i < vBiUncles.size(); ++i)
{
RLPStream uncleRlp;
vBiUncles[i].streamRLP(uncleRlp, WithNonce);
uncleStream.appendRaw(uncleRlp.out());
}
RLPStream block2 = createFullBlockFromHeader(current_BlockHeader, txStream.out(), uncleStream.out());
blObj["rlp"] = toHex(block2.out(), 2, HexPrefix::Add);
@ -497,14 +502,20 @@ mArray importUncles(mObject const& blObj, vector<BlockInfo>& vBiUncles, vector<B
writeBlockHeaderToJson(uncleHeaderObj_pre, vBiUncles[vBiUncles.size()-1]);
aUncleList.push_back(uncleHeaderObj_pre);
vBiUncles.push_back(vBiUncles[vBiUncles.size()-1]);
uncleHeaderObj_pre = uncleHeaderObj;
continue;
}
if (uncleHeaderObj.count("sameAsBlock"))
{
writeBlockHeaderToJson(uncleHeaderObj_pre, vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
aUncleList.push_back(uncleHeaderObj_pre);
vBiUncles.push_back(vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
size_t number = (size_t)toInt(uncleHeaderObj["sameAsBlock"]);
uncleHeaderObj.erase("sameAsBlock");
BlockInfo currentUncle = vBiBlocks[number];
writeBlockHeaderToJson(uncleHeaderObj, currentUncle);
aUncleList.push_back(uncleHeaderObj);
vBiUncles.push_back(currentUncle);
uncleHeaderObj_pre = uncleHeaderObj;
continue;
}
string overwrite = "false";

259
test/libevm/VMTestsFiller/vmArithmeticTestFiller.json

@ -728,6 +728,41 @@
"gas" : "100000"
}
},
"divByZero_2": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x" : "0x00"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (+ (/ 13 0) 7)}",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"div1": {
"env" : {
@ -974,6 +1009,34 @@
}
},
"sdivByZero2": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (+ (SDIV (- 0 115792089237316195423570985008687907853269984665640564039457584007900129639935) 0) 1) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"sdiv0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
@ -1639,6 +1702,34 @@
}
},
"modByZero": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (- (% 3 0) 1) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"smod0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
@ -1873,7 +1964,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "100000"
}
},
@ -1912,6 +2003,104 @@
}
},
"smod8_byZero": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (- (SMOD (- 0 200) 0) 13)}",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"smod_i256min1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x" : "0x8000000000000000000000000000000000000000000000000000000000000000"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (SMOD (- 0 57896044618658097711785492504343953926634992332820282019728792003956564819968) (- 0 1) ) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"smod_i256min2": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x" : "0x8000000000000000000000000000000000000000000000000000000000000000"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (- (SMOD (- 0 57896044618658097711785492504343953926634992332820282019728792003956564819968) (- 0 1) ) 1) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"addmod0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
@ -2006,7 +2195,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "1000000"
}
},
@ -2104,7 +2293,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "1000000"
}
},
@ -2132,7 +2321,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "1000000"
}
},
@ -2416,6 +2605,34 @@
}
},
"addmodDivByZero3": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (- (ADDMOD 0 0 0) 1) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"mulmod0": {
"env" : {
@ -2546,7 +2763,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "1000000"
}
},
@ -2574,7 +2791,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "1000000"
}
},
@ -2602,7 +2819,7 @@
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
"gas" : "1000000"
}
},
@ -2921,6 +3138,34 @@
}
},
"mulmoddivByZero3": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ [[ 0 ]] (- 1 (MULMOD 0 0 0)) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"expXY": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

7
test/libevm/vm.cpp

@ -300,9 +300,14 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
{
for (auto& i: v.get_obj())
{
std::cout << " " << i.first << "\n";
mObject& o = i.second.get_obj();
if (test::Options::get().singleTest && test::Options::get().singleTestName != i.first)
{
o.clear();
continue;
}
std::cout << " " << i.first << "\n";
BOOST_REQUIRE(o.count("env") > 0);
BOOST_REQUIRE(o.count("pre") > 0);
BOOST_REQUIRE(o.count("exec") > 0);

45
test/libsolidity/SolidityOptimizer.cpp

@ -97,7 +97,7 @@ public:
{
eth::KnownState state;
for (auto const& item: addDummyLocations(_input))
state.feedItem(item);
state.feedItem(item, true);
return state;
}
@ -315,6 +315,49 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches)
BOOST_CHECK_EQUAL(1, numSHA3s);
}
BOOST_AUTO_TEST_CASE(store_tags_as_unions)
{
// This calls the same function from two sources and both calls have a certain sha3 on
// the stack at the same position.
// Without storing tags as unions, the return from the shared function would not know where to
// jump and thus all jumpdests are forced to clear their state and we do not know about the
// sha3 anymore.
// Note that, for now, this only works if the functions have the same number of return
// parameters since otherwise, the return jump addresses are at different stack positions
// which triggers the "unknown jump target" situation.
char const* sourceCode = R"(
contract test {
bytes32 data;
function f(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) {
r_d = sha3(y);
shared(y);
r_d = sha3(y);
r_a = 5;
}
function g(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) {
r_d = sha3(y);
shared(y);
r_d = bytes32(uint(sha3(y)) + 2);
r_a = 7;
}
function shared(bytes32 y) internal {
data = sha3(y);
}
}
)";
compileBothVersions(sourceCode);
compareVersions("f()", 7, "abc");
m_optimize = true;
bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test");
size_t numSHA3s = 0;
eth::eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
if (_instr == eth::Instruction::SHA3)
numSHA3s++;
});
BOOST_CHECK_EQUAL(2, numSHA3s);
}
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
{
eth::KnownState state;

Loading…
Cancel
Save