Browse Source

Merge branch 'p2p-udp-nodetable' into p2p

Conflicts:
	libp2p/NodeTable.cpp
cl-refactor
subtly 10 years ago
parent
commit
431713a0ac
  1. 2
      evmjit
  2. 15
      libdevcore/CommonJS.cpp
  3. 8
      libdevcore/CommonJS.h
  4. 2
      libethcore/CommonEth.cpp
  5. 11
      libethcore/Exceptions.cpp
  6. 2
      libethereum/BlockChain.cpp
  7. 4
      libethereum/BlockChain.h
  8. 3
      libethereum/Executive.cpp
  9. 3
      libethereum/Executive.h
  10. 8
      libethereum/Precompiled.cpp
  11. 2
      libethereum/TransactionReceipt.cpp
  12. 3
      libethereum/TransactionReceipt.h
  13. 16
      libevm/VM.h
  14. 4
      libevmcore/Instruction.cpp
  15. 2
      libevmcore/Instruction.h
  16. 20
      libp2p/Host.cpp
  17. 38
      libp2p/NodeTable.cpp
  18. 28
      libp2p/UDP.h
  19. 2
      libserpent/opcodes.cpp
  20. 6
      libsolidity/ExpressionCompiler.cpp
  21. 2
      libsolidity/SourceReferenceFormatter.h
  22. 24
      mix/AppContext.cpp
  23. 30
      mix/AppContext.h
  24. 171
      mix/AssemblyDebuggerControl.cpp
  25. 84
      mix/AssemblyDebuggerControl.h
  26. 103
      mix/AssemblyDebuggerCtrl.cpp
  27. 70
      mix/AssemblyDebuggerCtrl.h
  28. 65
      mix/AssemblyDebuggerModel.cpp
  29. 14
      mix/AssemblyDebuggerModel.h
  30. 30
      mix/CodeEditorExtensionManager.cpp
  31. 17
      mix/CodeEditorExtensionManager.h
  32. 28
      mix/ConstantCompilationControl.cpp
  33. 15
      mix/ConstantCompilationControl.h
  34. 3
      mix/ConstantCompilationModel.cpp
  35. 10
      mix/ConstantCompilationModel.h
  36. 131
      mix/ContractCallDataEncoder.cpp
  37. 64
      mix/ContractCallDataEncoder.h
  38. 19
      mix/DebuggingStateWrapper.cpp
  39. 74
      mix/DebuggingStateWrapper.h
  40. 5
      mix/Extension.cpp
  41. 11
      mix/Extension.h
  42. 9
      mix/KeyEventManager.h
  43. 1
      mix/MixApplication.h
  44. 30
      mix/QBasicNodeDefinition.h
  45. 48
      mix/QContractDefinition.cpp
  46. 53
      mix/QContractDefinition.h
  47. 37
      mix/QFunctionDefinition.cpp
  48. 58
      mix/QFunctionDefinition.h
  49. 49
      mix/QVariableDeclaration.h
  50. 55
      mix/QVariableDefinition.cpp
  51. 72
      mix/QVariableDefinition.h
  52. 40
      mix/TransactionBuilder.cpp
  53. 221
      mix/TransactionListModel.cpp
  54. 168
      mix/TransactionListModel.h
  55. 56
      mix/TransactionListView.cpp
  56. 54
      mix/TransactionListView.h
  57. 2
      mix/qml.qrc
  58. 5
      mix/qml/AlertMessageDialog.qml
  59. 8
      mix/qml/BasicContent.qml
  60. 1
      mix/qml/BasicMessage.qml
  61. 54
      mix/qml/Debugger.qml
  62. 23
      mix/qml/MainContent.qml
  63. 7
      mix/qml/ModalDialog.qml
  64. 219
      mix/qml/TransactionDialog.qml
  65. 89
      mix/qml/TransactionList.qml
  66. 10
      mix/qml/js/Debugger.js
  67. 6
      mix/qml/main.qml
  68. 4
      test/stSystemOperationsTestFiller.json
  69. 65
      test/trie.cpp
  70. 2392
      test/vmArithmeticTestFiller.json

2
evmjit

@ -1 +1 @@
Subproject commit 66d5a2b5cdf1361dcf0205b191dd12be090ed224 Subproject commit 3df5a125fa0baa579528abce80402118cad803fd

15
libdevcore/CommonJS.cpp

@ -42,8 +42,6 @@ bytes padded(bytes _b, unsigned _l)
{ {
while (_b.size() < _l) while (_b.size() < _l)
_b.insert(_b.begin(), 0); _b.insert(_b.begin(), 0);
while (_b.size() < _l)
_b.push_back(0);
return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l)));
} }
@ -54,15 +52,23 @@ bytes unpadded(bytes _b)
return _b; return _b;
} }
std::string unpadLeft(std::string _b)
{
auto p = _b.find_first_not_of('0');
if (p == std::string::npos)
return "0";
return _b.substr(p, _b.length() - 1);
}
std::string prettyU256(u256 _n) std::string prettyU256(u256 _n)
{ {
unsigned inc = 0; unsigned inc = 0;
std::string raw; std::string raw;
std::ostringstream s; std::ostringstream s;
if (!(_n >> 64)) if (!(_n >> 64))
s << " " << (uint64_t)_n << " (0x" << (uint64_t)_n << ")"; s << " " << (uint64_t)_n << " (0x" << std::hex << (uint64_t)_n << ")";
else if (!~(_n >> 64)) else if (!~(_n >> 64))
s << " " << (int64_t)_n << " (0x" << (int64_t)_n << ")"; s << " " << (int64_t)_n << " (0x" << std::hex << (int64_t)_n << ")";
else if ((_n >> 160) == 0) else if ((_n >> 160) == 0)
{ {
Address a = right160(_n); Address a = right160(_n);
@ -113,5 +119,4 @@ Address fromString(std::string const& _sn)
return Address(); return Address();
} }
} }

8
libdevcore/CommonJS.h

@ -46,11 +46,19 @@ inline std::string toJS(dev::bytes const& _n)
return "0x" + dev::toHex(_n); return "0x" + dev::toHex(_n);
} }
/// Convert string to byte array. Input parameters can be hex or dec. Returns empty array if invalid input e.g neither dec or hex.
bytes jsToBytes(std::string const& _s); bytes jsToBytes(std::string const& _s);
/// Add '0' on the head of _b until _l.
bytes padded(bytes _b, unsigned _l); bytes padded(bytes _b, unsigned _l);
/// Removing all trailing '0'. Returns empty array if input contains only '0' char.
bytes unpadded(bytes _s); bytes unpadded(bytes _s);
/// Remove all '0' on the head of _s. Returns 0 if _s contains only '0'.
std::string unpadLeft(std::string _s);
/// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256.
std::string prettyU256(u256 _n); std::string prettyU256(u256 _n);
/// Convert h256 into user-readable string (by directly using std::string constructor).
std::string fromRaw(h256 _n, unsigned* _inc = nullptr); std::string fromRaw(h256 _n, unsigned* _inc = nullptr);
/// Convert string to Address (h160), returns empty address if (_a.size != 40).
Address fromString(std::string const& _a); Address fromString(std::string const& _a);
template <unsigned N> FixedHash<N> jsToFixed(std::string const& _s) template <unsigned N> FixedHash<N> jsToFixed(std::string const& _s)

2
libethcore/CommonEth.cpp

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

11
libethcore/Exceptions.cpp

@ -20,13 +20,22 @@
*/ */
#include "Exceptions.h" #include "Exceptions.h"
#include <boost/thread.hpp>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
#define ETH_RETURN_STRING(S) static string s_what; s_what = S; return s_what.c_str(); #if ALL_COMPILERS_ARE_CPP11_COMPLIANT
#define ETH_RETURN_STRING(S) thread_local static string s_what; s_what = S; return s_what.c_str();
#else
#define ETH_RETURN_STRING(S) \
static boost::thread_specific_ptr<string> s_what; \
if (!s_what.get()) \
s_what.reset(new string); \
*s_what = S; return s_what->c_str();
#endif
const char* InvalidBlockFormat::what() const noexcept { ETH_RETURN_STRING("Invalid block format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")"); } const char* InvalidBlockFormat::what() const noexcept { ETH_RETURN_STRING("Invalid block format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")"); }
const char* UncleInChain::what() const noexcept { ETH_RETURN_STRING("Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")"); } const char* UncleInChain::what() const noexcept { ETH_RETURN_STRING("Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")"); }

2
libethereum/BlockChain.cpp

@ -71,7 +71,7 @@ std::map<Address, Account> const& dev::eth::genesisState()
return s_ret; return s_ret;
} }
BlockInfo* BlockChain::s_genesis = nullptr; std::unique_ptr<BlockInfo> BlockChain::s_genesis;
boost::shared_mutex BlockChain::x_genesis; boost::shared_mutex BlockChain::x_genesis;
ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub) ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)

4
libethereum/BlockChain.h

@ -132,7 +132,7 @@ public:
h256Set allUnclesFrom(h256 _parent) const; h256Set allUnclesFrom(h256 _parent) const;
/// @returns the genesis block header. /// @returns the genesis block header.
static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); (s_genesis = new BlockInfo)->populate(&gb); } return *s_genesis; } static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); s_genesis.reset(new BlockInfo); s_genesis->populate(&gb); } return *s_genesis; }
/// @returns the genesis block as its RLP-encoded byte array. /// @returns the genesis block as its RLP-encoded byte array.
/// @note This is slow as it's constructed anew each call. Consider genesis() instead. /// @note This is slow as it's constructed anew each call. Consider genesis() instead.
@ -211,7 +211,7 @@ private:
/// Static genesis info and its lock. /// Static genesis info and its lock.
static boost::shared_mutex x_genesis; static boost::shared_mutex x_genesis;
static BlockInfo* s_genesis; static std::unique_ptr<BlockInfo> s_genesis;
}; };
std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc); std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);

3
libethereum/Executive.cpp

@ -1,16 +1,13 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */

3
libethereum/Executive.h

@ -1,16 +1,13 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */

8
libethereum/Precompiled.cpp

@ -75,11 +75,17 @@ static bytes ripemd160Code(bytesConstRef _in)
return ret; return ret;
} }
static bytes identityCode(bytesConstRef _in)
{
return _in.toBytes();
}
static const std::map<unsigned, PrecompiledAddress> c_precompiled = static const std::map<unsigned, PrecompiledAddress> c_precompiled =
{ {
{ 1, { [](bytesConstRef) -> bigint { return (bigint)500; }, ecrecoverCode }}, { 1, { [](bytesConstRef) -> bigint { return (bigint)500; }, ecrecoverCode }},
{ 2, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, sha256Code }}, { 2, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, sha256Code }},
{ 3, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, ripemd160Code }} { 3, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, ripemd160Code }},
{ 4, { [](bytesConstRef i) -> bigint { return (bigint)1 + (i.size() + 31) / 32 * 1; }, identityCode }}
}; };
std::map<unsigned, PrecompiledAddress> const& dev::eth::precompiled() std::map<unsigned, PrecompiledAddress> const& dev::eth::precompiled()

2
libethereum/TransactionReceipt.cpp

@ -50,7 +50,7 @@ void TransactionReceipt::streamRLP(RLPStream& _s) const
l.streamRLP(_s); l.streamRLP(_s);
} }
std::ostream& dev::operator<<(std::ostream& _out, TransactionReceipt const& _r) std::ostream& dev::eth::operator<<(std::ostream& _out, TransactionReceipt const& _r)
{ {
_out << "Root: " << _r.stateRoot() << std::endl; _out << "Root: " << _r.stateRoot() << std::endl;
_out << "Gas used: " << _r.gasUsed() << std::endl; _out << "Gas used: " << _r.gasUsed() << std::endl;

3
libethereum/TransactionReceipt.h

@ -57,8 +57,7 @@ private:
using TransactionReceipts = std::vector<TransactionReceipt>; using TransactionReceipts = std::vector<TransactionReceipt>;
}
std::ostream& operator<<(std::ostream& _out, eth::TransactionReceipt const& _r); std::ostream& operator<<(std::ostream& _out, eth::TransactionReceipt const& _r);
} }
}

16
libevm/VM.h

@ -196,8 +196,6 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
require(7); require(7);
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1]; runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
if (_ext.depth == 1024)
BOOST_THROW_EXCEPTION(OutOfGas());
break; break;
case Instruction::CREATE: case Instruction::CREATE:
@ -207,8 +205,6 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
u256 inSize = m_stack[m_stack.size() - 3]; u256 inSize = m_stack[m_stack.size() - 3];
newTempSize = (bigint)inOff + inSize; newTempSize = (bigint)inOff + inSize;
runGas = c_createGas; runGas = c_createGas;
if (_ext.depth == 1024)
BOOST_THROW_EXCEPTION(OutOfGas());
break; break;
} }
case Instruction::EXP: case Instruction::EXP:
@ -219,8 +215,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
break; break;
} }
case Instruction::PREVHASH: case Instruction::BLOCKHASH:
if (c_protocolVersion > 49)
require(1); require(1);
break; break;
@ -563,11 +558,8 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
case Instruction::GASPRICE: case Instruction::GASPRICE:
m_stack.push_back(_ext.gasPrice); m_stack.push_back(_ext.gasPrice);
break; break;
case Instruction::PREVHASH: case Instruction::BLOCKHASH:
if (c_protocolVersion > 49)
m_stack.back() = (u256)_ext.prevhash(m_stack.back()); m_stack.back() = (u256)_ext.prevhash(m_stack.back());
else
m_stack.push_back(_ext.previousBlock.hash);
break; break;
case Instruction::COINBASE: case Instruction::COINBASE:
m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress); m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress);
@ -784,7 +776,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
unsigned initSize = (unsigned)m_stack.back(); unsigned initSize = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= endowment) if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024)
{ {
_ext.subBalance(endowment); _ext.subBalance(endowment);
m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp));
@ -812,7 +804,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
unsigned outSize = (unsigned)m_stack.back(); unsigned outSize = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= value) if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024)
{ {
_ext.subBalance(value); _ext.subBalance(value);
m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress)); m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress));

4
libevmcore/Instruction.cpp

@ -67,7 +67,7 @@ const std::map<std::string, Instruction> dev::eth::c_instructions =
{ "GASPRICE", Instruction::GASPRICE }, { "GASPRICE", Instruction::GASPRICE },
{ "EXTCODESIZE", Instruction::EXTCODESIZE }, { "EXTCODESIZE", Instruction::EXTCODESIZE },
{ "EXTCODECOPY", Instruction::EXTCODECOPY }, { "EXTCODECOPY", Instruction::EXTCODECOPY },
{ "PREVHASH", Instruction::PREVHASH }, { "BLOCKHASH", Instruction::BLOCKHASH },
{ "COINBASE", Instruction::COINBASE }, { "COINBASE", Instruction::COINBASE },
{ "TIMESTAMP", Instruction::TIMESTAMP }, { "TIMESTAMP", Instruction::TIMESTAMP },
{ "NUMBER", Instruction::NUMBER }, { "NUMBER", Instruction::NUMBER },
@ -200,7 +200,7 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false } }, { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false } },
{ Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false } }, { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false } },
{ Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true } }, { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true } },
{ Instruction::PREVHASH, { "PREVHASH", 0, 0, 1, false } }, { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false } },
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false } }, { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false } },
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false } },
{ Instruction::NUMBER, { "NUMBER", 0, 0, 1, false } }, { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false } },

