Browse Source

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

cl-refactor
arkpar 10 years ago
parent
commit
04b929465b
  1. 3
      alethzero/CMakeLists.txt
  2. 28
      alethzero/Main.ui
  3. 5
      alethzero/MainFace.h
  4. 159
      alethzero/MainWin.cpp
  5. 7
      alethzero/MainWin.h
  6. 194
      alethzero/Transact.cpp
  7. 14
      alethzero/Transact.h
  8. 321
      alethzero/Transact.ui
  9. 26
      alethzero/plugins/blockchain/AllAccounts.cpp
  10. 2
      alethzero/plugins/blockchain/AllAccounts.h
  11. 11
      alethzero/plugins/blockchain/AllAccounts.ui
  12. 91
      alethzero/plugins/blockchain/ExportState.cpp
  13. 15
      alethzero/plugins/blockchain/ExportState.h
  14. 0
      alethzero/plugins/blockchain/ExportState.ui
  15. 222
      alethzero/plugins/keys/ImportKey.cpp
  16. 44
      alethzero/plugins/keys/ImportKey.h
  17. 336
      alethzero/plugins/keys/ImportKey.ui
  18. 171
      alethzero/plugins/namers/NewAccount.cpp
  19. 56
      alethzero/plugins/namers/NewAccount.h
  20. 260
      alethzero/plugins/namers/NewAccount.ui
  21. 15
      alethzero/plugins/namers/OtherAccounts.cpp
  22. 87
      alethzero/plugins/special/InjectTransactions.cpp
  23. 48
      alethzero/plugins/special/InjectTransactions.h
  24. 95
      alethzero/plugins/special/InjectTransactions.ui
  25. 2
      cmake/EthDependencies.cmake
  26. 2
      cmake/EthExecutableHelper.cmake
  27. 70
      eth/main.cpp
  28. 323
      ethkey/KeyAux.h
  29. 8
      ethminer/MinerAux.h
  30. 2
      evmjit/libevmjit/Array.h
  31. 6
      evmjit/libevmjit/BasicBlock.cpp
  32. 82
      evmjit/libevmjit/Compiler.cpp
  33. 4
      evmjit/libevmjit/Compiler.h
  34. 2
      evmjit/libevmjit/Stack.cpp
  35. 7
      libdevcore/FixedHash.cpp
  36. 3
      libdevcore/vector_ref.h
  37. 14
      libdevcrypto/SecretStore.cpp
  38. 3
      libdevcrypto/SecretStore.h
  39. 4
      libethcore/Common.cpp
  40. 17
      libethcore/KeyManager.cpp
  41. 6
      libethcore/KeyManager.h
  42. 22
      libethereum/ExtVM.cpp
  43. 5
      libethereum/TransactionQueue.cpp
  44. 1
      libevmasm/CMakeLists.txt
  45. 24
      libjsqrc/ethereumjs/dist/web3-light.js
  46. 4
      libjsqrc/ethereumjs/dist/web3-light.min.js
  47. 24
      libjsqrc/ethereumjs/dist/web3.js
  48. 4
      libjsqrc/ethereumjs/dist/web3.js.map
  49. 4
      libjsqrc/ethereumjs/dist/web3.min.js
  50. 24
      libjsqrc/ethereumjs/lib/web3/shh.js
  51. 24
      mix/qml/Block.qml
  52. 21
      mix/qml/Watchers.qml
  53. BIN
      mix/qml/img/rightarrowcircle.png
  54. 1
      mix/res.qrc
  55. 4
      templates/dockplugin.cpp
  56. 4
      templates/plugin.cpp
  57. 25
      test/libdevcrypto/SecretStore.cpp
  58. 39
      test/libethereum/StateTestsFiller/stSpecialTestFiller.json

3
alethzero/CMakeLists.txt

@ -42,7 +42,6 @@ qt5_wrap_ui(ui_Main.h Main.ui)
qt5_wrap_ui(ui_Connect.h Connect.ui)
qt5_wrap_ui(ui_Debugger.h Debugger.ui)
qt5_wrap_ui(ui_Transact.h Transact.ui)
qt5_wrap_ui(ui_ExportState.h ExportState.ui)
qt5_wrap_ui(ui_GetPassword.h GetPassword.ui)
qt5_wrap_ui(ui_GasPricing.h GasPricing.ui)
@ -60,7 +59,7 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui
UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui GetPassword.ui GasPricing.ui
WIN_RESOURCES alethzero.rc
)

28
alethzero/Main.ui

@ -162,9 +162,9 @@
<addaction name="prepNextDAG"/>
<addaction name="separator"/>
<addaction name="newTransaction"/>
<addaction name="newAccount"/>
<addaction name="importKey"/>
<addaction name="importKeyFile"/>
<addaction name="importPresale"/>
<addaction name="claimPresale"/>
<addaction name="exportKey"/>
<addaction name="reencryptAll"/>
@ -173,7 +173,6 @@
<addaction name="separator"/>
<addaction name="loadJS"/>
<addaction name="separator"/>
<addaction name="exportState"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
@ -189,7 +188,6 @@
<addaction name="paranoia"/>
<addaction name="clearPending"/>
<addaction name="killBlockchain"/>
<addaction name="inject"/>
<addaction name="injectBlock"/>
<addaction name="forceMining"/>
<addaction name="separator"/>
@ -214,6 +212,7 @@
<property name="title">
<string>&amp;Debug</string>
</property>
<addaction name="debugPending"/>
<addaction name="debugCurrent"/>
<addaction name="debugDumpState"/>
<addaction name="debugDumpStatePre"/>
@ -1098,11 +1097,6 @@ font-size: 14pt</string>
<string>&amp;Load Javascript...</string>
</property>
</action>
<action name="exportState">
<property name="text">
<string>&amp;Export State...</string>
</property>
</action>
<action name="debugStepBack">
<property name="enabled">
<bool>false</bool>
@ -1388,6 +1382,24 @@ font-size: 14pt</string>
<string>Dump &amp;Block State as JSON...</string>
</property>
</action>
<action name="bulkTransactions">
<property name="text">
<string>&amp;Bulk Inject Transactions...</string>
</property>
</action>
<action name="debugPending">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Debug &amp;Pending Transaction</string>
</property>
</action>
<action name="importPresale">
<property name="text">
<string>Import Ether &amp;Presale Wallet...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

5
alethzero/MainFace.h

