Browse Source

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

cl-refactor
Gav Wood 10 years ago
parent
commit
8ab1b55425
  1. 128
      alethzero/AllAccounts.cpp
  2. 59
      alethzero/AllAccounts.h
  3. 134
      alethzero/AllAccounts.ui
  4. 5
      alethzero/CMakeLists.txt
  5. 92
      alethzero/Main.ui
  6. 71
      alethzero/MainFace.cpp
  7. 97
      alethzero/MainFace.h
  8. 116
      alethzero/MainWin.cpp
  9. 28
      alethzero/MainWin.h
  10. 2
      eth/main.cpp
  11. 4
      libdevcore/FileSystem.cpp
  12. 4
      libdevcrypto/Common.cpp
  13. 6
      libdevcrypto/Common.h
  14. 3
      libsolidity/AST.cpp
  15. 88
      libsolidity/Compiler.cpp
  16. 14
      libsolidity/Compiler.h
  17. 11
      libsolidity/CompilerStack.cpp
  18. 6
      libsolidity/CompilerStack.h
  19. 47
      libsolidity/ExpressionCompiler.cpp
  20. 2
      libsolidity/Types.cpp
  21. 2
      libsolidity/Version.cpp
  22. 25
      mix/ClientModel.cpp
  23. 2
      mix/QVariableDeclaration.h
  24. 5
      mix/qml/BlockChain.qml
  25. 1
      mix/qml/Debugger.qml
  26. 21
      mix/qml/DeployContractStep.qml
  27. 8
      mix/qml/DeploymentWorker.qml
  28. 28
      mix/qml/PackagingStep.qml
  29. 162
      mix/qml/QAddressView.qml
  30. 66
      mix/qml/QBoolTypeView.qml
  31. 4
      mix/qml/QIntTypeView.qml
  32. 3
      mix/qml/QStringTypeView.qml
  33. 44
      mix/qml/RegisteringStep.qml
  34. 1
      mix/qml/ScenarioLoader.qml
  35. 2
      mix/qml/StateDialog.qml
  36. 3
      mix/qml/StateList.qml
  37. 4
      mix/qml/StateListModel.qml
  38. 44
      mix/qml/StructView.qml
  39. 18
      mix/qml/TransactionDialog.qml
  40. 2
      mix/qml/VariablesView.qml
  41. 1
      mix/qml/Watchers.qml
  42. 2
      mix/qml/html/codeeditor.js
  43. 9
      mix/qml/js/InputValidator.js
  44. 44
      solc/CommandLineInterface.cpp
  45. 33
      test/libsolidity/SolidityEndToEndTest.cpp
  46. 2
      test/libwhisper/whisperTopic.cpp

128
alethzero/AllAccounts.cpp

