Browse Source

Merge branch 'develop' into libnatspec

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
2b68e9fe31
  1. 6
      CMakeLists.txt
  2. 4
      CodingStandards.txt
  3. 2
      alethzero/CMakeLists.txt
  4. 4
      alethzero/MainWin.cpp
  5. 2
      evmjit/libevmjit/Utils.h
  6. 9
      libdevcore/CommonData.h
  7. 2
      libethcore/BlockInfo.cpp
  8. 2
      libethcore/CommonEth.cpp
  9. 32
      libethereum/Client.cpp
  10. 7
      libethereum/Client.h
  11. 2
      libethereum/LogFilter.cpp
  12. 8
      libethereum/LogFilter.h
  13. 31
      libjsqrc/ethereumjs/dist/ethereum.js
  14. 4
      libjsqrc/ethereumjs/dist/ethereum.js.map
  15. 2
      libjsqrc/ethereumjs/dist/ethereum.min.js
  16. 31
      libjsqrc/ethereumjs/lib/providermanager.js
  17. 11
      libsolidity/AST.cpp
  18. 18
      libsolidity/AST.h
  19. 8
      libsolidity/Parser.cpp
  20. 6
      libsolidity/Token.h
  21. 30
      libsolidity/Types.cpp
  22. 6
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  23. 2
      mix/CMakeLists.txt
  24. 13
      mix/ClientModel.cpp
  25. 9
      mix/ClientModel.h
  26. 117
      mix/MixClient.cpp
  27. 7
      mix/MixClient.h
  28. 26
      mix/qml/DebugInfoList.qml
  29. 306
      mix/qml/Debugger.qml
  30. 3
      mix/qml/WebPreview.qml
  31. 7
      mix/qml/js/Debugger.js
  32. 1
      mix/qml/js/ProjectModel.js
  33. 2
      mix/qml/main.qml
  34. 13
      pysol/MANIFEST.in
  35. 0
      pysol/README.md
  36. 115
      pysol/pysolidity.cpp
  37. 41
      pysol/setup.py
  38. 2
      sc/CMakeLists.txt
  39. 70
      test/SolidityExpressionCompiler.cpp
  40. 19
      test/SolidityParser.cpp
  41. 9
      test/SolidityScanner.cpp
  42. 4
      third/CMakeLists.txt

6
CMakeLists.txt

@ -131,11 +131,15 @@ endif()
add_subdirectory(libdevcore)
add_subdirectory(libevmcore)
add_subdirectory(liblll)
add_subdirectory(libserpent)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
add_subdirectory(libserpent)
endif ()
add_subdirectory(libsolidity)
add_subdirectory(lllc)
add_subdirectory(solc)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
add_subdirectory(sc)
endif()
if (JSONRPC)
add_subdirectory(libweb3jsonrpc)

4
CodingStandards.txt

@ -93,7 +93,7 @@ b. Only one per line.
c. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)).
d. Favour declarations close to use; don't habitually declare at top of scope ala C.
e. Always pass non-trivial parameters with a const& suffix.
f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
f. If a func tion returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
g. Never use a macro where adequate non-preprocessor C++ can be written.
h. Prefer "using NewType = OldType" to "typedef OldType NewType".
@ -128,7 +128,7 @@ d. Use override, final and const judiciously.
e. No implementations with the class declaration, except:
- template or force-inline method (though prefer implementation at bottom of header file).
- one-line implementation (in which case include it in same line as declaration).
f. For a method 'foo'
f. For a property 'foo'
- Member: m_foo;
- Getter: foo() [ also: for booleans, isFoo() ];
- Setter: setFoo();

2
alethzero/CMakeLists.txt

@ -40,7 +40,9 @@ target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} secp256k1)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
target_link_libraries(${EXECUTABLE} serpent)
endif()
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} solidity)
target_link_libraries(${EXECUTABLE} evmcore)

4
alethzero/MainWin.cpp

@ -30,8 +30,10 @@
#include <QtCore/QtCore>
#include <boost/algorithm/string.hpp>
#include <test/JsonSpiritHeaders.h>
#ifndef _MSC_VER
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#endif
#include <libdevcrypto/FileSystem.h>
#include <libethcore/CommonJS.h>
#include <liblll/Compiler.h>
@ -1719,6 +1721,7 @@ void Main::on_data_textChanged()
solidity = "<h4>Solidity</h4><pre>Uncaught exception.</pre>";
}
}
#ifndef _MSC_VER
else if (sourceIsSerpent(src))
{
try
@ -1732,6 +1735,7 @@ void Main::on_data_textChanged()
errors.push_back("Serpent " + err);
}
}
#endif
else
{
m_data = compileLLL(src, m_enableOptimizer, &errors);

2
evmjit/libevmjit/Utils.h

@ -1,5 +1,7 @@
#pragma once
#include <iostream>
#include "Common.h"
namespace dev

9
libdevcore/CommonData.h

@ -246,4 +246,13 @@ inline std::set<_T> operator+(std::set<_T> const& _a, std::set<_T> const& _b)
/// Make normal string from fixed-length string.
std::string toString(string32 const& _s);
template<class T, class U>
std::vector<T> keysOf(std::map<T, U> const& _m)
{
std::vector<T> ret;
for (auto const& i: _m)
ret.push_back(i.first);
return ret;
}
}

2
libethcore/BlockInfo.cpp

@ -208,7 +208,7 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const
if (parentHash != _parent.hash)
BOOST_THROW_EXCEPTION(InvalidParentHash());
if (timestamp < _parent.timestamp)
if (timestamp <= _parent.timestamp)
BOOST_THROW_EXCEPTION(InvalidTimestamp());
if (number != _parent.number + 1)

2
libethcore/CommonEth.cpp