@ -43,8 +43,13 @@ namespace shh { class WhisperHost; }
namespace az
{
#ifndef _MSC_VER // MSVC does not like gcc compiler attributes
#define DEV_AZ_NOTE_PLUGIN(ClassName) \
static bool s_notePlugin __attribute__((unused)) = [](){ MainFace::notePlugin([](MainFace* m){ return new ClassName(m); }); return true; }()
#else
#define DEV_AZ_NOTE_PLUGIN(ClassName) \
static bool s_notePlugin = [](){ MainFace::notePlugin([](MainFace* m){ return new ClassName(m); }); return true; }()
#endif
class Plugin;
class MainFace;

159
alethzero/MainWin.cpp

@ -73,7 +73,6 @@
#include "DappLoader.h"
#include "DappHost.h"
#include "WebPage.h"
#include "ExportState.h"
#include "ui_Main.h"
#include "ui_GetPassword.h"
#include "ui_GasPricing.h"
@ -241,7 +240,7 @@ Main::Main(QWidget* _parent):
ui->vmSmart->setEnabled(false);
#endif
readSettings();
readSettings(true, false);
m_transact = new Transact(this, this);
m_transact->setWindowFlags(Qt::Dialog);
@ -263,6 +262,8 @@ Main::Main(QWidget* _parent):
for (auto const& i: *s_linkedPlugins)
initPlugin(i(this));
readSettings(false, true);
}
Main::~Main()
@ -668,9 +669,10 @@ std::string Main::render(dev::Address const& _a) const
if (p.size() == 9 && p.find_first_not_of("QWERYUOPASDFGHJKLZXCVBNM1234567890") == string::npos)
p = ICAP(p, "XREG").encoded();
else
DEV_IGNORE_EXCEPTIONS(n = ICAP(_a).encoded());
if (n.empty())
n = _a.abridged();
DEV_IGNORE_EXCEPTIONS(n = ICAP(_a).encoded().substr(0, 8));
if (!n.empty())
n += " ";
n += _a.abridged();
return p.empty() ? n : (p + " " + n);
}
@ -850,13 +852,15 @@ Secret Main::retrieveSecret(Address const& _address) const
}
}
void Main::readSettings(bool _skipGeometry)
void Main::readSettings(bool _skipGeometry, bool _onlyGeometry)
{
QSettings s("ethereum", "alethzero");
if (!_skipGeometry)
restoreGeometry(s.value("geometry").toByteArray());
restoreState(s.value("windowState").toByteArray());
if (_onlyGeometry)
return;
forEach([&](std::shared_ptr<Plugin> p)
{
@ -1018,6 +1022,28 @@ void Main::on_claimPresale_triggered()
}
}
void Main::on_importPresale_triggered()
{
QString s = QFileDialog::getOpenFileName(this, "Claim Account Contents", QDir::homePath(), "JSON Files (*.json);;All Files (*)");
try
{
string pass;
KeyPair k = m_keyManager.presaleSecret(dev::contentsString(s.toStdString()), [&](bool){ return (pass = QInputDialog::getText(this, "Enter Password", "Enter the wallet's passphrase", QLineEdit::Password).toStdString()); });
cnote << k.address();
if (!m_keyManager.hasAccount(k.address()))
keyManager().import(k.secret(), "Presale wallet (" + s.toStdString() + ")", pass, "Same password as for the presale wallet");
else
QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account.");
}
catch (dev::eth::PasswordUnknown&) {}
catch (...)
{
cerr << "Unhandled exception!" << endl <<
boost::current_exception_diagnostic_information();
QMessageBox::warning(this, "Key File Invalid", "Could not find secret key definition. This is probably not an Ethereum key file.");
}
}
void Main::on_exportKey_triggered()
{
if (ui->ourAccounts->currentRow() >= 0)
@ -1029,12 +1055,6 @@ void Main::on_exportKey_triggered()
}
}
void Main::on_exportState_triggered()
{
ExportStateDialog dialog(this);
dialog.exec();
}
void Main::on_usePrivate_triggered()
{
QString pc;
@ -1549,6 +1569,7 @@ void Main::on_transactionQueue_currentItemChanged()
int i = ui->transactionQueue->currentRow();
if (i >= 0 && i < (int)ethereum()->pending().size())
{
ui->debugPending->setEnabled(true);
Transaction tx(ethereum()->pending()[i]);
TransactionReceipt receipt(ethereum()->postState().receipt(i));
auto ss = tx.safeSender();
@ -1588,30 +1609,13 @@ void Main::on_transactionQueue_currentItemChanged()
// s << "Pre: " << fs.rootHash() << "<br/>";
// s << "Post: <b>" << ts.rootHash() << "</b>";
}
else
ui->debugPending->setEnabled(false);
ui->pendingInfo->setHtml(QString::fromStdString(s.str()));
ui->pendingInfo->moveCursor(QTextCursor::Start);
}
void Main::on_inject_triggered()
{
QString s = QInputDialog::getText(this, "Inject Transaction", "Enter transaction dump in hex");
try
{
bytes b = fromHex(s.toStdString(), WhenError::Throw);
ethereum()->injectTransaction(b);
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, transaction rejected";
cwarn << boost::diagnostic_information(_e);
}
catch (...)
{
cwarn << "transaction rejected";
}
}
void Main::on_injectBlock_triggered()
{
QString s = QInputDialog::getText(this, "Inject Block", "Enter block dump in hex");
@ -1804,6 +1808,22 @@ void Main::on_debugCurrent_triggered()
}
}
void Main::on_debugPending_triggered()
{
int txi = ui->transactionQueue->currentRow();
if (txi == -1)
return;
Block b = ethereum()->postState();
bytes t = b.pending()[txi].rlp();
State s(ethereum()->state(txi));
BlockInfo bi(b.info());
Executive e(s, ethereum()->blockChain(), EnvInfo(bi));
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckTransaction::Everything));
dw.exec();
}
std::string minHex(h256 const& _h)
{
unsigned i = 0;
@ -1988,83 +2008,6 @@ void Main::keysChanged()
onBalancesChange();
}
bool beginsWith(Address _a, bytes const& _b)
{
for (unsigned i = 0; i < min<unsigned>(20, _b.size()); ++i)
if (_a[i] != _b[i])
return false;
return true;
}
void Main::on_newAccount_triggered()
{
bool ok = true;
enum { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch };
QStringList items = {"No vanity (instant)", "Direct ICAP address", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"};
unsigned v = items.QList<QString>::indexOf(QInputDialog::getItem(this, "Vanity Key?", "Would you a vanity key? This could take several hours.", items, 1, false, &ok));
if (!ok)
return;
bytes bs;
if (v == StringMatch)
{
QString s = QInputDialog::getText(this, "Vanity Beginning?", "Enter some hex digits that it should begin with.\nNOTE: The more you enter, the longer generation will take.", QLineEdit::Normal, QString(), &ok);
if (!ok)
return;
bs = fromHex(s.toStdString());
}
KeyPair p;
bool keepGoing = true;
unsigned done = 0;
function<void()> f = [&]() {
KeyPair lp;
while (keepGoing)
{
done++;
if (done % 1000 == 0)
cnote << "Tried" << done << "keys";
lp = KeyPair::create();
auto a = lp.address();
if (v == NoVanity ||
(v == DirectICAP && !a[0]) ||
(v == FirstTwo && a[0] == a[1]) ||
(v == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) ||
(v == FirstThree && a[0] == a[1] && a[1] == a[2]) ||
(v == FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) ||
(v == StringMatch && beginsWith(lp.address(), bs))
)
break;
}
if (keepGoing)
p = lp;
keepGoing = false;
};
vector<std::thread*> ts;
for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t)
ts.push_back(new std::thread(f));
f();
for (std::thread* t: ts)
{
t->join();
delete t;
}
QString s = QInputDialog::getText(this, "Create Account", "Enter this account's name");
if (QMessageBox::question(this, "Create Account", "Would you like to use additional security for this key? This lets you protect it with a different password to other keys, but also means you must re-enter the key's password every time you wish to use the account.", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
{
bool ok = false;
std::string hint;
std::string password = getPassword("Create Account", "Enter the password you would like to use for this key. Don't forget it!", &hint, &ok);
if (!ok)
return;
m_keyManager.import(p.secret(), s.toStdString(), password, hint);
}
else
m_keyManager.import(p.secret(), s.toStdString());
keysChanged();
}
void Main::on_killAccount_triggered()
{
if (ui->ourAccounts->currentRow() >= 0)

7
alethzero/MainWin.h

@ -151,19 +151,18 @@ private slots:
void on_preview_triggered();
// Account management
void on_newAccount_triggered();
void on_killAccount_triggered();
void on_importKey_triggered();
void on_reencryptKey_triggered();
void on_reencryptAll_triggered();
void on_importKeyFile_triggered();
void on_claimPresale_triggered();
void on_importPresale_triggered();
void on_exportKey_triggered();
// Tools
void on_newTransaction_triggered();
void on_loadJS_triggered();
void on_exportState_triggered();
// Stuff concerning the blocks/transactions/accounts panels
void on_ourAccounts_itemClicked(QListWidgetItem* _i);
@ -181,7 +180,6 @@ private slots:
void on_paranoia_triggered();
void on_killBlockchain_triggered();
void on_clearPending_triggered();
void on_inject_triggered();
void on_injectBlock_triggered();
void on_forceMining_triggered();
void on_usePrivate_triggered();
@ -194,6 +192,7 @@ private slots:
// Debugger
void on_debugCurrent_triggered();
void on_debugPending_triggered();
void on_debugDumpState_triggered() { debugDumpState(1); }
void on_debugDumpStatePre_triggered() { debugDumpState(0); }
void on_dumpBlockState_triggered();
@ -226,7 +225,7 @@ private:
Address getCurrencies() const;
void updateFee();
void readSettings(bool _skipGeometry = false);
void readSettings(bool _skipGeometry = false, bool _onlyGeometry = false);
void writeSettings();
void setPrivateChain(QString const& _private, bool _forceConfigure = false);

194
alethzero/Transact.cpp

@ -104,7 +104,12 @@ bool Transact::isCreation() const
u256 Transact::fee() const
{
return ui->gas->value() * gasPrice();
return gas() * gasPrice();
}
u256 Transact::gas() const
{
return ui->gas->value() == -1 ? m_upperBound : ui->gas->value();
}
u256 Transact::value() const
@ -131,11 +136,12 @@ void Transact::updateDestination()
// TODO: should be a Qt model.
ui->destination->clear();
ui->destination->addItem("(Create Contract)");
QMultiMap<QString, QString> in;
for (Address const& a: m_main->allKnownAddresses())
{
cdebug << "Adding" << a << m_main->toName(a) << " -> " << (m_main->toName(a) + " (" + ICAP(a).encoded() + ")");
ui->destination->addItem(QString::fromStdString(m_main->toName(a) + " (" + ICAP(a).encoded() + ")"), QString::fromStdString(a.hex()));
}
in.insert(QString::fromStdString(m_main->toName(a) + " (" + ICAP(a).encoded() + ")"), QString::fromStdString(a.hex()));
for (auto i = in.begin(); i != in.end(); ++i)
ui->destination->addItem(i.key(), i.value());
}
void Transact::updateFee()
@ -197,10 +203,10 @@ void Transact::on_copyUnsigned_clicked()
if (isCreation())
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
t = Transaction(value(), gasPrice(), ui->gas->value(), m_data, nonce);
t = Transaction(value(), gasPrice(), gas(), m_data, nonce);
else
// TODO: cache like m_data.
t = Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, nonce);
t = Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, nonce);
qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp())));
}
@ -334,6 +340,90 @@ pair<Address, bytes> Transact::toAccount()
return p;
}
void Transact::timerEvent(QTimerEvent*)
{
Address from = fromAccount();
Address to = toAccount().first;
if (m_upperBound != m_lowerBound)
{
qint64 mid = (m_lowerBound + m_upperBound) / 2;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
else
er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed)
m_lowerBound = m_lowerBound == mid ? m_upperBound : mid;
else
{
m_lastGood = er;
m_upperBound = m_upperBound == mid ? m_lowerBound : mid;
}
updateBounds();
}
finaliseBounds();
}
void Transact::updateBounds()
{
ui->minGas->setValue(m_lowerBound);
ui->maxGas->setValue(m_upperBound);
double oran = m_startUpperBound - m_startLowerBound;
double nran = m_upperBound - m_lowerBound;
int x = int(log2(oran / nran) * 100.0 / log2(oran * 2));
ui->progressGas->setValue(x);
ui->progressGas->setVisible(true);
ui->gas->setSpecialValueText(QString("Auto (%1 gas)").arg(m_upperBound));
}
void Transact::finaliseBounds()
{
killTimer(m_gasCalcTimer);
quint64 baseGas = (quint64)Transaction::gasRequired(m_data, 0);
ui->progressGas->setVisible(false);
quint64 executionGas = m_upperBound - baseGas;
QString htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(m_upperBound).arg(baseGas).arg(executionGas).arg((qint64)m_lastGood.gasRefunded);
auto bail = [&](QString he) {
ui->send->setEnabled(false);
ui->code->setHtml(he + htmlInfo + m_dataInfo);
};
auto s = fromAccount();
auto b = ethereum()->balanceAt(s, PendingBlock);
if (b < value() + baseGas * gasPrice())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Account doesn't contain enough for paying even the basic amount of gas required.</div>");
return;
}
if (m_upperBound > m_ethereum->gasLimitRemaining())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Gas remaining in block isn't enough to allow the gas required.</div>");
return;
}
if (m_lastGood.excepted != TransactionException::None)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(m_lastGood.excepted)) + "</div>");
return;
}
if (m_lastGood.codeDeposit == CodeDeposit::Failed)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(m_lastGood.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(m_lastGood.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
return;
}
updateFee();
ui->code->setHtml(htmlInfo + m_dataInfo);
ui->send->setEnabled(true);
}
GasRequirements Transact::determineGasRequirements()
{
// Determine the minimum amount of gas we need to play...
@ -343,12 +433,11 @@ GasRequirements Transact::determineGasRequirements()
Address to = toAccount().first;
ExecutionResult lastGood;
bool haveUpperBound = false;
qint64 lowerBound = baseGas;
qint64 upperBound = (qint64)ethereum()->gasLimitRemaining();
for (unsigned i = 0; i < 30 && ((haveUpperBound && upperBound - lowerBound > 16) || !haveUpperBound); ++i) // get to with 100.
m_startLowerBound = baseGas;
m_startUpperBound = (qint64)ethereum()->gasLimitRemaining();
for (unsigned i = 0; i < 30; ++i)
{
qint64 mid = haveUpperBound ? (lowerBound + upperBound) / 2 : upperBound;
qint64 mid = m_startUpperBound;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
@ -356,23 +445,21 @@ GasRequirements Transact::determineGasRequirements()
er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed)
{
lowerBound = mid;
if (!haveUpperBound)
upperBound *= 2;
m_startLowerBound = mid;
m_startUpperBound *= 2;
}
else
{
lastGood = er;
if (haveUpperBound)
upperBound = mid;
else
haveUpperBound = true;
// Begin async binary chop for gas calculation..
m_lastGood = lastGood;
m_lowerBound = m_startLowerBound;
m_upperBound = m_startUpperBound;
killTimer(m_gasCalcTimer);
m_gasCalcTimer = startTimer(0);
return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
}
}
// Dry-run execution to determine gas requirement and any execution errors
// (qint64)(er.gasUsed + er.gasRefunded + c_callStipend);
return GasRequirements{upperBound, baseGas, upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
return GasRequirements();
}
void Transact::rejigData()
@ -386,15 +473,12 @@ void Transact::rejigData()
if (!s)
return;
auto b = ethereum()->balanceAt(s, PendingBlock);
m_allGood = true;
QString htmlInfo;
auto bail = [&](QString he) {
m_allGood = false;
// ui->send->setEnabled(false);
ui->code->setHtml(he + htmlInfo);
ui->send->setEnabled(false);
m_dataInfo = he + htmlInfo;
ui->code->setHtml(m_dataInfo);
};
// Determine m_info.
@ -422,49 +506,15 @@ void Transact::rejigData()
htmlInfo += "<h4>Hex</h4>" + QString(ETH_HTML_DIV(ETH_HTML_MONO)) + QString::fromStdString(toHex(m_data)) + "</div>";
auto gasReq = determineGasRequirements();
htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas) + htmlInfo;
if (b < value() + gasReq.baseGas * gasPrice())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Account doesn't contain enough for paying even the basic amount of gas required.</div>");
return;
}
if (gasReq.neededGas > m_ethereum->gasLimitRemaining())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Gas remaining in block isn't enough to allow the gas required.</div>");
return;
}
if (gasReq.er.excepted != TransactionException::None)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(gasReq.er.excepted)) + "</div>");
return;
}
if (gasReq.er.codeDeposit == CodeDeposit::Failed)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
return;
}
// Add Natspec information
if (!isCreation())
htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "</div>" + htmlInfo;
// Update gas
if (ui->gas->value() == ui->gas->minimum())
{
ui->gas->setMinimum(gasReq.neededGas);
ui->gas->setValue(gasReq.neededGas);
}
else
ui->gas->setMinimum(gasReq.neededGas);
updateFee();
determineGasRequirements();
ui->code->setHtml(htmlInfo);
// ui->send->setEnabled(m_allGood);
m_dataInfo = htmlInfo;
ui->code->setHtml(m_dataInfo);
ui->send->setEnabled(true);
}
Secret Transact::findSecret(u256 _totalReq) const
@ -526,7 +576,7 @@ void Transact::on_send_clicked()
{
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice(), nonce);
ethereum()->submitTransaction(s, value(), m_data, gas(), gasPrice(), nonce);
#if ETH_SOLIDITY
string src = ui->data->toPlainText().toStdString();
if (sourceIsSolidity(src))
@ -545,7 +595,7 @@ void Transact::on_send_clicked()
}
else
// TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), toAccount().first, m_data, ui->gas->value(), gasPrice(), nonce);
ethereum()->submitTransaction(s, value(), toAccount().first, m_data, gas(), gasPrice(), nonce);
close();
}
@ -564,8 +614,8 @@ 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(), toAccount().first, m_data, postState.transactionsFrom(from));
Transaction(value(), gasPrice(), gas(), m_data, postState.transactionsFrom(from)) :
Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, postState.transactionsFrom(from));
t.forceSender(from);
Debugger dw(m_main, this);
Executive e(postState, ethereum()->blockChain(), 0);

14
alethzero/Transact.h

@ -79,6 +79,8 @@ private:
dev::eth::Client* ethereum() const { return m_ethereum; }
void rejigData();
void updateNonce();
void updateBounds();
void finaliseBounds();
dev::Address fromAccount();
std::pair<dev::Address, bytes> toAccount();
@ -86,6 +88,7 @@ private:
void updateFee();
bool isCreation() const;
dev::u256 fee() const;
dev::u256 gas() const;
dev::u256 total() const;
dev::u256 value() const;
dev::u256 gasPrice() const;
@ -95,6 +98,8 @@ private:
std::string natspecNotice(dev::Address _to, dev::bytes const& _data);
dev::Secret findSecret(dev::u256 _totalReq) const;
void timerEvent(QTimerEvent*) override;
Ui::Transact* ui = nullptr;
unsigned m_backupGas = 0;
@ -104,9 +109,14 @@ private:
dev::eth::Client* m_ethereum = nullptr;
MainFace* m_main = nullptr;
NatSpecFace* m_natSpecDB = nullptr;
bool m_allGood = false;
bool m_determiningGas = false;
QString m_dataInfo;
qint64 m_startLowerBound = 0;
qint64 m_startUpperBound = 0;
qint64 m_lowerBound = 0;
qint64 m_upperBound = 0;
eth::ExecutionResult m_lastGood;
int m_gasCalcTimer = 0;
};
}