2
libevmcore/Instruction.h

@ -73,7 +73,7 @@ enum class Instruction: uint8_t
EXTCODESIZE, ///< get external code size (from another contract) EXTCODESIZE, ///< get external code size (from another contract)
EXTCODECOPY, ///< copy external code (from another contract) EXTCODECOPY, ///< copy external code (from another contract)
PREVHASH = 0x40, ///< get hash of most recent complete block BLOCKHASH = 0x40, ///< get hash of most recent complete block
COINBASE, ///< get the block's coinbase address COINBASE, ///< get the block's coinbase address
TIMESTAMP, ///< get the block's timestamp TIMESTAMP, ///< get the block's timestamp
NUMBER, ///< get the block's number NUMBER, ///< get the block's number

20
libp2p/Host.cpp

@ -276,15 +276,15 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
// if user supplied address is a public address then we use it // if user supplied address is a public address then we use it
// if user supplied address is private, and localnetworking is enabled, we use it // if user supplied address is private, and localnetworking is enabled, we use it
bi::address reqpublicaddr(bi::address(_publicAddress.empty() ? bi::address() : bi::address::from_string(_publicAddress))); bi::address reqPublicAddr(bi::address(_publicAddress.empty() ? bi::address() : bi::address::from_string(_publicAddress)));
bi::tcp::endpoint reqpublic(reqpublicaddr, m_listenPort); bi::tcp::endpoint reqPublic(reqPublicAddr, m_listenPort);
bool isprivate = isPrivateAddress(reqpublicaddr); bool isprivate = isPrivateAddress(reqPublicAddr);
bool ispublic = !isprivate && !isLocalHostAddress(reqpublicaddr); bool ispublic = !isprivate && !isLocalHostAddress(reqPublicAddr);
if (!reqpublicaddr.is_unspecified() && (ispublic || (isprivate && m_netPrefs.localNetworking))) if (!reqPublicAddr.is_unspecified() && (ispublic || (isprivate && m_netPrefs.localNetworking)))
{ {
if (!m_peerAddresses.count(reqpublicaddr)) if (!m_peerAddresses.count(reqPublicAddr))
m_peerAddresses.insert(reqpublicaddr); m_peerAddresses.insert(reqPublicAddr);
m_tcpPublic = reqpublic; m_tcpPublic = reqPublic;
return; return;
} }
@ -311,7 +311,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
} }
// or if no address provided, use private ipv4 address if local networking is enabled // or if no address provided, use private ipv4 address if local networking is enabled
if (reqpublicaddr.is_unspecified()) if (reqPublicAddr.is_unspecified())
if (m_netPrefs.localNetworking) if (m_netPrefs.localNetworking)
for (auto addr: m_peerAddresses) for (auto addr: m_peerAddresses)
if (addr.is_v4() && isPrivateAddress(addr)) if (addr.is_v4() && isPrivateAddress(addr))

38
libp2p/NodeTable.cpp

