Browse Source

Merge remote-tracking branch 'upstream/develop' into addTests

cl-refactor
CJentzsch 10 years ago
parent
commit
b9c38b42ab
  1. 9
      CMakeLists.txt
  2. 24
      alethzero/DappLoader.cpp
  3. 9
      alethzero/Main.ui
  4. 23
      alethzero/MainWin.cpp
  5. 4
      cmake/EthDependencies.cmake
  6. 2
      libdevcore/Common.cpp
  7. 3
      libethcore/Common.h
  8. 68
      libethereum/BlockChain.cpp
  9. 10
      libethereum/BlockChain.h
  10. 44
      libethereum/BlockQueue.cpp
  11. 14
      libethereum/BlockQueue.h
  12. 26
      libethereum/Client.cpp
  13. 2
      libethereum/Client.h
  14. 1
      libethereum/ClientBase.h
  15. 19
      libethereum/EthereumHost.cpp
  16. 13
      libethereum/EthereumPeer.cpp
  17. 5
      libethereum/EthereumPeer.h
  18. 2
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  19. 2
      mix/CMakeLists.txt
  20. 6
      mix/ClientModel.cpp
  21. 3
      mix/ClientModel.h
  22. 5
      mix/ContractCallDataEncoder.cpp
  23. 8
      mix/ContractCallDataEncoder.h
  24. 1
      mix/FileIo.cpp
  25. 5
      mix/MixApplication.cpp
  26. 84
      mix/Web3Server.cpp
  27. 2
      mix/Web3Server.h
  28. 23
      mix/qml/DeploymentDialog.qml
  29. 4
      mix/qml/LogsPane.qml
  30. 2
      mix/qml/ProjectModel.qml
  31. 6
      mix/qml/StatusPane.qml
  32. 1
      mix/qml/WebPreview.qml
  33. 42
      mix/qml/js/ProjectModel.js
  34. 16
      mix/qml/js/QEtherHelper.js

9
CMakeLists.txt

@ -190,12 +190,13 @@ else ()
set(SOLIDITY OFF) set(SOLIDITY OFF)
endif() endif()
if (SERPENT) if (SERPENT)
set(SERPENT ON) set(SERPENT ${DECENT_PLATFORM})
else () else ()
set(SERPENT OFF) set(SERPENT OFF)
endif() endif()
if (GUI) if (GUI)
set(GUI ON) set(GUI ON)
set(JSONRPC ON)
else () else ()
set(GUI OFF) set(GUI OFF)
endif () endif ()
@ -215,7 +216,7 @@ else ()
set(ETHASHCL OFF) set(ETHASHCL OFF)
endif() endif()
if (NCURSES) if (NCURSES)
set(NCURSES ON) set(NCURSES ${DECENT_PLATFORM})
else () else ()
set(NCURSES OFF) set(NCURSES OFF)
endif () endif ()
@ -229,7 +230,7 @@ if (BUNDLE STREQUAL "minimal")
set(TOOLS ON) set(TOOLS ON)
set(TESTS OFF) set(TESTS OFF)
elseif (BUNDLE STREQUAL "full") elseif (BUNDLE STREQUAL "full")
set(SERPENT ON) set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON) set(SOLIDITY ON)
set(USENPM ON) set(USENPM ON)
set(GUI ON) set(GUI ON)
@ -238,7 +239,7 @@ elseif (BUNDLE STREQUAL "full")
set(TESTS ON) set(TESTS ON)
set(FATDB ON) set(FATDB ON)
elseif (BUNDLE STREQUAL "tests") elseif (BUNDLE STREQUAL "tests")
set(SERPENT ON) set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON) set(SOLIDITY ON)
set(USENPM OFF) set(USENPM OFF)
set(GUI OFF) set(GUI OFF)

24
alethzero/DappLoader.cpp

@ -193,10 +193,26 @@ Manifest DappLoader::loadManifest(std::string const& _manifest)
void DappLoader::loadDapp(QString const& _uri) void DappLoader::loadDapp(QString const& _uri)
{ {
DappLocation location = resolveAppUri(_uri); QUrl uri(_uri);
QUrl uri(location.contentUri); QUrl contentUri;
QNetworkRequest request(uri); h256 hash;
m_uriHashes[uri] = location.contentHash; if (uri.path().endsWith(".dapp") && uri.query().startsWith("hash="))
{
contentUri = uri;
QString query = uri.query();
query.remove("hash=");
if (!query.startsWith("0x"))
query.insert(0, "0x");
hash = jsToFixed<32>(query.toStdString());
}
else
{
DappLocation location = resolveAppUri(_uri);
contentUri = location.contentUri;
hash = location.contentHash;
}
QNetworkRequest request(contentUri);
m_uriHashes[uri] = hash;
m_net.get(request); m_net.get(request);
} }

9
alethzero/Main.ui

@ -45,6 +45,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="chainStatus">
<property name="text">
<string>#0</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="balance"> <widget class="QLabel" name="balance">
<property name="text"> <property name="text">
@ -118,7 +125,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1617</width> <width>1617</width>
<height>22</height> <height>24</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menu_File"> <widget class="QMenu" name="menu_File">

23
alethzero/MainWin.cpp

