Browse Source

Auto-loading plugins.

OtherAccounts address namer + interface.
OurAccounts address namer.
Additional internal support for extensible account naming.
cl-refactor
Gav Wood 10 years ago
parent
commit
f2fb952995
  1. 5
      alethzero/AllAccounts.cpp
  2. 4
      alethzero/AllAccounts.h
  3. 8
      alethzero/BrainWallet.cpp
  4. 4
      alethzero/BrainWallet.ui
  5. 3
      alethzero/CMakeLists.txt
  6. 2
      alethzero/LogPanel.cpp
  7. 20
      alethzero/MainFace.cpp
  8. 30
      alethzero/MainFace.h
  9. 65
      alethzero/MainWin.cpp
  10. 7
      alethzero/MainWin.h
  11. 87
      alethzero/OtherAccounts.cpp
  12. 55
      alethzero/OtherAccounts.h
  13. 95
      alethzero/OtherAccounts.ui
  14. 66
      alethzero/OurAccounts.cpp
  15. 52
      alethzero/OurAccounts.h
  16. 51
      alethzero/Transact.cpp
  17. 6
      alethzero/Transact.h
  18. 20
      libethcore/Common.cpp
  19. 5
      libethcore/Common.h
  20. 19
      libethcore/CommonJS.cpp
  21. 4
      libethcore/CommonJS.h

5
alethzero/AllAccounts.cpp

@ -19,6 +19,8 @@
* @date 2015
*/
#if ETH_FATDB
#include "AllAccounts.h"
#include <sstream>
#include <QClipboard>
@ -32,6 +34,8 @@ using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(AllAccounts);
AllAccounts::AllAccounts(MainFace* _m):
Plugin(_m, "AllAccounts"),
m_ui(new Ui::AllAccounts)
@ -131,3 +135,4 @@ void AllAccounts::on_accounts_doubleClicked()
}
}
#endif

4
alethzero/AllAccounts.h

@ -21,6 +21,8 @@
#pragma once
#if ETH_FATDB
#include <QListWidget>
#include <QPlainTextEdit>
#include "MainFace.h"
@ -58,3 +60,5 @@ private:
}
}
#endif

8
alethzero/BrainWallet.cpp

@ -34,14 +34,12 @@ using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(BrainWallet);
BrainWallet::BrainWallet(MainFace* _m):
Plugin(_m, "BrainWallet")
{
QAction* a = new QAction("New Brain Wallet...", main());
QMenu* m = _m->findChild<QMenu*>("menuTools");
m->addSeparator();
m->addAction(a);
connect(a, SIGNAL(triggered()), SLOT(create()));
connect(addMenuItem("New Brain Wallet...", "menuTools", true), SIGNAL(triggered()), SLOT(create()));
}
BrainWallet::~BrainWallet()

4
alethzero/BrainWallet.ui

@ -17,7 +17,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;WARNING: Brain wallets, or human-entropic seeds, are practically and cryptographically insecure. They're a terrible idea for protecteding anything of value and this functionality is here only as a toy.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;That said, if you're intent on using one, make the phrase as long and random as you can. If you're sensible, you'll ask the internet for a list of words to memorise and use those. Write the phrase down on paper and bury it under an oak tree or something - if you forget it, you're screwed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;WARNING: Brain wallets, or human-entropic seeds, are generally a Bad Plan. Unless used properly they're a terrible idea for protecteding anything of value. Read up on them and know the risks before using this functionality!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;That said, if you're intent on using one, make the phrase as long and random as you can. If you're sensible, you'll use the Generate button and memorise the list of words it gives you. This is the only way to guarantee a strong brainwallet. Write the phrase down on paper and bury it under an oak tree or something - if you forget it, you're screwed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -34,7 +34,7 @@
<item>
<widget class="QTextEdit" name="seed">
<property name="placeholderText">
<string>Write your seed phrase here. Make it long and random. Don't ever forget it. If you want it to have any chance at being secure, ask a machine to select 13 dictionary words at random.</string>
<string>Write your seed phrase here. Make it long and random. Don't ever forget it. If you want it to have any chance at being secure, hit the Generate button and memorize what ends up here.</string>
</property>
</widget>
</item>