@ -58,13 +58,13 @@ void NodeTable::join()
doFindNode(m_node.id); doFindNode(m_node.id);
} }
std::list<NodeId> NodeTable::nodes() const list<NodeId> NodeTable::nodes() const
{ {
std::list<NodeId> nodes; list<NodeId> nodes;
Guard l(x_nodes); Guard l(x_nodes);
for (auto& i: m_nodes) for (auto& i: m_nodes)
nodes.push_back(i.second->id); nodes.push_back(i.second->id);
return std::move(nodes); return move(nodes);
} }
list<NodeEntry> NodeTable::state() const list<NodeEntry> NodeTable::state() const
@ -90,7 +90,7 @@ void NodeTable::requestNeighbors(NodeEntry const& _node, NodeId _target) const
m_socketPtr->send(p); m_socketPtr->send(p);
} }
void NodeTable::doFindNode(NodeId _node, unsigned _round, std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>> _tried) void NodeTable::doFindNode(NodeId _node, unsigned _round, shared_ptr<set<shared_ptr<NodeEntry>>> _tried)
{ {
if (!m_socketPtr->isOpen() || _round == s_maxSteps) if (!m_socketPtr->isOpen() || _round == s_maxSteps)
return; return;
@ -102,10 +102,10 @@ void NodeTable::doFindNode(NodeId _node, unsigned _round, std::shared_ptr<std::s
} }
else if(!_round && !_tried) else if(!_round && !_tried)
// initialized _tried on first round // initialized _tried on first round
_tried.reset(new std::set<std::shared_ptr<NodeEntry>>()); _tried.reset(new set<shared_ptr<NodeEntry>>());
auto nearest = findNearest(_node); auto nearest = findNearest(_node);
std::list<std::shared_ptr<NodeEntry>> tried; list<shared_ptr<NodeEntry>> tried;
for (unsigned i = 0; i < nearest.size() && tried.size() < s_alpha; i++) for (unsigned i = 0; i < nearest.size() && tried.size() < s_alpha; i++)
if (!_tried->count(nearest[i])) if (!_tried->count(nearest[i]))
{ {
@ -138,14 +138,14 @@ void NodeTable::doFindNode(NodeId _node, unsigned _round, std::shared_ptr<std::s
}); });
} }
std::vector<std::shared_ptr<NodeEntry>> NodeTable::findNearest(NodeId _target) vector<shared_ptr<NodeEntry>> NodeTable::findNearest(NodeId _target)
{ {
// send s_alpha FindNode packets to nodes we know, closest to target // send s_alpha FindNode packets to nodes we know, closest to target
static unsigned lastBin = s_bins - 1; static unsigned lastBin = s_bins - 1;
unsigned head = dist(m_node.id, _target); unsigned head = dist(m_node.id, _target);
unsigned tail = head == 0 ? lastBin : (head - 1) % s_bins; unsigned tail = head == 0 ? lastBin : (head - 1) % s_bins;
std::map<unsigned, std::list<std::shared_ptr<NodeEntry>>> found; map<unsigned, list<shared_ptr<NodeEntry>>> found;
unsigned count = 0; unsigned count = 0;
// if d is 0, then we roll look forward, if last, we reverse, else, spread from d // if d is 0, then we roll look forward, if last, we reverse, else, spread from d
@ -205,11 +205,11 @@ std::vector<std::shared_ptr<NodeEntry>> NodeTable::findNearest(NodeId _target)
tail--; tail--;
} }
std::vector<std::shared_ptr<NodeEntry>> ret; vector<shared_ptr<NodeEntry>> ret;
for (auto& nodes: found) for (auto& nodes: found)
for (auto n: nodes.second) for (auto n: nodes.second)
ret.push_back(n); ret.push_back(n);
return std::move(ret); return move(ret);
} }
void NodeTable::ping(bi::udp::endpoint _to) const void NodeTable::ping(bi::udp::endpoint _to) const
@ -225,7 +225,7 @@ void NodeTable::ping(NodeEntry* _n) const
ping(_n->endpoint.udp); ping(_n->endpoint.udp);
} }
void NodeTable::evict(std::shared_ptr<NodeEntry> _leastSeen, std::shared_ptr<NodeEntry> _new) void NodeTable::evict(shared_ptr<NodeEntry> _leastSeen, shared_ptr<NodeEntry> _new)
{ {
if (!m_socketPtr->isOpen()) if (!m_socketPtr->isOpen())
return; return;
@ -245,7 +245,7 @@ void NodeTable::noteNode(Public const& _pubk, bi::udp::endpoint const& _endpoint
if (_pubk == m_node.address()) if (_pubk == m_node.address())
return; return;
std::shared_ptr<NodeEntry> node; shared_ptr<NodeEntry> node;
{ {
Guard l(x_nodes); Guard l(x_nodes);
auto n = m_nodes.find(_pubk); auto n = m_nodes.find(_pubk);
@ -267,13 +267,13 @@ void NodeTable::noteNode(Public const& _pubk, bi::udp::endpoint const& _endpoint
noteNode(node); noteNode(node);
} }
void NodeTable::noteNode(std::shared_ptr<NodeEntry> _n) void NodeTable::noteNode(shared_ptr<NodeEntry> _n)
{ {
std::shared_ptr<NodeEntry> contested; shared_ptr<NodeEntry> contested;
{ {
NodeBucket& s = bucket(_n.get()); NodeBucket& s = bucket(_n.get());
Guard l(x_state); Guard l(x_state);
s.nodes.remove_if([&_n](std::weak_ptr<NodeEntry> n) s.nodes.remove_if([&_n](weak_ptr<NodeEntry> n)
{ {
if (n.lock() == _n) if (n.lock() == _n)
return true; return true;
@ -297,12 +297,12 @@ void NodeTable::noteNode(std::shared_ptr<NodeEntry> _n)
evict(contested, _n); evict(contested, _n);
} }
void NodeTable::dropNode(std::shared_ptr<NodeEntry> _n) void NodeTable::dropNode(shared_ptr<NodeEntry> _n)
{ {
NodeBucket &s = bucket(_n.get()); NodeBucket &s = bucket(_n.get());
{ {
Guard l(x_state); Guard l(x_state);
s.nodes.remove_if([&_n](std::weak_ptr<NodeEntry> n) { return n.lock() == _n; }); s.nodes.remove_if([&_n](weak_ptr<NodeEntry> n) { return n.lock() == _n; });
} }
Guard l(x_nodes); Guard l(x_nodes);
m_nodes.erase(_n->id); m_nodes.erase(_n->id);
@ -368,7 +368,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
// clog(NodeTableMessageSummary) << "Received FindNode from " << _from.address().to_string() << ":" << _from.port(); // clog(NodeTableMessageSummary) << "Received FindNode from " << _from.address().to_string() << ":" << _from.port();
FindNode in = FindNode::fromBytesConstRef(_from, rlpBytes); FindNode in = FindNode::fromBytesConstRef(_from, rlpBytes);
std::vector<std::shared_ptr<NodeEntry>> nearest = findNearest(in.target); vector<shared_ptr<NodeEntry>> nearest = findNearest(in.target);
static unsigned const nlimit = (m_socketPtr->maxDatagramSize - 11) / 86; static unsigned const nlimit = (m_socketPtr->maxDatagramSize - 11) / 86;
for (unsigned offset = 0; offset < nearest.size(); offset += nlimit) for (unsigned offset = 0; offset < nearest.size(); offset += nlimit)
{ {
@ -415,7 +415,7 @@ void NodeTable::doCheckEvictions(boost::system::error_code const& _ec)
return; return;
bool evictionsRemain = false; bool evictionsRemain = false;
std::list<shared_ptr<NodeEntry>> drop; list<shared_ptr<NodeEntry>> drop;
{ {
Guard le(x_evictions); Guard le(x_evictions);
Guard ln(x_nodes); Guard ln(x_nodes);

28
libp2p/UDP.h

@ -140,13 +140,13 @@ protected:
bi::udp::endpoint m_endpoint; ///< Endpoint which we listen to. bi::udp::endpoint m_endpoint; ///< Endpoint which we listen to.
Mutex x_sendQ; Mutex x_sendQ;
std::deque<UDPDatagram> sendQ; ///< Queue for egress data. std::deque<UDPDatagram> m_sendQ; ///< Queue for egress data.
std::array<byte, maxDatagramSize> recvData; ///< Buffer for ingress data. std::array<byte, maxDatagramSize> m_recvData; ///< Buffer for ingress data.
bi::udp::endpoint recvEndpoint; ///< Endpoint data was received from. bi::udp::endpoint m_recvEndpoint; ///< Endpoint data was received from.
bi::udp::socket m_socket; ///< Boost asio udp socket. bi::udp::socket m_socket; ///< Boost asio udp socket.
Mutex x_socketError; ///< Mutex for error which can be set from host or IO thread. Mutex x_socketError; ///< Mutex for error which can be set from host or IO thread.
boost::system::error_code socketError; ///< Set when shut down due to error. boost::system::error_code m_socketError; ///< Set when shut down due to error.
}; };
template <typename Handler, unsigned MaxDatagramSize> template <typename Handler, unsigned MaxDatagramSize>
@ -161,7 +161,7 @@ void UDPSocket<Handler,MaxDatagramSize>::connect()
// clear write queue so reconnect doesn't send stale messages // clear write queue so reconnect doesn't send stale messages
Guard l(x_sendQ); Guard l(x_sendQ);
sendQ.clear(); m_sendQ.clear();
m_closed = false; m_closed = false;
doRead(); doRead();
@ -174,8 +174,8 @@ bool UDPSocket<Handler,MaxDatagramSize>::send(UDPDatagram const& _datagram)
return false; return false;
Guard l(x_sendQ); Guard l(x_sendQ);
sendQ.push_back(_datagram); m_sendQ.push_back(_datagram);
if (sendQ.size() == 1) if (m_sendQ.size() == 1)
doWrite(); doWrite();
return true; return true;
@ -188,13 +188,13 @@ void UDPSocket<Handler,MaxDatagramSize>::doRead()
return; return;
auto self(UDPSocket<Handler, MaxDatagramSize>::shared_from_this()); auto self(UDPSocket<Handler, MaxDatagramSize>::shared_from_this());
m_socket.async_receive_from(boost::asio::buffer(recvData), recvEndpoint, [this, self](boost::system::error_code _ec, size_t _len) m_socket.async_receive_from(boost::asio::buffer(m_recvData), m_recvEndpoint, [this, self](boost::system::error_code _ec, size_t _len)
{ {
if (_ec) if (_ec)
return disconnectWithError(_ec); return disconnectWithError(_ec);
assert(_len); assert(_len);
m_host.onReceived(this, recvEndpoint, bytesConstRef(recvData.data(), _len)); m_host.onReceived(this, m_recvEndpoint, bytesConstRef(m_recvData.data(), _len));
doRead(); doRead();
}); });
} }
@ -205,7 +205,7 @@ void UDPSocket<Handler,MaxDatagramSize>::doWrite()
if (m_closed) if (m_closed)
return; return;
const UDPDatagram& datagram = sendQ[0]; const UDPDatagram& datagram = m_sendQ[0];
auto self(UDPSocket<Handler, MaxDatagramSize>::shared_from_this()); auto self(UDPSocket<Handler, MaxDatagramSize>::shared_from_this());
m_socket.async_send_to(boost::asio::buffer(datagram.data), datagram.endpoint(), [this, self](boost::system::error_code _ec, std::size_t) m_socket.async_send_to(boost::asio::buffer(datagram.data), datagram.endpoint(), [this, self](boost::system::error_code _ec, std::size_t)
{ {
@ -214,8 +214,8 @@ void UDPSocket<Handler,MaxDatagramSize>::doWrite()
else else
{ {
Guard l(x_sendQ); Guard l(x_sendQ);
sendQ.pop_front(); m_sendQ.pop_front();
if (sendQ.empty()) if (m_sendQ.empty())
return; return;
} }
doWrite(); doWrite();
@ -233,9 +233,9 @@ void UDPSocket<Handler,MaxDatagramSize>::disconnectWithError(boost::system::erro
{ {
// disconnect-operation following prior non-zero errors are ignored // disconnect-operation following prior non-zero errors are ignored
Guard l(x_socketError); Guard l(x_socketError);
if (socketError != boost::system::error_code()) if (m_socketError != boost::system::error_code())
return; return;
socketError = _ec; m_socketError = _ec;
} }
// TODO: (if non-zero error) schedule high-priority writes // TODO: (if non-zero error) schedule high-priority writes

2
libserpent/opcodes.cpp

@ -44,7 +44,7 @@ Mapping mapping[] = {
Mapping("GASPRICE", 0x3a, 0, 1), Mapping("GASPRICE", 0x3a, 0, 1),
Mapping("EXTCODESIZE", 0x3b, 1, 1), Mapping("EXTCODESIZE", 0x3b, 1, 1),
Mapping("EXTCODECOPY", 0x3c, 4, 0), Mapping("EXTCODECOPY", 0x3c, 4, 0),
Mapping("PREVHASH", 0x40, 0, 1), Mapping("BLOCKHASH", 0x40, 1, 1),
Mapping("COINBASE", 0x41, 0, 1), Mapping("COINBASE", 0x41, 0, 1),
Mapping("TIMESTAMP", 0x42, 0, 1), Mapping("TIMESTAMP", 0x42, 0, 1),
Mapping("NUMBER", 0x43, 0, 1), Mapping("NUMBER", 0x43, 0, 1),

6
libsolidity/ExpressionCompiler.cpp

@ -344,9 +344,9 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
m_context << eth::Instruction::COINBASE; m_context << eth::Instruction::COINBASE;
else if (member == "timestamp") else if (member == "timestamp")
m_context << eth::Instruction::TIMESTAMP; m_context << eth::Instruction::TIMESTAMP;
else if (member == "prevhash") /* else if (member == "blockhash")
m_context << eth::Instruction::PREVHASH; m_context << eth::Instruction::BLOCKHASH;
else if (member == "difficulty") */ else if (member == "difficulty")
m_context << eth::Instruction::DIFFICULTY; m_context << eth::Instruction::DIFFICULTY;
else if (member == "number") else if (member == "number")
m_context << eth::Instruction::NUMBER; m_context << eth::Instruction::NUMBER;

2
libsolidity/SourceReferenceFormatter.h

@ -28,7 +28,7 @@
namespace dev namespace dev
{ {
class Exception; // forward struct Exception; // forward
namespace solidity namespace solidity
{ {

24
mix/AppContext.cpp

@ -26,12 +26,15 @@
#include <QMessageBox> #include <QMessageBox>
#include <QQmlComponent> #include <QQmlComponent>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include "libdevcrypto/FileSystem.h" #include <libwebthree/WebThree.h>
#include <libdevcrypto/FileSystem.h>
#include <libsolidity/CompilerStack.h>
#include "KeyEventManager.h" #include "KeyEventManager.h"
#include "AppContext.h" #include "AppContext.h"
using namespace dev; using namespace dev;
using namespace dev::mix;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::solidity;
using namespace dev::mix;
AppContext* AppContext::Instance = nullptr; AppContext* AppContext::Instance = nullptr;
@ -40,6 +43,7 @@ AppContext::AppContext(QQmlApplicationEngine* _engine)
m_applicationEngine = std::unique_ptr<QQmlApplicationEngine>(_engine); m_applicationEngine = std::unique_ptr<QQmlApplicationEngine>(_engine);
m_keyEventManager = std::unique_ptr<KeyEventManager>(new KeyEventManager()); m_keyEventManager = std::unique_ptr<KeyEventManager>(new KeyEventManager());
m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"}));
m_compiler = std::unique_ptr<CompilerStack>(new CompilerStack()); //TODO : to move in a codel model structure.
} }
QQmlApplicationEngine* AppContext::appEngine() QQmlApplicationEngine* AppContext::appEngine()
@ -47,11 +51,6 @@ QQmlApplicationEngine* AppContext::appEngine()
return m_applicationEngine.get(); return m_applicationEngine.get();
} }
dev::eth::Client* AppContext::getEthereumClient()
{
return m_webThree->ethereum();
}
void AppContext::initKeyEventManager(QObject* _res) void AppContext::initKeyEventManager(QObject* _res)
{ {
QObject* mainContent = _res->findChild<QObject*>("mainContent", Qt::FindChildrenRecursively); QObject* mainContent = _res->findChild<QObject*>("mainContent", Qt::FindChildrenRecursively);
@ -66,6 +65,11 @@ KeyEventManager* AppContext::getKeyEventManager()
return m_keyEventManager.get(); return m_keyEventManager.get();
} }
CompilerStack* AppContext::compiler()
{
return m_compiler.get();
}
void AppContext::setApplicationContext(QQmlApplicationEngine* _engine) void AppContext::setApplicationContext(QQmlApplicationEngine* _engine)
{ {
if (Instance == nullptr) if (Instance == nullptr)
@ -74,9 +78,9 @@ void AppContext::setApplicationContext(QQmlApplicationEngine* _engine)
void AppContext::displayMessageDialog(QString _title, QString _message) void AppContext::displayMessageDialog(QString _title, QString _message)
{ {
QObject* dialogWin = m_applicationEngine.get()->rootObjects().at(0)->findChild<QObject*>("alertMessageDialog", Qt::FindChildrenRecursively); // TODO : move to a UI dedicated layer.
QObject* dialogWinComponent = m_applicationEngine.get()->rootObjects().at(0)->findChild<QObject*>("alertMessageDialogContent", Qt::FindChildrenRecursively); QObject* dialogWin = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("alertMessageDialog", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(dialogWin, "close"); QObject* dialogWinComponent = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("alertMessageDialogContent", Qt::FindChildrenRecursively);
dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml")); dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml"));
dialogWin->setProperty("title", _title); dialogWin->setProperty("title", _title);
dialogWin->setProperty("width", "250"); dialogWin->setProperty("width", "250");

30
mix/AppContext.h

@ -27,28 +27,48 @@
#pragma once #pragma once
#include <memory>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include "libwebthree/WebThree.h" #include <libsolidity/CompilerStack.h>
#include <libwebthree/WebThree.h>
#include "KeyEventManager.h" #include "KeyEventManager.h"
namespace dev
{
class WebThreeDirect;
namespace solidity
{
class CompilerStack;
}
}
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
/**
* @brief Provides access to application scope variable.
*/
class AppContext: public QObject class AppContext: public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
AppContext(QQmlApplicationEngine* _engine); AppContext(QQmlApplicationEngine* _engine);
~AppContext() {} /// Get the current QQmlApplicationEngine instance.
static AppContext* getInstance() { return Instance; } static AppContext* getInstance() { return Instance; }
/// Renew QQMLApplicationEngine with a new instance.
static void setApplicationContext(QQmlApplicationEngine* _engine); static void setApplicationContext(QQmlApplicationEngine* _engine);
/// Get the current QQMLApplicationEngine instance.
QQmlApplicationEngine* appEngine(); QQmlApplicationEngine* appEngine();
dev::eth::Client* getEthereumClient(); /// Initialize KeyEventManager (used to handle key pressed event).
void initKeyEventManager(QObject* _obj); void initKeyEventManager(QObject* _obj);
/// Get the current KeyEventManager instance.
KeyEventManager* getKeyEventManager(); KeyEventManager* getKeyEventManager();
/// Get the current Compiler instance (used to parse and compile contract code).
dev::solidity::CompilerStack* compiler();
/// Display an alert message.
void displayMessageDialog(QString _title, QString _message); void displayMessageDialog(QString _title, QString _message);
private: private:
@ -56,12 +76,14 @@ private:
std::unique_ptr<QQmlApplicationEngine> m_applicationEngine; std::unique_ptr<QQmlApplicationEngine> m_applicationEngine;
std::unique_ptr<dev::WebThreeDirect> m_webThree; std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::unique_ptr<KeyEventManager> m_keyEventManager; std::unique_ptr<KeyEventManager> m_keyEventManager;
std::unique_ptr<solidity::CompilerStack> m_compiler;
public slots: public slots:
/// Delete the current instance when application quit.
void quitApplication() { delete Instance; } void quitApplication() { delete Instance; }
/// Initialize components after the loading of the main QML view.
void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_url); initKeyEventManager(_obj); } void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_url); initKeyEventManager(_obj); }
}; };
} }
} }

171
mix/AssemblyDebuggerControl.cpp

@ -0,0 +1,171 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerControl.cpp
* @author Yann yann@ethdev.com
* @date 2014
* display opcode debugging.
*/
#include <QtConcurrent/QtConcurrent>
#include <QDebug>
#include <QVariableDefinition.h>
#include <QQmlContext>
#include <QModelIndex>
#include <libdevcore/CommonJS.h>
#include <libethereum/Transaction.h>
#include "AssemblyDebuggerModel.h"
#include "AssemblyDebuggerControl.h"
#include "KeyEventManager.h"
#include "AppContext.h"
#include "DebuggingStateWrapper.h"
#include "TransactionListModel.h"
#include "QContractDefinition.h"
#include "QVariableDeclaration.h"
#include "ContractCallDataEncoder.h"
using namespace dev::eth;
using namespace dev::mix;
AssemblyDebuggerControl::AssemblyDebuggerControl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog)
{
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*");
qRegisterMetaType<QList<QVariableDefinition*>>("QList<QVariableDefinition*>");
qRegisterMetaType<QList<QVariableDeclaration*>>("QList<QVariableDeclaration*>");
qRegisterMetaType<QVariableDeclaration*>("QVariableDeclaration*");
qRegisterMetaType<AssemblyDebuggerData>("AssemblyDebuggerData");
qRegisterMetaType<DebuggingStatusResult>("DebuggingStatusResult");
connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList<QVariableDefinition*>, QList<QObject*>, AssemblyDebuggerData)),
this, SLOT(updateGUI(bool, DebuggingStatusResult, QList<QVariableDefinition*>, QList<QObject*>, AssemblyDebuggerData)), Qt::QueuedConnection);
m_modelDebugger = std::unique_ptr<AssemblyDebuggerModel>(new AssemblyDebuggerModel);
m_compilation = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel);
m_doc = _doc;
}
QString AssemblyDebuggerControl::contentUrl() const
{
return QStringLiteral("qrc:/qml/Debugger.qml");
}
QString AssemblyDebuggerControl::title() const
{
return QApplication::tr("debugger");
}
void AssemblyDebuggerControl::start() const
{
//start to listen on F5
m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int)));
}
void AssemblyDebuggerControl::keyPressed(int _key)
{
if (_key == Qt::Key_F5)
{
QtConcurrent::run([this]()
{
deployContract(m_doc->toPlainText());
});
}
else if (_key == Qt::Key_F6)
{
m_modelDebugger->resetState();
AppContext::getInstance()->displayMessageDialog(QApplication::tr("State status"), QApplication::tr("State reseted ... need to redeploy contract"));
}
}
void AssemblyDebuggerControl::callContract(TransactionSettings _tr, dev::Address _contract)
{
CompilerResult compilerRes = m_compilation->compile(m_doc->toPlainText());
if (!compilerRes.success)
AppContext::getInstance()->displayMessageDialog("debugger","compilation failed");
else
{
ContractCallDataEncoder c;
std::shared_ptr<QContractDefinition> contractDef = QContractDefinition::Contract(m_doc->toPlainText());
QFunctionDefinition* f = nullptr;
for (int k = 0; k < contractDef->functions().size(); k++)
{
if (contractDef->functions().at(k)->name() == _tr.functionId)
{
f = (QFunctionDefinition*)contractDef->functions().at(k);
break;
}
}
if (!f)
AppContext::getInstance()->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("function not found. Please redeploy this contract."));
else
{
c.encode(f->index());
for (int k = 0; k < f->parameters().size(); k++)
{
QVariableDeclaration* var = (QVariableDeclaration*)f->parameters().at(k);
c.encode(var, _tr.parameterValues[var->name()]);
}
DebuggingContent debuggingContent = m_modelDebugger->callContract(_contract, c.encodedData(), _tr);
debuggingContent.returnParameters = c.decode(f->returnParameters(), debuggingContent.returnValue);
finalizeExecution(debuggingContent);
}
}
}
void AssemblyDebuggerControl::deployContract(QString _source)
{
CompilerResult compilerRes = m_compilation->compile(_source);
if (!compilerRes.success)
emit dataAvailable(false, DebuggingStatusResult::Compilationfailed);
else
{
m_previousDebugResult = m_modelDebugger->deployContract(compilerRes.bytes);
finalizeExecution(m_previousDebugResult);
}
}
void AssemblyDebuggerControl::finalizeExecution(DebuggingContent _debuggingContent)
{
//we need to wrap states in a QObject before sending to QML.
QList<QObject*> wStates;
for(int i = 0; i < _debuggingContent.machineStates.size(); i++)
{
QPointer<DebuggingStateWrapper> s(new DebuggingStateWrapper(_debuggingContent.executionCode, _debuggingContent.executionData.toBytes()));
s->setState(_debuggingContent.machineStates.at(i));
wStates.append(s);
}
AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(_debuggingContent.executionCode);
emit dataAvailable(true, DebuggingStatusResult::Ok, _debuggingContent.returnParameters, wStates, code);
}
void AssemblyDebuggerControl::updateGUI(bool _success, DebuggingStatusResult const& _reason, QList<QVariableDefinition*> const& _returnParam, QList<QObject*> const& _wStates, AssemblyDebuggerData const& _code)
{
Q_UNUSED(_reason);
if (_success)
{
m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates));
m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code)));
m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code)));
m_appEngine->rootContext()->setContextProperty("contractCallReturnParameters", QVariant::fromValue(new QVariableDefinitionList(_returnParam)));
this->addContentOn(this);
}
else
m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed"));
}
void AssemblyDebuggerControl::runTransaction(TransactionSettings const& _tr)
{
QtConcurrent::run([this, _tr]()
{
callContract(_tr, m_previousDebugResult.contractAddress);
});
}

84
mix/AssemblyDebuggerControl.h