@ -161,8 +161,11 @@ Main::Main(QWidget *parent) :
statusBar()->addPermanentWidget(ui->balance); statusBar()->addPermanentWidget(ui->balance);
statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->peerCount);
statusBar()->addPermanentWidget(ui->mineStatus); statusBar()->addPermanentWidget(ui->mineStatus);
statusBar()->addPermanentWidget(ui->chainStatus);
statusBar()->addPermanentWidget(ui->blockCount); statusBar()->addPermanentWidget(ui->blockCount);
ui->blockCount->setText(QString("PV%2 D%3 H%4 v%5").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(c_ethashVersion).arg(dev::Version));
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
QSettings s("ethereum", "alethzero"); QSettings s("ethereum", "alethzero");
@ -301,16 +304,25 @@ unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f)
void Main::uninstallWatch(unsigned _w) void Main::uninstallWatch(unsigned _w)
{ {
cdebug << "!!! Main: uninstalling watch" << _w;
ethereum()->uninstallWatch(_w); ethereum()->uninstallWatch(_w);
m_handlers.erase(_w); m_handlers.erase(_w);
} }
void Main::installWatches() void Main::installWatches()
{ {
auto newBlockId = installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){
onNewBlock();
});
auto newPendingId = installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){
onNewPending();
});
cdebug << "newBlock watch ID: " << newBlockId;
cdebug << "newPending watch ID: " << newPendingId;
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
} }
Address Main::getNameReg() const Address Main::getNameReg() const
@ -900,7 +912,7 @@ void Main::on_urlEdit_returnPressed()
{ {
QString s = ui->urlEdit->text(); QString s = ui->urlEdit->text();
QUrl url(s); QUrl url(s);
if (url.scheme().isEmpty() || url.scheme() == "eth") if (url.scheme().isEmpty() || url.scheme() == "eth" || url.path().endsWith(".dapp"))
{ {
try try
{ {
@ -1089,9 +1101,9 @@ void Main::refreshAccounts()
void Main::refreshBlockCount() void Main::refreshBlockCount()
{ {
cwatch << "refreshBlockCount()";
auto d = ethereum()->blockChain().details(); auto d = ethereum()->blockChain().details();
ui->blockCount->setText(QString("%4 #%1 PV%2 D%3 H%5").arg(d.number).arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(c_ethashVersion)); BlockQueueStatus b = ethereum()->blockQueueStatus();
ui->chainStatus->setText(QString("%3 ready %4 future %5 unknown %6 bad %1 #%2").arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.ready).arg(b.future).arg(b.unknown).arg(b.bad));
} }
void Main::on_turboMining_triggered() void Main::on_turboMining_triggered()
@ -1270,6 +1282,7 @@ void Main::timerEvent(QTimerEvent*)
refreshNetwork(); refreshNetwork();
refreshWhispers(); refreshWhispers();
refreshCache(); refreshCache();
refreshBlockCount();
poll(); poll();
} }
else else

4
cmake/EthDependencies.cmake

@ -101,7 +101,7 @@ find_program(ETH_JSON_RPC_STUB jsonrpcstub)
message(" - jsonrpcstub location : ${ETH_JSON_RPC_STUB}") message(" - jsonrpcstub location : ${ETH_JSON_RPC_STUB}")
# do not compile GUI # do not compile GUI
if (NOT HEADLESS) if (GUI)
# we need json rpc to build alethzero # we need json rpc to build alethzero
if (NOT JSON_RPC_CPP_FOUND) if (NOT JSON_RPC_CPP_FOUND)
@ -153,7 +153,7 @@ if (NOT HEADLESS)
endif() endif()
endif() endif()
endif() #HEADLESS endif() #GUI
# use multithreaded boost libraries, with -mt suffix # use multithreaded boost libraries, with -mt suffix
set(Boost_USE_MULTITHREADED ON) set(Boost_USE_MULTITHREADED ON)

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev namespace dev
{ {
char const* Version = "0.9.4"; char const* Version = "0.9.5";
} }

3
libethcore/Common.h

@ -92,7 +92,8 @@ enum class ImportResult
FutureTime, FutureTime,
AlreadyInChain, AlreadyInChain,
AlreadyKnown, AlreadyKnown,
Malformed Malformed,
BadChain
}; };
} }

68
libethereum/BlockChain.cpp

@ -306,39 +306,49 @@ LastHashes BlockChain::lastHashes(unsigned _n) const
return m_lastLastHashes; return m_lastLastHashes;
} }
pair<h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max) tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
{ {
_bq.tick(*this); _bq.tick(*this);
vector<bytes> blocks; vector<bytes> blocks;
_bq.drain(blocks, _max); _bq.drain(blocks, _max);
h256s ret; h256s fresh;
h256s dead;
h256s badBlocks;
for (auto const& block: blocks) for (auto const& block: blocks)
{ {
try try
{ {
for (auto h: import(block, _stateDB)) auto r = import(block, _stateDB);
ret.push_back(h); bool isOld = true;
for (auto const& h: r.first)
if (h == r.second)
isOld = false;
else if (isOld)
dead.push_back(h);
else
fresh.push_back(h);
} }
catch (UnknownParent) catch (UnknownParent)
{ {
cwarn << "Unknown parent of block!!!" << BlockInfo::headerHash(block).abridged() << boost::current_exception_diagnostic_information(); cwarn << "ODD: Import queue contains block with unknown parent." << boost::current_exception_diagnostic_information();
_bq.import(&block, *this); // NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(BlockInfo::headerHash(block));
} }
catch (Exception const& _e) catch (Exception const& _e)
{ {
cwarn << "Unexpected exception!" << diagnostic_information(_e); cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << diagnostic_information(_e);
_bq.import(&block, *this); // NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(BlockInfo::headerHash(block));
} }
catch (...)
{}
} }
bool yetMore = _bq.doneDrain(); return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
return make_pair(ret, yetMore);
} }
h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept
{ {
try try
{ {
@ -347,11 +357,11 @@ h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB,
catch (...) catch (...)
{ {
cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information(); cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information();
return h256s(); return make_pair(h256s(), h256());
} }
} }
h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force) pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
{ {
//@tidy This is a behemoth of a method - could do to be split into a few smaller ones. //@tidy This is a behemoth of a method - could do to be split into a few smaller ones.
@ -532,14 +542,14 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
); );
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; // cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
h256s ret; h256s route;
h256 common;
// This might be the new best block... // This might be the new best block...
h256 last = currentHash(); h256 last = currentHash();
if (td > details(last).totalDifficulty) if (td > details(last).totalDifficulty)
{ {
h256 common;
unsigned commonIndex; unsigned commonIndex;
tie(ret, common, commonIndex) = treeRoute(last, newHash); tie(route, common, commonIndex) = treeRoute(last, newHash);
{ {
WriteGuard l(x_lastBlockHash); WriteGuard l(x_lastBlockHash);
m_lastBlockHash = newHash; m_lastBlockHash = newHash;
@ -554,7 +564,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
clearBlockBlooms(number(common) + 1, number(last) + 1); clearBlockBlooms(number(common) + 1, number(last) + 1);
// Go through ret backwards until hash != last.parent and update m_transactionAddresses, m_blockHashes // Go through ret backwards until hash != last.parent and update m_transactionAddresses, m_blockHashes
for (auto i = ret.rbegin(); i != ret.rend() && *i != common; ++i) for (auto i = route.rbegin(); i != route.rend() && *i != common; ++i)
{ {
auto b = block(*i); auto b = block(*i);
BlockInfo bi(b); BlockInfo bi(b);
@ -606,7 +616,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
m_extrasDB->Put(m_writeOptions, toSlice(h, ExtraTransactionAddress), (ldb::Slice)dev::ref(m_transactionAddresses[h].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(h, ExtraTransactionAddress), (ldb::Slice)dev::ref(m_transactionAddresses[h].rlp()));
} }
clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(route);
noteCanonChanged(); noteCanonChanged();
StructuredLogger::chainNewHead( StructuredLogger::chainNewHead(
@ -631,7 +641,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
cnote << "checkBest:" << checkBest; cnote << "checkBest:" << checkBest;
#endif #endif
return ret; return make_pair(route, common);
} }
void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end) void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end)
@ -704,21 +714,21 @@ tuple<h256s, h256, unsigned> BlockChain::treeRoute(h256 const& _from, h256 const
tn--; tn--;
// cdebug << "to:" << tn << _to.abridged(); // cdebug << "to:" << tn << _to.abridged();
} }
while (from != to) for (;; from = details(from).parent, to = details(to).parent)
{ {
if (!from)
assert(from);
if (!to)
assert(to);
from = details(from).parent;
to = details(to).parent;
if (_pre && (from != to || _common)) if (_pre && (from != to || _common))
ret.push_back(from); ret.push_back(from);
if (_post && (from != to || (!_pre && _common))) if (_post && (from != to || (!_pre && _common)))
back.push_back(to); back.push_back(to);
fn--; fn--;
tn--; tn--;
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged(); // cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
if (from == to)
break;
if (!from)
assert(from);
if (!to)
assert(to);
} }
ret.reserve(ret.size() + back.size()); ret.reserve(ret.size() + back.size());
unsigned i = ret.size() - (int)(_common && !ret.empty() && !back.empty()); unsigned i = ret.size() - (int)(_common && !ret.empty() && !back.empty());

10
libethereum/BlockChain.h

@ -100,15 +100,15 @@ public:
void process(); void process();
/// Sync the chain with any incoming blocks. All blocks should, if processed in order /// Sync the chain with any incoming blocks. All blocks should, if processed in order
std::pair<h256s, bool> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max); std::tuple<h256s, h256s, bool> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max);
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept; std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept;
/// Import block into disk-backed DB /// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
h256s import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false); std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false);
/// Returns true if the given block is known (though not necessarily a part of the canon chain). /// Returns true if the given block is known (though not necessarily a part of the canon chain).
bool isKnown(h256 const& _hash) const; bool isKnown(h256 const& _hash) const;
@ -178,6 +178,10 @@ public:
bytes transaction(h256 const& _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); } bytes transaction(h256 const& _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); }
bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); } bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); }
/// Get all transactions from a block.
std::vector<bytes> transactions(h256 const& _blockHash) const { bytes b = block(_blockHash); std::vector<bytes> ret; for (auto const& i: RLP(b)[1]) ret.push_back(i.data().toBytes()); return ret; }
std::vector<bytes> transactions() const { return transactions(currentHash()); }
/// Get a number for the given hash (or the most recent mined if none given). Thread-safe. /// Get a number for the given hash (or the most recent mined if none given). Thread-safe.
unsigned number(h256 const& _hash) const { return details(_hash).number; } unsigned number(h256 const& _hash) const { return details(_hash).number; }
unsigned number() const { return number(currentHash()); } unsigned number() const { return number(currentHash()); }