@ -32,7 +32,7 @@ namespace dev
namespace eth
{
const unsigned c_protocolVersion = 52;
const unsigned c_protocolVersion = 53;
const unsigned c_databaseVersion = 5;
static const vector<pair<u256, string>> g_units =

32
libethereum/Client.cpp

@ -223,13 +223,17 @@ void Client::uninstallWatch(unsigned _i)
auto fit = m_filters.find(id);
if (fit != m_filters.end())
if (!--fit->second.refCount)
{
cwatch << "*X*" << fit->first << ":" << fit->second.filter;
m_filters.erase(fit);
}
}
void Client::noteChanged(h256Set const& _filters)
{
Guard l(m_filterLock);
cnote << "noteChanged(" << _filters << ")";
if (_filters.size())
cnote << "noteChanged(" << _filters << ")";
// accrue all changes left in each filter into the watches.
for (auto& i: m_watches)
if (_filters.count(i.second.id))
@ -250,8 +254,11 @@ LocalisedLogEntries Client::peekWatch(unsigned _watchId) const
Guard l(m_filterLock);
try {
return m_watches.at(_watchId).changes;
auto& w = m_watches.at(_watchId);
w.lastPoll = chrono::system_clock::now();
return w.changes;
} catch (...) {}
return LocalisedLogEntries();
}
@ -261,7 +268,9 @@ LocalisedLogEntries Client::checkWatch(unsigned _watchId)
LocalisedLogEntries ret;
try {
std::swap(ret, m_watches.at(_watchId).changes);
auto& w = m_watches.at(_watchId);
std::swap(ret, w.changes);
w.lastPoll = chrono::system_clock::now();
} catch (...) {}
return ret;
@ -556,6 +565,23 @@ void Client::doWork()
cworkout << "WORK";
this_thread::sleep_for(chrono::milliseconds(100));
if (chrono::system_clock::now() - m_lastGarbageCollection > chrono::seconds(5))
{
// garbage collect on watches
vector<unsigned> toUninstall;
{
Guard l(m_filterLock);
for (auto key: keysOf(m_watches))
if (chrono::system_clock::now() - m_watches[key].lastPoll > chrono::seconds(20))
{
toUninstall.push_back(key);
cnote << "GC: Uninstall" << key << "(" << chrono::duration_cast<chrono::seconds>(chrono::system_clock::now() - m_watches[key].lastPoll).count() << "s old)";
}
}
for (auto i: toUninstall)
uninstallWatch(i);
m_lastGarbageCollection = chrono::system_clock::now();
}
}
unsigned Client::numberOf(int _n) const

7
libethereum/Client.h

@ -89,11 +89,12 @@ static const LocalisedLogEntry InitialChange(SpecialLogEntry, 0);
struct ClientWatch
{
ClientWatch() {}
explicit ClientWatch(h256 _id): id(_id) {}
ClientWatch(): lastPoll(std::chrono::system_clock::now()) {}
explicit ClientWatch(h256 _id): id(_id), lastPoll(std::chrono::system_clock::now()) {}
h256 id;
LocalisedLogEntries changes = LocalisedLogEntries{ InitialChange };
mutable std::chrono::system_clock::time_point lastPoll = std::chrono::system_clock::now();
};
struct WatchChannel: public LogChannel { static const char* name() { return "(o)"; } static const int verbosity = 7; };
@ -328,6 +329,8 @@ private:
mutable std::mutex m_filterLock;
std::map<h256, InstalledFilter> m_filters;
std::map<unsigned, ClientWatch> m_watches;
mutable std::chrono::system_clock::time_point m_lastGarbageCollection;
};
}

2
libethereum/LogFilter.cpp

@ -27,7 +27,7 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
std::ostream& dev::operator<<(std::ostream& _out, LogFilter const& _s)
std::ostream& dev::eth::operator<<(std::ostream& _out, LogFilter const& _s)
{
// TODO
_out << "(@" << _s.m_addresses << "#" << _s.m_topics << ">" << _s.m_earliest << "-" << _s.m_latest << "< +" << _s.m_skip << "^" << _s.m_max << ")";

8
libethereum/LogFilter.h

@ -34,12 +34,12 @@ namespace eth
class LogFilter;
}
/// Simple stream output for the StateDiff.
std::ostream& operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
namespace eth
{
/// Simple stream output for the StateDiff.
std::ostream& operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
class State;
class LogFilter
@ -65,7 +65,7 @@ public:
LogFilter withEarliest(int _e) { m_earliest = _e; return *this; }
LogFilter withLatest(int _e) { m_latest = _e; return *this; }
friend std::ostream& dev::operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
friend std::ostream& dev::eth::operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
private:
AddressSet m_addresses;

31
libjsqrc/ethereumjs/dist/ethereum.js

@ -1043,33 +1043,16 @@ var ProviderManager = function() {
var self = this;
var poll = function () {
if (self.provider) {
var pollsBatch = self.polls.map(function (data) {
return data.data;
});
var payload = jsonrpc.toBatchPayload(pollsBatch);
var results = self.provider.send(payload);
self.polls.forEach(function (data, index) {
var result = results[index];
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return;
}
result = result.result;
// dont call the callback if result is not an array, or empty one
if (!(result instanceof Array) || result.length === 0) {
return;
}
self.polls.forEach(function (data) {
var result = self.send(data.data);
data.callback(result);
if (!(result instanceof Array) || result.length === 0) {
return;
}
});
data.callback(result);
});
}
setTimeout(poll, 1000);
};
poll();

4
libjsqrc/ethereumjs/dist/ethereum.js.map

File diff suppressed because one or more lines are too long

2
libjsqrc/ethereumjs/dist/ethereum.min.js

File diff suppressed because one or more lines are too long

31
libjsqrc/ethereumjs/lib/providermanager.js

@ -42,33 +42,16 @@ var ProviderManager = function() {
var self = this;
var poll = function () {
if (self.provider) {
var pollsBatch = self.polls.map(function (data) {
return data.data;
});
self.polls.forEach(function (data) {
var result = self.send(data.data);
var payload = jsonrpc.toBatchPayload(pollsBatch);
var results = self.provider.send(payload);
if (!(result instanceof Array) || result.length === 0) {
return;
}
self.polls.forEach(function (data, index) {
var result = results[index];
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return;
}
data.callback(result);
});
result = result.result;
// dont call the callback if result is not an array, or empty one
if (!(result instanceof Array) || result.length === 0) {
return;
}
data.callback(result);
});
}
setTimeout(poll, 1000);
};
poll();

11
libsolidity/AST.cpp

@ -594,6 +594,17 @@ void ElementaryTypeNameExpression::checkTypeRequirements()
m_type = make_shared<TypeType>(Type::fromElementaryTypeName(m_typeToken));
}
Literal::Literal(Location const& _location, Token::Value _token,
ASTPointer<ASTString> const& _value,
Token::Value _sub):
PrimaryExpression(_location), m_token(_token), m_value(_value)
{
if (Token::isEtherSubdenomination(_sub))
m_subDenomination = static_cast<Literal::SubDenomination>(_sub);
else
m_subDenomination = Literal::SubDenomination::None;
}
void Literal::checkTypeRequirements()
{
m_type = Type::forLiteral(*this);

18
libsolidity/AST.h

@ -1112,13 +1112,22 @@ private:
};
/**
* A literal string or number. @see Type::literalToBigEndian is used to actually parse its value.
* A literal string or number. @see ExpressionCompiler::endVisit() is used to actually parse its value.
*/
class Literal: public PrimaryExpression
{
public:
Literal(Location const& _location, Token::Value _token, ASTPointer<ASTString> const& _value):
PrimaryExpression(_location), m_token(_token), m_value(_value) {}
enum class SubDenomination
{
None = Token::ILLEGAL,
Wei = Token::SubWei,
Szabo = Token::SubSzabo,
Finney = Token::SubFinney,
Ether = Token::SubEther
};
Literal(Location const& _location, Token::Value _token,
ASTPointer<ASTString> const& _value,
Token::Value _sub = Token::ILLEGAL);
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
@ -1127,9 +1136,12 @@ public:
/// @returns the non-parsed value of the literal
ASTString const& getValue() const { return *m_value; }
SubDenomination getSubDenomination() const { return m_subDenomination; }
private:
Token::Value m_token;
ASTPointer<ASTString> m_value;
SubDenomination m_subDenomination;
};
/// @}

8
libsolidity/Parser.cpp

@ -180,7 +180,7 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
{
Declaration::Visibility visibility;
Declaration::Visibility visibility = Declaration::Visibility::DEFAULT;
if (_token == Token::PUBLIC)
visibility = Declaration::Visibility::PUBLIC;
else if (_token == Token::PROTECTED)
@ -684,6 +684,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken();
ASTPointer<Expression> expression;
Token::Value nextToken = Token::ILLEGAL;
switch (token)
{
case Token::TRUE_LITERAL:
@ -691,9 +692,12 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break;
case Token::NUMBER:
nextToken = m_scanner->peekNextToken();
case Token::STRING_LITERAL:
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance(), nextToken);
if (Token::isEtherSubdenomination(nextToken))
m_scanner->next();
break;
case Token::IDENTIFIER:
nodeFactory.markEndPosition();

6
libsolidity/Token.h

@ -174,6 +174,11 @@ namespace solidity
K(WHILE, "while", 0) \
\
\
/* Ether subdenominations */ \
K(SubWei, "wei", 0) \
K(SubSzabo, "szabo", 0) \
K(SubFinney, "finney", 0) \
K(SubEther, "ether", 0) \
/* type keywords, keep them in this order, keep int as first keyword
* the implementation in Types.cpp has to be synced to this here
* TODO more to be added */ \
@ -378,6 +383,7 @@ public:
static bool isCountOp(Value op) { return op == INC || op == DEC; }
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == Token::SubEther; }
// Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or NULL if the token doesn't

30
libsolidity/Types.cpp

@ -326,15 +326,39 @@ string IntegerConstantType::toString() const
return "int_const " + m_value.str();
}
u256 IntegerConstantType::literalValue(Literal const*) const
u256 IntegerConstantType::literalValue(Literal const* _literal) const
{
u256 value;
// we ignore the literal and hope that the type was correctly determined
solAssert(m_value <= u256(-1), "Integer constant too large.");
solAssert(m_value >= -(bigint(1) << 255), "Integer constant too small.");
if (m_value >= 0)
return u256(m_value);
value = u256(m_value);
else
return s2u(s256(m_value));
value = s2u(s256(m_value));
if (_literal)
{
Literal::SubDenomination sub =_literal->getSubDenomination();
switch(sub)
{
case Literal::SubDenomination::Wei:
case Literal::SubDenomination::None:
break;
case Literal::SubDenomination::Szabo:
value *= u256(1000000000000);
break;
case Literal::SubDenomination::Finney:
value *= u256(1000000000000000);
break;
case Literal::SubDenomination::Ether:
value *= u256(1000000000000000000);
break;
}
}
return value;
}
shared_ptr<IntegerType const> IntegerConstantType::getIntegerType() const

6
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -31,7 +31,9 @@
#include <libethcore/CommonJS.h>
#include <libwhisper/Message.h>
#include <libwhisper/WhisperHost.h>
#ifndef _MSC_VER
#include <libserpent/funcs.h>
#endif
#include "WebThreeStubServerBase.h"
using namespace std;
@ -446,7 +448,9 @@ Json::Value WebThreeStubServerBase::eth_compilers()
Json::Value ret(Json::arrayValue);
ret.append("lll");
ret.append("solidity");
#ifndef _MSC_VER
ret.append("serpent");
#endif
return ret;
}
@ -462,6 +466,7 @@ std::string WebThreeStubServerBase::eth_lll(std::string const& _code)
std::string WebThreeStubServerBase::eth_serpent(std::string const& _code)
{
string res;
#ifndef _MSC_VER
try
{
res = toJS(dev::asBytes(::compile(_code)));
@ -474,6 +479,7 @@ std::string WebThreeStubServerBase::eth_serpent(std::string const& _code)
{
cwarn << "Uncought serpent compilation exception";
}
#endif
return res;
}

2
mix/CMakeLists.txt

@ -46,7 +46,9 @@ target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} secp256k1)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
target_link_libraries(${EXECUTABLE} serpent)
endif()
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} solidity)
target_link_libraries(${EXECUTABLE} evmcore)

13
mix/ClientModel.cpp

@ -113,24 +113,27 @@ QString ClientModel::apiCall(QString const& _message)
void ClientModel::mine()
{
if (m_running)
if (m_running || m_mining)
BOOST_THROW_EXCEPTION(ExecutionStateException());
m_running = true;
emit runStarted();
emit runStateChanged();
m_mining = true;
emit miningStarted();
emit miningStateChanged();
QtConcurrent::run([=]()
{
try
{
m_client->mine();
newBlock();
m_mining = false;
emit miningComplete();
}
catch (...)
{
m_mining = false;
std::cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
}
m_running = false;
emit miningStateChanged();
});
}

9
mix/ClientModel.h