@ -0,0 +1,84 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerControl.h
* @author Yann yann@ethdev.com
* @date 2014
* Extension which display debugging steps in assembly code.
*/
#pragma once
#include <QKeySequence>
#include <QTextDocument>
#include "Extension.h"
#include "ConstantCompilationModel.h"
#include "TransactionListModel.h"
#include "AssemblyDebuggerModel.h"
#include "AppContext.h"
using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>;
enum DebuggingStatusResult
{
Ok,
Compilationfailed
};
Q_DECLARE_METATYPE(AssemblyDebuggerData)
Q_DECLARE_METATYPE(DebuggingStatusResult)
Q_DECLARE_METATYPE(dev::mix::DebuggingContent)
namespace dev
{
namespace mix
{
/**
* @brief Extension which display transaction creation or transaction call debugging. handle: F5 to deploy contract, F6 to reset state.
*/
class AssemblyDebuggerControl: public Extension
{
Q_OBJECT
public:
AssemblyDebuggerControl(QTextDocument* _doc);
~AssemblyDebuggerControl() {}
void start() const override;
QString title() const override;
QString contentUrl() const override;
private:
void deployContract(QString _source);
void callContract(TransactionSettings _tr, Address _contract);
void finalizeExecution(DebuggingContent _content);
std::unique_ptr<AssemblyDebuggerModel> m_modelDebugger;
std::unique_ptr<ConstantCompilationModel> m_compilation;
DebuggingContent m_previousDebugResult; //TODO: to be replaced in a more consistent struct. Used for now to keep the contract address in case of future transaction call.
QTextDocument* m_doc;
public slots:
/// Handle key pressed. F5 deploy contract - F6 reset state.
void keyPressed(int);
/// Update UI with machine states result. Display a modal dialog.
void updateGUI(bool _success, DebuggingStatusResult const& _reason, QList<QVariableDefinition*> const& _returnParams = QList<QVariableDefinition*>(), QList<QObject*> const& _wStates = QList<QObject*>(), AssemblyDebuggerData const& _code = AssemblyDebuggerData());
/// Run the given transaction.
void runTransaction(TransactionSettings const& _tr);
signals:
/// Emited when machine states are available.
void dataAvailable(bool _success, DebuggingStatusResult const& _reason, QList<QVariableDefinition*> const& _returnParams = QList<QVariableDefinition*>(), QList<QObject*> const& _wStates = QList<QObject*>(), AssemblyDebuggerData const& _code = AssemblyDebuggerData());
};
}
}

103
mix/AssemblyDebuggerCtrl.cpp

@ -1,103 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* display opcode debugging.
*/
#include <QtConcurrent/QtConcurrent>
#include <QDebug>
#include <QQmlContext>
#include <QModelIndex>
#include "libethereum/Transaction.h"
#include "AssemblyDebuggerModel.h"
#include "AssemblyDebuggerCtrl.h"
#include "TransactionBuilder.h"
#include "KeyEventManager.h"
#include "AppContext.h"
#include "DebuggingStateWrapper.h"
using namespace dev::mix;
AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog)
{
qRegisterMetaType<AssemblyDebuggerData>();
qRegisterMetaType<DebuggingStatusResult>();
connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)),
this, SLOT(updateGUI(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)), Qt::QueuedConnection);
m_modelDebugger = std::unique_ptr<AssemblyDebuggerModel>(new AssemblyDebuggerModel);
m_doc = _doc;
}
QString AssemblyDebuggerCtrl::contentUrl() const
{
return QStringLiteral("qrc:/qml/Debugger.qml");
}
QString AssemblyDebuggerCtrl::title() const
{
return QApplication::tr("debugger");
}
void AssemblyDebuggerCtrl::start() const
{
//start to listen on F5
m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int)));
}
void AssemblyDebuggerCtrl::keyPressed(int _key)
{
if (_key == Qt::Key_F5)
{
QString code = m_doc->toPlainText();
QtConcurrent::run([this, code]()
{
if (!m_modelDebugger->compile(m_doc->toPlainText()))
{
emit dataAvailable(false, DebuggingStatusResult::Compilationfailed);
return;
}
u256 gasPrice = 10000000000000;
u256 gas = 1000000;
u256 amount = 100;
DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText());
//we need to wrap states in a QObject before sending to QML.
QList<QObject*> wStates;
for(int i = 0; i < debuggingContent.states.size(); i++)
{
DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes(), this);
s->setState(debuggingContent.states.at(i));
wStates.append(s);
}
AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this);
emit dataAvailable(true, DebuggingStatusResult::Ok, wStates, code);
});
}
}
void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates, AssemblyDebuggerData _code)
{
Q_UNUSED(reason);
if (success)
{
m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates));
m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code)));
m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code)));
this->addContentOn(this);
}
else
m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed"));
}

70
mix/AssemblyDebuggerCtrl.h

@ -1,70 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QKeySequence>
#include "QTextDocument"
#include "Extension.h"
#include "ConstantCompilationModel.h"
#include "AssemblyDebuggerModel.h"
#include "AppContext.h"
using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>;
enum DebuggingStatusResult
{
Ok,
Compilationfailed
};
Q_DECLARE_METATYPE(AssemblyDebuggerData)
Q_DECLARE_METATYPE(DebuggingStatusResult)
namespace dev
{
namespace mix
{
class AssemblyDebuggerCtrl: public Extension
{
Q_OBJECT
public:
AssemblyDebuggerCtrl(QTextDocument*);
~AssemblyDebuggerCtrl() {}
void start() const override;
QString title() const override;
QString contentUrl() const override;
private:
std::unique_ptr<AssemblyDebuggerModel> m_modelDebugger;
QTextDocument* m_doc;
public slots:
void keyPressed(int);
void updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData());
signals:
void dataAvailable(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData());
};
}
}

65
mix/AssemblyDebuggerModel.cpp

@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file AssemblyDebuggerModel.h /** @file AssemblyDebuggerModel.cpp
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* used as a model to debug contract assembly code. * used as a model to debug contract assembly code.
@ -24,7 +24,7 @@
#include <libethereum/Transaction.h> #include <libethereum/Transaction.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include "AppContext.h" #include "AppContext.h"
#include "TransactionBuilder.h" #include "TransactionListModel.h"
#include "AssemblyDebuggerModel.h" #include "AssemblyDebuggerModel.h"
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
@ -38,15 +38,14 @@ AssemblyDebuggerModel::AssemblyDebuggerModel():
m_baseState(Address(), m_overlayDB, BaseState::Empty) m_baseState(Address(), m_overlayDB, BaseState::Empty)
{ {
m_baseState.addBalance(m_userAccount.address(), 10000000 * ether); m_baseState.addBalance(m_userAccount.address(), 10000000 * ether);
m_executiveState = m_baseState;
m_currentExecution = std::unique_ptr<Executive>(new Executive(m_executiveState, LastHashes(), 0)); m_currentExecution = std::unique_ptr<Executive>(new Executive(m_executiveState, LastHashes(), 0));
} }
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) DebuggingContent AssemblyDebuggerModel::executeTransaction(bytesConstRef const& _rawTransaction)
{ {
// Reset the state back to our clean premine. QList<DebuggingState> machineStates;
m_executiveState = m_baseState; m_currentExecution.reset(new Executive(m_executiveState, LastHashes(), 0));
QList<DebuggingState> states;
m_currentExecution->setup(_rawTransaction); m_currentExecution->setup(_rawTransaction);
std::vector<DebuggingState const*> levels; std::vector<DebuggingState const*> levels;
bytes code; bytes code;
@ -65,21 +64,21 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by
} }
if (levels.size() < ext.depth) if (levels.size() < ext.depth)
levels.push_back(&states.back()); levels.push_back(&machineStates.back());
else else
levels.resize(ext.depth); levels.resize(ext.depth);
states.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), machineStates.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(),
vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
}; };
m_currentExecution->go(onOp); m_currentExecution->go(onOp);
cdebug << states.size();
m_currentExecution->finalize(onOp); m_currentExecution->finalize(onOp);
m_executiveState.completeMine();
DebuggingContent d; DebuggingContent d;
d.states = states; d.returnValue = m_currentExecution->out().toVector();
d.machineStates = machineStates;
d.executionCode = code; d.executionCode = code;
d.executionData = data; d.executionData = data;
d.contentAvailable = true; d.contentAvailable = true;
@ -87,34 +86,32 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by
return d; return d;
} }
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates( DebuggingContent AssemblyDebuggerModel::deployContract(bytes const& _code)
dev::u256 _value,
dev::u256 _gasPrice,
dev::u256 _gas,
QString _code
)
{
ConstantCompilationModel compiler;
CompilerResult res = compiler.compile(_code);
if (!res.success)
{ {
DebuggingContent r; u256 gasPrice = 10000000000000;
r.contentAvailable = false; u256 gas = 1000000;
r.message = QApplication::tr("compilation failed"); u256 amount = 100;
return r; Transaction _tr(amount, gasPrice, min(gas, m_baseState.gasLimitRemaining()), _code, m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret());
bytes b = _tr.rlp();
dev::bytesConstRef bytesRef = &b;
DebuggingContent d = executeTransaction(bytesRef);
h256 th = sha3(rlpList(_tr.sender(), _tr.nonce()));
d.contractAddress = right160(th);
return d;
} }
TransactionBuilder trBuild; DebuggingContent AssemblyDebuggerModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr)
Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, min(_gas, m_baseState.gasLimitRemaining()), res.bytes, {
m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret()); Transaction tr = Transaction(_tr.value, _tr.gasPrice, min(_tr.gas, m_baseState.gasLimitRemaining()), _contract, _data, m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret());
bytes b = tr.rlp(); bytes b = tr.rlp();
dev::bytesConstRef bytesRef = &b; dev::bytesConstRef bytesRef = &b;
return getContractInitiationDebugStates(bytesRef); DebuggingContent d = executeTransaction(bytesRef);
d.contractAddress = tr.receiveAddress();
return d;
} }
bool AssemblyDebuggerModel::compile(QString _code) void AssemblyDebuggerModel::resetState()
{ {
ConstantCompilationModel compiler; // Reset the state back to our clean premine.
CompilerResult res = compiler.compile(_code); m_executiveState = m_baseState;
return res.success;
} }

14
mix/AssemblyDebuggerModel.h

@ -14,7 +14,7 @@
/** @file AssemblyDebuggerModel.h /** @file AssemblyDebuggerModel.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* serves as a model to debug contract assembly code. * Used as a model to debug contract assembly code.
*/ */
#pragma once #pragma once
@ -26,6 +26,7 @@
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/Executive.h> #include <libethereum/Executive.h>
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
#include "TransactionListModel.h"
namespace dev namespace dev
{ {
@ -39,9 +40,12 @@ class AssemblyDebuggerModel
{ {
public: public:
AssemblyDebuggerModel(); AssemblyDebuggerModel();
DebuggingContent getContractInitiationDebugStates(u256, u256, u256, QString); /// Call function in a already deployed contract.
DebuggingContent getContractInitiationDebugStates(bytesConstRef); DebuggingContent callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr);
bool compile(QString); /// Deploy the contract described by _code.
DebuggingContent deployContract(bytes const& _code);
/// Reset state to the base state.
void resetState();
private: private:
KeyPair m_userAccount; KeyPair m_userAccount;
@ -49,8 +53,8 @@ private:
eth::State m_baseState; eth::State m_baseState;
eth::State m_executiveState; eth::State m_executiveState;
std::unique_ptr<eth::Executive> m_currentExecution; std::unique_ptr<eth::Executive> m_currentExecution;
DebuggingContent executeTransaction(dev::bytesConstRef const& _rawTransaction);
}; };
} }
} }

30
mix/CodeEditorExtensionManager.cpp

@ -26,8 +26,9 @@
#include <QQmlComponent> #include <QQmlComponent>
#include <QQuickTextDocument> #include <QQuickTextDocument>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "ConstantCompilationCtrl.h" #include "ConstantCompilationControl.h"
#include "AssemblyDebuggerCtrl.h" #include "AssemblyDebuggerControl.h"
#include "TransactionListView.h"
#include "AppContext.h" #include "AppContext.h"
#include "CodeEditorExtensionManager.h" #include "CodeEditorExtensionManager.h"
using namespace dev::mix; using namespace dev::mix;
@ -48,7 +49,17 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
{ {
QQuickTextDocument* qqdoc = doc.value<QQuickTextDocument*>(); QQuickTextDocument* qqdoc = doc.value<QQuickTextDocument*>();
if (qqdoc) if (qqdoc)
{
m_doc = qqdoc->textDocument(); m_doc = qqdoc->textDocument();
auto args = QApplication::arguments();
if (args.length() > 1)
{
QString path = args[1];
QFile file(path);
if (file.exists() && file.open(QFile::ReadOnly))
m_doc->setPlainText(file.readAll());
}
}
} }
} }
catch (...) catch (...)
@ -59,8 +70,12 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
void CodeEditorExtensionManager::initExtensions() void CodeEditorExtensionManager::initExtensions()
{ {
initExtension(std::make_shared<ConstantCompilationCtrl>(m_doc)); initExtension(std::make_shared<ConstantCompilationControl>(m_doc));
initExtension(std::make_shared<AssemblyDebuggerCtrl>(m_doc)); std::shared_ptr<AssemblyDebuggerControl> debug = std::make_shared<AssemblyDebuggerControl>(m_doc);
std::shared_ptr<TransactionListView> tr = std::make_shared<TransactionListView>(m_doc);
QObject::connect(tr->model(), &TransactionListModel::transactionStarted, debug.get(), &AssemblyDebuggerControl::runTransaction);
initExtension(debug);
initExtension(tr);
} }
void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext) void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
@ -71,6 +86,8 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
{ {
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab)
_ext->addTabOn(m_tabView); _ext->addTabOn(m_tabView);
else if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightTab)
_ext->addTabOn(m_rightTabView);
} }
catch (...) catch (...)
{ {
@ -88,6 +105,11 @@ void CodeEditorExtensionManager::setEditor(QQuickItem* _editor)
this->initExtensions(); this->initExtensions();
} }
void CodeEditorExtensionManager::setRightTabView(QQuickItem* _tabView)
{
m_rightTabView = _tabView;
}
void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView) void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView)
{ {
m_tabView = _tabView; m_tabView = _tabView;

17
mix/CodeEditorExtensionManager.h

@ -22,40 +22,49 @@
#pragma once #pragma once
#include "memory"
#include <QQuickItem> #include <QQuickItem>
#include <QTextDocument> #include <QTextDocument>
#include <QVector> #include <QVector>
#include "ConstantCompilationCtrl.h" #include "ConstantCompilationControl.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
/**
* @brief Init and provides connection between extensions.
*/
class CodeEditorExtensionManager: public QObject class CodeEditorExtensionManager: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QQuickItem* editor MEMBER m_editor WRITE setEditor) Q_PROPERTY(QQuickItem* editor MEMBER m_editor WRITE setEditor)
Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView) Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView)
Q_PROPERTY(QQuickItem* rightTabView MEMBER m_rightTabView WRITE setRightTabView)
public: public:
CodeEditorExtensionManager() {} CodeEditorExtensionManager() {}
~CodeEditorExtensionManager(); ~CodeEditorExtensionManager();
/// Initialize all extensions.
void initExtensions(); void initExtensions();
/// Initialize extension.
void initExtension(std::shared_ptr<Extension>); void initExtension(std::shared_ptr<Extension>);
/// Set current text editor.
void setEditor(QQuickItem*); void setEditor(QQuickItem*);
/// Set current tab view
void setTabView(QQuickItem*); void setTabView(QQuickItem*);
/// Set current right tab view.
void setRightTabView(QQuickItem*);
private: private:
QQuickItem* m_editor; QQuickItem* m_editor;
QVector<std::shared_ptr<Extension>> m_features; QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_tabView; QQuickItem* m_tabView;
QQuickItem* m_rightTabView;
QTextDocument* m_doc; QTextDocument* m_doc;
void loadEditor(QQuickItem*); void loadEditor(QQuickItem* _editor);
}; };
} }
} }