@ -0,0 +1,128 @@
/*
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 AllAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "AllAccounts.h"
#include <sstream>
#include <QClipboard>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include <libevmcore/Instruction.h>
#include <libethereum/Client.h>
#include "ui_AllAccounts.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
AllAccounts::AllAccounts(MainFace* _m):
Plugin(_m, "AllAccounts"),
m_ui(new Ui::AllAccounts)
{
dock(Qt::RightDockWidgetArea, "All Accounts")->setWidget(new QWidget());
m_ui->setupUi(dock()->widget());
installWatches();
refresh();
connect(m_ui->accounts, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), SLOT(on_accounts_currentItemChanged()));
connect(m_ui->accounts, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_accounts_doubleClicked()));
connect(m_ui->refreshAccounts, SIGNAL(clicked()), SLOT(refresh()));
connect(m_ui->accountsFilter, SIGNAL(textChanged(QString)), SLOT(onAllChange()));
connect(m_ui->showBasic, SIGNAL(toggled(bool)), SLOT(onAllChange()));
connect(m_ui->showContracts, SIGNAL(toggled(bool)), SLOT(onAllChange()));
connect(m_ui->onlyNamed, SIGNAL(toggled(bool)), SLOT(onAllChange()));
}
AllAccounts::~AllAccounts()
{
}
void AllAccounts::installWatches()
{
main()->installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onAllChange(); });
main()->installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onAllChange(); });
}
void AllAccounts::refresh()
{
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
m_ui->accounts->clear();
bool showContract = m_ui->showContracts->isChecked();
bool showBasic = m_ui->showBasic->isChecked();
bool onlyNamed = m_ui->onlyNamed->isChecked();
for (auto const& i: ethereum()->addresses())
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = static_cast<Context*>(main())->render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), m_ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
#endif
m_ui->refreshAccounts->setEnabled(false);
}
void AllAccounts::onAllChange()
{
m_ui->refreshAccounts->setEnabled(true);
}
void AllAccounts::on_accounts_currentItemChanged()
{
m_ui->accountInfo->clear();
if (auto item = m_ui->accounts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto address = h160((byte const*)hba.data(), h160::ConstructFromPointer);
stringstream s;
try
{
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << main()->prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << main()->prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << ETH_HTML_DIV(ETH_HTML_MONO) << toHex(ethereum()->codeAt(address)) << "</div>";
m_ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::InvalidTrie)
{
m_ui->accountInfo->appendHtml("Corrupted trie.");
}
m_ui->accountInfo->moveCursor(QTextCursor::Start);
}
}
void AllAccounts::on_accounts_doubleClicked()
{
if (m_ui->accounts->count())
{
auto hba = m_ui->accounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}

59
alethzero/AllAccounts.h

@ -0,0 +1,59 @@
/*
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 AllAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <QListWidget>
#include <QPlainTextEdit>
#include "MainFace.h"
namespace Ui
{
class AllAccounts;
}
namespace dev
{
namespace az
{
class AllAccounts: public QObject, public Plugin
{
Q_OBJECT
public:
AllAccounts(MainFace* _m);
~AllAccounts();
private slots:
void on_accounts_currentItemChanged();
void on_accounts_doubleClicked();
void onAllChange();
void refresh();
private:
void installWatches();
Ui::AllAccounts* m_ui;
};
}
}

134
alethzero/AllAccounts.ui

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AllAccounts</class>
<widget class="QWidget" name="AllAccounts">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="accounts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

5
alethzero/CMakeLists.txt

@ -31,6 +31,9 @@ qt5_wrap_ui(ui_ExportState.h ExportState.ui)
qt5_wrap_ui(ui_GetPassword.h GetPassword.ui)
qt5_wrap_ui(ui_GasPricing.h GasPricing.ui)
# Extensions
qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui)
file(GLOB HEADERS "*.h")
if (APPLE)
@ -42,7 +45,7 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui
WIN_RESOURCES alethzero.rc
)

92
alethzero/Main.ui

@ -615,98 +615,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="accounts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>

71
alethzero/MainFace.cpp

@ -0,0 +1,71 @@
/*
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 MainFace.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "MainFace.h"
using namespace std;
using namespace dev;
using namespace az;
Plugin::Plugin(MainFace* _f, std::string const& _name):
m_main(_f),
m_name(_name)
{
_f->adoptPlugin(this);
}
QDockWidget* Plugin::dock(Qt::DockWidgetArea _area, QString _title)
{
if (_title.isEmpty())
_title = QString::fromStdString(m_name);
if (!m_dock)
{
m_dock = new QDockWidget(_title, m_main);
m_main->addDockWidget(_area, m_dock);
m_dock->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar);
}
return m_dock;
}
void Plugin::addToDock(Qt::DockWidgetArea _area, QDockWidget* _dockwidget, Qt::Orientation _orientation)
{
m_main->addDockWidget(_area, _dockwidget, _orientation);
}
void Plugin::addAction(QAction* _a)
{
m_main->addAction(_a);
}
void MainFace::adoptPlugin(Plugin* _p)
{
m_plugins[_p->name()] = shared_ptr<Plugin>(_p);
}
void MainFace::killPlugins()
{
m_plugins.clear();
}
void MainFace::allChange()
{
for (auto const& p: m_plugins)
p.second->onAllChange();
}

97
alethzero/MainFace.h

@ -0,0 +1,97 @@
/*
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 MainFace.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <memory>
#include <map>
#include <string>
#include <functional>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QAction>
#include <QtWidgets/QDockWidget>
#include <libevm/ExtVMFace.h>
#include "Context.h"
namespace dev
{
class WebThreeDirect;
namespace eth { class Client; class LogFilter; }
namespace shh { class WhisperHost; }
namespace az
{
class Plugin;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
class MainFace: public QMainWindow, public Context
{
public:
explicit MainFace(QWidget* _parent = nullptr): QMainWindow(_parent) {}
void adoptPlugin(Plugin* _p);
void killPlugins();
void allChange();
// TODO: tidy - all should be references that throw if module unavailable.
// TODO: provide a set of available web3 modules.
virtual dev::WebThreeDirect* web3() const = 0;
virtual dev::eth::Client* ethereum() const = 0;
virtual std::shared_ptr<dev::shh::WhisperHost> whisper() const = 0;
virtual unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f) = 0;
virtual unsigned installWatch(dev::h256 const& _tf, WatchHandler const& _f) = 0;
private:
std::unordered_map<std::string, std::shared_ptr<Plugin>> m_plugins;
};
class Plugin
{
public:
Plugin(MainFace* _f, std::string const& _name);
virtual ~Plugin() {}
std::string const& name() const { return m_name; }
dev::WebThreeDirect* web3() const { return m_main->web3(); }
dev::eth::Client* ethereum() const { return m_main->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_main->whisper(); }
MainFace* main() { return m_main; }
QDockWidget* dock(Qt::DockWidgetArea _area = Qt::RightDockWidgetArea, QString _title = QString());
void addToDock(Qt::DockWidgetArea _area, QDockWidget* _dockwidget, Qt::Orientation _orientation);
void addAction(QAction* _a);
virtual void onAllChange() {}
private:
MainFace* m_main = nullptr;
std::string m_name;
QDockWidget* m_dock = nullptr;
};
}
}

116
alethzero/MainWin.cpp

@ -74,13 +74,15 @@
#include "DappHost.h"
#include "WebPage.h"
#include "ExportState.h"
#include "AllAccounts.h"
#include "ui_Main.h"
#include "ui_GetPassword.h"
#include "ui_GasPricing.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::eth;
using namespace az;
using namespace p2p;
using namespace eth;
namespace js = json_spirit;
string Main::fromRaw(h256 _n, unsigned* _inc)
@ -126,8 +128,8 @@ static QString filterOutTerminal(QString _s)
return _s.replace(QRegExp("\x1b\\[(\\d;)?\\d+m"), "");
}
Main::Main(QWidget *parent) :
QMainWindow(parent),
Main::Main(QWidget* _parent):
MainFace(_parent),
ui(new Ui::Main),
m_transact(nullptr),
m_dappLoader(nullptr),
@ -136,6 +138,7 @@ Main::Main(QWidget *parent) :
QtWebEngine::initialize();
setWindowFlags(Qt::Window);
ui->setupUi(this);
std::string dbPath = getDataDir();
for (int i = 1; i < qApp->arguments().size(); ++i)
{
@ -146,6 +149,8 @@ Main::Main(QWidget *parent) :
resetNetwork(eth::Network::Olympic);
else if (arg == "--genesis-json" && i + 1 < qApp->arguments().size())
CanonBlockChain<Ethash>::setGenesis(contentsString(qApp->arguments()[++i].toStdString()));
else if ((arg == "--db-path" || arg == "-d") && i + 1 < qApp->arguments().size())
dbPath = qApp->arguments()[++i].toStdString();
}
if (c_network == eth::Network::Olympic)
@ -200,8 +205,8 @@ Main::Main(QWidget *parent) :
#endif
m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
if (!dev::contents(getDataDir() + "/genesis.json").empty())
CanonBlockChain<Ethash>::setGenesis(contentsString(getDataDir() + "/genesis.json"));
if (!dev::contents(dbPath + "/genesis.json").empty())
CanonBlockChain<Ethash>::setGenesis(contentsString(dbPath + "/genesis.json"));
cerr << "State root: " << CanonBlockChain<Ethash>::genesis().stateRoot() << endl;
auto block = CanonBlockChain<Ethash>::createGenesisBlock();
@ -226,7 +231,7 @@ Main::Main(QWidget *parent) :
QSettings s("ethereum", "alethzero");
m_networkConfig = s.value("peers").toByteArray();
bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size());
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), WithExisting::Trust, {"eth"/*, "shh"*/}, p2p::NetworkPreferences(), network));
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath, WithExisting::Trust, {"eth"/*, "shh"*/}, p2p::NetworkPreferences(), network));
ui->blockCount->setText(QString("PV%1.%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(eth::c_minorProtocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ethereum()->sealEngine()->name())).arg(ethereum()->sealEngine()->revision()).arg(dev::Version));
@ -302,6 +307,8 @@ Main::Main(QWidget *parent) :
s.setValue("splashMessage", false);
}
}
new dev::az::AllAccounts(this);
}
Main::~Main()
@ -414,7 +421,7 @@ unsigned Main::installWatch(LogFilter const& _tf, WatchHandler const& _f)
return ret;
}
unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f)
unsigned Main::installWatch(h256 const& _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf, Reaping::Manual);
m_handlers[ret] = _f;
@ -522,7 +529,6 @@ void Main::onNewBlock()
// update blockchain dependent views.
refreshBlockCount();
refreshBlockChain();
ui->refreshAccounts->setEnabled(true);
// We must update balances since we can't filter updates to basic accounts.
refreshBalances();
@ -534,7 +540,6 @@ void Main::onNewPending()
// update any pending-transaction dependent views.
refreshPending();
ui->refreshAccounts->setEnabled(true);
}
void Main::on_forceMining_triggered()
@ -1043,7 +1048,10 @@ void Main::on_usePrivate_triggered()
bool ok;
pc = QInputDialog::getText(this, "Enter Name", "Enter the name of your private chain", QLineEdit::Normal, QString("NewChain-%1").arg(time(0)), &ok);
if (!ok)
{
ui->usePrivate->setChecked(false);
return;
}
}
setPrivateChain(pc);
}
@ -1237,8 +1245,8 @@ void Main::refreshAll()
refreshBlockChain();
refreshBlockCount();
refreshPending();
ui->refreshAccounts->setEnabled(true);
refreshBalances();
allChange();
}
void Main::refreshPending()
@ -1263,55 +1271,6 @@ void Main::refreshPending()
}
}
void Main::on_accountsFilter_textChanged()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_showBasic_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_showContracts_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_onlyNamed_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_refreshAccounts_clicked()
{
refreshAccounts();
}
void Main::refreshAccounts()
{
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
ui->accounts->clear();
bool showContract = ui->showContracts->isChecked();
bool showBasic = ui->showBasic->isChecked();
bool onlyNamed = ui->onlyNamed->isChecked();
for (auto const& i: ethereum()->addresses())
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
#endif
ui->refreshAccounts->setEnabled(false);
}
void Main::refreshBlockCount()
{
auto d = ethereum()->blockChain().details();
@ -1919,33 +1878,6 @@ void Main::debugDumpState(int _add)
}
}
void Main::on_accounts_currentItemChanged()
{
ui->accountInfo->clear();
if (auto item = ui->accounts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto address = h160((byte const*)hba.data(), h160::ConstructFromPointer);
stringstream s;
try
{
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << ETH_HTML_DIV(ETH_HTML_MONO) << toHex(ethereum()->codeAt(address)) << "</div>";
ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::InvalidTrie)
{
ui->accountInfo->appendHtml("Corrupted trie.");
}
ui->accountInfo->moveCursor(QTextCursor::Start);
}
}
void Main::on_idealPeers_valueChanged(int)
{
m_webThree->setIdealPeerCount(ui->idealPeers->value());
@ -1964,16 +1896,6 @@ void Main::on_ourAccounts_doubleClicked()
m_logHistory.clear();
}*/
void Main::on_accounts_doubleClicked()
{
if (ui->accounts->count())
{
auto hba = ui->accounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}
static shh::Topics topicFromText(QString _s)
{
shh::BuildTopic ret;

28
alethzero/MainWin.h

@ -26,7 +26,6 @@
#endif
#include <map>
#include <QtNetwork/QNetworkAccessManager>
#include <QtCore/QAbstractListModel>
#include <QtCore/QMutex>
@ -42,6 +41,7 @@
#include "Transact.h"
#include "NatspecHandler.h"
#include "Connect.h"
#include "MainFace.h"
class QListWidgetItem;
class QActionGroup;
@ -65,11 +65,9 @@ class DappLoader;
class DappHost;
struct Dapp;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
QString contentsOfQResource(std::string const& res);
class Main: public QMainWindow, public Context
class Main: public dev::az::MainFace
{
Q_OBJECT
@ -77,9 +75,9 @@ public:
explicit Main(QWidget *parent = 0);
~Main();
dev::WebThreeDirect* web3() const { return m_webThree.get(); }
dev::eth::Client* ethereum() const { return m_webThree->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_webThree->whisper(); }
dev::WebThreeDirect* web3() const override { return m_webThree.get(); }
dev::eth::Client* ethereum() const override { return m_webThree->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const override { return m_webThree->whisper(); }
bool confirm() const;
NatSpecFace* natSpec() { return &m_natSpecDB; }
@ -131,7 +129,6 @@ private slots:
// View
void on_refresh_triggered();
void on_showAll_triggered() { refreshBlockChain(); }
void on_showAllAccounts_triggered() { refreshAccounts(); }
void on_preview_triggered();
// Account management
@ -144,13 +141,6 @@ private slots:
void on_claimPresale_triggered();
void on_exportKey_triggered();
// Account pane
void on_accountsFilter_textChanged();
void on_showBasic_toggled();
void on_showContracts_toggled();
void on_onlyNamed_toggled();
void on_refreshAccounts_clicked();
// Tools
void on_newTransaction_triggered();
void on_loadJS_triggered();
@ -159,8 +149,6 @@ private slots:
// Stuff concerning the blocks/transactions/accounts panels
void on_ourAccounts_itemClicked(QListWidgetItem* _i);
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_accounts_currentItemChanged();
void on_transactionQueue_currentItemChanged();
void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged();
@ -229,8 +217,8 @@ private:
void setPrivateChain(QString const& _private, bool _forceConfigure = false);
unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f);
unsigned installWatch(dev::h256 _tf, WatchHandler const& _f);
unsigned installWatch(dev::eth::LogFilter const& _tf, dev::az::WatchHandler const& _f) override;
unsigned installWatch(dev::h256 const& _tf, dev::az::WatchHandler const& _f) override;
void uninstallWatch(unsigned _w);
void keysChanged();
@ -266,7 +254,7 @@ private:
std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::map<unsigned, WatchHandler> m_handlers;
std::map<unsigned, dev::az::WatchHandler> m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
unsigned m_currenciesFilter = (unsigned)-1;
unsigned m_balancesFilter = (unsigned)-1;

2
eth/main.cpp

@ -1726,7 +1726,7 @@ int main(int argc, char** argv)
masterPassword = getPassword("Please enter your MASTER password: ");
if (keyManager.load(masterPassword))
break;
cout << "Password invalid. Try again." << endl;
cout << "The password you entered is incorrect. If you have forgotten your password, and you wish to start afresh, manually remove the file: " + getDataDir("ethereum") + "/keys.info" << endl;
}
}
else

4
libdevcore/FileSystem.cpp

@ -27,7 +27,7 @@
#if defined(_WIN32)
#include <shlobj.h>
#elif defined(__APPLE__)
#else
#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
@ -56,14 +56,12 @@ std::string dev::getDataDir(std::string _prefix)
#else
boost::filesystem::path dataDirPath;
char const* homeDir = getenv("HOME");
#if defined(__APPLE__)
if (!homeDir || strlen(homeDir) == 0)
{
struct passwd* pwd = getpwuid(getuid());
if (pwd)
homeDir = pwd->pw_dir;
}
#endif
if (!homeDir || strlen(homeDir) == 0)
dataDirPath = boost::filesystem::path("/");

4
libdevcrypto/Common.cpp

@ -300,7 +300,7 @@ h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
{
// H(H(r||k)^h)
h256 s;
sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
sha3mac(Secret::random().ref(), _priv.ref(), s.ref());
s ^= _hash;
sha3(s.ref(), s.ref());
@ -367,7 +367,7 @@ Secret Nonce::next()
{
initialiseIfNeeded();
m_value = sha3(m_value);
return m_value;
return sha3(m_value);
}
void Nonce::resetInternal()

6
libdevcrypto/Common.h

@ -189,6 +189,12 @@ h256 kdf(Secret const& _priv, h256 const& _hash);
/**
* @brief Generator for nonce material.
*The Nonce class should only be used when a non-repeating nonce
* is required and, in its current form, not recommended for signatures.
* This is primarily because the key-material for signatures is
* encrypted on disk whereas the seed for Nonce is not.
* Thus, Nonce's primary intended use at this time is for networking
* where the key is also stored in plaintext.
*/
class Nonce
{

3
libsolidity/AST.cpp

@ -784,8 +784,7 @@ void Expression::expectType(Type const& _expectedType)
" is not implicitly convertible to expected type " +
_expectedType.toString() +
"."
)
);
));
}
void Expression::requireLValue()