@ -114,6 +114,8 @@ public:
~ClientModel();
/// @returns true if currently executing contract code
Q_PROPERTY(bool running MEMBER m_running NOTIFY runStateChanged)
/// @returns true if currently mining
Q_PROPERTY(bool mining MEMBER m_mining NOTIFY miningStateChanged)
/// @returns address of the last executed contract
Q_PROPERTY(QString contractAddress READ contractAddress NOTIFY contractAddressChanged)
/// ethereum.js RPC request entry point
@ -144,6 +146,12 @@ signals:
void runStarted();
/// Transaction execution completed successfully
void runComplete();
/// Mining has started
void miningStarted();
/// Mined a new block
void miningComplete();
/// Mining stopped or started
void miningStateChanged();
/// Transaction execution completed with error
/// @param _message Error message
void runFailed(QString const& _message);
@ -174,6 +182,7 @@ private:
AppContext* m_context;
std::atomic<bool> m_running;
std::atomic<bool> m_mining;
std::unique_ptr<MixClient> m_client;
std::unique_ptr<RpcConnector> m_rpcConnector;
std::unique_ptr<Web3Server> m_web3Server;

117
mix/MixClient.cpp

@ -27,6 +27,7 @@
#include <libethereum/Transaction.h>
#include <libethereum/Executive.h>
#include <libethereum/ExtVM.h>
#include <libethereum/BlockChain.h>
#include <libevm/VM.h>
#include "Exceptions.h"
@ -34,15 +35,37 @@
using namespace dev;
using namespace dev::eth;
using namespace dev::mix;
namespace dev
{
namespace mix
{
const Secret c_userAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074");
const u256 c_mixGenesisDifficulty = (u256) 1 << 4;
class MixBlockChain: public dev::eth::BlockChain
{
public:
MixBlockChain(std::string const& _path, h256 _stateRoot): BlockChain(createGenesisBlock(_stateRoot), _path, true)
{
}
static bytes createGenesisBlock(h256 _stateRoot)
{
RLPStream block(3);
block.appendList(14)
<< h256() << EmptyListSHA3 << h160() << _stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_mixGenesisDifficulty << 0 << 1000000 << 0 << (unsigned)0 << std::string() << sha3(bytes(1, 42));
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();
}
};
MixClient::MixClient(std::string const& _dbPath):
m_userAccount(c_userAccountSecret), m_bc(_dbPath, true), m_dbPath(_dbPath), m_minigThreads(0)
m_userAccount(c_userAccountSecret), m_dbPath(_dbPath), m_minigThreads(0)
{
//TODO: put this into genesis block somehow
//resetState(10000000 * ether);
resetState(10000000 * ether);
}
MixClient::~MixClient()
@ -51,21 +74,24 @@ MixClient::~MixClient()
void MixClient::resetState(u256 _balance)
{
(void) _balance;
{
WriteGuard l(x_state);
Guard fl(m_filterLock);
m_filters.clear();
m_watches.clear();
m_bc.reopen(m_dbPath, true);
m_state = eth::State();
m_stateDB = OverlayDB();
m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::CanonGenesis);
m_state.sync(m_bc);
m_startState = m_state;
m_pendingExecutions.clear();
}
mine();
WriteGuard l(x_state);
Guard fl(m_filterLock);
m_filters.clear();
m_watches.clear();
m_stateDB = OverlayDB();
TrieDB<Address, MemoryDB> accountState(&m_stateDB);
accountState.init();
std::map<Address, Account> genesisState = { std::make_pair(KeyPair(c_userAccountSecret).address(), Account(_balance, Account::NormalCreation)) };
dev::eth::commit(genesisState, static_cast<MemoryDB&>(m_stateDB), accountState);
h256 stateRoot = accountState.root();
m_bc.reset();
m_bc.reset(new MixBlockChain(m_dbPath, stateRoot));
m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Empty);
m_state.sync(bc());
m_startState = m_state;
m_pendingExecutions.clear();
m_executions.clear();
}
void MixClient::executeTransaction(Transaction const& _t, State& _state)
@ -74,9 +100,9 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
// do debugging run first
LastHashes lastHashes(256);
lastHashes[0] = m_bc.numberHash(m_bc.number());
lastHashes[0] = bc().numberHash(bc().number());
for (unsigned i = 1; i < 256; ++i)
lastHashes[i] = lastHashes[i - 1] ? m_bc.details(lastHashes[i - 1]).parent : h256();
lastHashes[i] = lastHashes[i - 1] ? bc().details(lastHashes[i - 1]).parent : h256();
State execState = _state;
Executive execution(execState, lastHashes, 0);
@ -155,7 +181,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
h256Set changed;
Guard l(m_filterLock);
for (std::pair<h256 const, eth::InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() > m_bc.number())
if ((unsigned)i.second.filter.latest() > bc().number())
{
// acceptable number.
auto m = i.second.filter.matches(_state.receipt(_state.pending().size() - 1));
@ -163,7 +189,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
{
// filter catches them
for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1));
i.second.changes.push_back(LocalisedLogEntry(l, bc().number() + 1));
changed.insert(i.first);
}
}
@ -174,11 +200,11 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
void MixClient::mine()
{
WriteGuard l(x_state);
m_state.commitToMine(m_bc);
m_state.commitToMine(bc());
while (!m_state.mine(100, true).completed) {}
m_state.completeMine();
m_bc.import(m_state.blockData(), m_stateDB);
m_state.sync(m_bc);
bc().import(m_state.blockData(), m_stateDB);
m_state.sync(bc());
//m_state.cleanup(true);
m_startState = m_state;
m_executions.emplace_back(std::move(m_pendingExecutions));
@ -188,9 +214,9 @@ void MixClient::mine()
ExecutionResult const& MixClient::execution(unsigned _block, unsigned _transaction) const
{
if (_block == m_bc.number() + 1)
if (_block == bc().number() + 1)
return m_pendingExecutions.at(_transaction);
return m_executions.at(_block).at(_transaction);
return m_executions.at(_block - 1).at(_transaction);
}
ExecutionResult const& MixClient::lastExecution() const
@ -213,14 +239,13 @@ State MixClient::asOf(int _block) const
else if (_block == -1)
return m_startState;
else
return State(m_stateDB, m_bc, m_bc.numberHash(_block));
return State(m_stateDB, bc(), bc().numberHash(_block));
}
void MixClient::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{
WriteGuard l(x_state);
u256 n = m_state.transactionsFrom(toAddress(_secret));
_gasPrice = 0; //TODO: remove after fixing setBalance
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
executeTransaction(t, m_state);
}
@ -229,7 +254,6 @@ Address MixClient::transact(Secret _secret, u256 _endowment, bytes const& _init,
{
WriteGuard l(x_state);
u256 n = m_state.transactionsFrom(toAddress(_secret));
_gasPrice = 0; //TODO: remove after fixing setBalance
eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret);
executeTransaction(t, m_state);
Address address = right160(sha3(rlpList(t.sender(), t.nonce())));
@ -301,12 +325,12 @@ eth::LocalisedLogEntries MixClient::logs(unsigned _watchId) const
eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const
{
LocalisedLogEntries ret;
unsigned lastBlock = m_bc.number();
unsigned lastBlock = bc().number();
unsigned block = std::min<unsigned>(lastBlock, (unsigned)_f.latest());
unsigned end = std::min(lastBlock, std::min(block, (unsigned)_f.earliest()));
unsigned skip = _f.skip();
// Pending transactions
if (block > m_bc.number())
if (block > bc().number())
{
ReadGuard l(x_state);
for (unsigned i = 0; i < m_state.pending().size(); ++i)
@ -318,15 +342,15 @@ eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const
ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block));
skip -= std::min(skip, static_cast<unsigned>(logEntries.size()));
}
block = m_bc.number();
block = bc().number();
}
// The rest
auto h = m_bc.numberHash(block);
auto h = bc().numberHash(block);
for (; ret.size() != block && block != end; block--)
{
if (_f.matches(m_bc.info(h).logBloom))
for (TransactionReceipt receipt: m_bc.receipts(h).receipts)
if (_f.matches(bc().info(h).logBloom))
for (TransactionReceipt receipt: bc().receipts(h).receipts)
if (_f.matches(receipt.bloom()))
{
LogEntries logEntries = _f.matches(receipt);
@ -334,7 +358,7 @@ eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const
ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block));
skip -= std::min(skip, static_cast<unsigned>(logEntries.size()));
}
h = m_bc.details(h).parent;
h = bc().details(h).parent;
}
return ret;
}
@ -416,22 +440,22 @@ LocalisedLogEntries MixClient::checkWatch(unsigned _watchId)
h256 MixClient::hashFromNumber(unsigned _number) const
{
return m_bc.numberHash(_number);
return bc().numberHash(_number);
}
eth::BlockInfo MixClient::blockInfo(h256 _hash) const
{
return BlockInfo(m_bc.block(_hash));
return BlockInfo(bc().block(_hash));
}
eth::BlockDetails MixClient::blockDetails(h256 _hash) const
{
return m_bc.details(_hash);
return bc().details(_hash);
}
eth::Transaction MixClient::transaction(h256 _blockHash, unsigned _i) const
{
auto bl = m_bc.block(_blockHash);
auto bl = bc().block(_blockHash);
RLP b(bl);
if (_i < b[1].itemCount())
return Transaction(b[1][_i].data(), CheckSignature::Range);
@ -441,7 +465,7 @@ eth::Transaction MixClient::transaction(h256 _blockHash, unsigned _i) const
eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const
{
auto bl = m_bc.block(_blockHash);
auto bl = bc().block(_blockHash);
RLP b(bl);
if (_i < b[2].itemCount())
return BlockInfo::fromHeader(b[2][_i].data());
@ -451,7 +475,7 @@ eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const
unsigned MixClient::number() const
{
return m_bc.number();
return bc().number();
}
eth::Transactions MixClient::pending() const
@ -461,7 +485,7 @@ eth::Transactions MixClient::pending() const
eth::StateDiff MixClient::diff(unsigned _txi, h256 _block) const
{
State st(m_stateDB, m_bc, _block);
State st(m_stateDB, bc(), _block);
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
}
@ -526,3 +550,6 @@ eth::MineProgress MixClient::miningProgress() const
{
return eth::MineProgress();
}
}
}