28
mix/ConstantCompilationCtrl.cpp → mix/ConstantCompilationControl.cpp

@ -14,56 +14,58 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file ConstantCompilationCtrl.cpp /** @file ConstantCompilationControl.cpp
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Ethereum IDE client. * Ethereum IDE client.
*/ */
#include <QQmlContext>
#include <QQuickItem> #include <QQuickItem>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QApplication> #include <QApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QtCore/QtCore> #include <QtCore/QtCore>
#include <QDebug> #include <QDebug>
#include "ConstantCompilationCtrl.h" #include "ConstantCompilationControl.h"
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
#include "QContractDefinition.h"
using namespace dev::mix; using namespace dev::mix;
ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab) ConstantCompilationControl::ConstantCompilationControl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab)
{ {
m_editor = _doc; m_editor = _doc;
m_compilationModel = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel()); m_compilationModel = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel());
} }
QString ConstantCompilationCtrl::contentUrl() const QString ConstantCompilationControl::contentUrl() const
{ {
return QStringLiteral("qrc:/qml/BasicContent.qml"); return QStringLiteral("qrc:/qml/BasicContent.qml");
} }
QString ConstantCompilationCtrl::title() const QString ConstantCompilationControl::title() const
{ {
return QApplication::tr("compiler"); return QApplication::tr("compiler");
} }
void ConstantCompilationCtrl::start() const void ConstantCompilationControl::start() const
{ {
connect(m_editor, SIGNAL(contentsChange(int,int,int)), this, SLOT(compile())); connect(m_editor, SIGNAL(contentsChange(int,int,int)), this, SLOT(compile()));
} }
void ConstantCompilationCtrl::compile() void ConstantCompilationControl::compile()
{ {
QString codeContent = m_editor->toPlainText().replace("\n", ""); QString codeContent = m_editor->toPlainText().replace("\n", "");
if (codeContent.isEmpty()) if (codeContent.isEmpty())
{
resetOutPut(); resetOutPut();
return; else
} {
CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " "));
writeOutPut(res); writeOutPut(res);
} }
}
void ConstantCompilationCtrl::resetOutPut() void ConstantCompilationControl::resetOutPut()
{ {
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively); QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively); QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
@ -71,7 +73,7 @@ void ConstantCompilationCtrl::resetOutPut()
content->setProperty("text", ""); content->setProperty("text", "");
} }
void ConstantCompilationCtrl::writeOutPut(CompilerResult const& _res) void ConstantCompilationControl::writeOutPut(CompilerResult const& _res)
{ {
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively); QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively); QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
@ -80,13 +82,11 @@ void ConstantCompilationCtrl::writeOutPut(CompilerResult const& _res)
status->setProperty("text", "succeeded"); status->setProperty("text", "succeeded");
status->setProperty("color", "green"); status->setProperty("color", "green");
content->setProperty("text", _res.hexCode); content->setProperty("text", _res.hexCode);
qDebug() << QString(QApplication::tr("compile succeeded") + " " + _res.hexCode);
} }
else else
{ {
status->setProperty("text", "failure"); status->setProperty("text", "failure");
status->setProperty("color", "red"); status->setProperty("color", "red");
content->setProperty("text", _res.comment); content->setProperty("text", _res.comment);
qDebug() << QString(QApplication::tr("compile failed") + " " + _res.comment);
} }
} }

15
mix/ConstantCompilationCtrl.h → mix/ConstantCompilationControl.h

@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file ConstantCompilationCtrl.h /** @file ConstantCompilationControl.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Ethereum IDE client. * Ethereum IDE client.
@ -28,13 +28,16 @@ namespace dev
namespace mix namespace mix
{ {
class ConstantCompilationCtrl: public Extension /**
* @brief Extension which display assembly code of the contract being edited.
*/
class ConstantCompilationControl: public Extension
{ {
Q_OBJECT Q_OBJECT
public: public:
ConstantCompilationCtrl(QTextDocument*); ConstantCompilationControl(QTextDocument* _doc);
~ConstantCompilationCtrl() {} ~ConstantCompilationControl() {}
void start() const override; void start() const override;
QString title() const override; QString title() const override;
QString contentUrl() const override; QString contentUrl() const override;
@ -42,13 +45,13 @@ public:
private: private:
QTextDocument* m_editor; QTextDocument* m_editor;
std::unique_ptr<ConstantCompilationModel> m_compilationModel; std::unique_ptr<ConstantCompilationModel> m_compilationModel;
void writeOutPut(CompilerResult const&); void writeOutPut(CompilerResult const& _res);
void resetOutPut(); void resetOutPut();
public slots: public slots:
/// Compile text editor content.
void compile(); void compile();
}; };
} }
} }

3
mix/ConstantCompilationModel.cpp

@ -24,13 +24,16 @@
#include <QObject> #include <QObject>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/CompilerStack.h> #include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h> #include <libsolidity/SourceReferenceFormatter.h>
#include <libsolidity/NameAndTypeResolver.h>
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::mix; using namespace dev::mix;
using namespace dev::solidity;
CompilerResult ConstantCompilationModel::compile(QString _code) CompilerResult ConstantCompilationModel::compile(QString _code)
{ {

10
mix/ConstantCompilationModel.h

@ -22,14 +22,18 @@
#pragma once #pragma once
#include <libevm/VM.h>
#include <QObject> #include <QObject>
#include <libevm/VM.h>
#include <libsolidity/AST.h>
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
/**
* @brief Provides compiler result information.
*/
struct CompilerResult struct CompilerResult
{ {
QString hexCode; QString hexCode;
@ -38,12 +42,16 @@ struct CompilerResult
bool success; bool success;
}; };
/**
* @brief Compile source code using the solidity library.
*/
class ConstantCompilationModel class ConstantCompilationModel
{ {
public: public:
ConstantCompilationModel() {} ConstantCompilationModel() {}
~ConstantCompilationModel() {} ~ConstantCompilationModel() {}
/// Compile code.
CompilerResult compile(QString _code); CompilerResult compile(QString _code);
}; };

131
mix/ContractCallDataEncoder.cpp

@ -0,0 +1,131 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ContractCallDataEncoder.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QDebug>
#include <QMap>
#include <QStringList>
#include <libdevcore/CommonJS.h>
#include <libsolidity/AST.h>
#include "QVariableDeclaration.h"
#include "QVariableDefinition.h"
#include "ContractCallDataEncoder.h"
using namespace dev;
using namespace dev::solidity;
using namespace dev::mix;
bytes ContractCallDataEncoder::encodedData()
{
return m_encodedData;
}
void ContractCallDataEncoder::encode(int _functionIndex)
{
bytes i = jsToBytes(std::to_string(_functionIndex));
m_encodedData.insert(m_encodedData.end(), i.begin(), i.end());
}
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, bool _value)
{
return encode(_dec, QString(formatBool(_value)));
}
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, QString _value)
{
int padding = this->padding(_dec->type());
bytes data = padded(jsToBytes(_value.toStdString()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
}
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, u256 _value)
{
int padding = this->padding(_dec->type());
std::ostringstream s;
s << std::hex << "0x" << _value;
bytes data = padded(jsToBytes(s.str()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
encodedData();
}
QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> _returnParameters, bytes _value)
{
QList<QVariableDefinition*> r;
std::string returnValue = toJS(_value);
returnValue = returnValue.substr(2, returnValue.length() - 1);
for (int k = 0; k <_returnParameters.length(); k++)
{
QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k);
int padding = this->padding(dec->type());
std::string rawParam = returnValue.substr(0, padding * 2);
r.append(new QVariableDefinition(dec, convertToReadable(unpadLeft(rawParam), dec)));
returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1);
}
return r;
}
int ContractCallDataEncoder::padding(QString type)
{
// TODO : to be improved (load types automatically from solidity library).
if (type.indexOf("uint") != -1)
return integerPadding(type.remove("uint").toInt());
else if (type.indexOf("int") != -1)
return integerPadding(type.remove("int").toInt());
else if (type.indexOf("bool") != -1)
return 1;
else if ((type.indexOf("address") != -1))
return 20;
else
return 0;
}
int ContractCallDataEncoder::integerPadding(int bitValue)
{
return bitValue / 8;
}
QString ContractCallDataEncoder::formatBool(bool _value)
{
return (_value ? "1" : "0");
}
QString ContractCallDataEncoder::convertToReadable(std::string _v, QVariableDeclaration* _dec)
{
if (_dec->type().indexOf("int") != -1)
return convertToInt(_v);
else if (_dec->type().indexOf("bool") != -1)
return convertToBool(_v);
else
return QString::fromStdString(_v);
}
QString ContractCallDataEncoder::convertToBool(std::string _v)
{
return _v == "1" ? "true" : "false";
}
QString ContractCallDataEncoder::convertToInt(std::string _v)
{
//TO DO to be improve to manage all int, uint size (128, 256, ...) in ethereum QML types task #612.
int x = std::stol(_v, nullptr, 16);
std::stringstream ss;
ss << std::dec << x;
return QString::fromStdString(ss.str());
}

64
mix/ContractCallDataEncoder.h

@ -0,0 +1,64 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ContractCallDataEncoder.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include "QVariableDeclaration.h"
#include "QVariableDefinition.h"
namespace dev
{
namespace mix
{
/**
* @brief Encode/Decode data to be sent to a transaction or to be displayed in a view.
*/
class ContractCallDataEncoder
{
public:
ContractCallDataEncoder() {}
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration* _dec, QString _value);
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration* _dec, u256 _value);
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration* _dec, bool _value);
/// Encode index of the function to call.
void encode(int _functionIndex);
/// Decode variable in order to be sent to QML view.
QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> _dec, bytes _value);
/// Get all encoded data encoded by encode function.
bytes encodedData();
private:
int padding(QString _type);
bytes m_encodedData;
static QString convertToReadable(std::string _v, QVariableDeclaration* _dec);
static QString convertToBool(std::string _v);
static QString convertToInt(std::string _v);
static int integerPadding(int _bitValue);
static QString formatBool(bool _value);
};
}
}

19
mix/DebuggingStateWrapper.cpp

@ -22,17 +22,18 @@
#include <QApplication> #include <QApplication>
#include <QDebug> #include <QDebug>
#include "libevmcore/Instruction.h" #include <QPointer>
#include "libdevcore/CommonJS.h" #include <libevmcore/Instruction.h>
#include "libdevcrypto/Common.h" #include <libdevcore/CommonJS.h>
#include "libevmcore/Instruction.h" #include <libdevcrypto/Common.h>
#include "libdevcore/Common.h" #include <libevmcore/Instruction.h>
#include <libdevcore/Common.h>
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::mix; using namespace dev::mix;
std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code, QObject* _objUsedAsParent) std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code)
{ {
QList<QObject*> codeStr; QList<QObject*> codeStr;
QMap<int, int> codeMapping; QMap<int, int> codeMapping;
@ -52,7 +53,7 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc)));
i += bc; i += bc;
} }
HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent); QPointer<HumanReadableCode> humanCode(new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line));
codeStr.append(humanCode); codeStr.append(humanCode);
} }
catch (...) catch (...)
@ -62,7 +63,7 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
break; // probably hit data segment break; // probably hit data segment
} }
} }
return std::make_tuple(codeStr, new QQMLMap(codeMapping, _objUsedAsParent)); return std::make_tuple(codeStr, QPointer<QQMLMap>(new QQMLMap(codeMapping)));
} }
QString DebuggingStateWrapper::gasLeft() QString DebuggingStateWrapper::gasLeft()
@ -99,7 +100,7 @@ QString DebuggingStateWrapper::debugStorage()
{ {
std::stringstream s; std::stringstream s;
for (auto const& i: m_state.storage) for (auto const& i: m_state.storage)
s << "@" << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << prettyU256(i.second); s << "@" << prettyU256(i.first) << " " << prettyU256(i.second);
return QString::fromStdString(s.str()); return QString::fromStdString(s.str());
} }

74
mix/DebuggingStateWrapper.h

@ -23,15 +23,20 @@
#pragma once #pragma once
#include <QStringList> #include <QStringList>
#include "libethereum/State.h" #include <QMap>
#include "libethereum/Executive.h" #include <libdevcore/Common.h>
#include "libdevcore/Common.h" #include <libethereum/State.h>
#include <libethereum/Executive.h>
#include "QVariableDefinition.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
/**
* @brief Store information about a machine state.
*/
struct DebuggingState struct DebuggingState
{ {
uint64_t steps; uint64_t steps;
@ -47,13 +52,19 @@ struct DebuggingState
std::vector<DebuggingState const*> levels; std::vector<DebuggingState const*> levels;
}; };
/**
* @brief Store information about a machine states.
*/
struct DebuggingContent struct DebuggingContent
{ {
QList<DebuggingState> states; QList<DebuggingState> machineStates;
bytes executionCode; bytes executionCode;
bytesConstRef executionData; bytesConstRef executionData;
Address contractAddress;
bool contentAvailable; bool contentAvailable;
QString message; QString message;
bytes returnValue;
QList<QVariableDefinition*> returnParameters;
}; };
/** /**
@ -62,12 +73,14 @@ struct DebuggingContent
class HumanReadableCode: public QObject class HumanReadableCode: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString line READ line) Q_PROPERTY(QString line READ line CONSTANT)
Q_PROPERTY(int processIndex READ processIndex) Q_PROPERTY(int processIndex READ processIndex CONSTANT)
public: public:
HumanReadableCode(QString _line, int _processIndex, QObject* _parent): QObject(_parent), m_line(_line), m_processIndex(_processIndex) {} HumanReadableCode(QString _line, int _processIndex): QObject(), m_line(_line), m_processIndex(_processIndex) {}
/// Get the assembly code line.
QString line() { return m_line; } QString line() { return m_line; }
/// Get corresponding index.
int processIndex() { return m_processIndex; } int processIndex() { return m_processIndex; }
private: private:
@ -84,7 +97,8 @@ class QQMLMap: public QObject
Q_OBJECT Q_OBJECT
public: public:
QQMLMap(QMap<int, int> _map, QObject* _parent): QObject(_parent), m_map(_map) { } QQMLMap(QMap<int, int> _map): QObject(), m_map(_map) { }
/// Get the value associated with _key store in n_map.
Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); }
private: private:
@ -97,36 +111,51 @@ private:
class DebuggingStateWrapper: public QObject class DebuggingStateWrapper: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int step READ step) Q_PROPERTY(int step READ step CONSTANT)
Q_PROPERTY(int curPC READ curPC) Q_PROPERTY(int curPC READ curPC CONSTANT)
Q_PROPERTY(QString gasCost READ gasCost) Q_PROPERTY(QString gasCost READ gasCost CONSTANT)
Q_PROPERTY(QString gas READ gas) Q_PROPERTY(QString gas READ gas CONSTANT)
Q_PROPERTY(QString gasLeft READ gasLeft) Q_PROPERTY(QString gasLeft READ gasLeft CONSTANT)
Q_PROPERTY(QString debugStack READ debugStack) Q_PROPERTY(QString debugStack READ debugStack CONSTANT)
Q_PROPERTY(QString debugStorage READ debugStorage) Q_PROPERTY(QString debugStorage READ debugStorage CONSTANT)
Q_PROPERTY(QString debugMemory READ debugMemory) Q_PROPERTY(QString debugMemory READ debugMemory CONSTANT)
Q_PROPERTY(QString debugCallData READ debugCallData) Q_PROPERTY(QString debugCallData READ debugCallData CONSTANT)
Q_PROPERTY(QString headerInfo READ headerInfo) Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT)
Q_PROPERTY(QString endOfDebug READ endOfDebug) Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT)
Q_PROPERTY(QStringList levels READ levels) Q_PROPERTY(QStringList levels READ levels CONSTANT)
public: public:
DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {} DebuggingStateWrapper(bytes _code, bytes _data): QObject(), m_code(_code), m_data(_data) {}
/// Get the step of this machine states.
int step() { return (int)m_state.steps; } int step() { return (int)m_state.steps; }
/// Get the proccessed code index.
int curPC() { return (int)m_state.curPC; } int curPC() { return (int)m_state.curPC; }
/// Get gas left.
QString gasLeft(); QString gasLeft();
/// Get gas cost.
QString gasCost(); QString gasCost();
/// Get gas used.
QString gas(); QString gas();
/// Get stack.
QString debugStack(); QString debugStack();
/// Get storage.
QString debugStorage(); QString debugStorage();
/// Get memory.
QString debugMemory(); QString debugMemory();
/// Get call data.
QString debugCallData(); QString debugCallData();
/// Get info to be displayed in the header.
QString headerInfo(); QString headerInfo();
/// get end of debug information.
QString endOfDebug(); QString endOfDebug();
/// Get all previous steps.
QStringList levels(); QStringList levels();
/// Get the current processed machine state.
DebuggingState state() { return m_state; } DebuggingState state() { return m_state; }
/// Set the current processed machine state.
void setState(DebuggingState _state) { m_state = _state; } void setState(DebuggingState _state) { m_state = _state; }
static std::tuple<QList<QObject*>, QQMLMap*> getHumanReadableCode(bytes const& _code, QObject* _objUsedAsParent); /// Convert all machine state in human readable code.
static std::tuple<QList<QObject*>, QQMLMap*> getHumanReadableCode(bytes const& _code);
private: private:
DebuggingState m_state; DebuggingState m_state;
@ -135,5 +164,4 @@ private:
}; };
} }
} }

5
mix/Extension.cpp

@ -20,6 +20,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <QDebug> #include <QDebug>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libwebthree/WebThree.h>
#include "Extension.h" #include "Extension.h"
#include "AppContext.h" #include "AppContext.h"
using namespace dev; using namespace dev;
@ -65,10 +66,10 @@ void Extension::addContentOn(QObject* _view)
Q_UNUSED(_view); Q_UNUSED(_view);
if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog)
{ {
QQmlComponent* component = new QQmlComponent(AppContext::getInstance()->appEngine(), QUrl(contentUrl()), _view);
QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("dialog", Qt::FindChildrenRecursively); QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("dialog", Qt::FindChildrenRecursively);
QObject* dialogWinComponent = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("modalDialogContent", Qt::FindChildrenRecursively); QObject* dialogWinComponent = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("modalDialogContent", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(dialogWin, "close"); dialogWinComponent->setProperty("sourceComponent", QVariant::fromValue(component));
dialogWinComponent->setProperty("source", contentUrl());
dialogWin->setProperty("title", title()); dialogWin->setProperty("title", title());
QMetaObject::invokeMethod(dialogWin, "open"); QMetaObject::invokeMethod(dialogWin, "open");
} }

11
mix/Extension.h

@ -31,6 +31,7 @@ namespace mix
enum ExtensionDisplayBehavior enum ExtensionDisplayBehavior
{ {
Tab, Tab,
RightTab,
ModalDialog ModalDialog
}; };
@ -42,12 +43,19 @@ class Extension: public QObject
public: public:
Extension(); Extension();
Extension(ExtensionDisplayBehavior _displayBehavior); Extension(ExtensionDisplayBehavior _displayBehavior);
/// Return the QML url of the view to display.
virtual QString contentUrl() const { return ""; } virtual QString contentUrl() const { return ""; }
/// Return the title of this extension.
virtual QString title() const { return ""; } virtual QString title() const { return ""; }
/// Initialize extension.
virtual void start() const {} virtual void start() const {}
void addContentOn(QObject* _tabView); /// Add the view define in contentUrl() in the _view QObject.
void addContentOn(QObject* _view);
/// Add the view define in contentUrl() in the _view QObject (_view has to be a tab).
void addTabOn(QObject* _view); void addTabOn(QObject* _view);
/// Modify the display behavior of this extension.
void setDisplayBehavior(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } void setDisplayBehavior(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; }
/// Get the display behavior of thi extension.
ExtensionDisplayBehavior getDisplayBehavior() { return m_displayBehavior; } ExtensionDisplayBehavior getDisplayBehavior() { return m_displayBehavior; }
protected: protected:
@ -61,5 +69,4 @@ private:
}; };
} }
} }

9
mix/KeyEventManager.h

@ -17,12 +17,13 @@
/** @file KeyEventManager.h /** @file KeyEventManager.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* use as an event handler for all classes which need keyboard interactions * Used as an event handler for all classes which need keyboard interactions
*/ */
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QVariant>
class KeyEventManager: public QObject class KeyEventManager: public QObject
{ {
@ -30,13 +31,17 @@ class KeyEventManager: public QObject
public: public:
KeyEventManager() {} KeyEventManager() {}
/// Allows _receiver to handle key pressed event.
void registerEvent(const QObject* _receiver, const char* _slot); void registerEvent(const QObject* _receiver, const char* _slot);
/// Unregister _receiver.
void unRegisterEvent(QObject* _receiver); void unRegisterEvent(QObject* _receiver);
signals: signals:
void onKeyPressed(int); /// Emited when a key is pressed.
void onKeyPressed(int _event);
public slots: public slots:
/// Called when a key is pressed.
void keyPressed(QVariant _event); void keyPressed(QVariant _event);
}; };

1
mix/MixApplication.h

@ -41,5 +41,4 @@ public:
}; };
} }
} }

30
mix/TransactionBuilder.h → mix/QBasicNodeDefinition.h

@ -1,43 +1,49 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file TransactionBuilder.h /** @file QBasicNodeDefinition.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Ethereum IDE client.
*/ */
#pragma once #pragma once
#include <QString> #include <QObject>
#include "libdevcore/Common.h" #include <libsolidity/AST.h>
#include "libethereum/Transaction.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
class TransactionBuilder class QBasicNodeDefinition: public QObject
{ {
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
public: public:
TransactionBuilder() {} QBasicNodeDefinition(): QObject() {}
dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, ~QBasicNodeDefinition() {}
QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; QBasicNodeDefinition(solidity::Declaration const* _d): QObject(), m_name(QString::fromStdString(_d->getName())) {}
dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, /// Get the name of the node.
dev::bytes _data, dev::u256 _nonce, Secret _secret) const; QString name() const { return m_name; }
private:
QString m_name;
}; };
} }
} }

48
mix/QContractDefinition.cpp

@ -0,0 +1,48 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QContractDefinition.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <QObject>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/AST.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/NameAndTypeResolver.h>
#include "AppContext.h"
#include "QContractDefinition.h"
using namespace dev::solidity;
using namespace dev::mix;
std::shared_ptr<QContractDefinition> QContractDefinition::Contract(QString _source)
{
CompilerStack* comp = AppContext::getInstance()->compiler();
comp->addSource("contract", _source.toStdString());
comp->parse();
ContractDefinition const* def = &comp->getContractDefinition(comp->getContractNames().front());
return std::make_shared<QContractDefinition>(def);
}
void QContractDefinition::initQFunctions()
{
std::vector<FunctionDefinition const*> functions = m_contract->getInterfaceFunctions();
for (unsigned i = 0; i < functions.size(); i++)
m_functions.append(new QFunctionDefinition(functions.at(i), i));
}

53
mix/QContractDefinition.h

@ -0,0 +1,53 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QContractDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#pragma once
#include <QObject>
#include <libsolidity/AST.h>
#include "QFunctionDefinition.h"
#include "QBasicNodeDefinition.h"
namespace dev
{
namespace mix
{
class QContractDefinition: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QList<QFunctionDefinition*> functions READ functions)
public:
QContractDefinition(solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_contract), m_contract(_contract) { initQFunctions(); }
/// Get all the functions of the contract.
QList<QFunctionDefinition*> functions() const { return m_functions; }
/// Get the description (functions, parameters, return parameters, ...) of the contract describes by _code.
static std::shared_ptr<QContractDefinition> Contract(QString _code);
private:
solidity::ContractDefinition const* m_contract;
QList<QFunctionDefinition*> m_functions;
void initQFunctions();
};
}
}

37
mix/QFunctionDefinition.cpp

@ -0,0 +1,37 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QFunctionDefinition.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <libsolidity/AST.h>
#include "QVariableDeclaration.h"
#include "QFunctionDefinition.h"
using namespace dev::solidity;
using namespace dev::mix;
void QFunctionDefinition::initQParameters()
{
std::vector<std::shared_ptr<VariableDeclaration>> parameters = m_functions->getParameterList().getParameters();
for (unsigned i = 0; i < parameters.size(); i++)
m_parameters.append(new QVariableDeclaration(parameters.at(i).get()));
std::vector<std::shared_ptr<VariableDeclaration>> returnParameters = m_functions->getReturnParameters();
for (unsigned i = 0; i < returnParameters.size(); i++)
m_returnParameters.append(new QVariableDeclaration(returnParameters.at(i).get()));
}

58
mix/QFunctionDefinition.h

@ -0,0 +1,58 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QFunctionDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#pragma once
#include <QObject>
#include <libsolidity/AST.h>
#include <QVariableDeclaration.h>
#include "QBasicNodeDefinition.h"
namespace dev
{
namespace mix
{
class QFunctionDefinition: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QList<QVariableDeclaration*> parameters READ parameters)
Q_PROPERTY(int index READ index)
public:
QFunctionDefinition(solidity::FunctionDefinition const* _f, int _index): QBasicNodeDefinition(_f), m_index(_index), m_functions(_f) { initQParameters(); }
/// Get all input parameters of this function.
QList<QVariableDeclaration*> parameters() const { return m_parameters; }
/// Get all return parameters of this function.
QList<QVariableDeclaration*> returnParameters() const { return m_returnParameters; }
/// Get the index of this function on the contract ABI.
int index() const { return m_index; }
private:
int m_index;
solidity::FunctionDefinition const* m_functions;
QList<QVariableDeclaration*> m_parameters;
QList<QVariableDeclaration*> m_returnParameters;
void initQParameters();
};
}
}

49
mix/QVariableDeclaration.h

@ -0,0 +1,49 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QVariableDeclaration.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <libsolidity/AST.h>
#include "QBasicNodeDefinition.h"
#pragma once
namespace dev
{
namespace mix
{
class QVariableDeclaration: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QString type READ type CONSTANT)
public:
QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_variable(_v) {}
/// Get the type of this variable.
QString type() const { return QString::fromStdString(m_variable->getType()->toString()); }
private:
solidity::VariableDeclaration const* m_variable;
};
}
}
Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*)

55
mix/QVariableDefinition.cpp

@ -0,0 +1,55 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QVariableDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#include "QVariableDefinition.h"
using namespace dev::mix;
int QVariableDefinitionList::rowCount(const QModelIndex& _parent) const
{
Q_UNUSED(_parent);
return m_def.size();
}
QVariant QVariableDefinitionList::data(const QModelIndex& _index, int _role) const
{
if (_role != Qt::DisplayRole)
return QVariant();
int i = _index.row();
if (i < 0 || i >= m_def.size())
return QVariant(QVariant::Invalid);
return QVariant::fromValue(m_def.at(i));
}
QHash<int, QByteArray> QVariableDefinitionList::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "variable";
return roles;
}
QVariableDefinition* QVariableDefinitionList::val(int _idx)
{
if (_idx < 0 || _idx >= m_def.size())
return nullptr;
return m_def.at(_idx);
}

72
mix/QVariableDefinition.h

@ -0,0 +1,72 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QVariableDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#pragma once
#include <QAbstractListModel>
#include "QVariableDeclaration.h"
namespace dev
{
namespace mix
{
class QVariableDefinition: public QObject
{
Q_OBJECT
Q_PROPERTY(QString value READ value CONSTANT)
Q_PROPERTY(QVariableDeclaration* declaration READ declaration CONSTANT)
public:
QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {}
/// Return the associated declaration of this variable definition.
QVariableDeclaration* declaration() const { return m_dec; }
/// Return the variable value.
QString value() const { return m_value; }
private:
QString m_value;
QVariableDeclaration* m_dec;
};
class QVariableDefinitionList: public QAbstractListModel
{
Q_OBJECT
public:
QVariableDefinitionList(QList<QVariableDefinition*> _def): m_def(_def) {}
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
/// Return the variable definition at index _idx.
QVariableDefinition* val(int _idx);
/// Return the list of variables.
QList<QVariableDefinition*> def() { return m_def; }
private:
QList<QVariableDefinition*> m_def;
};
}
}
Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*)

40
mix/TransactionBuilder.cpp

@ -1,40 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionBuilder.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include "libethereum/Executive.h"
#include "libdevcore/CommonJS.h"
#include "libdevcore/Common.h"
#include "AppContext.h"
#include "TransactionBuilder.h"
using namespace dev::mix;
using namespace dev::eth;
using namespace dev;
Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPrice, u256 _gas,
bytes _data, u256 _nonce, Secret _secret) const
{
return Transaction(_value, _gasPrice, _gas, _data, _nonce, _secret);
}
Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas,
QString _address, bytes _data, u256 _nonce, Secret _secret) const
{
return Transaction(_value, _gasPrice, _gas, dev::fromString(_address.toStdString()), _data, _nonce, _secret);
}

221
mix/TransactionListModel.cpp

@ -0,0 +1,221 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionListModel.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QObject>
#include <QQmlEngine>
#include <QTextDocument>
#include <QAbstractListModel>
#include <libdevcore/CommonJS.h>
#include "TransactionListModel.h"
#include "QContractDefinition.h"
#include "QFunctionDefinition.h"
#include "QVariableDeclaration.h"
namespace dev
{
namespace mix
{
/// @todo Move this to QML
u256 fromQString(QString const& _s)
{
return dev::jsToU256(_s.toStdString());
}
/// @todo Move this to QML
QString toQString(u256 _value)
{
std::ostringstream s;
s << _value;
return QString::fromStdString(s.str());
}
TransactionListItem::TransactionListItem(int _index, TransactionSettings const& _t, QObject* _parent):
QObject(_parent), m_index(_index), m_title(_t.title), m_functionId(_t.functionId), m_value(toQString(_t.value)),
m_gas(toQString(_t.gas)), m_gasPrice(toQString(_t.gasPrice))
{}
TransactionListModel::TransactionListModel(QObject* _parent, QTextDocument* _document):
QAbstractListModel(_parent), m_document(_document)
{
qRegisterMetaType<TransactionListItem*>("TransactionListItem*");
}
QHash<int, QByteArray> TransactionListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[TitleRole] = "title";
roles[IdRole] = "transactionIndex";
return roles;
}
int TransactionListModel::rowCount(QModelIndex const& _parent) const
{
Q_UNUSED(_parent);
return m_transactions.size();
}
QVariant TransactionListModel::data(QModelIndex const& _index, int _role) const
{
if (_index.row() < 0 || _index.row() >= (int)m_transactions.size())
return QVariant();
auto const& transaction = m_transactions.at(_index.row());
switch (_role)
{
case TitleRole:
return QVariant(transaction.title);
case IdRole:
return QVariant(_index.row());
default:
return QVariant();
}
}
///@todo: get parameters from code model
QList<TransactionParameterItem*> buildParameters(QTextDocument* _document, TransactionSettings const& _transaction, QString const& _functionId)
{
QList<TransactionParameterItem*> params;
try
{
std::shared_ptr<QContractDefinition> contract = QContractDefinition::Contract(_document->toPlainText());
auto functions = contract->functions();
for (auto f : functions)
{
if (f->name() != _functionId)
continue;
auto parameters = f->parameters();
//build a list of parameters for a function. If the function is selected as current, add parameter values as well
for (auto p : parameters)
{
QString paramValue;
if (f->name() == _transaction.functionId)
{
auto paramValueIter = _transaction.parameterValues.find(p->name());
if (paramValueIter != _transaction.parameterValues.cend())
paramValue = toQString(paramValueIter->second);
}
TransactionParameterItem* item = new TransactionParameterItem(p->name(), p->type(), paramValue);
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
params.append(item);
}
}
}
catch (boost::exception const&)
{
//TODO:
}
return params;
}
///@todo: get fnctions from code model
QList<QString> TransactionListModel::getFunctions()
{
QList<QString> functionNames;
try
{
QString code = m_document->toPlainText();
std::shared_ptr<QContractDefinition> contract(QContractDefinition::Contract(code));
auto functions = contract->functions();
for (auto f : functions)
{
functionNames.append(f->name());
}
}
catch (boost::exception const&)
{
}
return functionNames;
}
QVariantList TransactionListModel::getParameters(int _index, QString const& _functionId)
{
TransactionSettings const& transaction = (_index >= 0 && _index < (int)m_transactions.size()) ? m_transactions[_index] : TransactionSettings();
auto plist = buildParameters(m_document, transaction, _functionId);
QVariantList vl;
for (QObject* p : plist)
vl.append(QVariant::fromValue(p));
return vl;
}
TransactionListItem* TransactionListModel::getItem(int _index)
{
TransactionSettings const& transaction = (_index >= 0 && _index < (int)m_transactions.size()) ? m_transactions[_index] : TransactionSettings();
TransactionListItem* item = new TransactionListItem(_index, transaction, nullptr);
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
return item;
}
void TransactionListModel::edit(QObject* _data)
{
//these properties come from TransactionDialog QML object
///@todo change the model to a qml component
int index = _data->property("transactionIndex").toInt();
QString title = _data->property("transactionTitle").toString();
QString gas = _data->property("gas").toString();
QString gasPrice = _data->property("gasPrice").toString();
QString value = _data->property("transactionValue").toString();
QString functionId = _data->property("functionId").toString();
QAbstractListModel* paramsModel = qvariant_cast<QAbstractListModel*>(_data->property("transactionParams"));
TransactionSettings transaction(title, functionId, fromQString(value), fromQString(gas), fromQString(gasPrice));
int paramCount = paramsModel->rowCount(QModelIndex());
for (int p = 0; p < paramCount; ++p)
{
QString paramName = paramsModel->data(paramsModel->index(p, 0), Qt::DisplayRole).toString();
QString paramValue = paramsModel->data(paramsModel->index(p, 0), Qt::DisplayRole + 2).toString();
if (!paramValue.isEmpty() && !paramName.isEmpty())
transaction.parameterValues[paramName] = fromQString(paramValue);
}
if (index >= 0 && index < (int)m_transactions.size())
{
beginRemoveRows(QModelIndex(), index, index);
m_transactions.erase(m_transactions.begin() + index);
endRemoveRows();
}
else
index = rowCount(QModelIndex());
beginInsertRows(QModelIndex(), index, index);
m_transactions.push_back(transaction);
emit countChanged();
endInsertRows();
}
int TransactionListModel::getCount() const
{
return rowCount(QModelIndex());
}
void TransactionListModel::runTransaction(int _index)
{
TransactionSettings tr = m_transactions.at(_index);
emit transactionStarted(tr);
}
}
}

168
mix/TransactionListModel.h

@ -0,0 +1,168 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionListView.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QObject>
#include <QVariant>
#include <QAbstractListModel>
#include <QHash>
#include <QByteArray>
#include <libdevcore/Common.h>
#include <libethcore/CommonEth.h>
class QTextDocument;
namespace dev
{
namespace mix
{
/// Backend transaction config class
struct TransactionSettings
{
TransactionSettings():
value(0), gas(10000), gasPrice(10 * dev::eth::szabo) {}
TransactionSettings(QString const& _title, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice):
title(_title), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {}
/// User specified transaction title
QString title;
/// Contract function name
QString functionId;
/// Transaction value
u256 value;
/// Gas
u256 gas;
/// Gas price
u256 gasPrice;
/// Mapping from contract function parameter name to value
std::map<QString, u256> parameterValues;
};
/// QML transaction parameter class
class TransactionParameterItem: public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString type READ type CONSTANT)
Q_PROPERTY(QString value READ value CONSTANT)
public:
TransactionParameterItem(QString const& _name, QString const& _type, QString const& _value):
m_name(_name), m_type(_type), m_value(_value) {}
/// Parameter name, set by contract definition
QString name() { return m_name; }
/// Parameter type, set by contract definition
QString type() { return m_type; }
/// Parameter value, set by user
QString value() { return m_value; }
private:
QString m_name;
QString m_type;
QString m_value;
};
class TransactionListItem: public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index CONSTANT)
Q_PROPERTY(QString title READ title CONSTANT)
Q_PROPERTY(QString functionId READ functionId CONSTANT)
Q_PROPERTY(QString gas READ gas CONSTANT)
Q_PROPERTY(QString gasPrice READ gasPrice CONSTANT)
Q_PROPERTY(QString value READ value CONSTANT)
public:
TransactionListItem(int _index, TransactionSettings const& _t, QObject* _parent);
/// User specified transaction title
QString title() { return m_title; }
/// Gas
QString gas() { return m_gas; }
/// Gas cost
QString gasPrice() { return m_gasPrice; }
/// Transaction value
QString value() { return m_value; }
/// Contract function name
QString functionId() { return m_functionId; }
/// Index of this transaction in the transactions list
int index() { return m_index; }
private:
int m_index;
QString m_title;
QString m_functionId;
QString m_value;
QString m_gas;
QString m_gasPrice;
};
/// QML model for a list of transactions
class TransactionListModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ getCount() NOTIFY countChanged())
enum Roles
{
TitleRole = Qt::DisplayRole,
IdRole = Qt::UserRole + 1
};
public:
TransactionListModel(QObject* _parent, QTextDocument* _document);
~TransactionListModel() {}
QHash<int, QByteArray> roleNames() const override;
int rowCount(QModelIndex const& _parent) const override;
QVariant data(QModelIndex const& _index, int _role) const override;
int getCount() const;
/// Apply changes from transaction dialog. Argument is a dialog model as defined in TransactionDialog.qml
/// @todo Change that to transaction item
Q_INVOKABLE void edit(QObject* _data);
/// @returns transaction item for a give index
Q_INVOKABLE TransactionListItem* getItem(int _index);
/// @returns a list of functions for current contract
Q_INVOKABLE QList<QString> getFunctions();
/// @returns function parameters along with parameter values if set. @see TransactionParameterItem
Q_INVOKABLE QVariantList getParameters(int _id, QString const& _functionId);
/// Launch transaction execution UI handler
Q_INVOKABLE void runTransaction(int _index);
signals:
/// Transaction count has changed
void countChanged();
/// Transaction has been launched
void transactionStarted(dev::mix::TransactionSettings);
private:
std::vector<TransactionSettings> m_transactions;
QTextDocument* m_document;
};
}
}

56
mix/TransactionListView.cpp

@ -0,0 +1,56 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionListView.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQuickItem>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include "TransactionListView.h"
#include "TransactionListModel.h"
using namespace dev::mix;
TransactionListView::TransactionListView(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::RightTab)
{
m_editor = _doc;
m_model.reset(new TransactionListModel(this, _doc));
m_appEngine->rootContext()->setContextProperty("transactionListModel", m_model.get());
}
TransactionListView::~TransactionListView()
{
//implementation is in cpp file so that all types deleted are complete
}
QString TransactionListView::contentUrl() const
{
return QStringLiteral("qrc:/qml/TransactionList.qml");
}
QString TransactionListView::title() const
{
return QApplication::tr("Transactions");
}
void TransactionListView::start() const
{
}

54
mix/TransactionListView.h

@ -0,0 +1,54 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionListView.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QTextDocument>
#include "Extension.h"
namespace dev
{
namespace mix
{
class TransactionListModel;
/// Transactions list control
/// @todo This should be moved into state as a sequence
class TransactionListView: public Extension
{
Q_OBJECT
public:
TransactionListView(QTextDocument*);
~TransactionListView();
void start() const override;
QString title() const override;
QString contentUrl() const override;
/// @returns the underlying model
TransactionListModel* model() const { return m_model.get(); }
private:
QTextDocument* m_editor;
std::unique_ptr<TransactionListModel> m_model;
};
}
}

2
mix/qml.qrc

@ -7,6 +7,8 @@
<file>qml/Debugger.qml</file> <file>qml/Debugger.qml</file>
<file>qml/js/Debugger.js</file> <file>qml/js/Debugger.js</file>
<file>qml/BasicMessage.qml</file> <file>qml/BasicMessage.qml</file>
<file>qml/TransactionDialog.qml</file>
<file>qml/TransactionList.qml</file>
<file>qml/ModalDialog.qml</file> <file>qml/ModalDialog.qml</file>
<file>qml/AlertMessageDialog.qml</file> <file>qml/AlertMessageDialog.qml</file>
</qresource> </qresource>

5
mix/qml/AlertMessageDialog.qml

@ -22,6 +22,9 @@ Window
} }
function close() function close()
{ {
visible = false visible = false;
alertMessageDialogContent.source = "";
alertMessageDialogContent.sourceComponent = undefined;
alertMessageDialog.destroy();
} }
} }

8
mix/qml/BasicContent.qml

@ -7,13 +7,13 @@ Rectangle {
height: parent.height height: parent.height
color: "lightgray" color: "lightgray"
Text { Text {
font.pointSize: 7 font.pointSize: 9
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 3 anchors.topMargin: 3
anchors.leftMargin: 3 anchors.leftMargin: 3
height: 9 height: 9
font.family: "Sego UI light" font.family: "Monospace"
objectName: "status" objectName: "status"
id: status id: status
} }
@ -23,8 +23,8 @@ Rectangle {
anchors.leftMargin: 10 anchors.leftMargin: 10
anchors.top: status.bottom anchors.top: status.bottom
anchors.topMargin: 3 anchors.topMargin: 3
font.pointSize: 7 font.pointSize: 9
font.family: "Sego UI light" font.family: "Monospace"
height: parent.height * 0.8 height: parent.height * 0.8
width: parent.width - 20 width: parent.width - 20
wrapMode: Text.Wrap wrapMode: Text.Wrap

1
mix/qml/BasicMessage.qml

@ -16,6 +16,7 @@ Rectangle {
objectName: "messageContent" objectName: "messageContent"
id: messageTxt id: messageTxt
text: "" text: ""
wrapMode: "Wrap"
} }
} }

54
mix/qml/Debugger.qml