44
libethereum/BlockQueue.cpp

@ -38,7 +38,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
UpgradableGuard l(m_lock); UpgradableGuard l(m_lock);
if (m_readySet.count(h) || m_drainingSet.count(h) || m_unknownSet.count(h)) if (m_readySet.count(h) || m_drainingSet.count(h) || m_unknownSet.count(h) || m_knownBad.count(h))
{ {
// Already know about this one. // Already know about this one.
cblockq << "Already known."; cblockq << "Already known.";
@ -48,20 +48,17 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
// VERIFY: populates from the block and checks the block is internally coherent. // VERIFY: populates from the block and checks the block is internally coherent.
BlockInfo bi; BlockInfo bi;
#if ETH_CATCH
try try
#endif
{ {
// TODO: quick verify
bi.populate(_block); bi.populate(_block);
bi.verifyInternals(_block); bi.verifyInternals(_block);
} }
#if ETH_CATCH
catch (Exception const& _e) catch (Exception const& _e)
{ {
cwarn << "Ignoring malformed block: " << diagnostic_information(_e); cwarn << "Ignoring malformed block: " << diagnostic_information(_e);
return ImportResult::Malformed; return ImportResult::Malformed;
} }
#endif
// Check block doesn't already exist first! // Check block doesn't already exist first!
if (_bc.details(h)) if (_bc.details(h))
@ -82,7 +79,13 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
else else
{ {
// We now know it. // We now know it.
if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash)) if (m_knownBad.count(bi.parentHash))
{
m_knownBad.insert(bi.hash());
// bad parent; this is bad too, note it as such
return ImportResult::BadChain;
}
else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash))
{ {
// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on. // We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
cblockq << "OK - queued as unknown parent:" << bi.parentHash.abridged(); cblockq << "OK - queued as unknown parent:" << bi.parentHash.abridged();
@ -104,6 +107,35 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
} }
} }
namespace dev {
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.insert(i);
return _a;
} }
bool BlockQueue::doneDrain(h256s const& _bad)
{
WriteGuard l(m_lock);
m_drainingSet.clear();
if (_bad.size())
{
vector<bytes> old;
swap(m_ready, old);
for (auto& b: old)
{
BlockInfo bi(b);
if (m_knownBad.count(bi.parentHash))
m_knownBad.insert(bi.hash());
else
m_ready.push_back(std::move(b));
}
}
m_knownBad += _bad;
return !m_readySet.empty();
}
void BlockQueue::tick(BlockChain const& _bc) void BlockQueue::tick(BlockChain const& _bc)
{ {
unsigned t = time(0); unsigned t = time(0);

14
libethereum/BlockQueue.h

@ -38,6 +38,14 @@ class BlockChain;
struct BlockQueueChannel: public LogChannel { static const char* name() { return "[]Q"; } static const int verbosity = 4; }; struct BlockQueueChannel: public LogChannel { static const char* name() { return "[]Q"; } static const int verbosity = 4; };
#define cblockq dev::LogOutputStream<dev::eth::BlockQueueChannel, true>() #define cblockq dev::LogOutputStream<dev::eth::BlockQueueChannel, true>()
struct BlockQueueStatus
{
size_t ready;
size_t future;
size_t unknown;
size_t bad;
};
/** /**
* @brief A queue of blocks. Sits between network or other I/O and the BlockChain. * @brief A queue of blocks. Sits between network or other I/O and the BlockChain.
* Sorts them ready for blockchain insertion (with the BlockChain::sync() method). * Sorts them ready for blockchain insertion (with the BlockChain::sync() method).
@ -58,7 +66,7 @@ public:
/// Must be called after a drain() call. Notes that the drained blocks have been imported into the blockchain, so we can forget about them. /// Must be called after a drain() call. Notes that the drained blocks have been imported into the blockchain, so we can forget about them.
/// @returns true iff there are additional blocks ready to be processed. /// @returns true iff there are additional blocks ready to be processed.
bool doneDrain() { WriteGuard l(m_lock); m_drainingSet.clear(); return !m_readySet.empty(); } bool doneDrain(h256s const& _knownBad = h256s());
/// Notify the queue that the chain has changed and a new block has attained 'ready' status (i.e. is in the chain). /// Notify the queue that the chain has changed and a new block has attained 'ready' status (i.e. is in the chain).
void noteReady(h256 _b) { WriteGuard l(m_lock); noteReadyWithoutWriteGuard(_b); } void noteReady(h256 _b) { WriteGuard l(m_lock); noteReadyWithoutWriteGuard(_b); }
@ -72,6 +80,9 @@ public:
/// Return first block with an unknown parent. /// Return first block with an unknown parent.
h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); } h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); }
/// Get some infomration on the current status.
BlockQueueStatus status() const { ReadGuard l(m_lock); return BlockQueueStatus{m_ready.size(), m_future.size(), m_unknown.size(), m_knownBad.size()}; }
private: private:
void noteReadyWithoutWriteGuard(h256 _b); void noteReadyWithoutWriteGuard(h256 _b);
void notePresentWithoutWriteGuard(bytesConstRef _block); void notePresentWithoutWriteGuard(bytesConstRef _block);
@ -83,6 +94,7 @@ private:
std::set<h256> m_unknownSet; ///< Set of all blocks whose parents are not ready/in-chain. std::set<h256> m_unknownSet; ///< Set of all blocks whose parents are not ready/in-chain.
std::multimap<h256, std::pair<h256, bytes>> m_unknown; ///< For transactions that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears. std::multimap<h256, std::pair<h256, bytes>> m_unknown; ///< For transactions that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears.
std::multimap<unsigned, bytes> m_future; ///< Set of blocks that are not yet valid. std::multimap<unsigned, bytes> m_future; ///< Set of blocks that are not yet valid.
std::set<h256> m_knownBad; ///< Set of blocks that we know will never be valid.
}; };
} }

26
libethereum/Client.cpp

@ -453,6 +453,7 @@ void Client::doWork()
// TODO: enable a short-circuit option since we mined it. will need to get the end state from the miner. // TODO: enable a short-circuit option since we mined it. will need to get the end state from the miner.
auto lm = dynamic_cast<LocalMiner*>(&m); auto lm = dynamic_cast<LocalMiner*>(&m);
h256s hs; h256s hs;
h256 c;
if (false && lm && !m_verifyOwnBlocks) if (false && lm && !m_verifyOwnBlocks)
{ {
// TODO: implement // TODO: implement
@ -463,12 +464,13 @@ void Client::doWork()
{ {
cwork << "CHAIN <== postSTATE"; cwork << "CHAIN <== postSTATE";
WriteGuard l(x_stateDB); WriteGuard l(x_stateDB);
hs = m_bc.attemptImport(m.blockData(), m_stateDB); tie(hs, c) = m_bc.attemptImport(m.blockData(), m_stateDB);
} }
if (hs.size()) if (hs.size())
{ {
for (auto const& h: hs) for (auto const& h: hs)
appendFromNewBlock(h, changeds); if (h != c)
appendFromNewBlock(h, changeds);
changeds.insert(ChainChangedFilter); changeds.insert(ChainChangedFilter);
} }
for (auto& m: m_localMiners) for (auto& m: m_localMiners)
@ -498,18 +500,28 @@ void Client::doWork()
cwork << "BQ ==> CHAIN ==> STATE"; cwork << "BQ ==> CHAIN ==> STATE";
OverlayDB db = m_stateDB; OverlayDB db = m_stateDB;
x_stateDB.unlock(); x_stateDB.unlock();
h256s newBlocks; h256s fresh;
h256s dead;
bool sgw; bool sgw;
tie(newBlocks, sgw) = m_bc.sync(m_bq, db, 100); // TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on. tie(fresh, dead, sgw) = m_bc.sync(m_bq, db, 100);
// TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on.
for (auto const& h: dead)
for (auto const& t: m_bc.transactions(h))
m_tq.import(t);
for (auto const& h: fresh)
for (auto const& th: m_bc.transactionHashes(h))
m_tq.drop(th);
stillGotWork = stillGotWork | sgw; stillGotWork = stillGotWork | sgw;
if (newBlocks.size()) if (!fresh.empty())
{ {
for (auto i: newBlocks) for (auto i: fresh)
appendFromNewBlock(i, changeds); appendFromNewBlock(i, changeds);
changeds.insert(ChainChangedFilter); changeds.insert(ChainChangedFilter);
} }
x_stateDB.lock(); x_stateDB.lock();
if (newBlocks.size()) if (fresh.size())
m_stateDB = db; m_stateDB = db;
cwork << "preSTATE <== CHAIN"; cwork << "preSTATE <== CHAIN";

2
libethereum/Client.h

@ -168,6 +168,8 @@ public:
dev::eth::State postState() const { ReadGuard l(x_stateDB); return m_postMine; } dev::eth::State postState() const { ReadGuard l(x_stateDB); return m_postMine; }
/// Get the object representing the current canonical blockchain. /// Get the object representing the current canonical blockchain.
CanonBlockChain const& blockChain() const { return m_bc; } CanonBlockChain const& blockChain() const { return m_bc; }
/// Get some information on the block queue.
BlockQueueStatus blockQueueStatus() const { return m_bq.status(); }
// Mining stuff: // Mining stuff:

1
libethereum/ClientBase.h

@ -108,6 +108,7 @@ public:
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override; virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override;
virtual LocalisedLogEntries checkWatch(unsigned _watchId) override; virtual LocalisedLogEntries checkWatch(unsigned _watchId) override;
// TODO: switch all the _blockHash arguments to also accept _blockNumber
virtual h256 hashFromNumber(unsigned _number) const override; virtual h256 hashFromNumber(unsigned _number) const override;
virtual eth::BlockInfo blockInfo(h256 _hash) const override; virtual eth::BlockInfo blockInfo(h256 _hash) const override;
virtual eth::BlockDetails blockDetails(h256 _hash) const override; virtual eth::BlockDetails blockDetails(h256 _hash) const override;

19
libethereum/EthereumHost.cpp

@ -162,6 +162,11 @@ void EthereumHost::doWork()
maintainTransactions(); maintainTransactions();
maintainBlocks(h); maintainBlocks(h);
} }
for (auto p: peerSessions())
if (shared_ptr<EthereumPeer> const& ep = p.first->cap<EthereumPeer>())
ep->tick();
// return netChange; // return netChange;
// TODO: Figure out what to do with netChange. // TODO: Figure out what to do with netChange.
(void)netChange; (void)netChange;
@ -201,16 +206,22 @@ void EthereumHost::maintainBlocks(h256 _currentHash)
{ {
clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")";
for (auto j: peerSessions()) std::vector<std::shared_ptr<EthereumPeer>> dispersal;
for (auto const& j: peerSessions())
if (!j.first->cap<EthereumPeer>()->m_knownBlocks.count(_currentHash))
dispersal.push_back(j.first->cap<EthereumPeer>());
for (unsigned i = (dispersal.size() + 3) / 4; i--;)
{ {
auto p = j.first->cap<EthereumPeer>().get(); unsigned n = rand() % dispersal.size();
auto p = std::move(dispersal[n]);
dispersal.erase(dispersal.begin() + n);
RLPStream ts; RLPStream ts;
p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(), 1).append(m_chain.details().totalDifficulty); p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(), 1).append(m_chain.details().totalDifficulty);
Guard l(p->x_knownBlocks); Guard l(p->x_knownBlocks);
if (!p->m_knownBlocks.count(_currentHash)) p->sealAndSend(ts);
p->sealAndSend(ts);
p->m_knownBlocks.clear(); p->m_knownBlocks.clear();
} }
m_latestBlockSent = _currentHash; m_latestBlockSent = _currentHash;

13
libethereum/EthereumPeer.cpp

@ -220,6 +220,8 @@ void EthereumPeer::setAsking(Asking _a, bool _isSyncing)
m_syncingNeededBlocks.clear(); m_syncingNeededBlocks.clear();
} }
m_lastAsk = chrono::system_clock::now();
session()->addNote("ask", _a == Asking::Nothing ? "nothing" : _a == Asking::State ? "state" : _a == Asking::Hashes ? "hashes" : _a == Asking::Blocks ? "blocks" : "?"); session()->addNote("ask", _a == Asking::Nothing ? "nothing" : _a == Asking::State ? "state" : _a == Asking::Hashes ? "hashes" : _a == Asking::Blocks ? "blocks" : "?");
session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : "")); session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : ""));
} }
@ -235,6 +237,13 @@ void EthereumPeer::setNeedsSyncing(h256 _latestHash, u256 _td)
session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : "")); session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : ""));
} }
void EthereumPeer::tick()
{
if (chrono::system_clock::now() - m_lastAsk > chrono::seconds(10) && m_asking != Asking::Nothing)
// timeout
session()->disconnect(PingTimeout);
}
bool EthereumPeer::isSyncing() const bool EthereumPeer::isSyncing() const
{ {
return host()->m_syncer == this; return host()->m_syncer == this;
@ -451,6 +460,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
break; break;
case ImportResult::Malformed: case ImportResult::Malformed:
case ImportResult::BadChain:
disable("Malformed block received."); disable("Malformed block received.");
return true; return true;
@ -505,8 +515,9 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
break; break;
case ImportResult::Malformed: case ImportResult::Malformed:
case ImportResult::BadChain:
disable("Malformed block received."); disable("Malformed block received.");
break; return true;
case ImportResult::AlreadyInChain: case ImportResult::AlreadyInChain:
case ImportResult::AlreadyKnown: case ImportResult::AlreadyKnown:

5
libethereum/EthereumPeer.h

@ -105,6 +105,9 @@ private:
/// Check whether the session should bother grabbing the peer's blocks. /// Check whether the session should bother grabbing the peer's blocks.
bool shouldGrabBlocks() const; bool shouldGrabBlocks() const;
/// Runs period checks to check up on the peer.
void tick();
/// Peer's protocol version. /// Peer's protocol version.
unsigned m_protocolVersion; unsigned m_protocolVersion;
/// Peer's network id. /// Peer's network id.
@ -112,6 +115,8 @@ private:
/// What, if anything, we last asked the other peer for. /// What, if anything, we last asked the other peer for.
Asking m_asking = Asking::Nothing; Asking m_asking = Asking::Nothing;
/// When we asked for it. Allows a time out.
std::chrono::system_clock::time_point m_lastAsk;
/// Whether this peer is in the process of syncing or not. Only one peer can be syncing at once. /// Whether this peer is in the process of syncing or not. Only one peer can be syncing at once.
bool m_isSyncing = false; bool m_isSyncing = false;

2
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -385,7 +385,7 @@ string WebThreeStubServerBase::eth_getBlockTransactionCountByNumber(string const
{ {
try try
{ {
return toJS(client()->transactionCount(client()->hashFromNumber(toBlockNumber(_blockNumber)))); return toJS(_blockNumber == "pending" ? client()->pending().size() : client()->transactionCount(client()->hashFromNumber(toBlockNumber(_blockNumber))));
} }
catch (...) catch (...)
{ {

2
mix/CMakeLists.txt

@ -29,7 +29,7 @@ else()
qt5_add_resources(UI_RESOURCES noweb.qrc) qt5_add_resources(UI_RESOURCES noweb.qrc)
endif() endif()
if (CMAKE_BUILD_TYPE EQUAL "DEBUG") if (CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DQT_QML_DEBUG) add_definitions(-DQT_QML_DEBUG)
endif() endif()

6
mix/ClientModel.cpp

@ -139,6 +139,12 @@ QString ClientModel::newAddress()
return QString::fromStdString(toHex(a.secret().ref())); return QString::fromStdString(toHex(a.secret().ref()));
} }
QString ClientModel::encodeAbiString(QString _string)
{
ContractCallDataEncoder encoder;
return QString::fromStdString(toHex(encoder.encodeBytes(_string)));
}
QVariantMap ClientModel::contractAddresses() const QVariantMap ClientModel::contractAddresses() const
{ {
QVariantMap res; QVariantMap res;

3
mix/ClientModel.h

@ -155,7 +155,10 @@ public slots:
Q_INVOKABLE void debugRecord(unsigned _index); Q_INVOKABLE void debugRecord(unsigned _index);
/// Show the debugger for an empty record /// Show the debugger for an empty record
Q_INVOKABLE void emptyRecord(); Q_INVOKABLE void emptyRecord();
/// Generate new adress
Q_INVOKABLE QString newAddress(); Q_INVOKABLE QString newAddress();
/// Encode a string to ABI parameter. Returns a hex string
Q_INVOKABLE QString encodeAbiString(QString _string);
private slots: private slots:
/// Update UI with machine states result. Display a modal dialog. /// Update UI with machine states result. Display a modal dialog.

5
mix/ContractCallDataEncoder.cpp

@ -110,11 +110,6 @@ unsigned ContractCallDataEncoder::encodeSingleItem(QVariant const& _data, Solidi
return dataSize; return dataSize;
} }
void ContractCallDataEncoder::push(bytes const& _b)
{
m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end());
}
bigint ContractCallDataEncoder::decodeInt(dev::bytes const& _rawValue) bigint ContractCallDataEncoder::decodeInt(dev::bytes const& _rawValue)
{ {
dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue); dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue);

8
mix/ContractCallDataEncoder.h

@ -52,8 +52,10 @@ public:
QVariant decode(SolidityType const& _type, bytes const& _value); QVariant decode(SolidityType const& _type, bytes const& _value);
/// Get all encoded data encoded by encode function. /// Get all encoded data encoded by encode function.
bytes encodedData(); bytes encodedData();
/// Push the given @a _b to the current param context. /// Encode a string to ABI bytes
void push(bytes const& _b); dev::bytes encodeBytes(QString const& _str);
/// Decode bytes from ABI
dev::bytes decodeBytes(dev::bytes const& _rawValue);
private: private:
unsigned encodeSingleItem(QVariant const& _data, SolidityType const& _type, bytes& _dest); unsigned encodeSingleItem(QVariant const& _data, SolidityType const& _type, bytes& _dest);
@ -63,8 +65,6 @@ private:
dev::bytes encodeBool(QString const& _str); dev::bytes encodeBool(QString const& _str);
bool decodeBool(dev::bytes const& _rawValue); bool decodeBool(dev::bytes const& _rawValue);
QString toString(bool _b); QString toString(bool _b);
dev::bytes encodeBytes(QString const& _str);
dev::bytes decodeBytes(dev::bytes const& _rawValue);
QString toString(dev::bytes const& _b); QString toString(dev::bytes const& _b);
bool asString(dev::bytes const& _b, QString& _str); bool asString(dev::bytes const& _b, QString& _str);

1
mix/FileIo.cpp

@ -196,6 +196,7 @@ QStringList FileIo::makePackage(QString const& _deploymentFolder)
QStringList ret; QStringList ret;
ret.append(QString::fromStdString(toHex(dappHash.ref()))); ret.append(QString::fromStdString(toHex(dappHash.ref())));
ret.append(qFileBytes.toBase64()); ret.append(qFileBytes.toBase64());
ret.append(url.toString());
return ret; return ret;
} }

5
mix/MixApplication.cpp

@ -36,6 +36,7 @@
#include "Clipboard.h" #include "Clipboard.h"
#include "HttpServer.h" #include "HttpServer.h"
extern int qInitResources_js();
using namespace dev::mix; using namespace dev::mix;
ApplicationService::ApplicationService() ApplicationService::ApplicationService()
@ -59,7 +60,6 @@ MixApplication::MixApplication(int& _argc, char* _argv[]):
} }
} }
void MixApplication::initialize() void MixApplication::initialize()
{ {
#if __linux #if __linux
@ -72,6 +72,9 @@ void MixApplication::initialize()
if (!getenv("OPENSSL_CONF")) if (!getenv("OPENSSL_CONF"))
putenv((char*)"OPENSSL_CONF=c:\\"); putenv((char*)"OPENSSL_CONF=c:\\");
#endif #endif
#ifdef ETH_HAVE_WEBENGINE
qInitResources_js();
#endif
setOrganizationName(tr("Ethereum")); setOrganizationName(tr("Ethereum"));
setOrganizationDomain(tr("ethereum.org")); setOrganizationDomain(tr("ethereum.org"));

84
mix/Web3Server.cpp

@ -23,13 +23,93 @@
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libethereum/Interface.h> #include <libethereum/Interface.h>
#include <libwebthree/WebThree.h>
#include "Web3Server.h" #include "Web3Server.h"
using namespace dev::mix; using namespace dev::mix;
using namespace dev;
namespace
{
class EmptyNetwork : public dev::WebThreeNetworkFace
{
std::vector<p2p::PeerSessionInfo> peers() override
{
return std::vector<p2p::PeerSessionInfo>();
}
size_t peerCount() const override
{
return 0;
}
void addNode(p2p::NodeId const& _node, bi::tcp::endpoint const& _hostEndpoint) override
{
(void)_node;
(void)_hostEndpoint;
}
void requirePeer(p2p::NodeId const& _node, bi::tcp::endpoint const& _endpoint) override
{
(void)_node;
(void)_endpoint;
}
dev::bytes saveNetwork() override
{
return dev::bytes();
}
void setIdealPeerCount(size_t _n) override
{
(void)_n;
}
bool haveNetwork() const override
{
return false;
}
void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) override
{
(void)_n;
(void)_dropPeers;
}
p2p::NodeId id() const override
{
return p2p::NodeId();
}
p2p::Peers nodes() const override
{
return p2p::Peers();
}
void startNetwork() override
{
}
void stopNetwork() override
{
}
bool isNetworkStarted() const override
{
return false;
}
};
}
Web3Server::Web3Server(jsonrpc::AbstractServerConnector& _conn, std::vector<dev::KeyPair> const& _accounts, dev::eth::Interface* _client): Web3Server::Web3Server(jsonrpc::AbstractServerConnector& _conn, std::vector<dev::KeyPair> const& _accounts, dev::eth::Interface* _client):
WebThreeStubServerBase(_conn, _accounts), WebThreeStubServerBase(_conn, _accounts),
m_client(_client) m_client(_client),
m_network(new EmptyNetwork())
{
}
Web3Server::~Web3Server()
{ {
} }
@ -40,7 +120,7 @@ std::shared_ptr<dev::shh::Interface> Web3Server::face()
dev::WebThreeNetworkFace* Web3Server::network() dev::WebThreeNetworkFace* Web3Server::network()
{ {
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::WebThreeNetworkFace")); return m_network.get();
} }
std::string Web3Server::get(std::string const& _name, std::string const& _key) std::string Web3Server::get(std::string const& _name, std::string const& _key)

2
mix/Web3Server.h

@ -39,6 +39,7 @@ class Web3Server: public QObject, public dev::WebThreeStubServerBase, public dev
public: public:
Web3Server(jsonrpc::AbstractServerConnector& _conn, std::vector<dev::KeyPair> const& _accounts, dev::eth::Interface* _client); Web3Server(jsonrpc::AbstractServerConnector& _conn, std::vector<dev::KeyPair> const& _accounts, dev::eth::Interface* _client);
virtual ~Web3Server();
signals: signals:
void newTransaction(); void newTransaction();
@ -60,6 +61,7 @@ private:
private: private:
dev::eth::Interface* m_client; dev::eth::Interface* m_client;
std::map<std::string, std::string> m_db; std::map<std::string, std::string> m_db;
std::unique_ptr<dev::WebThreeNetworkFace> m_network;
}; };
} }

23
mix/qml/DeploymentDialog.qml

@ -24,7 +24,8 @@ Window {
visible: false visible: false
property alias applicationUrlEth: applicationUrlEth.text property alias applicationUrlEth: applicationUrlEth.text
property alias applicationUrlHttp: applicationUrlHttp.text property alias applicationUrlHttp: applicationUrlHttp.text
property string urlHintContract: urlHintAddr.text property alias urlHintContract: urlHintAddr.text
property alias localPackageUrl: localPackageUrl.text
property string packageHash property string packageHash
property string packageBase64 property string packageBase64
property string eth: registrarAddr.text property string eth: registrarAddr.text
@ -131,8 +132,8 @@ Window {
var jsonRpcRequestId = 0; var jsonRpcRequestId = 0;
requests.push({ requests.push({
jsonrpc: "2.0", jsonrpc: "2.0",
method: "eth_countAt", method: "eth_getTransactionCount",
params: [ currentAccount ], params: [ currentAccount, "pending" ],
id: jsonRpcRequestId++ id: jsonRpcRequestId++
}); });
TransactionHelper.rpcCall(requests, function (httpRequest, response){ TransactionHelper.rpcCall(requests, function (httpRequest, response){
@ -299,7 +300,7 @@ Window {
DefaultTextField DefaultTextField
{ {
text: "20000" text: "1000000"
Layout.preferredWidth: 350 Layout.preferredWidth: 350
id: gasToUseInput id: gasToUseInput
} }
@ -416,6 +417,20 @@ Window {
columns: 2 columns: 2
Layout.fillWidth: true Layout.fillWidth: true
DefaultLabel
{
Layout.preferredWidth: 355
text: qsTr("Local package URL")
}
DefaultTextField
{
Layout.preferredWidth: 350
id: localPackageUrl
readOnly: true
enabled: rowRegister.isOkToRegister()
}
DefaultLabel DefaultLabel
{ {
Layout.preferredWidth: 355 Layout.preferredWidth: 355

4
mix/qml/LogsPane.qml

@ -27,10 +27,6 @@ Rectangle
} }
} }
LogsPaneStyle {
id: logStyle
}
anchors.fill: parent anchors.fill: parent
radius: 10 radius: 10
color: "transparent" color: "transparent"

2
mix/qml/ProjectModel.qml

@ -160,7 +160,7 @@ Item {
} }
MessageDialog { MessageDialog {
id: deployRessourcesDialog id: deployResourcesDialog
title: qsTr("Project") title: qsTr("Project")
standardButtons: StandardButton.Ok standardButtons: StandardButton.Ok
} }

6
mix/qml/StatusPane.qml

@ -231,7 +231,11 @@ Rectangle {
top = top.parent top = top.parent
var coordinates = logsContainer.mapToItem(top, 0, 0); var coordinates = logsContainer.mapToItem(top, 0, 0);
logsContainer.parent = top; logsContainer.parent = top;
logsContainer.x = status.x + statusContainer.x - LogsPaneStyle.generic.layout.dateWidth - LogsPaneStyle.generic.layout.typeWidth + 70 logsContainer.x = status.x + statusContainer.x - logStyle.generic.layout.dateWidth - logStyle.generic.layout.typeWidth + 70
}
LogsPaneStyle {
id: logStyle
} }
LogsPane LogsPane

1
mix/qml/WebPreview.qml

@ -304,6 +304,7 @@ Item {
id: webView id: webView
experimental.settings.localContentCanAccessRemoteUrls: true experimental.settings.localContentCanAccessRemoteUrls: true
onJavaScriptConsoleMessage: { onJavaScriptConsoleMessage: {
console.log(sourceID + ":" + lineNumber + ": " + message);
webPreview.javaScriptMessage(level, sourceID, lineNumber, message); webPreview.javaScriptMessage(level, sourceID, lineNumber, message);
} }
onLoadingChanged: { onLoadingChanged: {

42
mix/qml/js/ProjectModel.js

@ -367,23 +367,8 @@ function startDeployProject(erasePrevious)
var ctrNames = Object.keys(codeModel.contracts); var ctrNames = Object.keys(codeModel.contracts);
var ctrAddresses = {}; var ctrAddresses = {};
setDefaultBlock(0, function() { deployContracts(0, ctrAddresses, ctrNames, function (){
deployContracts(0, ctrAddresses, ctrNames, function (){ finalizeDeployment(deploymentId, ctrAddresses);
finalizeDeployment(deploymentId, ctrAddresses);
});
});
}
function setDefaultBlock(val, callBack)
{
var requests = [{
jsonrpc: "2.0",
method: "eth_setDefaultBlock",
params: [val],
id: 0
}];
rpcCall(requests, function (httpCall, response){
callBack();
}); });
} }
@ -392,7 +377,7 @@ function deployContracts(ctrIndex, ctrAddresses, ctrNames, callBack)
var code = codeModel.contracts[ctrNames[ctrIndex]].codeHex; var code = codeModel.contracts[ctrNames[ctrIndex]].codeHex;
var requests = [{ var requests = [{
jsonrpc: "2.0", jsonrpc: "2.0",
method: "eth_transact", method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.currentAccount, "gas": deploymentDialog.gasToUse, "code": code } ], params: [ { "from": deploymentDialog.currentAccount, "gas": deploymentDialog.gasToUse, "code": code } ],
id: 0 id: 0
}]; }];
@ -452,7 +437,8 @@ function finalizeDeployment(deploymentId, addresses) {
"\tinterface: " + codeModel.contracts[c].contractInterface + ",\n" + "\tinterface: " + codeModel.contracts[c].contractInterface + ",\n" +
"\taddress: \"" + addresses[c] + "\"\n" + "\taddress: \"" + addresses[c] + "\"\n" +
"};\n" + "};\n" +
contractAccessor + ".contract = web3.eth.contract(" + contractAccessor + ".address, " + contractAccessor + ".interface);\n"; contractAccessor + ".contractClass = web3.eth.contract(" + contractAccessor + ".interface);\n" +
contractAccessor + ".contract = new " + contractAccessor + ".contractClass(" + contractAccessor + ".address);\n";
} }
fileIo.writeFile(deploymentDir + "deployment.js", deploymentJs); fileIo.writeFile(deploymentDir + "deployment.js", deploymentJs);
deploymentAddresses = addresses; deploymentAddresses = addresses;
@ -461,6 +447,7 @@ function finalizeDeployment(deploymentId, addresses) {
var packageRet = fileIo.makePackage(deploymentDir); var packageRet = fileIo.makePackage(deploymentDir);
deploymentDialog.packageHash = packageRet[0]; deploymentDialog.packageHash = packageRet[0];
deploymentDialog.packageBase64 = packageRet[1]; deploymentDialog.packageBase64 = packageRet[1];
deploymentDialog.localPackageUrl = packageRet[2] + "?hash=" + packageRet[0];
var applicationUrlEth = deploymentDialog.applicationUrlEth; var applicationUrlEth = deploymentDialog.applicationUrlEth;
@ -468,9 +455,8 @@ function finalizeDeployment(deploymentId, addresses) {
deploymentStepChanged(qsTr("Registering application on the Ethereum network ...")); deploymentStepChanged(qsTr("Registering application on the Ethereum network ..."));
checkEthPath(applicationUrlEth, function () { checkEthPath(applicationUrlEth, function () {
deploymentComplete(); deploymentComplete();
deployRessourcesDialog.text = qsTr("Register Web Application to finalize deployment."); deployResourcesDialog.text = qsTr("Register Web Application to finalize deployment.");
deployRessourcesDialog.open(); deployResourcesDialog.open();
setDefaultBlock(-1, function() {});
}); });
} }
@ -567,7 +553,7 @@ function checkRegistration(dappUrl, addr, callBack)
requests.push({ requests.push({
jsonrpc: "2.0", jsonrpc: "2.0",
method: "eth_transact", method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.currentAccount, "gas": 20000, "code": "0x60056013565b61059e8061001d6000396000f35b33600081905550560060003560e060020a90048063019848921461009a578063449c2090146100af5780635d574e32146100cd5780635fd4b08a146100e1578063618242da146100f65780636be16bed1461010b5780636c4489b414610129578063893d20e8146101585780639607730714610173578063c284bc2a14610187578063e50f599a14610198578063e5811b35146101af578063ec7b9200146101cd57005b6100a560043561031b565b8060005260206000f35b6100ba6004356103a0565b80600160a060020a031660005260206000f35b6100db600435602435610537565b60006000f35b6100ec600435610529565b8060005260206000f35b6101016004356103dd565b8060005260206000f35b6101166004356103bd565b80600160a060020a031660005260206000f35b61013460043561034b565b82600160a060020a031660005281600160a060020a03166020528060405260606000f35b610160610341565b80600160a060020a031660005260206000f35b6101816004356024356102b4565b60006000f35b6101926004356103fd565b60006000f35b6101a96004356024356044356101f2565b60006000f35b6101ba6004356101eb565b80600160a060020a031660005260206000f35b6101d8600435610530565b80600160a060020a031660005260206000f35b6000919050565b600054600160a060020a031633600160a060020a031614610212576102af565b8160026000858152602001908152602001600020819055508061023457610287565b81600160a060020a0316837f680ad70765443c2967675ab0fb91a46350c01c6df59bf9a41ff8a8dd097464ec60006000a3826001600084600160a060020a03168152602001908152602001600020819055505b827f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b505050565b600054600160a060020a031633600160a060020a0316146102d457610317565b806002600084815260200190815260200160002060010181905550817f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b5050565b60006001600083600160a060020a03168152602001908152602001600020549050919050565b6000600054905090565b6000600060006002600085815260200190815260200160002054925060026000858152602001908152602001600020600101549150600260008581526020019081526020016000206002015490509193909250565b600060026000838152602001908152602001600020549050919050565b600060026000838152602001908152602001600020600101549050919050565b600060026000838152602001908152602001600020600201549050919050565b600054600160a060020a031633600160a060020a03161461041d57610526565b80600160006002600085815260200190815260200160002054600160a060020a031681526020019081526020016000205414610458576104d2565b6002600082815260200190815260200160002054600160a060020a0316817f680ad70765443c2967675ab0fb91a46350c01c6df59bf9a41ff8a8dd097464ec60006000a36000600160006002600085815260200190815260200160002054600160a060020a03168152602001908152602001600020819055505b6002600082815260200190815260200160002060008101600090556001810160009055600281016000905550807f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b50565b6000919050565b6000919050565b600054600160a060020a031633600160a060020a0316146105575761059a565b806002600084815260200190815260200160002060020181905550817f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b505056" } ], params: [ { "from": deploymentDialog.currentAccount, "gas": 20000, "code": "0x60056013565b61059e8061001d6000396000f35b33600081905550560060003560e060020a90048063019848921461009a578063449c2090146100af5780635d574e32146100cd5780635fd4b08a146100e1578063618242da146100f65780636be16bed1461010b5780636c4489b414610129578063893d20e8146101585780639607730714610173578063c284bc2a14610187578063e50f599a14610198578063e5811b35146101af578063ec7b9200146101cd57005b6100a560043561031b565b8060005260206000f35b6100ba6004356103a0565b80600160a060020a031660005260206000f35b6100db600435602435610537565b60006000f35b6100ec600435610529565b8060005260206000f35b6101016004356103dd565b8060005260206000f35b6101166004356103bd565b80600160a060020a031660005260206000f35b61013460043561034b565b82600160a060020a031660005281600160a060020a03166020528060405260606000f35b610160610341565b80600160a060020a031660005260206000f35b6101816004356024356102b4565b60006000f35b6101926004356103fd565b60006000f35b6101a96004356024356044356101f2565b60006000f35b6101ba6004356101eb565b80600160a060020a031660005260206000f35b6101d8600435610530565b80600160a060020a031660005260206000f35b6000919050565b600054600160a060020a031633600160a060020a031614610212576102af565b8160026000858152602001908152602001600020819055508061023457610287565b81600160a060020a0316837f680ad70765443c2967675ab0fb91a46350c01c6df59bf9a41ff8a8dd097464ec60006000a3826001600084600160a060020a03168152602001908152602001600020819055505b827f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b505050565b600054600160a060020a031633600160a060020a0316146102d457610317565b806002600084815260200190815260200160002060010181905550817f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b5050565b60006001600083600160a060020a03168152602001908152602001600020549050919050565b6000600054905090565b6000600060006002600085815260200190815260200160002054925060026000858152602001908152602001600020600101549150600260008581526020019081526020016000206002015490509193909250565b600060026000838152602001908152602001600020549050919050565b600060026000838152602001908152602001600020600101549050919050565b600060026000838152602001908152602001600020600201549050919050565b600054600160a060020a031633600160a060020a03161461041d57610526565b80600160006002600085815260200190815260200160002054600160a060020a031681526020019081526020016000205414610458576104d2565b6002600082815260200190815260200160002054600160a060020a0316817f680ad70765443c2967675ab0fb91a46350c01c6df59bf9a41ff8a8dd097464ec60006000a36000600160006002600085815260200190815260200160002054600160a060020a03168152602001908152602001600020819055505b6002600082815260200190815260200160002060008101600090556001810160009055600281016000905550807f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b50565b6000919050565b6000919050565b600054600160a060020a031633600160a060020a0316146105575761059a565b806002600084815260200190815260200160002060020181905550817f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b505056" } ],
id: jsonRpcRequestId++ id: jsonRpcRequestId++
}); });
@ -588,7 +574,7 @@ function checkRegistration(dappUrl, addr, callBack)
requests.push({ requests.push({
//setRegister() //setRegister()
jsonrpc: "2.0", jsonrpc: "2.0",
method: "eth_transact", method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.currentAccount, "gas": 30000, "to": '0x' + addr, "data": "0x96077307" + crLevel + deploymentDialog.pad(newCtrAddress) } ], params: [ { "from": deploymentDialog.currentAccount, "gas": 30000, "to": '0x' + addr, "data": "0x96077307" + crLevel + deploymentDialog.pad(newCtrAddress) } ],
id: jsonRpcRequestId++ id: jsonRpcRequestId++
}); });
@ -617,12 +603,12 @@ function registerContentHash(registrar, callBack)
deploymentStepChanged(txt); deploymentStepChanged(txt);
console.log(txt); console.log(txt);
var requests = []; var requests = [];
var paramTitle = createString(projectModel.projectTitle); var paramTitle = clientModel.encodeAbiString(projectModel.projectTitle);
requests.push({ requests.push({
//setContent() //setContent()
jsonrpc: "2.0", jsonrpc: "2.0",
method: "eth_transact", method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.currentAccount, "gas": 30000, "gasPrice": "10", "to": '0x' + registrar, "data": "0x5d574e32" + paramTitle.encodeValueAsString() + deploymentDialog.packageHash } ], params: [ { "from": deploymentDialog.currentAccount, "gas": 30000, "gasPrice": "10", "to": '0x' + registrar, "data": "0x5d574e32" + paramTitle + deploymentDialog.packageHash } ],
id: jsonRpcRequestId++ id: jsonRpcRequestId++
}); });
rpcCall(requests, function (httpRequest, response) { rpcCall(requests, function (httpRequest, response) {
@ -638,7 +624,7 @@ function registerToUrlHint()
requests.push({ requests.push({
//urlHint => suggestUrl //urlHint => suggestUrl
jsonrpc: "2.0", jsonrpc: "2.0",
method: "eth_transact", method: "eth_sendTransaction",
params: [ { "to": '0x' + deploymentDialog.urlHintContract, "gas": 30000, "data": "0x4983e19c" + deploymentDialog.packageHash + paramUrlHttp.encodeValueAsString() } ], params: [ { "to": '0x' + deploymentDialog.urlHintContract, "gas": 30000, "data": "0x4983e19c" + deploymentDialog.packageHash + paramUrlHttp.encodeValueAsString() } ],
id: jsonRpcRequestId++ id: jsonRpcRequestId++
}); });

16
mix/qml/js/QEtherHelper.js

@ -15,19 +15,3 @@ function createBigInt(_value)
return bigint; return bigint;
} }
function createString(_value)
{
var stringComponent = Qt.createComponent("qrc:/qml/QStringType.qml");
var stringC = stringComponent.createObject();
stringC.setValue(_value);
return stringC;
}
function createHash(_value)
{
var hComponent = Qt.createComponent("qrc:/qml/QHashType.qml");
var hC = hComponent.createObject();
hC.setValue(_value);
return hC;
}

Loading…
Cancel
Save