7
mix/MixClient.h

@ -27,7 +27,6 @@
#include <string>
#include <libethereum/Interface.h>
#include <libethereum/Client.h>
#include <libethereum/CanonBlockChain.h>
#include "MachineStates.h"
namespace dev
@ -35,6 +34,8 @@ namespace dev
namespace mix
{
class MixBlockChain;
class MixClient: public dev::eth::Interface
{
public:
@ -90,12 +91,14 @@ private:
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state);
void noteChanged(h256Set const& _filters);
dev::eth::State asOf(int _block) const;
MixBlockChain& bc() { return *m_bc; }
MixBlockChain const& bc() const { return *m_bc; }
KeyPair m_userAccount;
eth::State m_state;
eth::State m_startState;
OverlayDB m_stateDB;
eth::CanonBlockChain m_bc;
std::auto_ptr<MixBlockChain> m_bc;
mutable boost::shared_mutex x_state;
mutable std::mutex m_filterLock;
std::map<h256, dev::eth::InstalledFilter> m_filters;

26
mix/qml/DebugInfoList.qml

@ -4,14 +4,19 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
ColumnLayout {
id: root
property string title
property variant listModel;
property bool collapsible;
property bool enableSelection;
property real storedHeight;
property Component itemDelegate
signal rowActivated(int index)
spacing: 0
function collapse()
{
storedHeight = childrenRect.height;
storageContainer.state = "collapsed";
}
@ -32,7 +37,9 @@ ColumnLayout {
Image {
source: "qrc:/qml/img/opentriangleindicator.png"
width: 15
height: 15
sourceSize.width: 15
sourceSize.height: 15
id: storageImgArrow
}
@ -53,16 +60,20 @@ ColumnLayout {
if (storageContainer.state == "collapsed")
{
storageContainer.state = "";
storageContainer.parent.parent.height = storageContainer.parent.parent.Layout.maximumHeight;
storageContainer.parent.parent.height = storedHeight;
}
else
{
storedHeight = root.childrenRect.height;
storageContainer.state = "collapsed";
}
}
}
}
}
Rectangle
{
id: storageContainer
border.width: 3
border.color: "#deddd9"
Layout.fillWidth: true
@ -80,18 +91,23 @@ ColumnLayout {
}
}
]
id: storageContainer
ListView {
TableView {
clip: true;
alternatingRowColors: false
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 3
anchors.leftMargin: 3
width: parent.width - 3
height: parent.height - 6
id: storageList
model: listModel
delegate: itemDelegate
selectionMode: enableSelection ? SelectionMode.SingleSelection : SelectionMode.NoSelection
headerDelegate: null
itemDelegate: root.itemDelegate
TableViewColumn {
role: "modelData"
width: parent.width
}
}
}
}

306
mix/qml/Debugger.qml

@ -55,6 +55,15 @@ Rectangle {
onCompilationComplete: update(null, false);
}
Settings {
id: splitSettings
property alias transactionLogHeight: transactionLog.height
property alias callStackHeight: callStackRect.height
property alias storageHeightSettings: storageRect.height
property alias memoryDumpHeightSettings: memoryRect.height
property alias callDataHeightSettings: callDataRect.height
}
Rectangle
{
visible: false;
@ -104,49 +113,60 @@ Rectangle {
}
}
Flickable {
property int firstColumnWidth: 180
property int secondColumnWidth: 250
ScrollView {
id: debugScrollArea
flickableDirection: Flickable.VerticalFlick
anchors.fill: parent
contentHeight: 4000
contentWidth: parent.width
Rectangle
SplitView
{
color: "transparent"
anchors.fill: parent
ColumnLayout
{
property int sideMargin: 10
id: machineStates
anchors.top: parent.top
anchors.topMargin: 15
anchors.left: parent.left;
anchors.leftMargin: machineStates.sideMargin
anchors.right: parent.right;
anchors.rightMargin: machineStates.sideMargin
anchors.fill: parent
property int sideMargin: 10
id: machineStates
anchors.top: parent.top
anchors.topMargin: 15
anchors.left: parent.left;
anchors.leftMargin: machineStates.sideMargin
width: debugScrollArea.width - machineStates.sideMargin * 2 - 20;
orientation: Qt.Vertical
handleDelegate: Rectangle {
height: machineStates.sideMargin
color: "transparent"
}
function updateHeight() {
machineStates.height = transactionLog.childrenRect.height + buttonRow.childrenRect.height + assemblyCodeRow.childrenRect.height +
callStackRect.childrenRect.height + storageRect.childrenRect.height + memoryRect.childrenRect.height + callDataRect.childrenRect.height + 120;
}
Component.onCompleted: updateHeight();
TransactionLog {
id: transactionLog
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: 60
height: 250
}
TransactionLog {
Layout.fillWidth: true
height: 250
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
id: statesLayout
spacing: machineStates.sideMargin
RowLayout {
Rectangle {
// step button + slider
id: buttonRow
spacing: machineStates.sideMargin
height: 27
Layout.fillWidth: true
color: "transparent"
Rectangle
{
height: parent.height
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
color: "transparent"
width: debugScrollArea.firstColumnWidth
width: stateListContainer.width
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
id: jumpButtons
@ -226,9 +246,11 @@ Rectangle {
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: debugInfoContainer.width
color: "transparent"
Layout.fillWidth: true
height: parent.height
Slider {
id: statesSlider
anchors.fill: parent
@ -255,83 +277,99 @@ Rectangle {
}
}
RowLayout {
Rectangle {
// Assembly code
id: assemblyCodeRow
Layout.fillWidth: true
height: 405
implicitHeight: 405
spacing: machineStates.sideMargin
color: "transparent"
Rectangle
{
id: stateListContainer
width: debugScrollArea.firstColumnWidth
anchors.top : parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width * 0.4
height: parent.height
border.width: 3
border.color: "#deddd9"
color: "white"
anchors.top: parent.top
ListView {
TableView {
id: statesList
anchors.fill: parent
anchors.leftMargin: 3
anchors.rightMargin: 3
anchors.topMargin: 3
anchors.bottomMargin: 3
clip: true
id: statesList
delegate: renderDelegate
highlight: highlightBar
//highlightFollowsCurrentItem: false
headerDelegate: null
itemDelegate: renderDelegate
model: ListModel {}
TableViewColumn {
role: "line"
width: parent.width - 10
}
}
Component {
id: highlightBar
Rectangle {
radius: 4
height: statesList.currentItem.height
width: statesList.currentItem.width;
anchors.fill: parent
y: statesList.currentItem.y
color: "#4A90E2"
//Behavior on y {
// PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50}
//}
}
}
Component {
id: renderDelegate
RowLayout {
id: wrapperItem
height: 20
width: parent.width
spacing: 5
Text {
anchors.left: parent.left
anchors.leftMargin: 10
width: 15
color: "#b2b3ae"
text: line.split(' ')[0]
font.family: "monospace"
font.pointSize: 9
id: id
wrapMode: Text.NoWrap
Item {
Rectangle {
radius: 4
anchors.fill: parent
color: "#4A90E2"
visible: styleData.selected;
}
Text {
wrapMode: Text.NoWrap
color: parent.ListView.isCurrentItem ? "white" : "black"
font.family: "monospace"
text: line.replace(line.split(' ')[0], '')
anchors.left: id.right
font.pointSize: 9
RowLayout {
id: wrapperItem
anchors.fill: parent
spacing: 5
Text {
anchors.left: parent.left
anchors.leftMargin: 10
width: 15
color: "#b2b3ae"
text: styleData.value.split(' ')[0]
font.family: "monospace"
font.pointSize: 9
wrapMode: Text.NoWrap
id: id
}
Text {
anchors.left: id.right;
wrapMode: Text.NoWrap
color: styleData.selected ? "white" : "black"
font.family: "monospace"
text: styleData.value.replace(styleData.value.split(' ')[0], '')
font.pointSize: 9
}
}
}
}
}
Rectangle {
Layout.fillWidth: true
id: debugInfoContainer
width: parent.width * 0.6 - machineStates.sideMargin
anchors.top : parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
height: parent.height //- 2 * stateListContainer.border.width
color: "transparent"
ColumnLayout
@ -372,7 +410,7 @@ Rectangle {
title : qsTr("Stack")
itemDelegate: Item {
id: renderedItem
height: 25
//height: 25
width: parent.width
RowLayout
{
@ -391,7 +429,7 @@ Rectangle {
anchors.leftMargin: 5
font.family: "monospace"
color: "#4a4a4a"
text: model.index;
text: styleData.row;
font.pointSize: 9
}
}
@ -402,7 +440,6 @@ Rectangle {
Layout.fillWidth: true
Layout.minimumWidth: 15
Layout.preferredWidth: 15
Layout.maximumWidth: 60
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
@ -410,7 +447,7 @@ Rectangle {
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: modelData
text: styleData.value
font.pointSize: 9
}
}
@ -434,33 +471,87 @@ Rectangle {
id: splitInfoList
Layout.fillHeight: true
Layout.fillWidth: true
Settings {
id: splitSettings
property alias storageHeightSettings: storageRect.height
property alias memoryDumpHeightSettings: memoryRect.height
property alias callDataHeightSettings: callDataRect.height
}
orientation: Qt.Vertical
width: debugPanel.width - 2 * machineStates.sideMargin
Rectangle
{
id: callStackRect;
color: "transparent"
height: 120
width: parent.width
Layout.minimumHeight: 120
Layout.maximumHeight: 400
CallStack {
anchors.fill: parent
Layout.minimumHeight: 25
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList
{
id: callStack
onFrameActivated: Debugger.displayFrame(index);
collapsible: true
anchors.fill: parent
title : qsTr("Call Stack")
enableSelection: true
onRowActivated: Debugger.displayFrame(index);
itemDelegate:
Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#4A90E2"
visible: styleData.selected;
}
RowLayout
{
id: row
anchors.fill: parent
Rectangle
{
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 30
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
font.family: "monospace"
anchors.leftMargin: 5
color: "#4a4a4a"
text: styleData.row;
font.pointSize: 9
width: parent.width - 5
elide: Text.ElideRight
}
}
Rectangle
{
color: "transparent"
Layout.fillWidth: true
Layout.minimumWidth: parent.width - 30
Layout.maximumWidth: parent.width - 30
Text {
anchors.leftMargin: 5
width: parent.width - 5
wrapMode: Text.Wrap
anchors.left: parent.left
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: styleData.value;
elide: Text.ElideRight
font.pointSize: 9
}
}
}
Rectangle {
anchors.top: row.bottom
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}
}
}
}
Rectangle
{
@ -468,8 +559,8 @@ Rectangle {
color: "transparent"
width: parent.width
Layout.minimumHeight: 25
Layout.maximumHeight: 223
height: 25
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList
{
id: storage
@ -478,29 +569,24 @@ Rectangle {
title : qsTr("Storage")
itemDelegate:
Item {
height: 27
width: parent.width;
anchors.fill: parent
RowLayout
{
id: row
width: parent.width
height: 26
anchors.fill: parent
Rectangle
{
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: parent.width / 2
Layout.preferredWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Layout.minimumHeight: parent.height
Layout.maximumHeight: parent.height
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
font.family: "monospace"
anchors.leftMargin: 5
color: "#4a4a4a"
text: modelData.split('\t')[0];
text: styleData.value.split('\t')[0];
font.pointSize: 9
width: parent.width - 5
elide: Text.ElideRight
@ -511,10 +597,7 @@ Rectangle {
color: "transparent"
Layout.fillWidth: true
Layout.minimumWidth: parent.width / 2
Layout.preferredWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Layout.minimumHeight: parent.height
Layout.maximumHeight: parent.height
Text {
anchors.leftMargin: 5
width: parent.width - 5
@ -523,7 +606,7 @@ Rectangle {
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: modelData.split('\t')[1];
text: styleData.value.split('\t')[1];
elide: Text.ElideRight
font.pointSize: 9
}
@ -545,10 +628,10 @@ Rectangle {
{
id: memoryRect;
color: "transparent"
height: 25
width: parent.width
Layout.minimumHeight: 25
Layout.maximumHeight: 223
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList {
id: memoryDump
anchors.fill: parent
@ -567,10 +650,10 @@ Rectangle {
{
id: callDataRect
color: "transparent"
height: 25
width: parent.width
Layout.minimumHeight: 25
Layout.maximumHeight: 223
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList {
id: callDataDump
anchors.fill: parent
@ -586,8 +669,9 @@ Rectangle {
}
Rectangle
{
id: bottomRect;
width: parent.width
Layout.minimumHeight: 25
Layout.minimumHeight: 20
color: "transparent"
}
}

3
mix/qml/WebPreview.qml

@ -114,7 +114,8 @@ Item {
onClientConnected: {
//filter polling spam
//TODO: do it properly
var log = _request.content.indexOf("eth_changed") < 0;
//var log = _request.content.indexOf("eth_changed") < 0;
var log = true;
if (log)
console.log(_request.content);
var response = clientModel.apiCall(_request.content);

7
mix/qml/js/Debugger.js

@ -107,7 +107,7 @@ function select(stateIndex)
callStackData.push(address);
}
callStackData.push(debugData.states[0].address);
callStack.model = callStackData;
callStack.listModel = callStackData;
}
function codeStr(stateIndex)
@ -118,8 +118,9 @@ function codeStr(stateIndex)
function highlightSelection(index)
{
statesList.currentIndex = index;
statesList.positionViewAtIndex(index, ListView.Center);
statesList.positionViewAtRow(index, ListView.Center);
statesList.selection.clear();
statesList.selection.select(index);
}
function completeCtxInformation(state)

1
mix/qml/js/ProjectModel.js

@ -153,6 +153,7 @@ function doCloseProject() {
console.log("closing project");
projectListModel.clear();
projectPath = "";
currentDocumentId = "";
projectClosed();
}

2
mix/qml/main.qml

@ -88,7 +88,7 @@ ApplicationWindow {
text: qsTr("Mine")
shortcut: "Ctrl+M"
onTriggered: clientModel.mine();
enabled: codeModel.hasContract && !clientModel.running
enabled: codeModel.hasContract && !clientModel.running &&!clientModel.mining
}
Connections {

13
pysol/MANIFEST.in

@ -0,0 +1,13 @@
include pysol/*.cpp
include *.py
include libdevcore/*cpp
include libdevcore/*h
include libdevcrypto/*cpp
include libdevcrypto/*h
include libethcore/*cpp
include libethcore/*h
include libsolidity/*cpp
include libsolidity/*h
include libevmcore/*cpp
include libevmcore/*h
include pysol/README.md

0
pysol/README.md

115
pysol/pysolidity.cpp

@ -0,0 +1,115 @@
#include <Python.h>
#include "structmember.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include "../libdevcore/CommonData.h"
#include <libsolidity/Compiler.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/CompilerUtils.h>
#include <libsolidity/SourceReferenceFormatter.h>
std::string compile(std::string src) {
dev::solidity::CompilerStack compiler;
try
{
std::vector<uint8_t> m_data = compiler.compile(src, false);
return std::string(m_data.begin(), m_data.end());
}
catch (dev::Exception const& exception)
{
std::ostringstream error;
dev::solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
std::string e = error.str();
throw(e);
}
}
std::string mk_full_signature(std::string src) {
dev::solidity::CompilerStack compiler;
try
{
compiler.compile(src);
return compiler.getInterface("");
}
catch (dev::Exception const& exception)
{
std::ostringstream error;
dev::solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
std::string e = error.str();
throw(e);
}
}
std::string bob(std::string src) { return src + src; }
#define PYMETHOD(name, FROM, method, TO) \
static PyObject * name(PyObject *, PyObject *args) { \
try { \
FROM(med) \
return TO(method(med)); \
} \
catch (std::string e) { \
PyErr_SetString(PyExc_Exception, e.c_str()); \
return NULL; \
} \
}
#define FROMSTR(v) \
const char *command; \
int len; \
if (!PyArg_ParseTuple(args, "s#", &command, &len)) \
return NULL; \
std::string v = std::string(command, len); \
// Convert string into python wrapper form
PyObject* pyifyString(std::string s) {
return Py_BuildValue("s#", s.c_str(), s.length());
}
// Convert integer into python wrapper form
PyObject* pyifyInteger(unsigned int i) {
return Py_BuildValue("i", i);
}
// Convert pyobject int into normal form
int cppifyInt(PyObject* o) {
int out;
if (!PyArg_Parse(o, "i", &out))
throw("Argument should be integer");
return out;
}
// Convert pyobject string into normal form
std::string cppifyString(PyObject* o) {
const char *command;
if (!PyArg_Parse(o, "s", &command))
throw("Argument should be string");
return std::string(command);
}
int fh(std::string i) {
return dev::fromHex(i[0]);
}
PYMETHOD(ps_compile, FROMSTR, compile, pyifyString)
PYMETHOD(ps_mk_full_signature, FROMSTR, mk_full_signature, pyifyString)
static PyMethodDef PyextMethods[] = {
{"compile", ps_compile, METH_VARARGS,
"Compile code."},
{"mk_full_signature", ps_mk_full_signature, METH_VARARGS,
"Get the signature of a piece of code."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC initsolidity(void)
{
Py_InitModule( "solidity", PyextMethods );
}

41
pysol/setup.py

@ -0,0 +1,41 @@
import os
os.chdir('..')
from setuptools import setup, Extension
from distutils.sysconfig import get_config_vars
(opt,) = get_config_vars('OPT')
os.environ['OPT'] = " ".join(
flag for flag in opt.split() if flag != '-Wstrict-prototypes'
)
setup(
# Name of this package
name="ethereum-solidity",
# Package version
version='1.8.0',
description='Solidity compiler python wrapper',
maintainer='Vitalik Buterin',
maintainer_email='v@buterin.com',
license='WTFPL',
url='http://www.ethereum.org/',
# Describes how to build the actual extension module from C source files.
ext_modules=[
Extension(
'solidity', # Python name of the module
sources= ['libdevcore/Common.cpp', 'libdevcore/CommonData.cpp', 'libdevcore/CommonIO.cpp', 'libdevcore/FixedHash.cpp', 'libdevcore/Guards.cpp', 'libdevcore/Log.cpp', 'libdevcore/RangeMask.cpp', 'libdevcore/RLP.cpp', 'libdevcore/Worker.cpp', 'libdevcrypto/AES.cpp', 'libdevcrypto/Common.cpp', 'libdevcrypto/CryptoPP.cpp', 'libdevcrypto/ECDHE.cpp', 'libdevcrypto/FileSystem.cpp', 'libdevcrypto/MemoryDB.cpp', 'libdevcrypto/OverlayDB.cpp', 'libdevcrypto/SHA3.cpp', 'libdevcrypto/TrieCommon.cpp', 'libdevcrypto/TrieDB.cpp', 'libethcore/CommonEth.cpp', 'libethcore/CommonJS.cpp', 'libethcore/Exceptions.cpp', 'libsolidity/AST.cpp', 'libsolidity/ASTJsonConverter.cpp', 'libsolidity/ASTPrinter.cpp', 'libsolidity/CompilerContext.cpp', 'libsolidity/Compiler.cpp', 'libsolidity/CompilerStack.cpp', 'libsolidity/CompilerUtils.cpp', 'libsolidity/DeclarationContainer.cpp', 'libsolidity/ExpressionCompiler.cpp', 'libsolidity/GlobalContext.cpp', 'libsolidity/InterfaceHandler.cpp', 'libsolidity/NameAndTypeResolver.cpp', 'libsolidity/Parser.cpp', 'libsolidity/Scanner.cpp', 'libsolidity/SourceReferenceFormatter.cpp', 'libsolidity/Token.cpp', 'libsolidity/Types.cpp', 'libevmcore/Assembly.cpp', 'libevmcore/Instruction.cpp', 'pysol/pysolidity.cpp'],
libraries=['boost_python', 'boost_filesystem', 'boost_chrono', 'boost_thread', 'cryptopp', 'leveldb', 'jsoncpp'],
include_dirs=['/usr/include/boost', '..', '../..', '.'],
extra_compile_args=['--std=c++11', '-Wno-unknown-pragmas']
)],
py_modules=[
],
scripts=[
],
entry_points={
}
),

2
sc/CMakeLists.txt

@ -8,7 +8,9 @@ set(EXECUTABLE sc)
add_executable(${EXECUTABLE} ${SRC_LIST})
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
target_link_libraries(${EXECUTABLE} serpent)
endif()
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore)

70
test/SolidityExpressionCompiler.cpp

@ -91,7 +91,15 @@ bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _
{
Parser parser;
ASTPointer<SourceUnit> sourceUnit;
BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode))));
try
{
sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)));
}
catch(boost::exception const& _e)
{
auto msg = std::string("Parsing source code failed with: \n") + boost::diagnostic_information(_e);
BOOST_FAIL(msg);
}
vector<Declaration const*> declarations;
declarations.reserve(_globalDeclarations.size() + 1);
@ -177,6 +185,66 @@ BOOST_AUTO_TEST_CASE(int_literal)
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 wei;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH1), 0x1});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 szabo;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_finney_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 finney;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH7), 0x3, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 ether;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(comparison)
{
char const* sourceCode = "contract test {\n"

19
test/SolidityParser.cpp

@ -660,6 +660,25 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations)
{
char const* text = R"(
contract c {
function c ()
{
a = 1 wei;
b = 2 szabo;
c = 3 finney;
b = 4 ether;
}
uint256 a;
uint256 b;
uint256 c;
uint256 d;
})";
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_SUITE_END()
}

9
test/SolidityScanner.cpp

@ -255,6 +255,15 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence)
BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "documentation comment ");
}
BOOST_AUTO_TEST_CASE(ether_subdenominations)
{
Scanner scanner(CharStream("wei szabo finney ether"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::SubWei);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubSzabo);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubFinney);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubEther);
}
BOOST_AUTO_TEST_SUITE_END()
}

4
third/CMakeLists.txt

@ -38,7 +38,9 @@ target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} serpent)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
target_link_libraries(${EXECUTABLE} serpent)
endif()
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore)

Loading…
Cancel
Save