Browse Source
Conflicts: README.md evmjit libdevcrypto/CryptoPP.cpp libethereum/State.cpp neth/main.cppcl-refactor
Gav Wood
10 years ago
549 changed files with 60144 additions and 12099 deletions
@ -0,0 +1,7 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#define ETH_COMMIT_HASH @ETH_COMMIT_HASH@ |
||||
|
#define ETH_CLEAN_REPO @ETH_CLEAN_REPO@ |
||||
|
#define ETH_BUILD_TYPE @ETH_BUILD_TYPE@ |
||||
|
#define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@ |
||||
|
|
@ -1,55 +0,0 @@ |
|||||
CURRENT_SOURCE_DIR=$1 |
|
||||
CURRENT_BINARY_DIR=$2 |
|
||||
BUILD_TYPE=$3 |
|
||||
BUILD_PLATFORM=$4 |
|
||||
|
|
||||
echo "Current source dir: $CURRENT_SOURCE_DIR" |
|
||||
echo "Current binary dir: $CURRENT_BINARY_DIR" |
|
||||
echo "Build type: $BUILD_TYPE" |
|
||||
echo "Build platform: $BUILD_PLATFORM" |
|
||||
|
|
||||
if [[ -e "$CURRENT_SOURCE_DIR/BuildInfo.h" ]] |
|
||||
then |
|
||||
echo "Using existing BuildInfo.h" |
|
||||
cp $CURRENT_SOURCE_DIR/BuildInfo.h $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
else |
|
||||
if [[ -e "$CURRENT_SOURCE_DIR/.git" ]] |
|
||||
then |
|
||||
ETH_COMMIT_HASH=$(git --git-dir=$CURRENT_SOURCE_DIR/.git --work-tree=$CURRENT_SOURCE_DIR rev-parse HEAD) |
|
||||
ETH_LOCAL_CHANGES=$(git --git-dir=$CURRENT_SOURCE_DIR/.git --work-tree=$CURRENT_SOURCE_DIR diff --shortstat) |
|
||||
if [[ -z "$ETH_LOCAL_CHANGES" ]] |
|
||||
then |
|
||||
ETH_CLEAN_REPO=1 |
|
||||
else |
|
||||
ETH_CLEAN_REPO=0 |
|
||||
fi |
|
||||
|
|
||||
echo "Commit hash: ${ETH_COMMIT_HASH} (Clean: ${ETH_CLEAN_REPO} - ${ETH_LOCAL_CHANGES})" |
|
||||
else |
|
||||
echo "Unknown repo." |
|
||||
ETH_COMMIT_HASH=0 |
|
||||
ETH_CLEAN_REPO=1 |
|
||||
fi |
|
||||
|
|
||||
echo "// This file was automatically generated by cmake" > $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "#pragma once" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "#define ETH_COMMIT_HASH $ETH_COMMIT_HASH" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "#define ETH_CLEAN_REPO $ETH_CLEAN_REPO" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "#define ETH_BUILD_TYPE $BUILD_TYPE" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
echo "#define ETH_BUILD_PLATFORM $BUILD_PLATFORM" >> $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
fi |
|
||||
|
|
||||
if [[ -e "$CURRENT_BINARY_DIR/BuildInfo.h" ]] |
|
||||
then |
|
||||
DIFF=$(diff $CURRENT_BINARY_DIR/BuildInfo.h $CURRENT_BINARY_DIR/BuildInfo.h.tmp) |
|
||||
if [[ -z "$DIFF" ]] |
|
||||
then |
|
||||
rm $CURRENT_BINARY_DIR/BuildInfo.h.tmp |
|
||||
else |
|
||||
mv $CURRENT_BINARY_DIR/BuildInfo.h.tmp $CURRENT_BINARY_DIR/BuildInfo.h |
|
||||
fi |
|
||||
else |
|
||||
mv $CURRENT_BINARY_DIR/BuildInfo.h.tmp $CURRENT_BINARY_DIR/BuildInfo.h |
|
||||
fi |
|
@ -0,0 +1,59 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file Debugger.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include "Context.h" |
||||
|
#include <QComboBox> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
NatSpecFace::~NatSpecFace() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
Context::~Context() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
void initUnits(QComboBox* _b) |
||||
|
{ |
||||
|
for (auto n = (unsigned)units().size(); n-- != 0; ) |
||||
|
_b->addItem(QString::fromStdString(units()[n].second), n); |
||||
|
} |
||||
|
|
||||
|
vector<KeyPair> keysAsVector(QList<KeyPair> const& keys) |
||||
|
{ |
||||
|
auto list = keys.toStdList(); |
||||
|
return {begin(list), end(list)}; |
||||
|
} |
||||
|
|
||||
|
bool sourceIsSolidity(string const& _source) |
||||
|
{ |
||||
|
// TODO: Improve this heuristic
|
||||
|
return (_source.substr(0, 8) == "contract" || _source.substr(0, 5) == "//sol"); |
||||
|
} |
||||
|
|
||||
|
bool sourceIsSerpent(string const& _source) |
||||
|
{ |
||||
|
// TODO: Improve this heuristic
|
||||
|
return (_source.substr(0, 5) == "//ser"); |
||||
|
} |
@ -0,0 +1,68 @@ |
|||||
|
/*
|
||||
|
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 Debugger.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
#include <QString> |
||||
|
#include <QList> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
|
||||
|
class QComboBox; |
||||
|
|
||||
|
namespace dev { namespace eth { struct StateDiff; } } |
||||
|
|
||||
|
#define Small "font-size: small; " |
||||
|
#define Mono "font-family: Ubuntu Mono, Monospace, Lucida Console, Courier New; font-weight: bold; " |
||||
|
#define Div(S) "<div style=\"" S "\">" |
||||
|
#define Span(S) "<span style=\"" S "\">" |
||||
|
|
||||
|
void initUnits(QComboBox* _b); |
||||
|
|
||||
|
std::vector<dev::KeyPair> keysAsVector(QList<dev::KeyPair> const& _keys); |
||||
|
|
||||
|
bool sourceIsSolidity(std::string const& _source); |
||||
|
bool sourceIsSerpent(std::string const& _source); |
||||
|
|
||||
|
class NatSpecFace |
||||
|
{ |
||||
|
public: |
||||
|
virtual ~NatSpecFace(); |
||||
|
|
||||
|
virtual void add(dev::h256 const& _contractHash, std::string const& _doc) = 0; |
||||
|
virtual std::string retrieve(dev::h256 const& _contractHash) const = 0; |
||||
|
virtual std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData) = 0; |
||||
|
virtual std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta) = 0; |
||||
|
}; |
||||
|
|
||||
|
class Context |
||||
|
{ |
||||
|
public: |
||||
|
virtual ~Context(); |
||||
|
|
||||
|
virtual QString pretty(dev::Address _a) const = 0; |
||||
|
virtual QString prettyU256(dev::u256 _n) const = 0; |
||||
|
virtual QString render(dev::Address _a) const = 0; |
||||
|
virtual dev::Address fromString(QString const& _a) const = 0; |
||||
|
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0; |
||||
|
}; |
||||
|
|
@ -0,0 +1,380 @@ |
|||||
|
/*
|
||||
|
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 Debugger.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include "Debugger.h" |
||||
|
|
||||
|
#include <fstream> |
||||
|
#include <QFileDialog> |
||||
|
#include <libevm/VM.h> |
||||
|
#include <libethereum/ExtVM.h> |
||||
|
#include <libethereum/Executive.h> |
||||
|
#include "ui_Debugger.h" |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
Debugger::Debugger(Context* _c, QWidget* _parent): |
||||
|
QDialog(_parent), |
||||
|
ui(new Ui::Debugger), |
||||
|
m_context(_c) |
||||
|
{ |
||||
|
ui->setupUi(this); |
||||
|
} |
||||
|
|
||||
|
Debugger::~Debugger() |
||||
|
{ |
||||
|
delete ui; |
||||
|
} |
||||
|
|
||||
|
void Debugger::init() |
||||
|
{ |
||||
|
if (m_session.history.size()) |
||||
|
{ |
||||
|
alterDebugStateGroup(true); |
||||
|
ui->debugCode->setEnabled(false); |
||||
|
ui->debugTimeline->setMinimum(0); |
||||
|
ui->debugTimeline->setMaximum(m_session.history.size()); |
||||
|
ui->debugTimeline->setValue(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Debugger::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction) |
||||
|
{ |
||||
|
finished(); |
||||
|
if (m_session.populate(_executive, _transaction)) |
||||
|
init(); |
||||
|
update(); |
||||
|
} |
||||
|
|
||||
|
bool DebugSession::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction) |
||||
|
{ |
||||
|
try { |
||||
|
if (_executive.setup(_transaction)) |
||||
|
return false; |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
// Invalid transaction
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
vector<WorldState const*> levels; |
||||
|
bytes lastExtCode; |
||||
|
bytesConstRef lastData; |
||||
|
h256 lastHash; |
||||
|
h256 lastDataHash; |
||||
|
auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, VM* voidVM, ExtVMFace const* voidExt) |
||||
|
{ |
||||
|
VM& vm = *voidVM; |
||||
|
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt); |
||||
|
if (ext.code != lastExtCode) |
||||
|
{ |
||||
|
lastExtCode = ext.code; |
||||
|
lastHash = sha3(lastExtCode); |
||||
|
if (!codes.count(lastHash)) |
||||
|
codes[lastHash] = ext.code; |
||||
|
} |
||||
|
if (ext.data != lastData) |
||||
|
{ |
||||
|
lastData = ext.data; |
||||
|
lastDataHash = sha3(lastData); |
||||
|
if (!codes.count(lastDataHash)) |
||||
|
codes[lastDataHash] = ext.data.toBytes(); |
||||
|
} |
||||
|
if (levels.size() < ext.depth) |
||||
|
levels.push_back(&history.back()); |
||||
|
else |
||||
|
levels.resize(ext.depth); |
||||
|
history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); |
||||
|
}; |
||||
|
_executive.go(onOp); |
||||
|
_executive.finalize(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void Debugger::finished() |
||||
|
{ |
||||
|
m_session = DebugSession(); |
||||
|
ui->callStack->clear(); |
||||
|
ui->debugCode->clear(); |
||||
|
ui->debugStack->clear(); |
||||
|
ui->debugMemory->setHtml(""); |
||||
|
ui->debugStorage->setHtml(""); |
||||
|
ui->debugStateInfo->setText(""); |
||||
|
alterDebugStateGroup(false); |
||||
|
} |
||||
|
|
||||
|
void Debugger::update() |
||||
|
{ |
||||
|
if (m_session.history.size()) |
||||
|
{ |
||||
|
WorldState const& nws = m_session.history[min((int)m_session.history.size() - 1, ui->debugTimeline->value())]; |
||||
|
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws; |
||||
|
|
||||
|
if (ui->debugTimeline->value() >= m_session.history.size()) |
||||
|
{ |
||||
|
if (ws.gasCost > ws.gas) |
||||
|
ui->debugMemory->setHtml("<h3>OUT-OF-GAS</h3>"); |
||||
|
else if (ws.inst == Instruction::RETURN && ws.stack.size() >= 2) |
||||
|
{ |
||||
|
unsigned from = (unsigned)ws.stack.back(); |
||||
|
unsigned size = (unsigned)ws.stack[ws.stack.size() - 2]; |
||||
|
unsigned o = 0; |
||||
|
bytes out(size, 0); |
||||
|
for (; o < size && from + o < ws.memory.size(); ++o) |
||||
|
out[o] = ws.memory[from + o]; |
||||
|
ui->debugMemory->setHtml("<h3>RETURN</h3>" + QString::fromStdString(dev::memDump(out, 16, true))); |
||||
|
} |
||||
|
else if (ws.inst == Instruction::STOP) |
||||
|
ui->debugMemory->setHtml("<h3>STOP</h3>"); |
||||
|
else if (ws.inst == Instruction::SUICIDE && ws.stack.size() >= 1) |
||||
|
ui->debugMemory->setHtml("<h3>SUICIDE</h3>0x" + QString::fromStdString(toString(right160(ws.stack.back())))); |
||||
|
else |
||||
|
ui->debugMemory->setHtml("<h3>EXCEPTION</h3>"); |
||||
|
|
||||
|
ostringstream ss; |
||||
|
ss << dec << "EXIT | GAS: " << dec << max<dev::bigint>(0, (dev::bigint)ws.gas - ws.gasCost); |
||||
|
ui->debugStateInfo->setText(QString::fromStdString(ss.str())); |
||||
|
ui->debugStorage->setHtml(""); |
||||
|
ui->debugCallData->setHtml(""); |
||||
|
m_session.currentData = h256(); |
||||
|
ui->callStack->clear(); |
||||
|
m_session.currentLevels.clear(); |
||||
|
ui->debugCode->clear(); |
||||
|
m_session.currentCode = h256(); |
||||
|
ui->debugStack->setHtml(""); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (m_session.currentLevels != nws.levels || !ui->callStack->count()) |
||||
|
{ |
||||
|
m_session.currentLevels = nws.levels; |
||||
|
ui->callStack->clear(); |
||||
|
for (unsigned i = 0; i <= nws.levels.size(); ++i) |
||||
|
{ |
||||
|
WorldState const& s = i ? *nws.levels[nws.levels.size() - i] : nws; |
||||
|
ostringstream out; |
||||
|
out << s.cur.abridged(); |
||||
|
if (i) |
||||
|
out << " " << instructionInfo(s.inst).name << " @0x" << hex << s.curPC; |
||||
|
ui->callStack->addItem(QString::fromStdString(out.str())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (ws.code != m_session.currentCode) |
||||
|
{ |
||||
|
m_session.currentCode = ws.code; |
||||
|
bytes const& code = m_session.codes[ws.code]; |
||||
|
QListWidget* dc = ui->debugCode; |
||||
|
dc->clear(); |
||||
|
m_session.pcWarp.clear(); |
||||
|
for (unsigned i = 0; i <= code.size(); ++i) |
||||
|
{ |
||||
|
byte b = i < code.size() ? code[i] : 0; |
||||
|
try |
||||
|
{ |
||||
|
QString s = QString::fromStdString(instructionInfo((Instruction)b).name); |
||||
|
ostringstream out; |
||||
|
out << hex << setw(4) << setfill('0') << i; |
||||
|
m_session.pcWarp[i] = dc->count(); |
||||
|
if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) |
||||
|
{ |
||||
|
unsigned bc = b - (byte)Instruction::PUSH1 + 1; |
||||
|
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); |
||||
|
i += bc; |
||||
|
} |
||||
|
dc->addItem(QString::fromStdString(out.str()) + " " + s); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Unhandled exception!" << endl << boost::current_exception_diagnostic_information(); |
||||
|
break; // probably hit data segment
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (ws.callData != m_session.currentData) |
||||
|
{ |
||||
|
m_session.currentData = ws.callData; |
||||
|
if (ws.callData) |
||||
|
{ |
||||
|
assert(m_session.codes.count(ws.callData)); |
||||
|
ui->debugCallData->setHtml(QString::fromStdString(dev::memDump(m_session.codes[ws.callData], 16, true))); |
||||
|
} |
||||
|
else |
||||
|
ui->debugCallData->setHtml(""); |
||||
|
} |
||||
|
|
||||
|
QString stack; |
||||
|
for (auto i: ws.stack) |
||||
|
stack.prepend("<div>" + m_context->prettyU256(i) + "</div>"); |
||||
|
ui->debugStack->setHtml(stack); |
||||
|
ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true))); |
||||
|
assert(m_session.codes.count(ws.code)); |
||||
|
|
||||
|
if (m_session.codes[ws.code].size() >= (unsigned)ws.curPC) |
||||
|
{ |
||||
|
int l = m_session.pcWarp[(unsigned)ws.curPC]; |
||||
|
ui->debugCode->setCurrentRow(max(0, l - 5)); |
||||
|
ui->debugCode->setCurrentRow(min(ui->debugCode->count() - 1, l + 5)); |
||||
|
ui->debugCode->setCurrentRow(l); |
||||
|
} |
||||
|
else |
||||
|
cwarn << "PC (" << (unsigned)ws.curPC << ") is after code range (" << m_session.codes[ws.code].size() << ")"; |
||||
|
|
||||
|
ostringstream ss; |
||||
|
ss << dec << "STEP: " << ws.steps << " | PC: 0x" << hex << ws.curPC << " : " << instructionInfo(ws.inst).name << " | ADDMEM: " << dec << ws.newMemSize << " words | COST: " << dec << ws.gasCost << " | GAS: " << dec << ws.gas; |
||||
|
ui->debugStateInfo->setText(QString::fromStdString(ss.str())); |
||||
|
stringstream s; |
||||
|
for (auto const& i: ws.storage) |
||||
|
s << "@" << m_context->prettyU256(i.first).toStdString() << " " << m_context->prettyU256(i.second).toStdString() << "<br/>"; |
||||
|
ui->debugStorage->setHtml(QString::fromStdString(s.str())); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_callStack_currentItemChanged() |
||||
|
{ |
||||
|
update(); |
||||
|
} |
||||
|
|
||||
|
void Debugger::alterDebugStateGroup(bool _enable) const |
||||
|
{ |
||||
|
ui->stepOver->setEnabled(_enable); |
||||
|
ui->stepInto->setEnabled(_enable); |
||||
|
ui->stepOut->setEnabled(_enable); |
||||
|
ui->backOver->setEnabled(_enable); |
||||
|
ui->backInto->setEnabled(_enable); |
||||
|
ui->backOut->setEnabled(_enable); |
||||
|
ui->dump->setEnabled(_enable); |
||||
|
ui->dumpStorage->setEnabled(_enable); |
||||
|
ui->dumpPretty->setEnabled(_enable); |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_debugTimeline_valueChanged() |
||||
|
{ |
||||
|
update(); |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_stepOver_clicked() |
||||
|
{ |
||||
|
if (ui->debugTimeline->value() < m_session.history.size()) { |
||||
|
auto l = m_session.history[ui->debugTimeline->value()].levels.size(); |
||||
|
if ((ui->debugTimeline->value() + 1) < m_session.history.size() && m_session.history[ui->debugTimeline->value() + 1].levels.size() > l) |
||||
|
{ |
||||
|
on_stepInto_clicked(); |
||||
|
if (m_session.history[ui->debugTimeline->value()].levels.size() > l) |
||||
|
on_stepOut_clicked(); |
||||
|
} |
||||
|
else |
||||
|
on_stepInto_clicked(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_stepInto_clicked() |
||||
|
{ |
||||
|
ui->debugTimeline->setValue(ui->debugTimeline->value() + 1); |
||||
|
ui->callStack->setCurrentRow(0); |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_stepOut_clicked() |
||||
|
{ |
||||
|
if (ui->debugTimeline->value() < m_session.history.size()) |
||||
|
{ |
||||
|
auto ls = m_session.history[ui->debugTimeline->value()].levels.size(); |
||||
|
auto l = ui->debugTimeline->value(); |
||||
|
for (; l < m_session.history.size() && m_session.history[l].levels.size() >= ls; ++l) {} |
||||
|
ui->debugTimeline->setValue(l); |
||||
|
ui->callStack->setCurrentRow(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_backInto_clicked() |
||||
|
{ |
||||
|
ui->debugTimeline->setValue(ui->debugTimeline->value() - 1); |
||||
|
ui->callStack->setCurrentRow(0); |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_backOver_clicked() |
||||
|
{ |
||||
|
auto l = m_session.history[ui->debugTimeline->value()].levels.size(); |
||||
|
if (ui->debugTimeline->value() > 0 && m_session.history[ui->debugTimeline->value() - 1].levels.size() > l) |
||||
|
{ |
||||
|
on_backInto_clicked(); |
||||
|
if (m_session.history[ui->debugTimeline->value()].levels.size() > l) |
||||
|
on_backOut_clicked(); |
||||
|
} |
||||
|
else |
||||
|
on_backInto_clicked(); |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_backOut_clicked() |
||||
|
{ |
||||
|
if (ui->debugTimeline->value() > 0 && m_session.history.size() > 0) |
||||
|
{ |
||||
|
auto ls = m_session.history[min(ui->debugTimeline->value(), m_session.history.size() - 1)].levels.size(); |
||||
|
int l = ui->debugTimeline->value(); |
||||
|
for (; l > 0 && m_session.history[l].levels.size() >= ls; --l) {} |
||||
|
ui->debugTimeline->setValue(l); |
||||
|
ui->callStack->setCurrentRow(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_dump_clicked() |
||||
|
{ |
||||
|
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace"); |
||||
|
ofstream f(fn.toStdString()); |
||||
|
if (f.is_open()) |
||||
|
for (WorldState const& ws: m_session.history) |
||||
|
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl; |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_dumpPretty_clicked() |
||||
|
{ |
||||
|
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace"); |
||||
|
ofstream f(fn.toStdString()); |
||||
|
if (f.is_open()) |
||||
|
for (WorldState const& ws: m_session.history) |
||||
|
{ |
||||
|
f << endl << " STACK" << endl; |
||||
|
for (auto i: ws.stack) |
||||
|
f << (h256)i << endl; |
||||
|
f << " MEMORY" << endl << dev::memDump(ws.memory); |
||||
|
f << " STORAGE" << endl; |
||||
|
for (auto const& i: ws.storage) |
||||
|
f << showbase << hex << i.first << ": " << i.second << endl; |
||||
|
f << dec << ws.levels.size() << " | " << ws.cur << " | #" << ws.steps << " | " << hex << setw(4) << setfill('0') << ws.curPC << " : " << instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Debugger::on_dumpStorage_clicked() |
||||
|
{ |
||||
|
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace"); |
||||
|
ofstream f(fn.toStdString()); |
||||
|
if (f.is_open()) |
||||
|
for (WorldState const& ws: m_session.history) |
||||
|
{ |
||||
|
if (ws.inst == Instruction::STOP || ws.inst == Instruction::RETURN || ws.inst == Instruction::SUICIDE) |
||||
|
for (auto i: ws.storage) |
||||
|
f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl; |
||||
|
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl; |
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
/*
|
||||
|
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 Debugger.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <libdevcore/RLP.h> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
#include <libethereum/State.h> |
||||
|
#include <libethereum/Executive.h> |
||||
|
#include <QDialog> |
||||
|
#include <QMap> |
||||
|
#include <QList> |
||||
|
#include "Context.h" |
||||
|
|
||||
|
namespace Ui { class Debugger; } |
||||
|
|
||||
|
struct WorldState |
||||
|
{ |
||||
|
uint64_t steps; |
||||
|
dev::Address cur; |
||||
|
dev::u256 curPC; |
||||
|
dev::eth::Instruction inst; |
||||
|
dev::bigint newMemSize; |
||||
|
dev::u256 gas; |
||||
|
dev::h256 code; |
||||
|
dev::h256 callData; |
||||
|
dev::u256s stack; |
||||
|
dev::bytes memory; |
||||
|
dev::bigint gasCost; |
||||
|
std::map<dev::u256, dev::u256> storage; |
||||
|
std::vector<WorldState const*> levels; |
||||
|
}; |
||||
|
|
||||
|
struct DebugSession |
||||
|
{ |
||||
|
DebugSession() {} |
||||
|
|
||||
|
bool populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction); |
||||
|
|
||||
|
dev::h256 currentCode; |
||||
|
dev::h256 currentData; |
||||
|
std::vector<WorldState const*> currentLevels; |
||||
|
|
||||
|
QMap<unsigned, unsigned> pcWarp; |
||||
|
QList<WorldState> history; |
||||
|
|
||||
|
std::map<dev::u256, dev::bytes> codes; |
||||
|
}; |
||||
|
|
||||
|
class Debugger: public QDialog |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
|
||||
|
public: |
||||
|
explicit Debugger(Context* _context, QWidget* _parent = 0); |
||||
|
~Debugger(); |
||||
|
|
||||
|
void populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction); |
||||
|
|
||||
|
protected slots: |
||||
|
void on_callStack_currentItemChanged(); |
||||
|
void on_debugTimeline_valueChanged(); |
||||
|
void on_stepOver_clicked(); |
||||
|
void on_stepInto_clicked(); |
||||
|
void on_stepOut_clicked(); |
||||
|
void on_backOver_clicked(); |
||||
|
void on_backInto_clicked(); |
||||
|
void on_backOut_clicked(); |
||||
|
void on_dump_clicked(); |
||||
|
void on_dumpPretty_clicked(); |
||||
|
void on_dumpStorage_clicked(); |
||||
|
void on_close_clicked() { close(); } |
||||
|
|
||||
|
private: |
||||
|
void init(); |
||||
|
void update(); |
||||
|
void finished(); |
||||
|
|
||||
|
void alterDebugStateGroup(bool _enable) const; |
||||
|
|
||||
|
Ui::Debugger* ui; |
||||
|
|
||||
|
DebugSession m_session; |
||||
|
Context* m_context; |
||||
|
}; |
@ -0,0 +1,300 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>Debugger</class> |
||||
|
<widget class="QDialog" name="Debugger"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>989</width> |
||||
|
<height>690</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Dialog</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<item> |
||||
|
<widget class="QFrame" name="frame"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="frameShadow"> |
||||
|
<enum>QFrame::Raised</enum> |
||||
|
</property> |
||||
|
<layout class="QHBoxLayout" name="horizontalLayout"> |
||||
|
<property name="leftMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="stepOver"> |
||||
|
<property name="text"> |
||||
|
<string>Step Over</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="stepInto"> |
||||
|
<property name="text"> |
||||
|
<string>Step Into</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="stepOut"> |
||||
|
<property name="text"> |
||||
|
<string>Step Out</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="backOver"> |
||||
|
<property name="text"> |
||||
|
<string>Back Over</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="backInto"> |
||||
|
<property name="text"> |
||||
|
<string>Back Into</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="backOut"> |
||||
|
<property name="text"> |
||||
|
<string>Back Out</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> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QSplitter" name="splitter_6"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<widget class="QSplitter" name="splitter_42"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding"> |
||||
|
<horstretch>1</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<widget class="QListWidget" name="debugCode"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
<widget class="QListWidget" name="callStack"> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<family>Ubuntu Mono</family> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</widget> |
||||
|
<widget class="QSplitter" name="splitter_4"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding"> |
||||
|
<horstretch>1</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<widget class="QTextEdit" name="debugStack"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="textInteractionFlags"> |
||||
|
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
<widget class="QTextEdit" name="debugMemory"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="textInteractionFlags"> |
||||
|
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
<widget class="QTextEdit" name="debugStorage"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="textInteractionFlags"> |
||||
|
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
<widget class="QTextEdit" name="debugCallData"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</widget> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QLabel" name="debugStateInfo"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QSlider" name="debugTimeline"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QFrame" name="frame_2"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="frameShadow"> |
||||
|
<enum>QFrame::Raised</enum> |
||||
|
</property> |
||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2"> |
||||
|
<property name="leftMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="dump"> |
||||
|
<property name="text"> |
||||
|
<string>Dump</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="dumpStorage"> |
||||
|
<property name="text"> |
||||
|
<string>Dump Storage</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="dumpPretty"> |
||||
|
<property name="text"> |
||||
|
<string>Dump Pretty</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="horizontalSpacer_2"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>577</width> |
||||
|
<height>20</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QToolButton" name="close"> |
||||
|
<property name="text"> |
||||
|
<string>Close</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
File diff suppressed because it is too large
@ -0,0 +1,101 @@ |
|||||
|
/*
|
||||
|
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 NatspecHandler.cpp
|
||||
|
* @author Lefteris Karapetsas <lefteris@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
#include "NatspecHandler.h" |
||||
|
#include <string> |
||||
|
#include <boost/filesystem.hpp> |
||||
|
|
||||
|
#include <libdevcore/Common.h> |
||||
|
#include <libdevcore/CommonData.h> |
||||
|
#include <libdevcore/Exceptions.h> |
||||
|
#include <libdevcore/Log.h> |
||||
|
#include <libdevcrypto/SHA3.h> |
||||
|
#include <libethereum/Defaults.h> |
||||
|
|
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
using namespace std; |
||||
|
|
||||
|
NatspecHandler::NatspecHandler() |
||||
|
{ |
||||
|
string path = Defaults::dbPath(); |
||||
|
boost::filesystem::create_directories(path); |
||||
|
ldb::Options o; |
||||
|
o.create_if_missing = true; |
||||
|
ldb::DB::Open(o, path + "/natspec", &m_db); |
||||
|
} |
||||
|
|
||||
|
NatspecHandler::~NatspecHandler() |
||||
|
{ |
||||
|
delete m_db; |
||||
|
} |
||||
|
|
||||
|
void NatspecHandler::add(dev::h256 const& _contractHash, string const& _doc) |
||||
|
{ |
||||
|
m_db->Put(m_writeOptions, _contractHash.ref(), _doc); |
||||
|
cdebug << "Registering NatSpec: " << _contractHash.abridged() << _doc; |
||||
|
} |
||||
|
|
||||
|
string NatspecHandler::retrieve(dev::h256 const& _contractHash) const |
||||
|
{ |
||||
|
string ret; |
||||
|
m_db->Get(m_readOptions, _contractHash.ref(), &ret); |
||||
|
cdebug << "Looking up NatSpec: " << _contractHash.abridged() << ret; |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
string NatspecHandler::getUserNotice(string const& json, dev::bytes const& _transactionData) |
||||
|
{ |
||||
|
Json::Value natspec; |
||||
|
Json::Value userNotice; |
||||
|
m_reader.parse(json, natspec); |
||||
|
|
||||
|
FixedHash<4> transactionFunctionHash((bytesConstRef(&_transactionData).cropped(0, 4).toBytes())); |
||||
|
|
||||
|
Json::Value methods = natspec["methods"]; |
||||
|
for (Json::ValueIterator it = methods.begin(); it != methods.end(); ++it) |
||||
|
{ |
||||
|
Json::Value keyValue = it.key(); |
||||
|
if (!keyValue.isString()) |
||||
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Illegal Natspec JSON detected")); |
||||
|
|
||||
|
string functionSig = keyValue.asString(); |
||||
|
FixedHash<4> functionHash(dev::sha3(functionSig)); |
||||
|
|
||||
|
if (functionHash == transactionFunctionHash) |
||||
|
{ |
||||
|
Json::Value val = (*it)["notice"]; |
||||
|
if (!val.isString()) |
||||
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Illegal Natspec JSON detected")); |
||||
|
return val.asString(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// not found
|
||||
|
return string(); |
||||
|
} |
||||
|
|
||||
|
string NatspecHandler::getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData) |
||||
|
{ |
||||
|
return getUserNotice(retrieve(_contractHash), _transactionData); |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,59 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
|
||||
|
/** @file NatspecHandler.h
|
||||
|
* @author Lefteris Karapetsas <lefteris@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#pragma warning(push) |
||||
|
#pragma warning(disable: 4100 4267) |
||||
|
#include <leveldb/db.h> |
||||
|
#pragma warning(pop) |
||||
|
#include <json/json.h> |
||||
|
#include <libdevcore/FixedHash.h> |
||||
|
#include "Context.h" |
||||
|
|
||||
|
namespace ldb = leveldb; |
||||
|
|
||||
|
class NatspecHandler: public NatSpecFace |
||||
|
{ |
||||
|
public: |
||||
|
NatspecHandler(); |
||||
|
~NatspecHandler(); |
||||
|
|
||||
|
/// Stores locally in a levelDB a key value pair of contract code hash to natspec documentation
|
||||
|
void add(dev::h256 const& _contractHash, std::string const& _doc); |
||||
|
/// Retrieves the natspec documentation as a string given a contract code hash
|
||||
|
std::string retrieve(dev::h256 const& _contractHash) const override; |
||||
|
|
||||
|
/// Given a json natspec string and the transaction data return the user notice
|
||||
|
std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData); |
||||
|
/// Given a contract code hash and the transaction's data retrieve the natspec documention's
|
||||
|
/// user notice for that transaction.
|
||||
|
/// @returns The user notice or an empty string if no natspec for the contract exists
|
||||
|
/// or if the existing natspec does not document the @c _methodName
|
||||
|
std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta); |
||||
|
|
||||
|
private: |
||||
|
ldb::ReadOptions m_readOptions; |
||||
|
ldb::WriteOptions m_writeOptions; |
||||
|
ldb::DB* m_db = nullptr; |
||||
|
Json::Reader m_reader; |
||||
|
}; |
@ -0,0 +1,334 @@ |
|||||
|
/*
|
||||
|
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 Transact.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include "Transact.h" |
||||
|
|
||||
|
#include <fstream> |
||||
|
#include <QFileDialog> |
||||
|
#include <QMessageBox> |
||||
|
#include <liblll/Compiler.h> |
||||
|
#include <liblll/CodeFragment.h> |
||||
|
#include <libsolidity/CompilerStack.h> |
||||
|
#include <libsolidity/Scanner.h> |
||||
|
#include <libsolidity/AST.h> |
||||
|
#include <libsolidity/SourceReferenceFormatter.h> |
||||
|
#include <libnatspec/NatspecExpressionEvaluator.h> |
||||
|
#include <libethereum/Client.h> |
||||
|
#include <libethereum/Utility.h> |
||||
|
#ifndef _MSC_VER |
||||
|
#include <libserpent/funcs.h> |
||||
|
#include <libserpent/util.h> |
||||
|
#endif |
||||
|
#include "Debugger.h" |
||||
|
#include "ui_Transact.h" |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
Transact::Transact(Context* _c, QWidget* _parent): |
||||
|
QDialog(_parent), |
||||
|
ui(new Ui::Transact), |
||||
|
m_context(_c) |
||||
|
{ |
||||
|
ui->setupUi(this); |
||||
|
|
||||
|
initUnits(ui->gasPriceUnits); |
||||
|
initUnits(ui->valueUnits); |
||||
|
ui->valueUnits->setCurrentIndex(6); |
||||
|
ui->gasPriceUnits->setCurrentIndex(4); |
||||
|
ui->gasPrice->setValue(10); |
||||
|
on_destination_currentTextChanged(); |
||||
|
} |
||||
|
|
||||
|
Transact::~Transact() |
||||
|
{ |
||||
|
delete ui; |
||||
|
} |
||||
|
|
||||
|
void Transact::setEnvironment(QList<dev::KeyPair> _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB) |
||||
|
{ |
||||
|
m_myKeys = _myKeys; |
||||
|
m_ethereum = _eth; |
||||
|
m_natSpecDB = _natSpecDB; |
||||
|
} |
||||
|
|
||||
|
bool Transact::isCreation() const |
||||
|
{ |
||||
|
return ui->destination->currentText().isEmpty() || ui->destination->currentText() == "(Create Contract)"; |
||||
|
} |
||||
|
|
||||
|
u256 Transact::fee() const |
||||
|
{ |
||||
|
return ui->gas->value() * gasPrice(); |
||||
|
} |
||||
|
|
||||
|
u256 Transact::value() const |
||||
|
{ |
||||
|
if (ui->valueUnits->currentIndex() == -1) |
||||
|
return 0; |
||||
|
return ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first; |
||||
|
} |
||||
|
|
||||
|
u256 Transact::gasPrice() const |
||||
|
{ |
||||
|
if (ui->gasPriceUnits->currentIndex() == -1) |
||||
|
return 0; |
||||
|
return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first; |
||||
|
} |
||||
|
|
||||
|
u256 Transact::total() const |
||||
|
{ |
||||
|
return value() + fee(); |
||||
|
} |
||||
|
|
||||
|
void Transact::updateDestination() |
||||
|
{ |
||||
|
cwatch << "updateDestination()"; |
||||
|
QString s; |
||||
|
for (auto i: ethereum()->addresses()) |
||||
|
if ((s = m_context->pretty(i)).size()) |
||||
|
// A namereg address
|
||||
|
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1) |
||||
|
ui->destination->addItem(s); |
||||
|
for (int i = 0; i < ui->destination->count(); ++i) |
||||
|
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i))) |
||||
|
ui->destination->removeItem(i--); |
||||
|
} |
||||
|
|
||||
|
void Transact::updateFee() |
||||
|
{ |
||||
|
ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str())); |
||||
|
auto totalReq = total(); |
||||
|
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str())); |
||||
|
|
||||
|
bool ok = false; |
||||
|
for (auto i: m_myKeys) |
||||
|
if (ethereum()->balanceAt(i.address()) >= totalReq) |
||||
|
{ |
||||
|
ok = true; |
||||
|
break; |
||||
|
} |
||||
|
ui->send->setEnabled(ok); |
||||
|
QPalette p = ui->total->palette(); |
||||
|
p.setColor(QPalette::WindowText, QColor(ok ? 0x00 : 0x80, 0x00, 0x00)); |
||||
|
ui->total->setPalette(p); |
||||
|
} |
||||
|
|
||||
|
string Transact::getFunctionHashes(dev::solidity::CompilerStack const& _compiler, string const& _contractName) |
||||
|
{ |
||||
|
string ret = ""; |
||||
|
auto const& contract = _compiler.getContractDefinition(_contractName); |
||||
|
auto interfaceFunctions = contract.getInterfaceFunctions(); |
||||
|
|
||||
|
for (auto const& it: interfaceFunctions) |
||||
|
{ |
||||
|
ret += it.first.abridged(); |
||||
|
ret += " :"; |
||||
|
ret += it.second->getDeclaration().getName() + "\n"; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
void Transact::on_destination_currentTextChanged() |
||||
|
{ |
||||
|
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") |
||||
|
if (Address a = m_context->fromString(ui->destination->currentText())) |
||||
|
ui->calculatedName->setText(m_context->render(a)); |
||||
|
else |
||||
|
ui->calculatedName->setText("Unknown Address"); |
||||
|
else |
||||
|
ui->calculatedName->setText("Create Contract"); |
||||
|
rejigData(); |
||||
|
// updateFee();
|
||||
|
} |
||||
|
|
||||
|
void Transact::rejigData() |
||||
|
{ |
||||
|
if (isCreation()) |
||||
|
{ |
||||
|
string src = ui->data->toPlainText().toStdString(); |
||||
|
vector<string> errors; |
||||
|
QString lll; |
||||
|
QString solidity; |
||||
|
if (src.find_first_not_of("1234567890abcdefABCDEF") == string::npos && src.size() % 2 == 0) |
||||
|
m_data = fromHex(src); |
||||
|
else if (sourceIsSolidity(src)) |
||||
|
{ |
||||
|
dev::solidity::CompilerStack compiler; |
||||
|
try |
||||
|
{ |
||||
|
// compiler.addSources(dev::solidity::StandardSources);
|
||||
|
m_data = compiler.compile(src, ui->optimize->isChecked()); |
||||
|
solidity = "<h4>Solidity</h4>"; |
||||
|
solidity += "<pre>var " + QString::fromStdString(compiler.defaultContractName()) + " = web3.eth.contractFromAbi(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + ");</pre>"; |
||||
|
solidity += "<pre>" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped() + "</pre>"; |
||||
|
solidity += "<pre>" + QString::fromStdString(getFunctionHashes(compiler)).toHtmlEscaped() + "</pre>"; |
||||
|
} |
||||
|
catch (dev::Exception const& exception) |
||||
|
{ |
||||
|
ostringstream error; |
||||
|
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler); |
||||
|
solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>"; |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
solidity = "<h4>Solidity</h4><pre>Uncaught exception.</pre>"; |
||||
|
} |
||||
|
} |
||||
|
#ifndef _MSC_VER |
||||
|
else if (sourceIsSerpent(src)) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
m_data = dev::asBytes(::compile(src)); |
||||
|
for (auto& i: errors) |
||||
|
i = "(LLL " + i + ")"; |
||||
|
} |
||||
|
catch (string const& err) |
||||
|
{ |
||||
|
errors.push_back("Serpent " + err); |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
|
else |
||||
|
{ |
||||
|
m_data = compileLLL(src, ui->optimize->isChecked(), &errors); |
||||
|
if (errors.empty()) |
||||
|
{ |
||||
|
auto asmcode = compileLLLToAsm(src, false); |
||||
|
lll = "<h4>Pre</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>"; |
||||
|
if (ui->optimize->isChecked()) |
||||
|
{ |
||||
|
asmcode = compileLLLToAsm(src, true); |
||||
|
lll = "<h4>Opt</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>" + lll; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
QString errs; |
||||
|
if (errors.size()) |
||||
|
{ |
||||
|
errs = "<h4>Errors</h4>"; |
||||
|
for (auto const& i: errors) |
||||
|
errs.append("<div style=\"border-left: 6px solid #c00; margin-top: 2px\">" + QString::fromStdString(i).toHtmlEscaped() + "</div>"); |
||||
|
} |
||||
|
ui->code->setHtml(errs + lll + solidity + "<h4>Code</h4>" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped() + "<h4>Hex</h4>" Div(Mono) + QString::fromStdString(toHex(m_data)) + "</div>"); |
||||
|
ui->gas->setMinimum((qint64)Interface::txGas(m_data, 0)); |
||||
|
if (!ui->gas->isEnabled()) |
||||
|
ui->gas->setValue(m_backupGas); |
||||
|
ui->gas->setEnabled(true); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
m_data = parseData(ui->data->toPlainText().toStdString()); |
||||
|
auto to = m_context->fromString(ui->destination->currentText()); |
||||
|
QString natspec; |
||||
|
if (ethereum()->codeAt(to, 0).size()) |
||||
|
{ |
||||
|
string userNotice = m_natSpecDB->getUserNotice(ethereum()->postState().codeHash(to), m_data); |
||||
|
if (userNotice.empty()) |
||||
|
natspec = "Destination contract unknown."; |
||||
|
else |
||||
|
{ |
||||
|
NatspecExpressionEvaluator evaluator; |
||||
|
natspec = evaluator.evalExpression(QString::fromStdString(userNotice)); |
||||
|
} |
||||
|
ui->gas->setMinimum((qint64)Interface::txGas(m_data, 1)); |
||||
|
if (!ui->gas->isEnabled()) |
||||
|
ui->gas->setValue(m_backupGas); |
||||
|
ui->gas->setEnabled(true); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
natspec += "Destination not a contract."; |
||||
|
if (ui->gas->isEnabled()) |
||||
|
m_backupGas = ui->gas->value(); |
||||
|
ui->gas->setValue((qint64)Interface::txGas(m_data)); |
||||
|
ui->gas->setEnabled(false); |
||||
|
} |
||||
|
ui->code->setHtml("<h3>NatSpec</h3>" + natspec + "<h3>Dump</h3>" + QString::fromStdString(dev::memDump(m_data, 8, true)) + "<h3>Hex</h3>" + Div(Mono) + QString::fromStdString(toHex(m_data)) + "</div>"); |
||||
|
} |
||||
|
updateFee(); |
||||
|
} |
||||
|
|
||||
|
void Transact::on_send_clicked() |
||||
|
{ |
||||
|
u256 totalReq = value() + fee(); |
||||
|
for (auto const& i: m_myKeys) |
||||
|
if (ethereum()->balanceAt(i.address(), 0) >= totalReq) |
||||
|
{ |
||||
|
Secret s = i.secret(); |
||||
|
if (isCreation()) |
||||
|
{ |
||||
|
// If execution is a contract creation, add Natspec to
|
||||
|
// a local Natspec LEVELDB
|
||||
|
ethereum()->transact(s, value(), m_data, ui->gas->value(), gasPrice()); |
||||
|
string src = ui->data->toPlainText().toStdString(); |
||||
|
if (sourceIsSolidity(src)) |
||||
|
try |
||||
|
{ |
||||
|
dev::solidity::CompilerStack compiler; |
||||
|
m_data = compiler.compile(src, ui->optimize->isChecked()); |
||||
|
for (string const& s: compiler.getContractNames()) |
||||
|
{ |
||||
|
h256 contractHash = compiler.getContractCodeHash(s); |
||||
|
m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser)); |
||||
|
} |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
} |
||||
|
close(); |
||||
|
return; |
||||
|
} |
||||
|
else |
||||
|
ethereum()->transact(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); |
||||
|
return; |
||||
|
} |
||||
|
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); |
||||
|
} |
||||
|
|
||||
|
void Transact::on_debug_clicked() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
u256 totalReq = value() + fee(); |
||||
|
for (auto i: m_myKeys) |
||||
|
if (ethereum()->balanceAt(i.address()) >= totalReq) |
||||
|
{ |
||||
|
State st(ethereum()->postState()); |
||||
|
Secret s = i.secret(); |
||||
|
Transaction t = isCreation() ? |
||||
|
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) : |
||||
|
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s); |
||||
|
Debugger dw(m_context, this); |
||||
|
Executive e(st, ethereum()->blockChain(), 0); |
||||
|
dw.populate(e, t); |
||||
|
dw.exec(); |
||||
|
return; |
||||
|
} |
||||
|
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); |
||||
|
} |
||||
|
catch (dev::Exception const& _e) |
||||
|
{ |
||||
|
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction. Low-level error: " + QString::fromStdString(diagnostic_information(_e))); |
||||
|
// this output is aimed at developers, reconsider using _e.what for more user friendly output.
|
||||
|
} |
||||
|
} |
@ -0,0 +1,82 @@ |
|||||
|
/*
|
||||
|
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 Transact.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <libdevcore/RLP.h> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
#include <libethereum/Transaction.h> |
||||
|
#include <QDialog> |
||||
|
#include <QMap> |
||||
|
#include <QList> |
||||
|
#include "Context.h" |
||||
|
|
||||
|
namespace Ui { class Transact; } |
||||
|
namespace dev { namespace eth { class Client; } } |
||||
|
namespace dev { namespace solidity { class CompilerStack; } } |
||||
|
|
||||
|
class Transact: public QDialog |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
|
||||
|
public: |
||||
|
explicit Transact(Context* _context, QWidget* _parent = 0); |
||||
|
~Transact(); |
||||
|
|
||||
|
void setEnvironment(QList<dev::KeyPair> _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB); |
||||
|
|
||||
|
private slots: |
||||
|
void on_destination_currentTextChanged(); |
||||
|
void on_value_valueChanged() { updateFee(); } |
||||
|
void on_gas_valueChanged() { updateFee(); } |
||||
|
void on_valueUnits_currentIndexChanged() { updateFee(); } |
||||
|
void on_gasPriceUnits_currentIndexChanged() { updateFee(); } |
||||
|
void on_gasPrice_valueChanged() { updateFee(); } |
||||
|
void on_data_textChanged() { rejigData(); } |
||||
|
void on_optimize_clicked() { rejigData(); } |
||||
|
void on_send_clicked(); |
||||
|
void on_debug_clicked(); |
||||
|
void on_cancel_clicked() { close(); } |
||||
|
|
||||
|
private: |
||||
|
dev::eth::Client* ethereum() { return m_ethereum; } |
||||
|
void rejigData(); |
||||
|
|
||||
|
void updateDestination(); |
||||
|
void updateFee(); |
||||
|
bool isCreation() const; |
||||
|
dev::u256 fee() const; |
||||
|
dev::u256 total() const; |
||||
|
dev::u256 value() const; |
||||
|
dev::u256 gasPrice() const; |
||||
|
|
||||
|
std::string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, std::string const& _contractName = std::string()); |
||||
|
|
||||
|
Ui::Transact* ui; |
||||
|
|
||||
|
unsigned m_backupGas; |
||||
|
dev::bytes m_data; |
||||
|
|
||||
|
QList<dev::KeyPair> m_myKeys; |
||||
|
dev::eth::Client* m_ethereum; |
||||
|
Context* m_context; |
||||
|
NatSpecFace* m_natSpecDB; |
||||
|
}; |
@ -0,0 +1,244 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>Transact</class> |
||||
|
<widget class="QDialog" name="Transact"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>543</width> |
||||
|
<height>695</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Dialog</string> |
||||
|
</property> |
||||
|
<layout class="QGridLayout" name="gridLayout"> |
||||
|
<item row="2" column="1" colspan="2"> |
||||
|
<widget class="QSpinBox" name="value"> |
||||
|
<property name="suffix"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
<property name="maximum"> |
||||
|
<number>430000000</number> |
||||
|
</property> |
||||
|
<property name="value"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="0"> |
||||
|
<widget class="QLabel" name="label5_2"> |
||||
|
<property name="text"> |
||||
|
<string>&Amount</string> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>value</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="1" colspan="3"> |
||||
|
<widget class="QLineEdit" name="calculatedName"> |
||||
|
<property name="enabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="placeholderText"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="5" column="0" colspan="4"> |
||||
|
<widget class="QSplitter" name="splitter_5"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<widget class="QPlainTextEdit" name="data"> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
<widget class="QTextEdit" name="code"> |
||||
|
<property name="focusPolicy"> |
||||
|
<enum>Qt::ClickFocus</enum> |
||||
|
</property> |
||||
|
<property name="frameShape"> |
||||
|
<enum>QFrame::NoFrame</enum> |
||||
|
</property> |
||||
|
<property name="lineWidth"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="readOnly"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="3"> |
||||
|
<widget class="QComboBox" name="gasPriceUnits"/> |
||||
|
</item> |
||||
|
<item row="4" column="1" colspan="2"> |
||||
|
<widget class="QLabel" name="fee"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<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>&To</string> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>destination</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="3"> |
||||
|
<widget class="QComboBox" name="valueUnits"/> |
||||
|
</item> |
||||
|
<item row="7" column="2"> |
||||
|
<widget class="QPushButton" name="debug"> |
||||
|
<property name="text"> |
||||
|
<string>&Debug</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="7" column="3"> |
||||
|
<widget class="QPushButton" name="send"> |
||||
|
<property name="text"> |
||||
|
<string>&Execute</string> |
||||
|
</property> |
||||
|
<property name="default"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="0"> |
||||
|
<widget class="QLabel" name="label_6"> |
||||
|
<property name="text"> |
||||
|
<string>&Gas</string> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>gas</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="1"> |
||||
|
<widget class="QSpinBox" name="gas"> |
||||
|
<property name="suffix"> |
||||
|
<string> gas</string> |
||||
|
</property> |
||||
|
<property name="minimum"> |
||||
|
<number>1</number> |
||||
|
</property> |
||||
|
<property name="maximum"> |
||||
|
<number>430000000</number> |
||||
|
</property> |
||||
|
<property name="value"> |
||||
|
<number>10000</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="2"> |
||||
|
<widget class="QSpinBox" name="gasPrice"> |
||||
|
<property name="prefix"> |
||||
|
<string>@ </string> |
||||
|
</property> |
||||
|
<property name="minimum"> |
||||
|
<number>1</number> |
||||
|
</property> |
||||
|
<property name="maximum"> |
||||
|
<number>430000000</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" column="3"> |
||||
|
<widget class="QCheckBox" name="optimize"> |
||||
|
<property name="text"> |
||||
|
<string>&Optimise</string> |
||||
|
</property> |
||||
|
<property name="checked"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" 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&ata</string> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> |
||||
|
</property> |
||||
|
<property name="buddy"> |
||||
|
<cstring>data</cstring> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" 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="6" 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/> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="7" column="0"> |
||||
|
<widget class="QPushButton" name="cancel"> |
||||
|
<property name="text"> |
||||
|
<string>&Cancel</string> |
||||
|
</property> |
||||
|
<property name="shortcut"> |
||||
|
<string>Esc</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -1,27 +0,0 @@ |
|||||
#!/usr/bin/python |
|
||||
# cpp-ethereum build script |
|
||||
# to be used from CI server, or to build locally |
|
||||
# uses python instead of bash script for better cross-platform support |
|
||||
|
|
||||
# TODO Initial version. Needs much more improvements |
|
||||
|
|
||||
import argparse |
|
||||
import os |
|
||||
import subprocess |
|
||||
|
|
||||
def build_dependencies(): |
|
||||
if os.path.exists("extdep"): |
|
||||
os.chdir("extdep") |
|
||||
if not os.path.exists("build"): |
|
||||
os.makedirs("build") |
|
||||
os.chdir("build") |
|
||||
subprocess.check_call(["cmake", ".."]) |
|
||||
subprocess.check_call("make") |
|
||||
|
|
||||
parser = argparse.ArgumentParser() |
|
||||
parser.add_argument("cmd", help="what to build") |
|
||||
|
|
||||
args = parser.parse_args() |
|
||||
if args.cmd == "dep": |
|
||||
build_dependencies() |
|
||||
|
|
@ -0,0 +1,24 @@ |
|||||
|
# |
||||
|
# renames the file if it is different from its destination |
||||
|
include(CMakeParseArguments) |
||||
|
# |
||||
|
macro(replace_if_different SOURCE DST) |
||||
|
set(extra_macro_args ${ARGN}) |
||||
|
set(options CREATE) |
||||
|
set(one_value_args) |
||||
|
set(multi_value_args) |
||||
|
cmake_parse_arguments(REPLACE_IF_DIFFERENT "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") |
||||
|
|
||||
|
if (REPLACE_IF_DIFFERENT_CREATE AND (NOT (EXISTS "${DST}"))) |
||||
|
file(WRITE "${DST}" "") |
||||
|
endif() |
||||
|
|
||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files "${SOURCE}" "${DST}" RESULT_VARIABLE DIFFERENT) |
||||
|
|
||||
|
if (DIFFERENT) |
||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E rename "${SOURCE}" "${DST}") |
||||
|
else() |
||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E remove "${SOURCE}") |
||||
|
endif() |
||||
|
endmacro() |
||||
|
|
@ -0,0 +1,47 @@ |
|||||
|
# Find microhttpd |
||||
|
# |
||||
|
# Find the microhttpd includes and library |
||||
|
# |
||||
|
# if you need to add a custom library search path, do it via via CMAKE_PREFIX_PATH |
||||
|
# |
||||
|
# This module defines |
||||
|
# MHD_INCLUDE_DIRS, where to find header, etc. |
||||
|
# MHD_LIBRARIES, the libraries needed to use jsoncpp. |
||||
|
# MHD_FOUND, If false, do not try to use jsoncpp. |
||||
|
|
||||
|
find_path( |
||||
|
MHD_INCLUDE_DIR |
||||
|
NAMES microhttpd.h |
||||
|
DOC "microhttpd include dir" |
||||
|
) |
||||
|
|
||||
|
find_library( |
||||
|
MHD_LIBRARY |
||||
|
NAMES microhttpd microhttpd-10 libmicrohttpd libmicrohttpd-dll |
||||
|
DOC "microhttpd library" |
||||
|
) |
||||
|
|
||||
|
set(MHD_INCLUDE_DIRS ${MHD_INCLUDE_DIR}) |
||||
|
set(MHD_LIBRARIES ${MHD_LIBRARY}) |
||||
|
|
||||
|
# debug library on windows |
||||
|
# same naming convention as in QT (appending debug library with d) |
||||
|
# boost is using the same "hack" as us with "optimized" and "debug" |
||||
|
# official MHD project actually uses _d suffix |
||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") |
||||
|
find_library( |
||||
|
MHD_LIBRARY_DEBUG |
||||
|
NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d |
||||
|
DOC "mhd debug library" |
||||
|
) |
||||
|
|
||||
|
set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG}) |
||||
|
|
||||
|
endif() |
||||
|
|
||||
|
include(FindPackageHandleStandardArgs) |
||||
|
find_package_handle_standard_args(mhd DEFAULT_MSG |
||||
|
MHD_INCLUDE_DIR MHD_LIBRARY) |
||||
|
|
||||
|
mark_as_advanced(MHD_INCLUDE_DIR MHD_LIBRARY) |
||||
|
|
@ -0,0 +1,48 @@ |
|||||
|
# generates BuildInfo.h |
||||
|
# |
||||
|
# this module expects |
||||
|
# ETH_SOURCE_DIR - main CMAKE_SOURCE_DIR |
||||
|
# ETH_DST_DIR - main CMAKE_BINARY_DIR |
||||
|
# ETH_BUILD_TYPE |
||||
|
# ETH_BUILD_PLATFORM |
||||
|
# |
||||
|
# example usage: |
||||
|
# cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=mac -P scripts/buildinfo.cmake |
||||
|
|
||||
|
if (NOT ETH_BUILD_TYPE) |
||||
|
set(ETH_BUILD_TYPE "unknown") |
||||
|
endif() |
||||
|
|
||||
|
if (NOT ETH_BUILD_PLATFORM) |
||||
|
set(ETH_BUILD_PLATFORM "unknown") |
||||
|
endif() |
||||
|
|
||||
|
execute_process( |
||||
|
COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD |
||||
|
OUTPUT_VARIABLE ETH_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET |
||||
|
) |
||||
|
|
||||
|
if (NOT ETH_COMMIT_HASH) |
||||
|
set(ETH_COMMIT_HASH 0) |
||||
|
endif() |
||||
|
|
||||
|
execute_process( |
||||
|
COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} diff --shortstat |
||||
|
OUTPUT_VARIABLE ETH_LOCAL_CHANGES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET |
||||
|
) |
||||
|
|
||||
|
if (ETH_LOCAL_CHANGES) |
||||
|
set(ETH_CLEAN_REPO 0) |
||||
|
else() |
||||
|
set(ETH_CLEAN_REPO 1) |
||||
|
endif() |
||||
|
|
||||
|
set(INFILE "${ETH_SOURCE_DIR}/BuildInfo.h.in") |
||||
|
set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") |
||||
|
set(OUTFILE "${ETH_DST_DIR}/BuildInfo.h") |
||||
|
|
||||
|
configure_file("${INFILE}" "${TMPFILE}") |
||||
|
|
||||
|
include("${ETH_SOURCE_DIR}/cmake/EthUtils.cmake") |
||||
|
replace_if_different("${TMPFILE}" "${OUTFILE}" CREATE) |
||||
|
|
@ -0,0 +1,14 @@ |
|||||
|
# adds possibility to run configure_file as buildstep |
||||
|
# reference: |
||||
|
# http://www.cmake.org/pipermail/cmake/2012-May/050227.html |
||||
|
# |
||||
|
# This module expects |
||||
|
# INFILE |
||||
|
# OUTFILE |
||||
|
# other custom vars |
||||
|
# |
||||
|
# example usage: |
||||
|
# cmake -DINFILE=blah.in -DOUTFILE=blah.out -Dvar1=value1 -Dvar2=value2 -P scripts/configure.cmake |
||||
|
|
||||
|
configure_file(${INFILE} ${OUTFILE}) |
||||
|
|
@ -0,0 +1,45 @@ |
|||||
|
# generates JSONRPC Stub Server && Client |
||||
|
# |
||||
|
# this script expects |
||||
|
# ETH_SOURCE_DIR - main CMAKE_SOURCE_DIR |
||||
|
# ETH_SPEC_PATH |
||||
|
# ETH_SERVER_DIR |
||||
|
# ETH_CLIENT_DIR |
||||
|
# ETH_SERVER_NAME |
||||
|
# ETH_CLIENT_NAME |
||||
|
# ETH_JSON_RPC_STUB |
||||
|
# |
||||
|
# example usage: |
||||
|
# cmake -DETH_SPEC_PATH=spec.json -DETH_SERVER_DIR=libweb3jsonrpc -DETH_CLIENT_DIR=test |
||||
|
# -DETH_SERVER_NAME=AbstractWebThreeStubServer -DETH_CLIENT_NAME=WebThreeStubClient -DETH_JSON_RPC_STUB=/usr/local/bin/jsonrpcstub |
||||
|
|
||||
|
# by default jsonrpcstub produces files in lowercase, we want to stick to this |
||||
|
string(TOLOWER ${ETH_SERVER_NAME} ETH_SERVER_NAME_LOWER) |
||||
|
string(TOLOWER ${ETH_CLIENT_NAME} ETH_CLIENT_NAME_LOWER) |
||||
|
|
||||
|
# setup names |
||||
|
set(SERVER_TMPFILE "${ETH_SERVER_DIR}/${ETH_SERVER_NAME_LOWER}.h.tmp") |
||||
|
set(SERVER_OUTFILE "${ETH_SERVER_DIR}/${ETH_SERVER_NAME_LOWER}.h") |
||||
|
set(CLIENT_TMPFILE "${ETH_CLIENT_DIR}/${ETH_CLIENT_NAME_LOWER}.h.tmp") |
||||
|
set(CLIENT_OUTFILE "${ETH_CLIENT_DIR}/${ETH_CLIENT_NAME_LOWER}.h") |
||||
|
|
||||
|
# create tmp files |
||||
|
execute_process( |
||||
|
COMMAND ${ETH_JSON_RPC_STUB} ${ETH_SPEC_PATH} |
||||
|
--cpp-server=${ETH_SERVER_NAME} --cpp-server-file=${SERVER_TMPFILE} |
||||
|
--cpp-client=${ETH_CLIENT_NAME} --cpp-client-file=${CLIENT_TMPFILE} |
||||
|
OUTPUT_VARIABLE ERR ERROR_QUIET |
||||
|
) |
||||
|
|
||||
|
# don't throw fatal error on jsonrpcstub error, someone might have old version of jsonrpcstub, |
||||
|
# he does not need to upgrade it if he is not working on JSON RPC |
||||
|
# show him warning instead |
||||
|
if (ERR) |
||||
|
message(WARNING "Your version of jsonrcpstub tool is not supported. Please upgrade it.") |
||||
|
message(WARNING "${ERR}") |
||||
|
else() |
||||
|
include("${ETH_SOURCE_DIR}/cmake/EthUtils.cmake") |
||||
|
replace_if_different("${SERVER_TMPFILE}" "${SERVER_OUTFILE}") |
||||
|
replace_if_different("${CLIENT_TMPFILE}" "${CLIENT_OUTFILE}") |
||||
|
endif() |
||||
|
|
@ -0,0 +1,94 @@ |
|||||
|
/*
|
||||
|
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 CanonBlockChain.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "CanonBlockChain.h" |
||||
|
|
||||
|
#include <test/JsonSpiritHeaders.h> |
||||
|
#include <boost/filesystem.hpp> |
||||
|
#include <libdevcore/Common.h> |
||||
|
#include <libdevcore/RLP.h> |
||||
|
#include <libdevcrypto/FileSystem.h> |
||||
|
#include <libethcore/Exceptions.h> |
||||
|
#include <libethcore/ProofOfWork.h> |
||||
|
#include <libethcore/BlockInfo.h> |
||||
|
#include <liblll/Compiler.h> |
||||
|
#include "GenesisInfo.h" |
||||
|
#include "State.h" |
||||
|
#include "Defaults.h" |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
namespace js = json_spirit; |
||||
|
|
||||
|
#define ETH_CATCH 1 |
||||
|
|
||||
|
std::map<Address, Account> const& dev::eth::genesisState() |
||||
|
{ |
||||
|
static std::map<Address, Account> s_ret; |
||||
|
if (s_ret.empty()) |
||||
|
{ |
||||
|
js::mValue val; |
||||
|
json_spirit::read_string(c_genesisInfo, val); |
||||
|
for (auto account: val.get_obj()) |
||||
|
{ |
||||
|
u256 balance; |
||||
|
if (account.second.get_obj().count("wei")) |
||||
|
balance = u256(account.second.get_obj()["wei"].get_str()); |
||||
|
else |
||||
|
balance = u256(account.second.get_obj()["finney"].get_str()) * finney; |
||||
|
if (account.second.get_obj().count("code")) |
||||
|
{ |
||||
|
s_ret[Address(fromHex(account.first))] = Account(balance, Account::ContractConception); |
||||
|
s_ret[Address(fromHex(account.first))].setCode(fromHex(account.second.get_obj()["code"].get_str())); |
||||
|
} |
||||
|
else |
||||
|
s_ret[Address(fromHex(account.first))] = Account(balance, Account::NormalCreation); |
||||
|
} |
||||
|
} |
||||
|
return s_ret; |
||||
|
} |
||||
|
|
||||
|
std::unique_ptr<BlockInfo> CanonBlockChain::s_genesis; |
||||
|
boost::shared_mutex CanonBlockChain::x_genesis; |
||||
|
|
||||
|
bytes CanonBlockChain::createGenesisBlock() |
||||
|
{ |
||||
|
RLPStream block(3); |
||||
|
|
||||
|
h256 stateRoot; |
||||
|
{ |
||||
|
MemoryDB db; |
||||
|
TrieDB<Address, MemoryDB> state(&db); |
||||
|
state.init(); |
||||
|
dev::eth::commit(genesisState(), db, state); |
||||
|
stateRoot = state.root(); |
||||
|
} |
||||
|
|
||||
|
block.appendList(14) |
||||
|
<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42)); |
||||
|
block.appendRaw(RLPEmptyList); |
||||
|
block.appendRaw(RLPEmptyList); |
||||
|
return block.out(); |
||||
|
} |
||||
|
|
||||
|
CanonBlockChain::CanonBlockChain(std::string _path, bool _killExisting): BlockChain(CanonBlockChain::createGenesisBlock(), _path, _killExisting) |
||||
|
{ |
||||
|
} |
@ -0,0 +1,76 @@ |
|||||
|
/*
|
||||
|
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 CanonBlockChain.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#pragma warning(push) |
||||
|
#pragma warning(disable: 4100 4267) |
||||
|
#include <leveldb/db.h> |
||||
|
#pragma warning(pop) |
||||
|
|
||||
|
#include <mutex> |
||||
|
#include <libdevcore/Log.h> |
||||
|
#include <libdevcore/Exceptions.h> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
#include <libethcore/BlockInfo.h> |
||||
|
#include <libdevcore/Guards.h> |
||||
|
#include "BlockDetails.h" |
||||
|
#include "Account.h" |
||||
|
#include "BlockQueue.h" |
||||
|
#include "BlockChain.h" |
||||
|
namespace ldb = leveldb; |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
|
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
// TODO: Move all this Genesis stuff into Genesis.h/.cpp
|
||||
|
std::map<Address, Account> const& genesisState(); |
||||
|
|
||||
|
/**
|
||||
|
* @brief Implements the blockchain database. All data this gives is disk-backed. |
||||
|
* @threadsafe |
||||
|
* @todo Make not memory hog (should actually act as a cache and deallocate old entries). |
||||
|
*/ |
||||
|
class CanonBlockChain: public BlockChain |
||||
|
{ |
||||
|
public: |
||||
|
CanonBlockChain(bool _killExisting = false): CanonBlockChain(std::string(), _killExisting) {} |
||||
|
CanonBlockChain(std::string _path, bool _killExisting = false); |
||||
|
~CanonBlockChain() {} |
||||
|
|
||||
|
/// @returns the genesis block header.
|
||||
|
static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); s_genesis.reset(new BlockInfo); s_genesis->populate(&gb); } return *s_genesis; } |
||||
|
|
||||
|
/// @returns the genesis block as its RLP-encoded byte array.
|
||||
|
/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
|
||||
|
static bytes createGenesisBlock(); |
||||
|
|
||||
|
private: |
||||
|
/// Static genesis info and its lock.
|
||||
|
static boost::shared_mutex x_genesis; |
||||
|
static std::unique_ptr<BlockInfo> s_genesis; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
/*
|
||||
|
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 GenesisInfo.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "GenesisInfo.h" |
||||
|
|
||||
|
std::string const dev::eth::c_genesisInfo = |
||||
|
R"ETHEREUM( |
||||
|
{ |
||||
|
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"e6716f9544a56c530d868e4bfbacb172315bdead": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"b9c015918bdaba24b4ff057a92a3873d6eb201be": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"2ef47100e0787b915105fd5e3f4ff6752079d5cb": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"6c386a4b26f73c802f34673f7248bb118f97424a": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"e4157b34ea9615cfbde6b4fda419828124b70c78": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }, |
||||
|
"b0afc46d9ce366d06ab4952ca27db1d9557ae9fd": { "finney": "154162184" }, |
||||
|
"f6b1e9dc460d4d62cc22ec5f987d726929c0f9f0": { "finney": "102774789" }, |
||||
|
"cc45122d8b7fa0b1eaa6b29e0fb561422a9239d0": { "finney": "51387394" }, |
||||
|
"b7576e9d314df41ec5506494293afb1bd5d3f65d": { "finney": "69423399" }, |
||||
|
} |
||||
|
)ETHEREUM"; |
@ -0,0 +1,32 @@ |
|||||
|
/*
|
||||
|
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 GenesisInfo.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <string> |
||||
|
|
||||
|
namespace dev { |
||||
|
namespace eth { |
||||
|
|
||||
|
extern std::string const c_genesisInfo; |
||||
|
|
||||
|
} |
||||
|
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue