arkpar
10 years ago
14 changed files with 797 additions and 188 deletions
@ -0,0 +1,183 @@ |
|||||
|
/*
|
||||
|
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 ExportState.cpp
|
||||
|
* @author Arkadiy Paronyan <arkadiy@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include "ExportState.h" |
||||
|
#include <QFileDialog> |
||||
|
#include <QTextStream> |
||||
|
#include <libethereum/Client.h> |
||||
|
#include "MainWin.h" |
||||
|
#include "ui_ExportState.h" |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
ExportStateDialog::ExportStateDialog(Main* _parent): |
||||
|
QDialog(_parent), |
||||
|
ui(new Ui::ExportState), |
||||
|
m_main(_parent) |
||||
|
{ |
||||
|
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); |
||||
|
fillBlocks(); |
||||
|
} |
||||
|
|
||||
|
ExportStateDialog::~ExportStateDialog() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
dev::eth::Client* ExportStateDialog::ethereum() const |
||||
|
{ |
||||
|
return m_main->ethereum(); |
||||
|
} |
||||
|
|
||||
|
void ExportStateDialog::on_block_editTextChanged() |
||||
|
{ |
||||
|
QString text = ui->block->currentText(); |
||||
|
int i = ui->block->count(); |
||||
|
while (i-- >= 0) |
||||
|
if (ui->block->itemText(i) == text) |
||||
|
return; |
||||
|
fillBlocks(); |
||||
|
} |
||||
|
|
||||
|
void ExportStateDialog::on_block_currentIndexChanged(int _index) |
||||
|
{ |
||||
|
m_block = 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); |
||||
|
const unsigned numLastBlocks = 10; |
||||
|
if (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); |
||||
|
if (h == bc.genesisHash()) |
||||
|
break; |
||||
|
} |
||||
|
if (ui->block->currentIndex() < 0) |
||||
|
ui->block->setCurrentIndex(0); |
||||
|
m_recentBlocks = numLastBlocks - i; |
||||
|
} |
||||
|
|
||||
|
int i = ui->block->count(); |
||||
|
while (i > 0 && i >= m_recentBlocks) |
||||
|
ui->block->removeItem(i--); |
||||
|
|
||||
|
h256Set blocks; |
||||
|
for (QString f: filters) |
||||
|
{ |
||||
|
if (f.startsWith("#")) |
||||
|
f = f.remove(0, 1); |
||||
|
if (f.size() == 64) |
||||
|
{ |
||||
|
h256 h(f.toStdString()); |
||||
|
if (bc.isKnown(h)) |
||||
|
blocks.insert(h); |
||||
|
for (auto const& b: bc.withBlockBloom(LogBloom().shiftBloom<3>(sha3(h)), 0, -1)) |
||||
|
blocks.insert(bc.numberHash(b)); |
||||
|
} |
||||
|
else if (f.toLongLong() <= bc.number()) |
||||
|
blocks.insert(bc.numberHash((unsigned)f.toLongLong())); |
||||
|
else if (f.size() == 40) |
||||
|
{ |
||||
|
Address h(f.toStdString()); |
||||
|
for (auto const& b: bc.withBlockBloom(LogBloom().shiftBloom<3>(sha3(h)), 0, -1)) |
||||
|
blocks.insert(bc.numberHash(b)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExportStateDialog::fillContracts() |
||||
|
{ |
||||
|
ui->accounts->clear(); |
||||
|
ui->contracts->clear(); |
||||
|
ui->accounts->setEnabled(true); |
||||
|
ui->contracts->setEnabled(true); |
||||
|
for (auto i: ethereum()->addresses(m_block)) |
||||
|
{ |
||||
|
QString r = m_main->render(i); |
||||
|
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts)) |
||||
|
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExportStateDialog::generateJSON() |
||||
|
{ |
||||
|
std::stringstream json; |
||||
|
json << "{\n"; |
||||
|
std::string prefix; |
||||
|
for(QListWidgetItem* item: 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()) |
||||
|
{ |
||||
|
auto hba = item->data(Qt::UserRole).toByteArray(); |
||||
|
auto address = Address((byte const*)hba.data(), Address::ConstructFromPointer); |
||||
|
json << prefix << "\t\"" << toHex(address.ref()) << "\":\n\t{\n\t\t\"wei\": \"" << ethereum()->balanceAt(address, m_block) << "\",\n"; |
||||
|
json << "\t\t\"code\": \"" << toHex(ethereum()->codeAt(address, m_block)) << "\",\n"; |
||||
|
std::map<u256, u256> storage = ethereum()->storageAt(address, m_block); |
||||
|
if (!storage.empty()) |
||||
|
{ |
||||
|
json << "\t\t\"storage\":\n\t\t{\n"; |
||||
|
for (auto s: storage) |
||||
|
json << "\t\t\t\"" << toHex(s.first) << "\": \"" << toHex(s.second) << "\"" << (s.first == storage.rbegin()->first ? "" : ",") <<"\n"; |
||||
|
json << "\t\t}\n"; |
||||
|
} |
||||
|
json << "\t}"; |
||||
|
prefix = ",\n"; |
||||
|
} |
||||
|
json << "\n}"; |
||||
|
json.flush(); |
||||
|
|
||||
|
ui->json->setEnabled(true); |
||||
|
ui->json->setText(QString::fromStdString(json.str())); |
||||
|
ui->saveButton->setEnabled(true); |
||||
|
} |
||||
|
|
||||
|
void ExportStateDialog::on_saveButton_clicked() |
||||
|
{ |
||||
|
QString fn = QFileDialog::getSaveFileName(this, "Save state", QString(), "JSON Files (*.json)"); |
||||
|
if (!fn.endsWith(".json")) |
||||
|
fn = fn.append(".json"); |
||||
|
ofstream file(fn.toStdString()); |
||||
|
if (file.is_open()) |
||||
|
file << ui->json->toPlainText().toStdString(); |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
/*
|
||||
|
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 ExportState.h
|
||||
|
* @author Arkadiy Paronyan <arkadiy@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <memory> |
||||
|
#include <QDialog> |
||||
|
#include <libethcore/Common.h> |
||||
|
|
||||
|
namespace Ui { class ExportState; } |
||||
|
namespace dev { namespace eth { class Client; } } |
||||
|
|
||||
|
class Main; |
||||
|
|
||||
|
class ExportStateDialog: public QDialog |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
|
||||
|
public: |
||||
|
explicit ExportStateDialog(Main* _parent = 0); |
||||
|
virtual ~ExportStateDialog(); |
||||
|
|
||||
|
private slots: |
||||
|
void on_block_editTextChanged(); |
||||
|
void on_block_currentIndexChanged(int _index); |
||||
|
void on_saveButton_clicked(); |
||||
|
|
||||
|
private: |
||||
|
dev::eth::Client* ethereum() const; |
||||
|
void fillBlocks(); |
||||
|
void fillContracts(); |
||||
|
void generateJSON(); |
||||
|
|
||||
|
private: |
||||
|
std::unique_ptr<Ui::ExportState> ui; |
||||
|
Main* m_main; |
||||
|
int m_recentBlocks = 0; |
||||
|
dev::eth::BlockNumber m_block = dev::eth::LatestBlock; |
||||
|
}; |
@ -0,0 +1,183 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>ExportState</class> |
||||
|
<widget class="QDialog" name="ExportState"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>490</width> |
||||
|
<height>522</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Export State</string> |
||||
|
</property> |
||||
|
<property name="modal"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<layout class="QGridLayout" name="gridLayout"> |
||||
|
<item row="0" 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>&Block</string> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>block</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="QComboBox" name="block"> |
||||
|
<property name="editable"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="currentText"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="0"> |
||||
|
<widget class="QLabel" name="label_7"> |
||||
|
<property name="text"> |
||||
|
<string>&Accounts</string> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>accounts</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="1"> |
||||
|
<widget class="QListWidget" name="accounts"> |
||||
|
<property name="enabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>1</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="selectionMode"> |
||||
|
<enum>QAbstractItemView::MultiSelection</enum> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="0"> |
||||
|
<widget class="QLabel" name="label_6"> |
||||
|
<property name="text"> |
||||
|
<string>&Contracts</string> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>contracts</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="1"> |
||||
|
<widget class="QListWidget" name="contracts"> |
||||
|
<property name="enabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>1</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="selectionMode"> |
||||
|
<enum>QAbstractItemView::MultiSelection</enum> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" 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>&JSON</string> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>json</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="1"> |
||||
|
<widget class="QTextEdit" name="json"> |
||||
|
<property name="enabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>2</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" column="1"> |
||||
|
<layout class="QHBoxLayout" name="horizontalLayout"> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="saveButton"> |
||||
|
<property name="enabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>&Save...</string> |
||||
|
</property> |
||||
|
<property name="shortcut"> |
||||
|
<string>Esc</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="close"> |
||||
|
<property name="text"> |
||||
|
<string>&Close</string> |
||||
|
</property> |
||||
|
<property name="shortcut"> |
||||
|
<string>Esc</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
Loading…
Reference in new issue