@ -8,12 +8,21 @@ import "js/Debugger.js" as Debugger
Rectangle { Rectangle {
anchors.fill: parent; anchors.fill: parent;
color: "lightgrey" color: "lightgrey"
Component.onCompleted: Debugger.init();
Rectangle { Rectangle {
color: "transparent" color: "transparent"
id: headerInfo id: headerInfo
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width width: parent.width
height: 30 height: 60
anchors.top: parent.top anchors.top: parent.top
Column {
width: parent.width
height: parent.height
Rectangle {
color: "transparent"
width: parent.width
height: 30
Label { Label {
anchors.centerIn: parent anchors.centerIn: parent
font.family: "Verdana" font.family: "Verdana"
@ -22,6 +31,33 @@ Rectangle {
id: headerInfoLabel id: headerInfoLabel
} }
} }
Rectangle {
color: "transparent"
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
height: 30
ListView {
orientation: ListView.Horizontal
anchors.centerIn: parent;
width: parent.width
id: headerReturnList
delegate: renderDelegateReturnValues
}
Component {
id: renderDelegateReturnValues
Item {
id: wrapperItem
width: 80
Text {
anchors.centerIn: parent
text: variable.declaration.name + " = " + variable.value
font.pointSize: 9
}
}
}
}
}
}
Keys.onPressed: { Keys.onPressed: {
if (event.key === Qt.Key_F10) if (event.key === Qt.Key_F10)
@ -37,7 +73,7 @@ Rectangle {
anchors.topMargin: 10 anchors.topMargin: 10
anchors.top: headerInfo.bottom anchors.top: headerInfo.bottom
anchors.left: parent.left anchors.left: parent.left
height: parent.height - 30 height: parent.height - 70
width: parent.width * 0.5 width: parent.width * 0.5
ListView { ListView {
@ -46,7 +82,6 @@ Rectangle {
width: 200 width: 200
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
id: statesList id: statesList
Component.onCompleted: Debugger.init();
model: humanReadableExecutionCode model: humanReadableExecutionCode
delegate: renderDelegate delegate: renderDelegate
highlight: highlightBar highlight: highlightBar
@ -94,7 +129,7 @@ Rectangle {
font.letterSpacing: 2 font.letterSpacing: 2
width: parent.width width: parent.width
height: 15 height: 15
text: "callstack" text: qsTr("callstack")
} }
ListView { ListView {
@ -140,7 +175,7 @@ Rectangle {
width: parent.width width: parent.width
height: 15 height: 15
anchors.top : parent.top anchors.top : parent.top
text: "debug stack" text: qsTr("debug stack")
} }
TextArea { TextArea {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -166,7 +201,7 @@ Rectangle {
width: parent.width width: parent.width
height: 15 height: 15
anchors.top : parent.top anchors.top : parent.top
text: "debug memory" text: qsTr("debug memory")
} }
TextArea { TextArea {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -192,7 +227,7 @@ Rectangle {
width: parent.width width: parent.width
height: 15 height: 15
anchors.top : parent.top anchors.top : parent.top
text: "debug storage" text: qsTr("debug storage")
} }
TextArea { TextArea {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -218,12 +253,15 @@ Rectangle {
width: parent.width width: parent.width
height: 15 height: 15
anchors.top : parent.top anchors.top : parent.top
text: "debug calldata" text: qsTr("debug calldata")
} }
TextArea { TextArea {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
width: parent.width width: parent.width
height: parent.height - 15 height: parent.height - 15
font.family: "Verdana"
font.pointSize: 8
font.letterSpacing: 2
id: debugCallDataTxt id: debugCallDataTxt
readOnly: true; readOnly: true;
} }

23
mix/qml/MainContent.qml

@ -18,7 +18,11 @@ Rectangle {
width: parent.width; width: parent.width;
id:root id:root
SplitView { SplitView {
orientation: Qt.Horizontal
anchors.fill: parent anchors.fill: parent
SplitView {
//anchors.fill: parent
width: parent.width * 0.8
orientation: Qt.Vertical orientation: Qt.Vertical
Rectangle { Rectangle {
anchors.top: parent.top anchors.top: parent.top
@ -28,8 +32,8 @@ Rectangle {
TextArea { TextArea {
id: codeEditor id: codeEditor
height: parent.height height: parent.height
font.family: "Verdana" font.family: "Monospace"
font.pointSize: 9 font.pointSize: 12
width: parent.width width: parent.width
anchors.centerIn: parent anchors.centerIn: parent
tabChangesFocus: false tabChangesFocus: false
@ -54,8 +58,23 @@ Rectangle {
style: TabStyle {} style: TabStyle {}
} }
} }
}
Rectangle {
anchors.right: parent.right
id: rightPaneView
width: parent.width * 0.2
height: parent.height
Layout.minimumWidth: 20
TabView {
id: rightPaneTabs
antialiasing: true
anchors.fill: parent
//style: TabStyle {}
}
}
CodeEditorExtensionManager { CodeEditorExtensionManager {
tabView: contextualTabs tabView: contextualTabs
rightTabView: rightPaneTabs
editor: codeEditor editor: codeEditor
} }
} }

7
mix/qml/ModalDialog.qml

@ -18,10 +18,13 @@ Window
} }
function open() function open()
{ {
visible = true visible = true;
} }
function close() function close()
{ {
visible = false visible = false;
modalDialogContent.source = "";
modalDialogContent.sourceComponent = undefined;
modalDialog.destroy();
} }
} }

219
mix/qml/TransactionDialog.qml

@ -0,0 +1,219 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
Window {
modality: Qt.WindowModal
width:640
height:480
visible: false
function open()
{
visible = true;
}
function close()
{
visible = false;
}
property alias focus : titleField.focus
property alias transactionTitle : titleField.text
property int transactionIndex
property alias transactionParams : paramsModel;
property alias gas : gasField.text;
property alias gasPrice : gasPriceField.text;
property alias transactionValue : valueField.text;
property alias functionId : functionComboBox.currentText;
property var model;
signal accepted;
function reset(index, m) {
model = m;
var item = model.getItem(index);
transactionIndex = index;
transactionTitle = item.title;
gas = item.gas;
gasPrice = item.gasPrice;
transactionValue = item.value;
var functionId = item.functionId;
functionsModel.clear();
var functionIndex = -1;
var functions = model.getFunctions();
for (var f = 0; f < functions.length; f++) {
functionsModel.append({ text: functions[f] });
if (functions[f] === item.functionId)
functionIndex = f;
}
functionComboBox.currentIndex = functionIndex;
}
function loadParameters() {
if (!paramsModel)
return;
paramsModel.clear();
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var parameters = model.getParameters(transactionIndex, functionsModel.get(functionComboBox.currentIndex).text);
for (var p = 0; p < parameters.length; p++) {
paramsModel.append({ name: parameters[p].name, type: parameters[p].type, value: parameters[p].value });
}
}
}
GridLayout {
id: dialogContent
columns: 2
anchors.fill: parent
anchors.margins: 10
rowSpacing: 10
columnSpacing: 10
Label {
text: qsTr("Title")
}
TextField {
id: titleField
focus: true
Layout.fillWidth: true
}
Label {
text: qsTr("Function")
}
ComboBox {
id: functionComboBox
Layout.fillWidth: true
currentIndex: -1
textRole: "text"
editable: false
model: ListModel {
id: functionsModel
}
onCurrentIndexChanged: {
loadParameters();
}
}
Label {
text: qsTr("Value")
}
TextField {
id: valueField
Layout.fillWidth: true
}
Label {
text: qsTr("Gas")
}
TextField {
id: gasField
Layout.fillWidth: true
}
Label {
text: qsTr("Gas price")
}
TextField {
id: gasPriceField
Layout.fillWidth: true
}
Label {
text: qsTr("Parameters")
}
TableView {
model: paramsModel
Layout.fillWidth: true
TableViewColumn {
role: "name"
title: "Name"
width: 120
}
TableViewColumn {
role: "type"
title: "Type"
width: 120
}
TableViewColumn {
role: "value"
title: "Value"
width: 120
}
itemDelegate: {
return editableDelegate;
}
}
}
RowLayout
{
anchors.bottom: parent.bottom
anchors.right: parent.right;
Button {
text: qsTr("Ok");
onClicked: {
close();
accepted();
}
}
Button {
text: qsTr("Cancel");
onClicked: close();
}
}
ListModel {
id: paramsModel
}
Component {
id: editableDelegate
Item {
Text {
width: parent.width
anchors.margins: 4
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
elide: styleData.elideMode
text: styleData.value !== undefined ? styleData.value : ""
color: styleData.textColor
visible: !styleData.selected
}
Loader {
id: loaderEditor
anchors.fill: parent
anchors.margins: 4
Connections {
target: loaderEditor.item
onTextChanged: {
paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text);
}
}
sourceComponent: (styleData.selected) ? editor : null
Component {
id: editor
TextInput {
id: textinput
color: styleData.textColor
text: styleData.value
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
}
}
}
}
}
}

89
mix/qml/TransactionList.qml

@ -0,0 +1,89 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
Rectangle {
color: "transparent"
id: transactionListContainer
focus: true
anchors.topMargin: 10
anchors.left: parent.left
height: parent.height
width: parent.width
ListView {
anchors.top: parent.top
height: parent.height
width: parent.width
id: transactionList
model: transactionListModel
delegate: renderDelegate
}
Button {
anchors.bottom: parent.bottom
text: qsTr("Add")
onClicked:
{
// Set next id here to work around Qt bug
// https://bugreports.qt-project.org/browse/QTBUG-41327
// Second call to signal handle would just edit the item that was just created, no harm done
transactionDialog.reset(transactionListModel.count, transactionListModel);
transactionDialog.open();
transactionDialog.focus = true;
}
}
TransactionDialog {
id: transactionDialog
onAccepted: {
transactionListModel.edit(transactionDialog);
}
}
Component {
id: renderDelegate
Item {
id: wrapperItem
height: 20
width: parent.width
RowLayout
{
anchors.fill: parent
Text {
//anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
text: title
font.pointSize: 12
verticalAlignment: Text.AlignBottom
}
ToolButton {
text: qsTr("Edit");
Layout.fillHeight: true
onClicked: {
transactionDialog.reset(index, transactionListModel);
transactionDialog.open();
transactionDialog.focus = true;
}
}
ToolButton {
text: qsTr("Delete");
Layout.fillHeight: true
onClicked: {
}
}
ToolButton {
text: qsTr("Run");
Layout.fillHeight: true
onClicked: {
transactionListModel.runTransaction(index);
}
}
}
}
}
}

10
mix/qml/js/Debugger.js

@ -8,6 +8,7 @@ function init()
{ {
currentSelectedState = 0; currentSelectedState = 0;
select(currentSelectedState); select(currentSelectedState);
displayReturnValue();
} }
function moveSelection(incr) function moveSelection(incr)
@ -30,7 +31,7 @@ function select(stateIndex)
var state = debugStates[stateIndex]; var state = debugStates[stateIndex];
var codeStr = bytesCodeMapping.getValue(state.curPC); var codeStr = bytesCodeMapping.getValue(state.curPC);
highlightSelection(codeStr); highlightSelection(codeStr);
currentSelectedState = codeStr; currentSelectedState = stateIndex;
completeCtxInformation(state); completeCtxInformation(state);
levelList.model = state.levels; levelList.model = state.levels;
levelList.update(); levelList.update();
@ -38,7 +39,6 @@ function select(stateIndex)
function highlightSelection(index) function highlightSelection(index)
{ {
console.log(index);
statesList.currentIndex = index; statesList.currentIndex = index;
} }
@ -60,3 +60,9 @@ function endOfDebug()
debugMemoryTxt.text = state.endOfDebug; debugMemoryTxt.text = state.endOfDebug;
headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft; headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft;
} }
function displayReturnValue()
{
headerReturnList.model = contractCallReturnParameters;
headerReturnList.update();
}

6
mix/qml/main.qml

@ -9,8 +9,6 @@ import CodeEditorExtensionManager 1.0
ApplicationWindow { ApplicationWindow {
id: mainApplication id: mainApplication
visible: true visible: true
x: Screen.width / 2 - width / 2
y: Screen.height / 2 - height / 2
width: 1200 width: 1200
height: 600 height: 600
minimumWidth: 400 minimumWidth: 400
@ -26,6 +24,10 @@ ApplicationWindow {
} }
} }
} }
Component.onCompleted: {
setX(Screen.width / 2 - width / 2);
setY(Screen.height / 2 - height / 2);
}
MainContent { MainContent {
} }

4
test/stSystemOperationsTestFiller.json

@ -740,7 +740,7 @@
"transaction" : { "transaction" : {
"nonce" : "0", "nonce" : "0",
"gasPrice" : "1", "gasPrice" : "1",
"gasLimit" : "365223", "gasLimit" : "365243",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "100000", "value" : "100000",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
@ -774,7 +774,7 @@
"transaction" : { "transaction" : {
"nonce" : "0", "nonce" : "0",
"gasPrice" : "1", "gasPrice" : "1",
"gasLimit" : "365224", "gasLimit" : "365244",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "100000", "value" : "100000",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",

65
test/trie.cpp

@ -50,7 +50,7 @@ static unsigned fac(unsigned _i)
BOOST_AUTO_TEST_SUITE(TrieTests) BOOST_AUTO_TEST_SUITE(TrieTests)
BOOST_AUTO_TEST_CASE(trie_tests) BOOST_AUTO_TEST_CASE(trie_test_anyorder)
{ {
string testPath = test::getTestPath(); string testPath = test::getTestPath();
@ -92,6 +92,69 @@ BOOST_AUTO_TEST_CASE(trie_tests)
} }
} }
BOOST_AUTO_TEST_CASE(trie_tests_ordered)
{
string testPath = test::getTestPath();
testPath += "/TrieTests";
cnote << "Testing Trie...";
js::mValue v;
string s = asString(contents(testPath + "/trietest.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?");
js::read_string(s, v);
for (auto& i: v.get_obj())
{
cnote << i.first;
js::mObject& o = i.second.get_obj();
vector<pair<string, string>> ss;
vector<string> keysToBeDeleted;
for (auto& i: o["in"].get_array())
{
vector<string> values;
for (auto& s: i.get_array())
{
if (s.type() == json_spirit::str_type)
values.push_back(s.get_str());
else if (s.type() == json_spirit::null_type)
{
// mark entry for deletion
values.push_back("");
if (!values[0].find("0x"))
values[0] = asString(fromHex(values[0].substr(2)));
keysToBeDeleted.push_back(values[0]);
}
else
BOOST_FAIL("Bad type (expected string)");
}
BOOST_REQUIRE(values.size() == 2);
ss.push_back(make_pair(values[0], values[1]));
if (!ss.back().first.find("0x"))
ss.back().first = asString(fromHex(ss.back().first.substr(2)));
if (!ss.back().second.find("0x"))
ss.back().second = asString(fromHex(ss.back().second.substr(2)));
}
MemoryDB m;
GenericTrieDB<MemoryDB> t(&m);
t.init();
BOOST_REQUIRE(t.check(true));
for (auto const& k: ss)
{
if (find(keysToBeDeleted.begin(), keysToBeDeleted.end(), k.first) != keysToBeDeleted.end() && k.second.empty())
t.remove(k.first);
else
t.insert(k.first, k.second);
BOOST_REQUIRE(t.check(true));
}
BOOST_REQUIRE(!o["root"].is_null());
BOOST_CHECK_EQUAL(o["root"].get_str(), "0x" + toHex(t.root().asArray()));
}
}
inline h256 stringMapHash256(StringMap const& _s) inline h256 stringMapHash256(StringMap const& _s)
{ {
return hash256(_s); return hash256(_s);

2392
test/vmArithmeticTestFiller.json

File diff suppressed because it is too large
Loading…
Cancel
Save