88
libsolidity/Compiler.cpp

@ -25,6 +25,7 @@
#include <boost/range/adaptor/reversed.hpp>
#include <libevmcore/Instruction.h>
#include <libevmasm/Assembly.h>
#include <libevmcore/Params.h>
#include <libsolidity/AST.h>
#include <libsolidity/ExpressionCompiler.h>
#include <libsolidity/CompilerUtils.h>
@ -53,31 +54,45 @@ void Compiler::compileContract(ContractDefinition const& _contract,
m_context = CompilerContext(); // clear it just in case
{
CompilerContext::LocationSetter locationSetterRunTime(m_context, _contract);
CompilerUtils(m_context).initialiseFreeMemoryPointer();
initializeContext(_contract, _contracts);
appendFunctionSelector(_contract);
set<Declaration const*> functions = m_context.getFunctionsWithoutCode();
while (!functions.empty())
{
for (Declaration const* function: functions)
{
m_context.setStackOffset(0);
function->accept(*this);
}
functions = m_context.getFunctionsWithoutCode();
}
appendFunctionsWithoutCode();
}
// Swap the runtime context with the creation-time context
swap(m_context, m_runtimeContext);
CompilerContext::LocationSetter locationSetterCreationTime(m_context, _contract);
CompilerUtils(m_context).initialiseFreeMemoryPointer();
initializeContext(_contract, _contracts);
packIntoContractCreator(_contract, m_runtimeContext);
if (m_optimize)
m_context.optimise(m_optimizeRuns);
}
void Compiler::compileClone(
ContractDefinition const& _contract,
map<ContractDefinition const*, bytes const*> const& _contracts
)
{
m_context = CompilerContext(); // clear it just in case
initializeContext(_contract, _contracts);
appendInitAndConstructorCode(_contract);
//@todo determine largest return size of all runtime functions
eth::AssemblyItem runtimeSub = m_context.addSubroutine(getCloneRuntime());
solAssert(runtimeSub.data() < numeric_limits<size_t>::max(), "");
m_runtimeSub = size_t(runtimeSub.data());
// stack contains sub size
m_context << eth::Instruction::DUP1 << runtimeSub << u256(0) << eth::Instruction::CODECOPY;
m_context << u256(0) << eth::Instruction::RETURN;
appendFunctionsWithoutCode();
if (m_optimize)
m_context.optimise(m_optimizeRuns);
}
eth::AssemblyItem Compiler::getFunctionEntryLabel(FunctionDefinition const& _function) const
{
return m_runtimeContext.getFunctionEntryLabelIfExists(_function);
@ -86,13 +101,14 @@ eth::AssemblyItem Compiler::getFunctionEntryLabel(FunctionDefinition const& _fun
void Compiler::initializeContext(ContractDefinition const& _contract,
map<ContractDefinition const*, bytes const*> const& _contracts)
{
CompilerUtils(m_context).initialiseFreeMemoryPointer();
m_context.setCompiledContracts(_contracts);
m_context.setInheritanceHierarchy(_contract.getLinearizedBaseContracts());
registerStateVariables(_contract);
m_context.resetVisitedNodes(&_contract);
}
void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
void Compiler::appendInitAndConstructorCode(ContractDefinition const& _contract)
{
// Determine the arguments that are used for the base constructors.
std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
@ -126,22 +142,22 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
appendConstructor(*constructor);
else if (auto c = m_context.getNextConstructor(_contract))
appendBaseConstructor(*c);
}
void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
{
appendInitAndConstructorCode(_contract);
eth::AssemblyItem runtimeSub = m_context.addSubroutine(_runtimeContext.getAssembly());
solAssert(runtimeSub.data() < numeric_limits<size_t>::max(), "");
m_runtimeSub = size_t(runtimeSub.data());
// stack contains sub size
m_context << eth::Instruction::DUP1 << runtimeSub << u256(0) << eth::Instruction::CODECOPY;
m_context << u256(0) << eth::Instruction::RETURN;
// note that we have to include the functions again because of absolute jump labels
set<Declaration const*> functions = m_context.getFunctionsWithoutCode();
while (!functions.empty())
{
for (Declaration const* function: functions)
function->accept(*this);
functions = m_context.getFunctionsWithoutCode();
}
appendFunctionsWithoutCode();
}
void Compiler::appendBaseConstructor(FunctionDefinition const& _constructor)
@ -618,6 +634,20 @@ bool Compiler::visit(PlaceholderStatement const& _placeholderStatement)
return true;
}
void Compiler::appendFunctionsWithoutCode()
{
set<Declaration const*> functions = m_context.getFunctionsWithoutCode();
while (!functions.empty())
{
for (Declaration const* function: functions)
{
m_context.setStackOffset(0);
function->accept(*this);
}
functions = m_context.getFunctionsWithoutCode();
}
}
void Compiler::appendModifierOrFunctionCode()
{
solAssert(m_currentFunction, "");
@ -674,3 +704,21 @@ void Compiler::compileExpression(Expression const& _expression, TypePointer cons
if (_targetType)
CompilerUtils(m_context).convertType(*_expression.getType(), *_targetType);
}
eth::Assembly Compiler::getCloneRuntime()
{
eth::Assembly a;
a << eth::Instruction::CALLDATASIZE;
a << u256(0) << eth::Instruction::DUP1 << eth::Instruction::CALLDATACOPY;
//@todo adjust for larger return values, make this dynamic.
a << u256(0x20) << u256(0) << eth::Instruction::CALLDATASIZE;
a << u256(0) << eth::Instruction::DUP1;
// this is the address which has to be substituted by the linker.
//@todo implement as special "marker" AssemblyItem.
a << u256("0xcafecafecafecafecafecafecafecafecafecafe");
a << u256(eth::c_callGas + 10) << eth::Instruction::GAS << eth::Instruction::SUB;
a << eth::Instruction::CALLCODE;
//@todo adjust for larger return values, make this dynamic.
a << u256(0x20) << u256(0) << eth::Instruction::RETURN;
return a;
}

14
libsolidity/Compiler.h

@ -44,6 +44,12 @@ public:
void compileContract(ContractDefinition const& _contract,
std::map<ContractDefinition const*, bytes const*> const& _contracts);
/// Compiles a contract that uses CALLCODE to call into a pre-deployed version of the given
/// contract at runtime, but contains the full creation-time code.
void compileClone(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, bytes const*> const& _contracts
);
bytes getAssembledBytecode() { return m_context.getAssembledBytecode(); }
bytes getRuntimeBytecode() { return m_context.getAssembledRuntimeBytecode(m_runtimeSub); }
/// @arg _sourceCodes is the map of input files to source code strings
@ -68,6 +74,8 @@ private:
/// Adds the code that is run at creation time. Should be run after exchanging the run-time context
/// with a new and initialized context. Adds the constructor code.
void packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext);
/// Appends state variable initialisation and constructor code.
void appendInitAndConstructorCode(ContractDefinition const& _contract);
void appendBaseConstructor(FunctionDefinition const& _constructor);
void appendConstructor(FunctionDefinition const& _constructor);
void appendFunctionSelector(ContractDefinition const& _contract);
@ -103,6 +111,9 @@ private:
virtual bool visit(ExpressionStatement const& _expressionStatement) override;
virtual bool visit(PlaceholderStatement const&) override;
/// Repeatedly visits all function which are referenced but which are not compiled yet.
void appendFunctionsWithoutCode();
/// Appends one layer of function modifier code of the current function, or the function
/// body itself if the last modifier was reached.
void appendModifierOrFunctionCode();
@ -110,6 +121,9 @@ private:
void appendStackVariableInitialisation(VariableDeclaration const& _variable);
void compileExpression(Expression const& _expression, TypePointer const& _targetType = TypePointer());
/// @returns the runtime assembly for clone contracts.
static eth::Assembly getCloneRuntime();
bool const m_optimize;
unsigned const m_optimizeRuns;
CompilerContext m_context;

11
libsolidity/CompilerStack.cpp

@ -166,7 +166,13 @@ void CompilerStack::compile(bool _optimize, unsigned _runs)
compiledContract.bytecode = compiler->getAssembledBytecode();
compiledContract.runtimeBytecode = compiler->getRuntimeBytecode();
compiledContract.compiler = move(compiler);
compiler = make_shared<Compiler>(_optimize, _runs);
compiler->compileContract(*contract, contractBytecode);
contractBytecode[compiledContract.contract] = &compiledContract.bytecode;
Compiler cloneCompiler(_optimize, _runs);
cloneCompiler.compileClone(*contract, contractBytecode);
compiledContract.cloneBytecode = cloneCompiler.getAssembledBytecode();
}
}
@ -199,6 +205,11 @@ bytes const& CompilerStack::getRuntimeBytecode(string const& _contractName) cons
return getContract(_contractName).runtimeBytecode;
}
bytes const& CompilerStack::getCloneBytecode(string const& _contractName) const
{
return getContract(_contractName).cloneBytecode;
}
dev::h256 CompilerStack::getContractCodeHash(string const& _contractName) const
{
return dev::sha3(getRuntimeBytecode(_contractName));

6
libsolidity/CompilerStack.h

@ -99,6 +99,11 @@ public:
bytes const& getBytecode(std::string const& _contractName = "") const;
/// @returns the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
bytes const& getRuntimeBytecode(std::string const& _contractName = "") const;
/// @returns the bytecode of a contract that uses an already deployed contract via CALLCODE.
/// The returned bytes will contain a sequence of 20 bytes of the format "XXX...XXX" which have to
/// substituted by the actual address. Note that this sequence starts end ends in three X
/// characters but can contain anything in between.
bytes const& getCloneBytecode(std::string const& _contractName = "") const;
/// @returns normal contract assembly items
eth::AssemblyItems const* getAssemblyItems(std::string const& _contractName = "") const;
/// @returns runtime contract assembly items
@ -167,6 +172,7 @@ private:
std::shared_ptr<Compiler> compiler;
bytes bytecode;
bytes runtimeBytecode;
bytes cloneBytecode;
std::shared_ptr<InterfaceHandler> interfaceHandler;
mutable std::unique_ptr<std::string const> interface;
mutable std::unique_ptr<std::string const> solidityInterface;

47
libsolidity/ExpressionCompiler.cpp

@ -85,6 +85,10 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
{
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
solAssert(
!paramTypes[i]->isDynamicallySized(),
"Accessors for mapping with dynamically-sized keys not yet implemented."
);
// pop offset
m_context << eth::Instruction::POP;
// move storage offset to memory.
@ -803,15 +807,30 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
if (baseType.getCategory() == Type::Category::Mapping)
{
// stack: storage_base_ref
Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType();
m_context << u256(0); // memory position
auto const& mapping = dynamic_cast<MappingType const&>(baseType);
Type const& keyType = *mapping.getKeyType();
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
solAssert(keyType.getCalldataEncodedSize() <= 0x20, "Dynamic keys not yet implemented.");
appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
m_context << eth::Instruction::SWAP1;
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
utils().storeInMemoryDynamic(IntegerType(256));
m_context << u256(0) << eth::Instruction::SHA3;
if (keyType.isDynamicallySized())
{
_indexAccess.getIndexExpression()->accept(*this);
utils().fetchFreeMemoryPointer();
// stack: base index mem
// note: the following operations must not allocate memory!
utils().encodeToMemory(TypePointers{mapping.getKeyType()}, TypePointers(), false, true);
m_context << eth::Instruction::SWAP1;
utils().storeInMemoryDynamic(IntegerType(256));
utils().toSizeAfterFreeMemoryPointer();
}
else
{
m_context << u256(0); // memory position
appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
m_context << eth::Instruction::SWAP1;
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
utils().storeInMemoryDynamic(IntegerType(256));
m_context << u256(0);
}
m_context << eth::Instruction::SHA3;
m_context << u256(0);
setLValueToStorageItem(_indexAccess);
}
@ -1072,6 +1091,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
using FunctionKind = FunctionType::Location;
FunctionKind funKind = _functionType.getLocation();
bool returnSuccessCondition = funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode;
bool isCallCode = funKind == FunctionKind::BareCallCode || funKind == FunctionKind::CallCode;
//@todo only return the first return value for now
Type const* firstReturnType =
@ -1158,13 +1178,20 @@ void ExpressionCompiler::appendExternalFunctionCall(
if (_functionType.gasSet())
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
else
{
// send all gas except the amount needed to execute "SUB" and "CALL"
// @todo this retains too much gas for now, needs to be fine-tuned.
u256 gasNeededByCaller = eth::c_callGas + 10;
if (_functionType.valueSet())
gasNeededByCaller += eth::c_callValueTransferGas;
if (!isCallCode)
gasNeededByCaller += eth::c_callNewAccountGas; // we never know
m_context <<
u256(eth::c_callGas + 10 + (_functionType.valueSet() ? eth::c_callValueTransferGas : 0) + eth::c_callNewAccountGas) <<
gasNeededByCaller <<
eth::Instruction::GAS <<
eth::Instruction::SUB;
if (funKind == FunctionKind::CallCode || funKind == FunctionKind::BareCallCode)
}
if (isCallCode)
m_context << eth::Instruction::CALLCODE;
else
m_context << eth::Instruction::CALL;

2
libsolidity/Types.cpp

@ -179,6 +179,8 @@ TypePointer Type::fromMapping(ElementaryTypeName& _keyType, TypeName& _valueType
BOOST_THROW_EXCEPTION(_valueType.createTypeError("Invalid type name."));
// Convert value type to storage reference.
valueType = ReferenceType::copyForLocationIfReference(DataLocation::Storage, valueType);
// Convert key type to memory.
keyType = ReferenceType::copyForLocationIfReference(DataLocation::Memory, keyType);
return make_shared<MappingType>(keyType, valueType);
}

2
libsolidity/Version.cpp

@ -29,7 +29,7 @@ using namespace dev;
using namespace dev::solidity;
using namespace std;
char const* dev::solidity::VersionNumber = "0.1.0";
char const* dev::solidity::VersionNumber = "0.1.1";
extern string const dev::solidity::VersionString =
string(dev::solidity::VersionNumber) +
"-" +

25
mix/ClientModel.cpp

@ -402,10 +402,29 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence)
{
QSolidityType const* type = p->type();
QVariant value = transaction.parameterValues.value(p->name());
if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<"))
if (type->type().type == SolidityType::Type::Address)
{
std::pair<QString, int> ctrParamInstance = resolvePair(value.toString());
value = QVariant(resolveToken(ctrParamInstance));
if (type->array())
{
QJsonArray jsonDoc = QJsonDocument::fromJson(value.toString().toUtf8()).array();
int k = 0;
for (QJsonValue const& item: jsonDoc)
{
if (item.toString().startsWith("<"))
{
std::pair<QString, int> ctrParamInstance = resolvePair(item.toString());
jsonDoc.replace(k, resolveToken(ctrParamInstance));
}
k++;
}
QJsonDocument doc(jsonDoc);
value = QVariant(doc.toJson(QJsonDocument::Compact));
}
else if (value.toString().startsWith("<"))
{
std::pair<QString, int> ctrParamInstance = resolvePair(value.toString());
value = QVariant(resolveToken(ctrParamInstance));
}
}
encoder.encode(value, type->type());
}

2
mix/QVariableDeclaration.h

@ -47,6 +47,7 @@ class QSolidityType: public QObject
Q_PROPERTY(int size READ size CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QVariantList members READ members CONSTANT)
Q_PROPERTY(bool array READ array CONSTANT)
public:
QSolidityType() {}
@ -71,6 +72,7 @@ public:
int size() const { return m_type.size; }
QString name() const { return m_type.name; }
QVariantList members() const;
bool array() const { return m_type.array; }
private:
SolidityType m_type;

5
mix/qml/BlockChain.qml

@ -376,7 +376,6 @@ ColumnLayout {
block.status = "mined"
retBlocks.push(block)
}
}
if (retBlocks.length === 0)
retBlocks.push(projectModel.stateListModel.createEmptyBlock())
@ -587,7 +586,7 @@ ColumnLayout {
itemTr.parameters = _r.parameters
itemTr.isContractCreation = itemTr.functionId === itemTr.contractId
itemTr.label = _r.label
itemTr.isFunctionCall = itemTr.functionId !== ""
itemTr.isFunctionCall = itemTr.functionId !== "" && itemTr.functionId !== "<none>"
itemTr.returned = _r.returned
itemTr.value = QEtherHelper.createEther(_r.value, QEther.Wei)
itemTr.sender = _r.sender
@ -617,7 +616,7 @@ ColumnLayout {
clientModel.addAccount(ac.secret);
for (var k in Object.keys(blockChainPanel.states))
blockChainPanel.states[k].accounts["0x" + ac.address] = "0 wei" // add the account in all the previous state (balance at O)
accountAdded(ac.address, "0")
accountAdded("0x" + ac.address, "0")
}
Layout.preferredWidth: 100
Layout.preferredHeight: 30

1
mix/qml/Debugger.qml

@ -112,7 +112,6 @@ Rectangle {
ColumnLayout {
id: debugScrollArea
anchors.fill: parent
//orientation: Qt.Vertical
spacing: 0
RowLayout
{

21
mix/qml/DeployContractStep.qml

@ -19,7 +19,7 @@ Rectangle {
id: root
property int labelWidth: 150
property bool verifyDeploy: true
function show()
{
@ -37,12 +37,12 @@ Rectangle {
}
verifyDeployedContract()
deployedAddresses.refresh()
worker.renewCtx()
worker.renewCtx()
verifyDeploy = true
worker.pooler.onTriggered.connect(function() {
if (root.visible)
if (root.visible && verifyDeploy)
verifyDeployedContract();
})
}
@ -73,10 +73,13 @@ Rectangle {
verificationLabel.text = nb
if (trLost.length > 0)
{
verifyDeploy = false
verificationTextArea.visible = true
verificationLabel.visible = false
verificationTextArea.text = ""
deploymentStepChanged("following transactions are invalidated:")
verificationTextArea.text += "\n" + qsTr("Transactions lost") + "\n"
verificationTextArea.textColor = "red"
for (var k in trLost)
{
deploymentStepChanged(trLost[k])
@ -143,9 +146,11 @@ Rectangle {
ScrollView
{
anchors.fill: parent
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
ColumnLayout
{
spacing: 0
ListModel
{
id: trListModel
@ -218,6 +223,13 @@ Rectangle {
font.italic: true
}
}
Rectangle
{
Layout.preferredWidth: scenarioList.width
Layout.preferredHeight: 1
color: "#cccccc"
}
}
}
}
@ -524,6 +536,5 @@ Rectangle {
}
}
}
}

8
mix/qml/DeploymentWorker.qml

@ -128,7 +128,7 @@ Item
params: [],
id: req
});
var label = {}
var label = []
for (var k in trHashes)
{
req++
@ -142,15 +142,13 @@ Item
}
TransactionHelper.rpcCall(requests, function (httpRequest, response){
console.log(response)
var ret = JSON.parse(response)
var b = ret[0].result;
var trLost = []
for (var k in ret)
{
if (ret[k].result === null)
trLost.push(label[ret[k]])
if (!ret[k].result)
trLost.push(label[ret[k].id])
}
callback(parseInt(b, 16), trLost)
});

28
mix/qml/PackagingStep.qml

@ -51,13 +51,14 @@ Rectangle {
id: col
spacing: 20
anchors.left: parent.left
anchors.leftMargin: 10
Label
{
anchors.top: parent.top
Layout.fillWidth: true
anchors.left: parent.left
anchors.leftMargin: 10
text: qsTr("Upload and update your Dapp assets")
}
@ -67,11 +68,11 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 5
Label
{
text: qsTr("Save Package to")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
}
@ -80,7 +81,7 @@ Rectangle {
{
id: packageFolder
visible: true
Layout.preferredWidth: 150
Layout.preferredWidth: 360
text: projectPath + "package/"
}
@ -102,7 +103,8 @@ Rectangle {
Button
{
id: generatePackageBtn
anchors.horizontalCenter: parent.horizontalCenter
anchors.left: parent.left
anchors.leftMargin: 10
text: qsTr("Generate Package")
onClicked:
{
@ -117,7 +119,6 @@ Rectangle {
anchors.top: generatePackageBtn.bottom
anchors.topMargin: 10
visible: root.lastDeployDate !== ""
anchors.horizontalCenter: parent.horizontalCenter
Label
{
id: lastPackage
@ -137,11 +138,11 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 5
Label
{
text: qsTr("Local package URL")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
}
@ -149,7 +150,7 @@ Rectangle {
DefaultTextField
{
id: localPackageUrl
Layout.preferredWidth: 235
Layout.preferredWidth: 450
readOnly: true
}
}
@ -157,7 +158,6 @@ Rectangle {
Label
{
Layout.preferredWidth: 300
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("You have to upload the package to a remote folder, or use a service like pastebin")
wrapMode: Text.WordWrap
clip: true
@ -171,8 +171,9 @@ Rectangle {
Button
{
Layout.preferredWidth: 200
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Copy Base64")
anchors.left: parent.left
anchors.leftMargin: 10
onClicked:
{
clipboard.text = deploymentDialog.packageStep.packageBase64;
@ -188,8 +189,9 @@ Rectangle {
Button
{
Layout.preferredWidth: 200
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Open pastebin")
anchors.left: parent.left
anchors.leftMargin: 10
onClicked:
{
Qt.openUrlExternally("http://pastebin.com/");

162
mix/qml/QAddressView.qml

@ -1,8 +1,10 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.1
import "js/InputValidator.js" as InputValidator
Row
ColumnLayout
{
property alias value: textinput.text
property alias accountRef: ctrModel
@ -12,8 +14,16 @@ Row
property alias displayInput: textInputRect.visible
property variant accounts
signal indexChanged()
spacing: 0
id: editRoot
height: 20
height:
{
if (isArray() && !readOnly)
return 60
else
return 30
}
width: 320
SourceSansProBold
@ -21,6 +31,12 @@ Row
id: boldFont
}
function isArray()
{
InputValidator.init()
return InputValidator.isArray(subType)
}
function currentValue() {
return value;
}
@ -38,7 +54,7 @@ Row
function load()
{
accountRef.clear();
if (subType === "contract" || subType === "address")
if (subType.indexOf("contract") !== -1 || subType.indexOf("address") !== -1)
{
var trCr = 0;
if (blockChainPanel)
@ -59,7 +75,7 @@ Row
}
}
}
if (subType === "address")
if (subType.indexOf("address") !== -1)
{
for (k = 0; k < accounts.length; k++)
{
@ -72,21 +88,42 @@ Row
function init()
{
trCombobox.visible = !readOnly
btnAdd.visible = isArray()
textinput.readOnly = readOnly
if (isArray() || readOnly)
displayInput = true
else
displayInput = false
if (isArray() || !readOnly)
trCombobox.visible = true
else
trCombobox.visible = false
if (!trCombobox.visible)
{
rowCombobox.visible = false
rowCombobox.height = 0
trCombobox.height = 0
textinput.anchors.top = textinput.parent.top
}
if (!readOnly)
{
trCombobox.currentIndex = 0
for (var k = 0; k < ctrModel.count; k++)
{
if (ctrModel.get(k).value === value)
{
trCombobox.currentIndex = k;
return;
trCombobox.currentIndex = k
break
}
}
trCombobox.currentIndex = 0;
}
trCombobox.update()
if (!isArray())
trCombobox.update()
else if (value === "")
textinput.text = "[]"
}
function select(address)
@ -101,17 +138,73 @@ Row
}
}
ListModel
{
id: ctrModel
}
Row
{
anchors.top: parent.top
height: 30
id: rowCombobox
ComboBox
{
property bool selected: false
id: trCombobox
model: ctrModel
width: 265
textRole: "itemid"
function update()
{
trCombobox.selected = false;
if (currentText === "")
return;
else if (currentText !== " - ")
{
if (model.get(currentIndex).type === "contract")
textinput.text = "<" + currentText + ">";
else
textinput.text = model.get(currentIndex).value; //address
trCombobox.selected = true;
}
else if (textinput.text.indexOf("<") === 0)
{
textinput.text = "";
}
indexChanged();
}
onCurrentIndexChanged: {
if (!isArray())
update()
}
}
Button
{
id: btnAdd
text: qsTr("Add")
visible: false
onClicked:
{
var ar = JSON.parse(textinput.text)
ar.push(trCombobox.model.get(currentIndex).value)
textinput.text = JSON.stringify(ar)
}
}
}
Rectangle {
radius: 4
anchors.verticalCenter: parent.verticalCenter
height: 20
width: 350
height: 30
id: textInputRect
TextInput {
TextField {
id: textinput
text: value
width: parent.width
height: parent.width
wrapMode: Text.WordWrap
anchors.fill: parent
clip: true
font.family: boldFont.name
MouseArea {
@ -130,43 +223,4 @@ Row
}
}
}
ListModel
{
id: ctrModel
}
ComboBox
{
property bool selected: false
id: trCombobox
model: ctrModel
width: 350
textRole: "itemid"
anchors.verticalCenter: parent.verticalCenter
function update()
{
trCombobox.selected = false;
if (currentText === "")
return;
else if (currentText !== " - ")
{
if (model.get(currentIndex).type === "contract")
textinput.text = "<" + currentText + ">";
else
textinput.text = model.get(currentIndex).value; //address
trCombobox.selected = true;
}
else if (textinput.text.indexOf("<") === 0)
{
textinput.text = "";
}
indexChanged();
}
onCurrentIndexChanged: {
update()
}
}
}

66
mix/qml/QBoolTypeView.qml

@ -1,5 +1,6 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "js/InputValidator.js" as InputValidator
Item
{
@ -7,6 +8,7 @@ Item
property string value
property string defaultValue
property bool readOnly: !boolCombo.enabled
property string subType
height: 20
width: 150
@ -14,20 +16,59 @@ Item
boolCombo.enabled = !readOnly;
}
function isArray()
{
InputValidator.init()
return InputValidator.isArray(subType)
}
function init()
{
if (!isArray())
{
boolArray.visible = false
boolCombo.visible = true
value = format(value)
var setValue = "1"
if (value === "")
setValue = parseInt(defaultValue);
else
setValue = parseInt(value);
boolCombo.checked = setValue === "1" ? true: false
boolCombo.enabled = !readOnly;
}
else
{
boolArray.visible = true
boolCombo.visible = false
if (value === "")
boolArray.text = "[]"
else
boolArray.text = value
var formattedparam = []
var param = JSON.parse(boolArray.text)
for (var k in JSON.parse(boolArray.text))
formattedparam.push(parseInt(format(param[k])))
boolArray.text = JSON.stringify(formattedparam)
}
}
function finalize()
{
if (isArray())
value = boolArray.text
}
function format(value)
{
value = value === true ? "1" : value
value = value === false ? "0" : value;
value = value === "true" ? "1" : value
value = value === "false" ? "0" : value;
var setValue = "1"
if (value === "")
setValue = parseInt(defaultValue);
else
setValue = parseInt(value);
boolCombo.checked = setValue === "1" ? true: false
boolCombo.enabled = !readOnly;
return value
}
Rectangle {
@ -52,6 +93,15 @@ Item
}
text: qsTr("True")
}
TextField
{
id: boolArray
onTextChanged:
{
value = text
}
}
}
}

4
mix/qml/QIntTypeView.qml

@ -5,7 +5,7 @@ Item
property alias value: textinput.text
property alias readOnly: textinput.readOnly
id: editRoot
width: 200
width: 350
DebuggerPaneStyle {
id: dbgStyle
}
@ -15,7 +15,7 @@ Item
id: textinput
selectByMouse: true
text: value
implicitWidth: 200
implicitWidth: 350
MouseArea {
id: mouseArea
anchors.fill: parent

3
mix/qml/QStringTypeView.qml

@ -6,7 +6,7 @@ Item
property alias value: textinput.text
property alias readOnly: textinput.readOnly
id: editRoot
width: readOnly ? textinput.implicitWidth : 150
width: 350
DebuggerPaneStyle {
id: dbgStyle
@ -17,6 +17,7 @@ Item
id: textinput
selectByMouse: true
text: value
width: 350
MouseArea {
id: mouseArea
anchors.fill: parent

44
mix/qml/RegisteringStep.qml

@ -90,11 +90,11 @@ Rectangle {
anchors.topMargin: 10
id: col
spacing: 20
anchors.left: parent.left
anchors.leftMargin: 10
Label
{
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: 10
Layout.fillWidth: true
text: qsTr("Register your Dapp on the Name registrar Contract")
}
@ -105,11 +105,11 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 5
Label
{
text: qsTr("Root Registrar address")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
}
@ -119,7 +119,7 @@ Rectangle {
id: registrarAddr
text: "c6d9d2cd449a754c494264e1809c50e34d64562b"
visible: true
Layout.preferredWidth: 235
Layout.preferredWidth: 450
}
}
@ -129,11 +129,11 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 5
Label
{
text: qsTr("Http URL")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
}
@ -141,7 +141,7 @@ Rectangle {
DefaultTextField
{
id: applicationUrlHttpCtrl
Layout.preferredWidth: 235
Layout.preferredWidth: 450
}
Label
@ -158,11 +158,11 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 5
Label
{
text: qsTr("Registration Cost")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
id: ctrRegisterLabel
function calculateRegisterGas()
@ -200,23 +200,23 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 5
Label
{
text: qsTr("Ethereum URL")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
}
}
Rectangle
{
height: 25
color: "transparent"
Layout.preferredWidth: 235
Layout.preferredWidth: 450
DefaultTextField
{
width: 235
width: 450
id: applicationUrlEthCtrl
onTextChanged: {
ctrRegisterLabel.calculateRegisterGas();
@ -231,11 +231,11 @@ Rectangle {
Layout.preferredHeight: 20
Rectangle
{
Layout.preferredWidth: col.width / 2
Layout.preferredWidth: col.width / 4
Label
{
text: qsTr("Formatted Ethereum URL")
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
}
@ -252,7 +252,7 @@ Rectangle {
Label
{
id: verificationEthUrl
anchors.verticalCenter: parent.verticalCenter;
anchors.verticalCenter: parent.verticalCenter;
anchors.topMargin: 10
font.italic: true
font.pointSize: appStyle.absoluteSize(-1)
@ -264,7 +264,7 @@ Rectangle {
{
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
width: parent.width
width: parent.width
function registerHash(gasPrice, callback)
{
@ -276,7 +276,7 @@ Rectangle {
inError.push(qsTr("Member too long: " + ethUrl[k]) + "\n");
}
if (!worker.stopForInputError(inError))
{
{
NetworkDeploymentCode.registerDapp(ethUrl, gasPrice, function(){
projectModel.applicationUrlEth = applicationUrlEthCtrl.text
projectModel.saveProject()
@ -309,7 +309,9 @@ Rectangle {
inError.push(qsTr(applicationUrlHttpCtrl.text));
if (!worker.stopForInputError(inError))
{
registerToUrlHint(applicationUrlHttpCtrl.text, gasPrice, function(){
var url = applicationUrlHttpCtrl.text
url = url.replace("http://", "").replace("https://", "")
registerToUrlHint(url, gasPrice, function(){
projectModel.applicationUrlHttp = applicationUrlHttpCtrl.text
projectModel.saveProject()
verificationUrl.text = qsTr("waiting verifications")

1
mix/qml/ScenarioLoader.qml

@ -29,7 +29,6 @@ ColumnLayout
function needSaveOrReload()
{
editStatus.visible = true
}
RowLayout

2
mix/qml/StateDialog.qml

@ -15,7 +15,7 @@ Dialog {
width: 630
height: 660
title: qsTr("Edit State")
title: qsTr("Edit Genesis Parameters")
visible: false
property alias isDefault: defaultCheckBox.checked

3
mix/qml/StateList.qml

@ -17,6 +17,7 @@ Dialog {
ColumnLayout
{
anchors.fill: parent
anchors.margins: 10
TableView {
id: list
Layout.fillHeight: true
@ -57,7 +58,7 @@ Dialog {
verticalAlignment: Text.AlignBottom
}
ToolButton {
text: qsTr("Edit");
text: qsTr("Edit Genesis");
Layout.fillHeight: true
onClicked: list.model.editState(styleData.row);
}

4
mix/qml/StateListModel.qml

@ -301,7 +301,7 @@ Item {
var ctorTr = defaultTransactionItem();
ctorTr.functionId = c;
ctorTr.contractId = c;
ctorTr.label = qsTr("Deploy") + " " + ctorTr.contractId;
ctorTr.label = ctorTr.contractId + "." + ctorTr.contractId + "()"
ctorTr.sender = item.accounts[0].secret;
item.transactions.push(ctorTr);
item.blocks[0].transactions.push(ctorTr)
@ -343,7 +343,7 @@ Item {
var ctorTr = defaultTransactionItem();
ctorTr.functionId = c;
ctorTr.contractId = c;
ctorTr.label = qsTr("Deploy") + " " + ctorTr.contractId;
ctorTr.label = ctorTr.contractId + "." + ctorTr.contractId + "()";
ctorTr.sender = state.accounts[0].secret;
state.transactions.push(ctorTr);
changed = true;

44
mix/qml/StructView.qml

@ -13,7 +13,16 @@ Column
property int transactionIndex
property string context
Layout.fillWidth: true
spacing: 5
spacing: 0
property int colHeight
function clear()
{
value = {}
members = []
colHeight = 0
}
Repeater
{
id: repeater
@ -21,8 +30,17 @@ Column
RowLayout
{
id: row
height: 30 + (members[index].type.category === QSolidityType.Struct ? (30 * members[index].type.members.length) : 0)
Layout.fillWidth: true
Component.onCompleted:
{
if (QSolidityType.Address === members[index].type.category && members[index].type.array && context === "parameter")
height = 60
else
height = 30 + (members[index].type.category === QSolidityType.Struct ? (30 * members[index].type.members.length) : 0)
root.colHeight += height
}
Rectangle
{
Layout.preferredWidth: 150
@ -30,12 +48,14 @@ Column
{
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
Label {
Label
{
id: nameLabel
text: modelData.name
}
Label {
Label
{
id: typeLabel
text: " (" + modelData.type.name + ")"
font.italic: true
@ -72,6 +92,7 @@ Column
var ptype = members[index].type;
var pname = members[index].name;
var vals = value;
item.readOnly = context === "variable";
if (ptype.category === QSolidityType.Address)
{
@ -94,18 +115,29 @@ Column
item.value = getValue();
if (ptype.category === QSolidityType.Bool)
{
item.subType = modelData.type.name
item.init();
}
item.onValueChanged.connect(function() {
vals[pname] = item.value;
valueChanged();
syncValue(vals, pname)
});
var newWidth = nameLabel.width + typeLabel.width + item.width + 108;
if (root.width < newWidth)
root.width = newWidth;
syncValue(vals, pname)
}
function syncValue(vals, pname)
{
vals[pname] = item.value;
valueChanged();
}
function getValue()
{
var r = "";

18
mix/qml/TransactionDialog.qml

@ -8,6 +8,7 @@ import org.ethereum.qml.QEther 1.0
import "js/TransactionHelper.js" as TransactionHelper
import "js/InputValidator.js" as InputValidator
import "js/NetworkDeployment.js" as NetworkDeployment
import "js/QEtherHelper.js" as QEtherHelper
import "."
Dialog {
@ -54,7 +55,6 @@ Dialog {
if (item.sender)
senderComboBox.select(item.sender);
trTypeCreate.checked = item.isContractCreation
trTypeSend.checked = !item.isFunctionCall
trTypeExecute.checked = item.isFunctionCall && !item.isContractCreation
@ -152,8 +152,7 @@ Dialog {
function initTypeLoader()
{
paramScroll.value = {}
paramScroll.members = []
paramScroll.clear()
paramScroll.value = paramValues;
paramScroll.members = paramsModel;
paramScroll.updateView()
@ -237,6 +236,8 @@ Dialog {
recipientsAccount.select(contractId);
if (functionId)
selectFunction(functionId);
else
functionComboBox.currentIndex = 0
if (isFunctionCall)
{
labelRecipient.text = qsTr("Recipient Contract")
@ -489,14 +490,14 @@ Dialog {
StructView
{
id: paramScroll
members: paramsModel;
members: paramsModel
accounts: senderComboBox.model
context: "parameter"
Layout.fillWidth: true
function updateView()
{
paramScroll.visible = paramsModel.length > 0
paramScroll.Layout.preferredHeight = paramsModel.length < 6 ? paramsModel.length * 30 : 205
paramScroll.Layout.preferredHeight = paramScroll.colHeight
if (paramsModel.length === 0)
paramScroll.height = 0
}
@ -519,7 +520,7 @@ Dialog {
Layout.preferredWidth: 350
id: valueField
edit: true
displayFormattedValue: false
displayFormattedValue: true
displayUnitSelection: true
}
}
@ -655,11 +656,12 @@ Dialog {
Label {
id: gasPriceMarket
anchors.top: gasPriceLabel.bottom
anchors.topMargin: 10
Component.onCompleted:
{
NetworkDeployment.gasPrice(function(result)
{
gasPriceMarket.text = qsTr("Current market: ") + " " + result + " Wei";
gasPriceMarket.text = qsTr("Current market: ") + " " + QEtherHelper.createEther(result, QEther.Wei).format()
}, function (){});
}
}
@ -667,7 +669,7 @@ Dialog {
}
Ether {
Layout.preferredWidth: 350
Layout.preferredWidth: 400
id: gasPriceField
edit: true
displayFormattedValue: false

2
mix/qml/VariablesView.qml

@ -25,7 +25,7 @@ DebugInfoList
members: []
value: {}
context: "variable"
width:parent.width
width: parent.width
}
}
}

1
mix/qml/Watchers.qml

@ -13,7 +13,6 @@ import "."
Rectangle {
color: "#4F4F4F"
radius: 4
property variant tx
property variant currentState
property variant bc

2
mix/qml/html/codeeditor.js

@ -246,7 +246,7 @@ displayGasEstimation = function(show)
{
var color;
var colorIndex = Math.round(step * gasCosts[i].gas);
if (gasCosts[i].isInfinite || colorIndex > colorGradient.length)
if (gasCosts[i].isInfinite || colorIndex >= colorGradient.length)
color = colorGradient[colorGradient.length - 1];
else
color = colorGradient[colorIndex];

9
mix/qml/js/InputValidator.js

@ -32,10 +32,11 @@ function init()
function check(type, value)
{
var res = { valid: true, message : "" }
if (isContractType(type))
res = validateAddress(type, value);
else if (isArray(type))
if (isArray(type))
res = validateArray(type, value);
else if (isContractType(type))
res = validateAddress(type, value);
else if (type.indexOf("int") !== -1)
res = validateInt(type, value);
else if (type.indexOf("enum") !== -1)
@ -196,7 +197,7 @@ function validateBytes(_type, _value)
function validateBool(_type, _value)
{
var ret = { valid: true, message: "" }
if (_value !== "1" && _value !== "0")
if (!(_value === "1" || _value === "0" || _value === 1 || _value === 0))
{
ret.valid = false;
ret.message = _value + " is not in the correct bool format";

44
solc/CommandLineInterface.cpp

@ -63,6 +63,7 @@ static string const g_argAsmJsonStr = "asm-json";
static string const g_argAstStr = "ast";
static string const g_argAstJson = "ast-json";
static string const g_argBinaryStr = "binary";
static string const g_argCloneBinaryStr = "clone-binary";
static string const g_argOpcodesStr = "opcodes";
static string const g_argNatspecDevStr = "natspec-dev";
static string const g_argNatspecUserStr = "natspec-user";
@ -71,6 +72,7 @@ static string const g_argAddStandard = "add-std";
/// Possible arguments to for --combined-json
static set<string> const g_combinedJsonArgs{
"binary",
"clone-binary",
"opcodes",
"json-abi",
"sol-abi",
@ -110,7 +112,8 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args)
humanTargetedStdout(_args, g_argAsmStr) ||
humanTargetedStdout(_args, g_argAsmJsonStr) ||
humanTargetedStdout(_args, g_argOpcodesStr) ||
humanTargetedStdout(_args, g_argBinaryStr);
humanTargetedStdout(_args, g_argBinaryStr) ||
humanTargetedStdout(_args, g_argCloneBinaryStr);
}
static inline bool outputToFile(OutputType type)
@ -140,18 +143,33 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output)
void CommandLineInterface::handleBinary(string const& _contract)
{
auto choice = m_args[g_argBinaryStr].as<OutputType>();
if (outputToStdout(choice))
if (m_args.count(g_argBinaryStr))
{
cout << "Binary: " << endl;
cout << toHex(m_compiler->getBytecode(_contract)) << endl;
if (outputToStdout(m_args[g_argBinaryStr].as<OutputType>()))
{
cout << "Binary: " << endl;
cout << toHex(m_compiler->getBytecode(_contract)) << endl;
}
if (outputToFile(m_args[g_argBinaryStr].as<OutputType>()))
{
ofstream outFile(_contract + ".binary");
outFile << toHex(m_compiler->getBytecode(_contract));
outFile.close();
}
}
if (outputToFile(choice))
if (m_args.count(g_argCloneBinaryStr))
{
ofstream outFile(_contract + ".binary");
outFile << toHex(m_compiler->getBytecode(_contract));
outFile.close();
if (outputToStdout(m_args[g_argCloneBinaryStr].as<OutputType>()))
{
cout << "Clone Binary: " << endl;
cout << toHex(m_compiler->getCloneBytecode(_contract)) << endl;
}
if (outputToFile(m_args[g_argCloneBinaryStr].as<OutputType>()))
{
ofstream outFile(_contract + ".clone_binary");
outFile << toHex(m_compiler->getCloneBytecode(_contract));
outFile.close();
}
}
}
@ -177,7 +195,7 @@ void CommandLineInterface::handleBytecode(string const& _contract)
{
if (m_args.count(g_argOpcodesStr))
handleOpcode(_contract);
if (m_args.count(g_argBinaryStr))
if (m_args.count(g_argBinaryStr) || m_args.count(g_argCloneBinaryStr))
handleBinary(_contract);
}
@ -329,6 +347,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv)
"Request to output the Opcodes of the contract.")
(g_argBinaryStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"Request to output the contract in binary (hexadecimal).")
(g_argCloneBinaryStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"Request to output the clone contract in binary (hexadecimal).")
(g_argAbiStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"Request to output the contract's JSON ABI interface.")
(g_argSolAbiStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
@ -490,6 +510,8 @@ void CommandLineInterface::handleCombinedJSON()
contractData["json-abi"] = m_compiler->getInterface(contractName);
if (requests.count("binary"))
contractData["binary"] = toHex(m_compiler->getBytecode(contractName));
if (requests.count("clone-binary"))
contractData["clone-binary"] = toHex(m_compiler->getCloneBytecode(contractName));
if (requests.count("opcodes"))
contractData["opcodes"] = eth::disassemble(m_compiler->getBytecode(contractName));
if (requests.count("asm"))

33
test/libsolidity/SolidityEndToEndTest.cpp

@ -5099,6 +5099,39 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_CASE(string_as_mapping_key)
{
char const* sourceCode = R"(
contract Test {
mapping(string => uint) data;
function set(string _s, uint _v) { data[_s] = _v; }
function get(string _s) returns (uint) { return data[_s]; }
}
)";
compileAndRun(sourceCode, 0, "Test");
vector<string> strings{
"Hello, World!",
"Hello, World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1111",
"",
"1"
};
for (unsigned i = 0; i < strings.size(); i++)
BOOST_CHECK(callContractFunction(
"set(string,uint256)",
u256(0x40),
u256(7 + i),
u256(strings[i].size()),
strings[i]
) == encodeArgs());
for (unsigned i = 0; i < strings.size(); i++)
BOOST_CHECK(callContractFunction(
"get(string)",
u256(0x20),
u256(strings[i].size()),
strings[i]
) == encodeArgs(u256(7 + i)));
}
BOOST_AUTO_TEST_SUITE_END()
}

2
test/libwhisper/whisperTopic.cpp

@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(topic)
});
Host host2("Test", NetworkPreferences("127.0.0.1", 30310, false));
host1.setIdealPeerCount(1);
host2.setIdealPeerCount(1);
auto whost2 = host2.registerCapability(new WhisperHost());
host2.start();

Loading…
Cancel
Save