3
alethzero/CMakeLists.txt

@ -41,6 +41,7 @@ qt5_wrap_ui(ui_GasPricing.h GasPricing.ui)
qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui)
qt5_wrap_ui(ui_LogPanel.h LogPanel.ui)
qt5_wrap_ui(ui_BrainWallet.h BrainWallet.ui)
qt5_wrap_ui(ui_OtherAccounts.h OtherAccounts.ui)
file(GLOB HEADERS "*.h")
@ -53,7 +54,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 AllAccounts.ui LogPanel.ui BrainWallet.ui
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui LogPanel.ui BrainWallet.ui OtherAccounts.ui
WIN_RESOURCES alethzero.rc
)

2
alethzero/LogPanel.cpp

@ -38,6 +38,8 @@ static QString filterOutTerminal(QString _s)
return _s.replace(QRegExp("\x1b\\[(\\d;)?\\d+m"), "");
}
DEV_AZ_NOTE_PLUGIN(LogPanel);
LogPanel::LogPanel(MainFace* _m):
Plugin(_m, "LogPanel"),
m_ui(new Ui::LogPanel)

20
alethzero/MainFace.cpp

@ -19,11 +19,19 @@
* @date 2014
*/
#include <QMenu>
#include "MainFace.h"
using namespace std;
using namespace dev;
using namespace az;
void MainFace::notePlugin(std::function<Plugin*(MainFace*)> const& _new)
{
if (!s_linkedPlugins)
s_linkedPlugins = new std::vector<std::function<Plugin*(MainFace*)>>();
s_linkedPlugins->push_back(_new);
}
Plugin::Plugin(MainFace* _f, std::string const& _name):
m_main(_f),
m_name(_name)
@ -54,6 +62,18 @@ void Plugin::addAction(QAction* _a)
m_main->addAction(_a);
}
QAction* Plugin::addMenuItem(QString _n, QString _menuName, bool _sep)
{
QAction* a = new QAction(_n, main());
QMenu* m = main()->findChild<QMenu*>(_menuName);
if (_sep)
m->addSeparator();
m->addAction(a);
return a;
}
std::vector<std::function<Plugin*(MainFace*)>>* MainFace::s_linkedPlugins = nullptr;
void MainFace::adoptPlugin(Plugin* _p)
{
m_plugins[_p->name()] = shared_ptr<Plugin>(_p);

30
alethzero/MainFace.h

@ -43,6 +43,9 @@ namespace shh { class WhisperHost; }
namespace az
{
#define DEV_AZ_NOTE_PLUGIN(ClassName) \
static bool s_notePlugin = [](){ MainFace::notePlugin([](MainFace* m){ return new ClassName(m); }); return true; }()
class Plugin;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
@ -57,14 +60,20 @@ public:
class MainFace: public QMainWindow, public Context
{
Q_OBJECT
public:
explicit MainFace(QWidget* _parent = nullptr): QMainWindow(_parent) {}
static void notePlugin(std::function<Plugin*(MainFace*)> const& _new);
void adoptPlugin(Plugin* _p);
void killPlugins();
void allChange();
using Context::render;
// 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;
@ -78,11 +87,22 @@ public:
virtual void install(AccountNamer* _adopt) = 0;
virtual void uninstall(AccountNamer* _kill) = 0;
virtual void noteAddressesChanged() = 0;
virtual Address toAddress(std::string const&) const = 0;
virtual std::string toName(Address const&) const = 0;
virtual Addresses allKnownAddresses() const = 0;
virtual void noteSettingsChanged() = 0;
protected:
template <class F> void forEach(F const& _f) { for (auto const& p: m_plugins) _f(p.second); }
std::shared_ptr<Plugin> takePlugin(std::string const& _name) { auto it = m_plugins.find(_name); std::shared_ptr<Plugin> ret; if (it != m_plugins.end()) { ret = it->second; m_plugins.erase(it); } return ret; }
static std::vector<std::function<Plugin*(MainFace*)>>* s_linkedPlugins;
signals:
void allKnownAddressesChanged();
void keyManagerChanged();
private:
std::unordered_map<std::string, std::shared_ptr<Plugin>> m_plugins;
};
@ -98,10 +118,11 @@ public:
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; }
MainFace* main() const { 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);
QAction* addMenuItem(QString _name, QString _menuName, bool _separate = false);
virtual void onAllChange() {}
virtual void readSettings(QSettings const&) {}
@ -113,6 +134,13 @@ private:
QDockWidget* m_dock = nullptr;
};
class AccountNamerPlugin: public Plugin, public AccountNamer
{
protected:
AccountNamerPlugin(MainFace* _m, std::string const& _name): Plugin(_m, _name) { main()->install(this); }
~AccountNamerPlugin() { main()->uninstall(this); }
};
}
}

65
alethzero/MainWin.cpp

@ -74,9 +74,6 @@
#include "DappHost.h"
#include "WebPage.h"
#include "ExportState.h"
#include "AllAccounts.h"
#include "LogPanel.h"
#include "BrainWallet.h"
#include "ui_Main.h"
#include "ui_GetPassword.h"
#include "ui_GasPricing.h"
@ -266,11 +263,8 @@ Main::Main(QWidget* _parent):
}
}
#if ETH_FATDB
loadPlugin<dev::az::AllAccounts>();
#endif
loadPlugin<dev::az::LogPanel>();
loadPlugin<dev::az::BrainWallet>();
for (auto const& i: *s_linkedPlugins)
initPlugin(i(this));
}
Main::~Main()
@ -282,6 +276,9 @@ Main::~Main()
// need to be rethought into something more like:
// forEach([&](shared_ptr<Plugin> const& p){ finalisePlugin(p.get()); });
writeSettings();
m_destructing = true;
killPlugins();
}
string Main::fromRaw(h256 const& _n, unsigned* _inc)
@ -318,14 +315,41 @@ void Main::install(AccountNamer* _adopt)
void Main::uninstall(AccountNamer* _kill)
{
m_namers.erase(_kill);
refreshAll();
if (!m_destructing)
refreshAll();
}
void Main::noteAddressesChanged()
{
emit allKnownAddressesChanged();
refreshAll();
}
Address Main::toAddress(string const& _n) const
{
for (AccountNamer* n: m_namers)
if (n->toAddress(_n))
return n->toAddress(_n);
return Address();
}
string Main::toName(Address const& _a) const
{
for (AccountNamer* n: m_namers)
if (!n->toName(_a).empty())
return n->toName(_a);
return string();
}
Addresses Main::allKnownAddresses() const
{
Addresses ret;
for (AccountNamer* i: m_namers)
ret += i->knownAddresses();
sort(ret.begin(), ret.end());
return ret;
}
bool Main::confirm() const
{
return ui->natSpec->isChecked();
@ -684,8 +708,6 @@ pair<Address, bytes> Main::fromString(std::string const& _n) const
return make_pair(Address(), bytes());
std::string n = _n;
if (n.find("0x") == 0)
n.erase(0, 2);
auto g_newNameReg = getNameReg();
if (g_newNameReg)
@ -699,6 +721,16 @@ pair<Address, bytes> Main::fromString(std::string const& _n) const
if (auto a = i->toAddress(_n))
return make_pair(a, bytes());
try {
return ICAP::decoded(n).address([&](Address const& a, bytes const& b) -> bytes
{
return ethereum()->call(a, b).output;
}, g_newNameReg);
}
catch (...) {}
if (n.find("0x") == 0)
n.erase(0, 2);
if (n.size() == 40)
{
try
@ -717,14 +749,6 @@ pair<Address, bytes> Main::fromString(std::string const& _n) const
return make_pair(Address(), bytes());
}
}
else
try {
return ICAP::decoded(n).address([&](Address const& a, bytes const& b) -> bytes
{
return ethereum()->call(a, b).output;
}, g_newNameReg);
}
catch (...) {}
return make_pair(Address(), bytes());
}
@ -1903,7 +1927,7 @@ void Main::on_ourAccounts_doubleClicked()
{
auto hba = ui->ourAccounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
qApp->clipboard()->setText(QString::fromStdString(ICAP(h).encoded()) + " (" + QString::fromStdString(h.hex()) + ")");
}
/*void Main::on_log_doubleClicked()
@ -2060,6 +2084,7 @@ void Main::on_mine_triggered()
void Main::keysChanged()
{
emit keyManagerChanged();
onBalancesChange();
}

7
alethzero/MainWin.h

@ -110,6 +110,11 @@ public:
void install(AccountNamer* _adopt) override;
void uninstall(AccountNamer* _kill) override;
void noteAddressesChanged() override;
Address toAddress(std::string const&) const override;
std::string toName(Address const&) const override;
Addresses allKnownAddresses() const override;
void noteSettingsChanged() override { writeSettings(); }
public slots:
void load(QString _file);
@ -299,6 +304,8 @@ private:
Connect m_connect;
std::unordered_set<AccountNamer*> m_namers;
bool m_destructing = false;
};
}

87
alethzero/OtherAccounts.cpp

@ -0,0 +1,87 @@
/*
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 OtherAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "OtherAccounts.h"
#include <QSettings>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include <ui_OtherAccounts.h>
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(OtherAccounts);
OtherAccounts::OtherAccounts(MainFace* _m):
AccountNamerPlugin(_m, "OtherAccounts")
{
connect(addMenuItem("New Brain Wallet...", "menuTools", true), SIGNAL(triggered()), SLOT(import()));
}
void OtherAccounts::import()
{
QDialog d;
Ui_OtherAccounts u;
u.setupUi(&d);
d.setWindowTitle("Add Named Accounts");
if (d.exec() == QDialog::Accepted)
{
QStringList sl = u.accounts->toPlainText().split("\n");
for (QString const& s: sl)
{
Address addr = toAddress(s.section("[ \\t]+", 0, 1).toStdString());
string name = s.section("[ \\t]+", 1).toStdString();
m_toName[addr] = name;
m_toAddress[name] = addr;
}
main()->noteSettingsChanged();
main()->noteAddressesChanged();
}
}
void OtherAccounts::readSettings(QSettings const& _s)
{
m_toName.clear();
m_toAddress.clear();
for (QVariant const& i: _s.value("OtherAccounts", QVariantList()).toList())
{
QStringList l = i.toStringList();
if (l.size() == 2)
{
m_toName[Address(l[0].toStdString())] = l[1].toStdString();
m_toAddress[l[1].toStdString()] = Address(l[0].toStdString());
}
}
}
void OtherAccounts::writeSettings(QSettings& _s)
{
QVariantList r;
for (auto const& i: m_toName)
{
QStringList l;
l += QString::fromStdString(i.first.hex());
l += QString::fromStdString(i.second);
r += QVariant(l);
}
_s.setValue("OtherAccounts", r);
}

55
alethzero/OtherAccounts.h

@ -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 OtherAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class OtherAccounts: public QObject, public AccountNamerPlugin
{
Q_OBJECT
public:
OtherAccounts(MainFace* _m);
protected:
std::string toName(Address const& _a) const override { if (m_toName.count(_a)) return m_toName.at(_a); return std::string(); }
Address toAddress(std::string const& _n) const override { if (m_toAddress.count(_n)) return m_toAddress.at(_n); return Address(); }
Addresses knownAddresses() const override { return keysOf(m_toName); }
private slots:
void import();
private:
void readSettings(QSettings const&) override;
void writeSettings(QSettings&) override;
std::unordered_map<std::string, Address> m_toAddress;
std::unordered_map<Address, std::string> m_toName;
};
}
}

95
alethzero/OtherAccounts.ui

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OtherAccounts</class>
<widget class="QDialog" name="OtherAccounts">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>511</width>
<height>508</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="accounts">
<property name="placeholderText">
<string>Write the accounts you wish to name here, one address/name pair per line, the name following the address split only be a single space character.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="create">
<property name="text">
<string>&amp;Import</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>create</sender>
<signal>clicked()</signal>
<receiver>OtherAccounts</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>462</x>
<y>484</y>
</hint>
<hint type="destinationlabel">
<x>449</x>
<y>504</y>
</hint>
</hints>
</connection>
<connection>
<sender>cancel</sender>
<signal>clicked()</signal>
<receiver>OtherAccounts</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>381</x>
<y>483</y>
</hint>
<hint type="destinationlabel">
<x>351</x>
<y>506</y>
</hint>
</hints>
</connection>
</connections>
</ui>

66
alethzero/OurAccounts.cpp

@ -0,0 +1,66 @@
/*
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 OurAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "OurAccounts.h"
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include <libethcore/KeyManager.h>
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(OurAccounts);
OurAccounts::OurAccounts(MainFace* _m):
AccountNamerPlugin(_m, "OurAccounts")
{
connect(main(), SIGNAL(keyManagerChanged()), SLOT(updateNames()));
updateNames();
}
OurAccounts::~OurAccounts()
{
}
std::string OurAccounts::toName(Address const& _a) const
{
return main()->keyManager().accountName(_a);
}
Address OurAccounts::toAddress(std::string const& _n) const
{
if (m_names.count(_n))
return m_names.at(_n);
return Address();
}
Addresses OurAccounts::knownAddresses() const
{
return main()->keyManager().accounts();
}
void OurAccounts::updateNames()
{
m_names.clear();
for (Address const& i: main()->keyManager().accounts())
m_names[main()->keyManager().accountName(i)] = i;
}

52
alethzero/OurAccounts.h

@ -0,0 +1,52 @@
/*
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 OurAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class OurAccounts: public QObject, public AccountNamerPlugin
{
Q_OBJECT
public:
OurAccounts(MainFace* _m);
~OurAccounts();
protected:
std::string toName(Address const& _a) const override;
Address toAddress(std::string const& _n) const override;
Addresses knownAddresses() const override;
private slots:
void updateNames();
private:
std::unordered_map<std::string, Address> m_names;
};
}
}

51
alethzero/Transact.cpp

@ -40,6 +40,7 @@
#include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#include <libethcore/ICAP.h>
#include <libethcore/KeyManager.h>
#if ETH_SERPENT
#include <libserpent/funcs.h>
@ -52,10 +53,10 @@ using namespace dev;
using namespace az;
using namespace eth;
Transact::Transact(Context* _c, QWidget* _parent):
Transact::Transact(MainFace* _c, QWidget* _parent):
QDialog(_parent),
ui(new Ui::Transact),
m_context(_c)
m_main(_c)
{
ui->setupUi(this);
@ -81,9 +82,10 @@ void Transact::setEnvironment(AddressHash const& _accounts, dev::eth::Client* _e
for (auto const& address: m_accounts)
{
u256 b = ethereum()->balanceAt(address, PendingBlock);
QString s = QString("%4 %2: %1").arg(formatBalance(b).c_str()).arg(QString::fromStdString(m_context->render(address))).arg(QString::fromStdString(m_context->keyManager().accountName(address)));
QString s = QString("%2: %1").arg(formatBalance(b).c_str()).arg(QString::fromStdString(m_main->render(address)));
ui->from->addItem(s);
}
updateDestination();
if (old > -1 && old < ui->from->count())
ui->from->setCurrentIndex(old);
else if (ui->from->count())
@ -92,7 +94,7 @@ void Transact::setEnvironment(AddressHash const& _accounts, dev::eth::Client* _e
void Transact::resetGasPrice()
{
setValueUnits(ui->gasPriceUnits, ui->gasPrice, m_context->gasPrice());
setValueUnits(ui->gasPriceUnits, ui->gasPrice, m_main->gasPrice());
}
bool Transact::isCreation() const
@ -121,7 +123,7 @@ u256 Transact::gasPrice() const
Address Transact::to() const
{
return m_context->fromString(ui->destination->currentText().toStdString()).first;
return m_main->fromString(ui->destination->currentText().toStdString()).first;
}
u256 Transact::total() const
@ -131,16 +133,11 @@ u256 Transact::total() const
void Transact::updateDestination()
{
cwatch << "updateDestination()";
QString s;
for (auto i: ethereum()->addresses())
if ((s = QString::fromStdString(m_context->pretty(i))).size())
// A namereg address
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !to())
ui->destination->removeItem(i--);
// TODO: should be a Qt model.
ui->destination->clear();
ui->destination->addItem("(Create Contract)");
for (Address const& a: m_main->allKnownAddresses())
ui->destination->addItem(QString::fromStdString(m_main->toName(a) + " (" + ICAP(a).encoded() + ")"), QVariant(QByteArray((char const*)a.data(), a.size)));
}
void Transact::updateFee()
@ -166,11 +163,19 @@ void Transact::on_destination_currentTextChanged(QString)
{
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
{
auto p = m_context->fromString(ui->destination->currentText().toStdString());
pair<Address, bytes> p;
if (!ui->destination->currentData().isNull())
p.first = Address(bytesConstRef((uint8_t const*)ui->destination->currentData().toByteArray().data_ptr(), 20));
else
p = m_main->fromString(ui->destination->currentText().toStdString());
if (p.first)
ui->calculatedName->setText(QString::fromStdString(m_context->render(p.first)));
ui->calculatedName->setText(QString::fromStdString(m_main->render(p.first)));
else
ui->calculatedName->setText("Unknown Address");
// ui->calculatedName->setText(m_main->toName(a) + " (" + ICAP(a).encoded() + ")");
if (!p.second.empty())
{
m_data = p.second;
@ -325,7 +330,7 @@ string Transact::natspecNotice(Address _to, bytes const& _data)
Address Transact::toAccount()
{
return isCreation() ? Address() : m_context->fromString(ui->destination->currentText().toStdString()).first;
return isCreation() ? Address() : m_main->fromString(ui->destination->currentText().toStdString()).first;
}
GasRequirements Transact::determineGasRequirements()
@ -481,7 +486,7 @@ Secret Transact::findSecret(u256 _totalReq) const
if (b > bestBalance)
bestBalance = b, best = i;
}
return m_context->retrieveSecret(best);
return m_main->retrieveSecret(best);
}
Address Transact::fromAccount()
@ -514,7 +519,7 @@ void Transact::on_send_clicked()
return;
}
Secret s = m_context->retrieveSecret(a);
Secret s = m_main->retrieveSecret(a);
if (!s)
return;
@ -541,7 +546,7 @@ void Transact::on_send_clicked()
}
else
// TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice(), nonce);
ethereum()->submitTransaction(s, value(), m_main->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice(), nonce);
close();
}
@ -561,9 +566,9 @@ void Transact::on_debug_clicked()
Block postState(ethereum()->postState());
Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, postState.transactionsFrom(from)) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, postState.transactionsFrom(from));
Transaction(value(), gasPrice(), ui->gas->value(), m_main->fromString(ui->destination->currentText().toStdString()).first, m_data, postState.transactionsFrom(from));
t.forceSender(from);
Debugger dw(m_context, this);
Debugger dw(m_main, this);
Executive e(postState, ethereum()->blockChain(), 0);
dw.populate(e, t);
dw.exec();

6
alethzero/Transact.h

@ -27,7 +27,7 @@
#include <QDialog>
#include <QMap>
#include <QList>
#include "Context.h"
#include "MainFace.h"
namespace Ui { class Transact; }
@ -54,7 +54,7 @@ class Transact: public QDialog
Q_OBJECT
public:
explicit Transact(Context* _context, QWidget* _parent = 0);
explicit Transact(MainFace* _context, QWidget* _parent = 0);
~Transact();
void resetGasPrice();
@ -102,7 +102,7 @@ private:
dev::AddressHash m_accounts;
dev::eth::Client* m_ethereum = nullptr;
Context* m_context = nullptr;
MainFace* m_main = nullptr;
NatSpecFace* m_natSpecDB = nullptr;
bool m_allGood = false;
};

20
libethcore/Common.cpp

@ -27,6 +27,7 @@
#include <libdevcore/CommonIO.h>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include "ICAP.h"
#include "Exceptions.h"
#include "Params.h"
#include "BlockInfo.h"
@ -50,9 +51,26 @@ const unsigned c_databaseBaseVersion = 9;
const unsigned c_databaseVersionModifier = 0;
#endif
const unsigned c_databaseVersion = c_databaseBaseVersion + (c_databaseVersionModifier << 8) + (23 << 9);
Address toAddress(std::string const& _s)
{
try
{
eth::ICAP i = eth::ICAP::decoded(_s);
return i.direct();
}
catch (eth::InvalidICAP&) {}
try
{
auto b = fromHex(_s.substr(0, 2) == "0x" ? _s.substr(2) : _s, WhenError::Throw);
if (b.size() == 20)
return Address(b);
}
catch (BadHexCharacter&) {}
BOOST_THROW_EXCEPTION(InvalidAddress());
}
const unsigned c_databaseVersion = c_databaseBaseVersion + (c_databaseVersionModifier << 8) + (23 << 9);
vector<pair<u256, string>> const& units()
{

5
libethcore/Common.h

@ -57,6 +57,11 @@ Network resetNetwork(Network _n);
/// User-friendly string representation of the amount _b in wei.
std::string formatBalance(bigint const& _b);
DEV_SIMPLE_EXCEPTION(InvalidAddress);
/// Convert the given string into an address.
Address toAddress(std::string const& _s);
/// Get information concerning the currency denominations.
std::vector<std::pair<u256, std::string>> const& units();

19
libethcore/CommonJS.cpp

@ -22,29 +22,10 @@
*/
#include "CommonJS.h"
#include "ICAP.h"
namespace dev
{
Address jsToAddress(std::string const& _s)
{
try
{
eth::ICAP i = eth::ICAP::decoded(_s);
return i.direct();
}
catch (eth::InvalidICAP&) {}
try
{
auto b = fromHex(_s.substr(0, 2) == "0x" ? _s.substr(2) : _s, WhenError::Throw);
if (b.size() == 20)
return Address(b);
}
catch (BadHexCharacter&) {}
BOOST_THROW_EXCEPTION(InvalidAddress());
}
std::string prettyU256(u256 _n, bool _abridged)
{
unsigned inc = 0;

4
libethcore/CommonJS.h

@ -33,8 +33,6 @@
namespace dev
{
DEV_SIMPLE_EXCEPTION(InvalidAddress);
/// Leniently convert string to Public (h512). Accepts integers, "0x" prefixing, non-exact length.
inline Public jsToPublic(std::string const& _s) { return jsToFixed<sizeof(dev::Public)>(_s); }
@ -42,7 +40,7 @@ inline Public jsToPublic(std::string const& _s) { return jsToFixed<sizeof(dev::P
inline Secret jsToSecret(std::string const& _s) { h256 d = jsToFixed<sizeof(dev::Secret)>(_s); Secret ret(d); d.ref().cleanse(); return ret; }
/// Leniently convert string to Address (h160). Accepts integers, "0x" prefixing, non-exact length.
Address jsToAddress(std::string const& _s);
inline Address jsToAddress(std::string const& _s) { return eth::toAddress(_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, bool _abridged = true);

Loading…
Cancel
Save