321
alethzero/Transact.ui

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>543</width>
<width>604</width>
<height>695</height>
</rect>
</property>
@ -14,82 +14,62 @@
<string>Transact</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="10" column="2">
<widget class="QPushButton" name="debug">
<property name="text">
<string>&amp;Debug</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="gas">
<property name="specialValueText">
<string>Automatic</string>
</property>
<property name="suffix">
<string> gas</string>
</property>
<property name="minimum">
<number>1</number>
<number>-1</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QPushButton" name="cancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QPushButton" name="debug">
<property name="text">
<string>&amp;Debug</string>
<number>-1</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
<item row="3" column="3">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="7" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label5_2">
<item row="7" column="1">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Amount</string>
<string>&amp;Optimise</string>
</property>
<property name="buddy">
<cstring>value</cstring>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="3">
<item row="10" column="3">
<widget class="QPushButton" name="send">
<property name="text">
<string>&amp;Execute</string>
@ -99,52 +79,41 @@
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QComboBox" name="destination">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>(Create Contract)</string>
<item row="7" column="3">
<widget class="QSpinBox" name="nonce">
<property name="enabled">
<bool>false</bool>
</property>
</item>
</widget>
</item>
<item row="4" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
<item row="8" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="minimum">
<number>0</number>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="maximum">
<number>430000000</number>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="text">
<string>D&amp;ata</string>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<property name="lineWidth">
<number>0</number>
</property>
<property name="buddy">
<cstring>data</cstring>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="valueUnits"/>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="value">
@ -159,55 +128,116 @@
</property>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
<item row="10" column="1">
<widget class="QPushButton" name="copyUnsigned">
<property name="text">
<string>Copy &amp;Unsigned</string>
</property>
<property name="readOnly">
<bool>true</bool>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Gas</string>
</property>
<property name="placeholderText">
<string/>
<property name="buddy">
<cstring>gas</cstring>
</property>
</widget>
</item>
<item row="6" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="1" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<property name="text">
<string>&amp;To</string>
</property>
<property name="lineWidth">
<number>0</number>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</item>
<item row="10" column="0">
<widget class="QPushButton" name="cancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<property name="shortcut">
<string>Esc</string>
</property>
<property name="lineWidth">
<number>0</number>
</widget>
</item>
<item row="7" column="2">
<widget class="QCheckBox" name="autoNonce">
<property name="text">
<string>Auto Nonce</string>
</property>
<property name="readOnly">
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QComboBox" name="destination">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>(Create Contract)</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<item row="9" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Gas</string>
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>&amp;Amount</string>
</property>
<property name="buddy">
<cstring>gas</cstring>
<cstring>value</cstring>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>D&amp;ata</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
@ -221,43 +251,64 @@
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Optimise</string>
<item row="4" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
</property>
<property name="checked">
<bool>true</bool>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QSpinBox" name="nonce">
<property name="enabled">
<bool>false</bool>
<widget class="QSpinBox" name="maxGas">
<property name="suffix">
<string> gas</string>
</property>
<property name="prefix">
<string>max </string>
</property>
<property name="maximum">
<number>450000000</number>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="autoNonce">
<property name="text">
<string>Auto Nonce</string>
</property>
<property name="checked">
<widget class="QSpinBox" name="minGas">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
<property name="suffix">
<string> gas</string>
</property>
<property name="prefix">
<string>min </string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>450000000</number>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="copyUnsigned">
<property name="text">
<string>Copy &amp;Unsigned</string>
<item row="5" column="1">
<widget class="QProgressBar" name="progressGas">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>24</number>
</property>
<property name="format">
<string>Calculating gas...</string>
</property>
</widget>
</item>

26
alethzero/plugins/blockchain/AllAccounts.cpp

@ -14,12 +14,12 @@
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
/** @file AllAccounts.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#if ETH_FATDB
#if ETH_FATDB || !ETH_TRUE
#include "AllAccounts.h"
#include <sstream>
@ -51,7 +51,7 @@ AllAccounts::AllAccounts(MainFace* _m):
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()));
connect(m_ui->onlyKnown, SIGNAL(toggled(bool)), SLOT(onAllChange()));
}
AllAccounts::~AllAccounts()
@ -72,20 +72,24 @@ void AllAccounts::refresh()
m_ui->accounts->clear();
bool showContract = m_ui->showContracts->isChecked();
bool showBasic = m_ui->showBasic->isChecked();
bool onlyNamed = m_ui->onlyNamed->isChecked();
auto as = ethereum()->addresses();
sort(as.begin(), as.end());
bool onlyKnown = m_ui->onlyKnown->isChecked();
Addresses as;
if (onlyKnown)
as = main()->allKnownAddresses();
else
as = ethereum()->addresses();
for (auto const& i: as)
{
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));
}
m_ui->accounts->sortItems();
#endif
m_ui->refreshAccounts->setEnabled(false);
}
@ -108,8 +112,10 @@ void AllAccounts::on_accounts_currentItemChanged()
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/>";
u256s keys = keysOf(storage);
sort(keys.begin(), keys.end());
for (auto const& i: keys)
s << "@" << showbase << hex << main()->prettyU256(i) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << main()->prettyU256(storage[i]) << "<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>";
s << "<h4>Creation Addresses (" << ethereum()->countAt(address) << "+)</h4>";

2
alethzero/plugins/blockchain/AllAccounts.h

@ -21,7 +21,7 @@
#pragma once
#if ETH_FATDB
#if ETH_FATDB || !ETH_TRUE
#include <QListWidget>
#include <QPlainTextEdit>

11
alethzero/plugins/blockchain/AllAccounts.ui

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<width>405</width>
<height>300</height>
</rect>
</property>
@ -46,6 +46,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
@ -62,15 +65,15 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<widget class="QToolButton" name="onlyKnown">
<property name="text">
<string>Only Named</string>
<string>Only Known</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
<bool>true</bool>
</property>
</widget>
</item>

91
alethzero/ExportState.cpp → alethzero/plugins/blockchain/ExportState.cpp

@ -19,77 +19,86 @@
* @date 2015
*/
#if ETH_FATDB
#include "ExportState.h"
#include <fstream>
#include <QFileDialog>
#include <QTextStream>
#include <libethereum/Client.h>
#include "MainWin.h"
#include "ui_ExportState.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
ExportStateDialog::ExportStateDialog(Main* _parent):
QDialog(_parent),
ui(new Ui::ExportState),
m_main(_parent)
DEV_AZ_NOTE_PLUGIN(ExportStateDialog);
ExportStateDialog::ExportStateDialog(MainFace* _m):
QDialog(_m),
Plugin(_m, "Export State"),
m_ui(new Ui::ExportState)
{
ui->setupUi(this);
connect(ui->close, &QPushButton::clicked, this, &ExportStateDialog::close);
connect(ui->accounts, &QListWidget::itemSelectionChanged, this, &ExportStateDialog::generateJSON);
connect(ui->contracts, &QListWidget::itemSelectionChanged, this, &ExportStateDialog::generateJSON);
m_ui->setupUi(this);
connect(m_ui->close, &QPushButton::clicked, this, &ExportStateDialog::close);
connect(m_ui->accounts, &QListWidget::itemSelectionChanged, this, &ExportStateDialog::generateJSON);
connect(m_ui->contracts, &QListWidget::itemSelectionChanged, this, &ExportStateDialog::generateJSON);
fillBlocks();
connect(addMenuItem("Export State...", "menuTools", true), SIGNAL(triggered()), SLOT(exec()));
}
ExportStateDialog::~ExportStateDialog()
{
}
Client* ExportStateDialog::ethereum() const
}
void ExportStateDialog::showEvent(QShowEvent*)
{
return m_main->ethereum();
m_ui->block->clear();
m_ui->block->clearEditText();
m_ui->accounts->clear();
m_ui->contracts->clear();
fillBlocks();
}
void ExportStateDialog::on_block_editTextChanged()
{
QString text = ui->block->currentText();
int i = ui->block->count();
QString text = m_ui->block->currentText();
int i = m_ui->block->count();
while (i-- >= 0)
if (ui->block->itemText(i) == text)
if (m_ui->block->itemText(i) == text)
return;
fillBlocks();
}
void ExportStateDialog::on_block_currentIndexChanged(int _index)
{
m_block = ui->block->itemData(_index).toUInt();
m_block = m_ui->block->itemData(_index).toUInt();
fillContracts();
}
void ExportStateDialog::fillBlocks()
{
BlockChain const& bc = ethereum()->blockChain();
QStringList filters = ui->block->currentText().toLower().split(QRegExp("\\s+"), QString::SkipEmptyParts);
QStringList filters = m_ui->block->currentText().toLower().split(QRegExp("\\s+"), QString::SkipEmptyParts);
const unsigned numLastBlocks = 10;
if (ui->block->count() == 0)
if (m_ui->block->count() == 0)
{
unsigned i = numLastBlocks;
for (auto h = bc.currentHash(); bc.details(h) && i; h = bc.details(h).parent, --i)
{
auto d = bc.details(h);
ui->block->addItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), d.number);
m_ui->block->addItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), d.number);
if (h == bc.genesisHash())
break;
}
if (ui->block->currentIndex() < 0)
ui->block->setCurrentIndex(0);
if (m_ui->block->currentIndex() < 0)
m_ui->block->setCurrentIndex(0);
m_recentBlocks = numLastBlocks - i;
}
int i = ui->block->count();
int i = m_ui->block->count();
while (i > 0 && i >= m_recentBlocks)
ui->block->removeItem(i--);
m_ui->block->removeItem(i--);
h256Hash blocks;
for (QString f: filters)
@ -117,31 +126,31 @@ void ExportStateDialog::fillBlocks()
for (auto const& h: blocks)
{
auto d = bc.details(h);
ui->block->addItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), d.number);
m_ui->block->addItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), d.number);
}
}
void ExportStateDialog::fillContracts()
{
ui->accounts->clear();
ui->contracts->clear();
ui->accounts->setEnabled(true);
ui->contracts->setEnabled(true);
m_ui->accounts->clear();
m_ui->contracts->clear();
m_ui->accounts->setEnabled(true);
m_ui->contracts->setEnabled(true);
try
{
for (auto i: ethereum()->addresses(m_block))
{
string r = m_main->render(i);
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts))
string r = main()->render(i);
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? m_ui->accounts : m_ui->contracts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
}
catch (InterfaceNotSupported const&)
{
ui->accounts->setEnabled(false);
ui->contracts->setEnabled(false);
ui->json->setEnabled(false);
ui->json->setText(QString("This feature requires compilation with FATDB support."));
m_ui->accounts->setEnabled(false);
m_ui->contracts->setEnabled(false);
m_ui->json->setEnabled(false);
m_ui->json->setText(QString("This feature requires compilation with FATDB support."));
}
}
@ -150,14 +159,14 @@ void ExportStateDialog::generateJSON()
std::stringstream json;
json << "{\n";
std::string prefix;
for(QListWidgetItem* item: ui->accounts->selectedItems())
for(QListWidgetItem* item: m_ui->accounts->selectedItems())
{
auto hba = item->data(Qt::UserRole).toByteArray();
auto address = Address((byte const*)hba.data(), Address::ConstructFromPointer);
json << prefix << "\t\"" << toHex(address.ref()) << "\": { \"wei\": \"" << ethereum()->balanceAt(address, m_block) << "\" }";
prefix = ",\n";
}
for(QListWidgetItem* item: ui->contracts->selectedItems())
for(QListWidgetItem* item: m_ui->contracts->selectedItems())
{
auto hba = item->data(Qt::UserRole).toByteArray();
auto address = Address((byte const*)hba.data(), Address::ConstructFromPointer);
@ -181,9 +190,9 @@ void ExportStateDialog::generateJSON()
json << "\n}";
json.flush();
ui->json->setEnabled(true);
ui->json->setText(QString::fromStdString(json.str()));
ui->saveButton->setEnabled(true);
m_ui->json->setEnabled(true);
m_ui->json->setText(QString::fromStdString(json.str()));
m_ui->saveButton->setEnabled(true);
}
void ExportStateDialog::on_saveButton_clicked()
@ -193,5 +202,7 @@ void ExportStateDialog::on_saveButton_clicked()
fn = fn.append(".json");
ofstream file(fn.toStdString());
if (file.is_open())
file << ui->json->toPlainText().toStdString();
file << m_ui->json->toPlainText().toStdString();
}
#endif //ETH_FATDB

15
alethzero/ExportState.h → alethzero/plugins/blockchain/ExportState.h

@ -21,9 +21,12 @@
#pragma once
#if ETH_FATDB
#include <memory>
#include <QDialog>
#include <libethcore/Common.h>
#include "MainFace.h"
namespace Ui { class ExportState; }
@ -35,14 +38,13 @@ namespace eth { class Client; }
namespace az
{
class Main;
class ExportStateDialog: public QDialog
class ExportStateDialog: public QDialog, public Plugin
{
Q_OBJECT
public:
explicit ExportStateDialog(Main* _parent = 0);
ExportStateDialog(MainFace* _m);
virtual ~ExportStateDialog();
private slots:
@ -51,17 +53,18 @@ private slots:
void on_saveButton_clicked();
private:
eth::Client* ethereum() const;
void showEvent(QShowEvent* _event) override;
void fillBlocks();
void fillContracts();
void generateJSON();
private:
std::unique_ptr<Ui::ExportState> ui;
Main* m_main;
std::unique_ptr<Ui::ExportState> m_ui;
int m_recentBlocks = 0;
eth::BlockNumber m_block = eth::LatestBlock;
};
}
}
#endif //ETH_FATDB

0
alethzero/ExportState.ui → alethzero/plugins/blockchain/ExportState.ui

222
alethzero/plugins/keys/ImportKey.cpp

@ -0,0 +1,222 @@
/*
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 ImportKey.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "ImportKey.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <libdevcore/Log.h>
#include <libethcore/KeyManager.h>
#include <libethcore/ICAP.h>
#include <libethereum/Client.h>
#include "ui_ImportKey.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(ImportKey);
ImportKey::ImportKey(MainFace* _m):
Plugin(_m, "ImportKey")
{
connect(addMenuItem("Import Key...", "menuTools", true), SIGNAL(triggered()), SLOT(import()));
}
ImportKey::~ImportKey()
{
}
void ImportKey::import()
{
QDialog d;
Ui_ImportKey u;
u.setupUi(&d);
d.setWindowTitle("Import Key");
string lastKey;
Secret lastSecret;
string lastPassword;
Address lastAddress;
auto updateAction = [&](){
if (!u.import_2->isEnabled())
u.action->clear();
else if (lastKey.empty() && !lastSecret)
u.action->setText("Import brainwallet with given address and hint");
else if (!lastKey.empty() && !lastSecret)
{
h256 ph;
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString()));
if (ph)
u.action->setText("Import untouched key with given address and hint");
else
u.action->setText("Import untouched key with given address, password hash and hint");
}
else
{
bool mp = u.noPassword->isChecked();
if (mp)
u.action->setText("Import recast key using master password and given hint");
else
u.action->setText("Import recast key with given password and hint");
}
};
auto updateImport = [&](){
u.import_2->setDisabled(u.addressOut->text().isEmpty() || u.name->text().isEmpty() || !(u.oldPassword->isChecked() || u.newPassword->isChecked() || u.noPassword->isChecked()));
updateAction();
};
auto updateAddress = [&](){
lastAddress.clear();
string as = u.address->text().toStdString();
try
{
lastAddress = eth::toAddress(as);
u.addressOut->setText(QString::fromStdString(main()->render(lastAddress)));
}
catch (...)
{
u.addressOut->setText("");
}
updateImport();
};
auto updatePassword = [&](){
u.passwordHash->setText(QString::fromStdString(sha3(u.password->text().toStdString()).hex()));
updateAction();
};
function<void()> updateKey = [&](){
// update according to key.
if (lastKey == u.key->text().toStdString())
return;
lastKey = u.key->text().toStdString();
lastSecret.clear();
u.address->clear();
u.oldPassword->setEnabled(false);
u.oldPassword->setChecked(false);
bytes b;
DEV_IGNORE_EXCEPTIONS(b = fromHex(lastKey, WhenError::Throw));
if (b.size() == 32)
{
lastSecret = Secret(b);
bytesRef(&b).cleanse();
}
while (!lastKey.empty() && !lastSecret)
{
bool ok;
lastPassword = QInputDialog::getText(&d, "Open Key File", "Enter the password protecting this key file. Cancel if you do not want to provide te password.", QLineEdit::Password, QString(), &ok).toStdString();
if (!ok)
{
lastSecret.clear();
break;
}
// Try to open as a file.
lastSecret = KeyManager::presaleSecret(contentsString(lastKey), [&](bool first){ return first ? lastPassword : string(); }).secret();
if (!lastSecret)
lastSecret = Secret(SecretStore::secret(contentsString(lastKey), lastPassword));
if (!lastSecret && QMessageBox::warning(&d, "Invalid Password or Key File", "The given password could not be used to decrypt the key file given. Are you sure it is a valid key file and that the password is correct?", QMessageBox::Abort, QMessageBox::Retry) == QMessageBox::Abort)
{
u.key->clear();
updateKey();
return;
}
}
u.oldPassword->setEnabled(!!lastSecret);
u.newPassword->setEnabled(!!lastSecret);
u.noPassword->setEnabled(!!lastSecret);
u.masterLabel->setEnabled(!!lastSecret);
u.oldLabel->setEnabled(!!lastSecret);
u.showPassword->setEnabled(!!lastSecret);
u.password->setEnabled(!!lastSecret);
u.passwordHash->setReadOnly(!!lastSecret);
u.address->setReadOnly(!!lastSecret);
if (lastSecret)
{
u.oldPassword->setEnabled(!lastPassword.empty());
if (lastPassword.empty())
u.oldPassword->setChecked(false);
u.address->setText(QString::fromStdString(ICAP(toAddress(lastSecret)).encoded()));
updateAddress();
}
else
u.address->clear();
updateImport();
};
connect(u.noPassword, &QRadioButton::clicked, [&](){
u.passwordHash->clear();
u.hint->setText("No additional password (same as master password).");
updateAction();
});
connect(u.oldPassword, &QRadioButton::clicked, [&](){
u.passwordHash->setText(QString::fromStdString(sha3(lastPassword).hex()));
u.hint->setText("Same as original password for file " + QString::fromStdString(lastKey));
updateAction();
});
connect(u.newPassword, &QRadioButton::clicked, [&](){
u.hint->setText("");
updatePassword();
});
connect(u.password, &QLineEdit::textChanged, [&](){ updatePassword(); });
connect(u.address, &QLineEdit::textChanged, [&](){ updateAddress(); });
connect(u.key, &QLineEdit::textEdited, [&](){ updateKey(); });
connect(u.name, &QLineEdit::textEdited, [&](){ updateImport(); });
connect(u.showPassword, &QCheckBox::toggled, [&](bool show){ u.password->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); });
connect(u.openKey, &QToolButton::clicked, [&](){
QString fn = QFileDialog::getOpenFileName(main(), "Open Key File", QDir::homePath(), "JSON Files (*.json);;All Files (*)");
if (!fn.isEmpty())
{
u.key->setText(fn);
updateKey();
}
});
if (d.exec() == QDialog::Accepted)
{
Address a = lastAddress;
string n = u.name->text().toStdString();
string h = u.hint->text().toStdString();
// check for a brain wallet import
if (lastKey.empty() && !lastSecret)
main()->keyManager().importExistingBrain(a, n, h);
else if (!lastKey.empty() && !lastSecret)
{
h256 ph;
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString()));
main()->keyManager().importExisting(main()->keyManager().store().importKey(lastKey), n, a, ph, h);
}
else
{
bool mp = u.noPassword->isChecked();
string p = mp ? string() : u.oldPassword ? lastPassword : u.password->text().toStdString();
if (mp)
main()->keyManager().import(lastSecret, n);
else
main()->keyManager().import(lastSecret, n, p, h);
}
main()->noteKeysChanged();
}
}

44
alethzero/plugins/keys/ImportKey.h

@ -0,0 +1,44 @@
/*
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 ImportKey.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class ImportKey: public QObject, public Plugin
{
Q_OBJECT
public:
ImportKey(MainFace* _m);
~ImportKey();
private slots:
void import();
};
}
}

336
alethzero/plugins/keys/ImportKey.ui

@ -0,0 +1,336 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImportKey</class>
<widget class="QDialog" name="ImportKey">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>530</width>
<height>389</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="10" column="2" colspan="3">
<widget class="QLineEdit" name="passwordHash">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="3" colspan="2">
<widget class="QCheckBox" name="showPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Address:</string>
</property>
<property name="buddy">
<cstring>address</cstring>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QToolButton" name="openKey">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QRadioButton" name="newPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>New &amp;Password:</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="4" column="2" colspan="3">
<widget class="QLineEdit" name="address">
<property name="placeholderText">
<string>Place the address of the key here</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>name</cstring>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QRadioButton" name="noPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Master password</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="11" column="2" colspan="3">
<widget class="QLineEdit" name="hint"/>
</item>
<item row="7" column="0" colspan="2">
<widget class="QRadioButton" name="oldPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Old password</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="8" column="2">
<widget class="QLineEdit" name="password">
<property name="placeholderText">
<string>Enter the password you wish to use for the key here</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="3">
<widget class="QLineEdit" name="name">
<property name="placeholderText">
<string>Enter this key's name here</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Password &amp;Hash:</string>
</property>
<property name="buddy">
<cstring>passwordHash</cstring>
</property>
</widget>
</item>
<item row="11" column="0" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password Hin&amp;t:</string>
</property>
<property name="buddy">
<cstring>hint</cstring>
</property>
</widget>
</item>
<item row="6" column="2" colspan="3">
<widget class="QLabel" name="masterLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Use same password for the key as for the master.</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="QLineEdit" name="key">
<property name="placeholderText">
<string>Brain wallet (no key file)</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Key:</string>
</property>
<property name="buddy">
<cstring>key</cstring>
</property>
</widget>
</item>
<item row="7" column="2" colspan="3">
<widget class="QLabel" name="oldLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Use the same password as in the key file.</string>
</property>
</widget>
</item>
<item row="5" column="2" colspan="3">
<widget class="QLineEdit" name="addressOut">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Unknown Address</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="action">
<property name="text">
<string/>
</property>
</widget>
</item>
<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>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="import_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Import</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>name</tabstop>
<tabstop>key</tabstop>
<tabstop>openKey</tabstop>
<tabstop>address</tabstop>
<tabstop>addressOut</tabstop>
<tabstop>noPassword</tabstop>
<tabstop>oldPassword</tabstop>
<tabstop>newPassword</tabstop>
<tabstop>password</tabstop>
<tabstop>showPassword</tabstop>
<tabstop>passwordHash</tabstop>
<tabstop>hint</tabstop>
<tabstop>cancel</tabstop>
<tabstop>import_2</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>import_2</sender>
<signal>clicked()</signal>
<receiver>ImportKey</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>519</x>
<y>378</y>
</hint>
<hint type="destinationlabel">
<x>449</x>
<y>388</y>
</hint>
</hints>
</connection>
<connection>
<sender>cancel</sender>
<signal>clicked()</signal>
<receiver>ImportKey</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>378</y>
</hint>
<hint type="destinationlabel">
<x>351</x>
<y>388</y>
</hint>
</hints>
</connection>
<connection>
<sender>newPassword</sender>
<signal>pressed()</signal>
<receiver>password</receiver>
<slot>setFocus()</slot>
<hints>
<hint type="sourcelabel">
<x>80</x>
<y>211</y>
</hint>
<hint type="destinationlabel">
<x>185</x>
<y>215</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

171
alethzero/plugins/namers/NewAccount.cpp

@ -0,0 +1,171 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NewAccount.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include "NewAccount.h"
#include <QMenu>
#include <QDialog>
#include <libdevcore/Log.h>
#include <libethcore/KeyManager.h>
#include <libethereum/Client.h>
#include "ui_NewAccount.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
bool beginsWith(Address _a, bytes const& _b)
{
for (unsigned i = 0; i < min<unsigned>(20, _b.size()); ++i)
if (_a[i] != _b[i])
return false;
return true;
}
DEV_AZ_NOTE_PLUGIN(NewAccount);
NewAccount::NewAccount(MainFace* _m):
Plugin(_m, "NewAccount")
{
connect(addMenuItem("New Account...", "menuTools", true), SIGNAL(triggered()), SLOT(create()));
}
NewAccount::~NewAccount()
{
}
void NewAccount::create()
{
QDialog d;
Ui::NewAccount u;
u.setupUi(&d);
d.setWindowTitle("New Account Wallet");
u.hexText->setEnabled(false);
u.passwordText->setEnabled(false);
u.passwordAgainText->setEnabled(false);
u.hintText->setEnabled(false);
QStringList items =
{
"No vanity (instant)",
"Direct ICAP address",
"Two pairs first (a few seconds)",
"Two pairs first and second (a few minutes)",
"Three pairs first (a few minutes)",
"Four pairs first (several hours)",
"Specific hex string"
};
u.typeComboBox->addItems(items);
void (QComboBox:: *indexChangedSignal)(int) = &QComboBox::currentIndexChanged;
connect(u.typeComboBox, indexChangedSignal, [&](int index)
{
u.hexText->setEnabled(index == StringMatch);
});
connect(u.additionalCheckBox, &QCheckBox::clicked, [&]()
{
bool checked = u.additionalCheckBox->checkState() == Qt::CheckState::Checked;
u.passwordText->setEnabled(checked);
u.passwordAgainText->setEnabled(checked);
u.hintText->setEnabled(checked);
});
connect(u.create, &QPushButton::clicked, [&]()
{
if (u.additionalCheckBox->checkState() == Qt::CheckState::Checked && !validatePassword(u))
{
u.passwordAgainLabel->setStyleSheet("QLabel { color : red }");
u.passwordAgainLabel->setText("Invalid! Please re-enter password correctly:");
return;
}
d.accept();
});
if (d.exec() == QDialog::Accepted)
onDialogAccepted(u);
}
bool NewAccount::validatePassword(Ui::NewAccount const& _u)
{
return QString::compare(_u.passwordText->toPlainText(), _u.passwordAgainText->toPlainText()) == 0;
}
void NewAccount::onDialogAccepted(Ui::NewAccount const& _u)
{
Type v = (Type)_u.typeComboBox->currentIndex();
bytes bs = fromHex(_u.hexText->toPlainText().toStdString());
KeyPair p = newKeyPair(v, bs);
QString s = _u.nameText->toPlainText();
if (_u.additionalCheckBox->checkState() == Qt::CheckState::Checked)
{
std::string hint = _u.hintText->toPlainText().toStdString();
std::string password = _u.passwordText->toPlainText().toStdString();
main()->keyManager().import(p.secret(), s.toStdString(), password, hint);
}
else
main()->keyManager().import(p.secret(), s.toStdString());
main()->noteKeysChanged();
}
KeyPair NewAccount::newKeyPair(Type _type, bytes const& _prefix)
{
KeyPair p;
bool keepGoing = true;
unsigned done = 0;
function<void()> f = [&]() {
KeyPair lp;
while (keepGoing)
{
done++;
if (done % 1000 == 0)
cnote << "Tried" << done << "keys";
lp = KeyPair::create();
auto a = lp.address();
if (_type == NoVanity ||
(_type == DirectICAP && !a[0]) ||
(_type == FirstTwo && a[0] == a[1]) ||
(_type == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) ||
(_type == FirstThree && a[0] == a[1] && a[1] == a[2]) ||
(_type == FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) ||
(_type == StringMatch && beginsWith(lp.address(), _prefix))
)
break;
}
if (keepGoing)
p = lp;
keepGoing = false;
};
vector<std::thread*> ts;
for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t)
ts.push_back(new std::thread(f));
f();
for (std::thread* t: ts)
{
t->join();
delete t;
}
return p;
}

56
alethzero/plugins/namers/NewAccount.h

@ -0,0 +1,56 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NewAccount.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace Ui
{
class NewAccount;
}
namespace dev
{
namespace az
{
class NewAccount: public QObject, public Plugin
{
Q_OBJECT
public:
NewAccount(MainFace* _m);
~NewAccount();
private slots:
void create();
private:
enum Type { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch };
bool validatePassword(Ui::NewAccount const& _u);
void onDialogAccepted(Ui::NewAccount const& _u);
KeyPair newKeyPair(Type _type, bytes const& _prefix);
};
}
}

260
alethzero/plugins/namers/NewAccount.ui

@ -0,0 +1,260 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewAccount</class>
<widget class="QDialog" name="NewAccount">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>511</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="typeLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Select new account type:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="typeComboBox">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="hexLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter some hex digits it should begin with.&lt;br/&gt;NOTE: The more you enter, the longer generation will take.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="hexText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nameLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Enter this account name:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="nameText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="additionalLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<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;Would you like to add additional security for this key? This lets you protect it with a different password to other keys, but also means that you need to re-enter the key's password every time you wish to use the account.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="additionalCheckBox">
<property name="text">
<string>Yes</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="passwordLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Enter password:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="passwordText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="passwordAgainLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Enter password again:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="passwordAgainText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="hintLabel">
<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;Enter hint:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="hintText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</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="maximumSize">
<size>
<width>83</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="create">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>83</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>&amp;Create</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>cancel</sender>
<signal>clicked()</signal>
<receiver>NewAccount</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>

15
alethzero/plugins/namers/OtherAccounts.cpp

@ -21,6 +21,7 @@
#include "OtherAccounts.h"
#include <QSettings>
#include <QMessageBox>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include <ui_OtherAccounts.h>
@ -46,13 +47,23 @@ void OtherAccounts::import()
if (d.exec() == QDialog::Accepted)
{
QStringList sl = u.accounts->toPlainText().split("\n");
unsigned line = 1;
for (QString const& s: sl)
{
Address addr = dev::eth::toAddress(s.section(QRegExp("[ \\0\\t]+"), 0, 0).toStdString());
string name = s.section(QRegExp("[ \\0\\t]+"), 1).toStdString();
try
{
Address addr = dev::eth::toAddress(s.section(QRegExp("[ \\0\\t]+"), 0, 0).trimmed().toStdString());
string name = s.section(QRegExp("[ \\0\\t]+"), 1).trimmed().toStdString();
m_toName[addr] = name;
m_toAddress[name] = addr;
}
catch (...)
{
if (QMessageBox::warning(&d, "Invalid Line Format", "Line format or address given on line " + QString::number(line) + " is invalid:\n" + s, QMessageBox::Abort, QMessageBox::Ignore) == QMessageBox::Abort)
break;
}
line++;
}
main()->noteSettingsChanged();
noteKnownChanged();
}

87
alethzero/plugins/special/InjectTransactions.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 InjectTransactions.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "InjectTransactions.h"
#include <QMessageBox>
#include <QInputDialog>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include "ui_InjectTransactions.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(InjectTransactions);
InjectTransactions::InjectTransactions(MainFace* _m):
Plugin(_m, "InjectTransactions")
{
connect(addMenuItem("Inject Transaction...", "menuSpecial", true), SIGNAL(triggered()), SLOT(injectOne()));
connect(addMenuItem("Bulk Inject Transactions...", "menuSpecial", false), SIGNAL(triggered()), SLOT(injectBulk()));
}
InjectTransactions::~InjectTransactions()
{
}
void InjectTransactions::injectOne()
{
bool ok;
QString s = QInputDialog::getText(main(), "Inject Transaction", "Enter transaction dump in hex", QLineEdit::Normal, QString(), &ok);
if (ok)
doInject(s);
}
void InjectTransactions::injectBulk()
{
QDialog d;
Ui_InjectTransactions u;
u.setupUi(&d);
d.setWindowTitle("Bulk Inject Transactions");
if (d.exec() == QDialog::Accepted)
for (QString const& s: u.transactions->toPlainText().split("\n"))
doInject(s);
}
void InjectTransactions::doInject(QString _txHex)
{
try
{
bytes b = fromHex(_txHex.toStdString(), WhenError::Throw);
main()->ethereum()->injectTransaction(b);
}
catch (BadHexCharacter& _e)
{
if (QMessageBox::warning(main(), "Invalid Transaction Hex", "Invalid hex character in:\n" + _txHex + "\nTransaction rejected.", QMessageBox::Ignore, QMessageBox::Abort) == QMessageBox::Abort)
return;
}
catch (Exception& _e)
{
if (QMessageBox::warning(main(), "Transaction Rejected", "Invalid transaction; due to" + QString::fromStdString(_e.what()) + "\n" + _txHex + "\nTransaction rejected.", QMessageBox::Ignore, QMessageBox::Abort) == QMessageBox::Abort)
return;
}
catch (...)
{
// Should not happen under normal circumstances.
return;
}
}

48
alethzero/plugins/special/InjectTransactions.h

@ -0,0 +1,48 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file InjectTransactions.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class InjectTransactions: public QObject, public Plugin
{
Q_OBJECT
public:
InjectTransactions(MainFace* _m);
~InjectTransactions();
private slots:
void injectOne();
void injectBulk();
private:
void doInject(QString _txHex);
};
}
}

95
alethzero/plugins/special/InjectTransactions.ui

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InjectTransactions</class>
<widget class="QDialog" name="InjectTransactions">
<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="transactions">
<property name="placeholderText">
<string>Write the transactions you wish to inject here, in hex, one per line.</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="inject">
<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>inject</sender>
<signal>clicked()</signal>
<receiver>InjectTransactions</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>InjectTransactions</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>

2
cmake/EthDependencies.cmake

@ -17,7 +17,7 @@ set(ETH_GENERATED_DIR "${PROJECT_BINARY_DIR}/gen")
include_directories(${ETH_GENERATED_DIR})
# custom cmake scripts
set(ETH_SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/cmake/scripts)
set(ETH_SCRIPTS_DIR ${CMAKE_CURRENT_LIST_DIR}/scripts)
# Qt5 requires opengl
# TODO use proper version of windows SDK (32 vs 64)

2
cmake/EthExecutableHelper.cmake

@ -95,7 +95,7 @@ macro(eth_install_executable EXECUTABLE)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app -executable=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir}
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND sh ${CMAKE_SOURCE_DIR}/cmake/scripts/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents
COMMAND sh ${ETH_SCRIPTS_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents
)
# This tool and next will inspect linked libraries in order to determine which dependencies are required

70
eth/main.cpp

@ -14,8 +14,10 @@
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 main.cpp
/**
* @file main.cpp
* @author Gav Wood <i@gavwood.com>
* @author Tasha Carl <tasha@carl.pro> - I here by place all my contributions in this file under MIT licence, as specified by http://opensource.org/licenses/MIT.
* @date 2014
* Ethereum client.
*/
@ -83,20 +85,20 @@ void help()
<< " --olympic Use the Olympic (0.9) protocol." << endl
<< " --frontier Use the Frontier (1.0) protocol." << endl
<< " --private <name> Use a private chain." << endl
<< " --genesis-json <file> Import the genesis block information from the given json file." << endl
<< " --genesis-json <file> Import the genesis block information from the given JSON file." << endl
<< endl
<< " -o,--mode <full/peer> Start a full node or a peer node (default: full)." << endl
<< endl
#if ETH_JSONRPC || !ETH_TRUE
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port <n> Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
<< " --admin <password> Specify admin session key for JSON-RPC (default: auto-generated and printed at startup)." << endl
<< " --admin <password> Specify admin session key for JSON-RPC (default: auto-generated and printed at start-up)." << endl
#endif
<< " -K,--kill First kill the blockchain." << endl
<< " -K,--kill Kill the blockchain first." << endl
<< " -R,--rebuild Rebuild the blockchain from the existing database." << endl
<< " --rescue Attempt to rescue a corrupt database." << endl
<< endl
<< " --import-presale <file> Import a presale key; you'll need to type the password to this." << endl
<< " --import-presale <file> Import a pre-sale key; you'll need to specify the password to this key." << endl
<< " -s,--import-secret <secret> Import a secret key into the key store and use as the default." << endl
<< " -S,--import-session-secret <secret> Import a secret key into the key store and use as the default for this session only." << endl
<< " --sign-key <address> Sign all transactions with the key of the given address." << endl
@ -106,54 +108,54 @@ void help()
<< " --sentinel <server> Set the sentinel for reporting bad blocks or chain issues." << endl
<< endl
<< "Client transacting:" << endl
/*<< " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (default: 30.679)." << endl
<< " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl*/
<< " --ask <wei> Set the minimum ask gas price under which no transactions will be mined (default " << toString(DefaultGasPrice) << " )." << endl
<< " --bid <wei> Set the bid gas price for to pay for transactions (default " << toString(DefaultGasPrice) << " )." << endl
/*<< " -B,--block-fees <n> Set the block fee profit in the reference unit, e.g. ¢ (default: 15)." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit, e.g. ¢ (default: 30.679)." << endl
<< " -P,--priority <0 - 100> Set the default priority percentage (%) of a transaction (default: 50)." << endl*/
<< " --ask <wei> Set the minimum ask gas price under which no transaction will be mined (default " << toString(DefaultGasPrice) << " )." << endl
<< " --bid <wei> Set the bid gas price to pay for transactions (default " << toString(DefaultGasPrice) << " )." << endl
<< endl
<< "Client mining:" << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (default: off)" << endl
<< " -f,--force-mining Mine even when there are no transactions to mine (default: off)" << endl
<< " --mine-on-wrong-chain Mine even when we know it's the wrong chain (default: off)" << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to given address (default: auto)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (default: off)." << endl
<< " -f,--force-mining Mine even when there are no transactions to mine (default: off)." << endl
<< " --mine-on-wrong-chain Mine even when we know that it is the wrong chain (default: off)." << endl
<< " -C,--cpu When mining, use the CPU." << endl
<< " -G,--opencl When mining use the GPU via OpenCL." << endl
<< " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl
<< " -G,--opencl When mining, use the GPU via OpenCL." << endl
<< " --opencl-platform <n> When mining using -G/--opencl, use OpenCL platform n (default: 0)." << endl
<< " --opencl-device <n> When mining using -G/--opencl, use OpenCL device n (default: 0)." << endl
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)." << endl
<< endl
<< "Client networking:" << endl
<< " --client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " --bootstrap Connect to the default Ethereum peerservers (default unless --no-discovery used)." << endl
<< " --no-bootstrap Do not connect to the default Ethereum peerservers (default only when --no-discovery is used)." << endl
<< " -x,--peers <number> Attempt to connect to given number of peers (default: 11)." << endl
<< " --peer-stretch <number> Accepted connection multiplier (default: 7)." << endl
<< " --bootstrap Connect to the default Ethereum peer servers (default unless --no-discovery used)." << endl
<< " --no-bootstrap Do not connect to the default Ethereum peer servers (default only when --no-discovery is used)." << endl
<< " -x,--peers <number> Attempt to connect to a given number of peers (default: 11)." << endl
<< " --peer-stretch <number> Give the accepted connection multiplier (default: 7)." << endl
<< " --public-ip <ip> Force advertised public ip to given (default: auto)." << endl
<< " --public-ip <ip> Force advertised public IP to the given IP (default: auto)." << endl
<< " --listen-ip <ip>(:<port>) Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
<< " --listen <port> Listen on the given port for incoming connections (default: 30303)." << endl
<< " -r,--remote <host>(:<port>) Connect to remote host (default: none)." << endl
<< " --port <port> Connect to remote port (default: 30303)." << endl
<< " -r,--remote <host>(:<port>) Connect to the given remote host (default: none)." << endl
<< " --port <port> Connect to the given remote port (default: 30303)." << endl
<< " --network-id <n> Only connect to other hosts with this network id." << endl
<< " --upnp <on/off> Use UPnP for NAT (default: on)." << endl
<< " --peerset <list> Space delimited list of type type:publickey@ipAddress[:port]" << endl
<< " --peerset <list> Space delimited list of peers; element format: type:publickey@ipAddress[:port]." << endl
<< " Types:" << endl
<< " default Attempt connection when no other peers are available and pinning is disable." << endl
<< " default Attempt connection when no other peers are available and pinning is disabled." << endl
<< " require Keep connected at all times." << endl
// TODO:
// << " --trust-peers <filename> Space delimited list of publickeys." << endl
<< " --no-discovery Disable Node discovery, implies --no-bootstrap." << endl
<< " --no-discovery Disable node discovery, implies --no-bootstrap." << endl
<< " --pin Only accept or connect to trusted peers." << endl
<< " --hermit Equivalent to --no-discovery --pin." << endl
<< " --sociable Forces discovery and no pinning." << endl
<< " --sociable Force discovery and no pinning." << endl
<< endl;
MinerCLI::streamHelp(cout);
cout
<< "Client structured logging:" << endl
<< " --structured-logging Enable structured logging (default output to stdout)." << endl
<< " --structured-logging Enable structured logging (default: output to stdout)." << endl
<< " --structured-logging-format <format> Set the structured logging time format." << endl
<< " --structured-logging-url <URL> Set the structured logging destination (currently only file:// supported)." << endl
<< endl
@ -161,19 +163,19 @@ void help()
<< " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only <n> Equivalent to --export-from n --export-to n." << endl
<< " --dont-check Avoids checking some of the aspects of blocks. Faster importing, but only do if you know the data is valid." << endl
<< " --dont-check Prevent checking some block aspects. Faster importing, but to apply only when the data is known to be valid." << endl
<< endl
<< "General Options:" << endl
<< " -d,--db-path <path> Load database from path (default: " << getDataDir() << ")" << endl
<< " -d,--db-path <path> Load database from path (default: " << getDataDir() << ")." << endl
#if ETH_EVMJIT || !ETH_TRUE
<< " --vm <vm-kind> Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl
<< " --vm <vm-kind> Select VM; options are: interpreter, jit or smart (default: interpreter)." << endl
#endif
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl
<< " -V,--version Show the version and exit." << endl
<< " -h,--help Show this help message and exit." << endl
<< endl
<< "Experimental / Proof of Concept:" << endl
<< " --shh Enable Whisper" << endl
<< " --shh Enable Whisper." << endl
<< endl
;
exit(0);

323
ethkey/KeyAux.h

@ -33,6 +33,7 @@
#include <libethcore/KeyManager.h>
#include <libethcore/ICAP.h>
#include <libethcore/Transaction.h>
#include <libdevcrypto/WordList.h>
#include "BuildInfo.h"
using namespace std;
using namespace dev;
@ -108,6 +109,9 @@ public:
Export,
Recode,
Kill,
NewBrain,
ImportBrain,
InspectBrain,
SignTx,
DecodeTx,
};
@ -140,6 +144,67 @@ public:
m_mode = OperationMode::SignTx;
m_signKey = argv[++i];
}
else if (arg == "--tx-data" && i + 1 < argc)
try
{
m_toSign.data = fromHex(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-nonce" && i + 1 < argc)
try
{
m_toSign.nonce = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if ((arg == "--tx-dest" || arg == "--tx-to" || arg == "--tx-destination") && i + 1 < argc)
try
{
m_toSign.creation = false;
m_toSign.to = toAddress(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-gas" && i + 1 < argc)
try
{
m_toSign.gas = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-gasprice" && i + 1 < argc)
try
{
m_toSign.gasPrice = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-value" && i + 1 < argc)
try
{
m_toSign.value = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--decode-tx")
m_mode = OperationMode::DecodeTx;
else if (arg == "--import-bare")
@ -175,6 +240,18 @@ public:
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if (arg == "--new-brain" && i + 1 < argc)
{
m_mode = OperationMode::NewBrain;
m_name = argv[++i];
}
else if (arg == "--import-brain" && i + 1 < argc)
{
m_mode = OperationMode::ImportBrain;
m_name = argv[++i];
}
else if (arg == "--inspect-brain")
m_mode = OperationMode::InspectBrain;
else if (arg == "--import-with-address" && i + 3 < argc)
{
m_mode = OperationMode::ImportWithAddress;
@ -203,9 +280,35 @@ public:
return k;
}
Secret getSecret(std::string const& _signKey)
{
string json = contentsString(_signKey);
if (!json.empty())
return Secret(secretStore().secret(secretStore().readKeyContent(json), [&](){ return getPassword("Enter password for key: "); }));
else
{
if (h128 u = fromUUID(_signKey))
return Secret(secretStore().secret(u, [&](){ return getPassword("Enter password for key: "); }));
if (_signKey.substr(0, 6) == "brain#" && _signKey.find(":") != string::npos)
return KeyManager::subkey(KeyManager::brain(_signKey.substr(_signKey.find(":"))), stoul(_signKey.substr(6, _signKey.find(":") - 7)));
if (_signKey.substr(0, 6) == "brain:")
return KeyManager::brain(_signKey.substr(6));
if (_signKey == "brain")
return KeyManager::brain(getPassword("Enter brain wallet phrase: "));
Address a;
DEV_IGNORE_EXCEPTIONS(a = Address(_signKey));
if (a)
return keyManager().secret(a, [&](){ return getPassword("Enter password for key (hint:" + keyManager().passwordHint(a) + "): "); });
cerr << "Bad file, UUID and address: " << _signKey << endl;
exit(-1);
}
}
void execute()
{
if (m_mode == OperationMode::CreateWallet)
switch (m_mode)
{
case OperationMode::CreateWallet:
{
KeyManager wallet(m_walletPath, m_secretsPath);
if (m_masterPassword.empty())
@ -223,8 +326,9 @@ public:
cerr << "unable to create wallet" << endl << boost::diagnostic_information(_e);
}
}
break;
}
else if (m_mode == OperationMode::DecodeTx)
case OperationMode::DecodeTx:
{
bytes b = inputData(m_inputs[0]);
if (b.empty())
@ -269,60 +373,19 @@ public:
{
cerr << "Invalid transaction: " << ex.what() << endl;
}
break;
}
else if (m_mode == OperationMode::SignTx)
{
Secret s;
string json = contentsString(m_signKey);
if (!json.empty())
{
SecretStore store(m_secretsPath);
s = Secret(store.secret(store.readKeyContent(json), [&](){ return getPassword("Enter password for key: "); }));
}
else
{
if (h128 u = fromUUID(m_signKey))
{
SecretStore store(m_secretsPath);
s = Secret(store.secret(u, [&](){ return getPassword("Enter password for key: "); }));
}
else if (Address a = Address(m_signKey))
{
KeyManager wallet(m_walletPath, m_secretsPath);
if (wallet.exists())
{
openWallet(wallet);
s = wallet.secret(a, [&](){ return getPassword("Enter password for key: "); });
}
else
{
cerr << "Wallet doesn't exist." << endl;
exit(-1);
}
}
else
{
cerr << "Bad file, UUID and address: " << m_signKey << endl;
exit(-1);
}
}
if (!s)
case OperationMode::SignTx:
{
cerr << "UUID/address not found: " << m_signKey << endl;
exit(-1);
}
Secret s = getSecret(m_signKey);
if (m_inputs.empty())
m_inputs.push_back(string());
for (string const& i: m_inputs)
{
bool isFile;
bytes b = inputData(i, &isFile);
if (b.empty())
cerr << "Unknown file or bad hex: '" << i << "'" << endl;
else
bool isFile = false;
try
{
TransactionBase t(b, CheckTransaction::None);
TransactionBase t = i.empty() ? TransactionBase(m_toSign) : TransactionBase(inputData(i, &isFile), CheckTransaction::None);
t.sign(s);
cout << t.sha3() << ": ";
if (isFile)
@ -338,14 +401,40 @@ public:
cerr << "Invalid transaction: " << ex.what() << endl;
}
}
break;
}
else if (m_mode < OperationMode::CreateWallet)
case OperationMode::NewBrain:
{
SecretStore store(m_secretsPath);
switch (m_mode)
if (m_name != "--")
keyManager();
boost::random_device d;
boost::random::uniform_int_distribution<unsigned> pickWord(0, WordList.size() - 1);
string seed;
for (int i = 0; i < 13; ++i)
seed += (seed.size() ? " " : "") + WordList[pickWord(d)];
cout << "Your brain key phrase: <<" << seed << ">>" << endl;
if (m_name != "--")
{
std::string hint;
cout << "Enter a hint for the phrase if you want: " << flush;
getline(cin, hint);
Address a = keyManager().importBrain(seed, m_name, hint);
cout << a.abridged() << endl;
cout << " ICAP: " << ICAP(a).encoded() << endl;
cout << " Address: " << a.hex() << endl;
}
break;
}
case OperationMode::InspectBrain:
{
Address a = toAddress(KeyManager::brain(getPassword("Enter brain wallet key phrase: ")));
cout << a.abridged() << endl;
cout << " ICAP: " << ICAP(a).encoded() << endl;
cout << " Address: " << a.hex() << endl;
break;
}
case OperationMode::ListBare:
for (h128 const& u: std::set<h128>() + store.keys())
for (h128 const& u: std::set<h128>() + secretStore().keys())
cout << toUUID(u) << endl;
break;
case OperationMode::NewBare:
@ -353,7 +442,7 @@ public:
if (m_lock.empty())
m_lock = createPassword("Enter a password with which to secure this account: ");
auto k = makeKey();
h128 u = store.importSecret(k.secret().ref(), m_lock);
h128 u = secretStore().importSecret(k.secret().ref(), m_lock);
cout << "Created key " << toUUID(u) << endl;
cout << " Address: " << k.address().hex() << endl;
cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
@ -370,10 +459,10 @@ public:
std::string s = contentsString(input);
b.writable() = fromHex(s);
if (b.size() != 32)
u = store.importKey(input);
u = secretStore().importKey(input);
}
if (!u && b.size() == 32)
u = store.importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
u = secretStore().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
if (!u)
{
cerr << "Cannot import " << input << " not a file or secret." << endl;
@ -386,8 +475,8 @@ public:
for (auto const& i: m_inputs)
if (!contents(i).empty())
{
h128 u = store.readKey(i, false);
bytesSec s = store.secret(u, [&](){ return getPassword("Enter password for key " + i + ": "); });
h128 u = secretStore().readKey(i, false);
bytesSec s = secretStore().secret(u, [&](){ return getPassword("Enter password for key " + i + ": "); });
cout << "Key " << i << ":" << endl;
cout << " UUID: " << toUUID(u) << ":" << endl;
cout << " Address: " << toAddress(Secret(s)).hex() << endl;
@ -395,7 +484,7 @@ public:
}
else if (h128 u = fromUUID(i))
{
bytesSec s = store.secret(u, [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); });
bytesSec s = secretStore().secret(u, [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); });
cout << "Key " << i << ":" << endl;
cout << " Address: " << toAddress(Secret(s)).hex() << endl;
cout << " Secret: " << toHex(s.ref().cropped(0, 8)) << "..." << endl;
@ -407,7 +496,7 @@ public:
case OperationMode::RecodeBare:
for (auto const& i: m_inputs)
if (h128 u = fromUUID(i))
if (store.recode(u, lockPassword(toUUID(u)), [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); }, kdf()))
if (secretStore().recode(u, lockPassword(toUUID(u)), [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); }, kdf()))
cerr << "Re-encoded " << toUUID(u) << endl;
else
cerr << "Couldn't re-encode " << toUUID(u) << "; key corrupt or incorrect password supplied." << endl;
@ -417,31 +506,17 @@ public:
case OperationMode::KillBare:
for (auto const& i: m_inputs)
if (h128 u = fromUUID(i))
store.kill(u);
secretStore().kill(u);
else
cerr << "Couldn't kill " << i << "; not found." << endl;
break;
default: break;
}
}
else
{
KeyManager wallet(m_walletPath, m_secretsPath);
if (wallet.exists())
openWallet(wallet);
else
{
cerr << "Couldn't open wallet. Does it exist?" << endl;
exit(-1);
}
switch (m_mode)
{
case OperationMode::New:
{
tie(m_lock, m_lockHint) = createPassword(wallet, "Enter a password with which to secure this account (or nothing to use the master password): ", m_lock, m_lockHint);
keyManager();
tie(m_lock, m_lockHint) = createPassword(keyManager(), "Enter a password with which to secure this account (or nothing to use the master password): ", m_lock, m_lockHint);
auto k = makeKey();
bool usesMaster = m_lock.empty();
h128 u = usesMaster ? wallet.import(k.secret(), m_name) : wallet.import(k.secret(), m_name, m_lock, m_lockHint);
h128 u = usesMaster ? keyManager().import(k.secret(), m_name) : keyManager().import(k.secret(), m_name, m_lock, m_lockHint);
cout << "Created key " << toUUID(u) << endl;
cout << " Name: " << m_name << endl;
if (usesMaster)
@ -454,6 +529,7 @@ public:
}
case OperationMode::ImportWithAddress:
{
keyManager();
string const& i = m_inputs[0];
h128 u;
bytesSec b;
@ -463,51 +539,65 @@ public:
std::string s = contentsString(i);
b.writable() = fromHex(s);
if (b.size() != 32)
u = wallet.store().importKey(i);
u = keyManager().store().importKey(i);
}
if (!u && b.size() == 32)
u = wallet.store().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
u = keyManager().store().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
if (!u)
{
cerr << "Cannot import " << i << " not a file or secret." << endl;
break;
}
wallet.importExisting(u, m_name, m_address);
keyManager().importExisting(u, m_name, m_address);
cout << "Successfully imported " << i << ":" << endl;
cout << " Name: " << m_name << endl;
cout << " Address: " << m_address << endl;
cout << " UUID: " << toUUID(u) << endl;
break;
}
case OperationMode::ImportBrain:
{
keyManager();
std::string seed = getPassword("Enter brain wallet key phrase: ");
std::string hint;
cout << "Enter a hint for the phrase if you want: " << flush;
getline(cin, hint);
Address a = keyManager().importBrain(seed, m_name, hint);
cout << a << endl;
cout << " ICAP: " << ICAP(a).encoded() << endl;
cout << " Address: " << a.hex() << endl;
break;
}
case OperationMode::ImportPresale:
{
keyManager();
std::string pw;
KeyPair k = wallet.presaleSecret(contentsString(m_inputs[0]), [&](bool){ return (pw = getPassword("Enter the password for the presale key: ")); });
wallet.import(k.secret(), m_name, pw, "Same password as used for presale key");
KeyPair k = keyManager().presaleSecret(contentsString(m_inputs[0]), [&](bool){ return (pw = getPassword("Enter the password for the presale key: ")); });
keyManager().import(k.secret(), m_name, pw, "Same password as used for presale key");
break;
}
case OperationMode::List:
{
vector<u128> bare;
vector<u128> nonIcap;
for (auto const& u: wallet.store().keys())
if (Address a = wallet.address(u))
if (a[0])
nonIcap.push_back(u);
else
AddressHash got;
for (auto const& u: keyManager().store().keys())
if (Address a = keyManager().address(u))
{
got.insert(a);
cout << toUUID(u) << " " << a.abridged();
cout << " " << ICAP(a).encoded();
cout << " " << wallet.accountName(a) << endl;
string s = ICAP(a).encoded();
cout << " " << s << string(35 - s.size(), ' ');
cout << " " << keyManager().accountName(a) << endl;
}
else
bare.push_back(u);
for (auto const& u: nonIcap)
if (Address a = wallet.address(u))
for (auto const& a: keyManager().accounts())
if (!got.count(a))
{
cout << toUUID(u) << " " << a.abridged();
cout << " " << ICAP(a).encoded();
cout << " " << wallet.accountName(a) << endl;
cout << " (Brain) " << a.abridged();
cout << " " << ICAP(a).encoded() << " ";
cout << " " << keyManager().accountName(a) << endl;
}
for (auto const& u: bare)
cout << toUUID(u) << " (Bare)" << endl;
@ -515,7 +605,6 @@ public:
default: break;
}
}
}
std::string lockPassword(std::string const& _accountName)
{
@ -544,6 +633,12 @@ public:
<< " --import-with-address [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
<< "Brain wallet operating modes:" << endl
<< "WARNING: Brain wallets with human-generated passphrasses are highly susceptible to attack. Don't use such a thing for" << endl
<< "anything important." << endl
<< " --new-brain [ <name>|-- ] Create a new 13-word brain wallet; argument is the name or if --, do not add to wallet."<< endl
<< " --import-brain <name> Import your own brain wallet." << endl
<< " --inspect-brain Check the address of a particular brain wallet." << endl
<< "Wallet configuration:" << endl
<< " --create-wallet Create an Ethereum master wallet." << endl
<< " --wallet-path <path> Specify Ethereum wallet path (default: " << KeyManager::defaultPath() << ")" << endl
@ -551,7 +646,7 @@ public:
<< endl
<< "Transaction operating modes:" << endl
<< " -d,--decode-tx [<hex>|<file>] Decode given transaction." << endl
<< " -s,--sign-tx [ <address>|<uuid>|<file> ] [ <hex>|<file> , ... ] (Re-)Sign given transaction." << endl
<< " -s,--sign-tx [ <address>|<uuid>|<file>|brain((#<HD-index>):<brain-phrase>) ] [ <hex>|<file> , ... ] (Re-)Sign given transaction." << endl
<< endl
<< "Encryption configuration:" << endl
<< " --kdf <kdfname> Specify KDF to use when encrypting (default: sc rypt)" << endl
@ -613,6 +708,35 @@ private:
KDF kdf() const { return m_kdf == "pbkdf2" ? KDF::PBKDF2_SHA256 : KDF::Scrypt; }
KeyManager& keyManager()
{
if (!m_keyManager)
{
m_keyManager.reset(new KeyManager(m_walletPath, m_secretsPath));
if (m_keyManager->exists())
openWallet(*m_keyManager);
else
{
cerr << "Couldn't open wallet. Does it exist?" << endl;
exit(-1);
}
}
return *m_keyManager;
}
SecretStore& secretStore()
{
if (m_keyManager)
return m_keyManager->store();
if (!m_secretStore)
m_secretStore.reset(new SecretStore(m_secretsPath));
return *m_secretStore;
}
/// Where the keys are.
unique_ptr<SecretStore> m_secretStore;
unique_ptr<KeyManager> m_keyManager;
/// Operating mode.
OperationMode m_mode;
@ -636,6 +760,7 @@ private:
/// Signing
string m_signKey;
TransactionSkeleton m_toSign;
string m_kdf = "scrypt";
map<string, string> m_kdfParams;

8
ethminer/MinerAux.h

@ -513,7 +513,15 @@ private:
minelog << "Getting work package...";
auto rate = mp.rate();
try
{
rpc.eth_submitHashrate((int)rate, "0x" + id.hex());
}
catch (jsonrpc::JsonRpcException const& _e)
{
cwarn << "Failed to submit hashrate.";
cwarn << boost::diagnostic_information(_e);
}
Json::Value v = rpc.eth_getWork();
h256 hh(v[0].asString());

2
evmjit/libevmjit/Array.h

@ -58,7 +58,7 @@ private:
llvm::Function* createExtendFunc();
llvm::Function* getReallocFunc();
LazyFunction m_pushFunc = {[this](){ return createArrayPushFunc(); }}; // TODO: If works on MSVC, remove form initialization list
LazyFunction m_pushFunc = {[this](){ return createArrayPushFunc(); }};
LazyFunction m_setFunc = {[this](){ return createArraySetFunc(); }};
LazyFunction m_getPtrFunc = {[this](){ return createGetPtrFunc(); }};
LazyFunction m_getFunc = {[this](){ return createArrayGetFunc(); }};

6
evmjit/libevmjit/BasicBlock.cpp

@ -110,11 +110,13 @@ void LocalStack::set(size_t _index, llvm::Value* _word)
void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb)
{
auto blockTerminator = _bb.getTerminator();
assert(blockTerminator);
if (blockTerminator->getOpcode() != llvm::Instruction::Ret)
if (!blockTerminator || blockTerminator->getOpcode() != llvm::Instruction::Ret)
{
// Not needed in case of ret instruction. Ret invalidates the stack.
if (blockTerminator)
_builder.SetInsertPoint(blockTerminator);
else
_builder.SetInsertPoint(&_bb);
// Update items fetched from global stack ignoring the poped ones
assert(m_globalPops <= m_input.size()); // pop() always does get()

82
evmjit/libevmjit/Compiler.cpp

@ -29,6 +29,8 @@ namespace eth
namespace jit
{
static const auto c_destIdxLabel = "destIdx";
Compiler::Compiler(Options const& _options):
m_options(_options),
m_builder(llvm::getGlobalContext())
@ -93,21 +95,34 @@ std::vector<BasicBlock> Compiler::createBasicBlocks(code_iterator _codeBegin, co
return blocks;
}
void Compiler::fillJumpTable()
void Compiler::resolveJumps()
{
assert(m_jumpTableBB);
if (llvm::pred_empty(m_jumpTableBB))
// Iterate through all EVM instructions blocks (skip first 4 - special blocks).
for (auto it = std::next(m_mainFunc->begin(), 4); it != m_mainFunc->end(); ++it)
{
m_jumpTableBB->eraseFromParent(); // remove if unused
return;
}
auto jumpTable = llvm::cast<llvm::SwitchInst>(m_jumpTableBB->getTerminator());
auto jumpTableInput = llvm::cast<llvm::PHINode>(m_jumpTableBB->begin());
auto nextBlock = it->getNextNode() != m_mainFunc->end() ? it->getNextNode() : m_stopBB;
auto term = it->getTerminator();
// TODO: Extend this function as `resolveJumps()` and fill gaps in branch instructions.
auto target = llvm::cast<llvm::PHINode>(m_jumpTableBB->begin());
for (auto pred: llvm::predecessors(m_jumpTableBB))
if (!term) // Block may have no terminator if the next instruction is a jump destination.
llvm::IRBuilder<>{it}.CreateBr(nextBlock);
else if (auto jump = llvm::dyn_cast<llvm::BranchInst>(term))
if (jump->getSuccessor(0) == m_jumpTableBB)
{
auto destIdx = llvm::cast<llvm::ValueAsMetadata>(jump->getMetadata(c_destIdxLabel)->getOperand(0))->getValue();
if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(destIdx))
{
auto targetMd = llvm::cast<llvm::LocalAsMetadata>(pred->getTerminator()->getMetadata("target")->getOperand(0));
target->addIncoming(targetMd->getValue(), pred);
// If destination index is a constant do direct jump to the destination block.
auto bb = jumpTable->findCaseValue(constant).getCaseSuccessor();
jump->setSuccessor(0, bb);
}
else
jumpTableInput->addIncoming(destIdx, it); // Fill up PHI node
if (jump->isConditional())
jump->setSuccessor(1, nextBlock); // Set next block for conditional jumps
}
}
}
@ -160,13 +175,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
auto firstBB = blocks.empty() ? m_stopBB : blocks.front().llvm();
m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue);
for (auto it = blocks.begin(); it != blocks.end(); ++it)
{
// TODO: Rewrite
auto nextIt = it + 1;
auto nextBasicBlock = (nextIt != blocks.end()) ? nextIt->llvm() : nullptr; // TODO: What with Stop block?
compileBasicBlock(*it, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable);
}
for (auto& block: blocks)
compileBasicBlock(block, runtimeManager, arith, memory, ext, gasMeter, stack);
// Code for special blocks:
m_builder.SetInsertPoint(m_stopBB);
@ -175,19 +185,15 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
m_builder.SetInsertPoint(m_abortBB);
runtimeManager.exit(ReturnCode::OutOfGas);
fillJumpTable();
resolveJumps();
return module;
}
void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runtimeManager,
Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, Stack& _globalStack,
llvm::SwitchInst& jumpTable)
Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, Stack& _globalStack)
{
if (!_nextBasicBlock) // this is the last block in the code
_nextBasicBlock = m_stopBB;
m_builder.SetInsertPoint(_basicBlock.llvm());
LocalStack stack{_globalStack};
@ -556,24 +562,16 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
case Instruction::JUMP:
case Instruction::JUMPI:
{
auto jumpBlock = m_jumpTableBB;
auto target = stack.pop();
auto destIdx = llvm::MDNode::get(m_builder.getContext(), llvm::ValueAsMetadata::get(stack.pop()));
// Create branch instruction, initially to jump table.
// Destination will be optimized with direct jump during jump resolving if destination index is a constant.
auto jumpInst = (inst == Instruction::JUMP) ?
m_builder.CreateBr(jumpBlock) :
m_builder.CreateCondBr(m_builder.CreateICmpNE(stack.pop(), Constant::get(0), "jump.check"), jumpBlock, _nextBasicBlock);
m_builder.CreateBr(m_jumpTableBB) :
m_builder.CreateCondBr(m_builder.CreateICmpNE(stack.pop(), Constant::get(0), "jump.check"), m_jumpTableBB, nullptr);
if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(target))
{
// If target index is a constant do direct jump to the target block.
auto bb = jumpTable.findCaseValue(constant).getCaseSuccessor();
jumpInst->setSuccessor(0, bb);
}
else
{
// Attach medatada to branch instruction with information about target index.
auto targetMd = llvm::MDNode::get(jumpInst->getContext(), llvm::LocalAsMetadata::get(target));
jumpInst->setMetadata("target", targetMd);
}
// Attach medatada to branch instruction with information about destination index.
jumpInst->setMetadata(c_destIdxLabel, destIdx);
break;
}
@ -790,10 +788,6 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
_gasMeter.commitCostBlock();
// Block may have no terminator if the next instruction is a jump destination.
if (!_basicBlock.llvm()->getTerminator())
m_builder.CreateBr(_nextBasicBlock);
stack.finalize(m_builder, *_basicBlock.llvm()); // TODO: Use references
m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); // TODO: Move to LocalStack::finalize

4
evmjit/libevmjit/Compiler.h

@ -31,9 +31,9 @@ private:
std::vector<BasicBlock> createBasicBlocks(code_iterator _begin, code_iterator _end, llvm::SwitchInst& _switchInst);
void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter,
llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack, llvm::SwitchInst& _jumpTable);
class Stack& _globalStack);
void fillJumpTable();
void resolveJumps();
/// Compiler options
Options const& m_options;

2
evmjit/libevmjit/Stack.cpp

@ -7,8 +7,6 @@
#include "RuntimeManager.h"
#include "Utils.h"
#include <set> // DEBUG only
namespace dev
{
namespace eth

7
libdevcore/FixedHash.cpp

@ -30,7 +30,14 @@ boost::random_device dev::s_fixedHashEngine;
h128 dev::fromUUID(std::string const& _uuid)
{
try
{
return h128(boost::replace_all_copy(_uuid, "-", ""));
}
catch (...)
{
return h128();
}
}
std::string dev::toUUID(h128 const& _uuid)

3
libdevcore/vector_ref.h

@ -71,7 +71,7 @@ public:
{
static unsigned char s_cleanseCounter = 0;
uint8_t* p = (uint8_t*)begin();
size_t len = (uint8_t*)end() - p;
size_t const len = (uint8_t*)end() - p;
size_t loop = len;
size_t count = s_cleanseCounter;
while (loop--)
@ -83,6 +83,7 @@ public:
if (p)
count += (63 + (size_t)p);
s_cleanseCounter = (uint8_t)count;
memset((uint8_t*)begin(), 0, len);
}
_T* begin() { return m_data; }

14
libdevcrypto/SecretStore.cpp

@ -107,6 +107,14 @@ bytesSec SecretStore::secret(h128 const& _uuid, function<string()> const& _pass,
return key;
}
bytesSec SecretStore::secret(string const& _content, string const& _pass)
{
js::mValue u = upgraded(_content);
if (u.type() != js::obj_type)
return bytesSec();
return decrypt(js::write_string(u.get_obj()["crypto"], false), _pass);
}
h128 SecretStore::importSecret(bytesSec const& _s, string const& _pass)
{
h128 r;
@ -169,11 +177,13 @@ void SecretStore::save(string const& _keysPath)
void SecretStore::load(string const& _keysPath)
{
fs::path p(_keysPath);
fs::create_directories(p);
DEV_IGNORE_EXCEPTIONS(fs::permissions(p, fs::owner_all));
try
{
for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it)
if (fs::is_regular_file(it->path()))
readKey(it->path().string(), true);
}
catch (...) {}
}
h128 SecretStore::readKey(string const& _file, bool _takeFileOwnership)

3
libdevcrypto/SecretStore.h

@ -53,6 +53,9 @@ public:
/// @param _pass function that returns the password for the key.
/// @param _useCache if true, allow previously decrypted keys to be returned directly.
bytesSec secret(h128 const& _uuid, std::function<std::string()> const& _pass, bool _useCache = true) const;
/// @returns the secret key stored by the given @a _uuid.
/// @param _pass function that returns the password for the key.
static bytesSec secret(std::string const& _content, std::string const& _pass);
/// Imports the (encrypted) key stored in the file @a _file and copies it to the managed directory.
h128 importKey(std::string const& _file) { auto ret = readKey(_file, false); if (ret) save(); return ret; }
/// Imports the (encrypted) key contained in the json formatted @a _content and stores it in

4
libethcore/Common.cpp

@ -112,14 +112,14 @@ std::string formatBalance(bigint const& _b)
else
b = (u256)_b;
if (b > units()[0].first * 10000)
if (b > units()[0].first * 1000)
{
ret << (b / units()[0].first) << " " << units()[0].second;
return ret.str();
}
ret << setprecision(5);
for (auto const& i: units())
if (i.first != 1 && b >= i.first * 100)
if (i.first != 1 && b >= i.first * 1)
{
ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second;
return ret.str();

17
libethcore/KeyManager.cpp

@ -224,6 +224,16 @@ Secret KeyManager::brain(string const& _seed)
return ret;
}
Secret KeyManager::subkey(Secret const& _s, unsigned _index)
{
RLPStream out(2);
out << _s.ref();
out << _index;
bytesSec r;
out.swapOut(r.writable());
return sha3(r);
}
Address KeyManager::importBrain(string const& _seed, string const& _accountName, string const& _passwordHint)
{
Address addr = toAddress(brain(_seed));
@ -233,6 +243,13 @@ Address KeyManager::importBrain(string const& _seed, string const& _accountName,
return addr;
}
void KeyManager::importExistingBrain(Address const& _a, string const& _accountName, string const& _passwordHint)
{
m_keyInfo[_a].accountName = _accountName;
m_keyInfo[_a].passwordHint = _passwordHint;
write();
}
void KeyManager::importExisting(h128 const& _uuid, string const& _info, string const& _pass, string const& _passwordHint)
{
bytesSec key = m_store.secret(_uuid, [&](){ return _pass; });

6
libethcore/KeyManager.h

@ -108,6 +108,7 @@ public:
h128 import(Secret const& _s, std::string const& _accountName, std::string const& _pass, std::string const& _passwordHint);
h128 import(Secret const& _s, std::string const& _accountName) { return import(_s, _accountName, defaultPassword(), std::string()); }
Address importBrain(std::string const& _seed, std::string const& _accountName, std::string const& _seedHint);
void importExistingBrain(Address const& _a, std::string const& _accountName, std::string const& _seedHint);
SecretStore& store() { return m_store; }
void importExisting(h128 const& _uuid, std::string const& _accountName, std::string const& _pass, std::string const& _passwordHint);
@ -130,11 +131,14 @@ public:
static std::string defaultPath() { return getDataDir("ethereum") + "/keys.info"; }
/// Extracts the secret key from the presale wallet.
KeyPair presaleSecret(std::string const& _json, std::function<std::string(bool)> const& _password);
static KeyPair presaleSecret(std::string const& _json, std::function<std::string(bool)> const& _password);
/// @returns the brainwallet secret for the given seed.
static Secret brain(std::string const& _seed);
/// @returns the HD subkey for a given key.
static Secret subkey(Secret const& _s, unsigned _index);
private:
std::string getPassword(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow) const;
std::string getPassword(h256 const& _passHash, std::function<std::string()> const& _pass = DontKnowThrow) const;

22
libethereum/ExtVM.cpp

@ -35,13 +35,20 @@ static unsigned const c_depthLimit = 1024;
/// Upper bound of stack space needed by single CALL/CREATE execution. Set experimentally.
static size_t const c_singleExecutionStackSize =
#ifdef NDEBUG
12 * 1024;
10 * 1024;
#else
33 * 1024;
16 * 1024;
#endif
/// Standard OSX thread stack limit. Should be reasonable for other platforms too.
static size_t const c_defaultStackSize = 512 * 1024;
/// Standard thread stack size.
static size_t const c_defaultStackSize =
#if defined(__linux)
8 * 1024 * 1024;
#elif defined(_WIN32)
16 * 1024 * 1024;
#else
512 * 1024; // OSX and other OSs
#endif
/// Stack overhead prior to allocation.
static size_t const c_entryOverhead = 128 * 1024;
@ -80,7 +87,10 @@ void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp)
// the rest of the calls up to the depth limit (c_depthLimit).
if (_depth == c_offloadPoint)
{
cnote << "Stack offloading (depth: " << c_offloadPoint << ")";
goOnOffloadedStack(_e, _onOp);
}
else
_e.go(_onOp);
}
@ -91,11 +101,7 @@ bool ExtVM::call(CallParameters& _p)
Executive e(m_s, envInfo(), depth + 1);
if (!e.call(_p, gasPrice, origin))
{
#if __clang__ // Enabled for clang only as the problem affects OSX
go(depth, e, _p.onOp);
#else
e.go(_p.onOp);
#endif
e.accrueSubState(sub);
}
_p.gas = e.gas();

5
libethereum/TransactionQueue.cpp

@ -294,6 +294,7 @@ void TransactionQueue::setFuture(h256 const& _txHash)
void TransactionQueue::makeCurrent_WITH_LOCK(Transaction const& _t)
{
bool newCurrent = false;
auto fs = m_future.find(_t.from());
if (fs != m_future.end())
{
@ -311,6 +312,7 @@ void TransactionQueue::makeCurrent_WITH_LOCK(Transaction const& _t)
--m_futureSize;
++ft;
++nonce;
newCurrent = true;
}
fs->second.erase(fb, ft);
if (fs->second.empty())
@ -328,6 +330,9 @@ void TransactionQueue::makeCurrent_WITH_LOCK(Transaction const& _t)
if (m_future.begin()->second.empty())
m_future.erase(m_future.begin());
}
if (newCurrent)
m_onReady();
}
void TransactionQueue::drop(h256 const& _txHash)

1
libevmasm/CMakeLists.txt

@ -20,7 +20,6 @@ else()
endif()
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcrypto)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

24
libjsqrc/ethereumjs/dist/web3-light.js

@ -4577,12 +4577,34 @@ var addToGroup = new Method({
params: 0
});
var newFilter = new Method({
name: 'newFilter',
call: 'shh_newFilter',
params: 1
});
var getFilterChanges = new Method({
name: 'getFilterChanges',
call: 'shh_getFilterChanges',
params: 1
});
var getMessages = new Method({
name: 'getMessages',
call: 'shh_getMessages',
params: 1
})
var methods = [
post,
newIdentity,
hasIdentity,
newGroup,
addToGroup
addToGroup,
newFilter,
getFilterChanges,
getMessages
];
module.exports = {

4
libjsqrc/ethereumjs/dist/web3-light.min.js

File diff suppressed because one or more lines are too long

24
libjsqrc/ethereumjs/dist/web3.js

@ -4577,12 +4577,34 @@ var addToGroup = new Method({
params: 0
});
var newFilter = new Method({
name: 'newFilter',
call: 'shh_newFilter',
params: 1
});
var getFilterChanges = new Method({
name: 'getFilterChanges',
call: 'shh_getFilterChanges',
params: 1
});
var getMessages = new Method({
name: 'getMessages',
call: 'shh_getMessages',
params: 1
})
var methods = [
post,
newIdentity,
hasIdentity,
newGroup,
addToGroup
addToGroup,
newFilter,
getFilterChanges,
getMessages
];
module.exports = {

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

File diff suppressed because one or more lines are too long

4
libjsqrc/ethereumjs/dist/web3.min.js

File diff suppressed because one or more lines are too long

24
libjsqrc/ethereumjs/lib/web3/shh.js

@ -54,12 +54,34 @@ var addToGroup = new Method({
params: 0
});
var newFilter = new Method({
name: 'newFilter',
call: 'shh_newFilter',
params: 1
});
var getFilterChanges = new Method({
name: 'getFilterChanges',
call: 'shh_getFilterChanges',
params: 1
});
var getMessages = new Method({
name: 'getMessages',
call: 'shh_getMessages',
params: 1
})
var methods = [
post,
newIdentity,
hasIdentity,
newGroup,
addToGroup
addToGroup,
newFilter,
getFilterChanges,
getMessages
];
module.exports = {

24
mix/qml/Block.qml

@ -23,6 +23,11 @@ ColumnLayout
property int blockIndex
property variant scenario
property string labelColor: "#414141"
property string selectedBlockColor: "#accbf2"
property string selectedBlockForeground: "#445e7f"
property int scenarioIndex
signal txSelected(var txIndex)
@ -105,14 +110,15 @@ ColumnLayout
}
}
Label
{
text: qsTr("EDIT")
color: "#1397da"
Image {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 14
visible: number === -2
source: "qrc:/qml/img/edit_combox.png"
height: 15
fillMode: Image.PreserveAspectFit
MouseArea
{
anchors.fill: parent
@ -122,6 +128,7 @@ ColumnLayout
projectModel.stateListModel.editState(scenarioIndex)
}
}
}
}
}
@ -238,10 +245,11 @@ ColumnLayout
function select()
{
rowContentTr.selected = true
rowContentTr.color = "#4F4F4F"
hash.color = "#EAB920"
func.color = "#EAB920"
rowContentTr.color = selectedBlockColor
hash.color = selectedBlockForeground
func.color = selectedBlockForeground
txSelected(index)
}
function deselect()
@ -345,7 +353,7 @@ ColumnLayout
Image {
id: debugImg
source: "qrc:/qml/img/rightarrow@2x.png"
source: "qrc:/qml/img/rightarrowcircle.png"
width: debugActionWidth
fillMode: Image.PreserveAspectFit
anchors.horizontalCenter: parent.horizontalCenter

21
mix/qml/Watchers.qml

@ -12,13 +12,16 @@ import "js/QEtherHelper.js" as QEtherHelper
import "."
Rectangle {
color: "#4F4F4F"
color: selectedBlockColor
property variant tx
property variant currentState
property variant bc
property var blockIndex
property var txIndex
property string selectedBlockColor: "#accbf2"
property string selectedBlockForeground: "#445e7f"
function clear()
{
from.text = ""
@ -83,11 +86,11 @@ Rectangle {
id: fromLabel
text: qsTr("from")
visible: false
color: "#EAB920"
color: selectedBlockForeground
}
Label {
id: from
color: "#EAB920"
color: selectedBlockForeground
elide: Text.ElideRight
maximumLineCount: 1
clip: true
@ -97,11 +100,11 @@ Rectangle {
id: toLabel
text: qsTr("to")
visible: false
color: "#EAB920"
color: selectedBlockForeground
}
Label {
id: to
color: "#EAB920"
color: selectedBlockForeground
elide: Text.ElideRight
maximumLineCount: 1
clip: true
@ -109,7 +112,7 @@ Rectangle {
}
Label {
id: value
color: "#EAB920"
color: selectedBlockForeground
font.italic: true
clip: true
}
@ -118,9 +121,9 @@ Rectangle {
Image {
anchors.right: rowHeader.parent.right
anchors.top: rowHeader.parent.top
anchors.topMargin: -3
source: "qrc:/qml/img/edittransaction2.png"
height: 30
anchors.topMargin: 5
source: "qrc:/qml/img/edit_combox.png"
height: 15
fillMode: Image.PreserveAspectFit
visible: from.text !== ""
MouseArea

BIN
mix/qml/img/rightarrowcircle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

1
mix/res.qrc

@ -86,6 +86,7 @@
<file>qml/img/restoreicon@2x.png</file>
<file>qml/img/rightarrow.png</file>
<file>qml/img/rightarrow@2x.png</file>
<file>qml/img/rightarrowcircle.png</file>
<file>qml/img/saveicon.png</file>
<file>qml/img/saveicon@2x.png</file>
<file>qml/img/sendtransactionicon.png</file>

4
templates/dockplugin.cpp

@ -14,11 +14,13 @@
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 $NAME.h
/** @file $NAME.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
DEV_AZ_NOTE_PLUGIN($NAME);
#include "$NAME.h"
#include <libdevcore/Log.h>
#include <libethereum/Client.h>

4
templates/plugin.cpp

@ -14,7 +14,7 @@
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 $NAME.h
/** @file $NAME.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
@ -27,6 +27,8 @@ using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN($NAME);
$NAME::$NAME(MainFace* _m):
Plugin(_m, "$NAME")
{

25
test/libdevcrypto/SecretStore.cpp

@ -131,6 +131,31 @@ BOOST_AUTO_TEST_CASE(import_secret)
}
}
BOOST_AUTO_TEST_CASE(import_secret_bytesConstRef)
{
for (string const& password: {"foobar", ""})
{
TransientDirectory storeDir;
string priv = "0202020202020202020202020202020202020202020202020202020202020202";
h128 uuid;
{
SecretStore store(storeDir.path());
BOOST_CHECK_EQUAL(store.keys().size(), 0);
bytes privateBytes = fromHex(priv);
uuid = store.importSecret(&privateBytes, password);
BOOST_CHECK(!!uuid);
BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
BOOST_CHECK_EQUAL(store.keys().size(), 1);
}
{
SecretStore store(storeDir.path());
BOOST_CHECK_EQUAL(store.keys().size(), 1);
BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
}
}
}
BOOST_AUTO_TEST_CASE(wrong_password)
{
TransientDirectory storeDir;

39
test/libethereum/StateTestsFiller/stSpecialTestFiller.json

@ -531,5 +531,44 @@
"to" : "1baf27b88c48dd02b744999cf3522766929d2b2a",
"value" : "0"
}
},
"StackDepthLimitSEC" : {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "1000000000000000000"
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "771500"
},
"aaaaaaaaace5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "100000000",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "1000000",
"to" : "",
"value" : "10",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : "305032503350600460006000396000515060046000600037600051506f600060006000600060003060405a03f160005260106010f3"
}
}
}

Loading…
Cancel
Save